16#include "../general/tinyxml2.h"
43 MFEM_VERIFY(version == 10 || version == 12 || version == 13,
44 "unknown MFEM mesh version");
52 MFEM_VERIFY(ident ==
"dimension",
"invalid mesh file");
58 MFEM_VERIFY(ident ==
"elements",
"invalid mesh file");
71 MFEM_VERIFY(ident ==
"attribute_sets",
"invalid mesh file");
81 MFEM_VERIFY(ident ==
"boundary",
"invalid mesh file");
94 MFEM_VERIFY(ident ==
"bdr_attribute_sets",
"invalid mesh file");
104 MFEM_VERIFY(ident ==
"vertices",
"invalid mesh file");
108 input >> ws >> ident;
109 if (ident !=
"nodes")
152 input >>
a >> p1 >> p2;
161 input >>
a >> ind[0];
169 int ints[32], attr, n;
180 >> ints[0] >> ints[1];
181 ints[0]--; ints[1]--;
191 for (
int j = 0; j < n; j++)
216 for (
int j = 0; j <
Dim; j++)
241 for (
int j = 0; j <
Dim; j++)
252 for (
int j = 0; j < 4; j++)
257#ifdef MFEM_USE_MEMALLOC
274 for (
int j = 0; j < 3; j++)
285 int i, j, ints[32], attr;
286 const int buflen = 1024;
298 input.getline(buf, buflen);
299 input.getline(buf, buflen);
301 input.getline(buf, buflen);
302 input.getline(buf, buflen);
303 input.getline(buf, buflen);
310 input.getline(buf, buflen);
317 input >> vari >> attr;
318 for (j = 0; j < 4; j++)
323 input.getline(buf, buflen);
324 input.getline(buf, buflen);
333 input.getline(buf, buflen);
334 input.getline(buf, buflen);
336 input.getline(buf, buflen);
337 input.getline(buf, buflen);
338 input.getline(buf, buflen);
345 input.getline(buf, buflen);
351 input >> vari >> attr;
352 for (j = 0; j < 8; j++)
357 input.getline(buf, buflen);
365 for (j = 0; j < 4; j++)
370 input.getline(buf, buflen);
378{ 0, 1, 2, 3, 4, 7, 5, 6, 8, 9 };
383{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
388{ 0, 2, 1, 3, 5, 4, 8, 7, 6, 11, 10, 9, 12, 14, 13, 17, 16, 15};
393 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
394 24, 22, 21, 23, 20, 25, 26
401 int &curved,
int &read_gf,
bool &finalize_topo)
403 int np = points.
Size()/3;
409 bool legacy_elem =
false, lagrange_elem =
false;
413 int j = (i > 0) ? cell_offsets[i-1] : 0;
414 int ct = cell_types[i];
417 if (cell_attributes.
Size() > 0)
419 elements[i]->SetAttribute(cell_attributes[i]);
425 int prism_vertices[6];
426 for (
int k=0; k<6; ++k)
430 elements[i]->SetVertices(prism_vertices);
434 elements[i]->SetVertices(&cell_data[j]);
441 else { legacy_elem =
true; }
443 MFEM_VERIFY(
Dim == -1 ||
Dim == elem_dim,
444 "Elements with different dimensions are not supported");
445 MFEM_VERIFY(order == -1 || order == elem_order,
446 "Elements with different orders are not supported");
447 MFEM_VERIFY(legacy_elem != lagrange_elem,
448 "Mixing of legacy and Lagrange cell types is not supported");
457 real_t min_value, max_value;
458 for (
int d = 3; d > 0; --d)
460 min_value = max_value = points(3*0 + d-1);
461 for (
int i = 1; i < np; i++)
463 min_value = std::min(min_value, points(3*i + d-1));
464 max_value = std::max(max_value, points(3*i + d-1));
465 if (min_value != max_value)
475 if (order == 1 && !lagrange_elem)
479 for (
int i = 0; i < np; i++)
502 int *v =
elements[i]->GetVertices();
503 int nv =
elements[i]->GetNVertices();
504 for (
int j = 0; j < nv; j++)
506 if (pts_dof[v[j]] == -1) { pts_dof[v[j]] = 0; }
515 for (
int i = 0; i < np; i++)
517 if (pts_dof[i] != -1)
525 int *v =
elements[i]->GetVertices();
526 int nv =
elements[i]->GetNVertices();
527 for (
int j = 0; j < nv; j++)
529 v[j] = pts_dof[v[j]];
534 for (
int i = 0; i < np; i++)
568 switch (
elements[i]->GetGeometryType())
586 int offset = (i == 0) ? 0 : cell_offsets[i-1];
587 for (
int j = 0; j < dofs.
Size(); j++)
589 if (pts_dof[cell_data[offset+j]] == -1)
591 pts_dof[cell_data[offset+j]] = dofs[vtk_mfem[j]];
595 if (pts_dof[cell_data[offset+j]] != dofs[vtk_mfem[j]])
597 MFEM_ABORT(
"VTK mesh: inconsistent quadratic mesh!");
613 std::map<Geometry::Type,Array<int>> vtk_inv_maps;
614 std::map<Geometry::Type,const Array<int>*> lex_orderings;
623 if (vtk_inv_map.
Size() == 0)
628 for (
int j=0; j<vtk_map.
Size(); ++j)
630 vtk_inv_map[vtk_map[j]] = j;
633 const Array<int> *&lex_ordering = lex_orderings[geom];
639 MFEM_ASSERT(nodal_fe != NULL,
"Unsupported element type");
643 for (
int lex_idx = 0; lex_idx < dofs.
Size(); lex_idx++)
645 int mfem_idx = (*lex_ordering)[lex_idx];
646 int vtk_idx = vtk_inv_map[lex_idx];
647 int pt_idx = cell_data[n + vtk_idx];
648 if (pts_dof[pt_idx] == -1)
650 pts_dof[pt_idx] = dofs[mfem_idx];
654 if (pts_dof[pt_idx] != dofs[mfem_idx])
656 MFEM_ABORT(
"VTK mesh: inconsistent Lagrange mesh!");
665 for (
int i = 0; i < np; i++)
668 if (pts_dof[i] != -1)
670 dofs[0] = pts_dof[i];
672 for (
int d = 0; d < dofs.
Size(); d++)
674 (*Nodes)(dofs[d]) = points(3*i+d);
685using namespace tinyxml2;
691 if (s1 == NULL || s2 == NULL) {
return false; }
692 return strcmp(s1, s2) == 0;
700struct BufferReaderBase
702 enum HeaderType { UINT32_HEADER, UINT64_HEADER };
703 virtual void ReadBinary(
const char *buf,
void *dest,
int n)
const = 0;
704 virtual void ReadBase64(
const char *txt,
void *dest,
int n)
const = 0;
705 virtual ~BufferReaderBase() { }
718template <
typename T,
typename F>
719struct BufferReader : BufferReaderBase
722 HeaderType header_type;
723 BufferReader(
bool compressed_, HeaderType header_type_)
724 : compressed(compressed_), header_type(header_type_) { }
727 size_t HeaderEntrySize()
const
729 return header_type == UINT64_HEADER ?
sizeof(uint64_t) : sizeof(uint32_t);
735 uint64_t ReadHeaderEntry(
const char *header_buf)
const
738 : bin_io::
read<uint32_t>(header_buf);
747 int NumHeaderBytes(
const char *header_buf)
const
749 if (!compressed) {
return static_cast<int>(HeaderEntrySize()); }
750 return (3 + ReadHeaderEntry(header_buf))*HeaderEntrySize();
758 void ReadBinaryWithHeader(
const char *header_buf,
const char *buf,
759 void *dest_void,
int n)
const
761 std::vector<char> uncompressed_data;
762 T *dest =
static_cast<T*
>(dest_void);
772 int header_entry_size = HeaderEntrySize();
773 int nblocks = ReadHeaderEntry(header_buf);
774 header_buf += header_entry_size;
775 std::vector<int> header(nblocks + 2);
776 for (
int i=0; i<nblocks+2; ++i)
778 header[i] = ReadHeaderEntry(header_buf);
779 header_buf += header_entry_size;
781 uncompressed_data.resize((nblocks-1)*header[0] + header[1]);
782 Bytef *dest_ptr = (Bytef *)uncompressed_data.data();
783 Bytef *dest_start = dest_ptr;
784 const Bytef *source_ptr = (
const Bytef *)buf;
785 for (
int i=0; i<nblocks; ++i)
787 uLongf source_len = header[i+2];
788 uLong dest_len = (i == nblocks-1) ? header[1] : header[0];
789 int res = uncompress(dest_ptr, &dest_len, source_ptr, source_len);
790 MFEM_VERIFY(res == Z_OK,
"Error uncompressing");
791 dest_ptr += dest_len;
792 source_ptr += source_len;
794 MFEM_VERIFY(
int(
sizeof(F)*n) == (dest_ptr - dest_start),
795 "AppendedData: wrong data size");
796 buf = uncompressed_data.data();
798 MFEM_ABORT(
"MFEM must be compiled with zlib enabled to uncompress.")
806 if (header_type == UINT32_HEADER)
808 uint32_t *data_size_32 = (uint32_t *)header_buf;
809 data_size = *data_size_32;
813 uint64_t *data_size_64 = (uint64_t *)header_buf;
814 data_size = *data_size_64;
816 MFEM_VERIFY(
sizeof(F)*n == data_size,
"AppendedData: wrong data size");
819 if (std::is_same<T, F>::value)
822 memcpy(dest, buf,
sizeof(T)*n);
826 for (
int i=0; i<n; ++i)
837 void ReadBinary(
const char *buf,
void *dest,
int n)
const override
839 ReadBinaryWithHeader(buf, buf + NumHeaderBytes(buf), dest, n);
846 void ReadBase64(
const char *txt,
void *dest,
int n)
const override
851 if (*txt !=
' ' && *txt !=
'\n') {
break; }
858 std::vector<char> nblocks_buf;
861 std::vector<char> data, header;
865 nblocks_buf.data())));
869 ReadBinaryWithHeader(header.data(), data.data(), dest, n);
873 std::vector<char> data;
875 ReadBinary(data.data(), dest, n);
886 const char *appended_data, *byte_order, *compressor;
887 enum AppendedDataEncoding { RAW, BASE64 };
888 map<string,BufferReaderBase*> type_map;
889 AppendedDataEncoding encoding;
895 XMLDataReader(
const XMLElement *vtk,
const XMLElement *vtu)
898 BufferReaderBase::HeaderType htype;
901 htype = BufferReaderBase::UINT64_HEADER;
905 htype = BufferReaderBase::UINT32_HEADER;
909 byte_order = vtk->Attribute(
"byte_order");
913 compressor = vtk->Attribute(
"compressor");
914 bool compressed = (compressor != NULL);
917 appended_data = NULL;
918 for (
const XMLElement *xml_elem = vtu->NextSiblingElement();
920 xml_elem = xml_elem->NextSiblingElement())
924 const char *encoding_str = xml_elem->Attribute(
"encoding");
927 appended_data = xml_elem->GetAppendedData();
932 appended_data = xml_elem->GetText();
935 MFEM_VERIFY(appended_data != NULL,
"Invalid AppendedData");
937 bool found_leading_underscore =
false;
938 while (*appended_data)
941 if (*appended_data ==
'_')
943 found_leading_underscore =
true;
948 MFEM_VERIFY(found_leading_underscore,
"Invalid AppendedData");
953 type_map[
"Int8"] =
new BufferReader<int, int8_t>(compressed, htype);
954 type_map[
"Int16"] =
new BufferReader<int, int16_t>(compressed, htype);
955 type_map[
"Int32"] =
new BufferReader<int, int32_t>(compressed, htype);
956 type_map[
"Int64"] =
new BufferReader<int, int64_t>(compressed, htype);
957 type_map[
"UInt8"] =
new BufferReader<int, uint8_t>(compressed, htype);
958 type_map[
"UInt16"] =
new BufferReader<int, uint16_t>(compressed, htype);
959 type_map[
"UInt32"] =
new BufferReader<int, uint32_t>(compressed, htype);
960 type_map[
"UInt64"] =
new BufferReader<int, uint64_t>(compressed, htype);
961 type_map[
"Float32"] =
new BufferReader<double, float>(compressed, htype);
962 type_map[
"Float64"] =
new BufferReader<double, double>(compressed, htype);
968 template <
typename T>
969 void Read(
const XMLElement *xml_elem, T *dest,
int n)
971 static const char *erstr =
"Error reading XML DataArray";
972 MFEM_VERIFY(
StringCompare(xml_elem->Name(),
"DataArray"), erstr);
973 const char *format = xml_elem->Attribute(
"format");
976 const char *txt = xml_elem->GetText();
977 MFEM_VERIFY(txt != NULL, erstr);
978 std::istringstream data_stream(txt);
979 for (
int i=0; i<n; ++i) { data_stream >> dest[i]; }
983 VerifyBinaryOptions();
984 int offset = xml_elem->IntAttribute(
"offset");
985 const char *type = xml_elem->Attribute(
"type");
986 MFEM_VERIFY(type != NULL, erstr);
987 BufferReaderBase *reader = type_map[type];
988 MFEM_VERIFY(reader != NULL, erstr);
989 MFEM_VERIFY(appended_data != NULL,
"No AppendedData found");
992 reader->ReadBinary(appended_data + offset, dest, n);
996 reader->ReadBase64(appended_data + offset, dest, n);
1001 VerifyBinaryOptions();
1002 const char *txt = xml_elem->GetText();
1003 MFEM_VERIFY(txt != NULL, erstr);
1004 const char *type = xml_elem->Attribute(
"type");
1005 if (type == NULL) { MFEM_ABORT(erstr); }
1006 BufferReaderBase *reader = type_map[type];
1007 if (reader == NULL) { MFEM_ABORT(erstr); }
1008 reader->ReadBase64(txt, dest, n);
1012 MFEM_ABORT(
"Invalid XML VTK DataArray format");
1020 void VerifyByteOrder()
const
1025 MFEM_ABORT(
"Converting between different byte orders is unsupported.");
1032 void VerifyCompressor()
const
1034 if (compressor && !
StringCompare(compressor,
"vtkZLibDataCompressor"))
1036 MFEM_ABORT(
"Unsupported compressor. Only zlib is supported.")
1038#ifndef MFEM_USE_ZLIB
1039 MFEM_VERIFY(compressor == NULL,
"MFEM must be compiled with zlib enabled "
1040 "to support reading compressed data.");
1046 void VerifyBinaryOptions()
const
1054 for (
auto &x : type_map) {
delete x.second; }
1061 bool &finalize_topo,
const std::string &xml_prefix)
1063 using namespace vtk_xml;
1065 static const char *erstr =
"XML parsing error";
1068 std::vector<char> buf(xml_prefix.begin(), xml_prefix.end());
1069 std::istreambuf_iterator<char> eos;
1070 buf.insert(buf.end(), std::istreambuf_iterator<char>(input), eos);
1071 buf.push_back(
'\0');
1074 xml.Parse(buf.data(), buf.size());
1075 if (xml.ErrorID() != XML_SUCCESS)
1077 MFEM_ABORT(
"Error parsing XML VTK file.\n" << xml.ErrorStr());
1080 const XMLElement *vtkfile = xml.FirstChildElement();
1081 MFEM_VERIFY(vtkfile, erstr);
1082 MFEM_VERIFY(StringCompare(vtkfile->Name(),
"VTKFile"), erstr);
1083 const XMLElement *vtu = vtkfile->FirstChildElement();
1084 MFEM_VERIFY(vtu, erstr);
1085 MFEM_VERIFY(StringCompare(vtu->Name(),
"UnstructuredGrid"), erstr);
1087 XMLDataReader data_reader(vtkfile, vtu);
1090 const XMLElement *piece = vtu->FirstChildElement();
1091 MFEM_VERIFY(StringCompare(piece->Name(),
"Piece"), erstr);
1092 MFEM_VERIFY(piece->NextSiblingElement() == NULL,
1093 "XML VTK meshes with more than one Piece are not supported");
1094 int npts = piece->IntAttribute(
"NumberOfPoints");
1095 int ncells = piece->IntAttribute(
"NumberOfCells");
1099 const XMLElement *pts_xml;
1100 for (pts_xml = piece->FirstChildElement();
1102 pts_xml = pts_xml->NextSiblingElement())
1104 if (StringCompare(pts_xml->Name(),
"Points"))
1106 const XMLElement *pts_data = pts_xml->FirstChildElement();
1107 MFEM_VERIFY(pts_data->IntAttribute(
"NumberOfComponents") == 3,
1108 "XML VTK Points DataArray must have 3 components");
1109 data_reader.Read(pts_data, points.
GetData(), points.
Size());
1113 if (pts_xml == NULL) { MFEM_ABORT(erstr); }
1116 Array<int> cell_data, cell_offsets(ncells), cell_types(ncells);
1117 const XMLElement *cells_xml;
1118 for (cells_xml = piece->FirstChildElement();
1120 cells_xml = cells_xml->NextSiblingElement())
1122 if (StringCompare(cells_xml->Name(),
"Cells"))
1124 const XMLElement *cell_data_xml = NULL;
1125 for (
const XMLElement *data_xml = cells_xml->FirstChildElement();
1127 data_xml = data_xml->NextSiblingElement())
1129 const char *data_name = data_xml->Attribute(
"Name");
1130 if (StringCompare(data_name,
"offsets"))
1132 data_reader.Read(data_xml, cell_offsets.GetData(), ncells);
1134 else if (StringCompare(data_name,
"types"))
1136 data_reader.Read(data_xml, cell_types.
GetData(), ncells);
1138 else if (StringCompare(data_name,
"connectivity"))
1144 cell_data_xml = data_xml;
1147 MFEM_VERIFY(cell_data_xml != NULL, erstr);
1148 int cell_data_size = cell_offsets.Last();
1149 cell_data.
SetSize(cell_data_size);
1150 data_reader.Read(cell_data_xml, cell_data.
GetData(), cell_data_size);
1154 if (cells_xml == NULL) { MFEM_ABORT(erstr); }
1160 bool found_attributes =
false;
1161 for (
const XMLElement *cell_data_xml = piece->FirstChildElement();
1162 cell_data_xml != NULL;
1163 cell_data_xml = cell_data_xml->NextSiblingElement())
1165 const bool is_cell_data =
1166 StringCompare(cell_data_xml->Name(),
"CellData");
1167 const bool is_material =
1168 StringCompare(cell_data_xml->Attribute(
"Scalars"),
"material");
1169 const bool is_attribute =
1170 StringCompare(cell_data_xml->Attribute(
"Scalars"),
"attribute");
1171 if (is_cell_data && (is_material || (is_attribute && !found_attributes)))
1173 found_attributes =
true;
1174 const XMLElement *data_xml = cell_data_xml->FirstChildElement();
1175 if (data_xml != NULL && StringCompare(data_xml->Name(),
"DataArray"))
1177 cell_attributes.
SetSize(ncells);
1178 data_reader.Read(data_xml, cell_attributes.
GetData(), ncells);
1183 CreateVTKMesh(points, cell_data, cell_offsets, cell_types, cell_attributes,
1184 curved, read_gf, finalize_topo);
1188 bool &finalize_topo)
1197 getline(input, buff);
1198 getline(input, buff);
1200 if (buff !=
"ASCII")
1202 MFEM_ABORT(
"VTK mesh is not in ASCII format!");
1207 getline(input, buff);
1209 if (!input.good()) { MFEM_ABORT(
"VTK mesh is not UNSTRUCTURED_GRID!"); }
1211 while (buff !=
"DATASET UNSTRUCTURED_GRID");
1220 MFEM_ABORT(
"VTK mesh does not have POINTS data!");
1223 while (buff !=
"POINTS");
1228 getline(input, buff);
1229 points.
Load(input, 3*np);
1244 MFEM_ABORT(
"VTK mesh does not have CELLS data!");
1247 while (buff !=
"CELLS");
1251 if (buff ==
"CELLS")
1254 input >> ncells >> n >> ws;
1256 cell_data.
SetSize(n - ncells);
1258 for (
int i=0; i<ncells; ++i)
1262 cell_offsets[i] = offset + nv;
1263 for (
int j=0; j<nv; ++j)
1265 input >> cell_data[offset + j];
1272 input >> ws >> buff;
1275 MFEM_VERIFY(buff ==
"CELL_TYPES",
"CELL_TYPES not provided in VTK mesh.")
1277 cell_types.
Load(ncells, input);
1279 while ((input.good()) && (buff !=
"CELL_DATA"))
1283 getline(input, buff);
1288 bool found_attributes =
false;
1289 while ((input.good()))
1291 getline(input, buff);
1292 if (buff.rfind(
"POINT_DATA") == 0)
1296 else if (buff.rfind(
"SCALARS material") == 0 ||
1297 (buff.rfind(
"SCALARS attribute") == 0 && !found_attributes))
1299 found_attributes =
true;
1300 getline(input, buff);
1301 if (buff.rfind(
"LOOKUP_TABLE default") != 0)
1303 MFEM_ABORT(
"Invalid LOOKUP_TABLE for material array in VTK file.");
1305 cell_attributes.
Load(ncells, input);
1317 CreateVTKMesh(points, cell_data, cell_offsets, cell_types, cell_attributes,
1318 curved, read_gf, finalize_topo);
1391 MFEM_VERIFY(input.get() ==
'=',
1392 "Inline mesh expected '=' after keyword " << name);
1399 else if (name ==
"ny")
1403 else if (name ==
"nz")
1407 else if (name ==
"sx")
1411 else if (name ==
"sy")
1415 else if (name ==
"sz")
1419 else if (name ==
"type")
1423 if (eltype ==
"segment")
1427 else if (eltype ==
"quad")
1431 else if (eltype ==
"tri")
1435 else if (eltype ==
"hex")
1439 else if (eltype ==
"wedge")
1443 else if (eltype ==
"pyramid")
1447 else if (eltype ==
"tet")
1453 MFEM_ABORT(
"unrecognized element type (read '" << eltype
1454 <<
"') in inline mesh format. "
1455 "Allowed: segment, tri, quad, tet, hex, wedge");
1460 MFEM_ABORT(
"unrecognized keyword (" << name
1461 <<
") in inline mesh format. "
1462 "Allowed: nx, ny, nz, type, sx, sy, sz");
1467 if (input.peek() ==
';')
1482 MFEM_VERIFY(nx > 0 && sx > 0.0,
1483 "invalid 1D inline mesh format, all values must be "
1485 <<
" nx = " << nx <<
"\n"
1486 <<
" sx = " << sx <<
"\n");
1491 MFEM_VERIFY(nx > 0 && ny > 0 && sx > 0.0 && sy > 0.0,
1492 "invalid 2D inline mesh format, all values must be "
1494 <<
" nx = " << nx <<
"\n"
1495 <<
" ny = " << ny <<
"\n"
1496 <<
" sx = " << sx <<
"\n"
1497 <<
" sy = " << sy <<
"\n");
1498 Make2D(nx, ny, type, sx, sy, generate_edges,
true);
1503 MFEM_VERIFY(nx > 0 && ny > 0 && nz > 0 &&
1504 sx > 0.0 && sy > 0.0 && sz > 0.0,
1505 "invalid 3D inline mesh format, all values must be "
1507 <<
" nx = " << nx <<
"\n"
1508 <<
" ny = " << ny <<
"\n"
1509 <<
" nz = " << nz <<
"\n"
1510 <<
" sx = " << sx <<
"\n"
1511 <<
" sy = " << sy <<
"\n"
1512 <<
" sz = " << sz <<
"\n");
1513 Make3D(nx, ny, nz, type, sx, sy, sz,
true);
1518 MFEM_ABORT(
"For inline mesh, must specify an element type ="
1519 " [segment, tri, quad, tet, hex, wedge]");
1528 input >> version >> binary >> dsize;
1531 MFEM_ABORT(
"Gmsh file version < 2.2");
1533 if (dsize !=
sizeof(
double))
1535 MFEM_ABORT(
"Gmsh file : dsize != sizeof(double)");
1537 getline(input, buff);
1542 input.read(
reinterpret_cast<char*
>(&one),
sizeof(one));
1545 MFEM_ABORT(
"Gmsh file : wrong binary format");
1552 map<int, int> vertices_map;
1558 map<int,map<int,std::string> > phys_names_by_dim;
1578 bool periodic =
false;
1585 while (input >> buff)
1587 if (buff ==
"$Nodes")
1590 getline(input, buff);
1593 const int gmsh_dim = 3;
1599 input.read(
reinterpret_cast<char*
>(&serial_number),
sizeof(
int));
1600 input.read(
reinterpret_cast<char*
>(coord), gmsh_dim*
sizeof(
double));
1604 input >> serial_number;
1605 for (
int ci = 0; ci < gmsh_dim; ++ci)
1611 vertices_map[serial_number] = ver;
1613 for (
int ci = 0; ci < gmsh_dim; ++ci)
1615 bb_min[ci] = (ver == 0) ? coord[ci] :
1616 std::min(
bb_min[ci], coord[ci]);
1617 bb_max[ci] = (ver == 0) ? coord[ci] :
1618 std::max(
bb_max[ci], coord[ci]);
1636 MFEM_ABORT(
"Gmsh file : vertices indices are not unique");
1639 else if (buff ==
"$Elements")
1641 int num_of_all_elements;
1642 input >> num_of_all_elements;
1644 getline(input, buff);
1647 int type_of_element;
1655 int nodes_of_gmsh_element[] =
1804 -1,-1,-1,-1,-1,-1,-1,
1820 -1,-1,-1,-1,-1,-1,-1,
1865 int lin3[] = {0,2,1};
1866 int lin4[] = {0,2,3,1};
1867 int tri6[] = {0,3,1,5,4,2};
1868 int tri10[] = {0,3,4,1,8,9,5,7,6,2};
1869 int quad9[] = {0,4,1,7,8,5,3,6,2};
1870 int quad16[] = {0,4,5,1,11,12,13,6,
1873 int tet10[] {0,4,1,6,5,2,7,9,8,3};
1874 int tet20[] = {0,4,5,1,9,16,6,8,7,2,
1875 11,17,15,18,19,13,10,14,12,3
1877 int hex27[] {0,8,1,9,20,11,3,13,2,
1878 10,21,12,22,26,23,15,24,14,
1879 4,16,5,17,25,18,7,19,6
1881 int hex64[] {0,8,9,1,10,32,35,14,
1882 11,33,34,15,3,19,18,2,
1883 12,36,37,16,40,56,57,44,
1884 43,59,58,45,22,49,48,20,
1885 13,39,38,17,41,60,61,47,
1886 42,63,62,46,23,50,51,21,
1887 4,24,25,5,26,52,53,28,
1888 27,55,54,29,7,31,30,6
1891 int wdg18[] = {0,6,1,7,9,2,8,15,10,
1892 16,17,11,3,12,4,13,14,5
1894 int wdg40[] = {0,6,7,1,8,24,12,9,13,2,
1895 10,26,27,14,30,38,34,33,35,16,
1896 11,29,28,15,31,39,37,32,36,17,
1897 3,18,19,4,20,25,22,21,23,5
1900 int pyr14[] = {0,5,1,6,13,8,3,
1903 int pyr30[] = {0,5,6,1,7,25,28,11,8,26,
1904 27,12,3,16,15,2,9,21,13,22,
1905 29,23,19,24,17,10,14,20,18,4
1908 vector<Element*> elements_0D, elements_1D, elements_2D, elements_3D;
1909 elements_0D.reserve(num_of_all_elements);
1910 elements_1D.reserve(num_of_all_elements);
1911 elements_2D.reserve(num_of_all_elements);
1912 elements_3D.reserve(num_of_all_elements);
1915 vector<Array<int>*> ho_verts_1D, ho_verts_2D, ho_verts_3D;
1916 ho_verts_1D.reserve(num_of_all_elements);
1917 ho_verts_2D.reserve(num_of_all_elements);
1918 ho_verts_3D.reserve(num_of_all_elements);
1921 vector<int> ho_el_order_1D, ho_el_order_2D, ho_el_order_3D;
1922 ho_el_order_1D.reserve(num_of_all_elements);
1923 ho_el_order_2D.reserve(num_of_all_elements);
1924 ho_el_order_3D.reserve(num_of_all_elements);
1936 ho_lin[2] = lin3; ho_lin[3] = lin4;
1937 ho_tri[2] = tri6; ho_tri[3] = tri10;
1938 ho_sqr[2] = quad9; ho_sqr[3] = quad16;
1939 ho_tet[2] = tet10; ho_tet[3] = tet20;
1940 ho_hex[2] = hex27; ho_hex[3] = hex64;
1941 ho_wdg[2] = wdg18; ho_wdg[3] = wdg40;
1942 ho_pyr[2] = pyr14; ho_pyr[3] = pyr30;
1944 bool has_nonpositive_phys_domain =
false;
1945 bool has_positive_phys_domain =
false;
1949 int n_elem_part = 0;
1950 const int header_size = 3;
1953 int header[header_size];
1954 int n_elem_one_type;
1956 while (n_elem_part < num_of_all_elements)
1958 input.read(
reinterpret_cast<char*
>(header),
1959 header_size*
sizeof(
int));
1960 type_of_element = header[0];
1961 n_elem_one_type = header[1];
1964 n_elem_part += n_elem_one_type;
1966 const int n_elem_nodes = nodes_of_gmsh_element[type_of_element-1];
1967 vector<int> data(1+n_tags+n_elem_nodes);
1968 for (
int el = 0; el < n_elem_one_type; ++el)
1970 input.read(
reinterpret_cast<char*
>(&data[0]),
1971 data.size()*
sizeof(
int));
1973 serial_number = data[dd++];
1976 phys_domain = (n_tags > 0) ? data[dd++] : 1;
1979 elem_domain = (n_tags > 1) ? data[dd++] : 0;
1982 n_partitions = (n_tags > 2) ? data[dd++] : 0;
1985 vector<int> vert_indices(n_elem_nodes);
1986 for (
int vi = 0; vi < n_elem_nodes; ++vi)
1988 map<int, int>::const_iterator it =
1989 vertices_map.find(data[1+n_tags+vi]);
1990 if (it == vertices_map.end())
1992 MFEM_ABORT(
"Gmsh file : vertex index doesn't exist");
1994 vert_indices[vi] = it->second;
2002 if (phys_domain <= 0)
2004 has_nonpositive_phys_domain =
true;
2009 has_positive_phys_domain =
true;
2014 switch (type_of_element)
2027 elements_1D.push_back(
2028 new Segment(&vert_indices[0], phys_domain));
2029 if (type_of_element != 1)
2031 el_order = n_elem_nodes - 1;
2033 hov->
Append(&vert_indices[0], n_elem_nodes);
2034 ho_verts_1D.push_back(hov);
2035 ho_el_order_1D.push_back(el_order);
2041 case 21: el_order--;
2042 case 23: el_order--;
2043 case 25: el_order--;
2044 case 42: el_order--;
2045 case 43: el_order--;
2046 case 44: el_order--;
2047 case 45: el_order--;
2048 case 46: el_order--;
2050 elements_2D.push_back(
2051 new Triangle(&vert_indices[0], phys_domain));
2055 hov->
Append(&vert_indices[0], n_elem_nodes);
2056 ho_verts_2D.push_back(hov);
2057 ho_el_order_2D.push_back(el_order);
2062 case 10: el_order--;
2063 case 36: el_order--;
2064 case 37: el_order--;
2065 case 38: el_order--;
2066 case 47: el_order--;
2067 case 48: el_order--;
2068 case 49: el_order--;
2069 case 50: el_order--;
2070 case 51: el_order--;
2072 elements_2D.push_back(
2077 hov->
Append(&vert_indices[0], n_elem_nodes);
2078 ho_verts_2D.push_back(hov);
2079 ho_el_order_2D.push_back(el_order);
2084 case 11: el_order--;
2085 case 29: el_order--;
2086 case 30: el_order--;
2087 case 31: el_order--;
2088 case 71: el_order--;
2089 case 72: el_order--;
2090 case 73: el_order--;
2091 case 74: el_order--;
2092 case 75: el_order--;
2094#ifdef MFEM_USE_MEMALLOC
2095 elements_3D.push_back(
TetMemory.Alloc());
2096 elements_3D.back()->SetVertices(&vert_indices[0]);
2097 elements_3D.back()->SetAttribute(phys_domain);
2099 elements_3D.push_back(
2105 hov->
Append(&vert_indices[0], n_elem_nodes);
2106 ho_verts_3D.push_back(hov);
2107 ho_el_order_3D.push_back(el_order);
2112 case 12: el_order--;
2113 case 92: el_order--;
2114 case 93: el_order--;
2115 case 94: el_order--;
2116 case 95: el_order--;
2117 case 96: el_order--;
2118 case 97: el_order--;
2119 case 98: el_order--;
2122 elements_3D.push_back(
2123 new Hexahedron(&vert_indices[0], phys_domain));
2127 hov->
Append(&vert_indices[0], n_elem_nodes);
2128 ho_verts_3D.push_back(hov);
2129 ho_el_order_3D.push_back(el_order);
2134 case 13: el_order--;
2135 case 90: el_order--;
2136 case 91: el_order--;
2137 case 106: el_order--;
2138 case 107: el_order--;
2139 case 108: el_order--;
2140 case 109: el_order--;
2141 case 110: el_order--;
2144 elements_3D.push_back(
2145 new Wedge(&vert_indices[0], phys_domain));
2149 hov->
Append(&vert_indices[0], n_elem_nodes);
2150 ho_verts_3D.push_back(hov);
2151 ho_el_order_3D.push_back(el_order);
2156 case 14: el_order--;
2157 case 118: el_order--;
2158 case 119: el_order--;
2159 case 120: el_order--;
2160 case 121: el_order--;
2161 case 122: el_order--;
2162 case 123: el_order--;
2163 case 124: el_order--;
2166 elements_3D.push_back(
2167 new Pyramid(&vert_indices[0], phys_domain));
2171 hov->
Append(&vert_indices[0], n_elem_nodes);
2172 ho_verts_3D.push_back(hov);
2173 ho_el_order_3D.push_back(el_order);
2179 elements_0D.push_back(
2180 new Point(&vert_indices[0], phys_domain));
2184 MFEM_WARNING(
"Unsupported Gmsh element type.");
2193 for (
int el = 0; el < num_of_all_elements; ++el)
2195 input >> serial_number >> type_of_element >> n_tags;
2196 vector<int> data(n_tags);
2197 for (
int i = 0; i < n_tags; ++i) { input >> data[i]; }
2200 phys_domain = (n_tags > 0) ? data[0] : 1;
2203 elem_domain = (n_tags > 1) ? data[1] : 0;
2206 n_partitions = (n_tags > 2) ? data[2] : 0;
2209 const int n_elem_nodes = nodes_of_gmsh_element[type_of_element-1];
2210 vector<int> vert_indices(n_elem_nodes);
2212 for (
int vi = 0; vi < n_elem_nodes; ++vi)
2215 map<int, int>::const_iterator it = vertices_map.find(
index);
2216 if (it == vertices_map.end())
2218 MFEM_ABORT(
"Gmsh file : vertex index doesn't exist");
2220 vert_indices[vi] = it->second;
2228 if (phys_domain <= 0)
2230 has_nonpositive_phys_domain =
true;
2235 has_positive_phys_domain =
true;
2240 switch (type_of_element)
2253 elements_1D.push_back(
2254 new Segment(&vert_indices[0], phys_domain));
2255 if (type_of_element != 1)
2258 hov->
Append(&vert_indices[0], n_elem_nodes);
2259 ho_verts_1D.push_back(hov);
2260 el_order = n_elem_nodes - 1;
2261 ho_el_order_1D.push_back(el_order);
2267 case 21: el_order--;
2268 case 23: el_order--;
2269 case 25: el_order--;
2270 case 42: el_order--;
2271 case 43: el_order--;
2272 case 44: el_order--;
2273 case 45: el_order--;
2274 case 46: el_order--;
2276 elements_2D.push_back(
2277 new Triangle(&vert_indices[0], phys_domain));
2281 hov->
Append(&vert_indices[0], n_elem_nodes);
2282 ho_verts_2D.push_back(hov);
2283 ho_el_order_2D.push_back(el_order);
2288 case 10: el_order--;
2289 case 36: el_order--;
2290 case 37: el_order--;
2291 case 38: el_order--;
2292 case 47: el_order--;
2293 case 48: el_order--;
2294 case 49: el_order--;
2295 case 50: el_order--;
2296 case 51: el_order--;
2298 elements_2D.push_back(
2303 hov->
Append(&vert_indices[0], n_elem_nodes);
2304 ho_verts_2D.push_back(hov);
2305 ho_el_order_2D.push_back(el_order);
2310 case 11: el_order--;
2311 case 29: el_order--;
2312 case 30: el_order--;
2313 case 31: el_order--;
2314 case 71: el_order--;
2315 case 72: el_order--;
2316 case 73: el_order--;
2317 case 74: el_order--;
2318 case 75: el_order--;
2320#ifdef MFEM_USE_MEMALLOC
2321 elements_3D.push_back(
TetMemory.Alloc());
2322 elements_3D.back()->SetVertices(&vert_indices[0]);
2323 elements_3D.back()->SetAttribute(phys_domain);
2325 elements_3D.push_back(
2331 hov->
Append(&vert_indices[0], n_elem_nodes);
2332 ho_verts_3D.push_back(hov);
2333 ho_el_order_3D.push_back(el_order);
2338 case 12: el_order--;
2339 case 92: el_order--;
2340 case 93: el_order--;
2341 case 94: el_order--;
2342 case 95: el_order--;
2343 case 96: el_order--;
2344 case 97: el_order--;
2345 case 98: el_order--;
2348 elements_3D.push_back(
2349 new Hexahedron(&vert_indices[0], phys_domain));
2353 hov->
Append(&vert_indices[0], n_elem_nodes);
2354 ho_verts_3D.push_back(hov);
2355 ho_el_order_3D.push_back(el_order);
2360 case 13: el_order--;
2361 case 90: el_order--;
2362 case 91: el_order--;
2363 case 106: el_order--;
2364 case 107: el_order--;
2365 case 108: el_order--;
2366 case 109: el_order--;
2367 case 110: el_order--;
2370 elements_3D.push_back(
2371 new Wedge(&vert_indices[0], phys_domain));
2375 hov->
Append(&vert_indices[0], n_elem_nodes);
2376 ho_verts_3D.push_back(hov);
2377 ho_el_order_3D.push_back(el_order);
2382 case 14: el_order--;
2383 case 118: el_order--;
2384 case 119: el_order--;
2385 case 120: el_order--;
2386 case 121: el_order--;
2387 case 122: el_order--;
2388 case 123: el_order--;
2389 case 124: el_order--;
2392 elements_3D.push_back(
2393 new Pyramid(&vert_indices[0], phys_domain));
2397 hov->
Append(&vert_indices[0], n_elem_nodes);
2398 ho_verts_3D.push_back(hov);
2399 ho_el_order_3D.push_back(el_order);
2405 elements_0D.push_back(
2406 new Point(&vert_indices[0], phys_domain));
2410 MFEM_WARNING(
"Unsupported Gmsh element type.");
2417 if (has_positive_phys_domain && has_nonpositive_phys_domain)
2419 MFEM_ABORT(
"Non-positive element attribute in Gmsh mesh!\n"
2420 "By default Gmsh sets element tags (attributes)"
2421 " to '0' but MFEM requires that they be"
2422 " positive integers.\n"
2423 "Use \"Physical Curve\", \"Physical Surface\","
2424 " or \"Physical Volume\" to set tags/attributes"
2425 " for all curves, surfaces, or volumes in your"
2426 " Gmsh geometry to values which are >= 1.");
2428 else if (has_nonpositive_phys_domain)
2430 mfem::out <<
"\nGmsh reader: all element attributes were zero.\n"
2431 <<
"MFEM only supports positive element attributes.\n"
2432 <<
"Setting element attributes to 1.\n\n";
2435 if (!elements_3D.empty())
2450 for (
size_t el = 0; el < ho_el_order_3D.size(); el++)
2452 mesh_order = max(mesh_order, ho_el_order_3D[el]);
2455 for (
size_t el = 0; el < elements_1D.size(); ++el)
2457 delete elements_1D[el];
2459 for (
size_t el = 0; el < elements_0D.size(); ++el)
2461 delete elements_0D[el];
2464 else if (!elements_2D.empty())
2479 for (
size_t el = 0; el < ho_el_order_2D.size(); el++)
2481 mesh_order = max(mesh_order, ho_el_order_2D[el]);
2484 for (
size_t el = 0; el < elements_0D.size(); ++el)
2486 delete elements_0D[el];
2489 else if (!elements_1D.empty())
2504 for (
size_t el = 0; el < ho_el_order_1D.size(); el++)
2506 mesh_order = max(mesh_order, ho_el_order_1D[el]);
2511 MFEM_ABORT(
"Gmsh file : no elements found");
2541 const int * vm = NULL;
2546 ho_verts = ho_verts_1D[el];
2547 el_order = ho_el_order_1D[el];
2548 if (!ho_lin[el_order])
2550 ho_lin[el_order] =
new int[ho_verts->
Size()];
2553 vm = ho_lin[el_order];
2556 ho_verts = ho_verts_2D[el];
2557 el_order = ho_el_order_2D[el];
2558 if (!ho_tri[el_order])
2560 ho_tri[el_order] =
new int[ho_verts->
Size()];
2563 vm = ho_tri[el_order];
2566 ho_verts = ho_verts_2D[el];
2567 el_order = ho_el_order_2D[el];
2568 if (!ho_sqr[el_order])
2570 ho_sqr[el_order] =
new int[ho_verts->
Size()];
2573 vm = ho_sqr[el_order];
2576 ho_verts = ho_verts_3D[el];
2577 el_order = ho_el_order_3D[el];
2578 if (!ho_tet[el_order])
2580 ho_tet[el_order] =
new int[ho_verts->
Size()];
2583 vm = ho_tet[el_order];
2586 ho_verts = ho_verts_3D[el];
2587 el_order = ho_el_order_3D[el];
2588 if (!ho_hex[el_order])
2590 ho_hex[el_order] =
new int[ho_verts->
Size()];
2593 vm = ho_hex[el_order];
2596 ho_verts = ho_verts_3D[el];
2597 el_order = ho_el_order_3D[el];
2598 if (!ho_wdg[el_order])
2600 ho_wdg[el_order] =
new int[ho_verts->
Size()];
2603 vm = ho_wdg[el_order];
2606 ho_verts = ho_verts_3D[el];
2607 el_order = ho_el_order_3D[el];
2608 if (!ho_pyr[el_order])
2610 ho_pyr[el_order] =
new int[ho_verts->
Size()];
2613 vm = ho_pyr[el_order];
2616 MFEM_WARNING(
"Unsupported Gmsh element type.");
2619 int nv = (ho_verts) ? ho_verts->
Size() : 0;
2621 for (
int v = 0; v<nv; v++)
2626 Nodes_gf(
spaceDim * (o + v) + d) = c[d];
2634 for (
size_t el=0; el<ho_verts_1D.size(); el++)
2636 delete ho_verts_1D[el];
2638 for (
size_t el=0; el<ho_verts_2D.size(); el++)
2640 delete ho_verts_2D[el];
2642 for (
size_t el=0; el<ho_verts_3D.size(); el++)
2644 delete ho_verts_3D[el];
2648 for (
int ord=4; ord<ho_lin.
Size(); ord++)
2650 if (ho_lin[ord] != NULL) {
delete [] ho_lin[ord]; }
2652 for (
int ord=4; ord<ho_tri.
Size(); ord++)
2654 if (ho_tri[ord] != NULL) {
delete [] ho_tri[ord]; }
2656 for (
int ord=4; ord<ho_sqr.
Size(); ord++)
2658 if (ho_sqr[ord] != NULL) {
delete [] ho_sqr[ord]; }
2660 for (
int ord=4; ord<ho_tet.
Size(); ord++)
2662 if (ho_tet[ord] != NULL) {
delete [] ho_tet[ord]; }
2664 for (
int ord=4; ord<ho_hex.
Size(); ord++)
2666 if (ho_hex[ord] != NULL) {
delete [] ho_hex[ord]; }
2668 for (
int ord=4; ord<ho_wdg.
Size(); ord++)
2670 if (ho_wdg[ord] != NULL) {
delete [] ho_wdg[ord]; }
2672 for (
int ord=4; ord<ho_pyr.
Size(); ord++)
2674 if (ho_pyr[ord] != NULL) {
delete [] ho_pyr[ord]; }
2680 MFEM_CONTRACT_VAR(n_partitions);
2681 MFEM_CONTRACT_VAR(elem_domain);
2684 else if (buff ==
"$PhysicalNames")
2690 for (
int i=0; i < num_names; i++)
2692 input >> mdim >> num;
2693 getline(input, name);
2696 while (!name.empty() &&
2697 (*name.begin() ==
' ' || *name.begin() ==
'\t'))
2701 while (!name.empty() &&
2702 (*name.rbegin() ==
' ' || *name.rbegin() ==
'\t' ||
2703 *name.rbegin() ==
'\n' || *name.rbegin() ==
'\r'))
2704 { name.resize(name.length()-1);}
2707 if ( (*name.begin() ==
'"' || *name.begin() ==
'\'') &&
2708 (*name.rbegin() ==
'"' || *name.rbegin() ==
'\''))
2710 name = name.substr(1,name.length()-2);
2713 phys_names_by_dim[mdim][num] = name;
2716 else if (buff ==
"$Periodic")
2723 for (
int i = 0; i < v2v.
Size(); i++)
2729 input >> num_per_ent;
2730 getline(input, buff);
2731 for (
int i = 0; i < num_per_ent; i++)
2733 getline(input, buff);
2734 getline(input, buff);
2735 if (!strncmp(buff.c_str(),
"Affine", 6))
2741 num_nodes = atoi(buff.c_str());
2743 for (
int j=0; j<num_nodes; j++)
2746 input >> slave >> master;
2747 v2v[slave - 1] = master - 1;
2749 getline(input, buff);
2756 for (
int slave = 0; slave < v2v.
Size(); slave++)
2758 int master = v2v[slave];
2759 if (master != slave)
2762 while (v2v[master] != master && master != slave)
2764 master = v2v[master];
2766 if (master == slave)
2775 v2v[slave] = master;
2781 if (mesh_order == 1)
2790 for (
int i = 0; i < this->
GetNE(); i++)
2795 for (
int j = 0; j < nv; j++)
2802 for (
int i = 0; i < this->
GetNBE(); i++)
2807 for (
int j = 0; j < nv; j++)
2816 if (phys_names_by_dim.size() > 0)
2819 for (
auto const &bdr_attr : phys_names_by_dim[
Dim-1])
2829 for (
auto const &attr : phys_names_by_dim[
Dim])
2853#ifdef MFEM_USE_NETCDF
2862 1,2,3,4,5,7,8,6,9,10
2868 1,2,3,4,5,6,7,8,9,10,11,
2871 12,17,18,19,20,13,14,15,
2874 16,22,26,25,27,24,23,21
2879 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
2884 1, 2, 3, 4, 5, 6, 7, 8, 9, 13, 14, 15, 10, 11, 12, 16, 17, 18
2985 CubitElement() =
delete;
2988 ~CubitElement() =
default;
2997 inline size_t GetNumFaces()
const {
return _num_faces; }
3000 inline size_t GetNumVertices()
const {
return _num_vertices; }
3003 inline size_t GetNumNodes()
const {
return _num_nodes; }
3006 size_t GetNumFaceVertices(
size_t iface = 1)
const;
3009 inline uint8_t GetOrder()
const {
return _order; }
3012 Element * BuildElement(Mesh & mesh,
const int * vertex_ids,
3013 const int block_id)
const;
3016 Element * BuildBoundaryElement(Mesh & mesh,
const int iface,
3017 const int * vertex_ids,
const int sideset_id)
const;
3030 Element * NewElement(Mesh & mesh,
Geometry::Type geom,
const int *vertices,
3031 const int attribute)
const;
3038 size_t _num_vertices;
3045 _element_type = element_type;
3047 switch (element_type)
3122 MFEM_ABORT(
"Unsupported Cubit element type " << element_type <<
".");
3148 MFEM_ABORT(
"Unsupported 3D element with " << num_nodes <<
" nodes.");
3165 MFEM_ABORT(
"Unsupported 2D element with " << num_nodes <<
" nodes.");
3174 return Get2DElementType(num_nodes);
3178 return Get3DElementType(num_nodes);
3182 MFEM_ABORT(
"Unsupported Cubit dimension " <<
dimension <<
".");
3186CubitFaceType CubitElement::GetFaceType(
size_t side_id)
const
3189 bool valid_id = (side_id >= 1 &&
3190 side_id <= GetNumFaces());
3193 MFEM_ABORT(
"Encountered invalid side ID: " << side_id <<
".");
3196 switch (_element_type)
3223 MFEM_ABORT(
"Unknown element type: " << _element_type <<
".");
3228size_t CubitElement::GetNumFaceVertices(
size_t side_id)
const
3230 switch (GetFaceType(side_id))
3242 MFEM_ABORT(
"Unrecognized Cubit face type " << GetFaceType(side_id) <<
".");
3248 const int *vertices,
3249 const int attribute)
const
3251 Element *new_element = mesh.NewElement(geom);
3253 new_element->SetAttribute(attribute);
3259 const int *vertex_ids,
3260 const int block_id)
const
3262 switch (GetElementType())
3283 MFEM_ABORT(
"Unsupported Cubit element type encountered.");
3288mfem::Element * CubitElement::BuildBoundaryElement(Mesh &mesh,
3290 const int *vertex_ids,
3291 const int sideset_id)
const
3293 switch (GetFaceType(face_id))
3305 MFEM_ABORT(
"Unsupported Cubit face type encountered.");
3318 CubitBlock() =
delete;
3319 ~CubitBlock() =
default;
3329 const CubitElement & GetBlockElement(
int block_id)
const;
3339 uint8_t GetOrder()
const;
3340 inline uint8_t GetDimension()
const {
return _dimension; }
3342 inline size_t GetNumBlocks()
const {
return BlockIDs().size(); }
3343 inline bool HasBlocks()
const {
return !BlockIDs().empty(); }
3350 void CheckElementBlockIsCompatible(
const CubitElement & new_block_element)
3356 void ClearBlockElements();
3361 inline const std::set<int> & BlockIDs()
const {
return _block_ids; }
3363 bool HasBlockID(
int block_id)
const;
3364 bool ValidBlockID(
int block_id)
const;
3365 bool ValidDimension(
int dimension)
const;
3371 std::set<int> _block_ids;
3376 std::map<int, CubitElement> _block_element_for_block_id;
3389 MFEM_ABORT(
"Invalid dimension '" <<
dimension <<
"' specified.");
3394 ClearBlockElements();
3400 if (HasBlockID(block_id))
3402 MFEM_ABORT(
"Block with ID '" << block_id <<
"' has already been added.");
3404 else if (!ValidBlockID(block_id))
3406 MFEM_ABORT(
"Illegal block ID '" << block_id <<
"'.");
3409 CubitElement block_element = CubitElement(element_type);
3414 CheckElementBlockIsCompatible(block_element);
3418 _order = block_element.GetOrder();
3421 _block_ids.insert(block_id);
3422 _block_element_for_block_id.emplace(block_id,
3427CubitBlock::GetOrder()
const
3431 MFEM_ABORT(
"No elements have been added.");
3438CubitBlock::ClearBlockElements()
3442 _block_element_for_block_id.clear();
3446CubitBlock::HasBlockID(
int block_id)
const
3448 return (_block_ids.count(block_id) > 0);
3452CubitBlock::ValidBlockID(
int block_id)
const
3454 return (block_id > 0);
3458CubitBlock::ValidDimension(
int dimension)
const
3464CubitBlock::GetBlockElement(
int block_id)
const
3466 if (!HasBlockID(block_id))
3468 MFEM_ABORT(
"No element info for block ID '" << block_id <<
"'.");
3471 return _block_element_for_block_id.at(block_id);
3475CubitBlock::CheckElementBlockIsCompatible(
const CubitElement &
3476 new_block_element)
const
3484 if (GetOrder() != new_block_element.GetOrder())
3486 MFEM_ABORT(
"All block elements must be of the same order.");
3496 NetCDFReader() =
delete;
3497 NetCDFReader(
const std::string fname);
3502 bool HasVariable(
const char * name);
3505 void ReadVariable(
const char * name,
int * data);
3508 void ReadVariable(
const char * name,
double * data);
3511 bool HasDimension(
const char * name);
3514 void ReadDimension(
const char * name,
size_t *
dimension);
3517 void BuildIDToNameMap(
const vector<int> & ids,
3518 unordered_map<int, string> & ids_to_names,
3519 const string & quantity_name);
3523 void CheckForNetCDFError();
3526 int ReadVariableID(
const char * name);
3529 int ReadDimensionID(
const char * name);
3533 void HandleNetCDFError(
const int error_code);
3535 int _netcdf_status{NC_NOERR};
3536 int _netcdf_descriptor;
3539 char *_name_buffer{NULL};
3543NetCDFReader::NetCDFReader(
const std::string fname)
3545 _netcdf_status = nc_open(fname.c_str(), NC_NOWRITE, &_netcdf_descriptor);
3546 CheckForNetCDFError();
3549 _name_buffer =
new char[NC_MAX_NAME + 1];
3552NetCDFReader::~NetCDFReader()
3554 _netcdf_status = nc_close(_netcdf_descriptor);
3555 CheckForNetCDFError();
3559 delete[] _name_buffer;
3563void NetCDFReader::CheckForNetCDFError()
3565 if (_netcdf_status != NC_NOERR)
3567 HandleNetCDFError(_netcdf_status);
3571void NetCDFReader::HandleNetCDFError(
const int error_code)
3573 MFEM_ABORT(
"Fatal NetCDF error: " << nc_strerror(error_code));
3576int NetCDFReader::ReadVariableID(
const char * var_name)
3580 _netcdf_status = nc_inq_varid(_netcdf_descriptor, var_name,
3582 CheckForNetCDFError();
3587int NetCDFReader::ReadDimensionID(
const char * name)
3591 _netcdf_status = nc_inq_dimid(_netcdf_descriptor, name, &dim_id);
3592 CheckForNetCDFError();
3597void NetCDFReader::ReadDimension(
const char * name,
size_t *
dimension)
3599 const int dimension_id = ReadDimensionID(name);
3602 _netcdf_status = nc_inq_dim(_netcdf_descriptor, dimension_id, _name_buffer,
3604 CheckForNetCDFError();
3607bool NetCDFReader::HasVariable(
const char * name)
3610 const int status = nc_inq_varid(_netcdf_descriptor, name, &var_id);
3619 HandleNetCDFError(status);
3624bool NetCDFReader::HasDimension(
const char * name)
3627 const int status = nc_inq_dimid(_netcdf_descriptor, name, &dim_id);
3636 HandleNetCDFError(status);
3641void NetCDFReader::ReadVariable(
const char * name,
int * data)
3643 const int variable_id = ReadVariableID(name);
3645 _netcdf_status = nc_get_var_int(_netcdf_descriptor, variable_id, data);
3646 CheckForNetCDFError();
3650void NetCDFReader::ReadVariable(
const char * name,
double * data)
3652 const int variable_id = ReadVariableID(name);
3654 _netcdf_status = nc_get_var_double(_netcdf_descriptor, variable_id, data);
3655 CheckForNetCDFError();
3659void NetCDFReader::BuildIDToNameMap(
const vector<int> & ids,
3660 unordered_map<int, string> & ids_to_names,
3661 const string & quantity_name)
3666 _netcdf_status = nc_inq_varid(_netcdf_descriptor, quantity_name.c_str(),
3670 if (_netcdf_status == NC_ENOTVAR)
3676 CheckForNetCDFError();
3681 _netcdf_status = nc_inq_vartype(_netcdf_descriptor, varid_names,
3683 CheckForNetCDFError();
3685 if (var_type == NC_CHAR)
3687 int dimids_names[2], names_ndim;
3688 size_t num_names, name_len;
3690 _netcdf_status = nc_inq_varndims(_netcdf_descriptor, varid_names,
3692 CheckForNetCDFError();
3693 MFEM_ASSERT(names_ndim == 2,
"This variable should have two dimensions");
3695 _netcdf_status = nc_inq_vardimid(_netcdf_descriptor, varid_names,
3697 CheckForNetCDFError();
3699 _netcdf_status = nc_inq_dimlen(_netcdf_descriptor, dimids_names[0], &num_names);
3700 CheckForNetCDFError();
3701 MFEM_ASSERT(num_names == ids.size(),
3702 "The block id and block name lengths don't match");
3704 _netcdf_status = nc_inq_dimlen(_netcdf_descriptor, dimids_names[1], &name_len);
3705 CheckForNetCDFError();
3708 vector<char> names(ids.size() * name_len);
3709 _netcdf_status = nc_get_var_text(_netcdf_descriptor, varid_names,
3711 CheckForNetCDFError();
3713 for (
size_t i = 0; i < ids.size(); ++i)
3715 string name(&names[i * name_len], name_len);
3717 name.resize(name.find(
'\0'));
3718 ids_to_names[ids[i]] = name;
3723 mfem_error(
"Unexpected netcdf variable type");
3729static void ReadCubitNodeCoordinates(NetCDFReader & cubit_reader,
3734 cubit_reader.ReadVariable(
"coordx", coordx);
3735 cubit_reader.ReadVariable(
"coordy", coordy);
3739 cubit_reader.ReadVariable(
"coordz", coordz);
3745static void ReadCubitNumElementsInBlock(NetCDFReader & cubit_reader,
3746 const vector<int> & block_ids,
3747 map<int, size_t> &num_elements_for_block_id)
3749 num_elements_for_block_id.clear();
3752 const int buffer_size = NC_MAX_NAME + 1;
3753 char string_buffer[buffer_size];
3756 for (
const auto block_id : block_ids)
3759 snprintf(string_buffer, buffer_size,
"num_el_in_blk%d", iblock++);
3761 size_t num_elements_for_block = 0;
3762 cubit_reader.ReadDimension(string_buffer, &num_elements_for_block);
3764 num_elements_for_block_id[block_id] = num_elements_for_block;
3770static void BuildElementIDsForBlockID(
3771 const vector<int> & block_ids,
3772 const map<int, size_t> & num_elements_for_block_id,
3773 map<
int, vector<int>> & element_ids_for_block_id,
3774 map<int, int> & block_id_for_element_id)
3776 element_ids_for_block_id.clear();
3777 block_id_for_element_id.clear();
3782 for (
int block_id : block_ids)
3784 const int num_elements_for_block = num_elements_for_block_id.at(block_id);
3786 vector<int> element_ids(num_elements_for_block);
3788 for (
int i = 0; i < num_elements_for_block; i++, element_id++)
3790 element_ids[i] = element_id;
3791 block_id_for_element_id[element_id] = block_id;
3794 element_ids_for_block_id[block_id] = std::move(element_ids);
3799static void ReadCubitBlocks(NetCDFReader & cubit_reader,
3800 const vector<int> block_ids,
3801 CubitBlock & cubit_blocks)
3803 const int buffer_size = NC_MAX_NAME + 1;
3804 char string_buffer[buffer_size];
3806 size_t num_nodes_per_element;
3809 for (
int block_id : block_ids)
3812 snprintf(string_buffer, buffer_size,
"num_nod_per_el%d", iblock++);
3814 cubit_reader.ReadDimension(string_buffer, &num_nodes_per_element);
3818 num_nodes_per_element, cubit_blocks.GetDimension());
3819 cubit_blocks.AddBlockElement(block_id, element_type);
3825static void ReadCubitDimensions(NetCDFReader & cubit_reader,
3830 size_t &num_side_sets)
3832 cubit_reader.ReadDimension(
"num_dim", &num_dim);
3833 cubit_reader.ReadDimension(
"num_nodes", &num_nodes);
3834 cubit_reader.ReadDimension(
"num_elem", &num_elem);
3835 cubit_reader.ReadDimension(
"num_el_blk", &num_el_blk);
3838 if (cubit_reader.HasDimension(
"num_side_sets"))
3840 cubit_reader.ReadDimension(
"num_side_sets", &num_side_sets);
3850static void ReadCubitBoundaries(NetCDFReader & cubit_reader,
3851 const vector<int> & boundary_ids,
3852 map<
int, vector<int>> & element_ids_for_boundary_id,
3853 map<
int, vector<int>> & side_ids_for_boundary_id)
3855 const int buffer_size = NC_MAX_NAME + 1;
3856 char string_buffer[buffer_size];
3859 for (
int boundary_id : boundary_ids)
3862 size_t num_sides = 0;
3864 snprintf(string_buffer, buffer_size,
"num_side_ss%d", ibdr);
3865 cubit_reader.ReadDimension(string_buffer, &num_sides);
3868 vector<int> boundary_element_ids(num_sides);
3869 vector<int> boundary_side_ids(num_sides);
3872 snprintf(string_buffer, buffer_size,
"elem_ss%d", ibdr);
3873 cubit_reader.ReadVariable(string_buffer, boundary_element_ids.data());
3876 snprintf(string_buffer, buffer_size,
"side_ss%d", ibdr++);
3877 cubit_reader.ReadVariable(string_buffer, boundary_side_ids.data());
3880 element_ids_for_boundary_id[boundary_id] = std::move(boundary_element_ids);
3881 side_ids_for_boundary_id[boundary_id] = std::move(boundary_side_ids);
3886static void BuildCubitBlockIDs(NetCDFReader & cubit_reader,
3887 const int num_element_blocks,
3888 vector<int> & block_ids)
3890 block_ids.resize(num_element_blocks);
3891 cubit_reader.ReadVariable(
"eb_prop1", block_ids.data());
3895static void ReadCubitBoundaryIDs(NetCDFReader & cubit_reader,
3896 const int num_boundaries, vector<int> & boundary_ids)
3898 boundary_ids.clear();
3900 if (num_boundaries < 1) {
return; }
3902 boundary_ids.resize(num_boundaries);
3903 cubit_reader.ReadVariable(
"ss_prop1", boundary_ids.data());
3907static void ReadCubitElementBlocks(NetCDFReader & cubit_reader,
3908 const CubitBlock & cubit_blocks,
3909 const vector<int> & block_ids,
3910 const map<
int, vector<int>> & element_ids_for_block_id,
3911 map<
int, vector<int>> &node_ids_for_element_id)
3913 const int buffer_size = NC_MAX_NAME + 1;
3914 char string_buffer[buffer_size];
3917 for (
const int block_id : block_ids)
3919 const CubitElement & block_element = cubit_blocks.GetBlockElement(block_id);
3921 const vector<int> & block_element_ids = element_ids_for_block_id.at(block_id);
3923 const size_t num_nodes_for_block = block_element_ids.size() *
3924 block_element.GetNumNodes();
3926 vector<int> node_ids_for_block(num_nodes_for_block);
3929 snprintf(string_buffer, buffer_size,
"connect%d", iblock++);
3931 cubit_reader.ReadVariable(string_buffer, node_ids_for_block.data());
3935 for (
int element_id : block_element_ids)
3937 vector<int> element_node_ids(block_element.GetNumNodes());
3939 for (
int i = 0; i < (int)block_element.GetNumNodes(); i++)
3941 element_node_ids[i] = node_ids_for_block[ielement * block_element.GetNumNodes()
3947 node_ids_for_element_id[element_id] = std::move(element_node_ids);
3953static void BuildBoundaryNodeIDs(
const vector<int> & boundary_ids,
3954 const CubitBlock & blocks,
3955 const map<
int, vector<int>> & node_ids_for_element_id,
3956 const map<
int, vector<int>> & element_ids_for_boundary_id,
3957 const map<
int, vector<int>> & side_ids_for_boundary_id,
3958 const map<int, int> & block_id_for_element_id,
3959 map<
int, vector<vector<int>>> & node_ids_for_boundary_id)
3961 for (
int boundary_id : boundary_ids)
3964 auto & boundary_element_ids = element_ids_for_boundary_id.at(
3966 auto & boundary_element_sides = side_ids_for_boundary_id.at(
3970 vector<vector<int>> boundary_node_ids(
3971 boundary_element_ids.size());
3974 for (
int jelement = 0; jelement < (int)boundary_element_ids.size(); jelement++)
3977 const int boundary_element_global_id = boundary_element_ids[jelement];
3978 const int boundary_side = boundary_element_sides[jelement];
3981 const int block_id = block_id_for_element_id.at(boundary_element_global_id);
3982 const CubitElement & block_element = blocks.GetBlockElement(block_id);
3984 const int num_face_vertices = block_element.GetNumFaceVertices(boundary_side);
3985 vector<int> nodes_of_element_on_side(num_face_vertices);
3988 const vector<int> & element_node_ids =
3989 node_ids_for_element_id.at(boundary_element_global_id);
3993 for (
int knode = 0; knode < num_face_vertices; knode++)
3997 switch (block_element.GetElementType())
4024 MFEM_ABORT(
"Unsupported element type encountered.\n");
4028 nodes_of_element_on_side[knode] = element_node_ids[inode - 1];
4031 boundary_node_ids[jelement] = std::move(nodes_of_element_on_side);
4035 node_ids_for_boundary_id[boundary_id] = std::move(boundary_node_ids);
4040static void BuildUniqueVertexIDs(
const vector<int> & unique_block_ids,
4041 const CubitBlock & blocks,
4042 const map<
int, vector<int>> & element_ids_for_block_id,
4043 const map<
int, vector<int>> & node_ids_for_element_id,
4044 vector<int> & unique_vertex_ids)
4047 for (
int block_id : unique_block_ids)
4049 auto & element_ids = element_ids_for_block_id.at(block_id);
4051 auto & block_element = blocks.GetBlockElement(block_id);
4053 for (
int element_id : element_ids)
4055 auto & node_ids = node_ids_for_element_id.at(element_id);
4057 for (
size_t knode = 0; knode < block_element.GetNumVertices(); knode++)
4059 unique_vertex_ids.push_back(node_ids[knode]);
4065 std::sort(unique_vertex_ids.begin(), unique_vertex_ids.end());
4067 auto new_end = std::unique(unique_vertex_ids.begin(), unique_vertex_ids.end());
4069 unique_vertex_ids.resize(std::distance(unique_vertex_ids.begin(), new_end));
4075static void BuildCubitToMFEMVertexMap(
const vector<int> & unique_vertex_ids,
4076 map<int, int> & cubit_to_mfem_vertex_map)
4078 cubit_to_mfem_vertex_map.clear();
4081 for (
int vertex_id : unique_vertex_ids)
4083 cubit_to_mfem_vertex_map[vertex_id] = ivertex++;
4091static void FinalizeCubitSecondOrderMesh(Mesh &mesh,
4092 const vector<int> & unique_block_ids,
4093 const CubitBlock & blocks,
4094 const map<
int, vector<int>> & element_ids_for_block_id,
4095 const map<
int, vector<int>> & node_ids_for_element_id,
4096 const double *coordx,
4097 const double *coordy,
4098 const double *coordz)
4100 mesh.FinalizeTopology();
4103 const int Dim = mesh.Dimension();
4104 FiniteElementCollection *fec =
new H1_FECollection(2, Dim);
4105 FiniteElementSpace *fes =
new FiniteElementSpace(&mesh, fec, Dim,
4107 GridFunction *Nodes =
new GridFunction(fes);
4108 Nodes->MakeOwner(fec);
4109 mesh.SetNodalGridFunction(Nodes,
true);
4111 for (
int block_id : unique_block_ids)
4113 const CubitElement & block_element = blocks.GetBlockElement(block_id);
4115 int *mfem_to_genesis_map = NULL;
4117 switch (block_element.GetElementType())
4138 MFEM_ABORT(
"Something went wrong. Linear elements detected when order is 2.");
4141 auto & element_ids = element_ids_for_block_id.at(block_id);
4143 for (
int element_id : element_ids)
4147 fes->GetElementDofs(element_id - 1, dofs);
4149 Array<int> vdofs = dofs;
4150 fes->DofsToVDofs(vdofs);
4152 const vector<int> & element_node_ids = node_ids_for_element_id.at(element_id);
4154 for (
int jnode = 0; jnode < dofs.Size(); jnode++)
4156 const int node_index = element_node_ids[mfem_to_genesis_map[jnode] - 1] - 1;
4158 (*Nodes)(vdofs[jnode]) = coordx[node_index];
4159 (*Nodes)(vdofs[jnode] + 1) = coordy[node_index];
4163 (*Nodes)(vdofs[jnode] + 2) = coordz[node_index];
4174 const vector<double> & coordx,
4175 const vector<double> & coordy,
4176 const vector<double> & coordz)
4183 const int original_1based_id = unique_vertex_ids[ivertex];
4185 vertices[ivertex](0) = coordx[original_1based_id - 1];
4186 vertices[ivertex](1) = coordy[original_1based_id - 1];
4190 vertices[ivertex](2) = coordz[original_1based_id - 1];
4197 const cubit::CubitBlock * blocks,
4198 const vector<int> & block_ids,
4199 const map<
int, vector<int>> & element_ids_for_block_id,
4200 const map<
int, vector<int>> & node_ids_for_element_id,
4201 const map<int, int> & cubit_to_mfem_vertex_map)
4203 using namespace cubit;
4208 int element_counter = 0;
4211 for (
int block_id : block_ids)
4213 const CubitElement & block_element = blocks->GetBlockElement(block_id);
4215 vector<int> renumbered_vertex_ids(block_element.GetNumVertices());
4217 const vector<int> &block_element_ids = element_ids_for_block_id.at(block_id);
4220 for (
int element_id : block_element_ids)
4222 const vector<int> & element_node_ids = node_ids_for_element_id.at(element_id);
4225 for (
size_t knode = 0; knode < block_element.GetNumVertices(); knode++)
4227 const int node_id = element_node_ids[knode];
4230 renumbered_vertex_ids[knode] = cubit_to_mfem_vertex_map.at(node_id) - 1;
4234 elements[element_counter++] = block_element.BuildElement(*
this,
4235 renumbered_vertex_ids.data(),
4243 const cubit::CubitBlock * blocks,
4244 const vector<int> & boundary_ids,
4245 const map<
int, vector<int>> & element_ids_for_boundary_id,
4246 const map<
int, vector<vector<int>>> & node_ids_for_boundary_id,
4247 const map<
int, vector<int>> & side_ids_for_boundary_id,
4248 const map<int, int> & block_id_for_element_id,
4249 const map<int, int> & cubit_to_mfem_vertex_map)
4251 using namespace cubit;
4254 for (
int boundary_id : boundary_ids)
4261 array<int, 8> renumbered_vertex_ids;
4264 int boundary_counter = 0;
4265 for (
int boundary_id : boundary_ids)
4267 const vector<int> &elements_on_boundary = element_ids_for_boundary_id.at(
4270 const vector<vector<int>> &nodes_on_boundary = node_ids_for_boundary_id.at(
4274 for (
int side_id : side_ids_for_boundary_id.at(boundary_id))
4277 const int element_id = elements_on_boundary.at(jelement);
4278 const int element_block = block_id_for_element_id.at(element_id);
4279 const CubitElement & block_element = blocks->GetBlockElement(element_block);
4281 const vector<int> & element_nodes_on_side = nodes_on_boundary.at(jelement);
4284 for (
size_t knode = 0; knode < element_nodes_on_side.size(); knode++)
4286 const int node_id = element_nodes_on_side[knode];
4289 renumbered_vertex_ids[knode] = cubit_to_mfem_vertex_map.at(node_id) - 1;
4293 boundary[boundary_counter++] = block_element.BuildBoundaryElement(*
this,
4295 renumbered_vertex_ids.data(),
4305 using namespace cubit;
4313 NetCDFReader cubit_reader(filename);
4318 size_t num_dimensions, num_nodes, num_elements, num_element_blocks,
4321 ReadCubitDimensions(cubit_reader, num_dimensions, num_nodes, num_elements,
4322 num_element_blocks, num_boundaries);
4324 Dim = num_dimensions;
4329 vector<int> block_ids;
4330 BuildCubitBlockIDs(cubit_reader, num_element_blocks, block_ids);
4331 unordered_map<int, string> blk_ids_to_names;
4332 cubit_reader.BuildIDToNameMap(block_ids, blk_ids_to_names,
"eb_names");
4333 for (
const auto & pr : blk_ids_to_names)
4335 const auto blk_id = pr.first;
4336 const auto & blk_name = pr.second;
4337 if (!blk_name.empty())
4347 map<int, size_t> num_elements_for_block_id;
4348 ReadCubitNumElementsInBlock(cubit_reader, block_ids,
4349 num_elements_for_block_id);
4351 map<int, vector<int>> element_ids_for_block_id;
4352 map<int, int> block_id_for_element_id;
4353 BuildElementIDsForBlockID(
4354 block_ids, num_elements_for_block_id, element_ids_for_block_id,
4355 block_id_for_element_id);
4359 CubitBlock blocks(num_dimensions);
4360 ReadCubitBlocks(cubit_reader, block_ids, blocks);
4363 map<int, vector<int>> node_ids_for_element_id;
4364 ReadCubitElementBlocks(cubit_reader,
4367 element_ids_for_block_id,
4368 node_ids_for_element_id);
4373 vector<int> boundary_ids;
4374 ReadCubitBoundaryIDs(cubit_reader, num_boundaries, boundary_ids);
4375 unordered_map<int, string> bnd_ids_to_names;
4376 cubit_reader.BuildIDToNameMap(boundary_ids, bnd_ids_to_names,
"ss_names");
4377 for (
const auto & pr : bnd_ids_to_names)
4379 const auto bnd_id = pr.first;
4380 const auto & bnd_name = pr.second;
4381 if (!bnd_name.empty())
4395 map<int, vector<int>> element_ids_for_boundary_id;
4396 map<int, vector<int>> side_ids_for_boundary_id;
4398 ReadCubitBoundaries(cubit_reader, boundary_ids,
4399 element_ids_for_boundary_id, side_ids_for_boundary_id);
4401 map<int, vector<vector<int>>> node_ids_for_boundary_id;
4403 BuildBoundaryNodeIDs(boundary_ids, blocks, node_ids_for_element_id,
4404 element_ids_for_boundary_id, side_ids_for_boundary_id,
4405 block_id_for_element_id,
4406 node_ids_for_boundary_id);
4411 vector<double> coordx(num_nodes);
4412 vector<double> coordy(num_nodes);
4413 vector<double> coordz(num_dimensions == 3 ? num_nodes : 0);
4415 ReadCubitNodeCoordinates(cubit_reader, coordx.data(), coordy.data(),
4421 vector<int> unique_vertex_ids;
4422 BuildUniqueVertexIDs(block_ids, blocks, element_ids_for_block_id,
4423 node_ids_for_element_id, unique_vertex_ids);
4431 map<int, int> cubit_to_mfem_vertex_map;
4432 BuildCubitToMFEMVertexMap(unique_vertex_ids, cubit_to_mfem_vertex_map);
4443 element_ids_for_block_id,
4444 node_ids_for_element_id, cubit_to_mfem_vertex_map);
4450 element_ids_for_boundary_id, node_ids_for_boundary_id, side_ids_for_boundary_id,
4451 block_id_for_element_id,
4452 cubit_to_mfem_vertex_map);
4457 if (blocks.GetOrder() == 2)
4461 FinalizeCubitSecondOrderMesh(*
this,
4464 element_ids_for_block_id,
4465 node_ids_for_element_id,
void Load(std::istream &in, int fmt=0)
Read an Array from the stream in using format fmt. The format fmt can be:
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int Size() const
Return the logical size of the array.
int Append(const T &el)
Append element 'el' to array, resize if necessary.
T * GetData()
Returns the data.
void SortAll()
Sort each named array in the container.
void UniqueAll()
Remove duplicates from each, previously sorted, named array.
void Load(std::istream &in)
Load the contents of the container from an input stream.
bool AttributeSetExists(const std::string &name) const
Return true is the named attribute set is present.
void AddToAttributeSet(const std::string &set_name, int attr)
Add a single entry to an existing attribute set.
ArraysByName< int > attr_sets
Named sets of attributes.
Array< int > & CreateAttributeSet(const std::string &set_name)
Create an empty named attribute set.
@ ClosedUniform
Nodes: x_i = i/(n-1), i=0,...,n-1.
Abstract data type element.
virtual void GetVertices(Array< int > &v) const =0
Get the indices defining the vertices.
void SetAttribute(const int attr)
Set element's attribute.
Type
Constants for the classes derived from Element.
virtual int GetNVertices() const =0
virtual void SetVertices(const Array< int > &v)=0
Set the indices defining the vertices.
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
void DofsToVDofs(Array< int > &dofs, int ndofs=-1) const
Compute the full set of vdofs corresponding to each entry in dofs.
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...
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
Abstract class for all finite elements.
static const int Dimension[NumGeom]
Class for grid function - Vector with associated FE space.
void MakeOwner(FiniteElementCollection *fec_)
Make the GridFunction the owner of fec_owned and fes.
virtual void ProjectCoefficient(Coefficient &coeff)
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
int VectorDim() const
Shortcut for calling FiniteElementSpace::GetVectorDim() on the underlying fes.
void GetNodalValues(int i, Array< real_t > &nval, int vdim=1) const
Returns the values in the vertices of i'th element for dimension vdim.
virtual void SetSpace(FiniteElementSpace *f)
Associate a new FiniteElementSpace with the GridFunction.
Arbitrary order H1-conforming (continuous) finite elements.
Data type hexahedron element.
Arbitrary order "L2-conforming" discontinuous finite elements.
int CheckElementOrientation(bool fix_it=true)
Check (and optionally attempt to fix) the orientation of the elements.
void ReadGmshMesh(std::istream &input, int &curved, int &read_gf)
Element * NewElement(int geom)
void BuildCubitElements(const int num_elements, const cubit::CubitBlock *blocks, const std::vector< int > &block_ids, const std::map< int, std::vector< int > > &element_ids_for_block_id, const std::map< int, std::vector< int > > &node_ids_for_element_id, const std::map< int, int > &cubit_to_mfem_vertex_map)
Called internally in ReadCubit. This method builds the mesh elements.
MemAlloc< Tetrahedron, 1024 > TetMemory
NURBSExtension * NURBSext
Optional NURBS mesh extension.
void ReadTrueGridMesh(std::istream &input)
static const int vtk_quadratic_tet[10]
Element::Type GetElementType(int i) const
Returns the type of element i.
void ReadNetgen3DMesh(std::istream &input)
void ReadInlineMesh(std::istream &input, bool generate_edges=false)
void ReadLineMesh(std::istream &input)
static const int vtk_quadratic_wedge[18]
AttributeSets bdr_attribute_sets
Named sets of boundary element attributes.
void Make1D(int n, real_t sx=1.0)
const Element * GetElement(int i) const
Return pointer to the i'th element object.
void FinalizeTopology(bool generate_bdr=true)
Finalize the construction of the secondary topology (connectivity) data of a Mesh.
void ReadXML_VTKMesh(std::istream &input, int &curved, int &read_gf, bool &finalize_topo, const std::string &xml_prefix="")
int GetNE() const
Returns number of elements.
void Make3D(int nx, int ny, int nz, Element::Type type, real_t sx, real_t sy, real_t sz, bool sfc_ordering)
Creates a mesh for the parallelepiped [0,sx]x[0,sy]x[0,sz], divided into nx*ny*nz hexahedra if type =...
const Element * GetBdrElement(int i) const
Return pointer to the i'th boundary element object.
friend class NURBSExtension
static bool remove_unused_vertices
void ReadNURBSMesh(std::istream &input, int &curved, int &read_gf, bool spacing=false)
void ReadCubit(const std::string &filename, int &curved, int &read_gf)
Load a mesh from a Genesis file.
static const int vtk_quadratic_pyramid[13]
AttributeSets attribute_sets
Named sets of element attributes.
void ReadVTKMesh(std::istream &input, int &curved, int &read_gf, bool &finalize_topo)
static const int vtk_quadratic_hex[27]
int GetNBE() const
Returns number of boundary elements.
void ReadMFEMMesh(std::istream &input, int version, int &curved)
void CreateVTKMesh(const Vector &points, const Array< int > &cell_data, const Array< int > &cell_offsets, const Array< int > &cell_types, const Array< int > &cell_attributes, int &curved, int &read_gf, bool &finalize_topo)
void BuildCubitBoundaries(const cubit::CubitBlock *blocks, const std::vector< int > &boundary_ids, const std::map< int, std::vector< int > > &element_ids_for_boundary_id, const std::map< int, std::vector< std::vector< int > > > &node_ids_for_boundary_id, const std::map< int, std::vector< int > > &side_ids_for_boundary_id, const std::map< int, int > &block_id_for_element_id, const std::map< int, int > &cubit_to_mfem_vertex_map)
Called internally in ReadCubit. This method adds the mesh boundary elements.
Array< Element * > boundary
void SetMeshGen()
Determine the mesh generator bitmask meshgen, see MeshGenerator().
void Make2D(int nx, int ny, Element::Type type, real_t sx, real_t sy, bool generate_edges, bool sfc_ordering)
Creates mesh for the rectangle [0,sx]x[0,sy], divided into nx*ny quadrilaterals if type = QUADRILATER...
virtual void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1)
Set the curvature of the mesh nodes using the given polynomial degree.
Element * ReadElement(std::istream &input)
Geometry::Type GetElementBaseGeometry(int i) const
void BuildCubitVertices(const std::vector< int > &unique_vertex_ids, const std::vector< double > &coordx, const std::vector< double > &coordy, const std::vector< double > &coordz)
Called internally in ReadCubit. This method creates the vertices.
void ReadNetgen2DMesh(std::istream &input, int &curved)
Array< Element * > elements
const real_t * GetVertex(int i) const
Return pointer to vertex i's coordinates.
void RemoveUnusedVertices()
Remove unused vertices and rebuild mesh connectivity.
int GetNBE() const
Return the number of active boundary elements.
void SetCoordsFromPatches(Vector &Nodes)
Set FE coordinates in Nodes, using data from patches, and erase patches.
void GetElementTopo(Array< Element * > &elements) const
Generate the active mesh elements and return them in elements.
bool HavePatches() const
Return true if at least 1 patch is defined, false otherwise.
void GetBdrElementTopo(Array< Element * > &boundary) const
Generate the active mesh boundary elements and return them in boundary.
int GetOrder() const
If all KnotVector orders are identical, return that number. Otherwise, return NURBSFECollection::Vari...
int GetNV() const
Return the local number of active vertices.
int Dimension() const
Return the dimension of the reference space (not physical space).
int GetNE() const
Return the number of active elements.
Arbitrary order non-uniform rational B-splines (NURBS) finite elements.
Class for standard nodal finite elements.
const Array< int > & GetLexicographicOrdering() const
Get an Array<int> that maps lexicographically ordered indices to the indices of the respective nodes/...
Data type Pyramid element.
Piecewise-(bi)quadratic continuous finite elements.
Data type quadrilateral element.
Data type line segment element.
Data type tetrahedron element.
void SetVertices(const Array< int > &v) override
Set the indices defining the vertices.
Data type triangle element.
Vector coefficient defined by a vector GridFunction.
void Load(std::istream **in, int np, int *dim)
Reads a vector from multiple files.
int Size() const
Returns the size of the vector.
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
constexpr int dimension
This example only works in 3D. Kernels for 2D are not implemented.
int index(int i, int j, int nx, int ny)
void DecodeBase64(const char *src, size_t len, std::vector< char > &buf)
Decode len base-64 encoded characters in the buffer src, and store the resulting decoded data in buf....
size_t NumBase64Chars(size_t nbytes)
Return the number of characters needed to encode nbytes in base-64.
T read(std::istream &is)
Read a value from the stream and return it.
const int mfem_to_genesis_tri6[6]
const int mfem_to_genesis_pyramid14[14]
const int cubit_side_map_tri3[3][2]
const int mfem_to_genesis_wedge18[18]
const int cubit_side_map_hex8[6][4]
const int cubit_side_map_quad4[4][2]
const int mfem_to_genesis_quad9[9]
const int cubit_side_map_tet4[4][3]
const int cubit_side_map_wedge6[5][4]
const int mfem_to_genesis_hex27[27]
const int cubit_side_map_pyramid5[5][4]
const int mfem_to_genesis_tet10[10]
bool StringCompare(const char *s1, const char *s2)
void mfem_error(const char *msg)
void GmshHOWedgeMapping(int order, int *map)
Generate Gmsh vertex mapping for a Wedge.
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
void GmshHOTriangleMapping(int order, int *map)
Generate Gmsh vertex mapping for a Triangle.
void GmshHOPyramidMapping(int order, int *map)
Generate Gmsh vertex mapping for a Pyramid.
void filter_dos(std::string &line)
Check for, and remove, a trailing '\r' from and std::string.
const char * VTKByteOrder()
Determine the byte order and return either "BigEndian" or "LittleEndian".
void GmshHOTetrahedronMapping(int order, int *map)
Generate Gmsh vertex mapping for a Tetrahedron.
void CreateVTKElementConnectivity(Array< int > &con, Geometry::Type geom, int ref)
Create the VTK element connectivity array for a given element geometry and refinement level.
void GmshHOSegmentMapping(int order, int *map)
Generate Gmsh vertex mapping for a Segment.
void GmshHOQuadrilateralMapping(int order, int *map)
Generate Gmsh vertex mapping for a Quadrilateral.
void GmshHOHexahedronMapping(int order, int *map)
Generate Gmsh vertex mapping for a Hexahedron.
void skip_comment_lines(std::istream &is, const char comment_char)
Check if the stream starts with comment_char. If so skip it.
static const int LAGRANGE_PRISM
static const int PrismMap[6]
Permutation from MFEM's prism ordering to VTK's prism ordering.
static bool IsLagrange(int vtk_geom)
Does the given VTK geometry type describe an arbitrary-order Lagrange element?
static Geometry::Type GetMFEMGeometry(int vtk_geom)
Given a VTK geometry type, return the corresponding MFEM Geometry::Type.
static int GetOrder(int vtk_geom, int npoints)
For the given VTK geometry type and number of points, return the order of the element.