25#include <unordered_map>
26#include <unordered_set>
35 ndofs(0), nvdofs(0), nedofs(0), nfdofs(0), nbdofs(0),
37 elem_dof(NULL), elem_fos(NULL), bdr_elem_dof(NULL), bdr_elem_fos(NULL),
39 NURBSext(NULL), own_ext(false),
42 sequence(0), mesh_sequence(0), orders_changed(false), relaxed_hp(false)
49 mesh_ = mesh_ ? mesh_ : orig.
mesh;
50 fec_ = fec_ ? fec_ : orig.
fec;
74 int vdim,
int ordering)
79 int vdim,
int ordering)
85 MFEM_VERIFY(
cP == NULL,
"");
86 MFEM_VERIFY(
cR == NULL,
"");
96 for (
int i=0; i<n; ++i)
100 perm_mat->
Set(i, j, s);
112 else if (perm != NULL)
123 else if (perm != NULL)
125 cR.reset(perm_mat_tr);
137 "Attempting to set serial prolongation operator for "
138 "parallel finite element space.");
156 "Attempting to set serial restriction operator for "
157 "parallel finite element space.");
173 "Space has not been Updated() after a Mesh change.");
174 MFEM_VERIFY(i >= 0 && i <
GetNE(),
"Invalid element index");
175 MFEM_VERIFY(
p >= 0 &&
p <=
MaxVarOrder,
"Order out of range");
198 "Space has not been Updated() after a Mesh change.");
199 MFEM_VERIFY(i >= 0 && i <
GetNE(),
"Invalid element index");
214 if (ndofs_ < 0) { ndofs_ = this->
ndofs; }
218 for (
int i = 0; i < dofs.
Size(); i++)
220 dofs[i] = Ordering::Map<Ordering::byNODES>(ndofs_,
vdim, i, vd);
225 for (
int i = 0; i < dofs.
Size(); i++)
227 dofs[i] = Ordering::Map<Ordering::byVDIM>(ndofs_,
vdim, i, vd);
234 if (
vdim == 1) {
return; }
235 if (ndofs_ < 0) { ndofs_ = this->
ndofs; }
239 Ordering::DofsToVDofs<Ordering::byNODES>(ndofs_,
vdim, dofs);
243 Ordering::DofsToVDofs<Ordering::byVDIM>(ndofs_,
vdim, dofs);
249 if (
vdim == 1) {
return; }
250 if (ndofs_ < 0) { ndofs_ = this->
ndofs; }
254 for (
int i = 0; i < dofs.
Size(); i++)
256 dofs[i] = Ordering::Map<Ordering::byNODES>(ndofs_,
vdim, dofs[i], vd);
261 for (
int i = 0; i < dofs.
Size(); i++)
263 dofs[i] = Ordering::Map<Ordering::byVDIM>(ndofs_,
vdim, dofs[i], vd);
270 if (
vdim == 1) {
return dof; }
271 if (ndofs_ < 0) { ndofs_ = this->
ndofs; }
275 return Ordering::Map<Ordering::byNODES>(ndofs_,
vdim, dof, vd);
279 return Ordering::Map<Ordering::byVDIM>(ndofs_,
vdim, dof, vd);
286 int n = vdofs.
Size(), *vdof = vdofs;
287 for (
int i = 0; i < n; i++) { vdof[i] =
UnsignIndex(vdof[i]); }
379 if (el_fos) { el_fos->
MakeJ(); }
418 if (bel_fos) { bel_fos->
MakeJ(); }
431 if (bel_fos) { bel_fos->
ShiftUpI(); }
447 for (
int i = 0; i < fc_dof->
Size(); i++)
453 for (
int i = 0; i < fc_dof->
Size(); i++)
478 for (
int k = 0, dof_counter = 0; k < nnz; k++)
480 const int sdof = J[k];
482 int new_dof = dof_marker[dof];
485 dof_marker[dof] = new_dof = dof_counter++;
501 for (
int i = 0; i <
mesh ->
GetNE(); i++)
503 const int *dofs =
elem_dof -> GetRow(i);
504 const int n =
elem_dof -> RowSize(i);
505 for (
int j = 0; j < n; j++)
530 for (
int j = 0; j < n; j++)
557 for (
int i = 0; i <
GetNBE(); i++)
569 for (
auto &d : dofs) { d =
DofToVDof(d, component); }
582 for (
auto v : bdr_verts)
591 for (
auto &d : dofs) { d =
DofToVDof(d, component); }
595 for (
auto e : bdr_edges)
604 for (
auto &d : dofs) { d =
DofToVDof(d, component); }
608 for (
auto f : bdr_faces)
617 for (
auto &d : dofs) { d =
DofToVDof(d, component); }
644 std::string error_msg =
"failed dof: ";
645 auto ess_tdofs_ = ess_tdofs.
HostRead();
646 auto ess_tdofs2_ = ess_tdofs2.
HostRead();
647 for (
int i = 0; i < ess_tdofs2.
Size(); ++i)
649 if (
bool(ess_tdofs_[i]) !=
bool(ess_tdofs2_[i]))
651 error_msg += std::to_string(i) +=
"(R ";
652 error_msg += std::to_string(
bool(ess_tdofs_[i])) +=
" P^T ";
653 error_msg += std::to_string(
bool(ess_tdofs2_[i])) +=
") ";
660 MFEM_ASSERT(R->
Width() == ess_vdofs.
Size(),
"!");
661 MFEM_VERIFY(counter == 0,
"internal MFEM error: counter = " << counter
662 <<
' ' << error_msg);
692 for (
int i = 0; i < ext_face_marker.
Size(); i++)
694 if (ext_face_marker[i])
705 for (
auto &d : dofs) { d =
DofToVDof(d, component); }
731 std::string error_msg =
"failed dof: ";
732 auto ext_tdofs_ = ext_tdofs.
HostRead();
733 auto ext_tdofs2_ = ext_tdofs2.
HostRead();
734 for (
int i = 0; i < ext_tdofs2.
Size(); ++i)
736 if (
bool(ext_tdofs_[i]) !=
bool(ext_tdofs2_[i]))
738 error_msg += std::to_string(i) +=
"(R ";
739 error_msg += std::to_string(
bool(ext_tdofs_[i])) +=
" P^T ";
740 error_msg += std::to_string(
bool(ext_tdofs2_[i])) +=
") ";
747 MFEM_ASSERT(R->
Width() == ext_vdofs.
Size(),
"!");
748 MFEM_VERIFY(counter == 0,
"internal MFEM error: counter = " << counter
749 <<
' ' << error_msg);
761 for (
int i = 0; i < marker.
Size(); i++)
763 if (marker[i]) { num_marked++; }
767 list.Reserve(num_marked);
768 for (
int i = 0; i < marker.
Size(); i++)
770 if (marker[i]) { list.Append(i); }
782 for (
int i = 0; i < list.Size(); i++)
784 marker[list[i]] = mark_val;
792 if (
cP) {
cP->BooleanMultTranspose(dofs, cdofs); }
793 else { dofs.
Copy(cdofs); }
800 if (
cR) {
cR->BooleanMultTranspose(cdofs, dofs); }
801 else { cdofs.
Copy(dofs); }
819 if (d_vdofs.
Size() != c_vdofs.
Size())
821 mfem_error (
"FiniteElementSpace::D2C_GlobalRestrictionMatrix (...)");
825 for (j = 0; j < d_vdofs.
Size(); j++)
827 R -> Set (c_vdofs[j], d_vdofs[j], 1.0);
851 if (c_dofs.
Size() != 1)
853 "D2Const_GlobalRestrictionMatrix (...)");
856 for (j = 0; j < d_dofs.
Size(); j++)
858 R -> Set (c_dofs[0], d_dofs[j], 1.0);
882 for (
int i = 0; i <
mesh ->
GetNE(); i++)
889 if (geom != cached_geom)
891 h_fe =
this ->
GetFE (i);
892 l_fe = lfes ->
GetFE (i);
894 h_fe->
Project(*l_fe, T, loc_restr);
898 for (
int vd = 0; vd < lvdim; vd++)
900 l_dofs.
Copy(l_vdofs);
903 h_dofs.
Copy(h_vdofs);
906 R -> SetSubMatrix (l_vdofs, h_vdofs, loc_restr, 1);
919 for (
int i = skipfirst; i < slave_dofs.
Size(); i++)
921 const int sdof = slave_dofs[i];
924 for (
int j = 0; j < master_dofs.
Size(); j++)
926 const real_t coef = I(i, j);
927 if (std::abs(coef) > 1e-12)
929 const int mdof = master_dofs[j];
932 deps.
Add(sdof, mdof, coef);
955 MFEM_ASSERT(V.
Size() == E.
Size(),
"");
962 for (
int i = 0; i < E.
Size(); i++)
964 int a = i,
b = (i+1) % V.
Size();
965 if (V[
a] > V[
b]) { std::swap(
a,
b); }
972 for (
int j = 0; j < 2; j++)
974 edge_pm(j, 0) = (*pm)(j,
a);
975 edge_pm(j, 1) = (*pm)(j,
b);
976 mid[j] = 0.5*((*pm)(j,
a) + (*pm)(j,
b));
981 if (mid[0] > eps && mid[0] < 1-eps &&
982 mid[1] > eps && mid[1] < 1-eps)
1001 for (
int i = 0; i < ndep; i++)
1003 if (!finalized[dep[i]]) {
return false; }
1030 if (!dofs.
Size()) {
return 0; }
1035 for (
int i = 0; i < nv; i++)
1038 dofs[nv+i] = edof[nv+i];
1042 for (
int i = 0; i < ne; i++)
1044 dofs[face_vert*nv + i] = edof[2*nv + i];
1107 MFEM_ASSERT(ent_dofs.
Size() >= num_ent+1,
"");
1111 for (
int i = 0; i < num_ent; i++)
1113 if (ent_dofs.
RowSize(i) <= 1) {
continue; }
1118 if (geom != last_geom)
1126 const auto *master_fe =
fec->
GetFE(geom,
p);
1127 if (!master_fe) {
break; }
1130 for (
int variant = 1; ; variant++)
1132 const int q =
GetEntityDofs(entity, i, slave_dofs, geom, variant);
1133 if (q < 0) {
break; }
1135 const auto *slave_fe =
fec->
GetFE(geom, q);
1148 "This method should not be used with a ParFiniteElementSpace!");
1163 Array<int> master_dofs, slave_dofs, highest_dofs;
1182 for (
int entity = 2; entity >= 1; entity--)
1185 if (!list.masters.Size()) {
continue; }
1194 if (!master_dofs.
Size()) {
continue; }
1197 if (!master_fe) {
continue; }
1199 switch (master_geom)
1204 default: MFEM_ABORT(
"unsupported geometry");
1207 for (
int si = master.slaves_begin; si < master.slaves_end; si++)
1212 if (!slave_dofs.
Size()) {
break; }
1231 const auto *pm = list.point_matrices[master_geom][slave.
matrix];
1233 slave_dofs, slave.
index, pm);
1244 const int q =
GetEntityDofs(entity, master.index, highest_dofs,
1245 master_geom, nvar-1);
1246 const auto *highest_fe =
fec->
GetFE(master_geom, q);
1263 int n_true_dofs = 0;
1264 for (
int i = 0; i <
ndofs; i++)
1266 if (!deps.
RowSize(i)) { n_true_dofs++; }
1270 if (n_true_dofs ==
ndofs)
1288 for (
int i = 0; i < n_true_dofs; i++)
1293 cR_I[n_true_dofs] = n_true_dofs;
1317 for (
int i = 0, true_dof = 0; i <
ndofs; i++)
1321 cP->
Add(i, true_dof, 1.0);
1323 finalized[i] =
true;
1329 inv_deps.
GetRow(i, cols, srow);
1330 cR_hp->AddRow(true_dof, cols, srow);
1334 cR_hp->Add(true_dof, i, 1.0);
1350 int n_finalized = n_true_dofs;
1354 for (
int dof = 0; dof <
ndofs; dof++)
1360 int n_dep = deps.
RowSize(dof);
1362 for (
int j = 0; j < n_dep; j++)
1364 cP->GetRow(dep_col[j], cols, srow);
1365 srow *= dep_coef[j];
1366 cP->AddRow(dof, cols, srow);
1369 finalized[dof] =
true;
1379 MFEM_VERIFY(n_finalized ==
ndofs,
1380 "Error creating cP matrix: n_finalized = "
1381 << n_finalized <<
", ndofs = " <<
ndofs);
1396 if (
vdim == 1) {
return; }
1398 int height = mat.
Height();
1399 int width = mat.
Width();
1405 for (
int i = 0; i < height; i++)
1407 mat.
GetRow(i, dofs, srow);
1408 for (
int vd = 0; vd <
vdim; vd++)
1515 auto key = std::make_tuple(is_dg_space, f_ordering, type, m);
1516 auto itr =
L2F.find(key);
1517 if (itr !=
L2F.end())
1519 return itr->second.get();
1523 std::unique_ptr<FaceRestriction> res;
1543 return L2F.emplace(key, std::move(res)).first->second.get();
1550 const auto key = make_tuple(f_ordering, type);
1559 auto interp = make_unique<InterpolationManager>(*
this, f_ordering, type);
1571 interp->RegisterFaceConformingInterpolation(face, face_idx);
1575 interp->RegisterFaceCoarseToFineInterpolation(face, face_idx);
1581 interp->LinearizeInterpolatorMapIntoVector();
1582 interp->InitializeNCInterpConfig();
1584 return *
interpolations.emplace(key, std::move(interp)).first->second;
1596 for (
int i = 0; i <
E2Q_array.Size(); i++)
1599 if (qi->
IntRule == &ir) {
return qi; }
1615 for (
int i = 0; i <
E2Q_array.Size(); i++)
1618 if (qi->
qspace == &qs) {
return qi; }
1640 if (qi->
IntRule == &ir) {
return qi; }
1653 if (qi->
IntRule == &ir) {
return qi; }
1664 const int coarse_ndofs,
const Table &coarse_elem_dof,
1677 if (elem_geoms.
Size() == 1)
1679 const int coarse_ldof = localP[elem_geoms[0]].
SizeJ();
1697 const int fine_ldof = localP[geom].
SizeI();
1702 for (
int vd = 0; vd <
vdim; vd++)
1704 coarse_dofs.
Copy(coarse_vdofs);
1707 for (
int i = 0; i < fine_ldof; i++)
1715 P->
SetRow(r, coarse_vdofs, row);
1722 MFEM_ASSERT(mark.
Sum() == P->
Height(),
"Not all rows of P set.");
1728 const int coarse_ndofs,
const Table &coarse_elem_dof)
const
1752 const int ldof = fe->
GetDof();
1758 const int fine_ldof = lP.
Height();
1763 for (
int vd = 0; vd <
vdim; vd++)
1765 coarse_dofs.
Copy(coarse_vdofs);
1768 for (
int i = 0; i < fine_ldof; i++)
1776 P->
SetRow(r, coarse_vdofs, row);
1783 MFEM_VERIFY(mark.
Sum() == P->
Height(),
"Not all rows of P set.");
1796 int nmat = pmats.
SizeK();
1803 localP.
SetSize(ldof, ldof, nmat);
1804 for (
int i = 0; i < nmat; i++)
1812 const Table* old_elem_dof,
1813 const Table* old_elem_fos)
1815 MFEM_VERIFY(
GetNE() >= old_elem_dof->
Size(),
1816 "Previous mesh is not coarser.");
1822 for (
int i = 0; i < elem_geoms.
Size(); i++)
1839 old_elem_dof(old_elem_dof),
1840 old_elem_fos(old_elem_fos)
1842 MFEM_VERIFY(fespace->
GetNE() >= old_elem_dof->
Size(),
1843 "Previous mesh is not coarser.");
1852 for (
int i = 0; i < elem_geoms.
Size(); i++)
1858 ConstructDoFTransArray();
1864 fespace(fespace), old_elem_dof(NULL), old_elem_fos(NULL)
1870 for (
int i = 0; i < elem_geoms.
Size(); i++)
1873 localP[elem_geoms[i]]);
1886 ConstructDoFTransArray();
1891 delete old_elem_dof;
1892 delete old_elem_fos;
1893 for (
int i=0; i<old_DoFTransArray.Size(); i++)
1895 delete old_DoFTransArray[i];
1899void FiniteElementSpace::RefinementOperator::ConstructDoFTransArray()
1902 for (
int i=0; i<old_DoFTransArray.Size(); i++)
1904 old_DoFTransArray[i] = NULL;
1918 const FiniteElement *nd_tet =
1923 new ND_TetDofTransformation(nd_tet->GetOrder());
1926 const FiniteElement *nd_pri =
1931 new ND_WedgeDofTransformation(nd_pri->GetOrder());
1934 const FiniteElement *nd_pyr =
1939 new ND_PyramidDofTransformation(nd_pyr->GetOrder());
1947 Mesh* mesh_ref = fespace->GetMesh();
1951 Array<int> dofs, vdofs, old_dofs, old_vdofs, old_Fo;
1953 int rvdim = fespace->GetVDim();
1954 int old_ndofs = width / rvdim;
1962 for (
int k = 0; k < mesh_ref->
GetNE(); k++)
1966 if (fespace->IsVariableOrder())
1970 const int ldof = fe->
GetDof();
1976 const DenseMatrix &lP = (fespace->IsVariableOrder()) ? eP : localP[geom](
1981 fespace->GetElementDofs(k, dofs, doftrans);
1982 old_elem_dof->GetRow(emb.
parent, old_dofs);
1986 for (
int vd = 0; vd < rvdim; vd++)
1989 fespace->DofsToVDofs(vd, vdofs);
1990 old_dofs.
Copy(old_vdofs);
1991 fespace->DofsToVDofs(vd, old_vdofs, old_ndofs);
1994 lP.
Mult(subX, subY);
2000 old_elem_fos->GetRow(emb.
parent, old_Fo);
2001 old_DoFTrans.SetDofTransformation(*old_DoFTransArray[geom]);
2002 old_DoFTrans.SetFaceOrientations(old_Fo);
2005 for (
int vd = 0; vd < rvdim; vd++)
2008 fespace->DofsToVDofs(vd, vdofs);
2009 old_dofs.
Copy(old_vdofs);
2010 fespace->DofsToVDofs(vd, old_vdofs, old_ndofs);
2013 old_DoFTrans.InvTransformPrimal(subX);
2014 lP.
Mult(subX, subY);
2018 doftrans.
SetVDim(rvdim, fespace->GetOrdering());
2028 Mesh* mesh_ref = fespace->GetMesh();
2035 Array<int> f_dofs, c_dofs, f_vdofs, c_vdofs, old_Fo;
2037 int rvdim = fespace->GetVDim();
2038 int old_ndofs = width / rvdim;
2040 Vector subY, subX, subYt;
2047 for (
int k = 0; k < mesh_ref->
GetNE(); k++)
2052 if (fespace->IsVariableOrder())
2054 fe = fespace->GetFE(k);
2056 const int ldof = fe->
GetDof();
2063 const DenseMatrix &lP = (fespace->IsVariableOrder()) ? eP : localP[geom](
2066 fespace->GetElementDofs(k, f_dofs, doftrans);
2067 old_elem_dof->GetRow(emb.
parent, c_dofs);
2073 for (
int vd = 0; vd < rvdim; vd++)
2075 f_dofs.
Copy(f_vdofs);
2076 fespace->DofsToVDofs(vd, f_vdofs);
2077 c_dofs.
Copy(c_vdofs);
2078 fespace->DofsToVDofs(vd, c_vdofs, old_ndofs);
2081 for (
int p = 0;
p < f_dofs.
Size(); ++
p)
2096 old_elem_fos->GetRow(emb.
parent, old_Fo);
2097 old_DoFTrans.SetDofTransformation(*old_DoFTransArray[geom]);
2098 old_DoFTrans.SetFaceOrientations(old_Fo);
2101 for (
int vd = 0; vd < rvdim; vd++)
2103 f_dofs.
Copy(f_vdofs);
2104 fespace->DofsToVDofs(vd, f_vdofs);
2105 c_dofs.
Copy(c_vdofs);
2106 fespace->DofsToVDofs(vd, c_vdofs, old_ndofs);
2110 for (
int p = 0;
p < f_dofs.
Size(); ++
p)
2118 old_DoFTrans.TransformDual(subYt);
2121 doftrans.
SetVDim(rvdim, fespace->GetOrdering());
2124 for (
int p = 0;
p < f_dofs.
Size(); ++
p)
2142 : geom(g), num_children(n), children(c) { }
2144 bool operator<(
const RefType &other)
const
2146 if (geom < other.geom) {
return true; }
2147 if (geom > other.geom) {
return false; }
2148 if (num_children < other.num_children) {
return true; }
2149 if (num_children > other.num_children) {
return false; }
2150 for (
int i = 0; i < num_children; i++)
2152 if (children[i].one < other.children[i].one) {
return true; }
2153 if (children[i].one > other.children[i].one) {
return false; }
2159void GetCoarseToFineMap(
const CoarseFineTransformations &cft,
2161 Table &coarse_to_fine,
2162 Array<int> &coarse_to_ref_type,
2163 Table &ref_type_to_matrix,
2164 Array<Geometry::Type> &ref_type_to_geom)
2166 const int fine_ne = cft.embeddings.Size();
2168 for (
int i = 0; i < fine_ne; i++)
2170 coarse_ne = std::max(coarse_ne, cft.embeddings[i].parent);
2174 coarse_to_ref_type.SetSize(coarse_ne);
2175 coarse_to_fine.SetDims(coarse_ne, fine_ne);
2177 Array<int> cf_i(coarse_to_fine.GetI(), coarse_ne+1);
2178 Array<Pair<int,int> > cf_j(fine_ne);
2180 for (
int i = 0; i < fine_ne; i++)
2182 cf_i[cft.embeddings[i].parent+1]++;
2185 MFEM_ASSERT(cf_i.Last() == cf_j.Size(),
"internal error");
2186 for (
int i = 0; i < fine_ne; i++)
2188 const Embedding &e = cft.embeddings[i];
2189 cf_j[cf_i[e.parent]].one = e.matrix;
2190 cf_j[cf_i[e.parent]].two = i;
2193 std::copy_backward(cf_i.begin(), cf_i.end()-1, cf_i.end());
2195 for (
int i = 0; i < coarse_ne; i++)
2197 std::sort(&cf_j[cf_i[i]], cf_j.GetData() + cf_i[i+1]);
2199 for (
int i = 0; i < fine_ne; i++)
2201 coarse_to_fine.GetJ()[i] = cf_j[i].two;
2207 map<RefType,int> ref_type_map;
2208 for (
int i = 0; i < coarse_ne; i++)
2210 const int num_children = cf_i[i+1]-cf_i[i];
2211 MFEM_ASSERT(num_children > 0,
"");
2212 const int fine_el = cf_j[cf_i[i]].two;
2215 const RefType ref_type(geom, num_children, &cf_j[cf_i[i]]);
2216 pair<map<RefType,int>::iterator,
bool> res =
2217 ref_type_map.insert(
2218 pair<const RefType,int>(ref_type, (
int)ref_type_map.size()));
2219 coarse_to_ref_type[i] = res.first->second;
2222 ref_type_to_matrix.MakeI((
int)ref_type_map.size());
2223 ref_type_to_geom.SetSize((
int)ref_type_map.size());
2224 for (map<RefType,int>::iterator it = ref_type_map.begin();
2225 it != ref_type_map.end(); ++it)
2227 ref_type_to_matrix.AddColumnsInRow(it->second, it->first.num_children);
2228 ref_type_to_geom[it->second] = it->first.geom;
2231 ref_type_to_matrix.MakeJ();
2232 for (map<RefType,int>::iterator it = ref_type_map.begin();
2233 it != ref_type_map.end(); ++it)
2235 const RefType &rt = it->first;
2236 for (
int j = 0; j < rt.num_children; j++)
2238 ref_type_to_matrix.AddConnection(it->second, rt.children[j].one);
2241 ref_type_to_matrix.ShiftUpI();
2256 "incompatible coarse and fine FE spaces");
2264 for (
int gi = 0; gi < elem_geoms.
Size(); gi++)
2267 DenseTensor &lP = localP[geom], &lM = localM[geom];
2277 for (
int i = 0; i < pmats.
SizeK(); i++)
2287 Table ref_type_to_matrix;
2288 internal::GetCoarseToFineMap(rtrans, *f_mesh, coarse_to_fine,
2289 coarse_to_ref_type, ref_type_to_matrix,
2291 MFEM_ASSERT(coarse_to_fine.Size() == c_fes->
GetNE(),
"");
2293 const int total_ref_types = ref_type_to_geom.Size();
2295 Array<int> ref_type_to_coarse_elem_offset(total_ref_types);
2296 ref_type_to_fine_elem_offset.
SetSize(total_ref_types);
2299 for (
int i = 0; i < total_ref_types; i++)
2302 ref_type_to_coarse_elem_offset[i] = num_ref_types[g];
2303 ref_type_to_fine_elem_offset[i] = num_fine_elems[g];
2305 num_fine_elems[g] += ref_type_to_matrix.
RowSize(i);
2310 if (num_ref_types[g] == 0) {
continue; }
2311 const int fine_dofs = localP[g].
SizeI();
2312 const int coarse_dofs = localP[g].
SizeJ();
2313 localPtMP[g].
SetSize(coarse_dofs, coarse_dofs, num_ref_types[g]);
2314 localR[g].
SetSize(coarse_dofs, fine_dofs, num_fine_elems[g]);
2316 for (
int i = 0; i < total_ref_types; i++)
2319 DenseMatrix &lPtMP = localPtMP[g](ref_type_to_coarse_elem_offset[i]);
2320 int lR_offset = ref_type_to_fine_elem_offset[i];
2321 const int *mi = ref_type_to_matrix.
GetRow(i);
2322 const int nm = ref_type_to_matrix.
RowSize(i);
2324 for (
int s = 0; s < nm; s++)
2333 for (
int s = 0; s < nm; s++)
2346 delete coarse_elem_dof;
2355 const int fine_vdim = fine_fes->GetVDim();
2356 const int coarse_ndofs = height/fine_vdim;
2357 for (
int coarse_el = 0; coarse_el < coarse_to_fine.Size(); coarse_el++)
2359 coarse_elem_dof->
GetRow(coarse_el, c_vdofs);
2360 fine_fes->DofsToVDofs(c_vdofs, coarse_ndofs);
2365 const int ref_type = coarse_to_ref_type[coarse_el];
2367 const int *fine_elems = coarse_to_fine.GetRow(coarse_el);
2368 const int num_fine_elems = coarse_to_fine.RowSize(coarse_el);
2369 const int lR_offset = ref_type_to_fine_elem_offset[ref_type];
2370 for (
int s = 0; s < num_fine_elems; s++)
2372 const DenseMatrix &lR = localR[geom](lR_offset+s);
2373 fine_fes->GetElementVDofs(fine_elems[s], f_vdofs);
2392 const int nmat = pmats.
SizeK();
2393 const int ldof = fe->
GetDof();
2399 localR.
SetSize(ldof, ldof, nmat);
2400 for (
int i = 0; i < nmat; i++)
2408 const Table* old_elem_dof,
2409 const Table* old_elem_fos)
2413 MFEM_VERIFY(
Nonconforming(),
"Not implemented for conforming meshes.");
2414 MFEM_VERIFY(old_ndofs,
"Missing previous (finer) space.");
2415 MFEM_VERIFY(
ndofs <= old_ndofs,
"Previous space is not finer.");
2425 for (
int i = 0; i < elem_geoms.
Size(); i++)
2439 MFEM_ASSERT(dtrans.
embeddings.Size() == old_elem_dof->
Size(),
"");
2445 for (
int k = 0; k < dtrans.
embeddings.Size(); k++)
2454 const int ldof = fe->
GetDof();
2468 old_elem_dof->
GetRow(k, old_dofs);
2469 MFEM_VERIFY(old_dofs.
Size() == dofs.
Size(),
2470 "Parent and child must have same #dofs.");
2472 for (
int vd = 0; vd <
vdim; vd++)
2474 old_dofs.
Copy(old_vdofs);
2477 for (
int i = 0; i < lR.
Height(); i++)
2479 if (!std::isfinite(lR(i, 0))) {
continue; }
2484 if (is_dg || !mark[m])
2487 R->
SetRow(r, old_vdofs, row);
2498 MFEM_VERIFY(num_marked == R->
Height(),
2499 "internal error: not all rows of R were set.");
2519 int nmat = pmats.
SizeK();
2526 for (
int i = 0; i < nmat; i++)
2535 int vdim_,
int ordering_)
2557 MFEM_VERIFY(mesh_->
NURBSext,
"NURBS FE space requires a NURBS mesh.");
2559 if (NURBSext_ == NULL)
2638 mfem_error(
"FiniteElementSpace::StealNURBSext");
2647 MFEM_VERIFY(
NURBSext,
"NURBSExt not defined.");
2690 *
VNURBSext[1]->GetElementDofTable(),offset1 );
2693 *
VNURBSext[1]->GetBdrElementDofTable(),offset1);
2698 int offset2 = offset1 +
VNURBSext[1]->GetNDof();
2703 *
VNURBSext[1]->GetElementDofTable(),offset1,
2704 *
VNURBSext[2]->GetElementDofTable(),offset2);
2707 *
VNURBSext[1]->GetBdrElementDofTable(),offset1,
2708 *
VNURBSext[2]->GetBdrElementDofTable(),offset2);
2742 if (
b == -1) {
continue; }
2752 for (
int i = 0; i < nv; i++)
2754 MFEM_VERIFY(fv[i] == bv[i],
2755 "non-matching face and boundary elements detected!");
2760 for (
int i = 0; i < row.
Size(); i++)
2763 face_dof_list.
Append(conn);
2772 MFEM_VERIFY(!
NURBSext,
"internal error");
2777 "Variable-order space requires a nonconforming mesh.");
2800 "Mesh was not correctly finalized.");
2814 else if (mixed_faces)
2838 MFEM_ASSERT(lastRow.
Size() == 1,
"");
2866 MFEM_ASSERT(lastRow.
Size() == 1,
"");
2920 const Table & loc_var_ent_dofs,
2925 const int osall0 = var_ent_dofs.
GetI()[entity];
2926 const int osall1 = var_ent_dofs.
GetI()[entity + 1];
2928 const int osloc0 = loc_var_ent_dofs.
GetI()[entity];
2929 const int osloc1 = loc_var_ent_dofs.
GetI()[entity + 1];
2933 for (
int i=osloc0; i<osloc1; ++i)
2935 const int order = loc_var_ent_orders[i];
2937 int na = var_ent_dofs.
GetJ()[j + 1] - var_ent_dofs.
GetJ()[j];
2938 while (var_ent_orders[j] != order && j < osall1 - 1)
2942 na = var_ent_dofs.
GetJ()[j + 1] - var_ent_dofs.
GetJ()[j];
2945 MFEM_ASSERT(var_ent_orders[j] == order,
"");
2947 const int n = loc_var_ent_dofs.
GetJ()[i + 1] - loc_var_ent_dofs.
GetJ()[i];
2949 MFEM_ASSERT(n == na &&
2950 n == var_ent_dofs.
GetJ()[j + 1] - var_ent_dofs.
GetJ()[j],
"");
2952 for (
int k=0; k<n; ++k) {
all2local[ndof_all + k] = ndof_loc + k; }
2962 const int na = var_ent_dofs.
GetJ()[j + 1] - var_ent_dofs.
GetJ()[j];
2977 for (
int i=0; i<
nvdofs; ++i)
3011 for (
int i=ndof_all; i<
ndofs; ++i)
3021 MFEM_ASSERT(bits != 0,
"invalid bit mask");
3022 for (
int order = 0; bits != 0; order++, bits >>= 1)
3024 if (bits & 1) {
return order; }
3058 edge_elem_orders = 0;
3059 face_elem_orders = 0;
3073 const int order = localVar ?
elem_order[i] : baseOrder;
3078 for (
int j = 0; j < E.
Size(); j++)
3080 edge_orders[E[j]] |= mask;
3081 edge_elem_orders[E[j]] |= mask;
3092 for (
int j = 0; j < F.
Size(); j++)
3094 face_orders[F[j]] |= mask;
3095 face_elem_orders[F[j]] |= mask;
3119 std::set<int> changedEdges;
3120 std::set<int> changedFaces;
3129 for (
int i = master.slaves_begin; i < master.slaves_end; i++)
3131 slave_orders |= edge_orders[edge_list.
slaves[i].index];
3134 if (slave_orders == 0)
3139 const int min_order_slaves =
MinOrder(slave_orders);
3140 if (edge_orders[master.index] == 0 ||
3141 min_order_slaves <
MinOrder(edge_orders[master.index]))
3143 edge_orders[master.index] |=
VarOrderBits(1) << min_order_slaves;
3144 changedEdges.insert(master.index);
3150 edge_orders[master.index]);
3151 for (
int i = master.slaves_begin; i < master.slaves_end; i++)
3153 if (edge_list.
slaves[i].index >= numEdges)
3159 edge_orders[edge_list.
slaves[i].index] |= min_mask;
3160 if (eo0 != edge_orders[edge_list.
slaves[i].index])
3162 changedEdges.insert(edge_list.
slaves[i].index);
3176 for (
int i = master.slaves_begin; i < master.slaves_end; i++)
3180 if (slave.
index >= 0)
3184 slave_orders |= face_orders[slave.
index];
3186 if (slave.
index >= numFaces)
3192 for (
int j = 0; j < E.
Size(); j++)
3194 slave_orders |= edge_orders[E[j]];
3204 if (slave_orders == 0)
3209 const int min_order_slaves =
MinOrder(slave_orders);
3210 if (face_orders[master.index] == 0 ||
3211 min_order_slaves <
MinOrder(face_orders[master.index]))
3213 face_orders[master.index] |=
VarOrderBits(1) << min_order_slaves;
3214 changedFaces.insert(master.index);
3221 for (
int i = master.slaves_begin; i < master.slaves_end; i++)
3225 if (slave.
index >= 0 && slave.
index < numFaces)
3228 face_orders[slave.
index] |= min_mask;
3229 if (fo0 != face_orders[slave.
index])
3231 changedFaces.insert(slave.
index);
3241 for (
int j = 0; j < E.
Size(); j++)
3244 edge_orders[E[j]] |= face_orders[i];
3245 if (eo0 != edge_orders[E[j]])
3247 changedEdges.insert(E[j]);
3255 edge_orders, face_orders);
3272 for (
int i=0; i<edge_orders.
Size(); ++i)
3274 if (edge_orders[i] == 0)
3276 skip_edges[i] =
true;
3280 for (
int i=0; i<face_orders.
Size(); ++i)
3282 if (face_orders[i] == 0)
3284 skip_faces[i] =
true;
3304 int num_ent = entity_orders.
Size();
3306 int total_dofs_nonghost = 0;
3314 var_ent_order->
Reserve(num_ent);
3317 int nonGhost = num_ent;
3324 for (
int i = 0; i < num_ent; i++)
3341 for (
int order = 0; bits != 0; order++, bits >>= 1)
3348 if (i < nonGhost) { total_dofs_nonghost += dofs; }
3349 if (var_ent_order) { var_ent_order->
Append(order); }
3355 list.Append(
Connection(num_ent, total_dofs));
3359 return total_dofs_nonghost;
3363 int row,
int ndof)
const
3365 const int *beg = var_dof_table.
GetRow(row);
3366 const int *end = var_dof_table.
GetRow(row + 1);
3371 if ((beg[1] - beg[0]) == ndof) {
return beg[0]; }
3375 MFEM_ABORT(
"DOFs not found for ndof = " << ndof);
3390 if (variant >= end - beg) {
return -1; }
3411 if (variant >= end - beg) {
return -1; }
3425static const char* msg_orders_changed =
3426 "Element orders changed, you need to Update() the space first.";
3468 for (
int i = 0; i < F.
Size(); i++)
3486 for (
int i = 0; i < V.
Size(); i++)
3488 for (
int j = 0; j < nv; j++)
3490 dofs.
Append(V[i]*nv + j);
3497 for (
int i = 0; i < E.
Size(); i++)
3502 for (
int j = 0; j < ne; j++)
3511 for (
int i = 0; i < F.
Size(); i++)
3519 for (
int j = 0; j < nf; j++)
3531 for (
int j = 0; j < nb; j++)
3608 for (
int i = 0; i < V.
Size(); i++)
3610 for (
int j = 0; j < nv; j++)
3612 dofs.
Append(V[i]*nv + j);
3619 for (
int i = 0; i < E.
Size(); i++)
3624 for (
int j = 0; j < ne; j++)
3636 for (
int j = 0; j < nf; j++)
3664 int order, nf, fbase;
3672 if (variant >= end - beg) {
return -1; }
3674 fbase = beg[variant];
3675 nf = beg[variant+1] - fbase;
3681 std::stringstream msg;
3682 msg <<
"fec->GetNumDof(" << (fgeom == Geometry::SQUARE ?
"square" :
"triangle")
3683 <<
", " << order <<
") = " << fec->GetNumDof(fgeom, order) <<
" nf " << nf;
3684 msg <<
" face " << face <<
" variant " << variant << std::endl;
3690 if (variant > 0) {
return -1; }
3709 for (
int i = 0; i < V.
Size(); i++)
3711 for (
int j = 0; j < nv; j++)
3713 dofs.
Append(V[i]*nv + j);
3719 for (
int i = 0; i < E.
Size(); i++)
3724 for (
int j = 0; j < ne; j++)
3730 for (
int j = 0; j < nf; j++)
3743 int order, ne, base;
3748 if (variant >= end - beg) {
return -1; }
3750 base = beg[variant];
3751 ne = beg[variant+1] - base;
3758 if (variant > 0) {
return -1; }
3771 for (
int i = 0; i < 2; i++)
3773 for (
int j = 0; j < nv; j++)
3775 dofs.
Append(V[i]*nv + j);
3778 for (
int j = 0; j < ne; j++)
3790 for (
int j = 0; j < nv; j++)
3805 for (
int j = 0; j < nb; j++)
3835 for (
int j = 0; j < nf; j++)
3847 for (
int j = 0, k =
nvdofs+i*ne; j < ne; j++, k++)
3856 "FiniteElementSpace::GetPatchDofs needs a NURBSExtension");
3866 MFEM_ABORT(
"Empty MPI partitions are not permitted!");
3868 MFEM_ABORT(
"Invalid element id:" << i <<
"; minimum allowed:" << 0 <<
3869 ", maximum allowed:" <<
mesh->
GetNE()-1);
3887 "internal error: " <<
3902 MFEM_VERIFY(fe !=
nullptr,
"Could not determine a typical FE!");
3945 MFEM_VERIFY(be !=
nullptr,
"Could not determine a typical BE!");
3972 "NURBS mesh: only boundary faces are supported!");
3987 MFEM_ASSERT(
mesh->
Dimension() > 1,
"No edges with mesh dimension < 2");
4018 for (
int i = 0; i <
E2Q_array.Size(); i++)
4043 for (
int i = 0; i <
VNURBSext.Size(); i++)
4092 for (
int i = 0; i < elem_geoms.
Size(); i++)
4095 localP[elem_geoms[i]]);
4137 if (RP_case == 0) {
return; }
4150 cR.get(), T.
Ptr(), coarse_P,
false, owner,
false));
4174 Table coarse_to_fine;
4177 for (
int i = 0; i < coarse_to_fine.
Size(); i++)
4179 coarse_to_fine.
GetRow(i, tabrow);
4186 MFEM_ABORT(
"not implemented yet");
4204 MFEM_ABORT(
"Error in update sequence. Space needs to be updated after "
4205 "each mesh modification.");
4212 MFEM_ABORT(
"Updating space after both mesh change and element order "
4213 "change is not supported. Please update separately after "
4224 Table* old_elem_dof = NULL;
4225 Table* old_elem_fos = NULL;
4251 MFEM_VERIFY(!old_orders_changed,
"Interpolation for element order change "
4252 "is not implemented yet, sorry.");
4262 old_elem_fos, old_ndofs));
4265 old_elem_dof = NULL;
4266 old_elem_fos = NULL;
4291 false,
false,
true));
4300 false,
false,
true));
4310 delete old_elem_dof;
4311 delete old_elem_fos;
4328 for (
auto ref : refs)
4356 if (geoms.
Size() != 1) {
return false; }
4370 int fes_nodes_ordering)
const
4373 const int NE = m->
GetNE();
4375 if (NE == 0) { fes_node_pos.
SetSize(0);
return; }
4384 for (
int e = 0; e < NE; e++)
4387 const int mdof_cnt = dofs.
Size() /
dim;
4392 Vector mesh_shape(mdof_cnt), gf_xyz(fdof_cnt *
dim);
4393 for (
int q = 0; q < fdof_cnt; q++)
4396 for (
int d = 0; d <
dim; d++)
4399 gf_xyz(d*fdof_cnt + q) = x * mesh_shape;
4411 int fes_format = 90;
4412 bool nurbs_unit_weights =
false;
4423 MFEM_VERIFY(nurbs_fec,
"invalid FE collection");
4425 const real_t eps = 5e-14;
4436 os << (fes_format == 90 ?
4437 "FiniteElementSpace\n" :
"MFEM FiniteElementSpace v1.0\n")
4438 <<
"FiniteElementCollection: " <<
fec->
Name() <<
'\n'
4439 <<
"VDim: " <<
vdim <<
'\n'
4440 <<
"Ordering: " <<
ordering <<
'\n';
4442 if (fes_format == 100)
4456 os <<
"NURBS_orders\n";
4463 os <<
"NURBS_periodic\n";
4468 if (!nurbs_unit_weights)
4470 os <<
"NURBS_weights\n";
4474 os <<
"End: MFEM FiniteElementSpace v1.0\n";
4478std::shared_ptr<const PRefinementTransferOperator>
4481void FiniteElementSpace
4482::GetEssentialBdrEdgesFaces(
const Array<int> &bdr_attr_is_ess,
4483 std::set<int> & edges, std::set<int> & faces)
const
4486 MFEM_VERIFY(
dim == 2 ||
dim == 3,
"");
4488 for (
int i = 0; i <
GetNBE(); i++)
4500 for (
auto edge : edges_i)
4518 for (
auto e : bdr_edges)
4523 for (
auto f : bdr_faces)
4537 "GetBoundaryLoopEdgeDofs requires 2D or 3D meshes to find edge objects");
4539 boundary_edge_dofs.
SetSize(0);
4540 if (dof_edges) { dof_edges->
SetSize(0); }
4541 if (dof_boundary_elements) { dof_boundary_elements->
SetSize(0); }
4558 std::unordered_map<int, int> dof_count, dof_edge, dof_belem;
4559 Array<int> edge_dofs, edges, edge_orientations;
4562 for (
int i = 0; i < boundary_element_indices.
Size(); ++i)
4564 const int boundary_element_idx = boundary_element_indices[i];
4565 std::unordered_set<int> boundary_element_dofs;
4570 int face_index, face_orientation;
4579 MFEM_VERIFY(edges.
Size() == 1,
4580 "2D boundary element should have exactly one edge");
4583 for (
int j = 0; j < edges.
Size(); ++j)
4586 for (
int k = 0; k < edge_dofs.
Size(); ++k)
4588 const int dof = edge_dofs[k];
4592 if (boundary_element_dofs.insert(dof).second &&
4593 dof_count[dof]++ == 0)
4595 dof_edge[dof] = edges[j];
4596 dof_belem[dof] = boundary_element_idx;
4604 std::vector<int> kept;
4605 kept.reserve(dof_count.size());
4606 for (
const auto &[dof, count] : dof_count)
4608 if (count == 1) { kept.push_back(dof); }
4610 std::sort(kept.begin(), kept.end());
4612 boundary_edge_dofs.
Reserve(
static_cast<int>(kept.size()));
4613 if (dof_edges) { dof_edges->
Reserve(
static_cast<int>(kept.size())); }
4614 if (dof_boundary_elements)
4616 dof_boundary_elements->
Reserve(
static_cast<int>(kept.size()));
4618 for (
int dof : kept)
4620 boundary_edge_dofs.
Append(dof);
4621 if (dof_edges) { dof_edges->
Append(dof_edge[dof]); }
4622 if (dof_boundary_elements) { dof_boundary_elements->
Append(dof_belem[dof]); }
4628 std::vector<
Array<int>> &attr_to_elements)
const
4635 std::unordered_map<int, int> attr_to_index;
4636 for (
int i = 0; i < bdr_attrs.
Size(); ++i)
4638 attr_to_index[bdr_attrs[i]] = i;
4645 auto it = attr_to_index.find(attr);
4646 if (it != attr_to_index.end())
4648 attr_to_elements[it->second].Append(i);
4654 int bdr_attr,
Array<int> &boundary_elements)
const
4662 boundary_elements.
Append(i);
4670 const Vector &loop_normal,
4673 MFEM_VERIFY(dof_edges.
Size() == dof_boundary_elements.
Size(),
4674 "dof_edges and dof_boundary_elements must be parallel-indexed");
4676 const int ndof = dof_edges.
Size();
4677 dof_orientations.
SetSize(ndof);
4680 Vector edge_vec(3), to_edge_vec(3), cross_product(3);
4681 for (
int i = 0; i < ndof; i++)
4683 const int edge_id = dof_edges[i];
4684 const int bdr_elem_idx = dof_boundary_elements[i];
4696 int third_vertex = -1;
4697 for (
int j = 0; j < bdr_elem_verts.
Size(); j++)
4699 int v = bdr_elem_verts[j];
4700 if (v != edge_verts[0] && v != edge_verts[1])
4707 if (third_vertex == -1)
4709 MFEM_ABORT(
"Boundary element " << bdr_elem_idx <<
" has only 2 vertices, "
4710 "but 3D boundary elements must have at least 3 vertices");
4716 for (
int j = 0; j < 3; j++) { edge_vec[j] = v1[j] - v0[j]; }
4719 for (
int j = 0; j < 3; j++)
4721 real_t edge_midpoint = (v0[j] + v1[j]) * 0.5;
4722 to_edge_vec[j] = edge_midpoint - v2[j];
4726 to_edge_vec.cross3D(edge_vec, cross_product);
4729 real_t dot_product = cross_product * loop_normal;
4730 dof_orientations[i] = (dot_product > 0) ? 1 : -1;
4737 int fes_format = 0, ord;
4743 getline(input, buff);
4745 if (buff ==
"FiniteElementSpace") { fes_format = 90; }
4746 else if (buff ==
"MFEM FiniteElementSpace v1.0") { fes_format = 100; }
4747 else { MFEM_ABORT(
"input stream is not a FiniteElementSpace!"); }
4748 getline(input, buff,
' ');
4750 getline(input, buff);
4753 getline(input, buff,
' ');
4755 getline(input, buff,
' ');
4761 if (fes_format == 90)
4765 MFEM_VERIFY(m->
NURBSext,
"NURBS FE collection requires a NURBS mesh!");
4766 const int order = nurbs_fec->
GetOrder();
4774 else if (fes_format == 100)
4779 MFEM_VERIFY(input.good(),
"error reading FiniteElementSpace v1.0");
4780 getline(input, buff);
4782 if (buff ==
"NURBS_order" || buff ==
"NURBS_orders")
4784 MFEM_VERIFY(nurbs_fec,
4785 buff <<
": NURBS FE collection is required!");
4786 MFEM_VERIFY(m->
NURBSext, buff <<
": NURBS mesh is required!");
4787 MFEM_VERIFY(!nurbs_ext, buff <<
": order redefinition!");
4788 if (buff ==
"NURBS_order")
4801 else if (buff ==
"NURBS_periodic")
4808 else if (buff ==
"NURBS_weights")
4810 MFEM_VERIFY(nurbs_ext,
"NURBS_weights: NURBS_orders have to be "
4811 "specified before NURBS_weights!");
4814 else if (buff ==
"element_orders")
4816 MFEM_VERIFY(!nurbs_fec,
"section element_orders cannot be used "
4817 "with a NURBS FE collection");
4818 MFEM_ABORT(
"element_orders: not implemented yet!");
4820 else if (buff ==
"End: MFEM FiniteElementSpace v1.0")
4826 MFEM_ABORT(
"unknown section: " << buff);
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
void Load(std::istream &in, int fmt=0)
Read an Array from the stream in using format fmt. The format fmt can be:
const T * HostRead() const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), false).
void Reserve(int capacity)
Ensures that the allocated size is at least the given size.
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int Size() const
Return the logical size of the array.
void MakeRef(T *data_, int size_, bool own_data=false)
Make this Array a reference to a pointer.
void DeleteAll()
Delete the whole array.
int Append(const T &el)
Append element 'el' to array, resize if necessary.
void Save(std::ostream &out, int fmt=0) const
Save the Array to the stream out using the format fmt. The format fmt can be:
void Copy(Array ©) const
Create a copy of the internal array to the provided copy.
T Sum() const
Return the sum of all the array entries using the '+'' operator for class 'T'.
T * HostWrite()
Shortcut for mfem::Write(a.GetMemory(), a.Size(), false).
void Mult(const real_t *x, real_t *y) const
Matrix vector multiplication with the inverse of dense matrix.
Data type dense matrix using column-major storage.
void Mult(const real_t *x, real_t *y) const
Matrix vector multiplication.
void MultTranspose(const real_t *x, real_t *y) const
Multiply a vector with the transpose matrix.
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
void UseExternalData(real_t *d, int h, int w)
Change the data array and the size of the DenseMatrix.
void GetRow(int r, Vector &row) const
Rank 3 tensor (array of matrices)
void SetSize(int i, int j, int k, MemoryType mt_=MemoryType::PRESERVE)
Abstract base class that defines an interface for element restrictions.
Operator that converts FiniteElementSpace L-vectors to E-vectors.
Abstract data type element.
virtual void GetVertices(Array< int > &v) const =0
Get the indices defining the vertices.
int GetAttribute() const
Return element's attribute.
virtual int GetNVertices() const =0
A class that performs interpolation from a face E-vector to quadrature point values and/or derivative...
const IntegrationRule * IntRule
Not owned.
static bool SupportsFESpace(const FiniteElementSpace &fes)
Returns true if the given finite element space is supported by FaceQuadratureInterpolator.
Base class for operators that extracts Face degrees of freedom.
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
static FiniteElementCollection * New(const char *name)
Factory method: return a newly allocated FiniteElementCollection according to the given name.
const int * GetDofOrdering(Geometry::Type geom, int p, int ori) const
Variable order version of DofOrderForOrientation().
int GetOrder() const
Return the order (polynomial degree) of the FE collection, corresponding to the order/degree returned...
virtual int GetContType() const =0
int HasFaceDofs(Geometry::Type geom, int p) const
virtual int DofForGeometry(Geometry::Type GeomType) const =0
int GetNumDof(Geometry::Type geom, int p) const
Variable order version of DofForGeometry().
virtual const FiniteElement * TraceFiniteElementForGeometry(Geometry::Type GeomType) const
const FiniteElement * GetTraceFE(Geometry::Type geom, int p) const
Variable order version of TraceFiniteElementForGeometry().
virtual const char * Name() const
const FiniteElement * GetFE(Geometry::Type geom, int p) const
Variable order version of FiniteElementForGeometry().
@ DISCONTINUOUS
Field is discontinuous across element interfaces.
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const =0
virtual ~DerefinementOperator()
void Mult(const Vector &x, Vector &y) const override
Operator application: y=A(x).
DerefinementOperator(const FiniteElementSpace *f_fes, const FiniteElementSpace *c_fes, BilinearFormIntegrator *mass_integ)
TODO: Implement DofTransformation support.
GridFunction interpolation operator applicable after mesh refinement.
virtual ~RefinementOperator()
virtual void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
RefinementOperator(const FiniteElementSpace *fespace, Table *old_elem_dof, Table *old_elem_fos, int old_ndofs)
virtual void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
std::unique_ptr< FiniteElementSpace > fesPrev
void Save(std::ostream &out) const
Save finite element space to output stream out.
void DestroyDoFTransArray()
virtual void ApplyGhostElementOrdersToEdgesAndFaces(Array< VarOrderBits > &edge_orders, Array< VarOrderBits > &face_orders) const
Helper function for ParFiniteElementSpace.
int GetEntityVDofs(int entity, int index, Array< int > &dofs, Geometry::Type master_geom=Geometry::INVALID, int variant=0) const
Helper to get vertex, edge or face VDOFs (entity=0,1,2 resp.).
void GetVDofs(int vd, Array< int > &dofs, int ndofs=-1) const
Returns the indices of all of the VDofs for the specified dimension 'vd'.
DofTransformation DoFTrans
static int EncodeDof(int entity_base, int idx)
Helper to encode a sign flip into a DOF index (for Hcurl/Hdiv shapes).
const SparseMatrix * GetConformingRestriction() const
The returned SparseMatrix is owned by the FiniteElementSpace.
void ReorderElementToDofTable()
Reorder the scalar DOFs based on the element ordering.
Array< char > var_face_orders
int GetVectorDim() const
Return the total dimension of a vector in the space.
bool IsVariableOrder() const
Returns true if the space contains elements of varying polynomial orders.
void SetRestriction(const SparseMatrix &r)
void BuildNURBSFaceToDofTable() const
Generates partial face_dof table for a NURBS space.
void BuildDofToBdrArrays() const
Initialize internal data that enables the use of the methods GetBdrElementForDof() and GetBdrLocalDof...
static void AddDependencies(SparseMatrix &deps, Array< int > &master_dofs, Array< int > &slave_dofs, DenseMatrix &I, int skipfirst=0)
const Table & GetElementToDofTable() const
Return a reference to the internal Table that stores the lists of scalar dofs, for each mesh element,...
Array< int > dof_ldof_array
Array< StatelessDofTransformation * > DoFTransArray
void DofsToVDofs(Array< int > &dofs, int ndofs=-1) const
Compute the full set of vdofs corresponding to each entry in dofs.
void GetEdgeInteriorDofs(int i, Array< int > &dofs) const
Returns the indices of the degrees of freedom for the interior of the specified edge.
Array< FaceQuadratureInterpolator * > E2BFQ_array
const FiniteElement * GetBE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th boundary fac...
Array< FaceQuadratureInterpolator * > E2IFQ_array
friend struct DerefineMatrixOp
Array< int > face_min_nghb_order
DofTransformation * GetElementDofs(int elem, Array< int > &dofs) const
Returns indices of degrees of freedom of element 'elem'. The returned indices are offsets into an ldo...
int GetNumElementInteriorDofs(int i) const
Returns the number of degrees of freedom associated with the interior of the specified element.
std::shared_ptr< PRefinementTransferOperator > PTh
virtual void GetExteriorTrueDofs(Array< int > &exterior_dofs, int component=-1) const
Get a list of all true dofs on the exterior of the mesh, exterior_dofs. For spaces with 'vdim' > 1,...
void GetEdgeVDofs(int i, Array< int > &vdofs) const
Returns the indices of the degrees of freedom for the specified edge, including the DOFs for the vert...
NURBSExtension * NURBSext
virtual int GetFaceDofs(int face, Array< int > &dofs, int variant=0) const
Returns the indices of the degrees of freedom for the specified face, including the DOFs for the edge...
virtual void GetTrueTransferOperator(const FiniteElementSpace &coarse_fes, OperatorHandle &T) const
Construct and return an Operator that can be used to transfer true-dof data from coarse_fes,...
static void AdjustVDofs(Array< int > &vdofs)
Remove the orientation information encoded into an array of dofs Some basis function types have a rel...
virtual void GetExteriorVDofs(Array< int > &exterior_vdofs, int component=-1) const
Mark degrees of freedom associated with exterior faces of the mesh. For spaces with 'vdim' > 1,...
SparseMatrix * VariableOrderRefinementMatrix(const int coarse_ndofs, const Table &coarse_elem_dof) const
int GetEdgeOrder(int edge, int variant=0) const
Array< char > loc_var_face_orders
bool Nonconforming() const
void GetVertexVDofs(int i, Array< int > &vdofs) const
Returns the indices of the degrees of freedom for the specified vertices.
void GetVertexDofs(int i, Array< int > &dofs) const
Returns the indices of the degrees of freedom for the specified vertices.
void BuildFaceToDofTable() const
int GetFaceOrder(int face, int variant=0) const
Returns the polynomial degree of the i'th face finite element.
int GetNumBorderDofs(Geometry::Type geom, int order) const
FiniteElementSpace()
Default constructor: the object is invalid until initialized using the method Load().
Array< int > dof_elem_array
int FindFaceDof(int face, int ndof) const
Similar to FindEdgeDof, but used for mixed meshes too.
static int MinOrder(VarOrderBits bits)
Return the minimum order (least significant bit set) in the bit mask.
static void ListToMarker(const Array< int > &list, int marker_size, Array< int > &marker, int mark_val=-1)
Convert an array of indices (list) to a Boolean marker array where all indices in the list are marked...
MFEM_DEPRECATED void RebuildElementToDofTable()
(
int GetNDofs() const
Returns number of degrees of freedom. This is the number of Local Degrees of Freedom.
bool orders_changed
True if at least one element order changed (variable-order space only).
SparseMatrix * DerefinementMatrix(int old_ndofs, const Table *old_elem_dof, const Table *old_elem_fos)
Calculate GridFunction restriction matrix after mesh derefinement.
friend class PRefinementTransferOperator
void GetLocalRefinementMatrices(Geometry::Type geom, DenseTensor &localP) const
void GetEdgeInteriorVDofs(int i, Array< int > &vdofs) const
Returns the indices of the degrees of freedom for the interior of the specified edge.
void GetTransferOperator(const FiniteElementSpace &coarse_fes, OperatorHandle &T) const
Construct and return an Operator that can be used to transfer GridFunction data from coarse_fes,...
SparseMatrix * D2C_GlobalRestrictionMatrix(FiniteElementSpace *cfes)
Generate the global restriction matrix from a discontinuous FE space to the continuous FE space of th...
virtual void GetEssentialTrueDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_tdof_list, int component=-1) const
Get a list of essential true dofs, ess_tdof_list, corresponding to the boundary attributes marked in ...
int GetNBE() const
Returns number of boundary elements in the mesh.
virtual void UpdateMeshPointer(Mesh *new_mesh)
int GetDegenerateFaceDofs(int index, Array< int > &dofs, Geometry::Type master_geom, int variant) const
const QuadratureInterpolator * GetQuadratureInterpolator(const IntegrationRule &ir) const
Return a QuadratureInterpolator that interpolates E-vectors to quadrature point values and/or derivat...
Array< char > ghost_edge_orders
int GetBdrAttribute(int i) const
Array< int > dof_bdr_elem_array
int GetEntityDofs(int entity, int index, Array< int > &dofs, Geometry::Type master_geom=Geometry::INVALID, int variant=0) const
Helper to get vertex, edge or face DOFs (entity=0,1,2 resp.).
const InterpolationManager & GetInterpolationManager(ElementDofOrdering f_ordering, FaceType type) const
virtual const Operator * GetRestrictionOperator() const
An abstract operator that performs the same action as GetRestrictionMatrix.
static constexpr int MaxVarOrder
virtual void CopyProlongationAndRestriction(const FiniteElementSpace &fes, const Array< int > *perm)
Copies the prolongation and restriction matrices from fes.
Array< char > var_edge_orders
const FiniteElement * GetTypicalBE() const
Return a "typical" boundary element.
std::unique_ptr< Operator > R_transpose
Operator computing the action of the transpose of the restriction.
int MakeDofTable(int ent_dim, const Array< VarOrderBits > &entity_orders, Table &entity_dofs, Array< char > *var_ent_order)
void UpdateElementOrders()
Resize the elem_order array on mesh change.
void MakeVDimMatrix(SparseMatrix &mat) const
Replicate 'mat' in the vector dimension, according to vdim ordering mode.
int GetNF() const
Returns number of faces (i.e. co-dimension 1 entities) in the mesh.
SparseMatrix * H2L_GlobalRestrictionMatrix(FiniteElementSpace *lfes)
Construct the restriction matrix from the FE space given by (*this) to the lower degree FE space give...
SparseMatrix * D2Const_GlobalRestrictionMatrix(FiniteElementSpace *cfes)
Generate the global restriction matrix from a discontinuous FE space to the piecewise constant FE spa...
const FiniteElementCollection * fec
Associated FE collection (not owned).
void GetNodePositions(const Vector &mesh_nodes, Vector &fes_node_pos, int fes_nodes_ordering=Ordering::byNODES) const
Compute the space's node positions w.r.t. given mesh positions. The function uses FiniteElement::GetN...
FiniteElementCollection * Load(Mesh *m, std::istream &input)
Read a FiniteElementSpace from a stream. The returned FiniteElementCollection is owned by the caller.
void BuildBdrElementToDofTable() const
DofTransformation * GetElementVDofs(int i, Array< int > &vdofs) const
Returns indices of degrees of freedom for the i'th element. The returned indices are offsets into an ...
Array< QuadratureInterpolator * > E2Q_array
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
Ordering::Type GetOrdering() const
Return the ordering method.
NURBSExtension * StealNURBSext()
void GetPatchDofs(int patch, Array< int > &dofs) const
Returns indices of degrees of freedom for NURBS patch index patch. Cartesian ordering is used,...
void BuildDofToArrays_() const
Initialize internal data that enables the use of the methods GetElementForDof() and GetLocalDofForDof...
const Operator * GetRestrictionTransposeOperator() const
Return an operator that performs the transpose of GetRestrictionOperator.
static bool DofFinalizable(int dof, const Array< bool > &finalized, const SparseMatrix &deps)
void GetLocalDerefinementMatrices(Geometry::Type geom, DenseTensor &localR) const
void BuildConformingInterpolation() const
Calculate the cP and cR matrices for a nonconforming mesh.
int GetNE() const
Returns number of elements in the mesh.
int vdim
Vector dimension (number of unknowns per degree of freedom).
Table var_face_dofs
NOTE: also used for spaces with mixed faces.
OperatorHandle L2E_nat
The element restriction operators, see GetElementRestriction().
bool lastUpdatePRef
Flag to indicate whether the last update was for p-refinement.
std::unordered_map< std::tuple< ElementDofOrdering, FaceType >, std::unique_ptr< InterpolationManager >, TupleHasher > interpolations
int * bdofs
internal DOFs of elements if mixed/var-order; NULL otherwise
std::unordered_map< key_face, std::unique_ptr< FaceRestriction >, TupleHasher > L2F
const ElementRestrictionOperator * GetElementRestriction(ElementDofOrdering e_ordering) const
Return an Operator that converts L-vectors to E-vectors.
const FiniteElement * GetEdgeElement(int i, int variant=0) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th edge in the ...
Array< char > ghost_face_orders
int GetEdgeDofs(int edge, Array< int > &dofs, int variant=0) const
Returns the indices of the degrees of freedom for the specified edge, including the DOFs for the vert...
std::unique_ptr< SparseMatrix > cR
Conforming restriction matrix such that cR.cP=I.
void ConstructDoFTransArray()
void GetElementInteriorVDofs(int i, Array< int > &vdofs) const
Returns the indices of the degrees of freedom for the interior of the specified element.
void GetFaceVDofs(int i, Array< int > &vdofs) const
Returns the indices of the degrees of freedom for the specified face, including the DOFs for the edge...
Array< char > loc_var_edge_orders
virtual void Update(bool want_transform=true)
Reflect changes in the mesh: update number of DOFs, etc. Also, calculate GridFunction transformation ...
OperatorHandle Th
Transformation to apply to GridFunctions after space Update().
SparseMatrix * RefinementMatrix(int old_ndofs, const Table *old_elem_dof, const Table *old_elem_fos)
std::uint64_t VarOrderBits
Bit-mask representing a set of orders needed by an edge/face.
void GetBoundaryElementsByAttribute(const Array< int > &bdr_attrs, std::vector< Array< int > > &attr_to_elements) const
Get boundary elements grouped by attribute.
SparseMatrix * RefinementMatrix_main(const int coarse_ndofs, const Table &coarse_elem_dof, const Table *coarse_elem_fos, const DenseTensor localP[]) const
int ndofs
Number of degrees of freedom. Number of unknowns is ndofs * vdim.
std::unique_ptr< SparseMatrix > cP
void AddEdgeFaceDependencies(SparseMatrix &deps, Array< int > &master_dofs, const FiniteElement *master_fe, Array< int > &slave_dofs, int slave_face, const DenseMatrix *pm) const
const FiniteElement * GetTraceElement(int i, Geometry::Type geom_type) const
Return the trace element from element 'i' to the given 'geom_type'.
bool UsesRaggedTensorBasis() const
Return true if the mesh contains only one topology, the elements are all triangles or tetrahedrons,...
void ComputeLoopEdgeOrientations(const Array< int > &dof_edges, const Array< int > &dof_boundary_elements, const Vector &loop_normal, Array< int > &dof_orientations) const
Compute edge orientations relative to a boundary loop direction.
const FiniteElement * GetTypicalTraceElement() const
Return a "typical" trace element.
void GetBoundaryLoopEdgeDofs(const Array< int > &boundary_element_indices, Array< int > &boundary_edge_dofs, Array< int > *dof_edges=nullptr, Array< int > *dof_boundary_elements=nullptr) const
Extract the edge degrees of freedom of a boundary "loop".
static void MarkerToList(const Array< int > &marker, Array< int > &list)
Convert a Boolean marker array to a list containing all marked indices.
Array< NURBSExtension * > VNURBSext
int GetElementOrder(int i) const
Returns the order of the i'th finite element.
void SetVarOrderLocalDofs()
Sets all2local. See documentation of all2local for details.
Mesh * mesh
The mesh that FE space lives on (not owned).
const FiniteElement * GetFaceElement(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th face in the ...
void ConvertToConformingVDofs(const Array< int > &dofs, Array< int > &cdofs)
For a partially conforming FE space, convert a marker array (nonzero entries are true) on the partial...
void CalcEdgeFaceVarOrders(Array< VarOrderBits > &edge_orders, Array< VarOrderBits > &face_orders, Array< VarOrderBits > &edge_elem_orders, Array< VarOrderBits > &face_elem_orders, Array< bool > &skip_edges, Array< bool > &skip_faces) const
virtual bool OrderPropagation(const std::set< int > &edges, const std::set< int > &faces, Array< VarOrderBits > &edge_orders, Array< VarOrderBits > &face_orders) const
Returns true if order propagation is done, for variable-order spaces.
std::shared_ptr< const PRefinementTransferOperator > GetPrefUpdateOperator()
void SetElementOrder(int i, int p)
Sets the order of the i'th finite element.
const SparseMatrix * GetHpConformingRestriction() const
The returned SparseMatrix is owned by the FiniteElementSpace.
const SparseMatrix * GetConformingProlongation() const
const FiniteElementCollection * FEColl() const
Mesh * GetMesh() const
Returns the mesh.
int GetElementOrderImpl(int i) const
Return element order: internal version of GetElementOrder without checks.
int GetNVariants(int entity, int index) const
Return number of possible DOF variants for edge/face (var. order spaces).
virtual ~FiniteElementSpace()
Array< int > dof_bdr_ldof_array
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
const Table * GetElementToFaceOrientationTable() const
DofTransformation * GetBdrElementDofs(int bel, Array< int > &dofs) const
Returns indices of degrees of freedom for boundary element 'bel'. The returned indices are offsets in...
void GetBoundaryTrueDofs(Array< int > &boundary_dofs, int component=-1)
Get a list of all boundary true dofs, boundary_dofs. For spaces with 'vdim' > 1, the 'component' para...
int GetVDim() const
Returns the vector dimension of the finite element space.
const FaceQuadratureInterpolator * GetFaceQuadratureInterpolator(const IntegrationRule &ir, FaceType type) const
Return a FaceQuadratureInterpolator that interpolates E-vectors to quadrature point values and/or der...
bool IsDGSpace() const
Return whether or not the space is discontinuous (L2)
void GetFaceInteriorDofs(int i, Array< int > &dofs) const
Returns the indices of the degrees of freedom for the interior of the specified face.
virtual void PRefineAndUpdate(const Array< pRefinement > &refs, bool want_transfer=true)
int GetNConformingDofs() const
void SetProlongation(const SparseMatrix &p)
Array< int > edge_min_nghb_order
Minimum order among neighboring elements.
const FiniteElement * GetTypicalFE() const
Return GetFE(0) if the local mesh is not empty; otherwise return a typical FE based on the Geometry t...
static int DecodeDof(int dof)
Helper to return the DOF associated with a sign encoded DOF.
void GetElementInteriorDofs(int i, Array< int > &dofs) const
Returns the indices of the degrees of freedom for the interior of the specified element.
virtual int NumGhostEdges() const
Returns the number of ghost edges (nonzero in ParFiniteElementSpace).
bool PRefinementSupported()
void Constructor(Mesh *mesh, NURBSExtension *ext, const FiniteElementCollection *fec, int vdim=1, int ordering=Ordering::byNODES)
Help function for constructors + Load().
DofTransformation * GetBdrElementVDofs(int i, Array< int > &vdofs) const
Returns indices of degrees of freedom for i'th boundary element. The returned indices are offsets int...
void ConvertFromConformingVDofs(const Array< int > &cdofs, Array< int > &dofs)
For a partially conforming FE space, convert a marker array (nonzero entries are true) on the conform...
const FiniteElement * GetTypicalFaceElement() const
Return a "typical" face element.
virtual void GetEssentialVDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_vdofs, int component=-1) const
Mark degrees of freedom associated with boundary elements with the specified boundary attributes (mar...
virtual int NumGhostFaces() const
Returns the number of ghost faces (nonzero in ParFiniteElementSpace).
int DofToVDof(int dof, int vd, int ndofs=-1) const
Compute a single vdof corresponding to the index dof and the vector index vd.
virtual const FaceRestriction * GetFaceRestriction(ElementDofOrdering f_ordering, FaceType, L2FaceValues mul=L2FaceValues::DoubleValued) const
Return an Operator that converts L-vectors to E-vectors on each face.
int GetCurlDim() const
Return the dimension of the curl of a GridFunction defined on this space.
virtual void GhostFaceOrderToEdges(const Array< VarOrderBits > &face_orders, Array< VarOrderBits > &edge_orders) const
Helper function for ParFiniteElementSpace.
int FindEdgeDof(int edge, int ndof) const
void GetPatchVDofs(int i, Array< int > &vdofs) const
Returns indices of degrees of freedom in vdofs for NURBS patch i.
void BuildElementToDofTable() const
std::unique_ptr< SparseMatrix > cR_hp
A version of the conforming restriction matrix for variable-order spaces.
int FindDofs(const Table &var_dof_table, int row, int ndof) const
Search row of a DOF table for a DOF set of size 'ndof', return first DOF.
void VariableOrderMinimumRule(SparseMatrix &deps) const
Abstract class for all finite elements.
int GetRangeDim() const
Returns the vector dimension for vector-valued finite elements, which is also the dimension of the in...
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
int GetDim() const
Returns the reference space dimension for the finite element.
virtual void GetTransferMatrix(const FiniteElement &fe, ElementTransformation &Trans, DenseMatrix &I) const
Return interpolation matrix, I, which maps dofs from a coarse element, fe, to the fine dofs on this f...
int GetRangeType() const
Returns the FiniteElement::RangeType of the element, one of {SCALAR, VECTOR}.
virtual void GetLocalRestriction(ElementTransformation &Trans, DenseMatrix &R) const
Return a local restriction matrix R (Dof x Dof) mapping fine dofs to coarse dofs.
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
Geometry::Type GetGeomType() const
Returns the Geometry::Type of the reference element.
virtual void GetLocalInterpolation(ElementTransformation &Trans, DenseMatrix &I) const
Return the local interpolation matrix I (Dof x Dof) where the fine element is the image of the base g...
virtual void Project(Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const
Given a coefficient and a transformation, compute its projection (approximation) in the local finite ...
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const =0
Evaluate the values of all shape functions of a scalar finite element in reference space at the given...
int GetDof() const
Returns the number of degrees of freedom in the finite element.
static const int NumVerts[NumGeom]
Arbitrary order H1-conforming (continuous) finite elements.
Class for an integration rule - an Array of IntegrationPoint.
int GetNPoints() const
Returns the number of the points in the integration rule.
This class manages the storage and computation of the interpolations from master (coarse) face to sla...
Operator that converts L2 FiniteElementSpace L-vectors to E-vectors.
Operator that extracts Face degrees of freedom for L2 spaces.
Operator that extracts face degrees of freedom for L2 interface spaces.
Arbitrary order "L2-conforming" discontinuous finite elements.
Class used by MFEM to store pointers to host and/or device memory.
List of mesh geometries stored as Array<Geometry::Type>.
void GetFaceEdges(int i, Array< int > &edges, Array< int > &o) const
void GetGeometries(int dim, Array< Geometry::Type > &el_geoms) const
Return all element geometries of the given dimension present in the mesh.
Operation GetLastOperation() const
Return type of last modification of the mesh.
int GetNEdges() const
Return the number of edges.
void GetBdrElementFace(int i, int *f, int *o) const
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
NURBSExtension * NURBSext
Optional NURBS mesh extension.
virtual void GetExteriorFaceMarker(Array< int > &face_marker) const
Populate a marker array identifying exterior faces.
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
void GetBdrElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of boundary element i.
Geometry::Type GetFaceGeometry(int i) const
Return the Geometry::Type associated with face i.
Geometry::Type GetElementGeometry(int i) const
Geometry::Type GetBdrElementGeometry(int i) const
void GetElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of element i.
const FiniteElementSpace * GetNodalFESpace() const
Geometry::Type GetTypicalElementGeometry() const
If the local mesh is not empty, return GetElementGeometry(0); otherwise, return a typical Geometry pr...
int GetBdrElementFaceIndex(int be_idx) const
Return the local face (codimension-1) index for the given boundary element index.
int GetNFaces() const
Return the number of faces in a 3D mesh.
const CoarseFineTransformations & GetRefinementTransforms() const
int GetNE() const
Returns number of elements.
const Element * GetFace(int i) const
Return pointer to the i'th face element object.
int Dimension() const
Dimension of the reference space used within the elements.
const Element * GetBdrElement(int i) const
Return pointer to the i'th boundary element object.
FaceInformation GetFaceInformation(int f) const
int GetNumFacesWithGhost() const
Return the number of faces (3D), edges (2D) or vertices (1D) including ghost faces.
void GetBdrElementEdges(int i, Array< int > &edges, Array< int > &cor) const
Return the indices and the orientations of all edges of bdr element i.
void GetElementFaces(int i, Array< int > &faces, Array< int > &ori) const
Return the indices and the orientations of all faces of element i.
int SpaceDimension() const
Dimension of the physical space containing the mesh.
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
void GetEdgeVertices(int i, Array< int > &vert) const
Returns the indices of the vertices of edge i.
void GetBdrElementAdjacentElement(int bdr_el, int &el, int &info) const
For the given boundary element, bdr_el, return its adjacent element and its info, i....
void GetFaceVertices(int i, Array< int > &vert) const
Returns the indices of the vertices of face i.
int GetNBE() const
Returns number of boundary elements.
NCMesh * ncmesh
Optional nonconforming mesh extension.
void GetElementEdges(int i, Array< int > &edges, Array< int > &cor) const
Return the indices and the orientations of all edges of element i.
int GetNumGeometries(int dim) const
Return the number of geometries of the given dimension present in the mesh.
Geometry::Type GetTypicalFaceGeometry() const
If the local mesh is not empty, return GetFaceGeometry(0); otherwise return a typical face geometry p...
Geometry::Type GetElementBaseGeometry(int i) const
const real_t * GetVertex(int i) const
Return pointer to vertex i's coordinates.
Operator that extracts face degrees of freedom for L2 nonconforming spaces.
const NCList & GetNCList(int entity)
Return vertex/edge/face list (entity = 0/1/2, respectively).
const CoarseFineTransformations & GetDerefinementTransforms() const
const NCList & GetFaceList()
Return the current list of conforming and nonconforming faces.
Geometry::Type GetFaceGeometry(int index) const
Return face geometry type. index is the Mesh face number.
virtual void GetBoundaryClosure(const Array< int > &bdr_attr_is_ess, Array< int > &bdr_vertices, Array< int > &bdr_edges, Array< int > &bdr_faces)
Get a list of vertices (2D/3D), edges (3D) and faces (3D) that coincide with boundary elements with t...
const NCList & GetEdgeList()
Return the current list of conforming and nonconforming edges.
int GetNFaces() const
Return the number of (2D) faces in the NCMesh.
int GetNEdges() const
Return the number of edges in the NCMesh.
Arbitrary order H(curl)-conforming Nedelec finite elements.
NURBSExtension generally contains multiple NURBSPatch objects spanning an entire Mesh....
const Vector & GetWeights() const
Access function to the vector of weights weights.
const Array< int > & GetSlave() const
int GetNKV() const
Return the number of KnotVectors.
void LoadBE(int i, const FiniteElement *BE) const
Load boundary element i into BE.
Table * GetElementDofTable()
const Array< int > & GetMaster() const
void LoadFE(int i, const FiniteElement *FE) const
Load element i into FE.
void GetPatchDofs(const int patch, Array< int > &dofs)
Return the degrees of freedom in dofs on patch patch, in Cartesian order.
Table * GetBdrElementDofTable()
int GetNDof() const
Return the number of active DOFs.
int GetOrder() const
If all KnotVector orders are identical, return that number. Otherwise, return NURBSFECollection::Vari...
NURBSExtension * GetCurlExtension(int component)
const Array< int > & GetOrders() const
Read-only access to the orders of all KnotVectors.
NURBSExtension * GetDivExtension(int component)
void ConnectBoundaries()
Set DOF maps for periodic BC.
Arbitrary order non-uniform rational B-splines (NURBS) finite elements.
int GetOrder() const
Get the order of the NURBS collection: either a positive number, when using fixed order,...
virtual void SetOrder(int Order) const
Set the order and the name, based on the given Order: either a positive number for fixed order,...
virtual void SetDim(const int dim)
Arbitrary order H(curl) NURBS finite elements.
Arbitrary order H(div) NURBS finite elements.
Pointer to an Operator of a specified type.
OpType * As() const
Return the Operator pointer statically cast to a specified OpType. Similar to the method Get().
bool OwnsOperator() const
Return true if the OperatorHandle owns the held Operator.
void SetOperatorOwner(bool own=true)
Set the ownership flag for the held Operator.
void SetType(Operator::Type tid)
Invoke Clear() and set a new type id.
Operator * Ptr() const
Access the underlying Operator pointer.
void Clear()
Clear the OperatorHandle, deleting the held Operator (if owned), while leaving the type id unchanged.
void Reset(OpType *A, bool own_A=true)
Reset the OperatorHandle to the given OpType pointer, A.
OpType * Is() const
Return the Operator pointer dynamically cast to a specified OpType.
Operator::Type Type() const
Get the currently set operator type id.
int width
Dimension of the input / number of columns in the matrix.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
int height
Dimension of the output / number of rows in the matrix.
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Type
Enumeration defining IDs for some classes derived from Operator.
@ ANY_TYPE
ID for the base class Operator, i.e. any type.
@ MFEM_SPARSEMAT
ID for class SparseMatrix.
The ordering method used when the number of unknowns per mesh node (vector dimension) is bigger than ...
Abstract parallel finite element space.
Parallel version of NURBSExtension.
General product operator: x -> (A*B)(x) = A(B(x)).
A class that performs interpolation from an E-vector to quadrature point values and/or derivatives (Q...
static bool SupportsFESpace(const FiniteElementSpace &fespace)
Returns true if the given finite element space is supported by QuadratureInterpolator.
const IntegrationRule * IntRule
Not owned.
const QuadratureSpace * qspace
Not owned.
Class representing the storage layout of a QuadratureFunction.
int GetRow(const int row, Array< int > &cols, Vector &srow) const override
Extract all column indices and values from a given row.
void Add(const int i, const int j, const real_t val)
void Swap(SparseMatrix &other)
void BooleanMultTranspose(const Array< int > &x, Array< int > &y) const
y = At * x, treating all entries as booleans (zero=false, nonzero=true).
void BooleanMult(const Array< int > &x, Array< int > &y) const
y = A * x, treating all entries as booleans (zero=false, nonzero=true).
int * GetRowColumns(const int row)
Return a pointer to the column indices in a row.
int RowSize(const int i) const
Returns the number of elements in row i.
real_t * GetRowEntries(const int row)
Return a pointer to the entries in a row.
void SetRow(const int row, const Array< int > &cols, const Vector &srow)
void Finalize(int skip_zeros=1) override
Finalize the matrix initialization, switching the storage format from LIL to CSR.
void Set(const int i, const int j, const real_t val)
Table stores the connectivity of elements of TYPE I to elements of TYPE II. For example,...
void AddConnections(int r, const int *c, int nc)
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
void AddConnection(int r, int c)
int Size() const
Returns the number of TYPE I elements.
int Size_of_connections() const
Returns the number of connections in the table.
void AddColumnsInRow(int r, int ncol)
void MakeFromList(int nrows, const Array< Connection > &list)
Create the table from a list of connections {(from, to)}, where 'from' is a TYPE I index and 'to' is ...
void AddAColumnInRow(int r)
The transpose of a given operator. Switches the roles of the methods Mult() and MultTranspose().
General triple product operator x -> A*B*C*x, with ownership of the factors.
void Print(std::ostream &out=mfem::out, int width=8) const
Prints vector to stream out.
void SetSubVector(const Array< int > &dofs, const real_t value)
Set the entries listed in dofs to the given value.
void AddElementVector(const Array< int > &dofs, const Vector &elemvect)
Add elements of the elemvect Vector to the entries listed in dofs. Negative dof values cause the -dof...
void Load(std::istream **in, int np, int *dim)
Reads a vector from multiple files.
real_t Max() const
Returns the maximal element of the vector.
void SetSize(int s)
Resize the vector to size s.
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
real_t Min() const
Returns the minimal element of the vector.
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Extract entries listed in dofs to the output Vector elemvect.
Vector & Add(const real_t a, const Vector &Va)
(*this) += a * Va
const int * ess_tdof_list
int index(int i, int j, int nx, int ny)
void RemoveBasisAndRestriction(const mfem::FiniteElementSpace *fes)
Remove from ceed_basis_map and ceed_restr_map the entries associated with the given fes.
Linear1DFiniteElement SegmentFE
void mfem_error(const char *msg)
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
void DofMapHelper(int entity, const Table &var_ent_dofs, const Table &loc_var_ent_dofs, const Array< char > &var_ent_orders, const Array< char > &loc_var_ent_orders, Array< int > &all2local, int &ndof_all, int &ndof_loc)
void Transpose(const Table &A, Table &At, int ncols_A_)
Transpose a Table.
MFEM_HOST_DEVICE int FlipIndexSign(int i)
Signed indices i -> -1 - i are used as a convention to encode orientation.
MFEM_HOST_DEVICE int UnsignIndex(int i)
void Swap(T &a, T &b)
Swap objects of type T. The operation is performed using the most specialized swap function from the ...
void filter_dos(std::string &line)
Check for, and remove, a trailing '\r' from and std::string.
bool UsesTensorBasis(const FiniteElementSpace &fes)
Return true if the mesh contains only one topology and the elements are tensor elements.
BiLinear2DFiniteElement QuadrilateralFE
ComplexDenseMatrix * MultAtB(const ComplexDenseMatrix &A, const ComplexDenseMatrix &B)
Multiply the complex conjugate transpose of a matrix A with a matrix B. A^H*B.
void AddMult(const DenseMatrix &b, const DenseMatrix &c, DenseMatrix &a)
Matrix matrix multiplication. A += B * C.
ElementDofOrdering GetEVectorOrdering(const FiniteElementSpace &fes)
Return LEXICOGRAPHIC if mesh contains only one topology and the elements are tensor elements,...
void MarkDofs(const Array< int > &dofs, Array< int > &mark_array)
ElementDofOrdering
Constants describing the possible orderings of the DOFs in one element.
@ NATIVE
Native ordering as defined by the FiniteElement.
std::function< real_t(const Vector &)> f(real_t mass_coeff)
MFEM_EXPORT Linear2DFiniteElement TriangleFE
void skip_comment_lines(std::istream &is, const char comment_char)
Check if the stream starts with comment_char. If so skip it.
real_t p(const Vector &x, real_t t)
bool operator<(const Data &d1, const Data &d2)
Helper struct for defining a connectivity table, see Table::MakeFromList.
Defines the position of a fine element within a coarse element.
int parent
Coarse Element index in the coarse mesh.
Geometry::Type Geom() const
Lists all edges/faces in the nonconforming mesh.
Array< Slave > slaves
All MeshIds corresponding to slave faces.
Array< Master > masters
All MeshIds corresponding to master faces.
Nonconforming edge/face within a bigger edge/face.
unsigned matrix
index into NCList::point_matrices[geom]