#include "Utilities.hpp" double CutOffFncn(const Vector &x, const Vector & pmin, const Vector & pmax, const Array2D & h_) { int dim = pmin.Size(); Vector h0(dim); Vector h1(dim); for (int i=0; i= pmax(i) || x(i) <= pmin(i)) { val = 0.0; } else if (x(i) <= pmax(i) && x(i) >= x0(i)) { if(x0(i)-pmax(i) != 0.0) val = (x(i)-pmax(i))/(x0(i)-pmax(i)); } else if (x(i) >= pmin(i) && x(i) <= x1(i)) { if (x1(i)-pmin(i) != 0.0) val = (x(i)-pmin(i))/(x1(i)-pmin(i)); } else { val = 1.0; } if (h_[i][0] == 0 && x(i) < pmin(i)) { val = 1.0; } if (h_[i][1] == 0 && x(i) > pmax(i)) { val = 1.0; } f *= val; } return f; } double ChiFncn(const Vector &x, const Vector & pmin, const Vector & pmax, const Array2D & h_) { int dim = pmin.Size(); Vector h0(dim); Vector h1(dim); for (int i=0; i= pmax(i) || x(i) <= pmin(i)) { val = 0.0; } else if (x(i) <= pmax(i) && x(i) >= x0(i)) { if(x0(i)-pmax(i) != 0.0) val = 0.0; } else if (x(i) >= pmin(i) && x(i) <= x1(i)) { if (x1(i)-pmin(i) != 0.0) val = 0.0; } else { val = 1.0; } if (h_[i][0] == 0 && x(i) < pmin(i)) { val = 1.0; } if (h_[i][1] == 0 && x(i) > pmax(i)) { val = 1.0; } f *= val; } return f; } DofMap::DofMap(SesquilinearForm * bf_ , MeshPartition * partition_) : bf(bf_), partition(partition_) { int partition_kind = partition->partition_kind; // MFEM_VERIFY(partition_kind == 1, "Check Partition kind"); fespace = bf->FESpace(); Mesh * mesh = fespace->GetMesh(); const FiniteElementCollection * fec = fespace->FEColl(); nrpatch = partition->nrpatch; fespaces.SetSize(nrpatch); Dof2GlobalDof.resize(nrpatch); for (int ip=0; ippatch_mesh[ip],fec); // construct the patch tdof to global tdof map int nrdof = fespaces[ip]->GetTrueVSize(); Dof2GlobalDof[ip].SetSize(2*nrdof); // loop through the elements in the patch for (int iel = 0; ielelement_map[ip].Size(); ++iel) { // index in the global mesh int iel_idx = partition->element_map[ip][iel]; // get the dofs of this element Array ElemDofs; Array GlobalElemDofs; fespaces[ip]->GetElementDofs(iel,ElemDofs); fespace->GetElementDofs(iel_idx,GlobalElemDofs); // the sizes have to match MFEM_VERIFY(ElemDofs.Size() == GlobalElemDofs.Size(), "Size inconsistency"); // loop through the dofs and take into account the signs; int ndof = ElemDofs.Size(); for (int i = 0; i= 0) ? pdof_ : abs(pdof_) - 1; int gdof = (gdof_ >= 0) ? gdof_ : abs(gdof_) - 1; Dof2GlobalDof[ip][pdof] = gdof; Dof2GlobalDof[ip][pdof+nrdof] = gdof+fespace->GetTrueVSize(); } } } } DofMap::DofMap(SesquilinearForm * bf_ , MeshPartition * partition_, int nrlayers) : bf(bf_), partition(partition_) { nx = partition->nxyz[0]; ny = partition->nxyz[1]; nz = partition->nxyz[2]; // cout << "nx =" << nx << endl; // cout << "ny =" << ny << endl; // cout << "nz =" << nz << endl; int partition_kind = partition->partition_kind; fespace = bf->FESpace(); Mesh * mesh = fespace->GetMesh(); const FiniteElementCollection * fec = fespace->FEColl(); nrpatch = partition->nrpatch; fespaces.SetSize(nrpatch); PmlMeshes.SetSize(nrpatch); // Extend patch meshes to include pml for (int ip = 0; ip directions; if (i > 0) { for (int i=0; i 0) { for (int i=0; i 0) { for (int i=0; ipatch_mesh[ip],directions); } // Save PML_meshes string meshpath; string solpath; if (partition_kind == 3 || partition_kind == 2) { meshpath = "output/mesh_ovlp_pml."; solpath = "output/sol_ovlp_pml."; } else if (partition_kind == 4) { meshpath = "output/mesh_novlp_pml."; solpath = "output/sol_novlp_pml."; } else { MFEM_ABORT("This partition kind not supported yet"); } // SaveMeshPartition(PmlMeshes, meshpath, solpath); PmlFespaces.SetSize(nrpatch); Dof2GlobalDof.resize(nrpatch); Dof2PmlDof.resize(nrpatch); for (int ip=0; ippatch_mesh[ip],fec); PmlFespaces[ip] = new FiniteElementSpace(PmlMeshes[ip],fec); // construct the patch tdof to global tdof map int nrdof = fespaces[ip]->GetTrueVSize(); Dof2GlobalDof[ip].SetSize(2*nrdof); Dof2PmlDof[ip].SetSize(2*nrdof); // build dof maps between patch and extended patch // loop through the patch elements and constract the dof map // The same elements in the extended mesh have the same ordering (but not the dofs) // loop through the elements in the patch for (int iel = 0; ielelement_map[ip].Size(); ++iel) { // index in the global mesh int iel_idx = partition->element_map[ip][iel]; // get the dofs of this element Array ElemDofs; Array PmlElemDofs; Array GlobalElemDofs; fespaces[ip]->GetElementDofs(iel,ElemDofs); PmlFespaces[ip]->GetElementDofs(iel,PmlElemDofs); fespace->GetElementDofs(iel_idx,GlobalElemDofs); // the sizes have to match MFEM_VERIFY(ElemDofs.Size() == GlobalElemDofs.Size(), "Size inconsistency"); MFEM_VERIFY(ElemDofs.Size() == PmlElemDofs.Size(), "Size inconsistency"); // loop through the dofs and take into account the signs; int ndof = ElemDofs.Size(); for (int i = 0; i= 0) ? pdof_ : abs(pdof_) - 1; int gdof = (gdof_ >= 0) ? gdof_ : abs(gdof_) - 1; int pmldof = (pmldof_ >= 0) ? pmldof_ : abs(pmldof_) - 1; Dof2GlobalDof[ip][pdof] = gdof; Dof2GlobalDof[ip][pdof+nrdof] = gdof+fespace->GetTrueVSize(); Dof2PmlDof[ip][pdof] = pmldof; Dof2PmlDof[ip][pdof+nrdof] = pmldof+PmlFespaces[ip]->GetTrueVSize(); } } } } LocalDofMap::LocalDofMap(const FiniteElementCollection * fec_, MeshPartition * part1_, MeshPartition * part2_):fec(fec_), part1(part1_), part2(part2_) { // Each overlapping patch has 2 non-overlapping subdomains // Thre are n non-overlapping and and n-1 overlapping subdomains int nrpatch = part2->nrpatch; MFEM_VERIFY(part1->nrpatch-1 == part2->nrpatch, "Check number of subdomains"); cout << "Constructing local dof maps" << endl; map1.resize(nrpatch); map2.resize(nrpatch); for (int ip=0; ippatch_mesh[ip]; Mesh * mesh1 = part1->patch_mesh[ip]; Mesh * mesh2 = part1->patch_mesh[ip+1]; // Define the fespaces FiniteElementSpace fespace(mesh, fec); FiniteElementSpace fespace1(mesh1, fec); FiniteElementSpace fespace2(mesh2, fec); int ndof1 = fespace1.GetTrueVSize(); int ndof2 = fespace2.GetTrueVSize(); map1[ip].SetSize(2*ndof1); // times 2 because it's complex map2[ip].SetSize(2*ndof2); // times 2 because it's complex // loop through the elements in the patches // map 1 is constructed by the first half of elements // map 2 is constructed by the second half of elements for (int iel = 0; ielelement_map[ip].Size(); ++iel) { // index in the overlapping mesh int iel_idx = iel; Array ElemDofs; Array GlobalElemDofs; fespace1.GetElementDofs(iel,ElemDofs); fespace.GetElementDofs(iel_idx,GlobalElemDofs); // the sizes have to match MFEM_VERIFY(ElemDofs.Size() == GlobalElemDofs.Size(), "Size inconsistency"); // loop through the dofs and take into account the signs; int ndof = ElemDofs.Size(); for (int i = 0; i= 0) ? pdof_ : abs(pdof_) - 1; int gdof = (gdof_ >= 0) ? gdof_ : abs(gdof_) - 1; map1[ip][pdof] = gdof; map1[ip][pdof+ndof1] = gdof+fespace.GetTrueVSize(); } } for (int iel = 0; ielelement_map[ip+1].Size(); ++iel) { // index in the overlapping mesh int k = part1->element_map[ip].Size(); int iel_idx = iel+k; Array ElemDofs; Array GlobalElemDofs; fespace2.GetElementDofs(iel,ElemDofs); fespace.GetElementDofs(iel_idx,GlobalElemDofs); // the sizes have to match MFEM_VERIFY(ElemDofs.Size() == GlobalElemDofs.Size(), "Size inconsistency"); // loop through the dofs and take into account the signs; int ndof = ElemDofs.Size(); for (int i = 0; i= 0) ? pdof_ : abs(pdof_) - 1; int gdof = (gdof_ >= 0) ? gdof_ : abs(gdof_) - 1; map2[ip][pdof] = gdof; map2[ip][pdof+ndof2] = gdof+fespace.GetTrueVSize(); } } } }