finalise the PR 4889 modifications - added command line option to specifiy the shared memory file name in the <buffer> XML element --damaris-shared-memory-name which will be a randomised string opm-damaris-<random-string> for better multi-simulation behaviour when running more than one simulation on a single node.

This commit is contained in:
Josh Bowden 2023-12-13 17:50:05 +01:00
parent 757a96941a
commit e16cd9a3b3
7 changed files with 347 additions and 238 deletions

View File

@ -99,6 +99,10 @@ struct DamarisDedicatedNodes {
using type = UndefinedProperty; using type = UndefinedProperty;
}; };
template<class TypeTag, class MyTypeTag> template<class TypeTag, class MyTypeTag>
struct DamarisSharedMemoryName {
using type = UndefinedProperty;
};
template<class TypeTag, class MyTypeTag>
struct DamarisSharedMemorySizeBytes { struct DamarisSharedMemorySizeBytes {
using type = UndefinedProperty; using type = UndefinedProperty;
}; };
@ -152,39 +156,41 @@ public:
{ {
EWOMS_REGISTER_PARAM(TypeTag, bool, DamarisOutputHdfCollective, EWOMS_REGISTER_PARAM(TypeTag, bool, DamarisOutputHdfCollective,
"Write output via Damaris using parallel HDF5 to get single file and dataset per timestep instead of one per Damaris \n \ "Write output via Damaris using parallel HDF5 to get single file and dataset per timestep instead of one per Damaris \n \
core with multiple datasets."); core with multiple datasets.");
EWOMS_REGISTER_PARAM(TypeTag, bool, DamarisSaveToHdf, EWOMS_REGISTER_PARAM(TypeTag, bool, DamarisSaveToHdf,
"Set to false to prevent output to HDF5. Uses collective output by default or set --enable-damaris-collective=false to\n \ "Set to false to prevent output to HDF5. Uses collective output by default or set --enable-damaris-collective=false to\n \
use file per core (file per Damaris server)."); use file per core (file per Damaris server).");
EWOMS_REGISTER_PARAM(TypeTag, bool, DamarisSaveMeshToHdf, EWOMS_REGISTER_PARAM(TypeTag, bool, DamarisSaveMeshToHdf,
"Saves the mesh data to the HDF5 file (1st iteration only). Will set --damaris-output-hdf-collective to false \n \ "Saves the mesh data to the HDF5 file (1st iteration only). Will set --damaris-output-hdf-collective to false \n \
so will use file per core (file per Damaris server) output (global sizes and offset values \n \ so will use file per core (file per Damaris server) output (global sizes and offset values \n \
of mesh variables are not being provided as yet)."); of mesh variables are not being provided as yet).");
EWOMS_REGISTER_PARAM(TypeTag, std::string, DamarisPythonScript, EWOMS_REGISTER_PARAM(TypeTag, std::string, DamarisPythonScript,
"Set to the path and filename of a Python script to run on Damaris server resources with access to OPM flow data."); "Set to the path and filename of a Python script to run on Damaris server resources with access to OPM flow data.");
EWOMS_REGISTER_PARAM(TypeTag, std::string, DamarisPythonParaviewScript, EWOMS_REGISTER_PARAM(TypeTag, std::string, DamarisPythonParaviewScript,
"Set to the path and filename of a Paraview Python script to run on Paraview Catalyst (1 or 2) on Damaris server \n \ "Set to the path and filename of a Paraview Python script to run on Paraview Catalyst (1 or 2) on Damaris server \n \
resources with access to OPM flow data."); resources with access to OPM flow data.");
EWOMS_REGISTER_PARAM(TypeTag, std::string, DamarisSimName, EWOMS_REGISTER_PARAM(TypeTag, std::string, DamarisSimName,
"The name of the simulation to be used by Damaris. If empty (the default) then Damaris uses \"opm-sim-<magic_number>\". \n \ "The name of the simulation to be used by Damaris. If empty (the default) then Damaris uses \"opm-sim-<random-number>\". \n \
This name should preferably be unique as it is used for the Damaris shmem name and by the Python Dask \n \ This name is used for the Damaris HDF5 file name prefix. Make unique if writing to the same output directory.");
library to locate sections of variables.");
EWOMS_REGISTER_PARAM(TypeTag, std::string, DamarisLogLevel, EWOMS_REGISTER_PARAM(TypeTag, std::string, DamarisLogLevel,
"The log level for the Damaris logging system (boost log based). \n \ "The log level for the Damaris logging system (boost log based). \n \
Levels are: [trace, debug, info, warning, error, fatal]. Currently debug and info are useful. "); Levels are: [trace, debug, info, warning, error, fatal]. Currently debug and info are useful. ");
EWOMS_REGISTER_PARAM(TypeTag, std::string, DamarisDaskFile, EWOMS_REGISTER_PARAM(TypeTag, std::string, DamarisDaskFile,
"The name of a Dask json configuration file (if using Dask for processing)."); "The name of a Dask json configuration file (if using Dask for processing).");
EWOMS_REGISTER_PARAM(TypeTag, int, DamarisDedicatedCores, EWOMS_REGISTER_PARAM(TypeTag, int, DamarisDedicatedCores,
"Set the number of dedicated cores (MPI processes) that should be used for Damaris processing (per node). \n \ "Set the number of dedicated cores (MPI processes) that should be used for Damaris processing (per node). \n \
Must divide evenly into the number of simulation ranks (client ranks)."); Must divide evenly into the number of simulation ranks (client ranks).");
EWOMS_REGISTER_PARAM(TypeTag, int, DamarisDedicatedNodes, EWOMS_REGISTER_PARAM(TypeTag, int, DamarisDedicatedNodes,
"Set the number of dedicated nodes (full nodes) that should be used for Damaris processing (per simulation). \n \ "Set the number of dedicated nodes (full nodes) that should be used for Damaris processing (per simulation). \n \
Must divide evenly into the number of simulation nodes."); Must divide evenly into the number of simulation nodes.");
EWOMS_REGISTER_PARAM(TypeTag, long, DamarisSharedMemorySizeBytes, EWOMS_REGISTER_PARAM(TypeTag, long, DamarisSharedMemorySizeBytes,
"Set the size of the shared memory buffer used for IPC between the simulation and the Damaris resources. \n \ "Set the size of the shared memory buffer used for IPC between the simulation and the Damaris resources. \n \
Needs to hold all the variables published, possibly over multiple simulation iterations."); Needs to hold all the variables published, possibly over multiple simulation iterations.");
EWOMS_REGISTER_PARAM(TypeTag, std::string, DamarisSharedMemoryName,
"The name of the shared memory area to be used by Damaris for the current. If empty (the default) then Damaris uses \"opm-damaris-<random-string>\". \n \
This name should be unique if multiple simulations are running on the same node/server as it is used for the Damaris shmem name and by the Python Dask \n \
library to locate sections of variables.");
} }
// The Simulator object should preferably have been const - the // The Simulator object should preferably have been const - the
@ -270,7 +276,7 @@ public:
int64_t temp_int64_t[1]; int64_t temp_int64_t[1];
temp_int64_t[0] = static_cast<int64_t>(this->elements_rank_offsets_[rank_]); temp_int64_t[0] = static_cast<int64_t>(this->elements_rank_offsets_[rank_]);
dam_err_ = damaris_set_position("PRESSURE", temp_int64_t); dam_err_ = damaris_set_position("PRESSURE", temp_int64_t);
if (dam_err_ != DAMARIS_OK && rank_ == 0) { if (dam_err_ != DAMARIS_OK) {
OpmLog::error(fmt::format("damariswriter::writeOutput() : ( rank:{})" OpmLog::error(fmt::format("damariswriter::writeOutput() : ( rank:{})"
"damaris_set_position(PRESSURE, ...), Damaris Error: {} ", "damaris_set_position(PRESSURE, ...), Damaris Error: {} ",
rank_, damaris_error_string(dam_err_) )); rank_, damaris_error_string(dam_err_) ));
@ -331,24 +337,20 @@ private:
"( rank:{}) damaris_write(GLOBAL_CELL_INDEX, ...), Damaris Error: {} ", "( rank:{}) damaris_write(GLOBAL_CELL_INDEX, ...), Damaris Error: {} ",
rank_, damaris_error_string(dam_err_) )); rank_, damaris_error_string(dam_err_) ));
} }
// This is an example of writing to the Damaris shared memory directly (i.e. not using // This is an example of writing to the Damaris shared memory directly (i.e. not using
// damaris_write() to copy data there) // damaris_write() to copy data there)
// We will add the MPI rank value directly into shared memory using the DamarisVar // We will add the MPI rank value directly into shared memory using the DamarisVar
// wrapper of the C based Damaris API. // wrapper of the C based Damaris API.
// The shared memory is given back to Damaris on object deletion - i.e. when the // The shared memory is given back to Damaris when the DamarisVarInt goes out of scope.
// unique_ptr goes out of scope. DamarisVarInt mpi_rank_var_test(1, {std::string("n_elements_local")}, std::string("MPI_RANK"), rank_);
std::unique_ptr<DamarisVarInt> mpi_rank_var( new DamarisVarInt(1, mpi_rank_var_test.setDamarisParameterAndShmem( {this->numElements_ } ) ;
{std::string("n_elements_local")},
std::string("MPI_RANK"), rank_) );
// N.B. we have not set any offset values, so HDF5 collective and Dask arrays cannot be used.
mpi_rank_var->setDamarisParameterAndShmem( {this->numElements_ } ) ;
// Fill the created memory area // Fill the created memory area
for (int i = 0 ; i < this->numElements_; i++ ) for (int i = 0 ; i < this->numElements_; i++ )
{ {
mpi_rank_var->data()[i] = rank_ ; // write the rank vaue to the shared memory area. mpi_rank_var_test.data()[i] = rank_ ; // write the rank vaue to the shared memory area.
} }
} }
void setupDamarisWritingPars(Parallel::Communication comm, const int n_elements_local_grid, std::vector<unsigned long long>& elements_rank_offsets) void setupDamarisWritingPars(Parallel::Communication comm, const int n_elements_local_grid, std::vector<unsigned long long>& elements_rank_offsets)
@ -417,10 +419,9 @@ private:
"damaris_set_position(\"GLOBAL_CELL_INDEX\", temp_int64_t);"); "damaris_set_position(\"GLOBAL_CELL_INDEX\", temp_int64_t);");
} }
std::unique_ptr<DamarisVarInt> mpi_rank_var( new DamarisVarInt(1, // Set the size of the MPI variable
{std::string("n_elements_local")}, DamarisVarInt mpi_rank_var(1, {std::string("n_elements_local")}, std::string("MPI_RANK"), rank_) ;
std::string("MPI_RANK"), rank_) ) ; mpi_rank_var.setDamarisPosition({*temp_int64_t}) ;
mpi_rank_var->setDamarisPosition({*temp_int64_t}) ;
} }
@ -448,27 +449,23 @@ private:
// <variable name="z" layout="n_coords_layout" type="scalar" visualizable="false" unit="m" script="PythonConduitTest" time-varying="false" /> // <variable name="z" layout="n_coords_layout" type="scalar" visualizable="false" unit="m" script="PythonConduitTest" time-varying="false" />
// </group> // </group>
std::unique_ptr<DamarisVarDbl> var_x(new DamarisVarDbl(1, {std::string("n_coords_local")}, std::string("coordset/coords/values/x"), rank_)) ; DamarisVarDbl var_x(1, {std::string("n_coords_local")}, std::string("coordset/coords/values/x"), rank_) ;
// N.B. We have not set any position/offset values (using DamarisVar::SetDamarisPosition). // N.B. We have not set any position/offset values (using DamarisVar::SetDamarisPosition).
// They are not needed for mesh data as each process has a local geometric model. // They are not needed for mesh data as each process has a local geometric model.
// However, HDF5 collective and Dask arrays cannot be used for this data. // However, HDF5 collective and Dask arrays cannot be used for this data.
var_x->setDamarisParameterAndShmem( { geomData.getNVertices() } ) ; var_x.setDamarisParameterAndShmem( { geomData.getNVertices() } ) ;
std::unique_ptr<DamarisVarDbl> var_y(new DamarisVarDbl(1, {std::string("n_coords_local")}, std::string("coordset/coords/values/y"), rank_)) ; DamarisVarDbl var_y(1, {std::string("n_coords_local")}, std::string("coordset/coords/values/y"), rank_) ;
var_y->setDamarisParameterAndShmem( { geomData.getNVertices() } ) ; var_y.setDamarisParameterAndShmem( { geomData.getNVertices() } ) ;
std::unique_ptr<DamarisVarDbl> var_z(new DamarisVarDbl(1, {std::string("n_coords_local")}, std::string("coordset/coords/values/z"), rank_)) ; DamarisVarDbl var_z(1, {std::string("n_coords_local")}, std::string("coordset/coords/values/z"), rank_) ;
var_z->setDamarisParameterAndShmem( { geomData.getNVertices() } ) ; var_z.setDamarisParameterAndShmem( { geomData.getNVertices() } ) ;
// Now we can return the memory that Damaris has allocated in shmem and use it to write the X,y,z coordinates // Now we can return the memory that Damaris has allocated in shmem and use it to write the X,y,z coordinates
double itime, ftime, exec_time; double itime, ftime, exec_time;
itime = omp_get_wtime(); itime = omp_get_wtime();
if ( geomData.writeGridPoints(*var_x,*var_y,*var_z) < 0) if ( geomData.writeGridPoints(var_x, var_y, var_z) < 0)
DUNE_THROW(Dune::IOError, geomData.getError() ); DUNE_THROW(Dune::IOError, geomData.getError() );
if ( geomData.writeGridPoints(var_x->data(),var_y->data(),var_z->data(), geomData.getNVertices()) < 0)
DUNE_THROW(Dune::IOError, geomData.getError() );
ftime = omp_get_wtime(); ftime = omp_get_wtime();
exec_time = ftime - itime; exec_time = ftime - itime;
// OpmLog::info("\n\nTime taken geomData.writeGridPoints(): is " + std::to_string(exec_time) ) ; // OpmLog::info("\n\nTime taken geomData.writeGridPoints(): is " + std::to_string(exec_time) ) ;
@ -488,29 +485,28 @@ private:
// <variable name="types" layout="n_types_layout_ph" type="scalar" visualizable="false" unit="" script="PythonConduitTest" time-varying="false" /> // <variable name="types" layout="n_types_layout_ph" type="scalar" visualizable="false" unit="" script="PythonConduitTest" time-varying="false" />
// </group> // </group>
std::unique_ptr<DamarisVarInt> var_connectivity(new DamarisVarInt(1, {std::string("n_connectivity_ph")}, std::string("topologies/topo/elements/connectivity"), rank_)) ; DamarisVarInt var_connectivity(1, {std::string("n_connectivity_ph")}, std::string("topologies/topo/elements/connectivity"), rank_) ;
var_connectivity->setDamarisParameterAndShmem({ geomData.getNCorners()}) ; var_connectivity.setDamarisParameterAndShmem({ geomData.getNCorners()}) ;
std::unique_ptr<DamarisVarInt> var_offsets(new DamarisVarInt(1, {std::string("n_offsets_types_ph")}, std::string("topologies/topo/elements/offsets"), rank_)) ; DamarisVarInt var_offsets(1, {std::string("n_offsets_types_ph")}, std::string("topologies/topo/elements/offsets"), rank_) ;
var_offsets->setDamarisParameterAndShmem({ geomData.getNCells()}) ; var_offsets.setDamarisParameterAndShmem({ geomData.getNCells()}) ;
std::unique_ptr<DamarisVarChar> var_types(new DamarisVarChar(1, {std::string("n_offsets_types_ph")}, std::string("topologies/topo/elements/types"), rank_)) ; DamarisVarChar var_types(1, {std::string("n_offsets_types_ph")}, std::string("topologies/topo/elements/types"), rank_) ;
var_types->setDamarisParameterAndShmem({ geomData.getNCells()}) ; var_types.setDamarisParameterAndShmem({ geomData.getNCells()}) ;
// Copy the mesh data from the Durne grid // Copy the mesh data from the Durne grid
long i = 0 ; long i = 0 ;
Opm::GridDataOutput::ConnectivityVertexOrder vtkorder = Opm::GridDataOutput::VTK ; Opm::GridDataOutput::ConnectivityVertexOrder vtkorder = Opm::GridDataOutput::VTK ;
i = geomData.writeConnectivity(*var_connectivity, vtkorder) ; i = geomData.writeConnectivity(var_connectivity, vtkorder) ;
if ( i != geomData.getNCorners()) if ( i != geomData.getNCorners())
DUNE_THROW(Dune::IOError, geomData.getError()); DUNE_THROW(Dune::IOError, geomData.getError());
i = geomData.writeOffsetsCells(*var_offsets); i = geomData.writeOffsetsCells(var_offsets);
if ( i != geomData.getNCells()+1) if ( i != geomData.getNCells()+1)
DUNE_THROW(Dune::IOError,geomData.getError()); DUNE_THROW(Dune::IOError,geomData.getError());
i = geomData.writeCellTypes(*var_types) ; i = geomData.writeCellTypes(var_types) ;
if ( i != geomData.getNCells()) if ( i != geomData.getNCells())
DUNE_THROW(Dune::IOError,geomData.getError()); DUNE_THROW(Dune::IOError,geomData.getError());
} }
catch (std::exception& e) catch (std::exception& e)
{ {

View File

@ -426,6 +426,10 @@ struct DamarisDedicatedNodes<TypeTag, TTag::EclBaseProblem> {
static constexpr int value = 0; static constexpr int value = 0;
}; };
template<class TypeTag> template<class TypeTag>
struct DamarisSharedMemoryName<TypeTag, TTag::EclBaseProblem> {
static constexpr auto value = "" ; // default name is empty, will make unique if needed in DamarisKeywords()
};
template<class TypeTag>
struct DamarisSharedMemorySizeBytes<TypeTag, TTag::EclBaseProblem> { struct DamarisSharedMemorySizeBytes<TypeTag, TTag::EclBaseProblem> {
static constexpr long value = 536870912; // 512 MB static constexpr long value = 536870912; // 512 MB
}; };

View File

@ -77,11 +77,27 @@ bool FileExists(const std::string& filename_in,
return (file_exists); return (file_exists);
} }
void DamarisSettings::SetRandString(void)
{
// rand_value_str_ = damaris::Environment::GetMagicNumber(comm); // requires Damaris >= v1.9.2
// We will create a random value.
// 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);
rand_value_str_ = std::to_string(rand_int) ;
}
std::map<std::string, std::string> std::map<std::string, std::string>
DamarisSettings::getKeywords([[maybe_unused]] const Parallel::Communication& comm, DamarisSettings::getKeywords([[maybe_unused]] const Parallel::Communication& comm,
const std::string& OutputDir) const std::string& OutputDir)
{ {
SetRandString() ; // sets rand_value_str_ used for naming things that might need a unique name
std::string saveToHDF5_str("MyStore"); std::string saveToHDF5_str("MyStore");
if (! saveToDamarisHDF5_ ){ if (! saveToDamarisHDF5_ ){
saveToHDF5_str = "#"; saveToHDF5_str = "#";
@ -126,8 +142,9 @@ DamarisSettings::getKeywords([[maybe_unused]] const Parallel::Communication& com
} }
} }
#else #else
OpmLog::info(fmt::format("INFO: Opm::DamarisOutput::DamarisKeywords() : Paraview is not enabled in the Damaris library. " OpmLog::info(fmt::format("Opm::DamarisOutput::DamarisKeywords() : Paraview is not enabled in the Damaris library. "
"The commandline --damaris-python-paraview-script={} will be set to empty string", paraviewPythonFilename_)); "The commandline --damaris-python-paraview-script={} will be set to empty string",
paraviewPythonFilename_));
paraviewPythonFilename_.clear(); paraviewPythonFilename_.clear();
#endif #endif
@ -154,29 +171,40 @@ DamarisSettings::getKeywords([[maybe_unused]] const Parallel::Communication& com
} else { } else {
damarisOutputCollective_str = "FilePerCore"; damarisOutputCollective_str = "FilePerCore";
} }
OpmLog::info(fmt::format("Opm::DamarisOutput::DamarisKeywords() : <option key=\"FileMode\"> {} </option> ",
damarisOutputCollective_str));
std::string simName_str; std::string simName_str;
// Check if simulation name was given on command line
// The simulation name is used as a prefix to name HDF5 files
if (damarisSimName_.empty()) { if (damarisSimName_.empty()) {
// Having a different simulation name is important if multiple simulations simName_str = "opm-flow-" + rand_value_str_;
// 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 = damaris::Environment::GetMagicNumber(comm);
if (simName_str.empty()) {
// We will add a random value as GetMagicNumber(comm) requires Damaris v1.9.2
// 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-flow-" + std::to_string(rand_int);
} else {
simName_str = "opm-flow-" + simName_str;
}
} else { } else {
simName_str = damarisSimName_; simName_str = damarisSimName_;
} }
OpmLog::info(fmt::format("Opm::DamarisOutput::DamarisKeywords() : <simulation name={} ",
simName_str));
// A different shared memory buffer name is important if multiple simulations
// are running on the same node, as one simulation will remove the buffer when it exits,
// which will remove the buffer for other simulations.
std::string shmemName_str;
if ( shmemName_.empty()) {
shmemName_str = "opm-damaris-" + rand_value_str_;
} else {
shmemName_str = shmemName_ ;
}
std::string shmemSizeBytes_str;
if (shmemSizeBytes_ != 0) {
shmemSizeBytes_str = std::to_string(shmemSizeBytes_);
} else {
shmemSizeBytes_str = "536870912"; // 512 MB
}
OpmLog::info(fmt::format("Opm::DamarisOutput::DamarisKeywords() : <buffer name={} size={} ",
shmemName_str, shmemSizeBytes_str));
if ((nDamarisCores_ > 0) && (nDamarisNodes_ > 0)) if ((nDamarisCores_ > 0) && (nDamarisNodes_ > 0))
{ {
nDamarisNodes_ = 0; // Default is to use Damaris Cores nDamarisNodes_ = 0; // Default is to use Damaris Cores
@ -194,20 +222,20 @@ DamarisSettings::getKeywords([[maybe_unused]] const Parallel::Communication& com
} else { } else {
nDamarisNodes_str = "0"; nDamarisNodes_str = "0";
} }
OpmLog::info(fmt::format("Opm::DamarisOutput::DamarisKeywords() : <dedicated cores={} nodes={} ",
nDamarisCores_str, nDamarisNodes_str));
std::string shmemSizeBytes_str;
if (shmemSizeBytes_ != 0) {
shmemSizeBytes_str = std::to_string(shmemSizeBytes_);
} else {
shmemSizeBytes_str = "536870912"; // 512 MB
}
std::string logLevel_str(damarisLogLevel_); std::string logLevel_str(damarisLogLevel_);
std::string logFlush_str("false"); std::string logFlush_str("false");
if ((logLevel_str == "debug") || (logLevel_str == "trace") ) { if ((logLevel_str == "debug") || (logLevel_str == "trace") ) {
logFlush_str = "true"; logFlush_str = "true";
} }
OpmLog::info(fmt::format("Opm::DamarisOutput::DamarisKeywords() : <log FileName={}/damaris_log/{} Flush={} LogLevel={} ",
OutputDir, simName_str, logFlush_str, logLevel_str));
std::map<std::string, std::string> damaris_keywords = { std::map<std::string, std::string> damaris_keywords = {
{"_SHMEM_BUFFER_BYTES_REGEX_", shmemSizeBytes_str}, {"_SHMEM_BUFFER_BYTES_REGEX_", shmemSizeBytes_str},
{"_DC_REGEX_", nDamarisCores_str}, {"_DC_REGEX_", nDamarisCores_str},
@ -222,6 +250,7 @@ DamarisSettings::getKeywords([[maybe_unused]] const Parallel::Communication& com
{"_PRESSURE_UNIT_","Pa"}, {"_PRESSURE_UNIT_","Pa"},
{"_MAKE_AVAILABLE_IN_PYTHON_",publishToPython_str}, /* must match <pyscript name="PythonScript" */ {"_MAKE_AVAILABLE_IN_PYTHON_",publishToPython_str}, /* must match <pyscript name="PythonScript" */
{"_SIM_NAME_",simName_str}, {"_SIM_NAME_",simName_str},
{"_SHMEM_NAME_",shmemName_str},
{"_LOG_LEVEL_",logLevel_str}, {"_LOG_LEVEL_",logLevel_str},
{"_LOG_FLUSH_",logFlush_str}, {"_LOG_FLUSH_",logFlush_str},
{"_DISABLEPYTHONSTART_",disablePythonXMLstart}, {"_DISABLEPYTHONSTART_",disablePythonXMLstart},
@ -230,6 +259,7 @@ DamarisSettings::getKeywords([[maybe_unused]] const Parallel::Communication& com
{"_DISABLEPARAVIEWFIN_",disableParaviewXMLfin}, {"_DISABLEPARAVIEWFIN_",disableParaviewXMLfin},
{"_DASK_SCHEDULER_FILE_",damarisDaskFile_}, {"_DASK_SCHEDULER_FILE_",damarisDaskFile_},
}; };
return damaris_keywords; return damaris_keywords;
} }

View File

@ -57,16 +57,21 @@ struct DamarisSettings {
std::string pythonFilename_; std::string pythonFilename_;
std::string paraviewPythonFilename_; std::string paraviewPythonFilename_;
std::string damarisSimName_; // empty defaults to opm-sim-<magic_number> std::string damarisSimName_; // empty and set to "opm-flow-<random-number>" if none provided on command line. Used as prefix to HDF5 filenames
std::string shmemName_; // empty and needs to be unique if multiple simulations are running on the same server/node. Used to name the Damaris shared memory region.
std::string damarisLogLevel_ = "info"; std::string damarisLogLevel_ = "info";
std::string damarisDaskFile_ = ""; std::string damarisDaskFile_ = "";
int nDamarisCores_ = 1; // this is the number of (Damaris server) cores per node int nDamarisCores_ = 1; // this is the number of (Damaris server) cores per node
int nDamarisNodes_ = 0; int nDamarisNodes_ = 0;
long shmemSizeBytes_ = 536870912; // 512 MB long shmemSizeBytes_ = 536870912; // 512 MB
std::string rand_value_str_ ; // to be added to sheared memory name to make unique
std::map<std::string, std::string> std::map<std::string, std::string>
getKeywords(const Parallel::Communication& comm, getKeywords(const Parallel::Communication& comm,
const std::string& OutputDir); const std::string& OutputDir);
void SetRandString(void); // sets the value of rand_value_str_
}; };
/** /**
@ -93,6 +98,7 @@ getDamarisKeywords(const Parallel::Communication& comm, const std::string& Outpu
settings.nDamarisCores_ = EWOMS_GET_PARAM(TypeTag, int, DamarisDedicatedCores); settings.nDamarisCores_ = EWOMS_GET_PARAM(TypeTag, int, DamarisDedicatedCores);
settings.nDamarisNodes_ = EWOMS_GET_PARAM(TypeTag, int, DamarisDedicatedNodes); settings.nDamarisNodes_ = EWOMS_GET_PARAM(TypeTag, int, DamarisDedicatedNodes);
settings.shmemSizeBytes_ = EWOMS_GET_PARAM(TypeTag, long, DamarisSharedMemorySizeBytes); settings.shmemSizeBytes_ = EWOMS_GET_PARAM(TypeTag, long, DamarisSharedMemorySizeBytes);
settings.shmemName_ = EWOMS_GET_PARAM(TypeTag, std::string, DamarisSharedMemoryName);
settings.damarisLogLevel_ = EWOMS_GET_PARAM(TypeTag, std::string, DamarisLogLevel); settings.damarisLogLevel_ = EWOMS_GET_PARAM(TypeTag, std::string, DamarisLogLevel);
settings.damarisDaskFile_ = EWOMS_GET_PARAM(TypeTag, std::string, DamarisDaskFile); settings.damarisDaskFile_ = EWOMS_GET_PARAM(TypeTag, std::string, DamarisDaskFile);
return settings.getKeywords(comm, OutputDir); return settings.getKeywords(comm, OutputDir);

View File

@ -161,38 +161,14 @@ public:
}; // class DamarisVarBase }; // class DamarisVarBase
/** /**
* class to store a Damaris variable representation for the XML file (can be * class to store a Damaris variable representation for the XML file
* used with /ref class DamarisKeywords). * (can be used with /ref class DamarisKeywords).
* *
* It is thought that the details stored in the object can be used to pass into * It is thought that the details stored in the object can be used to pass
* an XML generation function e.g. DamarisKeywords * 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 { template <typename T> class DamarisVar : public DamarisVarBase {
int dims_;
int num_params_; //!< Each paramater name string will need a value and they int num_params_; //!< Each paramater name string will need a value and they
//!< are set in SetDamarisParameter() //!< are set in SetDamarisParameter()
std::vector<int> std::vector<int>
@ -226,55 +202,67 @@ template <typename T> class DamarisVar : public DamarisVarBase {
size_t size_t
current_size_; //!< The total number of elements that may be held by this current_size_; //!< The total number of elements that may be held by this
//!< part of the variable - returned by the size() method. //!< part of the variable - returned by the size() method.
//!< N.B. the actual size of the data area is dependent on
//!< how the <variable> XML is written, as paramaters can
//!< be augmented by basic maths relationships. This value
//!< may not even be initialised if ParameterIsSet() method
//!< is being used (e.g. in version 2/ of the constructor below).
public: public:
/** /**
* Constructor - sets private data values and dos not initialise the shared memory area. * Constructor - sets private data values and dos not initialise the shared memory area.
* *
* Two usages: * N.B. These objects need a matching <variable ...> and <paramater ...> in the Damaris XML file
* Example XML definition: *
* <parameter name="my_param_name1" type="int" value="1" /> * Two usages:
* <parameter name="my_param_name2" type="int" value="1" /> * Example XML definition:
* <layout name="my_layout" type="int" dimensions="my_param_name1,my_param_name2" comment="This is a 2D variable"/> * <parameter name="my_param_name1" type="int" value="1" />
* <variable name="MYVARNAME" layout="my_layout" visualizable="true"/> * <parameter name="my_param_name2" type="int" value="1" />
* * <layout name="my_layout" type="int" dimensions="my_param_name1,my_param_name2" />
* 1/ The variable's layout needs to be initialised via parameters : * <variable name="MYVARNAME" layout="my_layout" visualizable="true"/>
* // Create the DamarisVar object: *
* damaris::model::DamarisVar<int>* MYVARNAME_2d = new damaris::model::DamarisVar<int>(2, * 1/ The variable's layout needs to be initialised via parameters :
* {std::string("my_param_name1"), std::string("my_param_name2")}, * // Create the DamarisVar object:
* {100, 25}, * damaris::model::DamarisVar<int> MYVARNAME_2d(2,{std::string("my_param_name1"),
* std::string("MYVARNAME"), rank_); * std::string("my_param_name2")},
* // sets the paramater sizes (so, here, my_param_name1 == 25 and my_param_name2 == 100) * {100, 25},
* MYVARNAME_2d->SetDamarisParameterAndShmem( {25, 100 } }; * std::string("MYVARNAME"), rank_);
* // Get a pointer to the memeory and use it * // sets the paramater sizes (so, here, my_param_name1 == 25 and my_param_name2 == 100)
* T * mymemory = MYVARNAME_2d->data(); * MYVARNAME_2d.SetDamarisParameterAndShmem( {25, 100 } };
* ... write data to mymemory .... * // Get a pointer to the memeory and use it
* delete MYVARNAME_2d; * T * mymemory = MYVARNAME_2d.data();
* or, * ... write data to mymemory ....
* 2/ The variable's layout has been initialised via parameters in another variable * // Damaris shared memory is tidied up when object MYVARNAME_2d is out of scope.
* (i.e. "my_param_name1" and "my_param_name2" have been previously set in the code) * or,
* // Create the DamarisVar object: * 2/ The variable's layout has been initialised via parameters in another variable
* damaris::model::DamarisVar<int>* MYVARNAME_2d = new damaris::model::DamarisVar<int>(2, * (i.e. "my_param_name1" and "my_param_name2" have been previously set in the code)
* {std::string("my_param_name1"), std::string("my_param_name2")}, * // Create the DamarisVar object:
* std::string("MYVARNAME"), rank_); * damaris::model::DamarisVar<int> MYVARNAME_2d(2, {std::string("my_param_name1"),
* // explicitly state that the paramater values have been set somewhere else in the code previously. std::string("my_param_name2")},
* MYVARNAME_2d->ParameterIsSet(); * std::string("MYVARNAME"), rank_);
* MYVARNAME_2d->SetPointersToDamarisShmem() *
* // Get a pointer to the memeory and use it * // explicitly state that the paramater values have been set somewhere else in the code previously.
* T * mymemory = MYVARNAME_2d->data(); * MYVARNAME_2d.ParameterIsSet();
* ... write data to mymemory .... *
* delete MYVARNAME_2d; * N.B. This will not set the internal current_size_ value so the size() value will
* * not be correct <- This is important to remember
* /param [IN] dims Used to check that the inputs to SetDamarisPosition() *
* have the same number of values - one value for each dimension * MYVARNAME_2d.SetPointersToDamarisShmem()
* /param [IN] param_names The name the Damaris paramaters. These names (in typical use) control * // Get a pointer to the memeory and use it
* a Damaris variables size (names are defined in the Damaris XML file). * T * mymemory = MYVARNAME_2d.data();
* /param [IN] variable_name The name of the Damaris variable (defined in the Damaris XML file) * ... write data to mymemory ....
* /param [IN] rank The rank of the process. Used for error output. * // Damaris shared memory is tidied up when object MYVARNAME_2d is out of scope.
*/ *
* /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 Damaris XML file)
* /param [IN] rank The rank of the process. Used for error output.
*/
DamarisVar(int dims, std::vector<std::string> param_names, DamarisVar(int dims, std::vector<std::string> param_names,
std::string variable_name, int rank) std::string variable_name, int rank)
: dims_(dims), param_names_(param_names), variable_name_(variable_name), : param_names_(param_names), variable_name_(variable_name),
rank_(rank) { rank_(rank) {
dam_err_ = DAMARIS_OK; dam_err_ = DAMARIS_OK;
@ -300,38 +288,40 @@ public:
has_error_ = false; has_error_ = false;
} }
/** /**
* Constructor - Sets private data values and also initialises the Damaris shared memory area for writing (and reading) * 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() * by specifying the values for the variables parameters .
* * i.e. makes the data() pointer available and sets the size of the memory block it points to.
* Example use: *
* Example XML definition: * N.B. These objects need a matching <variable ...> and <paramater ...> in the Damaris XML file
* <parameter name="my_param_name1" type="int" value="1" /> *
* <parameter name="my_param_name2" type="int" value="1" /> * Example use:
* <layout name="my_layout" type="int" dimensions="my_param_name1,my_param_name2" comment="This is a 2D variable" /> * Example XML definition:
* <variable name="MYVARNAME" layout="my_layout" visualizable="true"/> * <parameter name="my_param_name1" type="int" value="1" />
* // The paramaters are intialized in the constructor code * <parameter name="my_param_name2" type="int" value="1" />
* damaris::model::DamarisVar<int>* MYVARNAME_2d = new damaris::model::DamarisVar<int>(2, * <layout name="my_layout" type="int" dimensions="my_param_name1,my_param_name2" comment="This is a 2D variable" />
* {std::string("my_param_name1"), std::string("my_param_name2")}, * <variable name="MYVARNAME" layout="my_layout" visualizable="true"/>
* {100, 25}, * // The paramaters are intialized in the constructor code
* std::string("MYVARNAME"), rank_); * damaris::model::DamarisVar<int> MYVARNAME_2d(2,{std::string("my_param_name1"), std::string("my_param_name2")},
* T * mymemory = MYVARNAME_2d->data(); * {100, 25},
* ... write data to mymemory .... * std::string("MYVARNAME"), rank_);
* delete MYVARNAME_2d; * T * mymemory = MYVARNAME_2d.data();
* * ... write data to mymemory ....
* /param [IN] dims Used to check that the inputs to SetDamarisPosition() have * // Damaris shared memory is tidied up when object MYVARNAME_2d is out of scope.
* the same number of values - one value for each dimension *
* /param [IN] param_names The name the Damaris paramaters. These names (in typical use) * /param [IN] dims Used to check that the inputs to SetDamarisPosition() have
* control a Damaris variables size (names are defined in the Damaris XML file). * the same number of values - one value for each dimension
* /param [IN] param_values The values of the paramaters - this defines how much memory we will * /param [IN] param_names The name the Damaris paramaters. These names (in typical use)
* have access to in the shared memory area (on the current and ongoing iterations, * control a Damaris variables size (names are defined in the Damaris XML file).
* until later modified to new values) * /param [IN] param_values The values of the paramaters - this defines how much memory we will
* /param [IN] variable_name The name of the Damaris variable (defined in the Damaris XML file) * have access to in the shared memory area (on the current and ongoing iterations,
* /param [IN] rank The rank of the process. Used for error output. * until later modified to new values)
*/ * /param [IN] variable_name The name of the Damaris variable (defined in the Damaris XML file)
* /param [IN] rank The rank of the process. Used for error output.
*/
DamarisVar(int dims, std::vector<std::string> param_names, DamarisVar(int dims, std::vector<std::string> param_names,
std::vector<int> param_values, std::string variable_name, int rank) std::vector<int> param_values, std::string variable_name, int rank)
: dims_(dims), param_names_(param_names), variable_name_(variable_name), : param_names_(param_names), variable_name_(variable_name),
rank_(rank) { rank_(rank) {
DamarisVar(dims, param_names, variable_name, rank); DamarisVar(dims, param_names, variable_name, rank);
setDamarisParameterAndShmem( setDamarisParameterAndShmem(
@ -589,9 +579,9 @@ public:
* variable_name_ * variable_name_
*/ */
void setDamarisPosition(const std::vector<int64_t> &positionsVals) { void setDamarisPosition(const std::vector<int64_t> &positionsVals) {
assert(positionsVals.size() == dims_); assert(positionsVals.size() == num_params_);
for (int pos_dim = 0; pos_dim < dims_; pos_dim++) { for (int pos_dim = 0; pos_dim < num_params_; pos_dim++) {
positions_[pos_dim] = positionsVals[pos_dim]; positions_[pos_dim] = positionsVals[pos_dim];
} }
dam_err_ = dam_err_ =

View File

@ -48,7 +48,7 @@
// N.B. does not seem to be able to be allocated with new operator. // N.B. does not seem to be able to be allocated with new operator.
Opm::GridDataOutput::SimMeshDataAccessor geomData(gridView, Opm::GridDataOutput::SimMeshDataAccessor geomData(gridView,
Dune::Partition::interior ); Dune::Partition::interior );
geomData.printGridDetails(); geomData.printGridDetails();
@ -58,7 +58,7 @@
double * x_vert = new double[nvert]; double * x_vert = new double[nvert];
double * y_vert = new double[nvert]; double * y_vert = new double[nvert];
double * z_vert = new double[nvert]; double * z_vert = new double[nvert];
geomData.writeGridPoints(x_vert,y_vert,z_vert); geomData.writeGridPoints(x_vert,y_vert,z_vert, nvert);
... do something with vertex data x_vert, y_vert and z_vert .... ... do something with vertex data x_vert, y_vert and z_vert ....
@ -68,11 +68,18 @@
// example using AOS // example using AOS
double * xyz_vert_aos = new double[nvert*3]; double * xyz_vert_aos = new double[nvert*3];
geomData.writeGridPoints_AOS(xyz_vert_aos); geomData.writeGridPoints_AOS(xyz_vert_aos, nvert);
... do something with vertex data xyz_vert_aos.... ... do something with vertex data xyz_vert_aos....
delete [] xyz_vert_aos; delete [] xyz_vert_aos;
// example using SOA with std::vector<double>
std::vector<double> xyz_vert_soa(nvert*3);
geomData.writeGridPoints_SOA(xyz_vert_soa);
... do something with vertex data xyz_vert_soa....
*/ */
@ -148,8 +155,8 @@ public:
Count the vertices, cells and corners. Count the vertices, cells and corners.
Count all the vertices ( the Dune::Partitions::all partition ) as then we 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 do not need to renumber the vertices as all the subsets use references to
the full set. the full set.
*/ */
void countEntities() { void countEntities() {
// We include all the vertices for this ranks partition // We include all the vertices for this ranks partition
@ -166,10 +173,22 @@ public:
} }
} }
/**
Write the positions of vertices - directly to the pointers given in
parameters
@param x_inout to be filled with x coordinate verticies
@param y_inout to be filled with y coordinate verticies
@param y_inout to be filled with z coordinate verticies
@param max_size the maximum number of elements of type T that can be
written to the input pointer memory regions.
Returns the number of vertices written
*/
template <typename T> template <typename T>
long writeGridPoints(T *x_inout, T *y_inout, T *z_inout, long max_size = 0) { long writeGridPoints(T *x_inout, T *y_inout, T *z_inout, long max_size = 0) {
if (max_size < nvertices_) { if (max_size < nvertices_) {
// assert(max_size >= nvertices_);
OPM_THROW(std::runtime_error, OPM_THROW(std::runtime_error,
"Opm::GridDataOutput::writeGridPoints( T& x_inout, T& " "Opm::GridDataOutput::writeGridPoints( T& x_inout, T& "
"y_inout, T& z_inout ) " + "y_inout, T& z_inout ) " +
@ -207,21 +226,32 @@ public:
/** /**
Write the positions of vertices - directly to the pointers given in Write the positions of vertices - directly to the pointers given in
parameters parameters
@param x_inout to be filled with x coordinate verticies
@param y_inout to be filled with y coordinate verticies
@param y_inout to be filled with z coordinate verticies
All parameters must have a size() and data() method (e.g. a std::vector<T>)
and the current size() must be big enough
Returns the number of vertices written Returns the number of vertices written
*/ */
template <typename T> template <typename VectType>
long writeGridPoints(T &x_inout, T &y_inout, T &z_inout) { long writeGridPoints(VectType &x_inout, VectType &y_inout, VectType &z_inout) {
size_t check_size = x_inout.size(); size_t check_size_x = x_inout.size();
size_t check_size_y = y_inout.size();
size_t check_size_z = z_inout.size();
using VT = decltype(x_inout.data()[0]); using VT = decltype(x_inout.data()[0]);
if (check_size < nvertices_) { if ((check_size_x < nvertices_) || (check_size_y < nvertices_) || (check_size_z < nvertices_)){
// assert(check_size >= nvertices_); // assert(check_size >= nvertices_);
OPM_THROW(std::runtime_error, OPM_THROW(std::runtime_error,
"Opm::GridDataOutput::writeGridPoints( T& x_inout, T& " "Opm::GridDataOutput::writeGridPoints( VectType& x_inout, VectType& "
"y_inout, T& z_inout ) " + "y_inout, VectType& z_inout ) At least one of the inputs" +
" Input objects size " + std::to_string(check_size) + " object x size " + std::to_string(check_size_x) +
" object y size " + std::to_string(check_size_y) +
" object z size " + std::to_string(check_size_z) +
" is not sufficient to fit the nvertices_ values( " + " is not sufficient to fit the nvertices_ values( " +
std::to_string(nvertices_) + " )"); std::to_string(nvertices_) + " )");
} }
@ -254,10 +284,15 @@ public:
} }
/** /**
Write positions of vertices as array of structures : x,y,z,x,y,z,x,y,z,... Write the positions of vertices - directly to the pointers given in
parameters as Array of Structures x,y,z,x,y,z,x,y,z,...
Returns the number of vertices written
*/ @param xyz_inout is the array to be filled with x,y,z coordinate verticies.
@param max_size is the maximum number x,y,z structures with elements of type T
that can be written to the input pointer memory regions.
Returns the number of vertices written
*/
template <typename T> template <typename T>
long writeGridPoints_AOS(T *xyz_inout, long max_size = 0) { long writeGridPoints_AOS(T *xyz_inout, long max_size = 0) {
if (max_size < nvertices_ * 3) { if (max_size < nvertices_ * 3) {
@ -288,10 +323,15 @@ public:
return ((i) / 3); return ((i) / 3);
} }
/** /**
Write positions of vertices as array of structures : x,y,z,x,y,z,x,y,z,... Write the positions of vertices - directly to the pointers given in
parameters as Array of Structures x,y,z,x,y,z,x,y,z,...
Returns the number of vertices written
@param xyz_inout is the array to be filled with x,y,z coordinate verticies.
The object VectType must have a size() and data() method (e.g. a std::vector<T>)
Returns the number of vertices written
*/ */
template <typename VectType> long writeGridPoints_AOS(VectType &xyz_inout) { template <typename VectType> long writeGridPoints_AOS(VectType &xyz_inout) {
size_t check_size = xyz_inout.size(); size_t check_size = xyz_inout.size();
@ -328,12 +368,16 @@ public:
return ((i) / 3); return ((i) / 3);
} }
/** /**
Write positions of vertices as structure of arrays : Write the positions of vertices - directly to the pointers given in
x,x,x,...,y,y,y,...,z,z,z,... parameters as Structure of Arrays: x,x,x,...,y,y,y,...,z,z,z,...
Returns the number of vertices written @param xyz_inout is the array to be filled with x,y,z coordinate verticies.
*/ @param max_size number of verticies (x,...y,...z,... structures) with elements of type T
that can be written to the input pointer memory regions.
Returns the number of vertices written
*/
template <typename T> template <typename T>
long writeGridPoints_SOA(T *xyz_inout, long max_size = 0) { long writeGridPoints_SOA(T *xyz_inout, long max_size = 0) {
if (max_size < nvertices_ * 3) { if (max_size < nvertices_ * 3) {
@ -371,11 +415,14 @@ public:
} }
/** /**
Write positions of vertices as structure of arrays : Write the positions of vertices - directly to the pointers given in
x,x,x,...,y,y,y,...,z,z,z,... parameters as Structure of Arrays: x,x,x,...,y,y,y,...,z,z,z,...
Returns the number of vertices written @param xyz_inout is the array to be filled with x,y,z coordinate verticies.
*/ The object VectType must have a size() and data() method (e.g. a std::vector<T>)
Returns the number of vertices written
*/
template <typename VectType> long writeGridPoints_SOA(VectType &xyz_inout) { template <typename VectType> long writeGridPoints_SOA(VectType &xyz_inout) {
size_t check_size = xyz_inout.size(); size_t check_size = xyz_inout.size();
@ -420,7 +467,12 @@ public:
/** /**
* Write the connectivity array - directly to the pointer given in parameter 1 * Write the connectivity array - directly to the pointer given in parameter 1
Reorders the indices as selected either in DUNE order or VTK order. Reorders the indices as selected either in DUNE order or VTK order.
@param connectivity_inout is the array to be filled with connectivity indexes
(i.e. the index into the vertex array)
@param whichOrder, is the order that verticies are traversed to create a cell (VTK or DUNE)
@param max_size is used to check that the space available in the input pointer
parameter will fit the number of corner values written.
Returns the number of corner indices written. Returns the number of corner indices written.
*/ */
template <typename Integer> template <typename Integer>
@ -465,11 +517,17 @@ public:
} }
/** /**
* Write the connectivity array - directly to the pointer given in parameter 1 * Write the connectivity array - directly to a VectType object given in parameter 1
Reorders the indices as selected either in DUNE order or VTK order. Reorders the indices as selected either in DUNE order or VTK order.
Returns the number of corner indices written. @param connectivity_inout is the array to be filled with connectivity indexes
*/ (i.e. the index into the vertex array)
The object VectType must have a size() and data() method (e.g. a std::vector<T>)
@param whichOrder, is the order that verticies are traversed to create a cell (VTK or DUNE)
@param max_size is used to check that the space available in the input pointer
parameter will fit the number of corner values written.
Returns the number of corner indices written.
*/
template <typename VectType> template <typename VectType>
long writeConnectivity(VectType &connectivity_inout, long writeConnectivity(VectType &connectivity_inout,
ConnectivityVertexOrder whichOrder) { ConnectivityVertexOrder whichOrder) {
@ -514,10 +572,18 @@ public:
return (i); return (i);
} }
/**
/**
* Write the offsets values - directly to the pointer given in parameter 1 * Write the offsets values - directly to the pointer given in parameter 1
Returns the (number of offset values written + 1)
*/ @param offsets_inout is the array to be filled with offsets into the connectivity array
(i.e. the index into the connectivity array to determine the vertices used for
the particular cell)
@param max_size is used to check that the space available in the input pointer
parameter will fit the number of cell offset values written.
Returns number of offset values written + 1
*/
template <typename Integer> template <typename Integer>
long writeOffsetsCells(Integer *offsets_inout, long max_size = 0) { long writeOffsetsCells(Integer *offsets_inout, long max_size = 0) {
if (max_size < ncells_) { if (max_size < ncells_) {
@ -539,10 +605,16 @@ public:
return (i); // This should be 1 greater than ncells_ return (i); // This should be 1 greater than ncells_
} }
/** /**
* Write the offsets values - directly to the pointer given in parameter 1 * Write the offsets values - directly to a VectType object given in parameter 1
Returns the (number of offset values written + 1)
*/ @param offsets_inout is the array to be filled with offsets into the connectivity array
(i.e. the index into the connectivity array to determine the vertices used for
the particular cell).
The object VectType must have a size() and data() method (e.g. a std::vector<T>)
Returns number of offset values written + 1
*/
template <typename VectType> long writeOffsetsCells(VectType &offsets_inout) { template <typename VectType> long writeOffsetsCells(VectType &offsets_inout) {
size_t check_size = offsets_inout.size(); size_t check_size = offsets_inout.size();
if (check_size < ncells_) { if (check_size < ncells_) {
@ -567,9 +639,16 @@ public:
return (i); // This should be 1 greater than ncells_ return (i); // This should be 1 greater than ncells_
} }
/** /**
* Write the Cell types array - directly to the pointer given in parameter 1 * Write the cell types values - directly to the pointer given in parameter 1
*/
@param types_inout is the array to be filled with the cell types (VTK defined values)
@param max_size is used to check that the space available in the input pointer
parameter will fit the number of cell offset values written.
Returns number of cells type values written
*/
template <typename Integer> template <typename Integer>
long writeCellTypes(Integer *types_inout, long max_size = 0) { long writeCellTypes(Integer *types_inout, long max_size = 0) {
if (max_size < ncells_) { if (max_size < ncells_) {
@ -589,14 +668,18 @@ public:
return (i); return (i);
} }
/** /**
* Write the Cell types array - directly to the pointer given in parameter 1 * Write the cell types values - directly to the VectType object given in parameter 1
*/
@param types_inout is the array to be filled with the cell types (VTK defined values)
The object VectType must have a size() and data() method (e.g. a std::vector<T>)
Returns number of cells type values written
*/
template <typename VectType> long writeCellTypes(VectType &types_inout) { template <typename VectType> long writeCellTypes(VectType &types_inout) {
size_t check_size = types_inout.size(); size_t check_size = types_inout.size();
if (check_size < ncells_) { if (check_size < ncells_) {
// assert(check_size >= ncells_);
OPM_THROW( OPM_THROW(
std::runtime_error, std::runtime_error,
"Opm::GridDataOutput::writeCellTypes( VectType& types_inout ) " + "Opm::GridDataOutput::writeCellTypes( VectType& types_inout ) " +

View File

@ -39,7 +39,7 @@ std::string initDamarisXmlFile()
<architecture> <architecture>
<domains count="1"/> <domains count="1"/>
<dedicated cores="_DC_REGEX_" nodes="_DN_REGEX_"/> <dedicated cores="_DC_REGEX_" nodes="_DN_REGEX_"/>
<buffer name="_SIM_NAME_" size="_SHMEM_BUFFER_BYTES_REGEX_" /> <buffer name="_SHMEM_NAME_" size="_SHMEM_BUFFER_BYTES_REGEX_" />
<placement /> <placement />
<queue name="queue" size="300" /> <queue name="queue" size="300" />
</architecture> </architecture>