// Copyright (c) 2010-2023, Lawrence Livermore National Security, LLC. Produced // at the Lawrence Livermore National Laboratory. All Rights reserved. See files // LICENSE and NOTICE for details. LLNL-CODE-806117. // // This file is part of the MFEM library. For more information and source code // availability visit https://mfem.org. // // MFEM is free software; you can redistribute it and/or modify it under the // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. #ifndef MFEM_CONDUITDATACOLLECTION #define MFEM_CONDUITDATACOLLECTION #include "../config/config.hpp" #ifdef MFEM_USE_CONDUIT #include "datacollection.hpp" #include namespace mfem { /** @brief Data collection that uses the Conduit Mesh Blueprint specification. */ /** ConduitDataCollection provides json, simple binary, and HDF5-based file formats for visualization or restart. It also provides methods that convert between MFEM Meshes and GridFunctions and Conduit Mesh Blueprint descriptions. For more information, see: - LLNL conduit project, https://github.com/LLNL/conduit - HDF5 library, https://support.hdfgroup.org/HDF5 @note The ConduitDataCollection only wraps the mfem objects to save them and creates them on load, Conduit does not own any of the data. The SidreDataCollection provides more features, for example the SidreDataCollection allocates and will own the data backing the mfem objects in the data collection. This class also provides public static methods that convert between MFEM Meshes and GridFunctions and Conduit Mesh Blueprint descriptions. Those that describe MFEM data using Conduit (MFEM to Conduit Blueprint) try to zero-copy as much of data MFEM as possible. The Conduit node result will not own all of the data, however you can easily make a copy of the result node using Conduit's API when necessary. Those that construct MFEM objects from Conduit Nodes (Conduit Blueprint to MFEM) provide a zero-copy option. Zero-copy is only possible if the blueprint data matches the data types provided by the MFEM API, for example: ints for connectivity arrays, doubles for field value arrays, allocations that match MFEM's striding options, etc. If these constraints are not met, MFEM objects that own the data are created and returned. In either case pointers to new MFEM object instances are returned, the zero-copy only applies to data backing the MFEM object instances. @note QuadratureFunction%s (q-fields) are not supported. @note AMR Meshes are not fully supported. @warning This class is still _experimental_, meaning that in future releases, it may not be backward compatible, and the output files generated by the current version may become unreadable. */ /// Data collection with Conduit I/O routines class ConduitDataCollection : public DataCollection { protected: // file name helpers /// Returns blueprint root file name for the current cycle std::string RootFileName(); /// Returns the mesh file name for a given domain at the current cycle std::string MeshFileName(int domain_id, const std::string &file_protocol="hdf5"); /// Returns the mesh output directory for the current cycle std::string MeshDirectoryName(); /// Returns the mesh file pattern for the current cycle std::string MeshFilePattern(const std::string &file_protocol="hdf5"); // Helper functions for Save() /// Saves root file for the current cycle void SaveRootFile(int num_domains, const conduit::Node &n_mesh, const std::string &file_protocol); /// Saves all meshes and fields for the current cycle void SaveMeshAndFields(int domain_id, const conduit::Node &n_mesh, const std::string &file_protocol); // Helper functions for Load() /// Loads contents of the root field for the current cycle into n_root_out void LoadRootFile(conduit::Node &n_root_out); /// Loads all meshes and fields of a given domain id for the current cycle void LoadMeshAndFields(int domain_id, const std::string &file_protocol); // holds currently active conduit relay i/o protocol std::string relay_protocol; public: /// Constructor. The collection name is used when saving the data. /** If @a mesh is NULL, then the mesh can be set later by calling either SetMesh() or Load(). The latter works only in serial. */ ConduitDataCollection(const std::string& collection_name, Mesh *mesh = NULL); #ifdef MFEM_USE_MPI /// Construct a parallel ConduitDataCollection. ConduitDataCollection(MPI_Comm comm, const std::string& collection_name, Mesh *mesh = NULL); #endif /// We will delete the mesh and fields if we own them virtual ~ConduitDataCollection(); /// Set the Conduit relay i/o protocol to use /** Supported options: hdf5 (default), json, conduit_json, conduit_bin */ void SetProtocol(const std::string &protocol); /// Save the collection and a Conduit blueprint root file virtual void Save(); /// Load the collection based blueprint data virtual void Load(int cycle = 0); /* Methods that convert to and from MFEM objects and Conduit Nodes that conform to the mesh blueprint. These methods could be public Mesh and GF members in the future. One draw back is that would require use of MFEM_USE_CONDUIT in the mesh and gridfunc sources vs having everything contained in the conduitdatacollection sources. */ /// Describes a MFEM mesh using the mesh blueprint /** Sets up passed conduit::Node to describe the given mesh using the mesh blueprint. Zero-copies as much data as possible. @a coordset_name, @a main_topology_name, and @a boundary_topology_name control the names used for the mesh blueprint entries. With the default set of names, this method describes the mesh's coordinates with a coordinate set entry named `coords`. Describes the mesh with a topology entry named 'main'. If the mesh has nodes, these are described in a field entry named `mesh_nodes`. If the mesh has an attribute field, this is described in a field entry named `mesh_attribute`. If the mesh has boundary info, this is described in a topology entry named `boundary`. If the boundary has an attribute field, this is described in a field entry named `boundary_attribute`. */ static void MeshToBlueprintMesh(Mesh *m, conduit::Node &out, const std::string &coordset_name = "coords", const std::string &main_topology_name = "main", const std::string &boundary_topology_name = "boundary", const std::string &main_adjset_name = "main_adjset"); /// Describes a MFEM grid function using the mesh blueprint /** Sets up passed conduit::Node out to describe the given grid function using the mesh field blueprint. Zero-copies as much data as possible. @a main_toplogy_name is used to set the associated topology name. With the default setting, the resulting field is associated with the topology `main`. */ static void GridFunctionToBlueprintField(GridFunction *gf, conduit::Node &out, const std::string &main_topology_name = "main"); /// Constructs and MFEM mesh from a Conduit Blueprint Description /** @a main_topology_name is used to select which topology to use, when empty ("") the first topology entry will be used. If zero_copy == true, tries to construct a mesh that points to the data described by the conduit node. This is only possible if the data in the node matches the data types needed for the MFEM API (ints for connectivity, doubles for field values, etc). If these constraints are not met, a mesh that owns the data is created and returned. */ static Mesh *BlueprintMeshToMesh(const conduit::Node &n_mesh, const std::string &main_toplogy_name = "", bool zero_copy = false); /// Constructs and MFEM Grid Function from a Conduit Blueprint Description /** If zero_copy == true, tries to construct a grid function that points to the data described by the conduit node. This is only possible if the data in the node matches the data types needed for the MFEM API (doubles for field values, allocated in soa or aos ordering, etc). If these constraints are not met, a grid function that owns the data is created and returned. */ static GridFunction *BlueprintFieldToGridFunction(Mesh *mesh, const conduit::Node &n_field, bool zero_copy = false); private: /// Converts from MFEM element type enum to mesh bp shape name static std::string ElementTypeToShapeName(Element::Type element_type); /// Converts a mesh bp shape name to a MFEM geom type static mfem::Geometry::Type ShapeNameToGeomType(const std::string &shape_name); }; } // end namespace mfem #endif #endif