18 #ifdef MFEM_USE_ADIOS2
20 #include "../fem/geom.hpp"
21 #include "../general/array.hpp"
22 #include "../mesh/element.hpp"
23 #include "../mesh/mesh.hpp"
24 #include "../fem/gridfunc.hpp"
35 adios2::Variable<T> SafeDefineVariable(adios2::IO io,
36 const std::string& variable_name,
37 const adios2::Dims& shape = adios2::Dims(),
38 const adios2::Dims& start = adios2::Dims(),
39 const adios2::Dims& count = adios2::Dims())
41 adios2::Variable<T> variable = io.InquireVariable<T>(variable_name);
44 if (variable.Count() != count &&
45 variable.ShapeID() == adios2::ShapeID::LocalArray)
47 variable.SetSelection({start, count});
52 variable = io.DefineVariable<T>(variable_name, shape, start, count);
59 adios2::Attribute<T> SafeDefineAttribute(adios2::IO io,
60 const std::string& attribute_name,
62 const std::string& variable_name =
"",
63 const std::string separator =
"/")
65 adios2::Attribute<T> attribute = io.InquireAttribute<T>(attribute_name);
70 return io.DefineAttribute<T>(attribute_name, value, variable_name, separator );
74 adios2::Attribute<T> SafeDefineAttribute(adios2::IO io,
75 const std::string& attribute_name,
76 const T* values,
const size_t size,
77 const std::string& variable_name =
"",
78 const std::string separator =
"/")
80 adios2::Attribute<T> attribute = io.InquireAttribute<T>(attribute_name);
85 return io.DefineAttribute<T>(attribute_name, values, size, variable_name,
89 bool SetBoolParameter(
const std::string key,
90 const std::map<std::string, std::string>& parameters,
91 const bool default_value) noexcept
93 auto it = parameters.find(key);
94 if (it != parameters.end())
96 std::string value = it->second;
97 std::transform(value.begin(), value.end(), value.begin(), ::tolower);
98 if (value ==
"on" || value ==
"true")
102 else if ( value ==
"off" || value ==
"false")
107 return default_value;
115 MPI_Comm comm,
const std::string engineType)
117 adios2_openmode(mode),
118 adios(new adios2::ADIOS(comm)),
119 io(adios->DeclareIO(name))
121 io.SetEngine(engineType);
125 const std::string engineType)
127 adios2_openmode(mode),
128 adios(new adios2::ADIOS()),
129 io(adios->DeclareIO(name))
131 io.SetEngine(engineType);
139 SafeDefineAttribute<std::string>(io,
"vtk.xml", VTKSchema() );
145 const std::map<std::string, std::string>& parameters)
147 io.SetParameters(parameters);
148 refine = SetBoolParameter(
"RefinedData", parameters,
true);
152 const std::string value) noexcept
154 io.SetParameter(key, value);
155 if (key ==
"RefinedData")
157 refine = SetBoolParameter(
"RefinedData", io.Parameters(),
true);
173 if (!engine || !active_step)
175 const std::string message =
"MFEM adios2stream error: calling EndStep "
176 "on uninitialized step (need BeginStep)";
180 SafeDefineAttribute<std::string>(io,
"vtk.xml", VTKSchema() );
187 adios2::Variable<double> var_time = SafeDefineVariable<double>(io,
"TIME");
188 engine.Put(var_time, time);
194 adios2::Variable<int> var_cycle = SafeDefineVariable<int>(io,
"CYCLE");
195 engine.Put(var_cycle, cycle);
200 refinement_level = level;
205 return engine.CurrentStep();
214 SafeDefineAttribute<std::string>(io,
"vtk.xml", VTKSchema() );
228 auto lf_DefineMeshMetadata = [
this](
Mesh& mesh)
231 if (!IsConstantElementType(mesh.
elements))
233 throw std::invalid_argument(
"MFEM::adios2stream ERROR: non-constant "
234 " element types not yet implemented\n");
238 SafeDefineAttribute<std::string>(io,
"format",
"MFEM ADIOS2 BP v0.2" );
239 SafeDefineAttribute<std::string>(io,
"format/version",
"0.2" );
240 std::string mesh_type =
"Unknown";
241 std::vector<std::string> viz_tools;
242 viz_tools.reserve(2);
245 mesh_type =
"MFEM NURBS";
246 viz_tools.push_back(
"NONE");
250 mesh_type =
"MFEM mesh v1.1";
251 viz_tools.push_back(
"NONE");
255 mesh_type =
"MFEM mesh v1.0";
256 viz_tools.push_back(
"Paraview: ADIOS2VTXReader");
257 viz_tools.push_back(
"VTK: vtkADIOS2VTXReader.h");
260 SafeDefineAttribute<std::string>(io,
"format/mfem_mesh", mesh_type );
261 SafeDefineAttribute<std::string>(io,
"format/viz_tools", viz_tools.data(),
266 SafeDefineAttribute<uint32_t>(io,
"dimension",
dimension);
267 SafeDefineVariable<uint32_t>(io,
"NumOfElements", {adios2::LocalValueDim});
268 SafeDefineVariable<uint32_t>(io,
"types");
269 size_t nelements = 0;
270 size_t element_nvertices = 0;
271 size_t nvertices = 0;
275 for (
int i = 0; i < mesh.
GetNE(); ++i)
279 refinement_level, 1);
280 if (refined_geometry ==
nullptr)
282 mfem_error(
"ERROR: could not refine geometry in call to Save with adios2stream \n");
288 nelements += refined_geometry->
RefGeoms.
Size() / element_nvertices;
292 refined_mesh_nelements = nelements;
293 refined_mesh_nvertices = nvertices;
297 nelements =
static_cast<size_t>(mesh.
GetNE());
298 element_nvertices =
static_cast<size_t>(mesh.
elements[0]->GetNVertices());
300 SafeDefineVariable<uint64_t>(io,
"connectivity", {}, {}, {nelements, element_nvertices+1});
301 SafeDefineVariable<int32_t>(io,
"attribute", {}, {}, {nelements});
304 SafeDefineVariable<uint32_t>(io,
"NumOfVertices", {adios2::LocalValueDim});
307 SafeDefineVariable<double>( io,
"vertices", {}, {}, {nvertices,
static_cast<size_t>(
dimension)});
312 if (grid_function ==
nullptr)
314 const size_t nVertices =
static_cast<size_t>(mesh.
GetNV());
315 const size_t spaceDim =
static_cast<size_t>(mesh.
SpaceDimension());
317 SafeDefineVariable<double>( io,
"vertices", {}, {}, {nVertices, spaceDim});
321 const size_t size =
static_cast<size_t>(grid_function->
Size());
323 const size_t components =
static_cast<size_t>(fes->
GetVDim());
324 const size_t tuples = size /components;
325 SafeDefineVariable<double>(io,
"vertices", {}, {}, {tuples, components} );
329 ordering_by_node =
true;
335 auto lf_PrintRefinedMeshData = [
this](
Mesh& mesh)
338 engine.Put(
"NumOfElements", static_cast<uint32_t>(refined_mesh_nelements));
339 engine.Put(
"NumOfVertices", static_cast<uint32_t>(refined_mesh_nvertices));
341 const uint32_t vtkType =
342 GLVISToVTKType(static_cast<int>(mesh.
elements[0]->GetGeometryType()));
343 engine.Put(
"types", vtkType);
345 adios2::Variable<double> var_vertices = io.InquireVariable<
double>(
"vertices");
346 adios2::Variable<double>::Span span_vertices = engine.Put<
double>(var_vertices);
348 adios2::Variable<uint64_t> var_connectivity =
349 io.InquireVariable<uint64_t>(
"connectivity");
350 adios2::Variable<uint64_t>::Span span_connectivity = engine.Put<uint64_t>
353 adios2::Variable<int32_t> var_element_attribute =
354 io.InquireVariable<int32_t>(
"attribute");
355 adios2::Variable<int32_t>::Span span_element_attribute = engine.Put<int32_t>
356 (var_element_attribute);
358 size_t span_vertices_offset = 0;
359 size_t span_connectivity_offset = 0;
360 size_t span_element_attribute_offset = 0;
365 for (
int e = 0; e < mesh.
GetNE(); ++e)
369 refinement_level, 1);
372 for (
int i = 0; i < pmatrix.
Width(); ++i)
374 for (
int j = 0; j < pmatrix.
Height(); ++j)
376 span_vertices[span_vertices_offset + i*pmatrix.
Height() + j] = pmatrix(j, i);
379 span_vertices_offset +=
static_cast<size_t>(pmatrix.
Width()*pmatrix.
Height());
388 for (
int v = 0; v < element_vertices.
Size();)
390 span_connectivity[span_connectivity_offset] =
static_cast<uint64_t
>(nv);
391 ++span_connectivity_offset;
393 span_element_attribute[span_element_attribute_offset] =
static_cast<int32_t
>
395 ++span_element_attribute_offset;
397 for (
int k =0; k < nv; k++, v++ )
399 span_connectivity[span_connectivity_offset] =
static_cast<uint64_t
>
400 (point_id + element_vertices[v]);
401 ++span_connectivity_offset;
408 for (
int e = 0; e < mesh.
GetNE(); ++e)
412 refinement_level, 1);
416 auto lf_PrintMeshData = [&](
Mesh& mesh)
420 lf_PrintRefinedMeshData(mesh);
425 engine.Put(
"NumOfElements", static_cast<uint32_t>(mesh.
GetNE()));
427 const uint32_t vtkType =
428 GLVISToVTKType(static_cast<int>(mesh.
elements[0]->GetGeometryType()));
429 engine.Put(
"types", vtkType);
431 adios2::Variable<uint64_t> varConnectivity =
432 io.InquireVariable<uint64_t>(
"connectivity");
434 adios2::Variable<uint64_t>::Span spanConnectivity =
435 engine.Put<uint64_t>(varConnectivity);
437 adios2::Variable<int32_t> varElementAttribute =
438 io.InquireVariable<int32_t>(
"attribute");
440 adios2::Variable<int32_t>::Span spanElementAttribute =
441 engine.Put<int32_t>(varElementAttribute);
443 size_t elementPosition = 0;
444 for (
int e = 0; e < mesh.
GetNE(); ++e)
446 spanElementAttribute[e] =
static_cast<int32_t
>(mesh.
GetAttribute(e));
448 const int nVertices = mesh.
elements[e]->GetNVertices();
449 spanConnectivity[elementPosition] = nVertices;
450 for (
int v = 0; v < nVertices; ++v)
452 spanConnectivity[elementPosition + v + 1] =
455 elementPosition += nVertices + 1;
459 engine.Put(
"NumOfVertices", static_cast<uint32_t>(mesh.
GetNV()));
463 adios2::Variable<double> varVertices = io.InquireVariable<
double>(
"vertices");
465 adios2::Variable<double>::Span spanVertices = engine.Put(varVertices);
467 for (
int v = 0; v < mesh.
GetNV(); ++v)
470 for (
int coord = 0; coord < space_dim; ++coord)
472 spanVertices[v * space_dim + coord] = mesh.
vertices[v](coord);
479 if (ordering_by_node)
481 adios2::Variable<double> varVertices = io.InquireVariable<
double>(
"vertices");
483 adios2::Variable<double>::Span spanVertices = engine.Put(varVertices);
485 const size_t size =
static_cast<size_t>(grid_function->
Size());
487 const size_t components =
static_cast<size_t>(fes->
GetVDim());
488 const size_t tuples = size /components;
490 const double* data = grid_function->
GetData();
492 for (
size_t i = 0; i < tuples; ++i)
494 for (
size_t j = 0; j < components; ++j)
496 spanVertices[i*components + j] = data[j*tuples + i];
502 grid_function->
Print(*
this,
"vertices");
511 lf_DefineMeshMetadata(ref_mesh);
518 lf_PrintMeshData(ref_mesh);
522 engine.PerformPuts();
525 catch (std::exception& e)
527 const std::string warning =
528 "MFEM: adios2stream exception caught, invalid bp dataset: " + name +
535 const std::string& variable_name,
const data_type type)
537 auto lf_SafeDefine = [&](
const std::string& variable_name,
538 const size_t tuples,
const size_t components,
540 const std::string& fespace_name)
542 adios2::Variable<double> var = io.InquireVariable<
double>(variable_name);
547 io.DefineVariable<
double>(variable_name, {}, {}, {tuples*components});
552 adios2::Dims{components, tuples} :
553 adios2::Dims{tuples, components};
554 io.DefineVariable<
double>(variable_name, {}, {}, count);
556 SafeDefineAttribute<std::string>(io,
"FiniteElementSpace",
557 fespace_name, variable_name);
563 const std::map<std::string, std::string> parameters = io.Parameters();
564 const bool full_data = SetBoolParameter(
"FullData", parameters,
false);
566 if (!full_data && !refine)
576 const size_t components =
static_cast<size_t>(grid_function.
VectorDim());
578 const size_t tuples = refined_mesh_nvertices;
580 lf_SafeDefine(variable_name, tuples, components,
584 point_data_variables.insert(variable_name);
591 adios2::Variable<double> variable = io.InquireVariable<
double>(variable_name);
592 adios2::Variable<double>::Span span = engine.Put<
double>(variable);
599 const int nelements = mesh->
GetNE();
600 for (
int e = 0; e < nelements; ++e)
605 grid_function.
GetValues(e, refined_geometry->
RefPts, scalar, transform);
607 const int size = scalar.
Size();
609 for (
int i = 0; i < size; ++i)
611 const double value = scalar(i);
612 span.at(offset+i) = value;
614 offset +=
static_cast<size_t>(size);
620 for (
int e = 0; e < mesh->
GetNE(); ++e)
626 for (
int i = 0; i < vector.
Width(); ++i)
628 for (
int j = 0; j < vector.
Height(); ++j)
630 span[offset + i*vector.
Height() + j] = vector(j, i);
633 offset +=
static_cast<size_t>(vector.
Width()*vector.
Height());
640 const size_t size =
static_cast<size_t>(grid_function.
Size());
641 const size_t components =
static_cast<size_t>(fes->
GetVDim());
642 const size_t tuples = size /components;
643 lf_SafeDefine(variable_name +
"/full", tuples, components,
647 grid_function.
Print(*
this, variable_name+
"/full");
651 point_data_variables.insert(variable_name+
"/full");
657 int32_t adios2stream::GLVISToVTKType(
658 const int glvisType)
const noexcept
660 uint32_t vtkType = 0;
663 case Geometry::Type::POINT:
666 case Geometry::Type::SEGMENT:
669 case Geometry::Type::TRIANGLE:
672 case Geometry::Type::SQUARE:
676 case Geometry::Type::TETRAHEDRON:
679 case Geometry::Type::CUBE:
683 case Geometry::Type::PRISM:
693 bool adios2stream::IsConstantElementType(
const Array<Element*>& elements )
const
696 bool isConstType =
true;
699 for (
int e = 1; e < elements.Size(); ++e)
701 if (type != elements[e]->GetGeometryType())
710 std::string adios2stream::VTKSchema() const noexcept
712 std::string vtkSchema = R
"(
<?xml version="1.0"?>
<VTKFile type="UnstructuredGrid" version="0.2" byte_order="LittleEndian">
<UnstructuredGrid>
<Piece NumberOfPoints="NumOfVertices" NumberOfCells="NumOfElements">
<Points>
<DataArray Name="vertices" />)";
714 vtkSchema += R"(
</Points>
<CellData>
<DataArray Name="attribute" />
</CellData>
<Cells>
<DataArray Name="connectivity" />
<DataArray Name="types" />
</Cells>
<PointData>)";
716 if (point_data_variables.empty())
722 for (
const std::string& point_datum : point_data_variables )
724 vtkSchema +=
" <DataArray Name=\"" + point_datum +
"\"/>\n";
730 vtkSchema +=
" <DataArray Name=\"TIME\">\n";
731 vtkSchema +=
" TIME\n";
732 vtkSchema +=
" </DataArray>\n";
735 vtkSchema += R
"(
</PointData>
</Piece>
</UnstructuredGrid>
</VTKFile>)";
743 adios2::Mode adios2Mode = adios2::Mode::Undefined;
753 const std::string message =
"MFEM adios2stream ERROR: only "
754 "openmode::out and openmode::in "
755 " are valid, in call to adios2stream constructor";
763 #endif // MFEM_USE_ADIOS2
764 int GetNPoints() const
Returns the number of the points in the integration rule.
Ordering::Type GetOrdering() const
Return the ordering method.
int Size() const
Return the logical size of the array.
void Save(const GridFunction &grid_function, const std::string &variable_name, const data_type type)
void GetVectorValues(int i, const IntegrationRule &ir, DenseMatrix &vals, DenseMatrix &tr) const
Class for grid function - Vector with associated FE space.
void SetTime(const double time)
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
T * Write(Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for write access to mem with the mfem::Device's DeviceMemoryClass, if on_dev = true...
Data type dense matrix using column-major storage.
int Size() const
Returns the size of the vector.
int GetNE() const
Returns number of elements.
double * GetData() const
Return a pointer to the beginning of the Vector data.
Geometry::Type GetElementBaseGeometry(int i) const
void Print(const Mesh &mesh, const adios2stream::mode print_mode=mode::sync)
const IntegrationRule * GetVertices(int GeomType)
Return an IntegrationRule consisting of all vertices of the given Geometry::Type, GeomType...
void SetParameter(const std::string key, const std::string value) noexcept
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Mesh * GetMesh() const
Returns the mesh.
void mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
GeometryRefiner GlobGeometryRefiner
void SetRefinementLevel(const int level) noexcept
RefinedGeometry * Refine(Geometry::Type Geom, int Times, int ETimes=1)
void GetValues(int i, const IntegrationRule &ir, Vector &vals, int vdim=1) const
void SetCycle(const int cycle)
int GetVDim() const
Returns vector dimension.
FiniteElementSpace * FESpace()
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...
int SpaceDimension() const
void Print(std::ostream &out=mfem::out, int width=8) const
Prints vector to stream out.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
size_t CurrentStep() const
void SetParameters(const std::map< std::string, std::string > ¶meters=std::map< std::string, std::string >())
Array< Element * > elements
NURBSExtension * NURBSext
Optional NURBS mesh extension.
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
virtual const char * Name() const
void mfem_warning(const char *msg)
Function called by the macro MFEM_WARNING.
void GetElementTransformation(int i, IsoparametricTransformation *ElTr)
constexpr int dimension
This example only works in 3D. Kernels for 2D are not implemented.
NCMesh * ncmesh
Optional nonconforming mesh extension.
const FiniteElementCollection * FEColl() const
adios2stream(const std::string &name, const openmode mode, MPI_Comm comm, const std::string engine_type="BPFile")
void GetNodes(Vector &node_coord) const
int GetAttribute(int i) const
Return the attribute of element i.