684using namespace tinyxml2;
690 if (s1 == NULL || s2 == NULL) {
return false; }
691 return strcmp(s1, s2) == 0;
699struct BufferReaderBase
701 enum HeaderType { UINT32_HEADER, UINT64_HEADER };
702 virtual void ReadBinary(
const char *buf,
void *dest,
int n)
const = 0;
703 virtual void ReadBase64(
const char *txt,
void *dest,
int n)
const = 0;
704 virtual ~BufferReaderBase() { }
717template <
typename T,
typename F>
718struct BufferReader : BufferReaderBase
721 HeaderType header_type;
722 BufferReader(
bool compressed_, HeaderType header_type_)
723 : compressed(compressed_), header_type(header_type_) { }
726 size_t HeaderEntrySize()
const
728 return header_type == UINT64_HEADER ?
sizeof(uint64_t) : sizeof(uint32_t);
734 uint64_t ReadHeaderEntry(
const char *header_buf)
const
737 : bin_io::
read<uint32_t>(header_buf);
746 int NumHeaderBytes(
const char *header_buf)
const
748 if (!compressed) {
return HeaderEntrySize(); }
749 return (3 + ReadHeaderEntry(header_buf))*HeaderEntrySize();
757 void ReadBinaryWithHeader(
const char *header_buf,
const char *buf,
758 void *dest_void,
int n)
const
760 std::vector<char> uncompressed_data;
761 T *dest =
static_cast<T*
>(dest_void);
771 int header_entry_size = HeaderEntrySize();
772 int nblocks = ReadHeaderEntry(header_buf);
773 header_buf += header_entry_size;
774 std::vector<int> header(nblocks + 2);
775 for (
int i=0; i<nblocks+2; ++i)
777 header[i] = ReadHeaderEntry(header_buf);
778 header_buf += header_entry_size;
780 uncompressed_data.resize((nblocks-1)*header[0] + header[1]);
781 Bytef *dest_ptr = (Bytef *)uncompressed_data.data();
782 Bytef *dest_start = dest_ptr;
783 const Bytef *source_ptr = (
const Bytef *)buf;
784 for (
int i=0; i<nblocks; ++i)
786 uLongf source_len = header[i+2];
787 uLong dest_len = (i == nblocks-1) ? header[1] : header[0];
788 int res = uncompress(dest_ptr, &dest_len, source_ptr, source_len);
789 MFEM_VERIFY(res == Z_OK,
"Error uncompressing");
790 dest_ptr += dest_len;
791 source_ptr += source_len;
793 MFEM_VERIFY(
int(
sizeof(F)*n) == (dest_ptr - dest_start),
794 "AppendedData: wrong data size");
795 buf = uncompressed_data.data();
797 MFEM_ABORT(
"MFEM must be compiled with zlib enabled to uncompress.")
805 if (header_type == UINT32_HEADER)
807 uint32_t *data_size_32 = (uint32_t *)header_buf;
808 data_size = *data_size_32;
812 uint64_t *data_size_64 = (uint64_t *)header_buf;
813 data_size = *data_size_64;
815 MFEM_VERIFY(
sizeof(F)*n == data_size,
"AppendedData: wrong data size");
818 if (std::is_same<T, F>::value)
821 memcpy(dest, buf,
sizeof(T)*n);
825 for (
int i=0; i<n; ++i)
836 void ReadBinary(
const char *buf,
void *dest,
int n)
const override
838 ReadBinaryWithHeader(buf, buf + NumHeaderBytes(buf), dest, n);
845 void ReadBase64(
const char *txt,
void *dest,
int n)
const override
850 if (*txt !=
' ' && *txt !=
'\n') {
break; }
857 std::vector<char> nblocks_buf;
860 std::vector<char> data, header;
867 ReadBinaryWithHeader(header.data(), data.data(), dest, n);
871 std::vector<char> data;
873 ReadBinary(data.data(), dest, n);
884 const char *appended_data, *byte_order, *compressor;
885 enum AppendedDataEncoding { RAW, BASE64 };
886 map<string,BufferReaderBase*> type_map;
887 AppendedDataEncoding encoding;
893 XMLDataReader(
const XMLElement *vtk,
const XMLElement *vtu)
896 BufferReaderBase::HeaderType htype;
899 htype = BufferReaderBase::UINT64_HEADER;
903 htype = BufferReaderBase::UINT32_HEADER;
907 byte_order = vtk->Attribute(
"byte_order");
911 compressor = vtk->Attribute(
"compressor");
912 bool compressed = (compressor != NULL);
915 appended_data = NULL;
916 for (
const XMLElement *xml_elem = vtu->NextSiblingElement();
918 xml_elem = xml_elem->NextSiblingElement())
922 const char *encoding_str = xml_elem->Attribute(
"encoding");
925 appended_data = xml_elem->GetAppendedData();
930 appended_data = xml_elem->GetText();
933 MFEM_VERIFY(appended_data != NULL,
"Invalid AppendedData");
935 bool found_leading_underscore =
false;
936 while (*appended_data)
939 if (*appended_data ==
'_')
941 found_leading_underscore =
true;
946 MFEM_VERIFY(found_leading_underscore,
"Invalid AppendedData");
951 type_map[
"Int8"] =
new BufferReader<int, int8_t>(compressed, htype);
952 type_map[
"Int16"] =
new BufferReader<int, int16_t>(compressed, htype);
953 type_map[
"Int32"] =
new BufferReader<int, int32_t>(compressed, htype);
954 type_map[
"Int64"] =
new BufferReader<int, int64_t>(compressed, htype);
955 type_map[
"UInt8"] =
new BufferReader<int, uint8_t>(compressed, htype);
956 type_map[
"UInt16"] =
new BufferReader<int, uint16_t>(compressed, htype);
957 type_map[
"UInt32"] =
new BufferReader<int, uint32_t>(compressed, htype);
958 type_map[
"UInt64"] =
new BufferReader<int, uint64_t>(compressed, htype);
959 type_map[
"Float32"] =
new BufferReader<double, float>(compressed, htype);
960 type_map[
"Float64"] =
new BufferReader<double, double>(compressed, htype);
966 template <
typename T>
967 void Read(
const XMLElement *xml_elem, T *dest,
int n)
969 static const char *erstr =
"Error reading XML DataArray";
970 MFEM_VERIFY(
StringCompare(xml_elem->Name(),
"DataArray"), erstr);
971 const char *format = xml_elem->Attribute(
"format");
974 const char *txt = xml_elem->GetText();
975 MFEM_VERIFY(txt != NULL, erstr);
976 std::istringstream data_stream(txt);
977 for (
int i=0; i<n; ++i) { data_stream >> dest[i]; }
981 VerifyBinaryOptions();
982 int offset = xml_elem->IntAttribute(
"offset");
983 const char *type = xml_elem->Attribute(
"type");
984 MFEM_VERIFY(type != NULL, erstr);
985 BufferReaderBase *reader = type_map[type];
986 MFEM_VERIFY(reader != NULL, erstr);
987 MFEM_VERIFY(appended_data != NULL,
"No AppendedData found");
990 reader->ReadBinary(appended_data + offset, dest, n);
994 reader->ReadBase64(appended_data + offset, dest, n);
999 VerifyBinaryOptions();
1000 const char *txt = xml_elem->GetText();
1001 MFEM_VERIFY(txt != NULL, erstr);
1002 const char *type = xml_elem->Attribute(
"type");
1003 if (type == NULL) { MFEM_ABORT(erstr); }
1004 BufferReaderBase *reader = type_map[type];
1005 if (reader == NULL) { MFEM_ABORT(erstr); }
1006 reader->ReadBase64(txt, dest, n);
1010 MFEM_ABORT(
"Invalid XML VTK DataArray format");
1018 void VerifyByteOrder()
const
1023 MFEM_ABORT(
"Converting between different byte orders is unsupported.");
1030 void VerifyCompressor()
const
1032 if (compressor && !
StringCompare(compressor,
"vtkZLibDataCompressor"))
1034 MFEM_ABORT(
"Unsupported compressor. Only zlib is supported.")
1036#ifndef MFEM_USE_ZLIB
1037 MFEM_VERIFY(compressor == NULL,
"MFEM must be compiled with zlib enabled "
1038 "to support reading compressed data.");
1044 void VerifyBinaryOptions()
const
1052 for (
auto &x : type_map) {
delete x.second; }
1059 bool &finalize_topo,
const std::string &xml_prefix)
1061 using namespace vtk_xml;
1063 static const char *erstr =
"XML parsing error";
1066 std::vector<char> buf(xml_prefix.begin(), xml_prefix.end());
1067 std::istreambuf_iterator<char> eos;
1068 buf.insert(buf.end(), std::istreambuf_iterator<char>(input), eos);
1069 buf.push_back(
'\0');
1072 xml.Parse(buf.data(), buf.size());
1073 if (xml.ErrorID() != XML_SUCCESS)
1075 MFEM_ABORT(
"Error parsing XML VTK file.\n" << xml.ErrorStr());
1078 const XMLElement *vtkfile = xml.FirstChildElement();
1079 MFEM_VERIFY(vtkfile, erstr);
1080 MFEM_VERIFY(StringCompare(vtkfile->Name(),
"VTKFile"), erstr);
1081 const XMLElement *vtu = vtkfile->FirstChildElement();
1082 MFEM_VERIFY(vtu, erstr);
1083 MFEM_VERIFY(StringCompare(vtu->Name(),
"UnstructuredGrid"), erstr);
1085 XMLDataReader data_reader(vtkfile, vtu);
1088 const XMLElement *piece = vtu->FirstChildElement();
1089 MFEM_VERIFY(StringCompare(piece->Name(),
"Piece"), erstr);
1090 MFEM_VERIFY(piece->NextSiblingElement() == NULL,
1091 "XML VTK meshes with more than one Piece are not supported");
1092 int npts = piece->IntAttribute(
"NumberOfPoints");
1093 int ncells = piece->IntAttribute(
"NumberOfCells");
1097 const XMLElement *pts_xml;
1098 for (pts_xml = piece->FirstChildElement();
1100 pts_xml = pts_xml->NextSiblingElement())
1102 if (StringCompare(pts_xml->Name(),
"Points"))
1104 const XMLElement *pts_data = pts_xml->FirstChildElement();
1105 MFEM_VERIFY(pts_data->IntAttribute(
"NumberOfComponents") == 3,
1106 "XML VTK Points DataArray must have 3 components");
1107 data_reader.Read(pts_data, points.
GetData(), points.
Size());
1111 if (pts_xml == NULL) { MFEM_ABORT(erstr); }
1114 Array<int> cell_data, cell_offsets(ncells), cell_types(ncells);
1115 const XMLElement *cells_xml;
1116 for (cells_xml = piece->FirstChildElement();
1118 cells_xml = cells_xml->NextSiblingElement())
1120 if (StringCompare(cells_xml->Name(),
"Cells"))
1122 const XMLElement *cell_data_xml = NULL;
1123 for (
const XMLElement *data_xml = cells_xml->FirstChildElement();
1125 data_xml = data_xml->NextSiblingElement())
1127 const char *data_name = data_xml->Attribute(
"Name");
1128 if (StringCompare(data_name,
"offsets"))
1130 data_reader.Read(data_xml, cell_offsets.GetData(), ncells);
1132 else if (StringCompare(data_name,
"types"))
1134 data_reader.Read(data_xml, cell_types.
GetData(), ncells);
1136 else if (StringCompare(data_name,
"connectivity"))
1142 cell_data_xml = data_xml;
1145 MFEM_VERIFY(cell_data_xml != NULL, erstr);
1146 int cell_data_size = cell_offsets.Last();
1147 cell_data.
SetSize(cell_data_size);
1148 data_reader.Read(cell_data_xml, cell_data.
GetData(), cell_data_size);
1152 if (cells_xml == NULL) { MFEM_ABORT(erstr); }
1156 for (
const XMLElement *cell_data_xml = piece->FirstChildElement();
1157 cell_data_xml != NULL;
1158 cell_data_xml = cell_data_xml->NextSiblingElement())
1160 if (StringCompare(cell_data_xml->Name(),
"CellData")
1161 && StringCompare(cell_data_xml->Attribute(
"Scalars"),
"material"))
1163 const XMLElement *data_xml = cell_data_xml->FirstChildElement();
1164 if (data_xml != NULL && StringCompare(data_xml->Name(),
"DataArray"))
1166 cell_attributes.
SetSize(ncells);
1167 data_reader.Read(data_xml, cell_attributes.
GetData(), ncells);
1172 CreateVTKMesh(points, cell_data, cell_offsets, cell_types, cell_attributes,
1173 curved, read_gf, finalize_topo);
1514 input >> version >> binary >> dsize;
1517 MFEM_ABORT(
"Gmsh file version < 2.2");
1519 if (dsize !=
sizeof(
double))
1521 MFEM_ABORT(
"Gmsh file : dsize != sizeof(double)");
1523 getline(input, buff);
1528 input.read(
reinterpret_cast<char*
>(&one),
sizeof(one));
1531 MFEM_ABORT(
"Gmsh file : wrong binary format");
1538 map<int, int> vertices_map;
1544 map<int,map<int,std::string> > phys_names_by_dim;
1564 bool periodic =
false;
1571 while (input >> buff)
1573 if (buff ==
"$Nodes")
1576 getline(input, buff);
1579 const int gmsh_dim = 3;
1585 input.read(
reinterpret_cast<char*
>(&serial_number),
sizeof(
int));
1586 input.read(
reinterpret_cast<char*
>(coord), gmsh_dim*
sizeof(
double));
1590 input >> serial_number;
1591 for (
int ci = 0; ci < gmsh_dim; ++ci)
1597 vertices_map[serial_number] = ver;
1599 for (
int ci = 0; ci < gmsh_dim; ++ci)
1601 bb_min[ci] = (ver == 0) ? coord[ci] :
1602 std::min(
bb_min[ci], coord[ci]);
1603 bb_max[ci] = (ver == 0) ? coord[ci] :
1604 std::max(
bb_max[ci], coord[ci]);
1622 MFEM_ABORT(
"Gmsh file : vertices indices are not unique");
1625 else if (buff ==
"$Elements")
1627 int num_of_all_elements;
1628 input >> num_of_all_elements;
1630 getline(input, buff);
1633 int type_of_element;
1641 int nodes_of_gmsh_element[] =
1790 -1,-1,-1,-1,-1,-1,-1,
1806 -1,-1,-1,-1,-1,-1,-1,
1851 int lin3[] = {0,2,1};
1852 int lin4[] = {0,2,3,1};
1853 int tri6[] = {0,3,1,5,4,2};
1854 int tri10[] = {0,3,4,1,8,9,5,7,6,2};
1855 int quad9[] = {0,4,1,7,8,5,3,6,2};
1856 int quad16[] = {0,4,5,1,11,12,13,6,
1859 int tet10[] {0,4,1,6,5,2,7,9,8,3};
1860 int tet20[] = {0,4,5,1,9,16,6,8,7,2,
1861 11,17,15,18,19,13,10,14,12,3
1863 int hex27[] {0,8,1,9,20,11,3,13,2,
1864 10,21,12,22,26,23,15,24,14,
1865 4,16,5,17,25,18,7,19,6
1867 int hex64[] {0,8,9,1,10,32,35,14,
1868 11,33,34,15,3,19,18,2,
1869 12,36,37,16,40,56,57,44,
1870 43,59,58,45,22,49,48,20,
1871 13,39,38,17,41,60,61,47,
1872 42,63,62,46,23,50,51,21,
1873 4,24,25,5,26,52,53,28,
1874 27,55,54,29,7,31,30,6
1877 int wdg18[] = {0,6,1,7,9,2,8,15,10,
1878 16,17,11,3,12,4,13,14,5
1880 int wdg40[] = {0,6,7,1,8,24,12,9,13,2,
1881 10,26,27,14,30,38,34,33,35,16,
1882 11,29,28,15,31,39,37,32,36,17,
1883 3,18,19,4,20,25,22,21,23,5
1886 int pyr14[] = {0,5,1,6,13,8,3,
1889 int pyr30[] = {0,5,6,1,7,25,28,11,8,26,
1890 27,12,3,16,15,2,9,21,13,22,
1891 29,23,19,24,17,10,14,20,18,4
1894 vector<Element*> elements_0D, elements_1D, elements_2D, elements_3D;
1895 elements_0D.reserve(num_of_all_elements);
1896 elements_1D.reserve(num_of_all_elements);
1897 elements_2D.reserve(num_of_all_elements);
1898 elements_3D.reserve(num_of_all_elements);
1901 vector<Array<int>*> ho_verts_1D, ho_verts_2D, ho_verts_3D;
1902 ho_verts_1D.reserve(num_of_all_elements);
1903 ho_verts_2D.reserve(num_of_all_elements);
1904 ho_verts_3D.reserve(num_of_all_elements);
1907 vector<int> ho_el_order_1D, ho_el_order_2D, ho_el_order_3D;
1908 ho_el_order_1D.reserve(num_of_all_elements);
1909 ho_el_order_2D.reserve(num_of_all_elements);
1910 ho_el_order_3D.reserve(num_of_all_elements);
1922 ho_lin[2] = lin3; ho_lin[3] = lin4;
1923 ho_tri[2] = tri6; ho_tri[3] = tri10;
1924 ho_sqr[2] = quad9; ho_sqr[3] = quad16;
1925 ho_tet[2] = tet10; ho_tet[3] = tet20;
1926 ho_hex[2] = hex27; ho_hex[3] = hex64;
1927 ho_wdg[2] = wdg18; ho_wdg[3] = wdg40;
1928 ho_pyr[2] = pyr14; ho_pyr[3] = pyr30;
1930 bool has_nonpositive_phys_domain =
false;
1931 bool has_positive_phys_domain =
false;
1935 int n_elem_part = 0;
1936 const int header_size = 3;
1939 int header[header_size];
1940 int n_elem_one_type;
1942 while (n_elem_part < num_of_all_elements)
1944 input.read(
reinterpret_cast<char*
>(header),
1945 header_size*
sizeof(
int));
1946 type_of_element = header[0];
1947 n_elem_one_type = header[1];
1950 n_elem_part += n_elem_one_type;
1952 const int n_elem_nodes = nodes_of_gmsh_element[type_of_element-1];
1953 vector<int> data(1+n_tags+n_elem_nodes);
1954 for (
int el = 0; el < n_elem_one_type; ++el)
1956 input.read(
reinterpret_cast<char*
>(&data[0]),
1957 data.size()*
sizeof(
int));
1959 serial_number = data[dd++];
1962 phys_domain = (n_tags > 0) ? data[dd++] : 1;
1965 elem_domain = (n_tags > 1) ? data[dd++] : 0;
1968 n_partitions = (n_tags > 2) ? data[dd++] : 0;
1971 vector<int> vert_indices(n_elem_nodes);
1972 for (
int vi = 0; vi < n_elem_nodes; ++vi)
1974 map<int, int>::const_iterator it =
1975 vertices_map.find(data[1+n_tags+vi]);
1976 if (it == vertices_map.end())
1978 MFEM_ABORT(
"Gmsh file : vertex index doesn't exist");
1980 vert_indices[vi] = it->second;
1988 if (phys_domain <= 0)
1990 has_nonpositive_phys_domain =
true;
1995 has_positive_phys_domain =
true;
2000 switch (type_of_element)
2013 elements_1D.push_back(
2014 new Segment(&vert_indices[0], phys_domain));
2015 if (type_of_element != 1)
2017 el_order = n_elem_nodes - 1;
2019 hov->
Append(&vert_indices[0], n_elem_nodes);
2020 ho_verts_1D.push_back(hov);
2021 ho_el_order_1D.push_back(el_order);
2027 case 21: el_order--;
2028 case 23: el_order--;
2029 case 25: el_order--;
2030 case 42: el_order--;
2031 case 43: el_order--;
2032 case 44: el_order--;
2033 case 45: el_order--;
2034 case 46: el_order--;
2036 elements_2D.push_back(
2037 new Triangle(&vert_indices[0], phys_domain));
2041 hov->
Append(&vert_indices[0], n_elem_nodes);
2042 ho_verts_2D.push_back(hov);
2043 ho_el_order_2D.push_back(el_order);
2048 case 10: el_order--;
2049 case 36: el_order--;
2050 case 37: el_order--;
2051 case 38: el_order--;
2052 case 47: el_order--;
2053 case 48: el_order--;
2054 case 49: el_order--;
2055 case 50: el_order--;
2056 case 51: el_order--;
2058 elements_2D.push_back(
2063 hov->
Append(&vert_indices[0], n_elem_nodes);
2064 ho_verts_2D.push_back(hov);
2065 ho_el_order_2D.push_back(el_order);
2070 case 11: el_order--;
2071 case 29: el_order--;
2072 case 30: el_order--;
2073 case 31: el_order--;
2074 case 71: el_order--;
2075 case 72: el_order--;
2076 case 73: el_order--;
2077 case 74: el_order--;
2078 case 75: el_order--;
2080#ifdef MFEM_USE_MEMALLOC
2081 elements_3D.push_back(
TetMemory.Alloc());
2082 elements_3D.back()->SetVertices(&vert_indices[0]);
2083 elements_3D.back()->SetAttribute(phys_domain);
2085 elements_3D.push_back(
2091 hov->
Append(&vert_indices[0], n_elem_nodes);
2092 ho_verts_3D.push_back(hov);
2093 ho_el_order_3D.push_back(el_order);
2098 case 12: el_order--;
2099 case 92: el_order--;
2100 case 93: el_order--;
2101 case 94: el_order--;
2102 case 95: el_order--;
2103 case 96: el_order--;
2104 case 97: el_order--;
2105 case 98: el_order--;
2108 elements_3D.push_back(
2109 new Hexahedron(&vert_indices[0], phys_domain));
2113 hov->
Append(&vert_indices[0], n_elem_nodes);
2114 ho_verts_3D.push_back(hov);
2115 ho_el_order_3D.push_back(el_order);
2120 case 13: el_order--;
2121 case 90: el_order--;
2122 case 91: el_order--;
2123 case 106: el_order--;
2124 case 107: el_order--;
2125 case 108: el_order--;
2126 case 109: el_order--;
2127 case 110: el_order--;
2130 elements_3D.push_back(
2131 new Wedge(&vert_indices[0], phys_domain));
2135 hov->
Append(&vert_indices[0], n_elem_nodes);
2136 ho_verts_3D.push_back(hov);
2137 ho_el_order_3D.push_back(el_order);
2142 case 14: el_order--;
2143 case 118: el_order--;
2144 case 119: el_order--;
2145 case 120: el_order--;
2146 case 121: el_order--;
2147 case 122: el_order--;
2148 case 123: el_order--;
2149 case 124: el_order--;
2152 elements_3D.push_back(
2153 new Pyramid(&vert_indices[0], phys_domain));
2157 hov->
Append(&vert_indices[0], n_elem_nodes);
2158 ho_verts_3D.push_back(hov);
2159 ho_el_order_3D.push_back(el_order);
2165 elements_0D.push_back(
2166 new Point(&vert_indices[0], phys_domain));
2170 MFEM_WARNING(
"Unsupported Gmsh element type.");
2179 for (
int el = 0; el < num_of_all_elements; ++el)
2181 input >> serial_number >> type_of_element >> n_tags;
2182 vector<int> data(n_tags);
2183 for (
int i = 0; i < n_tags; ++i) { input >> data[i]; }
2186 phys_domain = (n_tags > 0) ? data[0] : 1;
2189 elem_domain = (n_tags > 1) ? data[1] : 0;
2192 n_partitions = (n_tags > 2) ? data[2] : 0;
2195 const int n_elem_nodes = nodes_of_gmsh_element[type_of_element-1];
2196 vector<int> vert_indices(n_elem_nodes);
2198 for (
int vi = 0; vi < n_elem_nodes; ++vi)
2201 map<int, int>::const_iterator it = vertices_map.find(
index);
2202 if (it == vertices_map.end())
2204 MFEM_ABORT(
"Gmsh file : vertex index doesn't exist");
2206 vert_indices[vi] = it->second;
2214 if (phys_domain <= 0)
2216 has_nonpositive_phys_domain =
true;
2221 has_positive_phys_domain =
true;
2226 switch (type_of_element)
2239 elements_1D.push_back(
2240 new Segment(&vert_indices[0], phys_domain));
2241 if (type_of_element != 1)
2244 hov->
Append(&vert_indices[0], n_elem_nodes);
2245 ho_verts_1D.push_back(hov);
2246 el_order = n_elem_nodes - 1;
2247 ho_el_order_1D.push_back(el_order);
2253 case 21: el_order--;
2254 case 23: el_order--;
2255 case 25: el_order--;
2256 case 42: el_order--;
2257 case 43: el_order--;
2258 case 44: el_order--;
2259 case 45: el_order--;
2260 case 46: el_order--;
2262 elements_2D.push_back(
2263 new Triangle(&vert_indices[0], phys_domain));
2267 hov->
Append(&vert_indices[0], n_elem_nodes);
2268 ho_verts_2D.push_back(hov);
2269 ho_el_order_2D.push_back(el_order);
2274 case 10: el_order--;
2275 case 36: el_order--;
2276 case 37: el_order--;
2277 case 38: el_order--;
2278 case 47: el_order--;
2279 case 48: el_order--;
2280 case 49: el_order--;
2281 case 50: el_order--;
2282 case 51: el_order--;
2284 elements_2D.push_back(
2289 hov->
Append(&vert_indices[0], n_elem_nodes);
2290 ho_verts_2D.push_back(hov);
2291 ho_el_order_2D.push_back(el_order);
2296 case 11: el_order--;
2297 case 29: el_order--;
2298 case 30: el_order--;
2299 case 31: el_order--;
2300 case 71: el_order--;
2301 case 72: el_order--;
2302 case 73: el_order--;
2303 case 74: el_order--;
2304 case 75: el_order--;
2306#ifdef MFEM_USE_MEMALLOC
2307 elements_3D.push_back(
TetMemory.Alloc());
2308 elements_3D.back()->SetVertices(&vert_indices[0]);
2309 elements_3D.back()->SetAttribute(phys_domain);
2311 elements_3D.push_back(
2317 hov->
Append(&vert_indices[0], n_elem_nodes);
2318 ho_verts_3D.push_back(hov);
2319 ho_el_order_3D.push_back(el_order);
2324 case 12: el_order--;
2325 case 92: el_order--;
2326 case 93: el_order--;
2327 case 94: el_order--;
2328 case 95: el_order--;
2329 case 96: el_order--;
2330 case 97: el_order--;
2331 case 98: el_order--;
2334 elements_3D.push_back(
2335 new Hexahedron(&vert_indices[0], phys_domain));
2339 hov->
Append(&vert_indices[0], n_elem_nodes);
2340 ho_verts_3D.push_back(hov);
2341 ho_el_order_3D.push_back(el_order);
2346 case 13: el_order--;
2347 case 90: el_order--;
2348 case 91: el_order--;
2349 case 106: el_order--;
2350 case 107: el_order--;
2351 case 108: el_order--;
2352 case 109: el_order--;
2353 case 110: el_order--;
2356 elements_3D.push_back(
2357 new Wedge(&vert_indices[0], phys_domain));
2361 hov->
Append(&vert_indices[0], n_elem_nodes);
2362 ho_verts_3D.push_back(hov);
2363 ho_el_order_3D.push_back(el_order);
2368 case 14: el_order--;
2369 case 118: el_order--;
2370 case 119: el_order--;
2371 case 120: el_order--;
2372 case 121: el_order--;
2373 case 122: el_order--;
2374 case 123: el_order--;
2375 case 124: el_order--;
2378 elements_3D.push_back(
2379 new Pyramid(&vert_indices[0], phys_domain));
2383 hov->
Append(&vert_indices[0], n_elem_nodes);
2384 ho_verts_3D.push_back(hov);
2385 ho_el_order_3D.push_back(el_order);
2391 elements_0D.push_back(
2392 new Point(&vert_indices[0], phys_domain));
2396 MFEM_WARNING(
"Unsupported Gmsh element type.");
2403 if (has_positive_phys_domain && has_nonpositive_phys_domain)
2405 MFEM_ABORT(
"Non-positive element attribute in Gmsh mesh!\n"
2406 "By default Gmsh sets element tags (attributes)"
2407 " to '0' but MFEM requires that they be"
2408 " positive integers.\n"
2409 "Use \"Physical Curve\", \"Physical Surface\","
2410 " or \"Physical Volume\" to set tags/attributes"
2411 " for all curves, surfaces, or volumes in your"
2412 " Gmsh geometry to values which are >= 1.");
2414 else if (has_nonpositive_phys_domain)
2416 mfem::out <<
"\nGmsh reader: all element attributes were zero.\n"
2417 <<
"MFEM only supports positive element attributes.\n"
2418 <<
"Setting element attributes to 1.\n\n";
2421 if (!elements_3D.empty())
2436 for (
size_t el = 0; el < ho_el_order_3D.size(); el++)
2438 mesh_order = max(mesh_order, ho_el_order_3D[el]);
2441 for (
size_t el = 0; el < elements_1D.size(); ++el)
2443 delete elements_1D[el];
2445 for (
size_t el = 0; el < elements_0D.size(); ++el)
2447 delete elements_0D[el];
2450 else if (!elements_2D.empty())
2465 for (
size_t el = 0; el < ho_el_order_2D.size(); el++)
2467 mesh_order = max(mesh_order, ho_el_order_2D[el]);
2470 for (
size_t el = 0; el < elements_0D.size(); ++el)
2472 delete elements_0D[el];
2475 else if (!elements_1D.empty())
2490 for (
size_t el = 0; el < ho_el_order_1D.size(); el++)
2492 mesh_order = max(mesh_order, ho_el_order_1D[el]);
2497 MFEM_ABORT(
"Gmsh file : no elements found");
2527 const int * vm = NULL;
2532 ho_verts = ho_verts_1D[el];
2533 el_order = ho_el_order_1D[el];
2534 if (!ho_lin[el_order])
2536 ho_lin[el_order] =
new int[ho_verts->
Size()];
2539 vm = ho_lin[el_order];
2542 ho_verts = ho_verts_2D[el];
2543 el_order = ho_el_order_2D[el];
2544 if (!ho_tri[el_order])
2546 ho_tri[el_order] =
new int[ho_verts->
Size()];
2549 vm = ho_tri[el_order];
2552 ho_verts = ho_verts_2D[el];
2553 el_order = ho_el_order_2D[el];
2554 if (!ho_sqr[el_order])
2556 ho_sqr[el_order] =
new int[ho_verts->
Size()];
2559 vm = ho_sqr[el_order];
2562 ho_verts = ho_verts_3D[el];
2563 el_order = ho_el_order_3D[el];
2564 if (!ho_tet[el_order])
2566 ho_tet[el_order] =
new int[ho_verts->
Size()];
2569 vm = ho_tet[el_order];
2572 ho_verts = ho_verts_3D[el];
2573 el_order = ho_el_order_3D[el];
2574 if (!ho_hex[el_order])
2576 ho_hex[el_order] =
new int[ho_verts->
Size()];
2579 vm = ho_hex[el_order];
2582 ho_verts = ho_verts_3D[el];
2583 el_order = ho_el_order_3D[el];
2584 if (!ho_wdg[el_order])
2586 ho_wdg[el_order] =
new int[ho_verts->
Size()];
2589 vm = ho_wdg[el_order];
2592 ho_verts = ho_verts_3D[el];
2593 el_order = ho_el_order_3D[el];
2594 if (!ho_pyr[el_order])
2596 ho_pyr[el_order] =
new int[ho_verts->
Size()];
2599 vm = ho_pyr[el_order];
2602 MFEM_WARNING(
"Unsupported Gmsh element type.");
2605 int nv = (ho_verts) ? ho_verts->
Size() : 0;
2607 for (
int v = 0; v<nv; v++)
2612 Nodes_gf(
spaceDim * (o + v) + d) = c[d];
2620 for (
size_t el=0; el<ho_verts_1D.size(); el++)
2622 delete ho_verts_1D[el];
2624 for (
size_t el=0; el<ho_verts_2D.size(); el++)
2626 delete ho_verts_2D[el];
2628 for (
size_t el=0; el<ho_verts_3D.size(); el++)
2630 delete ho_verts_3D[el];
2634 for (
int ord=4; ord<ho_lin.
Size(); ord++)
2636 if (ho_lin[ord] != NULL) {
delete [] ho_lin[ord]; }
2638 for (
int ord=4; ord<ho_tri.
Size(); ord++)
2640 if (ho_tri[ord] != NULL) {
delete [] ho_tri[ord]; }
2642 for (
int ord=4; ord<ho_sqr.
Size(); ord++)
2644 if (ho_sqr[ord] != NULL) {
delete [] ho_sqr[ord]; }
2646 for (
int ord=4; ord<ho_tet.
Size(); ord++)
2648 if (ho_tet[ord] != NULL) {
delete [] ho_tet[ord]; }
2650 for (
int ord=4; ord<ho_hex.
Size(); ord++)
2652 if (ho_hex[ord] != NULL) {
delete [] ho_hex[ord]; }
2654 for (
int ord=4; ord<ho_wdg.
Size(); ord++)
2656 if (ho_wdg[ord] != NULL) {
delete [] ho_wdg[ord]; }
2658 for (
int ord=4; ord<ho_pyr.
Size(); ord++)
2660 if (ho_pyr[ord] != NULL) {
delete [] ho_pyr[ord]; }
2666 MFEM_CONTRACT_VAR(n_partitions);
2667 MFEM_CONTRACT_VAR(elem_domain);
2670 else if (buff ==
"$PhysicalNames")
2676 for (
int i=0; i < num_names; i++)
2678 input >> mdim >> num;
2679 getline(input, name);
2682 while (!name.empty() &&
2683 (*name.begin() ==
' ' || *name.begin() ==
'\t'))
2687 while (!name.empty() &&
2688 (*name.rbegin() ==
' ' || *name.rbegin() ==
'\t' ||
2689 *name.rbegin() ==
'\n' || *name.rbegin() ==
'\r'))
2690 { name.resize(name.length()-1);}
2693 if ( (*name.begin() ==
'"' || *name.begin() ==
'\'') &&
2694 (*name.rbegin() ==
'"' || *name.rbegin() ==
'\''))
2696 name = name.substr(1,name.length()-2);
2699 phys_names_by_dim[mdim][num] = name;
2702 else if (buff ==
"$Periodic")
2709 for (
int i = 0; i < v2v.
Size(); i++)
2715 input >> num_per_ent;
2716 getline(input, buff);
2717 for (
int i = 0; i < num_per_ent; i++)
2719 getline(input, buff);
2720 getline(input, buff);
2721 if (!strncmp(buff.c_str(),
"Affine", 6))
2727 num_nodes = atoi(buff.c_str());
2729 for (
int j=0; j<num_nodes; j++)
2732 input >> slave >> master;
2733 v2v[slave - 1] = master - 1;
2735 getline(input, buff);
2742 for (
int slave = 0; slave < v2v.
Size(); slave++)
2744 int master = v2v[slave];
2745 if (master != slave)
2748 while (v2v[master] != master && master != slave)
2750 master = v2v[master];
2752 if (master == slave)
2761 v2v[slave] = master;
2767 if (mesh_order == 1)
2776 for (
int i = 0; i < this->
GetNE(); i++)
2781 for (
int j = 0; j < nv; j++)
2788 for (
int i = 0; i < this->
GetNBE(); i++)
2793 for (
int j = 0; j < nv; j++)
2802 if (phys_names_by_dim.size() > 0)
2805 for (
auto const &bdr_attr : phys_names_by_dim[
Dim-1])
2815 for (
auto const &attr : phys_names_by_dim[
Dim])
2851 1,2,3,4,5,7,8,6,9,10
2857 1,2,3,4,5,6,7,8,9,10,11,
2860 12,17,18,19,20,13,14,15,
2863 16,22,26,25,27,24,23,21
2934 {1,2,6,5,9,14,17,13,26},
2935 {2,3,7,6,10,15,18,14,25},
2936 {4,3,7,8,11,15,19,16,27},
2937 {1,4,8,5,12,16,20,13,24},
2938 {1,4,3,2,12,11,10,9,22},
2939 {5,8,7,6,20,19,18,17,23}
2966static void HandleNetCDFError(
const int error)
2968 if (error == NC_NOERR) {
return; }
2970 MFEM_ABORT(
"Fatal NetCDF error: " << nc_strerror(error));
2974static void ReadCubitNodeCoordinates(
const int netcdf_descriptor,
2979 if (!coordx || !coordy) {
return; }
2981 int variable_id, netcdf_status;
2983 netcdf_status = nc_inq_varid(netcdf_descriptor,
"coordx", &variable_id);
2984 netcdf_status = nc_get_var_double(netcdf_descriptor, variable_id, coordx);
2986 netcdf_status = nc_inq_varid(netcdf_descriptor,
"coordy", &variable_id);
2987 netcdf_status = nc_get_var_double(netcdf_descriptor, variable_id, coordy);
2991 netcdf_status = nc_inq_varid(netcdf_descriptor,
"coordz", &variable_id);
2992 netcdf_status = nc_get_var_double(netcdf_descriptor, variable_id, coordz);
2995 if (netcdf_status != NC_NOERR) { HandleNetCDFError(netcdf_status); }
2999static void ReadCubitNumElementsInBlock(
const int netcdf_descriptor,
3000 const int num_element_blocks,
3001 std::vector<std::size_t> &num_elements_for_block)
3003 int netcdf_status, variable_id;
3006 const int buffer_size = NC_MAX_NAME + 1;
3008 char string_buffer[buffer_size];
3010 for (
int iblock = 0; iblock < num_element_blocks; iblock++)
3013 snprintf(string_buffer, buffer_size,
"num_el_in_blk%d", iblock + 1);
3016 netcdf_status = nc_inq_dimid(netcdf_descriptor, string_buffer, &variable_id);
3019 netcdf_status = nc_inq_dim(netcdf_descriptor, variable_id, string_buffer,
3020 &num_elements_for_block[iblock]);
3022 if (netcdf_status != NC_NOERR) {
break; }
3025 if (netcdf_status != NC_NOERR) { HandleNetCDFError(netcdf_status); }
3029static void ReadCubitNumNodesPerElement(
const int netcdf_descriptor,
3030 const int num_element_blocks,
3031 size_t &num_nodes_per_element)
3033 int netcdf_status, variable_id;
3036 const int buffer_size = NC_MAX_NAME + 1;
3038 char string_buffer[buffer_size];
3040 size_t new_num_nodes_per_element, last_num_nodes_per_element;
3042 bool different_element_types_detected =
false;
3044 for (
int iblock = 0; iblock < num_element_blocks; iblock++)
3047 snprintf(string_buffer, buffer_size,
"num_nod_per_el%d", iblock + 1);
3050 netcdf_status = nc_inq_dimid(netcdf_descriptor, string_buffer, &variable_id);
3053 netcdf_status = nc_inq_dim(netcdf_descriptor, variable_id, string_buffer,
3054 &new_num_nodes_per_element);
3055 if (netcdf_status != NC_NOERR) {
break; }
3058 if (iblock > 0 && new_num_nodes_per_element != last_num_nodes_per_element)
3060 different_element_types_detected =
true;
3064 last_num_nodes_per_element = new_num_nodes_per_element;
3067 if (netcdf_status != NC_NOERR)
3069 HandleNetCDFError(netcdf_status);
3071 else if (different_element_types_detected)
3073 MFEM_ABORT(
"Element blocks of different types are not supported!\n");
3077 num_nodes_per_element = new_num_nodes_per_element;
3081static void ReadCubitDimensions(
const int netcdf_descriptor,
3086 size_t &num_side_sets)
3088 int netcdf_status, variable_id;
3090 const int buffer_size = NC_MAX_NAME + 1;
3091 char string_buffer[buffer_size];
3093 netcdf_status = nc_inq_dimid(netcdf_descriptor,
"num_dim", &variable_id);
3094 netcdf_status = nc_inq_dim(netcdf_descriptor, variable_id, string_buffer,
3096 if (netcdf_status != NC_NOERR) { HandleNetCDFError(netcdf_status); }
3098 netcdf_status = nc_inq_dimid(netcdf_descriptor,
"num_nodes", &variable_id);
3099 netcdf_status = nc_inq_dim(netcdf_descriptor, variable_id, string_buffer,
3101 if (netcdf_status != NC_NOERR) { HandleNetCDFError(netcdf_status); }
3103 netcdf_status = nc_inq_dimid(netcdf_descriptor,
"num_elem", &variable_id);
3104 netcdf_status = nc_inq_dim(netcdf_descriptor, variable_id, string_buffer,
3106 if (netcdf_status != NC_NOERR) { HandleNetCDFError(netcdf_status); }
3108 netcdf_status = nc_inq_dimid(netcdf_descriptor,
"num_el_blk", &variable_id);
3109 netcdf_status = nc_inq_dim(netcdf_descriptor, variable_id, string_buffer,
3111 if (netcdf_status != NC_NOERR) { HandleNetCDFError(netcdf_status); }
3113 netcdf_status = nc_inq_dimid(netcdf_descriptor,
"num_side_sets", &variable_id);
3114 netcdf_status = nc_inq_dim(netcdf_descriptor, variable_id, string_buffer,
3118 if (netcdf_status != NC_NOERR)
3125static void ReadCubitBoundaries(
const int netcdf_descriptor,
3126 const int num_boundaries,
3127 vector<size_t> &num_boundary_elements,
3128 vector<vector<int>> &boundary_elements,
3129 vector<vector<int>> &boundary_sides)
3131 int netcdf_status, variable_id;
3133 const int buffer_size = NC_MAX_NAME + 1;
3134 char string_buffer[buffer_size];
3136 for (
int iboundary = 0; iboundary < num_boundaries; iboundary++)
3139 size_t num_sides = 0;
3141 snprintf(string_buffer, buffer_size,
"num_side_ss%d", iboundary + 1);
3143 netcdf_status = nc_inq_dimid(netcdf_descriptor, string_buffer, &variable_id);
3144 netcdf_status = nc_inq_dim(netcdf_descriptor, variable_id, string_buffer,
3147 if (netcdf_status != NC_NOERR) {
break; }
3149 num_boundary_elements[iboundary] = num_sides;
3152 boundary_elements[iboundary].resize(num_sides);
3153 boundary_sides[iboundary].resize(num_sides);
3156 snprintf(string_buffer, buffer_size,
"elem_ss%d", iboundary + 1);
3158 netcdf_status = nc_inq_varid(netcdf_descriptor, string_buffer, &variable_id);
3159 netcdf_status = nc_get_var_int(netcdf_descriptor, variable_id,
3160 boundary_elements[iboundary].data());
3162 if (netcdf_status != NC_NOERR) {
break; }
3165 snprintf(string_buffer, buffer_size,
"side_ss%d", iboundary + 1);
3167 netcdf_status = nc_inq_varid(netcdf_descriptor, string_buffer, &variable_id);
3168 netcdf_status = nc_get_var_int(netcdf_descriptor, variable_id,
3169 boundary_sides[iboundary].data());
3171 if (netcdf_status != NC_NOERR) {
break; }
3174 if (netcdf_status != NC_NOERR) { HandleNetCDFError(netcdf_status); }
3178static void ReadCubitElementBlocks(
const int netcdf_descriptor,
3179 const int num_element_blocks,
const int num_nodes_per_element,
3180 const vector<size_t> &num_elements_for_block,
3181 vector<vector<int>> &block_elements)
3183 int netcdf_status, variable_id;
3185 const int buffer_size = NC_MAX_NAME + 1;
3186 char string_buffer[buffer_size];
3188 for (
int iblock = 0; iblock < num_element_blocks; iblock++)
3190 block_elements[iblock].resize(
3191 num_elements_for_block[iblock]*num_nodes_per_element);
3194 snprintf(string_buffer, buffer_size,
"connect%d", iblock + 1);
3197 netcdf_status = nc_inq_varid(netcdf_descriptor, string_buffer, &variable_id);
3198 netcdf_status = nc_get_var_int(netcdf_descriptor, variable_id,
3199 block_elements[iblock].data());
3201 if (netcdf_status != NC_NOERR) {
break; }
3204 if (netcdf_status != NC_NOERR) { HandleNetCDFError(netcdf_status); }
3208static void SetCubitElementAndFaceType2D(
const int num_nodes_per_element,
3211 int & num_element_linear_nodes)
3213 switch (num_nodes_per_element)
3219 num_element_linear_nodes = 3;
3226 num_element_linear_nodes = 3;
3233 num_element_linear_nodes = 4;
3240 num_element_linear_nodes = 4;
3245 MFEM_ABORT(
"Don't know what to do with a " << num_nodes_per_element <<
3246 " node 2D element\n");
3253static void SetCubitElementAndFaceType3D(
const int num_nodes_per_element,
3256 int & num_element_linear_nodes)
3258 switch (num_nodes_per_element)
3264 num_element_linear_nodes = 4;
3271 num_element_linear_nodes = 4;
3278 num_element_linear_nodes = 8;
3285 num_element_linear_nodes = 8;
3290 MFEM_ABORT(
"Don't know what to do with a " << num_nodes_per_element <<
3291 " node 3D element\n");
3298static void SetCubitElementAndFaceType(
const int num_dimensions,
3299 const int num_nodes_per_element,
3302 int & num_element_linear_nodes)
3304 switch (num_dimensions)
3308 SetCubitElementAndFaceType2D(num_nodes_per_element, cubit_element_type,
3309 cubit_face_type, num_element_linear_nodes);
3314 SetCubitElementAndFaceType3D(num_nodes_per_element, cubit_element_type,
3315 cubit_face_type, num_element_linear_nodes);
3320 MFEM_ABORT(
"Invalid dimension: " << num_dimensions);
3327static void SetCubitFaceInfo(
const CubitFaceType cubit_face_type,
3328 int & num_face_nodes,
3329 int & num_face_linear_nodes)
3331 switch (cubit_face_type)
3336 num_face_linear_nodes = 2;
3342 num_face_linear_nodes = 2;
3348 num_face_linear_nodes = 3;
3354 num_face_linear_nodes = 3;
3360 num_face_linear_nodes = 4;
3366 num_face_linear_nodes = 4;
3371 MFEM_ABORT(
"Unsupported cubit face type encountered.");
3377static int GetOrderFromCubitElementType(
const CubitElementType element_type)
3381 switch (element_type)
3401 MFEM_ABORT(
"Unsupported cubit element type encountered.");
3410static int GetCubitBlockIndexForElement(
const int global_element_index,
3411 const int num_element_blocks,
3412 const int *start_of_block)
3416 while (iblock < num_element_blocks &&
3417 global_element_index >= start_of_block[iblock + 1])
3422 if (iblock >= num_element_blocks)
3424 MFEM_ABORT(
"Element is not part of any blocks.");
3431 const int attribute)
3442 const int cubit_element_type,
3443 const int *vertex_ids,
3446 switch (cubit_element_type)
3461 MFEM_ABORT(
"Unsupported cubit element type encountered.");
3469 const int cubit_face_type,
3470 const int *vertex_ids,
3471 const int sideset_id)
3473 switch (cubit_face_type)
3485 MFEM_ABORT(
"Unsupported cubit face type encountered.");
3494 const int cubit_element_type,
3495 const int num_element_blocks,
3496 const int num_nodes_per_element,
3497 const int *start_of_block,
3498 const double *coordx,
3499 const double *coordy,
3500 const double *coordz,
3501 const vector<vector<int>> &element_blocks)
3503 int *mfem_to_genesis_map =
nullptr;
3505 switch (cubit_element_type)
3520 MFEM_ABORT(
"Something went wrong. Linear elements detected when order is 2.");
3534 for (
int ielement = 0; ielement < mesh.
GetNE(); ielement++)
3543 const int iblock = GetCubitBlockIndexForElement(ielement,
3548 const int element_offset = ielement - start_of_block[iblock];
3549 const int node_offset = element_offset * num_nodes_per_element;
3551 for (
int jnode = 0; jnode < dofs.
Size(); jnode++)
3553 const int node_index = element_blocks[iblock][node_offset +
3554 mfem_to_genesis_map[jnode] - 1] - 1;
3556 (*Nodes)(vdofs[jnode]) = coordx[node_index];
3557 (*Nodes)(vdofs[jnode] + 1) = coordy[node_index];
3561 (*Nodes)(vdofs[jnode] + 2) = coordz[node_index];
3572 using namespace cubit;
3581 int netcdf_status, netcdf_descriptor;
3583 netcdf_status = nc_open(filename.c_str(), NC_NOWRITE, &netcdf_descriptor);
3584 if (netcdf_status != NC_NOERR) { HandleNetCDFError(netcdf_status); }
3587 size_t num_dimensions, num_nodes, num_elements, num_element_blocks,
3590 ReadCubitDimensions(netcdf_descriptor, num_dimensions, num_nodes, num_elements,
3591 num_element_blocks, num_boundaries);
3593 Dim = num_dimensions;
3596 std::vector<std::size_t> num_elements_for_block(num_element_blocks);
3598 ReadCubitNumElementsInBlock(netcdf_descriptor, num_element_blocks,
3599 num_elements_for_block);
3603 size_t num_nodes_per_element;
3605 ReadCubitNumNodesPerElement(netcdf_descriptor, num_element_blocks,
3606 num_nodes_per_element);
3609 CubitElementType cubit_element_type;
3610 CubitFaceType cubit_face_type;
3611 int num_element_linear_nodes;
3613 SetCubitElementAndFaceType(num_dimensions, num_nodes_per_element,
3615 cubit_face_type, num_element_linear_nodes);
3618 int num_face_nodes, num_face_linear_nodes;
3620 SetCubitFaceInfo(cubit_face_type, num_face_nodes, num_face_linear_nodes);
3623 vector<size_t> num_boundary_elements(num_boundaries);
3625 vector<vector<int>> boundary_elements(num_boundaries);
3626 vector<vector<int>> boundary_sides(num_boundaries);
3628 ReadCubitBoundaries(netcdf_descriptor, num_boundaries, num_boundary_elements,
3629 boundary_elements, boundary_sides);
3632 vector<int> boundary_ids;
3634 if (num_boundaries > 0)
3636 boundary_ids.resize(num_boundaries);
3638 netcdf_status = nc_inq_varid(netcdf_descriptor,
"ss_prop1", &variable_id);
3639 netcdf_status = nc_get_var_int(netcdf_descriptor, variable_id,
3640 boundary_ids.data());
3642 if (netcdf_status != NC_NOERR) { HandleNetCDFError(netcdf_status); }
3646 vector<double> coordx(num_nodes);
3647 vector<double> coordy(num_nodes);
3648 vector<double> coordz(num_dimensions == 3 ? num_nodes : 0);
3650 ReadCubitNodeCoordinates(netcdf_descriptor, coordx.data(), coordy.data(),
3654 vector<vector<int>> block_elements(num_element_blocks);
3656 ReadCubitElementBlocks(netcdf_descriptor, num_element_blocks,
3657 num_nodes_per_element, num_elements_for_block,
3661 vector<int> block_ids(num_element_blocks);
3664 netcdf_status = nc_inq_varid(netcdf_descriptor,
"eb_prop1", &variable_id);
3665 netcdf_status = nc_get_var_int(netcdf_descriptor, variable_id,
3668 if (netcdf_status != NC_NOERR) { HandleNetCDFError(netcdf_status); }
3673 vector<int> start_of_block(num_element_blocks + 1);
3675 start_of_block[0] = 0;
3677 for (
size_t iblock = 1; iblock < num_element_blocks + 1; iblock++)
3679 start_of_block[iblock] = start_of_block[iblock - 1] +
3680 num_elements_for_block[iblock - 1];
3686 vector<vector<int>> boundary_nodes(num_boundaries);
3689 for (
size_t iboundary = 0; iboundary < num_boundaries; iboundary++)
3691 const int num_elements_on_boundary = num_boundary_elements[iboundary];
3692 const int num_nodes_on_boundary = num_elements_on_boundary * num_face_nodes;
3694 boundary_nodes[iboundary].resize(num_nodes_on_boundary);
3697 for (
int jelement = 0; jelement < num_elements_on_boundary; jelement++)
3699 const int element_global_index = boundary_elements[iboundary][jelement] - 1;
3702 const int this_side = boundary_sides[iboundary][jelement];
3705 const int iblock = GetCubitBlockIndexForElement(element_global_index,
3707 start_of_block.data());
3709 const int element_block_offset = element_global_index - start_of_block[iblock];
3710 const int node_block_offset = element_block_offset * num_nodes_per_element;
3713 for (
int knode = 0; knode < num_face_nodes; knode++)
3717 switch (cubit_element_type)
3719 case (ELEMENT_TRI3):
3721 inode = cubit_side_map_tri3[this_side - 1][knode];
3724 case (ELEMENT_TRI6):
3726 inode = cubit_side_map_tri6[this_side - 1][knode];
3729 case (ELEMENT_QUAD4):
3731 inode = cubit_side_map_quad4[this_side - 1][knode];
3734 case (ELEMENT_QUAD9):
3736 inode = cubit_side_map_quad9[this_side - 1][knode];
3739 case (ELEMENT_TET4):
3741 inode = cubit_side_map_tet4[this_side - 1][knode];
3744 case (ELEMENT_TET10):
3746 inode = cubit_side_map_tet10[this_side - 1][knode];
3749 case (ELEMENT_HEX8):
3751 inode = cubit_side_map_hex8[this_side - 1][knode];
3754 case (ELEMENT_HEX27):
3756 inode = cubit_side_map_hex27[this_side - 1][knode];
3761 MFEM_ABORT(
"Unsupported element type encountered.\n");
3766 boundary_nodes[iboundary][jelement * num_face_nodes + knode] =
3767 block_elements[iblock][node_block_offset + inode - 1];
3773 vector<int> unique_vertex_ids;
3775 for (
size_t iblock = 0; iblock < num_element_blocks; iblock++)
3777 const vector<int> &nodes_in_block = block_elements[iblock];
3779 for (
size_t jelement = 0; jelement < num_elements_for_block[iblock]; jelement++)
3781 const int element_block_offset = jelement * num_nodes_per_element;
3783 for (
int knode = 0; knode < num_element_linear_nodes; knode++)
3785 unique_vertex_ids.push_back(nodes_in_block[element_block_offset + knode]);
3791 std::sort(unique_vertex_ids.begin(), unique_vertex_ids.end());
3793 auto new_end = std::unique(unique_vertex_ids.begin(), unique_vertex_ids.end());
3794 unique_vertex_ids.resize(std::distance(unique_vertex_ids.begin(), new_end));
3800 std::map<int,int> cubit_to_mfem_vertex_map;
3802 for (
size_t ivertex = 0; ivertex < unique_vertex_ids.size(); ivertex++)
3804 const int key = unique_vertex_ids[ivertex];
3805 const int value = ivertex + 1;
3807 cubit_to_mfem_vertex_map[key] = value;
3818 const int original_1based_id = unique_vertex_ids[ivertex];
3820 vertices[ivertex](0) = coordx[original_1based_id - 1];
3821 vertices[ivertex](1) = coordy[original_1based_id - 1];
3825 vertices[ivertex](2) = coordz[original_1based_id - 1];
3835 std::vector<int> renumbered_vertex_ids(max(num_element_linear_nodes,
3836 num_face_linear_nodes));
3838 int element_counter = 0;
3841 for (
size_t iblock = 0; iblock < num_element_blocks; iblock++)
3843 const vector<int> &nodes_ids_for_block = block_elements[iblock];
3846 for (
size_t jelement = 0; jelement < num_elements_for_block[iblock]; jelement++)
3849 for (
int knode = 0; knode < num_element_linear_nodes; knode++)
3851 const int node_id = nodes_ids_for_block[jelement * num_nodes_per_element +
3855 renumbered_vertex_ids[knode] = cubit_to_mfem_vertex_map[node_id] - 1;
3859 elements[element_counter++] = CreateCubitElement(*
this, cubit_element_type,
3860 renumbered_vertex_ids.data(),
3869 for (
size_t iboundary = 0; iboundary < num_boundaries; iboundary++)
3876 int boundary_counter = 0;
3879 for (
size_t iboundary = 0; iboundary < num_boundaries; iboundary++)
3881 const vector<int> &nodes_on_boundary = boundary_nodes[iboundary];
3884 for (
size_t jelement = 0; jelement < num_boundary_elements[iboundary];
3888 for (
int knode = 0; knode < num_face_linear_nodes; knode++)
3890 const int node_id = nodes_on_boundary[jelement * num_face_nodes + knode];
3893 renumbered_vertex_ids[knode] = cubit_to_mfem_vertex_map[node_id] - 1;
3897 boundary[boundary_counter++] = CreateCubitBoundaryElement(*
this,
3899 renumbered_vertex_ids.data(),
3900 boundary_ids[iboundary]);
3905 const int order = GetOrderFromCubitElementType(cubit_element_type);
3911 FinalizeCubitSecondOrderMesh(*
this,
3914 num_nodes_per_element,
3915 start_of_block.data(),
3923 nc_close(netcdf_descriptor);