/* Copyright 2023 Inria, Bretagne–Atlantique 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 . */ #include #include #include #include #include #include #include #include #include #include namespace Opm::DamarisOutput { DamarisVarXMLAttributes::DamarisVarXMLAttributes() { // Additional data needed to complete an XML element type_ = "scalar"; // This is probably not needed as vector data is defined using // the Layout paramter. Could be useful for cross checking visualizable_ = "false"; time_varying_ = "true"; centering_ = "zonal"; } std::string DamarisVarXMLAttributes::ReturnXMLForVariable() { std::string var_str; using Entry = std::pair; auto addAttrib = [&var_str](const Entry& entry) { if (!entry.second.empty()) { var_str += fmt::format(" {}=\"{}\"", entry.first, entry.second); } }; const auto entries = std::array{ Entry{"layout", this->layout_}, Entry{"mesh", this->mesh_}, Entry{"type", this->type_}, Entry{"visualizable", this->visualizable_}, Entry{"unit", this->unit_}, Entry{"time_varying", this->time_varying_}, Entry{"centering", this->centering_}, Entry{"store", this->store_}, Entry{"select-mem", this->select_mem_}, Entry{"select-file", this->select_file_}, Entry{"select-subset", this->select_subset_} }; std::for_each(entries.begin(), entries.end(), addAttrib); return var_str; } template DamarisVar::DamarisVar(int dims, const std::vector& param_names, const std::string& variable_name, int rank) : param_names_(param_names) , variable_name_(variable_name) , rank_(rank) { dam_err_ = DAMARIS_OK; assert(param_names_.size() == static_cast(dims)); assert(dims > 0); has_error_ = false; // Check that our template type T matches out Damaris XML type TestType(variable_name); if (hasError()) { printError(); // throws a runtime error, with error message from // dam_err_sstr_ } current_size_ = 0; num_params_ = param_names_.size(); param_sizes_.resize(num_params_); positions_.resize(dims); data_ptr_ = nullptr; parameters_set_ = false; has_error_ = false; } template DamarisVar::DamarisVar(int dims, const std::vector& param_names, const std::vector& param_values, const std::string& variable_name, int rank) : param_names_(param_names) , variable_name_(variable_name) , rank_(rank) { DamarisVar(dims, param_names, variable_name, rank); setDamarisParameterAndShmem(param_values); // Initialise the memory size in the constructor. } template DamarisVar::~DamarisVar() { if (data_ptr_ != nullptr) { commitVariableDamarisShmem(); clearVariableDamarisShmem(); } if (this->hasError()) { printError(); // flush out any error messages } } template void DamarisVar::printError() const { OPM_THROW(std::runtime_error, dam_err_str_); } template std::string DamarisVar::returnXMLForVariable() { return fmt::format("", variable_name_, xml_attributes_.ReturnXMLForVariable()); } template void DamarisVar::setDamarisParameter(const std::vector& paramSizeVal) { assert(paramSizeVal.size() == static_cast(num_params_)); bool resbool = true; std::size_t total_size = 1; for (int varnum = 0; varnum < num_params_; varnum++) { param_sizes_[varnum] = paramSizeVal[varnum]; total_size *= param_sizes_[varnum]; dam_err_ = damaris_parameter_set(param_names_[varnum].c_str(), ¶mSizeVal[varnum], sizeof(int)); if (dam_err_ != DAMARIS_OK) { dam_err_str_ += fmt::format(" ERROR rank = {}: class DamarisVar : damaris_parameter_set(\"{}\"" ", paramSizeVal, sizeof(int)); Damaris error = {}\n", rank_, param_names_[varnum], damaris_error_string(dam_err_)); resbool = false; has_error_ = true; } } if (resbool == true) { parameterIsSet(); // sets parameters_set_ and gets the size of the // variables block storage (as number of elemnts) } if (total_size > 0) { current_size_ = total_size; } else { dam_err_str_ += fmt::format(" ERROR rank = {}: class DamarisVar::getDataStoreBlockSize() " "The total size of the variable is 0 - please check " "input paramSizeVal array.\n", rank_); has_error_ = true; } if (hasError()) { printError(); } } template void DamarisVar::setDamarisPosition(const std::vector& positionsVals) { assert(positionsVals.size() == static_cast(num_params_)); for (int pos_dim = 0; pos_dim < num_params_; 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_str_ += fmt::format(" ERROR rank = {}: class DamarisVar : damaris_set_position(\"{}\"" ", positionsVals); Damaris error = {}\n", rank_, variable_name_, damaris_error_string(dam_err_)); has_error_ = true; } if (hasError()) { printError(); } } template void DamarisVar::setPointersToDamarisShmem() { if (parameters_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_str_ += fmt::format(" ERROR rank = {}: class DamarisVar : damaris_alloc(\"{}\"" ", (void **) &ret_ptr), Damaris error = {}\n", rank_, variable_name_, damaris_error_string(dam_err_)); has_error_ = true; } } else { dam_err_ = -1; dam_err_str_ += fmt::format(" ERROR rank = {}: class DamarisVar : " "setDamarisParameter() should be " "called first to define the size of the memory " "block required for variable: {}\n", rank_, variable_name_); has_error_ = true; } if (hasError()) { printError(); } } template void DamarisVar::commitVariableDamarisShmem() { // 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_str_ += fmt::format(" ERROR rank = {}: class DamarisVar : damaris_commit(\"{}\")" ", Damaris error = {}\n", rank_, variable_name_, damaris_error_string(dam_err_)); has_error_ = true; } } template void DamarisVar::clearVariableDamarisShmem() { // 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_str_ += fmt::format(" ERROR rank = {}: class DamarisVar : damaris_clear(\"{}\")" ", Damaris error = {}\n", rank_, variable_name_, damaris_error_string(dam_err_)); has_error_ = true; } data_ptr_ = nullptr; } template bool DamarisVar::TestType(const std::string& variable_name) { bool resbool = true; // This gets the type of the Damaris XML 's DAMARIS_TYPE_STR vartype; dam_err_ = damaris_get_type(variable_name.c_str(), &vartype); if (dam_err_ != DAMARIS_OK) { dam_err_str_ = fmt::format(" ERROR rank = {}: DamarisVar::DamarisVar () damaris_get_type(\"{}\"" ", vartype); Damaris error = {}\n", rank_, variable_name_, damaris_error_string(dam_err_)); has_error_ = true; return false; } T test_id; const std::type_info& t1 = typeid(test_id); auto check = [&variable_name,this](auto td) { const std::type_info& t2 = typeid(td); if (t1 != t2) { formatTypeError(variable_name, t1.name(), t2.name()); return false; } return true; }; if (vartype == DAMARIS_TYPE_DOUBLE) { resbool = check(double{}); } else if (vartype == DAMARIS_TYPE_FLOAT) { resbool = check(float{}); } else if (vartype == DAMARIS_TYPE_CHAR) { resbool = check(char{}); } else if (vartype == DAMARIS_TYPE_UCHAR) { using uchar = unsigned char; resbool = check(uchar{}); } else if (vartype == DAMARIS_TYPE_SHORT) { resbool = check(short{}); } else if (vartype == DAMARIS_TYPE_USHORT) { using ushort = unsigned short; resbool = check(ushort{}); } else if (vartype == DAMARIS_TYPE_INT) { resbool = check(int{}); } else if (vartype == DAMARIS_TYPE_UINT) { using uint = unsigned int; resbool = check(uint{}); } else if (vartype == DAMARIS_TYPE_LONG) { resbool = check(long{}); } else if (vartype == DAMARIS_TYPE_ULONG) { using ulong = unsigned long; resbool = check(ulong{}); } else if (vartype == DAMARIS_TYPE_UNDEFINED) { dam_err_str_ += fmt::format(" ERROR rank = {}: DamarisVar::DamarisVar():: \"{}\"" " has type DAMARIS_TYPE_UNDEFINED\n", rank_, variable_name); has_error_ = true; resbool = false; } else { dam_err_str_ += fmt::format(" ERROR rank = {}: DamarisVar::DamarisVar():: \"{}\"" " is not of available type\n", rank_, variable_name); has_error_ = true; resbool = false; } return resbool; } template void DamarisVar::formatTypeError(const std::string& var_name, const std::string& type_name1, const std::string& type_name2) { dam_err_str_ += fmt::format(" ERROR rank = {}: DamarisVar::DamarisVar() variable_name: \"{}\"" " The template type of Type of DamarisVar in the code: {}" " does not match type in XML: {}\n", rank_, var_name, type_name1, type_name2); has_error_ = true; } template class DamarisVar; template class DamarisVar; template class DamarisVar; } // namespace Opm::DamarisOutput