Skip to content
Snippets Groups Projects
Select Git revision
  • 34d6a933b43fdf6a1340b1d679c0233cd4b08ae4
  • develop default protected
  • feature/gmsh-reader
  • save_clemence
  • origin/stage/bouguettaia
  • feature/kinetic-schemes
  • feature/reconstruction
  • feature/local-dt-fsi
  • feature/composite-scheme-sources
  • feature/composite-scheme-other-fluxes
  • feature/serraille
  • feature/variational-hydro
  • feature/composite-scheme
  • hyperplastic
  • feature/polynomials
  • feature/gks
  • feature/implicit-solver-o2
  • feature/coupling_module
  • feature/implicit-solver
  • feature/merge-local-dt-fsi
  • master protected
  • v0.5.0 protected
  • v0.4.1 protected
  • v0.4.0 protected
  • v0.3.0 protected
  • v0.2.0 protected
  • v0.1.0 protected
  • Kidder
  • v0.0.4 protected
  • v0.0.3 protected
  • v0.0.2 protected
  • v0 protected
  • v0.0.1 protected
33 results

AffectationRegisterForB.hpp

Blame
  • WriterBase.cpp 16.28 KiB
    #include <output/WriterBase.hpp>
    
    #include <mesh/IMesh.hpp>
    #include <mesh/ItemArrayVariant.hpp>
    #include <mesh/ItemValueVariant.hpp>
    #include <output/NamedDiscreteFunction.hpp>
    #include <output/NamedItemArrayVariant.hpp>
    #include <output/NamedItemValueVariant.hpp>
    #include <output/OutputNamedItemValueSet.hpp>
    #include <scheme/DiscreteFunctionP0.hpp>
    #include <scheme/DiscreteFunctionP0Vector.hpp>
    #include <scheme/DiscreteFunctionVariant.hpp>
    #include <scheme/IDiscreteFunctionDescriptor.hpp>
    #include <utils/Exceptions.hpp>
    
    template <typename DiscreteFunctionType>
    void
    WriterBase::_registerDiscreteFunction(const std::string& name,
                                          const DiscreteFunctionType& discrete_function,
                                          OutputNamedItemDataSet& named_item_data_set)
    {
      if constexpr (is_discrete_function_P0_v<DiscreteFunctionType>) {
        named_item_data_set.add(NamedItemData{name, discrete_function.cellValues()});
      } else {
        static_assert(is_discrete_function_P0_vector_v<DiscreteFunctionType>, "unexpected discrete function type");
        named_item_data_set.add(NamedItemData{name, discrete_function.cellArrays()});
      }
    }
    
    void
    WriterBase::_checkConnectivity(
      const std::shared_ptr<const IMesh>& mesh,
      const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list) const
    {
      Assert(named_discrete_data_list.size() > 0);
    
      std::shared_ptr<const IConnectivity> connectivity = [&]() -> std::shared_ptr<const IConnectivity> {
        switch (mesh->dimension()) {
        case 1: {
          return dynamic_cast<const Mesh<Connectivity<1>>&>(*mesh).shared_connectivity();
        }
        case 2: {
          return dynamic_cast<const Mesh<Connectivity<2>>&>(*mesh).shared_connectivity();
        }
        case 3: {
          return dynamic_cast<const Mesh<Connectivity<3>>&>(*mesh).shared_connectivity();
        }
        default: {
          throw UnexpectedError("invalid dimension");
        }
        }
      }();
    
      for (size_t i = 0; i < named_discrete_data_list.size(); ++i) {
        const auto& named_discrete_data = named_discrete_data_list[i];
    
        if (named_discrete_data->type() == INamedDiscreteData::Type::item_value) {
          const NamedItemValueVariant& named_item_value_variant =
            dynamic_cast<const NamedItemValueVariant&>(*named_discrete_data);
    
          std::visit(
            [&](auto&& item_value) {
              if (item_value.connectivity_ptr() != connectivity) {
                std::ostringstream error_msg;
                error_msg << "The variable " << rang::fgB::yellow << named_item_value_variant.name() << rang::fg::reset
                          << " is not defined on the provided same connectivity as the mesh\n";
                throw NormalError(error_msg.str());
              }
            },
            named_item_value_variant.itemValueVariant()->itemValue());
        }
      }
    }
    
    void
    WriterBase::_checkSignature(
      const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list) const
    {
      using NameTypeMap = std::map<std::string, std::string>;
      NameTypeMap name_type_map;
    
      for (auto named_discrete_data : named_discrete_data_list) {
        switch (named_discrete_data->type()) {
        case INamedDiscreteData::Type::item_value: {
          const NamedItemValueVariant& named_item_value = dynamic_cast<const NamedItemValueVariant&>(*named_discrete_data);
          std::visit(
            [&](auto&& item_value) {
              using ItemValueT = std::decay_t<decltype(item_value)>;
              using DataType   = std::decay_t<typename ItemValueT::data_type>;
    
              std::ostringstream type_name;
              type_name << "item_value(" << dataTypeName(ast_node_data_type_from<DataType>) << ')';
    
              name_type_map[named_discrete_data->name()] = type_name.str();
            },
            named_item_value.itemValueVariant()->itemValue());
          break;
        }
        case INamedDiscreteData::Type::item_array: {
          const NamedItemArrayVariant& named_item_array = dynamic_cast<const NamedItemArrayVariant&>(*named_discrete_data);
          std::visit(
            [&](auto&& item_value) {
              using ItemValueT = std::decay_t<decltype(item_value)>;
              using DataType   = std::decay_t<typename ItemValueT::data_type>;
    
              std::ostringstream type_name;
              type_name << "item_array(" << dataTypeName(ast_node_data_type_from<DataType>) << ')';
    
              name_type_map[named_discrete_data->name()] = type_name.str();
            },
            named_item_array.itemArrayVariant()->itemArray());
          break;
        }
        case INamedDiscreteData::Type::discrete_function: {
          const NamedDiscreteFunction& named_discrete_function =
            dynamic_cast<const NamedDiscreteFunction&>(*named_discrete_data);
          std::visit(
            [&](auto&& discrete_function) {
              std::ostringstream type_name;
              type_name << "Vh(" << dataTypeName(discrete_function.dataType()) << ')';
    
              name_type_map[named_discrete_data->name()] = type_name.str();
            },
            named_discrete_function.discreteFunctionVariant()->discreteFunction());
          break;
        }
        }
      }
    
      std::string signature{"|"};
      for (auto&& [name, type_name] : name_type_map) {
        signature += name + std::string{"-"} + type_name + std::string{"|"};
      }
    
      if (m_signature.has_value()) {
        if (m_signature.value() != signature) {
          throw NormalError("output variable list changed");
        }
      } else {
        m_signature = signature;
      }
    }
    
    void
    WriterBase::_checkMesh(const std::shared_ptr<const IMesh>& mesh,
                           const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list) const
    {
      Assert(named_discrete_data_list.size() > 0);
    
      for (size_t i = 0; i < named_discrete_data_list.size(); ++i) {
        const auto& named_discrete_data = named_discrete_data_list[i];
    
        if (named_discrete_data->type() == INamedDiscreteData::Type::discrete_function) {
          const NamedDiscreteFunction& named_discrete_function =
            dynamic_cast<const NamedDiscreteFunction&>(*named_discrete_data);
    
          std::shared_ptr<const IMesh> discrete_function_mesh =
            std::visit([](auto&& f) { return f.mesh(); },
                       named_discrete_function.discreteFunctionVariant()->discreteFunction());
    
          if (mesh != discrete_function_mesh) {
            std::ostringstream error_msg;
            error_msg << "The variable " << rang::fgB::yellow << named_discrete_function.name() << rang::fg::reset
                      << " is not defined on the provided mesh\n";
            throw NormalError(error_msg.str());
          }
        }
      }
    }
    
    std::shared_ptr<const IMesh>
    WriterBase::_getMesh(const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list) const
    {
      Assert(named_discrete_data_list.size() > 0);
    
      std::map<std::shared_ptr<const IMesh>, std::string> mesh_set;
      std::map<std::shared_ptr<const IConnectivity>, std::string> connectivity_set;
    
      for (size_t i = 0; i < named_discrete_data_list.size(); ++i) {
        const auto& named_discrete_data = named_discrete_data_list[i];
    
        switch (named_discrete_data->type()) {
        case INamedDiscreteData::Type::discrete_function: {
          const NamedDiscreteFunction& named_discrete_function =
            dynamic_cast<const NamedDiscreteFunction&>(*named_discrete_data);
    
          std::shared_ptr mesh = std::visit([&](auto&& f) { return f.mesh(); },
                                            named_discrete_function.discreteFunctionVariant()->discreteFunction());
          mesh_set[mesh]       = named_discrete_function.name();
    
          switch (mesh->dimension()) {
          case 1: {
            connectivity_set[dynamic_cast<const Mesh<Connectivity<1>>&>(*mesh).shared_connectivity()] =
              named_discrete_function.name();
            break;
          }
          case 2: {
            connectivity_set[dynamic_cast<const Mesh<Connectivity<2>>&>(*mesh).shared_connectivity()] =
              named_discrete_function.name();
            break;
          }
          case 3: {
            connectivity_set[dynamic_cast<const Mesh<Connectivity<3>>&>(*mesh).shared_connectivity()] =
              named_discrete_function.name();
            break;
          }
          default: {
            throw UnexpectedError("invalid dimension");
          }
          }
          break;
        }
        case INamedDiscreteData::Type::item_value: {
          const NamedItemValueVariant& named_item_value_variant =
            dynamic_cast<const NamedItemValueVariant&>(*named_discrete_data);
    
          std::visit([&](
                       auto&&
                         item_value) { connectivity_set[item_value.connectivity_ptr()] = named_item_value_variant.name(); },
                     named_item_value_variant.itemValueVariant()->itemValue());
          break;
        }
        case INamedDiscreteData::Type::item_array: {
          const NamedItemArrayVariant& named_item_array_variant =
            dynamic_cast<const NamedItemArrayVariant&>(*named_discrete_data);
    
          std::visit([&](
                       auto&&
                         item_array) { connectivity_set[item_array.connectivity_ptr()] = named_item_array_variant.name(); },
                     named_item_array_variant.itemArrayVariant()->itemArray());
          break;
        }
        }
      }
    
      if (mesh_set.size() != 1) {
        if (mesh_set.size() == 0) {
          throw NormalError("cannot find any mesh associated to output quantities");
        } else {
          std::ostringstream error_msg;
          error_msg << "cannot save data using different " << rang::fgB::red << "meshes" << rang::fg::reset
                    << " in the same file!\n";
          error_msg << rang::fgB::yellow << "note:" << rang::fg::reset
                    << "the following variables are defined on different meshes:";
          for (const auto& [mesh, name] : mesh_set) {
            error_msg << "\n- " << name;
          }
          throw NormalError(error_msg.str());
        }
      }
    
      if (connectivity_set.size() > 1) {
        std::ostringstream error_msg;
        error_msg << "cannot save data using different " << rang::fgB::red << "connectivities" << rang::fg::reset
                  << " in the same file!\n";
        error_msg << rang::fgB::yellow << "note:" << rang::fg::reset
                  << "the following variables are defined on different connectivities:";
        for (const auto& [connectivity, name] : connectivity_set) {
          error_msg << "\n- " << name;
        }
        throw NormalError(error_msg.str());
      }
    
      return mesh_set.begin()->first;
    }
    
    OutputNamedItemDataSet
    WriterBase::_getOutputNamedItemDataSet(
      const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list) const
    {
      OutputNamedItemDataSet named_item_data_set;
    
      for (auto& named_discrete_data : named_discrete_data_list) {
        switch (named_discrete_data->type()) {
        case INamedDiscreteData::Type::discrete_function: {
          const NamedDiscreteFunction& named_discrete_function =
            dynamic_cast<const NamedDiscreteFunction&>(*named_discrete_data);
    
          const std::string& name = named_discrete_function.name();
    
          const DiscreteFunctionVariant& discrete_function_variant = *named_discrete_function.discreteFunctionVariant();
    
          std::visit([&](auto&& f) { WriterBase::_registerDiscreteFunction(name, f, named_item_data_set); },
                     discrete_function_variant.discreteFunction());
          break;
        }
        case INamedDiscreteData::Type::item_value: {
          const NamedItemValueVariant& named_item_value_variant =
            dynamic_cast<const NamedItemValueVariant&>(*named_discrete_data);
    
          const std::string& name = named_item_value_variant.name();
    
          const ItemValueVariant& item_value_variant = *named_item_value_variant.itemValueVariant();
    
          std::visit([&](auto&& item_value) { named_item_data_set.add(NamedItemData{name, item_value}); },
                     item_value_variant.itemValue());
          break;
        }
        case INamedDiscreteData::Type::item_array: {
          const NamedItemArrayVariant& named_item_array_variant =
            dynamic_cast<const NamedItemArrayVariant&>(*named_discrete_data);
    
          const std::string& name = named_item_array_variant.name();
    
          const ItemArrayVariant& item_value_variant = *named_item_array_variant.itemArrayVariant();
    
          std::visit(
            [&](auto&& item_array) {
              using ItemArrayType = std::decay_t<decltype(item_array)>;
              using DataType      = std::decay_t<typename ItemArrayType::data_type>;
              if constexpr (std::is_arithmetic_v<DataType>) {
                named_item_data_set.add(NamedItemData{name, item_array});
              } else {
                throw NormalError("can only write item_array containing scalar values");
              }
            },
            item_value_variant.itemArray());
          break;
        }
        }
      }
      return named_item_data_set;
    }
    
    WriterBase::WriterBase(const std::string& base_filename, const double& time_period)
      : m_base_filename{base_filename}, m_period_manager(time_period), m_signature(std::nullopt)
    {}
    
    WriterBase::WriterBase(const std::string& base_filename) : m_base_filename{base_filename}, m_signature(std::nullopt) {}
    
    void
    WriterBase::write(const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list) const
    {
      if (m_period_manager.has_value()) {
        throw NormalError("this writer requires time value");
      } else {
        std::shared_ptr<const IMesh> mesh = _getMesh(named_discrete_data_list);
        this->_write(*mesh, named_discrete_data_list);
      }
    }
    
    void
    WriterBase::writeIfNeeded(const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list,
                              double time) const
    {
      if (m_period_manager.has_value()) {
        const double last_time = m_period_manager->getLastTime();
        if (time == last_time)
          return;   // output already performed
    
        if (time >= m_period_manager->nextTime()) {
          std::shared_ptr<const IMesh> mesh = _getMesh(named_discrete_data_list);
          this->_checkSignature(named_discrete_data_list);
          this->_writeAtTime(*mesh, named_discrete_data_list, time);
          m_period_manager->setSaveTime(time);
        }
      } else {
        throw NormalError("this writer does not allow time value");
      }
    }
    
    void
    WriterBase::writeForced(const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list,
                            double time) const
    {
      if (m_period_manager.has_value()) {
        if (time == m_period_manager->getLastTime())
          return;   // output already performed
    
        std::shared_ptr<const IMesh> mesh = _getMesh(named_discrete_data_list);
        this->_checkSignature(named_discrete_data_list);
        this->_writeAtTime(*mesh, named_discrete_data_list, time);
        m_period_manager->setSaveTime(time);
      } else {
        throw NormalError("this writer does not allow time value");
      }
    }
    
    void
    WriterBase::writeOnMesh(const std::shared_ptr<const IMesh>& mesh,
                            const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list) const
    {
      if (m_period_manager.has_value()) {
        throw NormalError("this writer requires time value");
      } else {
        this->_checkMesh(mesh, named_discrete_data_list);
        this->_checkConnectivity(mesh, named_discrete_data_list);
        this->_write(*mesh, named_discrete_data_list);
      }
    }
    
    void
    WriterBase::writeOnMeshIfNeeded(const std::shared_ptr<const IMesh>& mesh,
                                    const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list,
                                    double time) const
    {
      if (m_period_manager.has_value()) {
        if (time == m_period_manager->getLastTime()) {
          return;   // output already performed
        }
    
        this->_checkMesh(mesh, named_discrete_data_list);
        this->_checkConnectivity(mesh, named_discrete_data_list);
        this->_writeAtTime(*mesh, named_discrete_data_list, time);
        m_period_manager->setSaveTime(time);
      } else {
        throw NormalError("this writer does not allow time value");
      }
    }
    
    void
    WriterBase::writeOnMeshForced(const std::shared_ptr<const IMesh>& mesh,
                                  const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list,
                                  double time) const
    {
      if (m_period_manager.has_value()) {
        if (time == m_period_manager->getLastTime()) {
          return;   // output already performed
        }
        this->_checkMesh(mesh, named_discrete_data_list);
        this->_checkConnectivity(mesh, named_discrete_data_list);
        this->_writeAtTime(*mesh, named_discrete_data_list, time);
        m_period_manager->setSaveTime(time);
      } else {
        throw NormalError("this writer does not allow time value");
      }
    }
    
    void
    WriterBase::writeMesh(const std::shared_ptr<const IMesh>& mesh) const
    {
      writeMesh(*mesh);
    }
    
    void
    WriterBase::writeMesh(const IMesh& mesh) const
    {
      if (m_period_manager.has_value()) {
        throw NormalError("write_mesh requires a writer without time period");
      } else {
        this->_writeMesh(mesh);
      }
    }