Skip to content
Snippets Groups Projects
Select Git revision
  • 6b2d417ae691374ae1121ac1c5e156f154cda746
  • 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

GnuplotWriter1D.cpp

Blame
    • Stéphane Del Pino's avatar
      6b2d417a
      Add `gnuplot_1d_writer` · 6b2d417a
      Stéphane Del Pino authored
      The aim of this variant is to provide a more classic version of the
      output: one value per cell or per node.
      
      It can only be used for 1d data.
      
      It remains to make it work in parallel.
      6b2d417a
      History
      Add `gnuplot_1d_writer`
      Stéphane Del Pino authored
      The aim of this variant is to provide a more classic version of the
      output: one value per cell or per node.
      
      It can only be used for 1d data.
      
      It remains to make it work in parallel.
    GnuplotWriter1D.cpp 10.24 KiB
    #include <output/GnuplotWriter1D.hpp>
    
    #include <mesh/Connectivity.hpp>
    #include <mesh/ItemValue.hpp>
    #include <mesh/Mesh.hpp>
    #include <mesh/MeshData.hpp>
    #include <mesh/MeshDataManager.hpp>
    #include <utils/Messenger.hpp>
    #include <utils/PugsTraits.hpp>
    #include <utils/RevisionInfo.hpp>
    
    #include <utils/Demangle.hpp>
    
    #include <fstream>
    #include <iomanip>
    
    std::string
    GnuplotWriter1D::_getDateAndVersionComment() const
    {
      std::ostringstream os;
    
      std::time_t now = std::time(nullptr);
      os << "#  Generated by pugs: " << std::ctime(&now);
      os << "#  version: " << RevisionInfo::version() << '\n';
      os << "#  tag:  " << RevisionInfo::gitTag() << '\n';
      os << "#  HEAD: " << RevisionInfo::gitHead() << '\n';
      os << "#  hash: " << RevisionInfo::gitHash() << " (" << ((RevisionInfo::gitIsClean()) ? "clean" : "dirty") << ")\n";
      os << '\n';
    
      return os.str();
    }
    
    std::string
    GnuplotWriter1D::_getFilename() const
    {
      std::ostringstream sout;
      sout << m_base_filename;
      sout << '.' << std::setfill('0') << std::setw(4) << m_saved_times.size() << ".gnu";
      return sout.str();
    }
    
    template <typename DataType>
    bool
    GnuplotWriter1D::_is_cell_value(const CellValue<const DataType>&) const
    {
      return true;
    }
    
    template <typename DataType>
    bool
    GnuplotWriter1D::_is_cell_value(const NodeValue<const DataType>&) const
    {
      return false;
    }
    
    template <typename DataType>
    bool
    GnuplotWriter1D::_is_node_value(const CellValue<const DataType>&) const
    {
      return false;
    }
    
    template <typename DataType>
    bool
    GnuplotWriter1D::_is_node_value(const NodeValue<const DataType>&) const
    {
      return true;
    }
    
    template <size_t Dimension>
    void
    GnuplotWriter1D::_writePreamble(const OutputNamedItemValueSet& output_named_item_value_set, std::ostream& fout) const
    {
      fout << "# list of data\n";
      fout << "# 1:x";
      if constexpr (Dimension > 1) {
        fout << " 2:y";
      }
      uint64_t i = Dimension + 1;
      for (const auto& i_named_item_value : output_named_item_value_set) {
        const std::string name         = i_named_item_value.first;
        const auto& item_value_variant = i_named_item_value.second;
        std::visit(
          [&](auto&& item_value) {
            using ItemValueType = std::decay_t<decltype(item_value)>;
            using DataType      = std::decay_t<typename ItemValueType::data_type>;
            if constexpr (std::is_arithmetic_v<DataType>) {
              fout << ' ' << i++ << ':' << name;
            } else if constexpr (is_tiny_vector_v<DataType>) {
              for (size_t j = 0; j < DataType{}.dimension(); ++j) {
                fout << ' ' << i++ << ':' << name << '[' << j << ']';
              }
            } else if constexpr (is_tiny_matrix_v<DataType>) {
              for (size_t j = 0; j < DataType{}.nbRows(); ++j) {
                for (size_t k = 0; k < DataType{}.nbColumns(); ++k) {
                  fout << ' ' << i++ << ':' << name << '(' << j << ',' << k << ')';
                }
              }
            } else {
              throw UnexpectedError("invalid data type");
            }
          },
          item_value_variant);
      }
      fout << "\n\n";
    }
    
    template <typename DataType>
    void
    GnuplotWriter1D::_writeCellValue(const NodeValue<DataType>&, CellId, std::ostream&) const
    {}
    
    template <typename DataType>
    void
    GnuplotWriter1D::_writeCellValue(const CellValue<DataType>& cell_value, CellId cell_id, std::ostream& fout) const
    {
      const auto& value = cell_value[cell_id];
      if constexpr (std::is_arithmetic_v<DataType>) {
        fout << ' ' << value;
      } else if constexpr (is_tiny_vector_v<std::decay_t<DataType>>) {
        for (size_t i = 0; i < value.dimension(); ++i) {
          fout << ' ' << value[i];
        }
      } else if constexpr (is_tiny_matrix_v<std::decay_t<DataType>>) {
        for (size_t i = 0; i < value.nbRows(); ++i) {
          for (size_t j = 0; j < value.nbColumns(); ++j) {
            fout << ' ' << value(i, j);
          }
        }
      } else {
        throw UnexpectedError("invalid data type for cell value output: " + demangle<DataType>());
      }
    }
    
    template <typename MeshType>
    void
    GnuplotWriter1D::_writeCellValues(const std::shared_ptr<const MeshType>& mesh,
                                      const OutputNamedItemValueSet& output_named_item_value_set,
                                      std::ostream& fout) const
    {
      if constexpr (MeshType::Dimension == 1) {
        auto& mesh_data = MeshDataManager::instance().getMeshData(*mesh);
    
        const auto& cell_center = mesh_data.xj();
        for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) {
          fout << cell_center[cell_id][0];
          for (auto [name, item_value] : output_named_item_value_set) {
            std::visit([&](auto&& cell_value) { _writeCellValue(cell_value, cell_id, fout); }, item_value);
          }
          fout << '\n';
        }
      } else if constexpr (MeshType::Dimension == 2) {
        auto cell_to_node_matrix = mesh->connectivity().cellToNodeMatrix();
    
        for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) {
          std::ostringstream os;
          os.precision(15);
          os.setf(std::ios_base::scientific);
    
          for (auto [name, item_value] : output_named_item_value_set) {
            std::visit([&](auto&& cell_value) { _writeCellValue(cell_value, cell_id, os); }, item_value);
          }
    
          const auto& cell_nodes = cell_to_node_matrix[cell_id];
          for (size_t i_node = 0; i_node < cell_nodes.size(); ++i_node) {
            const NodeId& node_id   = cell_nodes[i_node];
            const TinyVector<2>& xr = mesh->xr()[node_id];
            fout << xr[0] << ' ' << xr[1] << ' ' << os.str() << '\n';
          }
          fout << '\n';
        }
      } else {
        throw UnexpectedError("invalid mesh dimension");
      }
    }
    
    template <typename ValueType>
    void
    GnuplotWriter1D::_writeNodeValue(const NodeValue<ValueType>& node_value, NodeId node_id, std::ostream& fout) const
    {
      const auto& value = node_value[node_id];
      if constexpr (std::is_arithmetic_v<ValueType>) {
        fout << ' ' << value;
      } else if constexpr (is_tiny_vector_v<std::decay_t<ValueType>>) {
        for (size_t i = 0; i < value.dimension(); ++i) {
          fout << ' ' << value[i];
        }
      } else if constexpr (is_tiny_matrix_v<std::decay_t<ValueType>>) {
        for (size_t i = 0; i < value.nbRows(); ++i) {
          for (size_t j = 0; j < value.nbColumns(); ++j) {
            fout << ' ' << value(i, j);
          }
        }
      } else {
        throw UnexpectedError("invalid data type for cell value output: " + demangle<ValueType>());
      }
    }
    
    template <typename ValueType>
    void
    GnuplotWriter1D::_writeNodeValue(const CellValue<ValueType>&, NodeId, std::ostream&) const
    {}
    
    template <typename MeshType>
    void
    GnuplotWriter1D::_writeNodeValues(const std::shared_ptr<const MeshType>& mesh,
                                      const OutputNamedItemValueSet& output_named_item_value_set,
                                      std::ostream& fout) const
    {
      if constexpr (MeshType::Dimension == 1) {
        const auto& xr = mesh->xr();
        for (NodeId node_id = 0; node_id < mesh->numberOfNodes(); ++node_id) {
          fout << xr[node_id][0];
          for (auto [name, item_value] : output_named_item_value_set) {
            std::visit([&](auto&& node_value) { _writeNodeValue(node_value, node_id, fout); }, item_value);
          }
          fout << '\n';
        }
      } else if constexpr (MeshType::Dimension == 2) {
        auto cell_to_node_matrix = mesh->connectivity().cellToNodeMatrix();
    
        for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) {
          std::ostringstream os;
          os.precision(15);
          os.setf(std::ios_base::scientific);
    
          const auto& cell_nodes = cell_to_node_matrix[cell_id];
          for (size_t i_node = 0; i_node < cell_nodes.size(); ++i_node) {
            const NodeId& node_id   = cell_nodes[i_node];
            const TinyVector<2>& xr = mesh->xr()[node_id];
            fout << xr[0] << ' ' << xr[1] << ' ' << os.str();
            for (auto [name, item_value] : output_named_item_value_set) {
              std::visit([&](auto&& node_value) { _writeNodeValue(node_value, node_id, os); }, item_value);
            }
            fout << '\n';
          }
          fout << '\n';
        }
      } else {
        throw UnexpectedError("invalid mesh dimension");
      }
    }
    
    template <typename MeshType>
    void
    GnuplotWriter1D::_write(const std::shared_ptr<const MeshType>& mesh,
                            const OutputNamedItemValueSet& output_named_item_value_set,
                            double time) const
    {
      bool has_cell_value = false;
      for (const auto& [name, item_value_variant] : output_named_item_value_set) {
        has_cell_value |=
          std::visit([&](auto&& item_value) { return this->_is_cell_value(item_value); }, item_value_variant);
      }
    
      bool has_node_value = false;
      for (const auto& [name, item_value_variant] : output_named_item_value_set) {
        has_node_value |=
          std::visit([&](auto&& item_value) { return this->_is_node_value(item_value); }, item_value_variant);
      }
    
      if (has_cell_value and has_node_value) {
        throw NormalError("cannot store both node and cell values in a gnuplot file");
      }
    
      std::ofstream fout(_getFilename());
      fout.precision(15);
      fout.setf(std::ios_base::scientific);
      fout << _getDateAndVersionComment();
    
      fout << "\n# time = " << time << "\n\n";
    
      _writePreamble<MeshType::Dimension>(output_named_item_value_set, fout);
    
      if (has_cell_value) {
        this->_writeCellValues(mesh, output_named_item_value_set, fout);
      } else {   // has_node_value
        this->_writeNodeValues(mesh, output_named_item_value_set, fout);
      }
    }
    
    void
    GnuplotWriter1D::writeMesh(const std::shared_ptr<const IMesh>&) const
    {
      throw UnexpectedError("This function should not be called");
    }
    
    void
    GnuplotWriter1D::write(const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list,
                           double time) const
    {
      std::shared_ptr mesh = this->_getMesh(named_discrete_function_list);
    
      OutputNamedItemValueSet output_named_item_value_set = this->_getOutputNamedItemValueSet(named_discrete_function_list);
    
      switch (mesh->dimension()) {
      case 1: {
        this->_write(std::dynamic_pointer_cast<const Mesh<Connectivity<1>>>(mesh), output_named_item_value_set, time);
        break;
      }
      case 2: {
        std::ostringstream errorMsg;
        errorMsg << "gnuplot_1d_writer is not available in dimension " << std::to_string(mesh->dimension()) << '\n'
                 << rang::style::bold << "note:" << rang::style::reset << " one can use " << rang::fgB::blue
                 << "gnuplot_writer" << rang::style::reset << " in dimension 2";
        throw NormalError(errorMsg.str());
      }
      default: {
        throw NormalError("gnuplot format is not available in dimension " + std::to_string(mesh->dimension()));
      }
      }
    }