Geometric mesh data added for in-situ visualisation

added access to DUNE mesh geometry and passing through data to Damaris;
Updated command line so users can specifiy Python or Paraview script names and other paramaters that control Damaris
- Simulation name
- Number of dedicated cores or dedicated nodes
- Shared memory region size
- switch to turn off HDF5 output.
- Damaris logging level
This commit is contained in:
josh bowden
2023-09-22 23:23:29 +02:00
parent 18f0d8fd27
commit 8095eb0c48
13 changed files with 1522 additions and 132 deletions

View File

@@ -20,6 +20,8 @@
#include <opm/simulators/utils/DamarisKeywords.hpp>
#include <string>
#include <map>
#include <random>
#include <mpi.h>
/*
Below is the Damaris Keywords supported by Damaris to be filled
@@ -33,39 +35,97 @@
namespace Opm::DamarisOutput
{
std::map<std::string, std::string>
DamarisKeywords(std::string OutputDir, bool enableDamarisOutputCollective)
DamarisKeywords(MPI_Comm comm, std::string OutputDir,
bool enableDamarisOutputCollective,
bool saveToHDF5,
int nDamarisCores,
int nDamarisNodes,
long shmemSizeBytes,
std::string pythonFilename,
std::string simName,
std::string logLevel,
std::string paraviewPythonFilename )
{
std::string saveToHDF5_str("MyStore") ;
if (! saveToHDF5 ) saveToHDF5_str = "" ;
std::string publishToPython_str("") ;
if (pythonFilename != "") publishToPython_str="PythonScript" ; // the name of the PyScript XML element
std::string damarisOutputCollective_str("") ;
if (enableDamarisOutputCollective) {
std::map<std::string, std::string> damaris_keywords = {
{"_SHMEM_BUFFER_BYTES_REGEX_", "536870912"},
{"_DC_REGEX_", "1"},
{"_DN_REGEX_", "0"},
{"_File_Mode", "Collective"},
{"_MORE_VARIABLES_REGEX_", ""},
{"_PATH_REGEX_", OutputDir},
{"_MYSTORE_OR_EMPTY_REGEX_", "MyStore"},
{"_PYTHON_OR_EMPTY_REGEX_", ""},
{"_PYTHON_XML_NAME_", "#"},
{"_PARAVIEWPY_OR_EMPTY_REGEX_", ""},
{"_MESHNAME_OR_HASH_", "#"},
};
return damaris_keywords;
damarisOutputCollective_str="Collective" ;
} else {
std::map<std::string, std::string> damaris_keywords = {
{"_SHMEM_BUFFER_BYTES_REGEX_", "536870912"},
{"_DC_REGEX_", "1"},
{"_DN_REGEX_", "0"},
{"_File_Mode", "FilePerCore"},
{"_MORE_VARIABLES_REGEX_", ""},
{"_PATH_REGEX_", OutputDir},
{"_MYSTORE_OR_EMPTY_REGEX_", "MyStore"},
{"_PYTHON_OR_EMPTY_REGEX_", ""},
{"_PYTHON_XML_NAME_", "#"},
{"_PARAVIEWPY_OR_EMPTY_REGEX_", ""},
{"_MESHNAME_OR_HASH_", "#"},
};
return damaris_keywords;
damarisOutputCollective_str="FilePerCore" ;
}
std::string simName_str ;
if (simName == "") {
// Having a different simulation name is important if multiple simulations
// are running on the same node, as it is used to name the simulations shmem area
// and when one sim finishes it removes its shmem file.
// simName_str = "opm-sim-" + damaris::Environment::GetMagicNumber(comm) ;
// We will just add a random value for now as GetMagicNumber(comm) requires latest Damaris
// Seed with a real random value, if available
std::random_device r;
// Choose a random number between 0 and MAX_INT
std::default_random_engine e1(r());
std::uniform_int_distribution<int> uniform_dist(0, std::numeric_limits<int>::max());
int rand_int = uniform_dist(e1);
simName_str = "opm-sim-" + std::to_string(rand_int) ;
} else {
simName_str = simName ;
}
if ((nDamarisCores > 0) && (nDamarisNodes > 0))
{
nDamarisNodes = 0 ; // Default is to use Damaris Cores
}
std::string nDamarisCores_str ;
if ( nDamarisCores != 0 ) {
nDamarisCores_str = std::to_string(nDamarisCores);
} else {
nDamarisCores_str = "0" ;
}
std::string nDamarisNodes_str ;
if ( nDamarisNodes != 0 ) {
nDamarisNodes_str = std::to_string(nDamarisNodes);
} else {
nDamarisNodes_str = "0" ;
}
std::string shmemSizeBytes_str ;
if ( shmemSizeBytes != 0 ) {
shmemSizeBytes_str = std::to_string(shmemSizeBytes);
} else {
shmemSizeBytes_str = "536870912" ;
}
std::string logLevel_str(logLevel) ;
// _MAKE_AVAILABLE_IN_PYTHON_
// _PYTHON_SCRIPT_
std::map<std::string, std::string> damaris_keywords = {
{"_SHMEM_BUFFER_BYTES_REGEX_", shmemSizeBytes_str},
{"_DC_REGEX_", nDamarisCores_str},
{"_DN_REGEX_", nDamarisNodes_str},
{"_File_Mode", damarisOutputCollective_str},
{"_MORE_VARIABLES_REGEX_", ""},
{"_PATH_REGEX_", OutputDir}, /* Do Not change the string "_PATH_REGEX_" as it is used to search for the output path */
{"_MYSTORE_OR_EMPTY_REGEX_", saveToHDF5_str},
{"_PARAVIEW_PYTHON_SCRIPT_",paraviewPythonFilename}, /* this has to be before _PYTHON_SCRIPT_ entry */
{"_PYTHON_SCRIPT_",pythonFilename}, /* if a Python script is specified then assume that we want to publish the data to Python */
{"_PRESSURE_UNIT_","Pa"},
{"_MAKE_AVAILABLE_IN_PYTHON_",publishToPython_str}, /* must match <pyscript name="PythonScript" */
{"_SIM_NAME_",simName_str},
{"_LOG_LEVEL_",logLevel_str},
};
return damaris_keywords;
}
} // namespace Opm::DamarisOutput

View File

@@ -22,7 +22,7 @@
#include <string>
#include <map>
#include <mpi.h>
/*
Below is the std::map with the keywords that are supported by Damaris.
@@ -34,7 +34,17 @@
namespace Opm::DamarisOutput
{
std::map<std::string,std::string> DamarisKeywords(std::string outputDir, bool enableDamarisOutputCollective);
std::map<std::string, std::string>
DamarisKeywords(MPI_Comm comm, std::string OutputDir,
bool enableDamarisOutputCollective,
bool saveToHDF5,
int nDamarisCores,
int nDamarisNodes,
long shmemSizeBytes,
std::string pythonFilename,
std::string simName,
std::string logLevel,
std::string paraviewPythonFilename ) ;
} // namespace Opm::DamarisOutput

View File

@@ -30,50 +30,56 @@
#include <fmt/format.h>
namespace Opm::DamarisOutput
{
std::string initDamarisXmlFile(); // Defined in initDamarisXMLFile.cpp, to avoid messing up this file.
// Initialize Damaris by filling in th XML file and storing it in the chosen directory
void
initializeDamaris(MPI_Comm comm, int mpiRank, std::string outputDir, bool enableDamarisOutputCollective)
initializeDamaris(MPI_Comm comm, int mpiRank, std::map<std::string, std::string>& find_replace_map )
{
if (outputDir.empty()) {
outputDir = ".";
}
// Prepare the XML file
std::string damaris_config_xml = initDamarisXmlFile();
damaris::model::ModifyModel myMod = damaris::model::ModifyModel(damaris_config_xml);
// The map will make it precise the output directory and FileMode (either FilePerCore or Collective storage)
// The map file find all occurences of the string in position 1 and repalce it/them with string in position 2
std::map<std::string, std::string> find_replace_map = DamarisKeywords(outputDir, enableDamarisOutputCollective);
myMod.RepalceWithRegEx(find_replace_map);
std::string damaris_xml_filename_str = outputDir + "/damaris_config.xml";
if (mpiRank == 0) {
myMod.SaveXMLStringToFile(damaris_xml_filename_str);
}
int damaris_err;
int dam_err_;
/* Get the name of the Damaris input file from an environment variable if available */
const char* cs_damaris_xml_file = getenv("FLOW_DAMARIS_XML_FILE");
if (cs_damaris_xml_file != NULL) {
std::cout << "INFO: initializing Damaris from environment variable FLOW_DAMARIS_XML_FILE: "
if (cs_damaris_xml_file != NULL)
{
std::cout << "INFO: Initializing Damaris from environment variable FLOW_DAMARIS_XML_FILE: "
<< cs_damaris_xml_file << std::endl;
damaris_err = damaris_initialize(cs_damaris_xml_file, MPI_COMM_WORLD);
if (damaris_err != DAMARIS_OK) {
std::cerr << "ERROR: damaris_initialize() error via FLOW_DAMARIS_XML_FILE=" << cs_damaris_xml_file
<< std::endl;
dam_err_ = damaris_initialize(cs_damaris_xml_file, MPI_COMM_WORLD);
if (dam_err_ != DAMARIS_OK) {
OpmLog::error(fmt::format("ERORR: damariswriter::initializeDamaris() : ( rank:{}) "
"damaris_initialize({}, MPI_COMM_WORLD), Damaris Error: {} ",
mpiRank, cs_damaris_xml_file, damaris_error_string(dam_err_) ));
}
} else {
std::cout << "INFO: initializing Damaris using internally built file:" << damaris_xml_filename_str << std::endl;
damaris_err = damaris_initialize(damaris_xml_filename_str.c_str(), comm);
if (damaris_err != DAMARIS_OK) {
std::cerr << "ERROR: damaris_initialize() error via built file:" << std::endl << myMod.GetConfigString();
// Prepare the XML file
std::string damaris_config_xml = initDamarisXmlFile(); // This is the template for a Damaris XML file
damaris::model::ModifyModel myMod = damaris::model::ModifyModel(damaris_config_xml);
// The map will make it precise the output directory and FileMode (either FilePerCore or Collective storage)
// The map file find all occurences of the string in position 1 and replace it/them with string in position 2
// std::map<std::string, std::string> find_replace_map = DamarisKeywords(outputDir, enableDamarisOutputCollective);
myMod.RepalceWithRegEx(find_replace_map);
std::string outputDir = find_replace_map["_PATH_REGEX_"] ;
std::string damaris_xml_filename_str = outputDir + "/damaris_config.xml";
if (mpiRank == 0) {
myMod.SaveXMLStringToFile(damaris_xml_filename_str);
}
std::cout << "INFO: Initializing Damaris using internally built file:" << damaris_xml_filename_str << " (N.B. use FLOW_DAMARIS_XML_FILE to override)" << std::endl;
dam_err_ = damaris_initialize(damaris_xml_filename_str.c_str(), comm);
if (dam_err_ != DAMARIS_OK) {
OpmLog::error(fmt::format("ERORR: damariswriter::initializeDamaris() : ( rank:{}) "
"damaris_initialize({}, MPI_COMM_WORLD), Damaris Error: {}. Error via OPM internally built file:",
mpiRank, cs_damaris_xml_file, damaris_error_string(dam_err_) ));
}
}
}
} // namespace Opm::DamarisOutput

View File

@@ -18,7 +18,14 @@
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <opm/common/OpmLog/OpmLog.hpp>
#include <limits>
#include <stdexcept>
#include <string>
#include <fmt/format.h>
#include <mpi.h>
#include <Damaris.h>
#include <opm/simulators/utils/ParallelCommunication.hpp>
@@ -34,7 +41,7 @@ namespace Opm::DamarisOutput
{
// Initialize an XML file
std::string initDamarisXmlFile();
// Initialize Damaris by filling in th XML file and stroring it in the chosed directory
void initializeDamaris(MPI_Comm comm, int mpiRank, std::string OutputDir, bool enableDamarisOutputCollective);
// Initialize Damaris by filling in th XML file and storing it in the chosen directory
void initializeDamaris(MPI_Comm comm, int mpiRank, std::map<std::string, std::string>& find_replace_map );
} // namespace Opm::DamarisOutput

View File

@@ -0,0 +1,620 @@
/*
Copyright 2023 Inria, BretagneAtlantique Research Center
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DAMARIS_MODEL_DATA_HPP
#define DAMARIS_MODEL_DATA_HPP
#include <string>
#include <iostream>
#include <sstream>
#include <cassert>
#include <typeinfo>
#include <Damaris.h>
/*
File: DamarisVar.hpp
Author: Joshua Bowden, Inria
Date: 06/02/2023
The DamarisVar class can be used to allocate memory in the Damaris shared memory region and a user can supply
the data required for the variable to pass to Damaris.
*/
namespace Opm
{
namespace DamarisOutput
{
/**
* This class contains the extra elements that need to be part of a Damaris <variable> type.
* They are simple string values that may reference other XML elements (and could be checked for existence etc.)
*/
class DamarisVarXMLAttributes {
std::string layout_ ; //!< Reference string to the XML attribute layout being used to describe the shape of the variable. This is a required attribute.
std::string mesh_ ; //!< Reference string to the XML attribute mesh element - the mesh is used to define the spatial layout of data and is used by visualization backends to generate 2D/3D model images
std::string type_ ; //!< Reference string to the XML attribute type of data - "scalar" or "vector" (others tensor maybe). TODO: check if this attribute is used by the Damaris library anywhere.
std::string visualizable_ ; //!< Reference string to the XML attribute property that data can be sent to vis backends - "true" | "false"
std::string unit_ ; //!< Reference string to the XML attribute element denoting unit of the data
std::string time_varying_ ; //!< Reference string to the XML attribute to indicate if data changes over iterations - "true" | "false"
std::string centering_ ; //!< Reference string to the XML attribute to indicate where data aligns on a mesh - "zonal" | "nodal"
std::string store_ ; //!< Reference string to the XML attribute to indicate if data should be passed to I/O store (e.g. to HDF5 plugin)
std::string script_ ; //!< Reference string to the XML attribute to indicate if data should be published as Python NumPy data
std::string select_mem_ ; //!< Reference string to the XML attribute select. The referenced variables data is used as indices to select dat from memory to reorder output in the collective HDF5 data writer (Damaris version 1.8+)
std::string select_file_ ; //!< Reference string to the XML attribute select. The referenced variables data is used as indices to select positions in the dataset file to reorder output in the collective HDF5 data writer (Damaris version 1.8+)
std::string select_subset_ ; //!< Reference string to the XML attribute select. Used to specify the output dataset shape and how much data each rank contributes to it and the global offsets to the ranks data (Damaris version 1.8+)
public:
DamarisVarXMLAttributes(){
// Additional data needed to complete an XML <variable> element
layout_ = "" ;
mesh_ = "" ;
type_ = "scalar" ; // This is probably not needed as vector data is defined using the Layout paramter. Could be useful for cross checking
visualizable_ = "false";
unit_ = "" ;
time_varying_ = "true";
centering_ = "zonal" ;
store_ = "" ;
script_ = "" ;
select_mem_ = "" ;
}
/**
* Creates the XML representation of the variable from the available strings
*/
std::string ReturnXMLForVariable ( void )
{
std::ostringstream var_sstr ;
var_sstr << " layout=\"" << this->layout_ << "\"" ;
if (this->mesh_ != "") var_sstr << " mesh=\"" << this->mesh_ << "\"" ;
if (this->type_ != "") var_sstr << " type=\"" << this->type_ << "\"" ;
if (this->visualizable_ != "") var_sstr << " visualizable=\"" << this->visualizable_ << "\"" ;
if (this->unit_ != "") var_sstr << " unit=\"" << this->unit_ << "\"" ;
if (this->time_varying_ != "") var_sstr << " time_varying=\"" << this->time_varying_ << "\"" ;
if (this->centering_ != "") var_sstr << " centering=\"" << this->centering_ << "\"" ;
if (this->store_ != "") var_sstr << " store=\"" << this->store_ << "\"" ;
if (this->script_ != "") var_sstr << " script=\"" << this->script_ << "\"" ;
if (this->select_mem_ != "") var_sstr << " select-mem=\"" << this->select_mem_ << "\"" ;
if (this->select_file_ != "") var_sstr << " select-file=\"" << this->select_file_ << "\"" ;
if (this->select_subset_ != "") var_sstr << " select-subset=\"" << this->select_subset_ << "\"" ;
return (var_sstr.str()) ;
}
} ;
class DamarisVarBase {
public:
// DamarisVarBase(int dims, std::vector<std::string>& param_names, std::string& variable_name, int rank=0) = 0 ;
virtual ~DamarisVarBase( void ) {} ;
virtual void PrintError ( void ) = 0 ;
virtual bool HasError( void ) = 0 ;
// virtual void SetDamarisParameterAndShmem( std::vector<int>& paramSizeVal ) = 0 ;
virtual void SetDamarisParameterAndShmem( std::vector<int> paramSizeVal ) = 0 ;
virtual void SetDamarisParameter( std::vector<int>& paramSizeVal ) = 0 ;
virtual void SetDamarisPosition( std::vector<int64_t> positionsVals ) = 0 ;
virtual void SetPointersToDamarisShmem( void ) = 0 ;
virtual void CommitVariableDamarisShmem( void ) = 0 ;
virtual void ClearVariableDamarisShmem( void ) = 0 ;
// virtual void * data_ptr( void ) = 0 ;
virtual std::string & variable_name( void ) = 0 ;
}; // class DamarisVar
/**
* class to store a Damaris variable representation for the XML file (can be used with /ref class DamarisKeywords).
*
* It is thought that the details stored in the object can be used to pass into an XML generation function e.g. DamarisKeywords
*
* Should be instantiated with something like the following:
* // The following needs to be defined in the Damaris XML file:
* // <parameter name="n_elements_mpi_local" type="int" value="1" />
* // <layout name="mpi_layout" type="int" dimensions="n_elements_mpi_local" comment="MPI elements layout" />
* // <variable name="MPI_RANK" layout="mpi_layout" type="scalar" visualizable="true" mesh="unstructured_mesh" unit="rank" centering="zonal"
* // store="#" time-varying="false" script="_PYTHON_XML_NAME_" comment="The cells MPI rank"/>
* damaris::model::DamarisVar<int> dam_var = new damaris::model::DamarisVar<int>(1, {std::string("n_connectivity_ph")}, std::string("topologies/topo/elements/connectivity"), rank_) ;
* dam_var->SetDamarisParameterAndShmem( { geomData.getNCorners() } ) ;
*
* int * shmem_mpi_ptr = dam_var->data_ptr() ;
* // Fill the created memory area
* for (int i = 0 ; i < ; i++ )
* {
* shmem_mpi_ptr[i] = rank_ ;
* }
* delete dam_var ; // this tells Damaris that the shared memory that it supplied is at its disposal. It will print error messages too.
*
*/
template <typename T>
class DamarisVar :
public DamarisVarBase {
int dims_ ;
int num_params_ ; //!< Each paramater name string will need a value and they are set in SetDamarisParameter()
int * param_sizes_ ; //!< The value for any paramaters that are being used to describe the size of the variables data array
int64_t * positions_ ; //!< The offsets into the array that the data in the Variable starts from for this rank.
int rank_ ; //!< Rank of process - used for error reporting.
bool paramaters_set_ ; //!< set to true after SetDamarisParameter() is call to ensure the variable has correct size for memory allocation in SetPointersToDamarisShmem()
std::vector<std::string> param_names_ ; //!< Contains one paramater name for each paramater that a variable depends on (via it's Layout)
std::string variable_name_ ; //!< Reference string to the XML attribute name of the variable.
int dam_err_ ; //!< Set to != DAMARIS_OK if a Daamris error was returned by a Damaris API function call
bool has_error_ ;
std::ostringstream dam_err_sstr_ ; //!< Use dam_err_sstr.str() to return an error string describing detected error
DamarisVarXMLAttributes xml_attributes_ ; //!< The extra elements that need to be part of a Damaris <variable> type. They are simple string values that may reference other XML elements (and could be checked for existence etc.)
T * data_ptr_ ; //!< This pointer will be mapped to the Damaris shared memory area for the variable in the SetPointersToDamarisShmem() method. The type T will match the Layout type
public:
/**
* Constructor - sets private data values and dos not initialise the shared memory area.
*
* Two usages:
* Example XML definition:
* <parameter name="my_param_name1" type="int" value="1" />
* <parameter name="my_param_name2" type="int" value="1" />
* <layout name="my_layout" type="int" dimensions="my_param_name1,my_param_name2" comment="This is a 2D variable" />
* <variable name="MYVARNAME" layout="my_layout" visualizable="true"/>
*
* 1/ The variable's layout needs to be initialised via parameters :
* // Create the DamarisVar object:
* damaris::model::DamarisVar<int> MYVARNAME_2d = new damaris::model::DamarisVar<int>(2, {std::string("my_param_name1"), std::string("my_param_name2")}, std::string("MYVARNAME"), rank_) ;
* // Set the paramter sizes
* MYVARNAME_2d->SetDamarisParameterAndShmem( {25, 100 } } ; // sets the paramaters (here, my_param_name1 == 25 and my_param_name2 == 100)
* // Get a pointer to the memeory and use it
* T * mymemory = MYVARNAME_2d->data_ptr() ;
* ... write data to mymemory ....
* delete MYVARNAME_2d ;
* or,
* 2/ The variable's layout has been initialised via parameters in another variable (i.e. "my_param_name1" and "my_param_name2" have been previously set in the code)
* // Create the DamarisVar object:
* damaris::model::DamarisVar<int> MYVARNAME_2d = new damaris::model::DamarisVar<int>(2, {std::string("my_param_name1"), std::string("my_param_name2")}, std::string("MYVARNAME"), rank_) ;
* // explicitly state that the paramater values have been set somewhere else in the code previously.
* MYVARNAME_2d->ParameterIsSet() ;
* MYVARNAME_2d->SetPointersToDamarisShmem()
* // Get a pointer to the memeory and use it
* T * mymemory = MYVARNAME_2d->data_ptr() ;
* ... write data to mymemory ....
* delete MYVARNAME_2d ;
*
* /param [IN] dims Used to check that the inputs to SetDamarisPosition() have the same number of values - one value for each dimension
* /param [IN] param_names The name the Damaris paramaters. These names (in typical use) control a Damaris variables size (names are defined in the Damaris XML file).
* /param [IN] variable_name The name of the Damaris variable (defined in the Dmaaris XML file)
* /param [IN] rank The rank of the process. Used for error output.
*/
DamarisVar(int dims, std::vector<std::string> param_names, std::string variable_name, int rank)
: dims_( dims ),
param_names_( param_names ),
variable_name_( variable_name ),
rank_(rank)
{
dam_err_ = DAMARIS_OK ;
assert( param_names_.size() == dims ) ;
assert( dims > 0 ) ;
// Check that our template type T matches out Damaris XML <layout> type
if ( !TestType(variable_name) ) {
std::exit(-1) ;
}
num_params_ = param_names_.size() ;
param_sizes_ = new int(num_params_) ;
positions_ = new int64_t(dims) ;
data_ptr_ = nullptr ;
paramaters_set_ = false ;
has_error_ = false ;
}
/**
* Constructor - Sets private data values and also initialises the Damaris shared memory area for writing (and reading)
* by specifying the values for the variables parameters . i.e. makes the data_ptr()
*
* Example use:
* Example XML definition:
* <parameter name="my_param_name1" type="int" value="1" />
* <parameter name="my_param_name2" type="int" value="1" />
* <layout name="my_layout" type="int" dimensions="my_param_name1,my_param_name2" comment="This is a 2D variable" />
* <variable name="MYVARNAME" layout="my_layout" visualizable="true"/>
* // The paramaters are intialized in the constructor code
* damaris::model::DamarisVar<int> MYVARNAME_2d = new damaris::model::DamarisVar<int>(2, {std::string("my_param_name1"), std::string("my_param_name2")}, {100, 25}, std::string("MYVARNAME"), rank_) ;
* T * mymemory = MYVARNAME_2d->data_ptr() ;
* ... write data to mymemory ....
* delete MYVARNAME_2d ;
*
* /param [IN] dims Used to check that the inputs to SetDamarisPosition() have the same number of values - one value for each dimension
* /param [IN] param_names The name the Damaris paramaters. These names (in typical use) control a Damaris variables size (names are defined in the Damaris XML file).
* /param [IN] param_values The values of the paramaters - this defines how much memory we will have access to in the shared memory area (on the current and ongoing iterations, until later modified to new values)
* /param [IN] variable_name The name of the Damaris variable (defined in the Dmaaris XML file)
* /param [IN] rank The rank of the process. Used for error output.
*/
DamarisVar(int dims, std::vector<std::string> param_names, std::vector<int> param_values, std::string variable_name, int rank)
: dims_( dims ),
param_names_( param_names ),
variable_name_( variable_name ),
rank_(rank)
{
dam_err_ = DAMARIS_OK ;
assert( param_names_.size() == dims ) ;
assert( dims > 0 ) ;
// Check that our template type T matches out Damaris XML <layout> type
if ( !TestType(variable_name) ) {
std::exit(-1) ;
}
num_params_ = param_names_.size() ;
param_sizes_ = new int(num_params_) ;
positions_ = new int64_t(dims) ;
data_ptr_ = nullptr ;
paramaters_set_ = false ;
has_error_ = false ;
SetDamarisParameterAndShmem( param_values ) ; // Initialise the memory size in the constructor.
}
~DamarisVar( void ) {
delete [] param_sizes_ ;
delete [] positions_ ;
if (data_ptr_ != nullptr)
{
CommitVariableDamarisShmem() ;
ClearVariableDamarisShmem() ;
}
if (this->HasError())
PrintError() ; // flush out any error messages
}
/**
* Method to check that the template paramater T is the same as the requested type for the variable in the XML file
*/
bool TestType(std::string variable_name)
{
bool resbool = true ;
// This gets the type of the Damaris XML <variable>'s <layout>
DAMARIS_TYPE_STR vartype ;
dam_err_ = damaris_get_type(variable_name.c_str(), &vartype) ;
if (dam_err_ != DAMARIS_OK) {
dam_err_sstr_ << " ERROR rankDamarisVar::DamarisVar () damaris_get_type(\""
<< variable_name_ << "\", vartype); Damaris error = " << damaris_error_string(dam_err_) << std::endl ;
has_error_ = true ;
return( false ) ;
}
T test_id;
const std::type_info& t1 = typeid(test_id) ;
if (vartype == DAMARIS_TYPE_DOUBLE)
{
double td = 0.0 ;
const std::type_info& t2 = typeid(td) ;
if (t1 != t2) {
OutputErrorAndAssert(variable_name, t1.name(), t2.name()) ;
resbool = false ;
}
}
else if (vartype == DAMARIS_TYPE_FLOAT)
{
float td = 0.0f ;
const std::type_info& t2 = typeid(td) ;
if (t1 != t2) {
OutputErrorAndAssert(variable_name, t1.name(), t2.name()) ;
resbool = false ;
}
}
else if (vartype == DAMARIS_TYPE_CHAR)
{
char td = 0;
const std::type_info& t2 = typeid(td) ;
if (t1 != t2) {
OutputErrorAndAssert(variable_name, t1.name(), t2.name()) ;
resbool = false ;
}
}
else if (vartype == DAMARIS_TYPE_UCHAR)
{
unsigned char td = 0;
const std::type_info& t2 = typeid(td) ;
if (t1 != t2) {
OutputErrorAndAssert(variable_name, t1.name(), t2.name()) ;
resbool = false ;
}
}
else if (vartype == DAMARIS_TYPE_SHORT)
{
short td = 0;
const std::type_info& t2 = typeid(td) ;
if (t1 != t2) {
OutputErrorAndAssert(variable_name, t1.name(), t2.name()) ;
resbool = false ;
}
}
else if (vartype == DAMARIS_TYPE_USHORT)
{
unsigned short td = 0;
const std::type_info& t2 = typeid(td) ;
if (t1 != t2) {
OutputErrorAndAssert(variable_name, t1.name(), t2.name()) ;
resbool = false ;
}
}
else if (vartype == DAMARIS_TYPE_INT)
{
int td = 0;
const std::type_info& t2 = typeid(td) ;
if (t1 != t2) {
OutputErrorAndAssert(variable_name, t1.name(), t2.name()) ;
resbool = false ;
}
}
else if (vartype == DAMARIS_TYPE_UINT)
{
unsigned int td = 0;
const std::type_info& t2 = typeid(td) ;
if (t1 != t2) {
OutputErrorAndAssert(variable_name, t1.name(), t2.name()) ;
resbool = false ;
}
}
else if (vartype == DAMARIS_TYPE_LONG)
{
long td = 0;
const std::type_info& t2 = typeid(td) ;
if (t1 != t2) {
OutputErrorAndAssert(variable_name, t1.name(), t2.name()) ;
resbool = false ;
}
}
else if (vartype == DAMARIS_TYPE_ULONG)
{
unsigned long td = 0;
const std::type_info& t2 = typeid(td) ;
if (t1 != t2) {
OutputErrorAndAssert(variable_name, t1.name(), t2.name()) ;
resbool = false ;
}
}
else if (vartype == DAMARIS_TYPE_UNDEFINED)
{
std::cerr << "ERROR rank =" << rank_ << " : DamarisVar::DamarisVar():: \"" << variable_name << "\" has type DAMARIS_TYPE_UNDEFINED"<< std::endl ;
resbool = false ;
}
else
{
std::cerr << "ERROR rank =" << rank_ << " : DamarisVar::DamarisVar():: \"" << variable_name << "\" is not of available type "<< std::endl ;
resbool = false ;
}
return resbool ;
}
/**
* Allow a user to indicate that the Damaris variable has allocated a size -
* This method is usefull as a single paramater can control one or more layouts and
* a single layout can describe the size of multiple <variable> elements.
* i.e. The current variable has had it's paramater(s) set through via another variable.
*/
void ParameterIsSet()
{
paramaters_set_ = true ;
}
void PrintError ( void )
{
std::cerr << dam_err_sstr_.str() ;
}
bool HasError( void )
{
return (has_error_) ;
}
/**
* Returns the data pointer to shared memory, or nullptr if it has not been allocated
*/
T * data_ptr( void )
{
return (data_ptr_) ;
}
std::string & variable_name( void )
{
return (variable_name_) ;
}
/**
* Creates the XML representation of the variable from the available strings
*/
std::string ReturnXMLForVariable ( void )
{
std::ostringstream var_sstr ;
var_sstr << "<variable " << " name=\"" << variable_name_ << "\"" ;
var_sstr << xml_attributes_.ReturnXMLForVariable() ;
var_sstr << " /> " ;
return var_sstr.str() ;
}
/**
* Method to set the Damaris paramater values and set the shmem region \ref data_ptr_
*
* /param [IN] paramSizeVal : A vector of values to set the Damaris paramters to. One element per param_names_ string
*
*
*/
void SetDamarisParameterAndShmem( std::vector<int> paramSizeVal )
{
this->SetDamarisParameter( paramSizeVal ) ;
this->SetPointersToDamarisShmem() ;
}
/**
* Method to set the Damaris paramater values.
*
* /param [IN] paramSizeVal : An pointer to a value or array of values to set. One element per param_names_ string
*
* /implicit : Implicitly uses the array of paramater names: \ref param_names_
*/
void SetDamarisParameter( std::vector<int>& paramSizeVal )
{
assert(paramSizeVal.size() == num_params_) ;
bool resbool = true ;
for (int varnum = 0 ; varnum < num_params_ ; varnum++)
{
param_sizes_[varnum] = paramSizeVal[varnum] ;
dam_err_ = damaris_parameter_set(param_names_[varnum].c_str(), &paramSizeVal[varnum], sizeof(int));
if (dam_err_ != DAMARIS_OK) {
dam_err_sstr_ << " ERROR rank =" << rank_ << " : class DamarisVar : damaris_parameter_set(\"" << param_names_[varnum]
<< "\", paramSizeVal, sizeof(int)); Damaris error = " << damaris_error_string(dam_err_) << std::endl ;
resbool = false ;
has_error_ = true ;
}
}
if (resbool == true)
paramaters_set_ = true ;
}
/**
* Method to set the Damaris position values.
*
* /param [IN] positionsVals : An pointer to a value or array of values to set as the offset into the array.
* One element per dimension (one value for each dim_)
*
* /implicit : Implicitly uses the variable name: \ref variable_name_
*/
void SetDamarisPosition( std::vector<int64_t> positionsVals )
{
assert(positionsVals.size() == dims_) ;
for (int pos_dim = 0 ; pos_dim < dims_ ; pos_dim++)
{
positions_[pos_dim] = positionsVals[pos_dim] ;
}
dam_err_ = damaris_set_position(variable_name_.c_str(), positionsVals.data());
if (dam_err_ != DAMARIS_OK) {
dam_err_sstr_ << " ERROR rank =" << rank_ << " : class DamarisVar : damaris_set_position(\""
<< variable_name_ << "\", positionsVals); Damaris error = " << damaris_error_string(dam_err_) << std::endl ;
has_error_ = true ;
}
}
/**
* Method to set the Damaris paramater values.
*
* /implicit : Implicitly uses the Damaris variable name string \ref variable_name_
* /implicit : Implicitly uses the class data element : \ref data_ptr_
*/
void SetPointersToDamarisShmem( void )
{
if (paramaters_set_ == true )
{
// Allocate memory in the shared memory section...
dam_err_ = damaris_alloc(variable_name_.c_str(), (void **) &data_ptr_) ;
if (dam_err_ != DAMARIS_OK) {
dam_err_sstr_ << " ERROR rank =" << rank_ << " : class DamarisVar : damaris_alloc(\""
<< variable_name_ <<"\", (void **) &ret_ptr)" << ", Damaris error = " << damaris_error_string(dam_err_) << std::endl ;
has_error_ = true ;
}
} else {
dam_err_ = -1 ;
dam_err_sstr_ << "ERROR rank =" << rank_ << " : class DamarisVar : SetDamarisParameter() should be called first so as to define the size of the memory block required for variable : " << variable_name_ << std::endl ;
has_error_ = true ;
}
}
void SetPointersToDamarisShmem( T ** ptr_in )
{
if (paramaters_set_ == true )
{
T * temp_ptr ;
// Allocate memory in the shared memory section...
dam_err_ = damaris_alloc(variable_name_.c_str(), (void **) &temp_ptr) ;
if (dam_err_ != DAMARIS_OK) {
dam_err_sstr_ << " ERROR rank =" << rank_ << " : class DamarisVar : damaris_alloc(\""
<< variable_name_ <<"\", (void **) &ret_ptr)" << ", Damaris error = " << damaris_error_string(dam_err_) << std::endl ;
has_error_ = true ;
}
*ptr_in = temp_ptr ;
data_ptr_ = temp_ptr ;
} else {
dam_err_ = -1 ;
dam_err_sstr_ << " ERROR rank =" << rank_ << " : class DamarisVar : SetDamarisParameter() should be called first so as to define the size of the memory block required for variable : " << variable_name_ << std::endl ;
has_error_ = true ;
}
}
/**
* Method to commit the memory of the data written to the Damaris variable -
* Indicates that we will not write any more data to \ref data_ptr_
*
* /implicit : Implicitly uses the variable name string \ref variable_name_
*/
void CommitVariableDamarisShmem( void )
{
// Signal to Damaris we are done writing data for this iteration
dam_err_ = damaris_commit (variable_name_.c_str()) ;
if (dam_err_ != DAMARIS_OK) {
dam_err_sstr_ << " ERROR rank =" << rank_ << " : class DamarisVar : damaris_commit(\""
<< variable_name_ <<"\")" << ", Damaris error = " << damaris_error_string(dam_err_) << std::endl ;
has_error_ = true ;
}
}
/**
* Method to release the memory of the data written to the Damaris variable -
* Indicates that Damaris may take control of the shared memory area that was used for the variable \ref data_ptr_
*
* /implicit : Implicitly uses the variable name string \ref variable_name_
*/
void ClearVariableDamarisShmem( void )
{
// Signal to Damaris it has complete charge of the memory area
dam_err_ = damaris_clear(variable_name_.c_str()) ;
if (dam_err_ != DAMARIS_OK) {
dam_err_sstr_ << " ERROR rank =" << rank_ << " : class DamarisVar : damaris_clear(\""
<< variable_name_ << "\")" << ", Damaris error = " << damaris_error_string(dam_err_) << std::endl ;
has_error_ = true ;
}
data_ptr_ = nullptr ;
}
private:
void OutputErrorAndAssert(std::string& var_name, std::string type_name1, std::string type_name2)
{
dam_err_sstr_ << "ERROR rank =" << rank_ << " : DamarisVar::DamarisVar () variable_name_: \"" << var_name
<< "\" The template type of Type of DamarisVar<T> in the code: " << type_name1 << " does not match type in XML (float)" << std::endl ;
PrintError() ;
assert( type_name1 == type_name2 ) ;
}
}; // class DamarisVar
} // namespace DamarisOutput
} // namespace OPM
#endif

View File

@@ -0,0 +1,455 @@
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
/*
Copyright 2023 Inria, BretagneAtlantique Research Center
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPM_SIM_MESH_DATA2_HPP
#define OPM_SIM_MESH_DATA2_HPP
#include <sstream>
#include <dune/grid/common/rangegenerators.hh>
#include <dune/grid/io/file/vtk/common.hh>
/** @file
@brief Allows model geometry data to be passed to external code - via a copy direct to input pointers.
This data extractor provides the full set of vertices (corresponding to Dune::Partition::all) and then
allows a user to specify Dune sub-partitions to get the references into the vertex array and element
(aka cell) types for the sub-partition. This allows the full set of verticies to be reused for
visualisation of the various sub-partitions, at the expense of copying all the vertices. Typically
a user is interested in the interiorBoarder elements which make use of the bulk (~80%) of the vertices.
This saves having to renumber the indexes to the vertices for the sub-partitions.
The vertex data can be retrieved as seperate x, y and z arrays, or as a single array of structures,
or as a single structure of arrays based
Example:
// From the opm-simulators repository
#include <opm/simulators/utils/GridDataOutput.hpp>
// N.B. does not seem to be able to be allocated with new operator.
Opm::GridDataOutput::SimMeshDataAccessor geomData(gridView, Dune::Partition::interior ) ;
geomData.printGridDetails() ;
// example using seperate x, y and z arrays
int nvert = geomData.getNVertices() ;
double * x_vert = new double[nvert] ;
double * y_vert = new double[nvert] ;
double * z_vert = new double[nvert] ;
geomData.writeGridPoints(x_vert,y_vert,z_vert) ;
... do something with vertex data x_vert, y_vert and z_vert ....
free [] x_vert;
free [] y_vert;
free [] z_vert;
// example using AOS
double * xyz_vert_aos = new double[nvert*3] ;
geomData.writeGridPoints_SOA(xyz_vert_aos) ;
... do something with vertex data xyz_vert_aos....
free [] xyz_vert_aos;
*/
namespace Opm::GridDataOutput
{
/**
* Allows selection of order of verticies in writeConnectivity()
*/
enum ConnectivityVertexOrder { DUNE = 0 , VTK = 1 } ;
template< class GridView, unsigned int partitions >
class SimMeshDataAccessor {
public:
/**
* @brief Construct a SimMeshDataAccessor working on a specific GridView and specialize to a Dune::PartitionSet<>.
*
* @param gridView The gridView
* @param PartitionSet<> the set of cells from which to extract geometric data
*
* The PartitionSet of the data can be specified from one of:
* Dune::Partitions::all
* Dune::Partitions::interior
* Dune::Partitions::border
* Dune::Partitions::overlap
* Dune::Partitions::front
* Dune::Partitions::ghost
* Dune::Partitions::interiorBorder
* Dune::Partitions::interiorBorderOverlap
* Dune::Partitions::interiorBorderOverlapFront
* Dune::Partitions::all
*
* N.B. To visualise 'field' data on the extracted grid mesh then the field variable
* should contain at least as many vlaues as the mesh has cells (ncells_) or vertices (nvertices_)
* depending on if data is cell centred or vertex centred, respectively.
*
* As we are templated on the Dune::PartitionSet<partitions>, values for ncorners_, nvertices_ and ncells_ cannot change
*
* This class does not work with grids containing polyhedral cells (well, it has not been tested
* with this kind of grid data). The user should call polyhedralCellPresent() to test if polyhedral
* cells are present and decide what they want to do before copying data using the data accessor methods.
*/
explicit SimMeshDataAccessor ( const GridView &gridView,
Dune::PartitionSet<partitions> dunePartition)
: gridView_( gridView ),
dunePartition_(dunePartition)
{
dimw_ = GridView::dimension ; // this is an enum
partition_value_ = dunePartition.value ;
countEntities() ;
}
//! destructor
~SimMeshDataAccessor ()
{
}
/**
Checks for cells that have polyhedral type within the current partition of cells
Returns true if a polyhedral sell is found. If this is the case then this partition
is not going to be available for visualisation as this class does not yet handle
polyhedral cells.
*/
bool polyhedralCellPresent()
{
for (const auto& cit : elements(gridView_, dunePartition_))
{
auto corner_geom = cit.geometry() ;
if( Dune::VTK::geometryType( corner_geom.type() ) == Dune::VTK::polyhedron )
{
return true ;
}
}
return false;
}
/**
Count the vertices, cells and corners.
Count all the vertices ( the Dune::Partitions::all partition ) as then we do not need to renumber
the vertices as all the subsets use references to the full set.
*/
void countEntities( )
{
// We include all the vertices for this ranks partition
const auto& vert_partition_it = vertices(gridView_, Dune::Partitions::all);
nvertices_ = std::distance(vert_partition_it.begin(), vert_partition_it.end());
const auto& cell_partition_it = elements(gridView_, dunePartition_);
ncells_ = std::distance(cell_partition_it.begin(), cell_partition_it.end());
ncorners_ = 0 ;
for (const auto& cit : cell_partition_it)
{
auto corner_geom = cit.geometry() ;
ncorners_ += corner_geom.corners() ;
}
}
/**
Write the positions of vertices - directly to the pointers given in paramaters
Returns the number of vertices written
*/
template <typename T>
long writeGridPoints( T* x_inout, T* y_inout, T* z_inout )
{
long i = 0 ;
if (dimw_ == 3) {
for (const auto& vit : vertices(gridView_, Dune::Partitions::all) )
{
// if (i < nvertices_) // As we are templated on the Dune::PartitionSet<partitions>, this cannot change
auto xyz_local = vit.geometry().corner(0); // verticies only have one corner
x_inout[i] = static_cast<T>(xyz_local[0]) ;
y_inout[i] = static_cast<T>(xyz_local[1]) ;
z_inout[i] = static_cast<T>(xyz_local[2]) ;
i++ ;
}
} else if (dimw_ == 2) {
for (const auto& vit : vertices(gridView_, Dune::Partitions::all) )
{
// if (i < nvertices_) // As we are templated on the Dune::PartitionSet<partitions>, this cannot change
auto xyz_local = vit.geometry().corner(0); // verticies only have one corner
x_inout[i] = static_cast<T>(xyz_local[0]) ;
y_inout[i] = static_cast<T>(xyz_local[1]) ;
z_inout[i] = static_cast<T>(0.0);
i++ ;
}
}
return i ;
}
/**
Write positions of vertices as array of structures : x,y,z,x,y,z,x,y,z,...
Returns the number of vertices written
*/
template <typename T>
long writeGridPoints_AOS( T* xyz_inout )
{
long i = 0 ;
if (dimw_ == 3) {
for (const auto& vit : vertices(gridView_, Dune::Partitions::all))
{
auto xyz_local = vit.geometry().corner(0);
xyz_inout[i++] = static_cast<T>(xyz_local[0]) ;
xyz_inout[i++] = static_cast<T>(xyz_local[1]) ;
xyz_inout[i++] = static_cast<T>(xyz_local[2]) ;
}
} else if (dimw_ == 2) {
for (const auto& vit : vertices(gridView_, Dune::Partitions::all))
{
auto xyz_local = vit.geometry().corner(0);
xyz_inout[i++] = static_cast<T>(xyz_local[0]) ;
xyz_inout[i++] = static_cast<T>(xyz_local[1]) ;
xyz_inout[i++] = static_cast<T>(0.0) ;
}
}
return ( (i) / 3 );
}
/**
Write positions of vertices as structure of arrays : x,x,x,...,y,y,y,...,z,z,z,...
Returns the number of vertices written
*/
template <typename T>
long writeGridPoints_SOA( T* xyz_inout )
{
long i = 0 ;
// Get offsets into structure
T * xyz_inout_y = xyz_inout + nvertices_ ;
T * xyz_inout_z = xyz_inout + (2*nvertices_) ;
if (dimw_ == 3) {
for (const auto& vit : vertices(gridView_, Dune::Partitions::all))
{
auto xyz_local = vit.geometry().corner(0);
xyz_inout[i] = static_cast<T>(xyz_local[0]) ;
xyz_inout_y[i]= static_cast<T>(xyz_local[1]) ;
xyz_inout_z[i] = static_cast<T>(xyz_local[2]) ;
i++ ;
}
} else if (dimw_ == 2) {
for (const auto& vit : vertices(gridView_, Dune::Partitions::all))
{
auto xyz_local = vit.geometry().corner(0);
xyz_inout[i] = static_cast<T>(xyz_local[0]) ;
xyz_inout_y[i]= static_cast<T>(xyz_local[1]) ;
xyz_inout_z[i] = static_cast<T>(0.0);
i++ ;
}
}
return (i) ;
}
/**
* Write the connectivity array - directly to the pointer given in paramater 1
Reorders the indecies as selected either in DUNE order or VTK order.
Returns the number of corner indices written.
*/
template <typename I>
long writeConnectivity(I * connectivity_inout, ConnectivityVertexOrder whichOrder)
{
long i = 0 ;
if ( whichOrder == DUNE ) {
// DUNE order
for (const auto& cit : elements(gridView_, dunePartition_))
{
auto cell_corners = cit.geometry().corners() ;
for( auto vx = 0; vx < cell_corners; ++ vx )
{
const int vxIdx = gridView_.indexSet().subIndex( cit, vx, 3 );
connectivity_inout[i + vx] = vxIdx ;
}
i += cell_corners ;
}
} else {
// VTK order
for (const auto& cit : elements(gridView_, dunePartition_))
{
auto cell_corners = cit.geometry().corners() ;
for( auto vx = 0; vx < cell_corners; ++ vx )
{
const int vxIdx = gridView_.indexSet().subIndex( cit, vx, 3 );
int vtkOrder ;
vtkOrder = Dune::VTK::renumber(cit.type(), vx) ;
connectivity_inout[i + vtkOrder] = vxIdx ;
}
i += cell_corners ;
}
}
return (i) ;
}
/**
* Write the offsets values - directly to the pointer given in paramater 1
Returns the number of offset values written, which should be 1 greater than ncells_
or -1 if an error was detected
*/
template <typename I>
long writeOffsetsCells( I* offsets_inout )
{
long i = 1 ;
offsets_inout[0] = 0 ;
for (const auto& cit : elements(gridView_, dunePartition_))
{
auto cell_corners = cit.geometry().corners() ;
offsets_inout[i] = offsets_inout[i-1] + cell_corners ;
i++ ;
}
return (i) ; // This should be 1 greater than ncells_
}
/**
* Write the Cell types array - directly to the pointer given in paramater 1
*/
template <typename I>
long writeCellTypes( I* types_inout)
{
int i = 0 ;
for (const auto& cit : elements(gridView_, dunePartition_))
{
I vtktype = static_cast<I>(Dune::VTK::geometryType(cit.type()));
types_inout[i++] = vtktype ;
}
return (i) ;
}
std::string getPartitionTypeString ( )
{
if (this->dunePartition_ == Dune::Partitions::all)
return (std::string("Dune::Partitions::all")) ;
if (this->dunePartition_ == Dune::Partitions::interior)
return (std::string("Dune::Partitions::interior")) ;
if (this->dunePartition_ == Dune::Partitions::interiorBorder)
return (std::string("Dune::Partitions::interiorBorder")) ;
if (this->dunePartition_ == Dune::Partitions::interiorBorderOverlap)
return (std::string("Dune::Partitions::interiorBorderOverlap")) ;
if (this->dunePartition_ == Dune::Partitions::front)
return (std::string("Dune::Partitions::front")) ;
if (this->dunePartition_ == Dune::Partitions::interiorBorderOverlapFront)
return (std::string("Dune::Partitions::InteriorBorderOverlapFront")) ;
if (this->dunePartition_ == Dune::Partitions::border)
return (std::string("Dune::Partitions::border")) ;
if (this->dunePartition_ == Dune::Partitions::ghost)
return (std::string("Dune::Partitions::ghost")) ;
return (std::string("Unknown Dune::PartitionSet<>")) ;
}
Dune::PartitionSet<partitions> getPartition ( void )
{
return ( this->dunePartition_ ) ;
}
void printGridDetails()
{
std::cout << "Dune Partition = " << partition_value_ << ", " << getPartitionTypeString() << std::endl ;
printNCells() ;
printNVertices() ;
printNCorners() ;
}
void printNCells()
{
std::cout << "ncells = " << ncells_ << std::endl ;
}
void printNVertices()
{
std::cout << "nvertices = " << nvertices_ << std::endl ;
}
void printNCorners()
{
std::cout << "ncorners = " << ncorners_ << std::endl ;
}
int getNCells()
{
return(ncells_) ;
}
int getNVertices()
{
return(nvertices_) ;
}
int getNCorners()
{
return(ncorners_) ;
}
std::string getError()
{
return error_strm_.str() ;
}
void clearError()
{
error_strm_.str("") ;
}
bool hasError()
{
if ( error_strm_.str().length() > 0 )
return true ;
else
return false ;
}
protected:
GridView gridView_; // the grid
Dune::PartitionSet<partitions> dunePartition_ ;
unsigned int partition_value_ ;
/**
Current partition grid information
*/
int ncells_;
/**
Current partition grid information
*/
int nvertices_;
/**
Current partition grid information
*/
int ncorners_;
int dimw_ ; // dimensions of the input grid
private:
std::stringstream error_strm_ ;
};
}
#endif

View File

@@ -22,8 +22,6 @@
namespace Opm::DamarisOutput
{
/*
Below is the XML file for Damaris that is supported by Damaris.
@@ -37,7 +35,7 @@ namespace Opm::DamarisOutput
std::string initDamarisXmlFile()
{
std::string init_damaris = R"V0G0N(<?xml version="1.0"?>
<simulation name="opm-flow" language="c" xmlns="http://damaris.gforge.inria.fr/damaris/model">
<simulation name="_SIM_NAME_" language="c" xmlns="http://damaris.gforge.inria.fr/damaris/model">
<architecture>
<domains count="1"/>
<dedicated cores="_DC_REGEX_" nodes="_DN_REGEX_"/>
@@ -46,28 +44,27 @@ std::string initDamarisXmlFile()
<queue name="queue" size="300" />
</architecture>
<data>
<data>
<parameter name="n_elements_total" type="int" value="1" />
<parameter name="n_elements_local" type="int" value="1" />
<parameter name="n" type="int" value="1" />
<layout name="zonal_layout_usmesh_integer" type="int" dimensions="n_elements_local" global="n_elements_total" comment="For the field data e.g. Pressure" />
<variable name="GLOBAL_CELL_INDEX" layout="zonal_layout_usmesh_integer" type="scalar" visualizable="false" time-varying="false" store="_MYSTORE_OR_EMPTY_REGEX_" centering="zonal" />
<layout name="zonal_layout_usmesh" type="double" dimensions="n_elements_local" global="n_elements_total" comment="For the field data e.g. Pressure" />
<variable name="PRESSURE" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="unstructured_mesh" unit="Bar" centering="zonal" time-varying="true"
select-file="GLOBAL_CELL_INDEX" store="_MYSTORE_OR_EMPTY_REGEX_" script="_PYTHON_XML_NAME_" />
<layout name="zonal_layout_usmesh_integer" type="int" dimensions="n_elements_local" global="n_elements_total" comment="For the field data e.g. Pressure" />
<variable name="GLOBAL_CELL_INDEX" layout="zonal_layout_usmesh_integer" type="scalar" visualizable="false" time-varying="false" centering="zonal" />
<layout name="zonal_layout_usmesh" type="double" dimensions="n_elements_local" global="n_elements_total" comment="For the field data e.g. Pressure" />
<variable name="PRESSURE" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="us_mesh" unit="_PRESSURE_UNIT_" centering="zonal" select-file="GLOBAL_CELL_INDEX" store="_MYSTORE_OR_EMPTY_REGEX_" script="PythonScript" />
_MORE_VARIABLES_REGEX_
<variable name="MPI_RANK" layout="zonal_layout_usmesh_integer" type="scalar" visualizable="true" mesh="us_mesh" unit="rank" centering="zonal" store="_MYSTORE_OR_EMPTY_REGEX_" time-varying="false" select-file="GLOBAL_CELL_INDEX" script="PythonScript" comment="The MPI rank of each cell"/>
<variable name="MPI_RANK" layout="zonal_layout_usmesh_integer" type="scalar" visualizable="true" mesh="unstructured_mesh" unit="rank" centering="zonal" select-file="GLOBAL_CELL_INDEX" store="#" time-varying="false" script="#" comment="The cells MPI rank"/>
<variable name="KRNSW_GO" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="unstructured_mesh" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="_PYTHON_XML_NAME_" />
<variable name="KRNSW_OW" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="_MESHNAME_OR_HASH_" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="_PYTHON_XML_NAME_" />
<variable name="PCSWM_GO" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="_MESHNAME_OR_HASH_" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="_PYTHON_XML_NAME_" />
<variable name="PCSWM_OW" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="_MESHNAME_OR_HASH_" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="_PYTHON_XML_NAME_" />
<variable name="PPCW" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="_MESHNAME_OR_HASH_" unit="Bar" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="_PYTHON_XML_NAME_" />
<variable name="RS" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="_MESHNAME_OR_HASH_" unit="Bar" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="_PYTHON_XML_NAME_" comment="Dissolved Gas units Gas Oil Ratio" />
<variable name="RV" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="_MESHNAME_OR_HASH_" unit="Bar" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="_PYTHON_XML_NAME_" />
<variable name="SOMAX" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="_MESHNAME_OR_HASH_" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" />
<variable name="KRNSW_GO" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="#" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" />
<variable name="KRNSW_OW" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="#" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" />
<variable name="PCSWM_GO" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="#" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" />
<variable name="PCSWM_OW" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="#" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" />
<variable name="PPCW" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="#" unit="Bar" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" />
<variable name="RS" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="#" unit="Bar" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" comment="Dissolved Gas units Gas Oil Ratio" />
<variable name="RV" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="#" unit="Bar" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" />
<variable name="SOMAX" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="#" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" />
<variable name="1OVERBG" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="#" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" />
<variable name="1OVERBO" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="#" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" />
<variable name="1OVERBW" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="#" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" />
@@ -81,8 +78,6 @@ std::string initDamarisXmlFile()
<variable name="WAT_DEN" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="#" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" />
<variable name="WAT_VISC" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="#" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" />
<variable name="2FBF" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="#" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" />
<variable name="4FBF" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="#" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" />
<variable name="DFBF" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="#" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" />
@@ -109,30 +104,27 @@ std::string initDamarisXmlFile()
<variable name="WIPG" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="#" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" />
<variable name="WIPL" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="#" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" />
<variable name="WIPR" layout="zonal_layout_usmesh" type="scalar" visualizable="true" mesh="#" unit="" centering="zonal" time-varying="true" select-file="GLOBAL_CELL_INDEX" store="#" script="#" />
<parameter name="n_coords_local" type="int" value="1" />
<layout name="n_coords_layout" type="double" dimensions="n_coords_local" comment="For the individual x, y and z coordinates of the mesh vertices, these values are referenced in the topologies/topo/subelements/connectivity_pg data" />
<group name="coordset/coords/values">
<variable name="x" layout="n_coords_layout" type="scalar" visualizable="false" unit="m" script="_PYTHON_XML_NAME_" time-varying="false" />
<variable name="y" layout="n_coords_layout" type="scalar" visualizable="false" unit="m" script="_PYTHON_XML_NAME_" time-varying="false" />
<variable name="z" layout="n_coords_layout" type="scalar" visualizable="false" unit="m" script="_PYTHON_XML_NAME_" time-varying="false" />
<variable name="x" layout="n_coords_layout" type="scalar" visualizable="false" unit="m" script="_MAKE_AVAILABLE_IN_PYTHON_" time-varying="false" />
<variable name="y" layout="n_coords_layout" type="scalar" visualizable="false" unit="m" script="_MAKE_AVAILABLE_IN_PYTHON_" time-varying="false" />
<variable name="z" layout="n_coords_layout" type="scalar" visualizable="false" unit="m" script="_MAKE_AVAILABLE_IN_PYTHON_" time-varying="false" />
</group>
<parameter name="n_connectivity_ph" type="int" value="1" />
<layout name="n_connections_layout_ph" type="int" dimensions="n_connectivity_ph" comment="Layout for connectivities " />
<parameter name="n_offsets_types_ph" type="int" value="1" />
<layout name="n_offsets_layout_ph" type="int" dimensions="n_offsets_types_ph+1" comment="Layout for the offsets_ph" />
<layout name="n_offsets_layout_ph" type="int" dimensions="n_offsets_types_ph + 1" comment="Layout for the offsets_ph" />
<layout name="n_types_layout_ph" type="char" dimensions="n_offsets_types_ph" comment="Layout for the types_ph " />
<group name="topologies/topo/elements">
<variable name="connectivity" layout="n_connections_layout_ph" type="scalar" visualizable="false" script="_PYTHON_XML_NAME_" time-varying="false" />
<variable name="offsets" layout="n_offsets_layout_ph" type="scalar" visualizable="false" script="_PYTHON_XML_NAME_" time-varying="false" />
<variable name="types" layout="n_types_layout_ph" type="scalar" visualizable="false" script="_PYTHON_XML_NAME_" time-varying="false" />
<variable name="connectivity" layout="n_connections_layout_ph" type="scalar" visualizable="false" script="_MAKE_AVAILABLE_IN_PYTHON_" time-varying="false" />
<variable name="offsets" layout="n_offsets_layout_ph" type="scalar" visualizable="false" script="_MAKE_AVAILABLE_IN_PYTHON_" time-varying="false" />
<variable name="types" layout="n_types_layout_ph" type="scalar" visualizable="false" script="_MAKE_AVAILABLE_IN_PYTHON_" time-varying="false" />
</group>
<mesh name="unstructured_mesh" type="unstructured" topology="3" time-varying="false"
<mesh name="us_mesh" type="unstructured" topology="3" time-varying="false"
comment="This Mesh definition is for connection with Paraview.
This definition references the variables that define an unstructured mesh specified above." >
<coord name="coordset/coords/values/x" unit="m" />
@@ -147,7 +139,7 @@ std::string initDamarisXmlFile()
<polyhedral_cell_faces_offsets name="#" />
<polyhedral_n_faces_per_cell name="#" />
</mesh>
</data>
<storage>
@@ -159,17 +151,17 @@ std::string initDamarisXmlFile()
</storage>
<scripts>
<pyscript name="PythonScript" file="_PYTHON_OR_EMPTY_REGEX_" language="python" frequency="1" scheduler-file="" nthreads="0" keep-workers="no" />
<pyscript name="PythonScript" file="_PYTHON_SCRIPT_" language="python" frequency="1" scheduler-file="" nthreads="0" keep-workers="no" />
</scripts>
<!-- paraview update-frequency="1" write-vtk="0" write-vtk-binary="false">
<script>_PARAVIEWPY_OR_EMPTY_REGEX_</script>
</paraview -->
<paraview update-frequency="1" write-vtk="0" write-vtk-binary="false" >
<script>_PARAVIEW_PYTHON_SCRIPT_</script>
</paraview>
<actions>
</actions>
<log FileName="_PATH_REGEX_/damaris_log/opm-flow" RotationSize="5" LogFormat="[%TimeStamp%]: %Message%" Flush="true" LogLevel="info" />
<log FileName="_PATH_REGEX_/damaris_log/_SIM_NAME_" RotationSize="5" LogFormat="[%TimeStamp%]: %Message%" Flush="True" LogLevel="_LOG_LEVEL_" />
</simulation>)V0G0N";