12 #include "../config/config.hpp"
28 FmsBasisTypeToMfemBasis(FmsBasisType
b)
33 case FMS_NODAL_GAUSS_OPEN:
36 case FMS_NODAL_GAUSS_CLOSED:
42 case FMS_NODAL_UNIFORM_OPEN:
45 case FMS_NODAL_UNIFORM_CLOSED:
48 case FMS_NODAL_CHEBYSHEV_OPEN:
49 case FMS_NODAL_CHEBYSHEV_CLOSED:
51 "FMS_NODAL_CHEBYSHEV_OPEN, FMS_NODAL_CHEBYSHEV_CLOSED need conversion to MFEM types."
65 FmsFieldGetOrderAndLayout(FmsField
f, FmsInt *f_order, FmsLayoutType *f_layout)
68 FmsFieldDescriptor fd;
70 FmsScalarType data_type;
71 const void *data =
nullptr;
74 FmsFieldGet(f, &fd, NULL, &layout, &data_type,
77 FmsFieldDescriptorType f_fd_type;
78 FmsFieldDescriptorGetType(fd, &f_fd_type);
79 if (f_fd_type != FMS_FIXED_ORDER)
85 FmsFieldType field_type;
86 FmsBasisType basis_type;
87 FmsFieldDescriptorGetFixedOrder(fd, &field_type,
105 template <
typename DataType>
115 FmsInt
dim, n_vert, n_elem, space_dim;
120 FmsMeshGetNumComponents(fms_mesh, &num_comp);
121 FmsComponent main_comp = NULL;
122 FmsField coords = NULL;
123 for (FmsInt comp_id = 0; comp_id < num_comp; comp_id++)
126 FmsMeshGetComponent(fms_mesh, comp_id, &comp);
127 FmsComponentGetCoordinates(comp, &coords);
128 if (coords) { main_comp = comp;
break; }
130 if (!main_comp) {
return 1; }
131 FmsComponentGetDimension(main_comp, &dim);
132 FmsComponentGetNumEntities(main_comp, &n_elem);
133 FmsInt n_ents[FMS_NUM_ENTITY_TYPES];
135 FmsComponentGetNumParts(main_comp, &n_main_parts);
136 for (FmsInt et = FMS_VERTEX; et < FMS_NUM_ENTITY_TYPES; et++)
139 for (FmsInt part_id = 0; part_id < n_main_parts; part_id++)
142 FmsComponentGetPart(main_comp, part_id, (FmsEntityType)et, NULL, NULL,
143 NULL, NULL, &num_ents);
144 n_ents[et] += num_ents;
147 n_vert = n_ents[FMS_VERTEX];
151 FmsFieldDescriptor f_fd;
152 FmsLayoutType f_layout;
153 FmsScalarType f_data_type;
155 FmsFieldGet(f, &f_fd, &space_dim, &f_layout, &f_data_type,
160 FmsFieldDescriptorGetNumDofs(f_fd, &f_num_dofs);
163 auto src_data =
reinterpret_cast<const DataType *
>(f_data);
165 FmsFieldDescriptorType f_fd_type;
166 FmsFieldDescriptorGetType(f_fd, &f_fd_type);
167 if (f_fd_type != FMS_FIXED_ORDER)
171 FmsFieldType f_field_type;
172 FmsBasisType f_basis_type;
174 FmsFieldDescriptorGetFixedOrder(f_fd, &f_field_type,
175 &f_basis_type, &f_order);
177 if (f_field_type != FMS_CONTINUOUS && f_field_type != FMS_DISCONTINUOUS &&
178 f_field_type != FMS_HDIV)
183 int btype = FmsBasisTypeToMfemBasis(f_basis_type);
197 switch (f_field_type)
199 case FMS_DISCONTINUOUS:
209 case FMS_DISCONTINUOUS_WEIGHTED:
210 MFEM_ABORT(
"Field types FMS_HCURL and FMS_DISCONTINUOUS_WEIGHTED"
211 " are not supported yet.");
220 const FmsInt nstride = (f_layout == FMS_BY_VDIM) ? space_dim : 1;
221 const FmsInt vstride = (f_layout == FMS_BY_VDIM) ? 1 : f_num_dofs;
224 if ((FmsInt)(func.
Size()) != f_num_dofs*space_dim)
230 const int vdim = fes->
GetVDim();
238 int ent_dofs[FMS_NUM_ENTITY_TYPES];
239 ent_dofs[FMS_VERTEX] = vert_dofs;
240 ent_dofs[FMS_EDGE] = edge_dofs;
241 ent_dofs[FMS_TRIANGLE] = tri_dofs;
242 ent_dofs[FMS_QUADRILATERAL] = quad_dofs;
243 ent_dofs[FMS_TETRAHEDRON] = tet_dofs;
244 ent_dofs[FMS_HEXAHEDRON] = hex_dofs;
245 FmsInt fms_dof_offset = 0;
246 int mfem_ent_cnt[4] = {0,0,0,0};
247 int mfem_last_vert_cnt = 0;
250 if (dim >= 2 && edge_dofs > 0)
253 for (
int i = 0; i < mesh->
GetNEdges(); i++)
256 int id = mfem_edge.
GetId(ev[0], ev[1]);
257 if (
id != i) {
return 13; }
261 ((n_ents[FMS_TRIANGLE] > 0 && tri_dofs > 0) ||
262 (n_ents[FMS_QUADRILATERAL] > 0 && quad_dofs > 0)))
265 for (
int i = 0; i < mesh->
GetNFaces(); i++)
270 int id = mfem_face.
GetId(fv[0], fv[1], fv[2], fv[3]);
271 if (
id != i) {
return 14; }
276 for (FmsInt part_id = 0; part_id < n_main_parts; part_id++)
279 for (FmsInt et = FMS_VERTEX; et < FMS_NUM_ENTITY_TYPES; et++)
282 FmsIntType ent_id_type;
284 const FmsOrientation *ents_ori;
286 FmsComponentGetPart(main_comp, part_id, (FmsEntityType)et, &domain,
287 &ent_id_type, &ents, &ents_ori, &num_ents);
288 if (num_ents == 0) {
continue; }
289 if (ent_dofs[et] == 0)
291 if (et == FMS_VERTEX) { mfem_last_vert_cnt = mfem_ent_cnt[et]; }
292 mfem_ent_cnt[FmsEntityDim[et]] += num_ents;
297 (ent_id_type != FMS_INT32 && ent_id_type != FMS_UINT32))
301 if (ents_ori != NULL)
306 if (et == FMS_VERTEX)
308 const int mfem_dof_offset = mfem_ent_cnt[0]*vert_dofs;
309 for (FmsInt i = 0; i < num_ents*vert_dofs; i++)
311 for (
int j = 0; j < vdim; j++)
313 const int idx = i*nstride+j*vstride;
314 func(mfem_dof_offset*nstride+idx) =
315 static_cast<double>(src_data[fms_dof_offset*nstride+idx]);
318 fms_dof_offset += num_ents*vert_dofs;
319 mfem_last_vert_cnt = mfem_ent_cnt[et];
320 mfem_ent_cnt[0] += num_ents;
324 if (FmsEntityDim[et] == dim)
326 for (FmsInt e = 0; e < num_ents; e++)
329 for (
int i = 0; i < ent_dofs[et]; i++, fms_dof_offset++)
331 for (
int j = 0; j < vdim; j++)
334 static_cast<double>(src_data[fms_dof_offset*nstride+j*vstride]);
338 mfem_ent_cnt[
dim] += num_ents;
341 const FmsInt nv = FmsEntityNumVerts[et];
343 const int *ei = (
const int *)ents;
346 FmsDomainGetEntitiesVerts(domain, (FmsEntityType)et, NULL, FMS_INT32,
347 0, ents_verts.GetData(), num_ents);
351 for (FmsInt i = 0; i < num_ents; i++)
353 FmsDomainGetEntitiesVerts(domain, (FmsEntityType)et, NULL,
354 FMS_INT32, ei[i], &ents_verts[i*nv], 1);
357 for (
int i = 0; i < ents_verts.Size(); i++)
359 ents_verts[i] += mfem_last_vert_cnt;
362 switch ((FmsEntityType)et)
366 for (FmsInt part_ent_id = 0; part_ent_id < num_ents; part_ent_id++)
368 const int *ev = &ents_verts[2*part_ent_id];
369 int mfem_edge_id = mfem_edge.
FindId(ev[0], ev[1]);
370 if (mfem_edge_id < 0)
375 int ori = (ev[0] == m_ev[0]) ? 0 : 1;
378 for (
int i = 0; i < edge_dofs; i++)
380 for (
int j = 0; j < vdim; j++)
383 static_cast<double>(src_data[(fms_dof_offset+perm[i])*nstride+j*vstride]);
386 fms_dof_offset += edge_dofs;
392 for (FmsInt part_ent_id = 0; part_ent_id < num_ents; part_ent_id++)
394 const int *tv = &ents_verts[3*part_ent_id];
395 int mfem_face_id = mfem_face.
FindId(tv[0], tv[1], tv[2], INT_MAX);
396 if (mfem_face_id < 0)
402 while (tv[ori] != m_ev[0]) { ori++; }
403 ori = (tv[(ori+1)%3] == m_ev[1]) ? 2*ori : 2*ori+1;
406 for (
int i = 0; i < tri_dofs; i++)
408 for (
int j = 0; j < vdim; j++)
411 static_cast<double>(src_data[(fms_dof_offset+perm[i])*nstride+j*vstride]);
414 fms_dof_offset += tri_dofs;
418 case FMS_QUADRILATERAL:
420 for (FmsInt part_ent_id = 0; part_ent_id < num_ents; part_ent_id++)
422 const int *qv = &ents_verts[4*part_ent_id];
423 int mfem_face_id = mfem_face.
FindId(qv[0], qv[1], qv[2], qv[3]);
424 if (mfem_face_id < 0) {
return 19; }
427 while (qv[ori] != m_ev[0]) { ori++; }
428 ori = (qv[(ori+1)%4] == m_ev[1]) ? 2*ori : 2*ori+1;
431 for (
int i = 0; i < quad_dofs; i++)
433 for (
int j = 0; j < vdim; j++)
436 static_cast<double>(src_data[(fms_dof_offset+perm[i])*nstride+j*vstride]);
439 fms_dof_offset += quad_dofs;
445 mfem_ent_cnt[FmsEntityDim[et]] += num_ents;
455 FmsInt
dim, n_vert, n_elem, n_bdr_elem, space_dim;
460 FmsMeshGetNumComponents(fms_mesh, &num_comp);
461 FmsComponent main_comp = NULL;
462 FmsField coords = NULL;
463 for (FmsInt comp_id = 0; comp_id < num_comp; comp_id++)
466 FmsMeshGetComponent(fms_mesh, comp_id, &comp);
467 FmsComponentGetCoordinates(comp, &coords);
468 if (coords) { main_comp = comp;
break; }
470 if (!main_comp) {
return 1; }
471 FmsComponentGetDimension(main_comp, &dim);
472 FmsComponentGetNumEntities(main_comp, &n_elem);
473 FmsInt n_ents[FMS_NUM_ENTITY_TYPES];
475 FmsComponentGetNumParts(main_comp, &n_main_parts);
477 #define RENUMBER_ENTITIES
478 #ifdef RENUMBER_ENTITIES
487 int *verts_per_part =
new int[n_main_parts];
491 for (FmsInt et = FMS_VERTEX; et < FMS_NUM_ENTITY_TYPES; et++)
494 for (FmsInt part_id = 0; part_id < n_main_parts; part_id++)
497 FmsComponentGetPart(main_comp, part_id, (FmsEntityType)et, NULL, NULL,
498 NULL, NULL, &num_ents);
499 n_ents[et] += num_ents;
500 #ifdef RENUMBER_ENTITIES
501 if (et == FMS_VERTEX)
503 verts_per_part[part_id] = num_ents;
508 n_vert = n_ents[FMS_VERTEX];
510 #ifdef RENUMBER_ENTITIES
511 int *verts_start =
new int[n_main_parts];
513 for (FmsInt i = 1; i < n_main_parts; ++i)
515 verts_start[i] = verts_start[i-1] + verts_per_part[i-1];
521 FmsComponent bdr_comp = NULL;
522 FmsInt num_rel_comps;
523 const FmsInt *rel_comp_ids;
524 FmsComponentGetRelations(main_comp, &rel_comp_ids, &num_rel_comps);
525 for (FmsInt i = 0; i < num_rel_comps; i++)
528 FmsMeshGetComponent(fms_mesh, rel_comp_ids[i], &comp);
530 FmsComponentGetDimension(comp, &comp_dim);
531 if (comp_dim == dim-1) { bdr_comp = comp;
break; }
535 FmsComponentGetNumEntities(bdr_comp, &n_bdr_elem);
542 FmsFieldGet(coords, NULL, &space_dim, NULL, NULL, NULL);
544 Mesh *mesh =
nullptr;
545 mesh =
new Mesh(dim, n_vert, n_elem, n_bdr_elem, space_dim);
549 FmsMeshGetNumTags(fms_mesh, &num_tags);
550 FmsTag elem_tag = NULL, bdr_tag = NULL;
551 for (FmsInt tag_id = 0; tag_id < num_tags; tag_id++)
554 FmsMeshGetTag(fms_mesh, tag_id, &tag);
556 FmsTagGetComponent(tag, &comp);
557 if (!elem_tag && comp == main_comp)
560 const char *tn = NULL;
561 FmsTagGetName(tag, &tn);
562 mfem::out <<
"Found element tag " << tn << std::endl;
566 else if (!bdr_tag && comp == bdr_comp)
569 const char *tn = NULL;
570 FmsTagGetName(tag, &tn);
571 mfem::out <<
"Found boundary tag " << tn << std::endl;
576 FmsIntType attr_type;
577 const void *v_attr, *v_bdr_attr;
583 FmsTagGet(elem_tag, &attr_type, &v_attr, &num_attr);
584 if (attr_type == FMS_UINT8)
589 else if (attr_type == FMS_INT32 || attr_type == FMS_UINT32)
591 attr.
MakeRef((
int*)v_attr, num_attr);
602 FmsTagGet(bdr_tag, &attr_type, &v_bdr_attr, &num_attr);
603 if (attr_type == FMS_UINT8)
608 else if (attr_type == FMS_INT32 || attr_type == FMS_UINT32)
610 bdr_attr.
MakeRef((
int*)v_bdr_attr, num_attr);
620 for (FmsInt part_id = 0; part_id < n_main_parts; part_id++)
622 for (
int et = FMS_VERTEX; et < FMS_NUM_ENTITY_TYPES; et++)
624 if (FmsEntityDim[et] != dim) {
continue; }
627 FmsIntType elem_id_type;
628 const void *elem_ids;
629 const FmsOrientation *elem_ori;
631 FmsComponentGetPart(main_comp, part_id, (FmsEntityType)et, &domain,
632 &elem_id_type, &elem_ids, &elem_ori, &num_elems);
634 if (num_elems == 0) {
continue; }
636 if (elem_ids != NULL &&
637 (elem_id_type != FMS_INT32 && elem_id_type != FMS_UINT32))
639 err = 3;
goto func_exit;
641 if (elem_ori != NULL)
643 err = 4;
goto func_exit;
646 const FmsInt nv = FmsEntityNumVerts[et];
648 if (elem_ids == NULL)
650 FmsDomainGetEntitiesVerts(domain, (FmsEntityType)et, NULL, FMS_INT32,
651 0, ents_verts.
GetData(), num_elems);
655 const int *ei = (
const int *)elem_ids;
656 for (FmsInt i = 0; i < num_elems; i++)
658 FmsDomainGetEntitiesVerts(domain, (FmsEntityType)et, NULL, FMS_INT32,
659 ei[i], &ents_verts[i*nv], 1);
662 const int elem_offset = mesh->
GetNE();
663 switch ((FmsEntityType)et)
670 #ifdef RENUMBER_ENTITIES
674 for (FmsInt i = 0; i < num_elems*3; i++)
676 ents_verts[i] += verts_start[part_id];
680 for (FmsInt i = 0; i < num_elems; i++)
683 &ents_verts[3*i], elem_tag ? attr[elem_offset+i] : 1);
686 case FMS_QUADRILATERAL:
687 #ifdef RENUMBER_ENTITIES
688 for (FmsInt i = 0; i < num_elems*4; i++)
690 ents_verts[i] += verts_start[part_id];
693 for (FmsInt i = 0; i < num_elems; i++)
695 mesh->
AddQuad(&ents_verts[4*i], elem_tag ? attr[elem_offset+i] : 1);
698 case FMS_TETRAHEDRON:
699 #ifdef RENUMBER_ENTITIES
700 for (FmsInt i = 0; i < num_elems*4; i++)
702 ents_verts[i] += verts_start[part_id];
705 for (FmsInt i = 0; i < num_elems; i++)
707 mesh->
AddTet(&ents_verts[4*i], elem_tag ? attr[elem_offset+i] : 1);
715 #ifdef RENUMBER_ENTITIES
716 for (FmsInt i = 0; i < num_elems*8; i++)
718 ents_verts[i] += verts_start[part_id];
722 for (FmsInt i = 0; i < num_elems; i++)
724 const int *hex_verts = &ents_verts[8*i];
726 const int reorder[8] = {0, 1, 2, 3, 5, 4, 6, 7};
727 const int new_verts[8] = {hex_verts[reorder[0]],
728 hex_verts[reorder[1]],
729 hex_verts[reorder[2]],
730 hex_verts[reorder[3]],
731 hex_verts[reorder[4]],
732 hex_verts[reorder[5]],
733 hex_verts[reorder[6]],
734 hex_verts[reorder[7]]
736 hex_verts = new_verts;
738 mesh->
AddHex(hex_verts, elem_tag ? attr[elem_offset+i] : 1);
748 if (bdr_comp && n_bdr_elem > 0)
751 FmsComponentGetNumParts(bdr_comp, &n_bdr_parts);
753 for (FmsInt part_id = 0; part_id < n_bdr_parts; part_id++)
755 for (
int et = FMS_VERTEX; et < FMS_NUM_ENTITY_TYPES; et++)
757 if (FmsEntityDim[et] != dim-1) {
continue; }
760 FmsIntType elem_id_type;
761 const void *elem_ids;
762 const FmsOrientation *elem_ori;
764 FmsComponentGetPart(bdr_comp, part_id, (FmsEntityType)et, &domain,
765 &elem_id_type, &elem_ids, &elem_ori, &num_elems);
766 if (num_elems == 0) {
continue; }
768 if (elem_ids != NULL &&
769 (elem_id_type != FMS_INT32 && elem_id_type != FMS_UINT32))
771 err = 6;
goto func_exit;
773 if (elem_ori != NULL)
775 err = 7;
goto func_exit;
778 const FmsInt nv = FmsEntityNumVerts[et];
780 if (elem_ids == NULL)
782 FmsDomainGetEntitiesVerts(domain, (FmsEntityType)et, NULL, FMS_INT32,
783 0, ents_verts.
GetData(), num_elems);
787 const int *ei = (
const int *)elem_ids;
788 for (FmsInt i = 0; i < num_elems; i++)
790 FmsDomainGetEntitiesVerts(domain, (FmsEntityType)et, NULL,
791 FMS_INT32, ei[i], &ents_verts[i*nv], 1);
794 const int elem_offset = mesh->
GetNBE();
795 switch ((FmsEntityType)et)
798 for (FmsInt i = 0; i < num_elems; i++)
801 &ents_verts[2*i], bdr_tag ? bdr_attr[elem_offset+i] : 1);
805 for (FmsInt i = 0; i < num_elems; i++)
808 &ents_verts[3*i], bdr_tag ? bdr_attr[elem_offset+i] : 1);
811 case FMS_QUADRILATERAL:
812 for (FmsInt i = 0; i < num_elems; i++)
815 &ents_verts[4*i], bdr_tag ? bdr_attr[elem_offset+i] : 1);
825 #ifdef RENUMBER_ENTITIES
826 delete [] verts_per_part;
827 delete [] verts_start;
833 const double origin[3] = {0.,0.,0.};
834 for (FmsInt vi = 0; vi < n_vert; vi++)
842 FmsFieldDescriptor coords_fd = NULL;
843 FmsLayoutType coords_layout;
844 FmsFieldGet(coords, &coords_fd, NULL, &coords_layout, NULL, NULL);
847 mfem::err <<
"Error reading the FMS mesh coords' FieldDescriptor." << std::endl;
851 FmsInt coords_order = 0;
852 FmsBasisType coords_btype = FMS_NODAL_GAUSS_CLOSED;
853 FmsFieldType coords_ftype = FMS_CONTINUOUS;
854 FmsFieldDescriptorGetFixedOrder(coords_fd, &coords_ftype, &coords_btype,
858 if (coords_btype != FMS_NODAL_GAUSS_CLOSED)
860 mfem::err <<
"Error reading FMS mesh coords." << std::endl;
866 const bool discont = (coords_ftype == FMS_DISCONTINUOUS);
868 (coords_layout == FMS_BY_VDIM) ?
876 FmsFieldToGridFunction<double>(fms_mesh, coords, mesh, nodes,
false);
900 btype = FMS_NODAL_GAUSS_OPEN;
905 btype = FMS_NODAL_GAUSS_CLOSED;
910 btype = FMS_POSITIVE;
915 btype = FMS_NODAL_UNIFORM_OPEN;
920 btype = FMS_NODAL_UNIFORM_CLOSED;
951 const std::string &fd_name,
952 const std::string &field_name,
957 if (!dc) {
return 1; }
958 if (!comp) {
return 2; }
959 if (!mesh) {
return 3; }
960 if (!gf) {
return 4; }
961 if (!outfield) {
return 5; }
968 #ifdef DEBUG_MFEM_FMS
969 mfem::out <<
"Adding FMS field for " << field_name <<
"..." << endl;
977 FmsFieldType ftype = FMS_CONTINUOUS;
978 FmsBasisType btype = FMS_NODAL_GAUSS_CLOSED;
983 ftype = FMS_CONTINUOUS;
984 order =
static_cast<FmsInt
>(fespace->
GetOrder(0));
991 mfem::err <<
"Error converting MFEM basis type to FMS for"
992 " FMS_CONTINUOUS." << std::endl;
1000 ftype = FMS_DISCONTINUOUS;
1001 order =
static_cast<FmsInt
>(fespace->
GetOrder(0));
1008 mfem::err <<
"Error converting MFEM basis type to FMS for"
1009 " FMS_DISCONTINUOUS." << std::endl;
1017 mfem::out <<
"Warning, unsupported ContType (TANGENTIAL) for "
1018 << field_name <<
". Using FMS_CONTINUOUS." << std::endl;
1030 if (sscanf(fecoll->
Name(),
"RT_%dD_P%d", &idim, &iorder) == 2)
1032 order = (FmsInt)iorder;
1036 order =
static_cast<FmsInt
>(fespace->
GetOrder(0));
1046 mfem::out <<
"Warning, unsupported ContType for field " << field_name
1047 <<
". Using FMS_CONTINUOUS." << std::endl;
1048 ftype = FMS_CONTINUOUS;
1053 FmsFieldDescriptor fd = NULL;
1055 FmsDataCollectionAddFieldDescriptor(dc, fd_name.c_str(), &fd);
1056 FmsDataCollectionAddField(dc, field_name.c_str(), &
f);
1060 FmsFieldDescriptorSetComponent(fd, comp);
1061 FmsFieldDescriptorSetFixedOrder(fd, ftype, btype, order);
1064 FmsFieldDescriptorGetNumDofs(fd, &ndofs);
1066 const char *name = NULL;
1067 FmsFieldGetName(f, &name);
1069 FMS_BY_VDIM : FMS_BY_NODES;
1071 #ifdef DEBUG_MFEM_FMS
1074 case FMS_CONTINUOUS:
1075 mfem::out <<
"\tFMS_CONTINUOUS" << std::endl;
1077 case FMS_DISCONTINUOUS:
1078 mfem::out <<
"\tFMS_DISCONTINUOUS" << std::endl;
1084 mfem::out <<
"\tField is order " << order <<
" with vdim " << vdim <<
1085 " and nDoFs " << ndofs << std::endl;
1086 mfem::out <<
"\tgf->size() " << gf->
Size() <<
" ndofs * vdim " << ndofs * vdim
1088 mfem::out <<
"\tlayout " << layout <<
" (0 = BY_NODES, 1 = BY_VDIM)" <<
1092 if (FmsFieldSet(f, fd, vdim, layout, FMS_DOUBLE, c))
1094 mfem::err <<
"Error setting field " << field_name <<
" in FMS." << std::endl;
1103 if (!mdc) {
return false; }
1104 if (!fdc) {
return false; }
1107 double *time = NULL, *timestep = NULL;
1108 FmsMetaData top_level = NULL;
1109 FmsMetaData *cycle_time_timestep = NULL;
1111 mdata_err = FmsDataCollectionAttachMetaData(fdc, &top_level);
1112 if (!top_level || mdata_err)
1114 mfem::err <<
"Failed to attach metadata to the FmsDataCollection" << std::endl;
1118 mdata_err = FmsMetaDataSetMetaData(top_level,
"MetaData", 3,
1119 &cycle_time_timestep);
1120 if (!cycle_time_timestep || mdata_err)
1122 mfem::err <<
"Failed to acquire FmsMetaData array" << std::endl;
1126 if (!cycle_time_timestep[0])
1128 mfem::err <<
"The MetaData pointer for cycle is NULL" << std::endl;
1131 mdata_err = FmsMetaDataSetIntegers(cycle_time_timestep[0],
"cycle",
1132 FMS_INT32, 1, (
void**)&cycle);
1133 if (!cycle || mdata_err)
1135 mfem::err <<
"The data pointer for cycle is NULL" << std::endl;
1140 if (!cycle_time_timestep[1])
1142 mfem::err <<
"The FmsMetaData pointer for time is NULL" << std::endl;
1145 mdata_err = FmsMetaDataSetScalars(cycle_time_timestep[1],
"time", FMS_DOUBLE,
1147 if (!time || mdata_err)
1149 mfem::err <<
"The data pointer for time is NULL." << std::endl;
1154 if (!cycle_time_timestep[2])
1156 mfem::err <<
"The FmsMetData pointer for timestep is NULL" << std::endl;
1159 mdata_err = FmsMetaDataSetScalars(cycle_time_timestep[2],
"timestep",
1160 FMS_DOUBLE, 1, (
void**)×tep);
1161 if (!timestep || mdata_err)
1163 mfem::err <<
"The data pointer for timestep is NULL" << std::endl;
1174 std::vector<int> &values)
1176 if (!mdata) {
return false; }
1178 bool retval =
false;
1179 FmsMetaDataType type;
1180 FmsIntType int_type;
1182 FmsMetaData *children =
nullptr;
1183 const void *data =
nullptr;
1184 const char *mdata_name =
nullptr;
1185 if (FmsMetaDataGetType(mdata, &type) == 0)
1190 if (FmsMetaDataGetIntegers(mdata, &mdata_name, &int_type, &size, &data) == 0)
1192 if (strcasecmp(key.c_str(), mdata_name) == 0)
1200 for (i = 0; i < size; i++)
1202 values.push_back(static_cast<int>(reinterpret_cast<const int8_t*>(data)[i]));
1206 for (i = 0; i < size; i++)
1208 values.push_back(static_cast<int>(reinterpret_cast<const int16_t*>(data)[i]));
1212 for (i = 0; i < size; i++)
1214 values.push_back(static_cast<int>(reinterpret_cast<const int32_t*>(data)[i]));
1218 for (i = 0; i < size; i++)
1220 values.push_back(static_cast<int>(reinterpret_cast<const int64_t*>(data)[i]));
1224 for (i = 0; i < size; i++)
1226 values.push_back(static_cast<int>(reinterpret_cast<const uint8_t*>(data)[i]));
1230 for (i = 0; i < size; i++)
1232 values.push_back(static_cast<int>(reinterpret_cast<const uint16_t*>(data)[i]));
1236 for (i = 0; i < size; i++)
1238 values.push_back(static_cast<int>(reinterpret_cast<const uint32_t*>(data)[i]));
1242 for (i = 0; i < size; i++)
1244 values.push_back(static_cast<int>(reinterpret_cast<const uint64_t*>(data)[i]));
1255 if (FmsMetaDataGetMetaData(mdata, &mdata_name, &size, &children) == 0)
1258 for (i = 0; i < size && !retval; i++)
1275 std::vector<double> &values)
1277 if (!mdata) {
return false; }
1279 bool retval =
false;
1280 FmsMetaDataType type;
1281 FmsScalarType scal_type;
1283 FmsMetaData *children =
nullptr;
1284 const void *data =
nullptr;
1285 const char *mdata_name =
nullptr;
1286 if (FmsMetaDataGetType(mdata, &type) == 0)
1291 if (FmsMetaDataGetScalars(mdata, &mdata_name, &scal_type, &size, &data) == 0)
1293 if (strcasecmp(key.c_str(), mdata_name) == 0)
1301 for (i = 0; i < size; i++)
1303 values.push_back(static_cast<double>(reinterpret_cast<const float*>(data)[i]));
1307 for (i = 0; i < size; i++)
1309 values.push_back(reinterpret_cast<const double*>(data)[i]);
1320 if (FmsMetaDataGetMetaData(mdata, &mdata_name, &size, &children) == 0)
1323 for (i = 0; i < size && !retval; i++)
1342 if (!mdata) {
return false; }
1344 bool retval =
false;
1345 FmsMetaDataType type;
1347 FmsMetaData *children =
nullptr;
1348 const char *mdata_name =
nullptr;
1349 const char *str_value =
nullptr;
1351 if (FmsMetaDataGetType(mdata, &type) == 0)
1358 if (strcasecmp(key.c_str(), mdata_name) == 0)
1366 if (FmsMetaDataGetMetaData(mdata, &mdata_name, &size, &children) == 0)
1369 for (i = 0; i < size && !retval; i++)
1392 FmsDataCollectionGetMesh(dc, &fms_mesh);
1396 Mesh *mesh =
nullptr;
1400 std::string collection_name(
"collection");
1401 const char *cn =
nullptr;
1402 FmsDataCollectionGetName(dc, &cn);
1405 collection_name = cn;
1413 FmsField *fields =
nullptr;
1414 FmsInt num_fields = 0;
1415 if (FmsDataCollectionGetFields(dc, &fields, &num_fields) == 0)
1417 for (FmsInt i = 0; i < num_fields; ++i)
1419 const char *name =
nullptr;
1420 FmsFieldGetName(fields[i], &name);
1425 FmsFieldDescriptor f_fd;
1426 FmsLayoutType f_layout;
1427 FmsScalarType f_data_type;
1429 FmsFieldGet(fields[i], &f_fd, NULL, &f_layout, &f_data_type,
1434 switch (f_data_type)
1437 err = FmsFieldToGridFunction<float>(fms_mesh, fields[i], mesh, *gf,
true);
1440 err = FmsFieldToGridFunction<double>(fms_mesh, fields[i], mesh, *gf,
true);
1442 case FMS_COMPLEX_FLOAT:
1443 case FMS_COMPLEX_DOUBLE:
1456 mfem::out <<
"There was an error converting " << name <<
" code: " << err <<
1461 const char *fname = NULL;
1462 FmsFieldGetName(fields[i], &fname);
1467 FmsMetaData mdata = NULL;
1468 FmsDataCollectionGetMetaData(dc, &mdata);
1471 std::vector<int> ivalues;
1472 std::vector<double> dvalues;
1476 if (!ivalues.empty())
1483 if (!dvalues.empty())
1490 if (!dvalues.empty())
1501 mfem::out <<
"FmsDataCollectionToDataCollection: mesh failed to convert. err="
1513 const auto &fields = (*mfem_dc)->GetFieldMap();
1514 for (
const auto &field : fields)
1534 if (!mmesh) {
return 1; }
1535 if (!fmesh) {
return 2; }
1536 if (!volume) {
return 3; }
1540 const int num_verticies = mmesh->
GetNV();
1541 #ifdef DEBUG_MFEM_FMS
1542 const int num_edges = mmesh->
GetNEdges();
1544 const int num_faces = mmesh->
GetNFaces();
1545 const int num_elements = mmesh->
GetNE();
1547 #ifdef DEBUG_MFEM_FMS
1548 mfem::out <<
"nverts: " << num_verticies << std::endl;
1549 mfem::out <<
"nedges: " << num_edges << std::endl;
1550 mfem::out <<
"nfaces: " << num_faces << std::endl;
1551 mfem::out <<
"nele: " << num_elements << std::endl;
1554 FmsMeshConstruct(fmesh);
1555 FmsMeshSetPartitionId(*fmesh, 0, 1);
1557 FmsDomain *domains = NULL;
1558 FmsMeshAddDomains(*fmesh,
"Domain", 1, &domains);
1559 FmsDomainSetNumVertices(domains[0], num_verticies);
1561 const int edge_reorder[2] = {1, 0};
1562 const int quad_reorder[4] = {0,1,2,3};
1563 const int tet_reorder[4] = {3,2,1,0};
1564 const int hex_reorder[6] = {0,5,1,3,4,2};
1565 const int *reorder[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
1566 reorder[FMS_EDGE] = edge_reorder;
1567 reorder[FMS_QUADRILATERAL] = quad_reorder;
1568 reorder[FMS_TETRAHEDRON] = tet_reorder;
1569 reorder[FMS_HEXAHEDRON] = hex_reorder;
1574 mfem::err <<
"Error, mesh has no edges." << std::endl;
1578 if (!faces && num_faces > 0)
1581 "Error, mesh contains faces but the \"GetFaceEdgeTable\" returned NULL." <<
1587 std::vector<int> edge_verts(edges->
Size() * 2);
1588 for (
int i = 0; i < edges->
Size(); i++)
1592 for (
int j = 0; j < 2; j++)
1594 edge_verts[i*2 + j] = nids[j];
1599 FmsDomainSetNumEntities(domains[0], FMS_EDGE, FMS_INT32, edge_verts.size() / 2);
1600 FmsDomainAddEntities(domains[0], FMS_EDGE, reorder, FMS_INT32,
1601 edge_verts.data(), edge_verts.size() / 2);
1602 #ifdef DEBUG_MFEM_FMS
1604 for (
int i = 0; i < edge_verts.size(); i++)
1606 if (i % 2 == 0) { mfem::out << std::endl <<
"\t" << i/2 <<
": "; }
1607 mfem::out << edge_verts[i] <<
" ";
1609 mfem::out << std::endl;
1617 int rowsize = faces->
RowSize(0);
1618 std::vector<int> face_edges(faces->
Size() * rowsize);
1619 for (
int i = 0; i < faces->
Size(); i++)
1623 for (
int j = 0; j < rowsize; j++)
1625 face_edges[i*rowsize + j] = eids[j];
1628 FmsEntityType ent_type = (rowsize == 3) ? FMS_TRIANGLE : FMS_QUADRILATERAL;
1629 FmsDomainSetNumEntities(domains[0], ent_type, FMS_INT32,
1630 face_edges.size() / rowsize);
1631 FmsDomainAddEntities(domains[0], ent_type, NULL, FMS_INT32, face_edges.data(),
1632 face_edges.size() / rowsize);
1633 #ifdef DEBUG_MFEM_FMS
1634 mfem::out <<
"FACES: ";
1635 for (
int i = 0; i < face_edges.size(); i++)
1637 if (i % rowsize == 0) { mfem::out << std::endl <<
"\t" << i/rowsize <<
": "; }
1638 mfem::out <<
"(" << edge_verts[face_edges[i]*2] <<
", " <<
1639 edge_verts[face_edges[i]*2+1] <<
") ";
1641 mfem::out << std::endl;
1646 std::vector<int> tags;
1647 std::vector<int> tris;
1648 std::vector<int> quads;
1649 std::vector<int> tets;
1650 std::vector<int> hexes;
1651 for (
int i = 0; i < num_elements; i++)
1671 for (
int e = 0; e < 3; e++)
1673 tris.push_back(eids[e]);
1681 for (
int e = 0; e < 4; e++)
1683 quads.push_back(eids[e]);
1691 for (
int f = 0; f < 4; f++)
1693 tets.push_back(fids[f]);
1701 for (
int f = 0; f < 6; f++)
1703 hexes.push_back(fids[f]);
1708 mfem::err <<
"Error, element not implemented." << std::endl;
1715 FmsDomainSetNumEntities(domains[0], FMS_TRIANGLE, FMS_INT32, tris.size() / 3);
1716 FmsDomainAddEntities(domains[0], FMS_TRIANGLE, reorder, FMS_INT32, tris.data(),
1718 #ifdef DEBUG_MFEM_FMS
1719 mfem::out <<
"TRIS: ";
1720 for (
int i = 0; i < tris.size(); i++)
1722 if (i % 3 == 0) { mfem::out << std::endl <<
"\t" << i/3 <<
": "; }
1723 mfem::out << tris[i] <<
" ";
1725 mfem::out << std::endl;
1733 FmsDomainSetNumEntities(domains[0], FMS_QUADRILATERAL, FMS_INT32,
1735 FmsDomainAddEntities(domains[0], FMS_QUADRILATERAL, reorder, FMS_INT32,
1736 quads.data(), quads.size() / 4);
1737 #ifdef DEBUG_MFEM_FMS
1738 mfem::out <<
"QUADS: ";
1739 for (
int i = 0; i < quads.size(); i++)
1741 if (i % 4 == 0) { mfem::out << std::endl <<
"\t" << i/4 <<
": "; }
1742 mfem::out << quads[i] <<
" ";
1744 mfem::out << std::endl;
1750 FmsDomainSetNumEntities(domains[0], FMS_TETRAHEDRON, FMS_INT32,
1752 FmsDomainAddEntities(domains[0], FMS_TETRAHEDRON, reorder, FMS_INT32,
1753 tets.data(), tets.size() / 4);
1754 #ifdef DEBUG_MFEM_FMS
1755 mfem::out <<
"TETS: ";
1756 for (
int i = 0; i < tets.size(); i++)
1758 if (i % 4 == 0) { mfem::out << std::endl <<
"\t" << i/4 <<
": "; }
1759 mfem::out << tets[i] <<
" ";
1761 mfem::out << std::endl;
1767 FmsDomainSetNumEntities(domains[0], FMS_HEXAHEDRON, FMS_INT32,
1769 FmsDomainAddEntities(domains[0], FMS_HEXAHEDRON, reorder, FMS_INT32,
1770 hexes.data(), hexes.size() / 6);
1771 #ifdef DEBUG_MFEM_FMS
1772 mfem::out <<
"HEXES: ";
1773 for (
int i = 0; i < hexes.size(); i++)
1775 if (i % 6 == 0) { mfem::out << std::endl <<
"\t" << i/6 <<
": "; }
1776 mfem::out << hexes[i] <<
" ";
1778 mfem::out << std::endl;
1782 err = FmsMeshFinalize(*fmesh);
1785 mfem::err <<
"FmsMeshFinalize returned error code " << err << std::endl;
1789 err = FmsMeshValidate(*fmesh);
1792 mfem::err <<
"FmsMeshValidate returned error code " << err << std::endl;
1796 FmsComponent v = NULL;
1797 FmsMeshAddComponent(*fmesh,
"volume", &v);
1798 FmsComponentAddDomain(v, domains[0]);
1801 FmsMeshAddTag(*fmesh,
"element_attribute", &tag);
1802 FmsTagSetComponent(tag, v);
1803 FmsTagSet(tag, FMS_INT32, FMS_INT32, tags.data(), tags.size());
1806 std::vector<int> bdr_eles[FMS_NUM_ENTITY_TYPES];
1807 std::vector<int> bdr_attributes;
1808 const int NBE = mmesh->
GetNBE();
1809 for (
int i = 0; i < NBE; i++)
1834 MFEM_WARNING(
"Unsupported boundary element " << betype <<
" at boundary index "
1842 FmsComponent boundary = NULL;
1843 FmsMeshAddComponent(*fmesh,
"boundary", &boundary);
1845 FmsComponentAddPart(boundary, domains[0], &part_id);
1846 for (
int i = FMS_NUM_ENTITY_TYPES - 1; i > 0; i--)
1848 if (bdr_eles[i].size())
1850 FmsComponentAddPartEntities(boundary, part_id, (FmsEntityType)i,
1851 FMS_INT32, FMS_INT32, FMS_INT32, NULL,
1853 NULL, bdr_eles[i].size());
1857 FmsComponentAddRelation(v, 1);
1858 FmsTag boundary_tag = NULL;
1859 FmsMeshAddTag(*fmesh,
"boundary_attribute", &boundary_tag);
1860 FmsTagSetComponent(boundary_tag, boundary);
1861 FmsTagSet(boundary_tag, FMS_INT32, FMS_INT32, bdr_attributes.data(),
1862 bdr_attributes.size());
1870 FmsDataCollection *dc)
1876 FmsMesh fmesh = NULL;
1877 FmsComponent volume = NULL;
1879 if (!fmesh || !volume || err)
1881 mfem::err <<
"Error converting mesh topology from MFEM to FMS" << std::endl;
1884 FmsMeshDestroy(&fmesh);
1892 mfem::err <<
"There was an error creating the FMS data collection." <<
1894 FmsMeshDestroy(&fmesh);
1897 FmsDataCollectionDestroy(dc);
1906 FmsField fcoords = NULL;
1909 err |= FmsComponentSetCoordinates(volume, fcoords);
1916 FmsFieldDescriptor fdcoords = NULL;
1917 FmsField fcoords = NULL;
1918 err = FmsDataCollectionAddFieldDescriptor(*dc,
"CoordsDescriptor", &fdcoords);
1919 err |= FmsFieldDescriptorSetComponent(fdcoords, volume);
1920 err |= FmsFieldDescriptorSetFixedOrder(fdcoords, FMS_CONTINUOUS,
1921 FMS_NODAL_GAUSS_CLOSED, 1);
1922 err |= FmsDataCollectionAddField(*dc,
"Coords", &fcoords);
1923 err |= FmsFieldSet(fcoords, fdcoords, mmesh->
SpaceDimension(), FMS_BY_NODES,
1924 FMS_DOUBLE, mverts);
1925 err |= FmsComponentSetCoordinates(volume, fcoords);
1930 mfem::err <<
"There was an error setting the mesh coordinates." << std::endl;
1931 FmsMeshDestroy(&fmesh);
1932 FmsDataCollectionDestroy(dc);
1937 for (
const auto &pair : fields)
1939 std::string fd_name(pair.first +
"Descriptor");
1942 pair.second, &field);
1945 mfem::err <<
"WARNING: There was an error adding the " << pair.first <<
1946 " field. Continuing..." << std::endl;
Normal component of vector field.
Field is discontinuous across element interfaces.
bool FmsMetaDataGetInteger(FmsMetaData mdata, const std::string &key, std::vector< int > &values)
Ordering::Type GetOrdering() const
Return the ordering method.
int Size() const
Return the logical size of the array.
int GetBdrAttribute(int i) const
Return the attribute of boundary element i.
Class for grid function - Vector with associated FE space.
int DofToVDof(int dof, int vd, int ndofs=-1) const
Table * GetEdgeVertexTable() const
Returns the edge-to-vertex Table (3D)
int AddQuad(int v1, int v2, int v3, int v4, int attr=1)
void SetCycle(int c)
Set time cycle (for time-dependent simulations)
void GetEdgeVertices(int i, Array< int > &vert) const
Returns the indices of the vertices of edge i.
double GetTime() const
Get physical time (for time-dependent simulations)
virtual int GetContType() const =0
Tangential components of vector field.
int GetNBE() const
Returns number of boundary elements.
bool FmsMetaDataGetScalar(FmsMetaData mdata, const std::string &key, std::vector< double > &values)
bool MfemMetaDataToFmsMetaData(DataCollection *mdc, FmsDataCollection fdc)
Element::Type GetElementType(int i) const
Returns the type of element i.
const std::string & GetCollectionName() const
Get the name of the collection.
Element::Type GetBdrElementType(int i) const
Returns the type of boundary element i.
T * GetData()
Returns the data.
int AddTriangle(int v1, int v2, int v3, int attr=1)
void GetFaceVertices(int i, Array< int > &vert) const
Returns the indices of the vertices of face i.
int Size() const
Returns the size of the vector.
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
int GetBdrElementEdgeIndex(int i) const
int GetNE() const
Returns number of elements.
virtual void Save()
Save the collection and a VisIt root file.
void GetVertices(Vector &vert_coord) const
static const char * Name(int b_type)
Check and convert a BasisType constant to a string identifier.
double * GetData() const
Return a pointer to the beginning of the Vector data.
int FmsMeshToMesh(FmsMesh fms_mesh, Mesh **mfem_mesh)
Nodes: x_i = i/(n-1), i=0,...,n-1.
bool FmsMetaDataGetString(FmsMetaData mdata, const std::string &key, std::string &value)
double GetTimeStep() const
Get the simulation time step (for time-dependent simulations)
Nodes: x_i = (i+1/2)/n, i=0,...,n-1.
void GetFaceInteriorDofs(int i, Array< int > &dofs) const
virtual int DofForGeometry(Geometry::Type GeomType) const =0
int AddBdrTriangle(int v1, int v2, int v3, int attr=1)
int AddVertex(double x, double y=0.0, double z=0.0)
virtual void RegisterField(const std::string &field_name, GridFunction *gf)
Add a grid function to the collection.
double f(const Vector &xvec)
int Append(const T &el)
Append element 'el' to array, resize if necessary.
int AddTet(int v1, int v2, int v3, int v4, int attr=1)
const FieldMapType & GetFieldMap() const
Get a const reference to the internal field map.
int GetCycle() const
Get time cycle (for time-dependent simulations)
Data collection with VisIt I/O routines.
virtual void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1)
Type
Constants for the classes derived from Element.
int AddBdrSegment(int v1, int v2, int attr=1)
int DataCollectionToFmsDataCollection(DataCollection *mfem_dc, FmsDataCollection *dc)
int FmsDataCollectionToDataCollection(FmsDataCollection dc, DataCollection **mfem_dc)
int Size() const
Returns the number of TYPE I elements.
int GetVDim() const
Returns vector dimension.
FiniteElementSpace * FESpace()
void SetTime(double t)
Set physical time (for time-dependent simulations)
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
void SetOwnData(bool o)
Set the ownership of collection data.
void GetElementInteriorDofs(int i, Array< int > &dofs) const
int SpaceDimension() const
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const =0
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i]...
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
OutStream err(std::cerr)
Global stream used by the library for standard error output. Initially it uses the same std::streambu...
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
int AddHex(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int attr=1)
void FinalizeTopology(bool generate_bdr=true)
Finalize the construction of the secondary topology (connectivity) data of a Mesh.
int AddBdrQuad(int v1, int v2, int v3, int v4, int attr=1)
int GetOrder(int i) const
Returns the polynomial degree of the i'th finite element.
int GridFunctionToFmsField(FmsDataCollection dc, FmsComponent comp, const std::string &fd_name, const std::string &field_name, const Mesh *mesh, const GridFunction *gf, FmsField *outfield)
Field is continuous across element interfaces.
bool BasisTypeToFmsBasisType(int bt, FmsBasisType &btype)
Nodes: x_i = (i+1)/(n+1), i=0,...,n-1.
virtual void RegisterField(const std::string &field_name, GridFunction *gf)
Add a grid function to the collection and update the root file.
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
void SetTimeStep(double ts)
Set the simulation time step (for time-dependent simulations)
virtual const char * Name() const
int MeshToFmsMesh(const Mesh *mmesh, FmsMesh *fmesh, FmsComponent *volume)
void GetElementEdges(int i, Array< int > &edges, Array< int > &cor) const
Return the indices and the orientations of all edges of element i.
virtual void Finalize(bool refine=false, bool fix_orientation=false)
Finalize the construction of a general Mesh.
void GetEdgeInteriorDofs(int i, Array< int > &dofs) const
virtual void SetSpace(FiniteElementSpace *f)
Associate a new FiniteElementSpace with the GridFunction.
Mesh * GetMesh()
Get a pointer to the mesh in the collection.
int GetNEdges() const
Return the number of edges.
void MakeRef(T *, int)
Make this Array a reference to a pointer.
int GetNFaces() const
Return the number of faces in a 3D mesh.
const FiniteElementCollection * FEColl() const
void GetNodes(Vector &node_coord) const
int GetId(int p1, int p2)
Get id of item whose parents are p1, p2... Create it if it doesn't exist.
Arbitrary order H1-conforming (continuous) finite elements.
Table * GetFaceEdgeTable() const
Returns the face-to-edge Table (3D)
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Serendipity basis (squares / cubes)
int FindId(int p1, int p2) const
Find id of item whose parents are p1, p2... Return -1 if it doesn't exist.
int GetAttribute(int i) const
Return the attribute of element i.
int FmsFieldToGridFunction(FmsMesh fms_mesh, FmsField f, Mesh *mesh, GridFunction &func, bool setFE)
This function converts an FmsField to an MFEM GridFunction.
void GetElementFaces(int i, Array< int > &faces, Array< int > &ori) const
Return the indices and the orientations of all faces of element i.
Arbitrary order "L2-conforming" discontinuous finite elements.