13 #include "../fem/fem.hpp"
14 #include "../general/binaryio.hpp"
15 #include "../general/text.hpp"
16 #include "../general/tinyxml2.h"
24 #ifdef MFEM_USE_NETCDF
37 bool Mesh::remove_unused_vertices =
true;
39 void Mesh::ReadMFEMMesh(std::istream &input,
int version,
int &curved)
42 MFEM_VERIFY(version == 10 || version == 12,
43 "unknown MFEM mesh version");
51 MFEM_VERIFY(ident ==
"dimension",
"invalid mesh file");
57 MFEM_VERIFY(ident ==
"elements",
"invalid mesh file");
58 input >> NumOfElements;
59 elements.SetSize(NumOfElements);
60 for (
int j = 0; j < NumOfElements; j++)
62 elements[j] = ReadElement(input);
68 MFEM_VERIFY(ident ==
"boundary",
"invalid mesh file");
69 input >> NumOfBdrElements;
70 boundary.SetSize(NumOfBdrElements);
71 for (
int j = 0; j < NumOfBdrElements; j++)
73 boundary[j] = ReadElement(input);
79 MFEM_VERIFY(ident ==
"vertices",
"invalid mesh file");
80 input >> NumOfVertices;
81 vertices.SetSize(NumOfVertices);
87 spaceDim = atoi(ident.c_str());
88 for (
int j = 0; j < NumOfVertices; j++)
90 for (
int i = 0; i < spaceDim; i++)
92 input >> vertices[j](i);
105 if (remove_unused_vertices) { RemoveUnusedVertices(); }
108 void Mesh::ReadLineMesh(std::istream &input)
114 input >> NumOfVertices;
115 vertices.SetSize(NumOfVertices);
117 for (j = 0; j < NumOfVertices; j++)
119 input >> vertices[j](0);
122 input >> NumOfElements;
123 elements.SetSize(NumOfElements);
125 for (j = 0; j < NumOfElements; j++)
127 input >> a >> p1 >> p2;
128 elements[j] =
new Segment(p1-1, p2-1, a);
132 input >> NumOfBdrElements;
133 boundary.SetSize(NumOfBdrElements);
134 for (j = 0; j < NumOfBdrElements; j++)
136 input >> a >> ind[0];
138 boundary[j] =
new Point(ind,a);
142 void Mesh::ReadNetgen2DMesh(std::istream &input,
int &curved)
144 int ints[32], attr, n;
150 input >> NumOfBdrElements;
151 boundary.SetSize(NumOfBdrElements);
152 for (
int i = 0; i < NumOfBdrElements; i++)
155 >> ints[0] >> ints[1];
156 ints[0]--; ints[1]--;
157 boundary[i] =
new Segment(ints, attr);
161 input >> NumOfElements;
162 elements.SetSize(NumOfElements);
163 for (
int i = 0; i < NumOfElements; i++)
166 for (
int j = 0; j < n; j++)
174 elements[i] =
new Segment(ints, attr);
177 elements[i] =
new Triangle(ints, attr);
188 input >> NumOfVertices;
189 vertices.SetSize(NumOfVertices);
190 for (
int i = 0; i < NumOfVertices; i++)
191 for (
int j = 0; j < Dim; j++)
193 input >> vertices[i](j);
198 input >> NumOfVertices;
199 vertices.SetSize(NumOfVertices);
204 void Mesh::ReadNetgen3DMesh(std::istream &input)
212 input >> NumOfVertices;
214 vertices.SetSize(NumOfVertices);
215 for (
int i = 0; i < NumOfVertices; i++)
216 for (
int j = 0; j < Dim; j++)
218 input >> vertices[i](j);
222 input >> NumOfElements;
223 elements.SetSize(NumOfElements);
224 for (
int i = 0; i < NumOfElements; i++)
227 for (
int j = 0; j < 4; j++)
232 #ifdef MFEM_USE_MEMALLOC
234 tet = TetMemory.Alloc();
244 input >> NumOfBdrElements;
245 boundary.SetSize(NumOfBdrElements);
246 for (
int i = 0; i < NumOfBdrElements; i++)
249 for (
int j = 0; j < 3; j++)
254 boundary[i] =
new Triangle(ints, attr);
258 void Mesh::ReadTrueGridMesh(std::istream &input)
260 int i, j, ints[32], attr;
261 const int buflen = 1024;
272 input >> vari >> NumOfVertices >> vari >> vari >> NumOfElements;
273 input.getline(buf, buflen);
274 input.getline(buf, buflen);
276 input.getline(buf, buflen);
277 input.getline(buf, buflen);
278 input.getline(buf, buflen);
281 vertices.SetSize(NumOfVertices);
282 for (i = 0; i < NumOfVertices; i++)
284 input >> vari >> varf >> vertices[i](0) >> vertices[i](1);
285 input.getline(buf, buflen);
289 elements.SetSize(NumOfElements);
290 for (i = 0; i < NumOfElements; i++)
292 input >> vari >> attr;
293 for (j = 0; j < 4; j++)
298 input.getline(buf, buflen);
299 input.getline(buf, buflen);
307 input >> vari >> NumOfVertices >> NumOfElements;
308 input.getline(buf, buflen);
309 input.getline(buf, buflen);
310 input >> vari >> vari >> NumOfBdrElements;
311 input.getline(buf, buflen);
312 input.getline(buf, buflen);
313 input.getline(buf, buflen);
315 vertices.SetSize(NumOfVertices);
316 for (i = 0; i < NumOfVertices; i++)
318 input >> vari >> varf >> vertices[i](0) >> vertices[i](1)
320 input.getline(buf, buflen);
323 elements.SetSize(NumOfElements);
324 for (i = 0; i < NumOfElements; i++)
326 input >> vari >> attr;
327 for (j = 0; j < 8; j++)
332 input.getline(buf, buflen);
336 boundary.SetSize(NumOfBdrElements);
337 for (i = 0; i < NumOfBdrElements; i++)
340 for (j = 0; j < 4; j++)
345 input.getline(buf, buflen);
352 const int Mesh::vtk_quadratic_tet[10] =
353 { 0, 1, 2, 3, 4, 7, 5, 6, 8, 9 };
357 const int Mesh::vtk_quadratic_wedge[18] =
358 { 0, 2, 1, 3, 5, 4, 8, 7, 6, 11, 10, 9, 12, 14, 13, 17, 16, 15};
361 const int Mesh::vtk_quadratic_hex[27] =
363 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
364 24, 22, 21, 23, 20, 25, 26
371 int &curved,
int &read_gf,
bool &finalize_topo)
373 int np = points.
Size()/3;
375 NumOfElements = cell_types.
Size();
376 elements.SetSize(NumOfElements);
379 bool legacy_elem =
false, lagrange_elem =
false;
382 for (
int i = 0; i < NumOfElements; i++)
384 int ct = cell_types[i];
386 elements[i] = NewElement(geom);
387 if (cell_attributes.
Size() > 0)
389 elements[i]->SetAttribute(cell_attributes[i]);
393 if (geom == Geometry::PRISM && ct != VTKGeometry::LAGRANGE_PRISM)
395 int prism_vertices[6];
396 for (
int k=0; k<6; ++k)
398 prism_vertices[k] = cell_data[j+VTKGeometry::PrismMap[k]];
400 elements[i]->SetVertices(prism_vertices);
404 elements[i]->SetVertices(&cell_data[j]);
407 int elem_dim = Geometry::Dimension[
geom];
408 int elem_order = VTKGeometry::GetOrder(ct, cell_offsets[i] - j);
410 if (VTKGeometry::IsLagrange(ct)) { lagrange_elem =
true; }
411 else { legacy_elem =
true; }
413 MFEM_VERIFY(Dim == -1 || Dim == elem_dim,
414 "Elements with different dimensions are not supported");
415 MFEM_VERIFY(order == -1 || order == elem_order,
416 "Elements with different orders are not supported");
417 MFEM_VERIFY(legacy_elem != lagrange_elem,
418 "Mixing of legacy and Lagrange cell types is not supported");
424 if (order == 1 && !lagrange_elem)
428 for (
int i = 0; i < np; i++)
430 vertices[i](0) = points(3*i+0);
431 vertices[i](1) = points(3*i+1);
432 vertices[i](2) = points(3*i+2);
435 NumOfBdrElements = 0;
437 CheckElementOrientation(
true);
449 for (
int i = 0; i < NumOfElements; i++)
451 int *v = elements[i]->GetVertices();
452 int nv = elements[i]->GetNVertices();
453 for (
int j = 0; j < nv; j++)
455 if (pts_dof[v[j]] == -1) { pts_dof[v[j]] = 0; }
464 for (n = i = 0; i < np; i++)
466 if (pts_dof[i] != -1)
472 for (
int i = 0; i < NumOfElements; i++)
474 int *v = elements[i]->GetVertices();
475 int nv = elements[i]->GetNVertices();
476 for (
int j = 0; j < nv; j++)
478 v[j] = pts_dof[v[j]];
484 for (
int i = 0; i < np; i++)
489 vertices[j](0) = points(3*i+0);
490 vertices[j](1) = points(3*i+1);
491 vertices[j](2) = points(3*i+2);
496 NumOfBdrElements = 0;
499 if (vertices.Size() > 0)
501 double min_value, max_value;
502 for (
int d=0; d<3; ++d)
504 min_value = max_value = vertices[0](d);
505 for (
int i = 1; i < vertices.Size(); i++)
507 min_value = std::min(min_value,vertices[i](d));
508 max_value = std::max(max_value,vertices[i](d));
509 if (min_value != max_value)
529 Nodes->MakeOwner(fec);
534 for (
int i = 0; i < NumOfElements; i++)
538 switch (elements[i]->GetGeometryType())
540 case Geometry::TRIANGLE:
541 case Geometry::SQUARE:
542 vtk_mfem = vtk_quadratic_hex;
break;
543 case Geometry::TETRAHEDRON:
544 vtk_mfem = vtk_quadratic_tet;
break;
546 vtk_mfem = vtk_quadratic_hex;
break;
547 case Geometry::PRISM:
548 vtk_mfem = vtk_quadratic_wedge;
break;
554 int offset = (i == 0) ? 0 : cell_offsets[i-1];
555 for (
int j = 0; j < dofs.
Size(); j++)
557 if (pts_dof[cell_data[offset+j]] == -1)
559 pts_dof[cell_data[offset+j]] = dofs[vtk_mfem[j]];
563 if (pts_dof[cell_data[offset+j]] != dofs[vtk_mfem[j]])
565 MFEM_ABORT(
"VTK mesh: inconsistent quadratic mesh!");
577 Nodes->MakeOwner(fec);
581 std::map<Geometry::Type,Array<int>> vtk_inv_maps;
582 std::map<Geometry::Type,const Array<int>*> lex_orderings;
585 for (n = i = 0; i < NumOfElements; i++)
591 if (vtk_inv_map.
Size() == 0)
596 for (
int j=0; j<vtk_map.
Size(); ++j)
598 vtk_inv_map[vtk_map[j]] = j;
607 MFEM_ASSERT(nodal_fe != NULL,
"Unsupported element type");
611 for (
int lex_idx = 0; lex_idx < dofs.
Size(); lex_idx++)
613 int mfem_idx = (*lex_ordering)[lex_idx];
614 int vtk_idx = vtk_inv_map[lex_idx];
615 int pt_idx = cell_data[n + vtk_idx];
616 if (pts_dof[pt_idx] == -1)
618 pts_dof[pt_idx] = dofs[mfem_idx];
622 if (pts_dof[pt_idx] != dofs[mfem_idx])
624 MFEM_ABORT(
"VTK mesh: inconsistent Lagrange mesh!");
633 for (
int i = 0; i < np; i++)
636 if (pts_dof[i] != -1)
638 dofs[0] = pts_dof[i];
640 for (
int d = 0; d < dofs.
Size(); d++)
642 (*Nodes)(dofs[d]) = points(3*i+d);
653 using namespace tinyxml2;
659 if (s1 == NULL || s2 == NULL) {
return false; }
660 return strcmp(s1, s2) == 0;
668 struct BufferReaderBase
670 enum HeaderType { UINT32_HEADER, UINT64_HEADER };
671 virtual void ReadBinary(
const char *buf,
void *dest,
int n)
const = 0;
672 virtual void ReadBase64(
const char *txt,
void *dest,
int n)
const = 0;
673 virtual ~BufferReaderBase() { }
686 template <
typename T,
typename F>
687 struct BufferReader : BufferReaderBase
690 HeaderType header_type;
691 BufferReader(
bool compressed_, HeaderType header_type_)
692 : compressed(compressed_), header_type(header_type_) { }
695 size_t HeaderEntrySize()
const
697 return header_type == UINT64_HEADER ?
sizeof(uint64_t) :
sizeof(uint32_t);
703 uint64_t ReadHeaderEntry(
const char *header_buf)
const
705 return (header_type == UINT64_HEADER) ? bin_io::read<uint64_t>(header_buf)
706 : bin_io::read<uint32_t>(header_buf);
715 int NumHeaderBytes(
const char *header_buf)
const
717 if (!compressed) {
return HeaderEntrySize(); }
718 return (3 + ReadHeaderEntry(header_buf))*HeaderEntrySize();
726 void ReadBinaryWithHeader(
const char *header_buf,
const char *buf,
727 void *dest_void,
int n)
const
729 std::vector<char> uncompressed_data;
730 T *dest =
static_cast<T*
>(dest_void);
740 int header_entry_size = HeaderEntrySize();
741 int nblocks = ReadHeaderEntry(header_buf);
742 header_buf += header_entry_size;
743 std::vector<int> header(nblocks + 2);
744 for (
int i=0; i<nblocks+2; ++i)
746 header[i] = ReadHeaderEntry(header_buf);
747 header_buf += header_entry_size;
749 uncompressed_data.resize((nblocks-1)*header[0] + header[1]);
750 Bytef *dest_ptr = (Bytef *)uncompressed_data.data();
751 Bytef *dest_start = dest_ptr;
752 const Bytef *source_ptr = (
const Bytef *)buf;
753 for (
int i=0; i<nblocks; ++i)
755 uLongf source_len = header[i+2];
756 uLong dest_len = (i == nblocks-1) ? header[1] : header[0];
757 int res = uncompress(dest_ptr, &dest_len, source_ptr, source_len);
758 MFEM_VERIFY(res == Z_OK,
"Error uncompressing");
759 dest_ptr += dest_len;
760 source_ptr += source_len;
762 MFEM_VERIFY(
int(
sizeof(F)*n) == (dest_ptr - dest_start),
763 "AppendedData: wrong data size");
764 buf = uncompressed_data.data();
766 MFEM_ABORT(
"MFEM must be compiled with zlib enabled to uncompress.")
774 if (header_type == UINT32_HEADER)
776 uint32_t *data_size_32 = (uint32_t *)header_buf;
777 data_size = *data_size_32;
781 uint64_t *data_size_64 = (uint64_t *)header_buf;
782 data_size = *data_size_64;
784 MFEM_VERIFY(
sizeof(F)*n == data_size,
"AppendedData: wrong data size");
787 if (std::is_same<T, F>::value)
790 memcpy(dest, buf,
sizeof(T)*n);
794 for (
int i=0; i<n; ++i)
797 dest[i] = bin_io::read<F>(buf + i*
sizeof(F));
805 void ReadBinary(
const char *buf,
void *dest,
int n)
const override
807 ReadBinaryWithHeader(buf, buf + NumHeaderBytes(buf), dest, n);
814 void ReadBase64(
const char *txt,
void *dest,
int n)
const override
819 if (*txt !=
' ' && *txt !=
'\n') {
break; }
826 std::vector<char> nblocks_buf;
829 std::vector<char> data, header;
836 ReadBinaryWithHeader(header.data(), data.data(), dest, n);
840 std::vector<char> data;
842 ReadBinary(data.data(), dest, n);
853 const char *appended_data, *byte_order, *compressor;
854 enum AppendedDataEncoding { RAW, BASE64 };
855 map<string,BufferReaderBase*> type_map;
856 AppendedDataEncoding encoding;
862 XMLDataReader(
const XMLElement *vtk,
const XMLElement *vtu)
865 BufferReaderBase::HeaderType htype;
868 htype = BufferReaderBase::UINT64_HEADER;
872 htype = BufferReaderBase::UINT32_HEADER;
876 byte_order = vtk->Attribute(
"byte_order");
880 compressor = vtk->Attribute(
"compressor");
881 bool compressed = (compressor != NULL);
884 appended_data = NULL;
885 for (
const XMLElement *xml_elem = vtu->NextSiblingElement();
887 xml_elem = xml_elem->NextSiblingElement())
891 const char *encoding_str = xml_elem->Attribute(
"encoding");
894 appended_data = xml_elem->GetAppendedData();
899 appended_data = xml_elem->GetText();
902 MFEM_VERIFY(appended_data != NULL,
"Invalid AppendedData");
904 bool found_leading_underscore =
false;
905 while (*appended_data)
908 if (*appended_data ==
'_')
910 found_leading_underscore =
true;
915 MFEM_VERIFY(found_leading_underscore,
"Invalid AppendedData");
920 type_map[
"Int8"] =
new BufferReader<int, int8_t>(compressed, htype);
921 type_map[
"Int16"] =
new BufferReader<int, int16_t>(compressed, htype);
922 type_map[
"Int32"] =
new BufferReader<int, int32_t>(compressed, htype);
923 type_map[
"Int64"] =
new BufferReader<int, int64_t>(compressed, htype);
924 type_map[
"UInt8"] =
new BufferReader<int, uint8_t>(compressed, htype);
925 type_map[
"UInt16"] =
new BufferReader<int, uint16_t>(compressed, htype);
926 type_map[
"UInt32"] =
new BufferReader<int, uint32_t>(compressed, htype);
927 type_map[
"UInt64"] =
new BufferReader<int, uint64_t>(compressed, htype);
928 type_map[
"Float32"] =
new BufferReader<double, float>(compressed, htype);
929 type_map[
"Float64"] =
new BufferReader<double, double>(compressed, htype);
935 template <
typename T>
936 void Read(
const XMLElement *xml_elem, T *dest,
int n)
938 static const char *erstr =
"Error reading XML DataArray";
939 MFEM_VERIFY(
StringCompare(xml_elem->Name(),
"DataArray"), erstr);
940 const char *format = xml_elem->Attribute(
"format");
943 const char *txt = xml_elem->GetText();
944 MFEM_VERIFY(txt != NULL, erstr);
945 std::istringstream data_stream(txt);
946 for (
int i=0; i<n; ++i) { data_stream >> dest[i]; }
950 VerifyBinaryOptions();
951 int offset = xml_elem->IntAttribute(
"offset");
952 const char *type = xml_elem->Attribute(
"type");
953 MFEM_VERIFY(type != NULL, erstr);
954 BufferReaderBase *reader = type_map[type];
955 MFEM_VERIFY(reader != NULL, erstr);
956 MFEM_VERIFY(appended_data != NULL,
"No AppendedData found");
959 reader->ReadBinary(appended_data + offset, dest, n);
963 reader->ReadBase64(appended_data + offset, dest, n);
968 VerifyBinaryOptions();
969 const char *txt = xml_elem->GetText();
970 MFEM_VERIFY(txt != NULL, erstr);
971 const char *type = xml_elem->Attribute(
"type");
972 if (type == NULL) { MFEM_ABORT(erstr); }
973 BufferReaderBase *reader = type_map[type];
974 if (reader == NULL) { MFEM_ABORT(erstr); }
975 reader->ReadBase64(txt, dest, n);
979 MFEM_ABORT(
"Invalid XML VTK DataArray format");
987 void VerifyByteOrder()
const
992 MFEM_ABORT(
"Converting between different byte orders is unsupported.");
999 void VerifyCompressor()
const
1001 if (compressor && !
StringCompare(compressor,
"vtkZLibDataCompressor"))
1003 MFEM_ABORT(
"Unsupported compressor. Only zlib is supported.")
1005 #ifndef MFEM_USE_ZLIB
1006 MFEM_VERIFY(compressor == NULL,
"MFEM must be compiled with zlib enabled "
1007 "to support reading compressed data.");
1013 void VerifyBinaryOptions()
const
1021 for (
auto &x : type_map) {
delete x.second; }
1027 void Mesh::ReadXML_VTKMesh(std::istream &input,
int &curved,
int &read_gf,
1028 bool &finalize_topo,
const std::string &xml_prefix)
1030 using namespace vtk_xml;
1032 static const char *erstr =
"XML parsing error";
1035 std::vector<char> buf(xml_prefix.begin(), xml_prefix.end());
1036 std::istreambuf_iterator<char> eos;
1037 buf.insert(buf.end(), std::istreambuf_iterator<char>(input), eos);
1038 buf.push_back(
'\0');
1041 xml.Parse(buf.data(), buf.size());
1042 if (xml.ErrorID() != XML_SUCCESS)
1044 MFEM_ABORT(
"Error parsing XML VTK file.\n" << xml.ErrorStr());
1047 const XMLElement *vtkfile = xml.FirstChildElement();
1048 MFEM_VERIFY(vtkfile, erstr);
1049 MFEM_VERIFY(
StringCompare(vtkfile->Name(),
"VTKFile"), erstr);
1050 const XMLElement *vtu = vtkfile->FirstChildElement();
1051 MFEM_VERIFY(vtu, erstr);
1052 MFEM_VERIFY(
StringCompare(vtu->Name(),
"UnstructuredGrid"), erstr);
1054 XMLDataReader data_reader(vtkfile, vtu);
1057 const XMLElement *piece = vtu->FirstChildElement();
1059 MFEM_VERIFY(piece->NextSiblingElement() == NULL,
1060 "XML VTK meshes with more than one Piece are not supported");
1061 int npts = piece->IntAttribute(
"NumberOfPoints");
1062 int ncells = piece->IntAttribute(
"NumberOfCells");
1066 const XMLElement *pts_xml;
1067 for (pts_xml = piece->FirstChildElement();
1069 pts_xml = pts_xml->NextSiblingElement())
1073 const XMLElement *pts_data = pts_xml->FirstChildElement();
1074 MFEM_VERIFY(pts_data->IntAttribute(
"NumberOfComponents") == 3,
1075 "XML VTK Points DataArray must have 3 components");
1076 data_reader.Read(pts_data, points.
GetData(), points.
Size());
1080 if (pts_xml == NULL) { MFEM_ABORT(erstr); }
1083 Array<int> cell_data, cell_offsets(ncells), cell_types(ncells);
1084 const XMLElement *cells_xml;
1085 for (cells_xml = piece->FirstChildElement();
1087 cells_xml = cells_xml->NextSiblingElement())
1091 const XMLElement *cell_data_xml = NULL;
1092 for (
const XMLElement *data_xml = cells_xml->FirstChildElement();
1094 data_xml = data_xml->NextSiblingElement())
1096 const char *data_name = data_xml->Attribute(
"Name");
1099 data_reader.Read(data_xml, cell_offsets.GetData(), ncells);
1103 data_reader.Read(data_xml, cell_types.
GetData(), ncells);
1111 cell_data_xml = data_xml;
1114 MFEM_VERIFY(cell_data_xml != NULL, erstr);
1115 int cell_data_size = cell_offsets.Last();
1116 cell_data.SetSize(cell_data_size);
1117 data_reader.Read(cell_data_xml, cell_data.GetData(), cell_data_size);
1121 if (cells_xml == NULL) { MFEM_ABORT(erstr); }
1125 for (
const XMLElement *cell_data_xml = piece->FirstChildElement();
1126 cell_data_xml != NULL;
1127 cell_data_xml = cell_data_xml->NextSiblingElement())
1130 &&
StringCompare(cell_data_xml->Attribute(
"Scalars"),
"material"))
1132 const XMLElement *data_xml = cell_data_xml->FirstChildElement();
1133 if (data_xml != NULL &&
StringCompare(data_xml->Name(),
"DataArray"))
1135 cell_attributes.
SetSize(ncells);
1136 data_reader.Read(data_xml, cell_attributes.GetData(), ncells);
1141 CreateVTKMesh(points, cell_data, cell_offsets, cell_types, cell_attributes,
1142 curved, read_gf, finalize_topo);
1145 void Mesh::ReadVTKMesh(std::istream &input,
int &curved,
int &read_gf,
1146 bool &finalize_topo)
1155 getline(input, buff);
1156 getline(input, buff);
1158 if (buff !=
"ASCII")
1160 MFEM_ABORT(
"VTK mesh is not in ASCII format!");
1165 getline(input, buff);
1167 if (!input.good()) { MFEM_ABORT(
"VTK mesh is not UNSTRUCTURED_GRID!"); }
1169 while (buff !=
"DATASET UNSTRUCTURED_GRID");
1178 MFEM_ABORT(
"VTK mesh does not have POINTS data!");
1181 while (buff !=
"POINTS");
1186 getline(input, buff);
1187 points.
Load(input, 3*np);
1202 MFEM_ABORT(
"VTK mesh does not have CELLS data!");
1205 while (buff !=
"CELLS");
1209 if (buff ==
"CELLS")
1212 input >> ncells >> n >> ws;
1214 cell_data.
SetSize(n - ncells);
1216 for (
int i=0; i<ncells; ++i)
1220 cell_offsets[i] = offset + nv;
1221 for (
int j=0; j<nv; ++j)
1223 input >> cell_data[offset + j];
1230 input >> ws >> buff;
1233 MFEM_VERIFY(buff ==
"CELL_TYPES",
"CELL_TYPES not provided in VTK mesh.")
1235 cell_types.
Load(ncells, input);
1237 while ((input.good()) && (buff !=
"CELL_DATA"))
1241 getline(input, buff);
1246 while ((input.good()))
1248 getline(input, buff);
1249 if (buff.rfind(
"POINT_DATA") == 0)
1253 else if (buff.rfind(
"SCALARS material") == 0)
1255 getline(input, buff);
1256 if (buff.rfind(
"LOOKUP_TABLE default") != 0)
1258 MFEM_ABORT(
"Invalid LOOKUP_TABLE for material array in VTK file.");
1260 cell_attributes.
Load(ncells, input);
1272 CreateVTKMesh(points, cell_data, cell_offsets, cell_types, cell_attributes,
1273 curved, read_gf, finalize_topo);
1276 void Mesh::ReadNURBSMesh(std::istream &input,
int &curved,
int &read_gf)
1280 Dim = NURBSext->Dimension();
1281 NumOfVertices = NURBSext->GetNV();
1282 NumOfElements = NURBSext->GetNE();
1283 NumOfBdrElements = NURBSext->GetNBE();
1285 NURBSext->GetElementTopo(elements);
1286 NURBSext->GetBdrElementTopo(boundary);
1288 vertices.SetSize(NumOfVertices);
1290 if (NURBSext->HavePatches())
1296 Nodes->MakeOwner(fec);
1297 NURBSext->SetCoordsFromPatches(*Nodes);
1300 spaceDim = Nodes->VectorDim();
1301 for (
int i = 0; i < spaceDim; i++)
1304 Nodes->GetNodalValues(vert_val, i+1);
1305 for (
int j = 0; j < NumOfVertices; j++)
1307 vertices[j](i) = vert_val(j);
1317 void Mesh::ReadInlineMesh(std::istream &input,
bool generate_edges)
1345 MFEM_VERIFY(input.get() ==
'=',
1346 "Inline mesh expected '=' after keyword " << name);
1353 else if (name ==
"ny")
1357 else if (name ==
"nz")
1361 else if (name ==
"sx")
1365 else if (name ==
"sy")
1369 else if (name ==
"sz")
1373 else if (name ==
"type")
1377 if (eltype ==
"segment")
1379 type = Element::SEGMENT;
1381 else if (eltype ==
"quad")
1383 type = Element::QUADRILATERAL;
1385 else if (eltype ==
"tri")
1387 type = Element::TRIANGLE;
1389 else if (eltype ==
"hex")
1391 type = Element::HEXAHEDRON;
1393 else if (eltype ==
"wedge")
1395 type = Element::WEDGE;
1397 else if (eltype ==
"tet")
1399 type = Element::TETRAHEDRON;
1403 MFEM_ABORT(
"unrecognized element type (read '" << eltype
1404 <<
"') in inline mesh format. "
1405 "Allowed: segment, tri, quad, tet, hex, wedge");
1410 MFEM_ABORT(
"unrecognized keyword (" << name
1411 <<
") in inline mesh format. "
1412 "Allowed: nx, ny, nz, type, sx, sy, sz");
1417 if (input.peek() ==
';')
1430 if (type == Element::SEGMENT)
1432 MFEM_VERIFY(nx > 0 && sx > 0.0,
1433 "invalid 1D inline mesh format, all values must be "
1435 <<
" nx = " << nx <<
"\n"
1436 <<
" sx = " << sx <<
"\n");
1439 else if (type == Element::TRIANGLE || type == Element::QUADRILATERAL)
1441 MFEM_VERIFY(nx > 0 && ny > 0 && sx > 0.0 && sy > 0.0,
1442 "invalid 2D inline mesh format, all values must be "
1444 <<
" nx = " << nx <<
"\n"
1445 <<
" ny = " << ny <<
"\n"
1446 <<
" sx = " << sx <<
"\n"
1447 <<
" sy = " << sy <<
"\n");
1448 Make2D(nx, ny, type, sx, sy, generate_edges,
true);
1450 else if (type == Element::TETRAHEDRON || type == Element::WEDGE ||
1451 type == Element::HEXAHEDRON)
1453 MFEM_VERIFY(nx > 0 && ny > 0 && nz > 0 &&
1454 sx > 0.0 && sy > 0.0 && sz > 0.0,
1455 "invalid 3D inline mesh format, all values must be "
1457 <<
" nx = " << nx <<
"\n"
1458 <<
" ny = " << ny <<
"\n"
1459 <<
" nz = " << nz <<
"\n"
1460 <<
" sx = " << sx <<
"\n"
1461 <<
" sy = " << sy <<
"\n"
1462 <<
" sz = " << sz <<
"\n");
1463 Make3D(nx, ny, nz, type, sx, sy, sz,
true);
1468 MFEM_ABORT(
"For inline mesh, must specify an element type ="
1469 " [segment, tri, quad, tet, hex, wedge]");
1473 void Mesh::ReadGmshMesh(std::istream &input,
int &curved,
int &read_gf)
1478 input >> version >> binary >> dsize;
1481 MFEM_ABORT(
"Gmsh file version < 2.2");
1483 if (dsize !=
sizeof(
double))
1485 MFEM_ABORT(
"Gmsh file : dsize != sizeof(double)");
1487 getline(input, buff);
1492 input.read(reinterpret_cast<char*>(&one),
sizeof(one));
1495 MFEM_ABORT(
"Gmsh file : wrong binary format");
1502 map<int, int> vertices_map;
1514 double bb_tol = 1e-14;
1522 bool periodic =
false;
1529 while (input >> buff)
1531 if (buff ==
"$Nodes")
1533 input >> NumOfVertices;
1534 getline(input, buff);
1535 vertices.SetSize(NumOfVertices);
1537 const int gmsh_dim = 3;
1538 double coord[gmsh_dim];
1539 for (
int ver = 0; ver < NumOfVertices; ++ver)
1543 input.read(reinterpret_cast<char*>(&serial_number),
sizeof(
int));
1544 input.read(reinterpret_cast<char*>(coord), gmsh_dim*
sizeof(
double));
1548 input >> serial_number;
1549 for (
int ci = 0; ci < gmsh_dim; ++ci)
1554 vertices[ver] =
Vertex(coord, gmsh_dim);
1555 vertices_map[serial_number] = ver;
1557 for (
int ci = 0; ci < gmsh_dim; ++ci)
1559 bb_min[ci] = (ver == 0) ? coord[ci] :
1560 std::min(bb_min[ci], coord[ci]);
1561 bb_max[ci] = (ver == 0) ? coord[ci] :
1562 std::max(bb_max[ci], coord[ci]);
1565 double bb_size = std::max(bb_max[0] - bb_min[0],
1566 std::max(bb_max[1] - bb_min[1],
1567 bb_max[2] - bb_min[2]));
1569 if (bb_max[1] - bb_min[1] > bb_size * bb_tol)
1573 if (bb_max[2] - bb_min[2] > bb_size * bb_tol)
1578 if (static_cast<int>(vertices_map.size()) != NumOfVertices)
1580 MFEM_ABORT(
"Gmsh file : vertices indices are not unique");
1583 else if (buff ==
"$Elements")
1585 int num_of_all_elements;
1586 input >> num_of_all_elements;
1588 getline(input, buff);
1591 int type_of_element;
1599 int nodes_of_gmsh_element[] =
1748 -1,-1,-1,-1,-1,-1,-1,
1764 -1,-1,-1,-1,-1,-1,-1,
1809 int lin3[] = {0,2,1};
1810 int lin4[] = {0,2,3,1};
1811 int tri6[] = {0,3,1,5,4,2};
1812 int tri10[] = {0,3,4,1,8,9,5,7,6,2};
1813 int quad9[] = {0,4,1,7,8,5,3,6,2};
1814 int quad16[] = {0,4,5,1,11,12,13,6,
1817 int tet10[] {0,4,1,6,5,2,7,9,8,3};
1818 int tet20[] = {0,4,5,1,9,16,6,8,7,2,
1819 11,17,15,18,19,13,10,14,12,3
1821 int hex27[] {0,8,1,9,20,11,3,13,2,
1822 10,21,12,22,26,23,15,24,14,
1823 4,16,5,17,25,18,7,19,6
1825 int hex64[] {0,8,9,1,10,32,35,14,
1826 11,33,34,15,3,19,18,2,
1827 12,36,37,16,40,56,57,44,
1828 43,59,58,45,22,49,48,20,
1829 13,39,38,17,41,60,61,47,
1830 42,63,62,46,23,50,51,21,
1831 4,24,25,5,26,52,53,28,
1832 27,55,54,29,7,31,30,6
1835 int wdg18[] = {0,6,1,7,9,2,8,15,10,
1836 16,17,11,3,12,4,13,14,5
1838 int wdg40[] = {0,6,7,1,8,24,12,9,13,2,
1839 10,26,27,14,30,38,34,33,35,16,
1840 11,29,28,15,31,39,37,32,36,17,
1841 3,18,19,4,20,25,22,21,23,5
1844 int pyr14[] = {0,5,1,6,13,8,3,
1847 int pyr30[] = {0,5,6,1,7,25,28,11,8,26,
1848 27,12,3,16,15,2,9,21,13,22,
1849 29,23,19,24,17,10,14,20,18,4
1852 vector<Element*> elements_0D, elements_1D, elements_2D, elements_3D;
1853 elements_0D.reserve(num_of_all_elements);
1854 elements_1D.reserve(num_of_all_elements);
1855 elements_2D.reserve(num_of_all_elements);
1856 elements_3D.reserve(num_of_all_elements);
1859 vector<Array<int>*> ho_verts_1D, ho_verts_2D, ho_verts_3D;
1860 ho_verts_1D.reserve(num_of_all_elements);
1861 ho_verts_2D.reserve(num_of_all_elements);
1862 ho_verts_3D.reserve(num_of_all_elements);
1865 vector<int> ho_el_order_1D, ho_el_order_2D, ho_el_order_3D;
1866 ho_el_order_1D.reserve(num_of_all_elements);
1867 ho_el_order_2D.reserve(num_of_all_elements);
1868 ho_el_order_3D.reserve(num_of_all_elements);
1880 ho_lin[2] = lin3; ho_lin[3] = lin4;
1881 ho_tri[2] = tri6; ho_tri[3] = tri10;
1882 ho_sqr[2] = quad9; ho_sqr[3] = quad16;
1883 ho_tet[2] = tet10; ho_tet[3] = tet20;
1884 ho_hex[2] = hex27; ho_hex[3] = hex64;
1885 ho_wdg[2] = wdg18; ho_wdg[3] = wdg40;
1886 ho_pyr[2] = pyr14; ho_pyr[3] = pyr30;
1890 int n_elem_part = 0;
1891 const int header_size = 3;
1894 int header[header_size];
1895 int n_elem_one_type;
1897 while (n_elem_part < num_of_all_elements)
1899 input.read(reinterpret_cast<char*>(header),
1900 header_size*
sizeof(
int));
1901 type_of_element = header[0];
1902 n_elem_one_type = header[1];
1905 n_elem_part += n_elem_one_type;
1907 const int n_elem_nodes = nodes_of_gmsh_element[type_of_element-1];
1908 vector<int> data(1+n_tags+n_elem_nodes);
1909 for (
int el = 0; el < n_elem_one_type; ++el)
1911 input.read(reinterpret_cast<char*>(&data[0]),
1912 data.size()*
sizeof(int));
1914 serial_number = data[dd++];
1917 phys_domain = (n_tags > 0) ? data[dd++] : 1;
1920 elem_domain = (n_tags > 1) ? data[dd++] : 0;
1923 n_partitions = (n_tags > 2) ? data[dd++] : 0;
1926 vector<int> vert_indices(n_elem_nodes);
1927 for (
int vi = 0; vi < n_elem_nodes; ++vi)
1929 map<int, int>::const_iterator it =
1930 vertices_map.find(data[1+n_tags+vi]);
1931 if (it == vertices_map.end())
1933 MFEM_ABORT(
"Gmsh file : vertex index doesn't exist");
1935 vert_indices[vi] = it->second;
1939 if (phys_domain <= 0)
1941 MFEM_ABORT(
"Non-positive element attribute in Gmsh mesh!\n"
1942 "By default Gmsh sets element tags (attributes)"
1943 " to '0' but MFEM requires that they be"
1944 " positive integers.\n"
1945 "Use \"Physical Curve\", \"Physical Surface\","
1946 " or \"Physical Volume\" to set tags/attributes"
1947 " for all curves, surfaces, or volumes in your"
1948 " Gmsh geometry to values which are >= 1.");
1953 switch (type_of_element)
1966 elements_1D.push_back(
1967 new Segment(&vert_indices[0], phys_domain));
1968 if (type_of_element != 1)
1970 el_order = n_elem_nodes - 1;
1972 hov->
Append(&vert_indices[0], n_elem_nodes);
1973 ho_verts_1D.push_back(hov);
1974 ho_el_order_1D.push_back(el_order);
1980 case 21: el_order--;
1981 case 23: el_order--;
1982 case 25: el_order--;
1983 case 42: el_order--;
1984 case 43: el_order--;
1985 case 44: el_order--;
1986 case 45: el_order--;
1987 case 46: el_order--;
1989 elements_2D.push_back(
1990 new Triangle(&vert_indices[0], phys_domain));
1994 hov->
Append(&vert_indices[0], n_elem_nodes);
1995 ho_verts_2D.push_back(hov);
1996 ho_el_order_2D.push_back(el_order);
2001 case 10: el_order--;
2002 case 36: el_order--;
2003 case 37: el_order--;
2004 case 38: el_order--;
2005 case 47: el_order--;
2006 case 48: el_order--;
2007 case 49: el_order--;
2008 case 50: el_order--;
2009 case 51: el_order--;
2011 elements_2D.push_back(
2016 hov->
Append(&vert_indices[0], n_elem_nodes);
2017 ho_verts_2D.push_back(hov);
2018 ho_el_order_2D.push_back(el_order);
2023 case 11: el_order--;
2024 case 29: el_order--;
2025 case 30: el_order--;
2026 case 31: el_order--;
2027 case 71: el_order--;
2028 case 72: el_order--;
2029 case 73: el_order--;
2030 case 74: el_order--;
2031 case 75: el_order--;
2033 #ifdef MFEM_USE_MEMALLOC
2034 elements_3D.push_back(TetMemory.Alloc());
2035 elements_3D.back()->SetVertices(&vert_indices[0]);
2036 elements_3D.back()->SetAttribute(phys_domain);
2038 elements_3D.push_back(
2044 hov->
Append(&vert_indices[0], n_elem_nodes);
2045 ho_verts_3D.push_back(hov);
2046 ho_el_order_3D.push_back(el_order);
2051 case 12: el_order--;
2052 case 92: el_order--;
2053 case 93: el_order--;
2054 case 94: el_order--;
2055 case 95: el_order--;
2056 case 96: el_order--;
2057 case 97: el_order--;
2058 case 98: el_order--;
2061 elements_3D.push_back(
2062 new Hexahedron(&vert_indices[0], phys_domain));
2066 hov->
Append(&vert_indices[0], n_elem_nodes);
2067 ho_verts_3D.push_back(hov);
2068 ho_el_order_3D.push_back(el_order);
2073 case 13: el_order--;
2074 case 90: el_order--;
2075 case 91: el_order--;
2076 case 106: el_order--;
2077 case 107: el_order--;
2078 case 108: el_order--;
2079 case 109: el_order--;
2080 case 110: el_order--;
2083 elements_3D.push_back(
2084 new Wedge(&vert_indices[0], phys_domain));
2088 hov->
Append(&vert_indices[0], n_elem_nodes);
2089 ho_verts_3D.push_back(hov);
2090 ho_el_order_3D.push_back(el_order);
2121 elements_0D.push_back(
2122 new Point(&vert_indices[0], phys_domain));
2126 MFEM_WARNING(
"Unsupported Gmsh element type.");
2135 for (
int el = 0; el < num_of_all_elements; ++el)
2137 input >> serial_number >> type_of_element >> n_tags;
2138 vector<int> data(n_tags);
2139 for (
int i = 0; i < n_tags; ++i) { input >> data[i]; }
2142 phys_domain = (n_tags > 0) ? data[0] : 1;
2145 elem_domain = (n_tags > 1) ? data[1] : 0;
2148 n_partitions = (n_tags > 2) ? data[2] : 0;
2151 const int n_elem_nodes = nodes_of_gmsh_element[type_of_element-1];
2152 vector<int> vert_indices(n_elem_nodes);
2154 for (
int vi = 0; vi < n_elem_nodes; ++vi)
2157 map<int, int>::const_iterator it = vertices_map.find(index);
2158 if (it == vertices_map.end())
2160 MFEM_ABORT(
"Gmsh file : vertex index doesn't exist");
2162 vert_indices[vi] = it->second;
2166 if (phys_domain <= 0)
2168 MFEM_ABORT(
"Non-positive element attribute in Gmsh mesh!\n"
2169 "By default Gmsh sets element tags (attributes)"
2170 " to '0' but MFEM requires that they be"
2171 " positive integers.\n"
2172 "Use \"Physical Curve\", \"Physical Surface\","
2173 " or \"Physical Volume\" to set tags/attributes"
2174 " for all curves, surfaces, or volumes in your"
2175 " Gmsh geometry to values which are >= 1.");
2180 switch (type_of_element)
2193 elements_1D.push_back(
2194 new Segment(&vert_indices[0], phys_domain));
2195 if (type_of_element != 1)
2198 hov->
Append(&vert_indices[0], n_elem_nodes);
2199 ho_verts_1D.push_back(hov);
2200 el_order = n_elem_nodes - 1;
2201 ho_el_order_1D.push_back(el_order);
2207 case 21: el_order--;
2208 case 23: el_order--;
2209 case 25: el_order--;
2210 case 42: el_order--;
2211 case 43: el_order--;
2212 case 44: el_order--;
2213 case 45: el_order--;
2214 case 46: el_order--;
2216 elements_2D.push_back(
2217 new Triangle(&vert_indices[0], phys_domain));
2221 hov->
Append(&vert_indices[0], n_elem_nodes);
2222 ho_verts_2D.push_back(hov);
2223 ho_el_order_2D.push_back(el_order);
2228 case 10: el_order--;
2229 case 36: el_order--;
2230 case 37: el_order--;
2231 case 38: el_order--;
2232 case 47: el_order--;
2233 case 48: el_order--;
2234 case 49: el_order--;
2235 case 50: el_order--;
2236 case 51: el_order--;
2238 elements_2D.push_back(
2243 hov->
Append(&vert_indices[0], n_elem_nodes);
2244 ho_verts_2D.push_back(hov);
2245 ho_el_order_2D.push_back(el_order);
2250 case 11: el_order--;
2251 case 29: el_order--;
2252 case 30: el_order--;
2253 case 31: el_order--;
2254 case 71: el_order--;
2255 case 72: el_order--;
2256 case 73: el_order--;
2257 case 74: el_order--;
2258 case 75: el_order--;
2260 #ifdef MFEM_USE_MEMALLOC
2261 elements_3D.push_back(TetMemory.Alloc());
2262 elements_3D.back()->SetVertices(&vert_indices[0]);
2263 elements_3D.back()->SetAttribute(phys_domain);
2265 elements_3D.push_back(
2271 hov->
Append(&vert_indices[0], n_elem_nodes);
2272 ho_verts_3D.push_back(hov);
2273 ho_el_order_3D.push_back(el_order);
2278 case 12: el_order--;
2279 case 92: el_order--;
2280 case 93: el_order--;
2281 case 94: el_order--;
2282 case 95: el_order--;
2283 case 96: el_order--;
2284 case 97: el_order--;
2285 case 98: el_order--;
2288 elements_3D.push_back(
2289 new Hexahedron(&vert_indices[0], phys_domain));
2293 hov->
Append(&vert_indices[0], n_elem_nodes);
2294 ho_verts_3D.push_back(hov);
2295 ho_el_order_3D.push_back(el_order);
2300 case 13: el_order--;
2301 case 90: el_order--;
2302 case 91: el_order--;
2303 case 106: el_order--;
2304 case 107: el_order--;
2305 case 108: el_order--;
2306 case 109: el_order--;
2307 case 110: el_order--;
2310 elements_3D.push_back(
2311 new Wedge(&vert_indices[0], phys_domain));
2315 hov->
Append(&vert_indices[0], n_elem_nodes);
2316 ho_verts_3D.push_back(hov);
2317 ho_el_order_3D.push_back(el_order);
2348 elements_0D.push_back(
2349 new Point(&vert_indices[0], phys_domain));
2353 MFEM_WARNING(
"Unsupported Gmsh element type.");
2360 if (!elements_3D.empty())
2363 NumOfElements = elements_3D.size();
2364 elements.SetSize(NumOfElements);
2365 for (
int el = 0; el < NumOfElements; ++el)
2367 elements[el] = elements_3D[el];
2369 NumOfBdrElements = elements_2D.size();
2370 boundary.SetSize(NumOfBdrElements);
2371 for (
int el = 0; el < NumOfBdrElements; ++el)
2373 boundary[el] = elements_2D[el];
2375 for (
size_t el = 0; el < ho_el_order_3D.size(); el++)
2377 mesh_order = max(mesh_order, ho_el_order_3D[el]);
2380 for (
size_t el = 0; el < elements_1D.size(); ++el)
2382 delete elements_1D[el];
2384 for (
size_t el = 0; el < elements_0D.size(); ++el)
2386 delete elements_0D[el];
2389 else if (!elements_2D.empty())
2392 NumOfElements = elements_2D.size();
2393 elements.SetSize(NumOfElements);
2394 for (
int el = 0; el < NumOfElements; ++el)
2396 elements[el] = elements_2D[el];
2398 NumOfBdrElements = elements_1D.size();
2399 boundary.SetSize(NumOfBdrElements);
2400 for (
int el = 0; el < NumOfBdrElements; ++el)
2402 boundary[el] = elements_1D[el];
2404 for (
size_t el = 0; el < ho_el_order_2D.size(); el++)
2406 mesh_order = max(mesh_order, ho_el_order_2D[el]);
2409 for (
size_t el = 0; el < elements_0D.size(); ++el)
2411 delete elements_0D[el];
2414 else if (!elements_1D.empty())
2417 NumOfElements = elements_1D.size();
2418 elements.SetSize(NumOfElements);
2419 for (
int el = 0; el < NumOfElements; ++el)
2421 elements[el] = elements_1D[el];
2423 NumOfBdrElements = elements_0D.size();
2424 boundary.SetSize(NumOfBdrElements);
2425 for (
int el = 0; el < NumOfBdrElements; ++el)
2427 boundary[el] = elements_0D[el];
2429 for (
size_t el = 0; el < ho_el_order_1D.size(); el++)
2431 mesh_order = max(mesh_order, ho_el_order_1D[el]);
2436 MFEM_ABORT(
"Gmsh file : no elements found");
2452 BasisType::ClosedUniform);
2460 for (
int el = 0; el < NumOfElements; el++)
2462 const int * vm = NULL;
2464 switch (GetElementType(el))
2466 case Element::SEGMENT:
2467 ho_verts = ho_verts_1D[el];
2468 el_order = ho_el_order_1D[el];
2469 if (!ho_lin[el_order])
2471 ho_lin[el_order] =
new int[ho_verts->
Size()];
2474 vm = ho_lin[el_order];
2476 case Element::TRIANGLE:
2477 ho_verts = ho_verts_2D[el];
2478 el_order = ho_el_order_2D[el];
2479 if (!ho_tri[el_order])
2481 ho_tri[el_order] =
new int[ho_verts->
Size()];
2484 vm = ho_tri[el_order];
2486 case Element::QUADRILATERAL:
2487 ho_verts = ho_verts_2D[el];
2488 el_order = ho_el_order_2D[el];
2489 if (!ho_sqr[el_order])
2491 ho_sqr[el_order] =
new int[ho_verts->
Size()];
2494 vm = ho_sqr[el_order];
2496 case Element::TETRAHEDRON:
2497 ho_verts = ho_verts_3D[el];
2498 el_order = ho_el_order_3D[el];
2499 if (!ho_tet[el_order])
2501 ho_tet[el_order] =
new int[ho_verts->
Size()];
2504 vm = ho_tet[el_order];
2506 case Element::HEXAHEDRON:
2507 ho_verts = ho_verts_3D[el];
2508 el_order = ho_el_order_3D[el];
2509 if (!ho_hex[el_order])
2511 ho_hex[el_order] =
new int[ho_verts->
Size()];
2514 vm = ho_hex[el_order];
2516 case Element::WEDGE:
2517 ho_verts = ho_verts_3D[el];
2518 el_order = ho_el_order_3D[el];
2519 if (!ho_wdg[el_order])
2521 ho_wdg[el_order] =
new int[ho_verts->
Size()];
2524 vm = ho_wdg[el_order];
2537 MFEM_WARNING(
"Unsupported Gmsh element type.");
2540 int nv = (ho_verts) ? ho_verts->
Size() : 0;
2542 for (
int v = 0; v<nv; v++)
2544 double * c = GetVertex((*ho_verts)[vm[v]]);
2545 for (
int d=0; d<spaceDim; d++)
2547 Nodes_gf(spaceDim * (o + v) + d) = c[d];
2555 for (
size_t el=0; el<ho_verts_1D.size(); el++)
2557 delete ho_verts_1D[el];
2559 for (
size_t el=0; el<ho_verts_2D.size(); el++)
2561 delete ho_verts_2D[el];
2563 for (
size_t el=0; el<ho_verts_3D.size(); el++)
2565 delete ho_verts_3D[el];
2569 for (
int ord=4; ord<ho_lin.
Size(); ord++)
2571 if (ho_lin[ord] != NULL) {
delete [] ho_lin[ord]; }
2573 for (
int ord=4; ord<ho_tri.
Size(); ord++)
2575 if (ho_tri[ord] != NULL) {
delete [] ho_tri[ord]; }
2577 for (
int ord=4; ord<ho_sqr.
Size(); ord++)
2579 if (ho_sqr[ord] != NULL) {
delete [] ho_sqr[ord]; }
2581 for (
int ord=4; ord<ho_tet.
Size(); ord++)
2583 if (ho_tet[ord] != NULL) {
delete [] ho_tet[ord]; }
2585 for (
int ord=4; ord<ho_hex.
Size(); ord++)
2587 if (ho_hex[ord] != NULL) {
delete [] ho_hex[ord]; }
2589 for (
int ord=4; ord<ho_wdg.
Size(); ord++)
2591 if (ho_wdg[ord] != NULL) {
delete [] ho_wdg[ord]; }
2593 for (
int ord=4; ord<ho_pyr.
Size(); ord++)
2595 if (ho_pyr[ord] != NULL) {
delete [] ho_pyr[ord]; }
2598 MFEM_CONTRACT_VAR(n_partitions);
2599 MFEM_CONTRACT_VAR(elem_domain);
2602 else if (buff ==
"$Periodic")
2609 for (
int i = 0; i < v2v.
Size(); i++)
2616 input >> num_per_ent;
2617 getline(input, buff);
2618 for (
int i = 0; i < num_per_ent; i++)
2620 getline(input, buff);
2621 getline(input, buff);
2622 if (!strncmp(buff.c_str(),
"Affine", 6))
2628 num_nodes = atoi(buff.c_str());
2630 for (
int j=0; j<num_nodes; j++)
2632 input >> slave >> master;
2633 v2v[slave - 1] = master - 1;
2635 getline(input, buff);
2642 for (
int slave = 0; slave < v2v.
Size(); slave++)
2644 int master = v2v[slave];
2645 if (master != slave)
2648 while (v2v[master] != master && master != slave)
2650 master = v2v[master];
2652 if (master == slave)
2661 v2v[slave] = master;
2667 if (mesh_order == 1)
2670 this->SetCurvature(1,
true, spaceDim, Ordering::byVDIM);
2675 for (
int i = 0; i < this->GetNE(); i++)
2677 Element *el = this->GetElement(i);
2680 for (
int j = 0; j < nv; j++)
2687 for (
int i = 0; i < this->GetNBE(); i++)
2689 Element *el = this->GetBdrElement(i);
2692 for (
int j = 0; j < nv; j++)
2700 this->RemoveUnusedVertices();
2703 this->RemoveInternalBoundaries();
2705 this->FinalizeTopology();
2710 SetCurvature(mesh_order, periodic, spaceDim, Ordering::byVDIM);
2713 Nodes->ProjectCoefficient(NodesCoef);
2718 #ifdef MFEM_USE_NETCDF
2719 void Mesh::ReadCubit(
const char *filename,
int &curved,
int &read_gf)
2726 const int sideMapTri3[3][2] =
2733 const int sideMapQuad4[4][2] =
2741 const int sideMapTri6[3][3] =
2748 const int sideMapQuad9[4][3] =
2756 const int sideMapTet4[4][3] =
2764 const int sideMapTet10[4][6] =
2772 const int sideMapHex8[6][4] =
2782 const int sideMapHex27[6][9] =
2784 {1,2,6,5,9,14,17,13,26},
2785 {2,3,7,6,10,15,18,14,25},
2786 {4,3,7,8,11,15,19,16,27},
2787 {1,4,8,5,12,16,20,13,24},
2788 {1,4,3,2,12,11,10,9,22},
2789 {5,8,7,6,20,19,18,17,23}
2794 const int mfemToGenesisTet10[10] = {1,2,3,4,5,7,8,6,9,10};
2797 const int mfemToGenesisHex27[27] = {1,2,3,4,5,6,7,8,9,10,11,
2799 12,17,18,19,20,13,14,15,
2801 16,22,26,25,27,24,23,21
2804 const int mfemToGenesisTri6[6] = {1,2,3,4,5,6};
2805 const int mfemToGenesisQuad9[9] = {1,2,3,4,5,6,7,8,9};
2812 char str_dummy[256];
2819 if ((retval = nc_open(filename, NC_NOWRITE, &ncid)))
2821 MFEM_ABORT(
"Fatal NetCDF error: " << nc_strerror(retval));
2827 size_t num_dim=0, num_nodes=0, num_elem=0, num_el_blk=0, num_side_sets=0;
2829 if ((retval = nc_inq_dimid(ncid,
"num_dim", &
id)) ||
2830 (retval = nc_inq_dim(ncid,
id, str_dummy, &num_dim)) ||
2832 (retval = nc_inq_dimid(ncid,
"num_nodes", &
id)) ||
2833 (retval = nc_inq_dim(ncid,
id, str_dummy, &num_nodes)) ||
2835 (retval = nc_inq_dimid(ncid,
"num_elem", &
id)) ||
2836 (retval = nc_inq_dim(ncid,
id, str_dummy, &num_elem)) ||
2838 (retval = nc_inq_dimid(ncid,
"num_el_blk", &
id)) ||
2839 (retval = nc_inq_dim(ncid,
id, str_dummy, &num_el_blk)))
2841 MFEM_ABORT(
"Fatal NetCDF error: " << nc_strerror(retval));
2843 if ((retval = nc_inq_dimid(ncid,
"num_side_sets", &
id)) ||
2844 (retval = nc_inq_dim(ncid,
id, str_dummy, &num_side_sets)))
2852 size_t *num_el_in_blk =
new size_t[num_el_blk];
2853 size_t num_node_per_el;
2855 int previous_num_node_per_el = 0;
2856 for (
int i = 0; i < (int) num_el_blk; i++)
2858 sprintf(temp_str,
"num_el_in_blk%d", i+1);
2859 if ((retval = nc_inq_dimid(ncid, temp_str, &temp_id)) ||
2860 (retval = nc_inq_dim(ncid, temp_id, str_dummy, &num_el_in_blk[i])))
2862 MFEM_ABORT(
"Fatal NetCDF error: " << nc_strerror(retval));
2865 sprintf(temp_str,
"num_nod_per_el%d", i+1);
2866 if ((retval = nc_inq_dimid(ncid, temp_str, &temp_id)) ||
2867 (retval = nc_inq_dim(ncid, temp_id, str_dummy, &num_node_per_el)))
2869 MFEM_ABORT(
"Fatal NetCDF error: " << nc_strerror(retval));
2876 if ((
int) num_node_per_el != previous_num_node_per_el)
2878 MFEM_ABORT(
"Element blocks of different element types not supported");
2881 previous_num_node_per_el = num_node_per_el;
2885 enum CubitElementType
2907 CubitElementType cubit_element_type = ELEMENT_TRI3;
2908 CubitFaceType cubit_face_type = FACE_EDGE2;
2909 int num_element_linear_nodes = 0;
2913 switch (num_node_per_el)
2917 cubit_element_type = ELEMENT_TRI3;
2918 cubit_face_type = FACE_EDGE2;
2919 num_element_linear_nodes = 3;
2924 cubit_element_type = ELEMENT_TRI6;
2925 cubit_face_type = FACE_EDGE3;
2926 num_element_linear_nodes = 3;
2931 cubit_element_type = ELEMENT_QUAD4;
2932 cubit_face_type = FACE_EDGE2;
2933 num_element_linear_nodes = 4;
2938 cubit_element_type = ELEMENT_QUAD9;
2939 cubit_face_type = FACE_EDGE3;
2940 num_element_linear_nodes = 4;
2945 MFEM_ABORT(
"Don't know what to do with a " << num_node_per_el <<
2946 " node 2D element\n");
2950 else if (num_dim == 3)
2952 switch (num_node_per_el)
2956 cubit_element_type = ELEMENT_TET4;
2957 cubit_face_type = FACE_TRI3;
2958 num_element_linear_nodes = 4;
2963 cubit_element_type = ELEMENT_TET10;
2964 cubit_face_type = FACE_TRI6;
2965 num_element_linear_nodes = 4;
2970 cubit_element_type = ELEMENT_HEX8;
2971 cubit_face_type = FACE_QUAD4;
2972 num_element_linear_nodes = 8;
2977 cubit_element_type = ELEMENT_HEX27;
2978 cubit_face_type = FACE_QUAD9;
2979 num_element_linear_nodes = 8;
2984 MFEM_ABORT(
"Don't know what to do with a " << num_node_per_el <<
2985 " node 3D element\n");
2991 MFEM_ABORT(
"Invalid dimension: num_dim = " << num_dim);
2996 if (cubit_element_type == ELEMENT_TRI3 || cubit_element_type == ELEMENT_QUAD4 ||
2997 cubit_element_type == ELEMENT_TET4 || cubit_element_type == ELEMENT_HEX8)
3001 else if (cubit_element_type == ELEMENT_TRI6 ||
3002 cubit_element_type == ELEMENT_QUAD9 ||
3003 cubit_element_type == ELEMENT_TET10 || cubit_element_type == ELEMENT_HEX27)
3009 size_t *num_side_in_ss =
new size_t[num_side_sets];
3010 for (
int i = 0; i < (int) num_side_sets; i++)
3012 sprintf(temp_str,
"num_side_ss%d", i+1);
3013 if ((retval = nc_inq_dimid(ncid, temp_str, &temp_id)) ||
3014 (retval = nc_inq_dim(ncid, temp_id, str_dummy, &num_side_in_ss[i])))
3016 MFEM_ABORT(
"Fatal NetCDF error: " << nc_strerror(retval));
3021 double *coordx =
new double[num_nodes];
3022 double *coordy =
new double[num_nodes];
3023 double *coordz =
new double[num_nodes];
3025 if ((retval = nc_inq_varid(ncid,
"coordx", &
id)) ||
3026 (retval = nc_get_var_double(ncid,
id, coordx)) ||
3027 (retval = nc_inq_varid(ncid,
"coordy", &
id)) ||
3028 (retval = nc_get_var_double(ncid,
id, coordy)))
3030 MFEM_ABORT(
"Fatal NetCDF error: " << nc_strerror(retval));
3035 if ((retval = nc_inq_varid(ncid,
"coordz", &
id)) ||
3036 (retval = nc_get_var_double(ncid,
id, coordz)))
3038 MFEM_ABORT(
"Fatal NetCDF error: " << nc_strerror(retval));
3043 int **elem_blk =
new int*[num_el_blk];
3044 for (
int i = 0; i < (int) num_el_blk; i++)
3046 elem_blk[i] =
new int[num_el_in_blk[i] * num_node_per_el];
3047 sprintf(temp_str,
"connect%d", i+1);
3048 if ((retval = nc_inq_varid(ncid, temp_str, &temp_id)) ||
3049 (retval = nc_get_var_int(ncid, temp_id, elem_blk[i])))
3051 MFEM_ABORT(
"Fatal NetCDF error: " << nc_strerror(retval));
3054 int *ebprop =
new int[num_el_blk];
3055 if ((retval = nc_inq_varid(ncid,
"eb_prop1", &
id)) ||
3056 (retval = nc_get_var_int(ncid,
id, ebprop)))
3058 MFEM_ABORT(
"Fatal NetCDF error: " << nc_strerror(retval));
3063 int **elem_ss =
new int*[num_side_sets];
3064 int **side_ss =
new int*[num_side_sets];
3066 for (
int i = 0; i < (int) num_side_sets; i++)
3068 elem_ss[i] =
new int[num_side_in_ss[i]];
3069 side_ss[i] =
new int[num_side_in_ss[i]];
3071 sprintf(temp_str,
"elem_ss%d", i+1);
3072 if ((retval = nc_inq_varid(ncid, temp_str, &temp_id)) ||
3073 (retval = nc_get_var_int(ncid, temp_id, elem_ss[i])))
3075 MFEM_ABORT(
"Fatal NetCDF error: " << nc_strerror(retval));
3078 sprintf(temp_str,
"side_ss%d",i+1);
3079 if ((retval = nc_inq_varid(ncid, temp_str, &temp_id)) ||
3080 (retval = nc_get_var_int(ncid, temp_id, side_ss[i])))
3082 MFEM_ABORT(
"Fatal NetCDF error: " << nc_strerror(retval));
3086 int *ssprop =
new int[num_side_sets];
3087 if ((num_side_sets > 0) &&
3088 ((retval = nc_inq_varid(ncid,
"ss_prop1", &
id)) ||
3089 (retval = nc_get_var_int(ncid,
id, ssprop))))
3091 MFEM_ABORT(
"Fatal NetCDF error: " << nc_strerror(retval));
3097 int num_face_nodes = 0;
3098 int num_face_linear_nodes = 0;
3100 switch (cubit_face_type)
3105 num_face_linear_nodes = 2;
3111 num_face_linear_nodes = 2;
3117 num_face_linear_nodes = 3;
3123 num_face_linear_nodes = 3;
3129 num_face_linear_nodes = 4;
3135 num_face_linear_nodes = 4;
3142 int *start_of_block =
new int[num_el_blk+1];
3143 start_of_block[0] = 0;
3144 for (
int i = 1; i < (int) num_el_blk+1; i++)
3146 start_of_block[i] = start_of_block[i-1] + num_el_in_blk[i-1];
3149 int **ss_node_id =
new int*[num_side_sets];
3151 for (
int i = 0; i < (int) num_side_sets; i++)
3153 ss_node_id[i] =
new int[num_side_in_ss[i]*num_face_nodes];
3154 for (
int j = 0; j < (int) num_side_in_ss[i]; j++)
3156 int glob_ind = elem_ss[i][j]-1;
3159 while (iblk < (
int) num_el_blk && glob_ind >= start_of_block[iblk+1])
3163 if (iblk >= (
int) num_el_blk)
3165 MFEM_ABORT(
"Sideset element does not exist");
3167 loc_ind = glob_ind - start_of_block[iblk];
3168 int this_side = side_ss[i][j];
3169 int ielem = loc_ind*num_node_per_el;
3171 for (
int k = 0; k < num_face_nodes; k++)
3174 switch (cubit_element_type)
3176 case (ELEMENT_TRI3):
3178 inode = sideMapTri3[this_side-1][k];
3181 case (ELEMENT_TRI6):
3183 inode = sideMapTri6[this_side-1][k];
3186 case (ELEMENT_QUAD4):
3188 inode = sideMapQuad4[this_side-1][k];
3191 case (ELEMENT_QUAD9):
3193 inode = sideMapQuad9[this_side-1][k];
3196 case (ELEMENT_TET4):
3198 inode = sideMapTet4[this_side-1][k];
3201 case (ELEMENT_TET10):
3203 inode = sideMapTet10[this_side-1][k];
3206 case (ELEMENT_HEX8):
3208 inode = sideMapHex8[this_side-1][k];
3211 case (ELEMENT_HEX27):
3213 inode = sideMapHex27[this_side-1][k];
3217 ss_node_id[i][j*num_face_nodes+k] =
3218 elem_blk[iblk][ielem + inode - 1];
3224 std::vector<int> uniqueVertexID;
3226 for (
int iblk = 0; iblk < (int) num_el_blk; iblk++)
3228 for (
int i = 0; i < (int) num_el_in_blk[iblk]; i++)
3230 for (
int j = 0; j < num_element_linear_nodes; j++)
3232 uniqueVertexID.push_back(elem_blk[iblk][i*num_node_per_el + j]);
3236 std::sort(uniqueVertexID.begin(), uniqueVertexID.end());
3237 std::vector<int>::iterator newEnd;
3238 newEnd = std::unique(uniqueVertexID.begin(), uniqueVertexID.end());
3239 uniqueVertexID.resize(std::distance(uniqueVertexID.begin(), newEnd));
3245 std::map<int,int> cubitToMFEMVertMap;
3246 for (
int i = 0; i < (int) uniqueVertexID.size(); i++)
3248 cubitToMFEMVertMap[uniqueVertexID[i]] = i+1;
3250 MFEM_ASSERT(cubitToMFEMVertMap.size() == uniqueVertexID.size(),
3251 "This should never happen\n");
3257 NumOfVertices = uniqueVertexID.size();
3258 vertices.SetSize(NumOfVertices);
3259 for (
int i = 0; i < (int) uniqueVertexID.size(); i++)
3261 vertices[i](0) = coordx[uniqueVertexID[i] - 1];
3262 vertices[i](1) = coordy[uniqueVertexID[i] - 1];
3265 vertices[i](2) = coordz[uniqueVertexID[i] - 1];
3269 NumOfElements = num_elem;
3270 elements.SetSize(num_elem);
3272 int renumberedVertID[8];
3273 for (
int iblk = 0; iblk < (int) num_el_blk; iblk++)
3275 int NumNodePerEl = num_node_per_el;
3276 for (
int i = 0; i < (int) num_el_in_blk[iblk]; i++)
3278 for (
int j = 0; j < num_element_linear_nodes; j++)
3280 renumberedVertID[j] =
3281 cubitToMFEMVertMap[elem_blk[iblk][i*NumNodePerEl+j]]-1;
3284 switch (cubit_element_type)
3286 case (ELEMENT_TRI3):
3287 case (ELEMENT_TRI6):
3289 elements[elcount] =
new Triangle(renumberedVertID,ebprop[iblk]);
3292 case (ELEMENT_QUAD4):
3293 case (ELEMENT_QUAD9):
3295 elements[elcount] =
new Quadrilateral(renumberedVertID,ebprop[iblk]);
3298 case (ELEMENT_TET4):
3299 case (ELEMENT_TET10):
3301 #ifdef MFEM_USE_MEMALLOC
3302 elements[elcount] = TetMemory.Alloc();
3303 elements[elcount]->SetVertices(renumberedVertID);
3304 elements[elcount]->SetAttribute(ebprop[iblk]);
3306 elements[elcount] =
new Tetrahedron(renumberedVertID,
3311 case (ELEMENT_HEX8):
3312 case (ELEMENT_HEX27):
3314 elements[elcount] =
new Hexahedron(renumberedVertID,ebprop[iblk]);
3324 NumOfBdrElements = 0;
3325 for (
int iss = 0; iss < (int) num_side_sets; iss++)
3327 NumOfBdrElements += num_side_in_ss[iss];
3329 boundary.SetSize(NumOfBdrElements);
3331 for (
int iss = 0; iss < (int) num_side_sets; iss++)
3333 for (
int i = 0; i < (int) num_side_in_ss[iss]; i++)
3335 for (
int j = 0; j < num_face_linear_nodes; j++)
3337 renumberedVertID[j] =
3338 cubitToMFEMVertMap[ss_node_id[iss][i*num_face_nodes+j]] - 1;
3340 switch (cubit_face_type)
3345 boundary[sidecount] =
new Segment(renumberedVertID,ssprop[iss]);
3351 boundary[sidecount] =
new Triangle(renumberedVertID,ssprop[iss]);
3357 boundary[sidecount] =
new Quadrilateral(renumberedVertID,ssprop[iss]);
3370 switch (cubit_element_type)
3372 case (ELEMENT_TRI6):
3374 mymap = (
int *) mfemToGenesisTri6;
3377 case (ELEMENT_QUAD9):
3379 mymap = (
int *) mfemToGenesisQuad9;
3382 case (ELEMENT_TET10):
3384 mymap = (
int *) mfemToGenesisTet10;
3387 case (ELEMENT_HEX27):
3389 mymap = (
int *) mfemToGenesisHex27;
3392 case (ELEMENT_TRI3):
3393 case (ELEMENT_QUAD4):
3394 case (ELEMENT_TET4):
3395 case (ELEMENT_HEX8):
3397 MFEM_ABORT(
"Something went wrong. Linear elements detected when order is 2.");
3409 Nodes->MakeOwner(fec);
3417 for (
int i = 0; i < NumOfElements; i++)
3424 for (
int l = 0; l < dofs.
Size(); l++) { vdofs[l] = dofs[l]; }
3428 while (iblk < (
int) num_el_blk && i >= start_of_block[iblk+1]) { iblk++; }
3429 loc_ind = i - start_of_block[iblk];
3430 for (
int j = 0; j < dofs.
Size(); j++)
3432 int point_id = elem_blk[iblk][loc_ind*num_node_per_el + mymap[j] - 1] - 1;
3433 (*Nodes)(vdofs[j]) = coordx[point_id];
3434 (*Nodes)(vdofs[j]+1) = coordy[point_id];
3437 (*Nodes)(vdofs[j]+2) = coordz[point_id];
3447 for (
int i = 0; i < (int) num_side_sets; i++)
3449 delete [] elem_ss[i];
3450 delete [] side_ss[i];
3455 delete [] num_el_in_blk;
3456 delete [] num_side_in_ss;
3461 for (
int i = 0; i < (int) num_el_blk; i++)
3463 delete [] elem_blk[i];
3467 delete [] start_of_block;
3469 for (
int i = 0; i < (int) num_side_sets; i++)
3471 delete [] ss_node_id[i];
3473 delete [] ss_node_id;
3478 #endif // #ifdef MFEM_USE_NETCDF
Abstract class for all finite elements.
Arbitrary order non-uniform rational B-splines (NURBS) finite elements.
Mesh * Make3D(int nsteps, double rstep, double aspect, int order, bool sfc)
int Size() const
Return the logical size of the array.
void Load(std::istream &in, int fmt=0)
Read an Array from the stream in using format fmt. The format fmt can be:
Class for grid function - Vector with associated FE space.
virtual void GetVertices(Array< int > &v) const =0
Returns element's vertices.
void GmshHOSegmentMapping(int order, int *map)
Generate Gmsh vertex mapping for a Segment.
T * GetData()
Returns the data.
int Size() const
Returns the size of the vector.
void MakeOwner(FiniteElementCollection *fec_)
Make the GridFunction the owner of fec and fes.
virtual void GetElementDofs(int elem, Array< int > &dofs) const
Returns indices of degrees of freedom of element 'elem'.
virtual void SetVertices(const int *ind)
Set the vertices according to the given input.
Data type quadrilateral element.
double * GetData() const
Return a pointer to the beginning of the Vector data.
void skip_comment_lines(std::istream &is, const char comment_char)
Check if the stream starts with comment_char. If so skip it.
void DecodeBase64(const char *src, size_t len, std::vector< char > &buf)
Mesh * Make2D(int nsteps, double rstep, double phi, double aspect, int order, bool sfc)
Class for standard nodal finite elements.
void Load(std::istream **in, int np, int *dim)
Reads a vector from multiple files.
Data type hexahedron element.
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Type
Constants for the classes derived from Element.
Data type triangle element.
size_t NumBase64Chars(size_t nbytes)
const T * Read(const Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for read access to mem with the mfem::Device's DeviceMemoryClass, if on_dev = true...
void GmshHOQuadrilateralMapping(int order, int *map)
Generate Gmsh vertex mapping for a Quadrilateral.
Data type tetrahedron element.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
void GmshHOTriangleMapping(int order, int *map)
Generate Gmsh vertex mapping for a Triangle.
void GmshHOTetrahedronMapping(int order, int *map)
Generate Gmsh vertex mapping for a Tetrahedron.
const Array< int > & GetLexicographicOrdering() const
Get an Array<int> that maps lexicographically ordered indices to the indices of the respective nodes/...
bool StringCompare(const char *s1, const char *s2)
const char * VTKByteOrder()
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
int index(int i, int j, int nx, int ny)
virtual int GetNVertices() const =0
void SetAttribute(const int attr)
Set element's attribute.
Piecewise-(bi)quadratic continuous finite elements.
virtual void SetSpace(FiniteElementSpace *f)
Associate a new FiniteElementSpace with the GridFunction.
void filter_dos(std::string &line)
Check for, and remove, a trailing '\r' from and std::string.
Vector coefficient defined by a vector GridFunction.
void GmshHOHexahedronMapping(int order, int *map)
Generate Gmsh vertex mapping for a Hexahedron.
void CreateVTKElementConnectivity(Array< int > &con, Geometry::Type geom, int ref)
Arbitrary order H1-conforming (continuous) finite elements.
void GmshHOWedgeMapping(int order, int *map)
Generate Gmsh vertex mapping for a Wedge.
Abstract data type element.
Data type line segment element.
Arbitrary order "L2-conforming" discontinuous finite elements.
void DofsToVDofs(Array< int > &dofs, int ndofs=-1) const