Commit 3543e7ff authored by Lukas Riedel's avatar Lukas Riedel

Merge KnoFu interfaces into single class

Plotting flux data requires the parameters and scaling field of the
associated ensemble member. Therefore, the plotting interface must
implement the capabilities of a regular model. This commit merges the
KnoFuPlotter methods into the KnoFuInterface and removes the separate
plotter class.
parent c7a8abdf
......@@ -23,6 +23,7 @@
#include <dune/pdelab/backend/istl.hh>
#include <dune/pdelab/common/function.hh>
#include <dune/pdelab/common/vtkexport.hh>
#include <dune/pdelab/constraints/common/constraintstransformation.hh>
#include <dune/pdelab/gridfunctionspace/localfunctionspace.hh>
#include <dune/pdelab/gridfunctionspace/lfsindexcache.hh>
......@@ -93,6 +94,21 @@ protected:
/// Storage for initial state passed by the filter
std::shared_ptr<U> _u_initial;
/// --- Plotting Interface ---
/// VTK writer
Dune::SubsamplingVTKWriter<typename Traits::GV> _vtkwriter;
/// Type of the flux grid function
using GFFluxReconstruction = typename Traits::GFFluxReconstruction;
/// Type of the VTK function adapter based on the solution grid function
template<class GF>
using VTKFunction = Dune::PDELab::VTKGridFunctionAdapter<GF>;
/// State storage (name, solution, time)
std::vector<std::tuple<std::string,
std::shared_ptr<GFSolution>,
std::shared_ptr<const GFFluxReconstruction>>
> _member_storage;
public:
using Grid = typename Traits::Grid;
/// Type of the grid creator
......@@ -112,9 +128,12 @@ public:
Simulation(inifile, grid_creator, helper),
_solution_type(solution_type),
_wc(*this->gfs, 0.0),
_u_initial(std::make_shared<U>(*this->u))
_u_initial(std::make_shared<U>(*this->u)),
_vtkwriter(this->gv,
Dune::refinementLevels(
inifile.get<int>("output.subsamplingLevel")))
{
// always block all output
// always block output of the actual model
this->set_policy(OutputPolicy::None);
}
......@@ -463,6 +482,110 @@ public:
/// Default destructor
virtual ~KnoFuInterface () override = default;
// --- Plotting Interface ---
/// Add a solution to the VTK output.
/** Create a new backend vector based on GFS and the solution vector
* supplied.
* \param state State vector (water content)
* \param name Name of the state (i.e. member number)
* \param time The simulation time associated with this state
* (required for flux reconstruction)
*/
void add_solution_to_output (
const BackendVector& state,
const std::string& name,
const double time)
{
const auto state_copy = std::make_shared<U>(*this->gfs, 0.0);
Dune::PDELab::Backend::native(*state_copy) = state;
// store the solution grid function (water content OR matric head)
auto solution_gf = std::make_shared<GFSolution>(this->gfs,
state_copy);
const auto state_head = std::make_shared<U>(*this->gfs, 0.0);
if (this->_solution_type == FilterSolutionType::water_content)
{
// Transform water content into matric head
GFWaterContentToHead head_gf(this->inifile,
this->gv,
solution_gf,
this->fparam);
Dune::PDELab::interpolate(head_gf, *this->gfs, *state_head);
}
else {
*state_head = *state_copy;
}
// reconstruct the flux
typename Traits::State state_pack{this->gfs, state_head, time};
auto flux_gf = this->get_water_flux_reconstructed(state_pack);
_member_storage.push_back(std::make_tuple(name,
solution_gf,
flux_gf));
}
/// Release the data stored in this object
void clear_stored_states ()
{
// release data
_member_storage.clear();
// release data stored in the writer
_vtkwriter.clear();
}
/// Write all stored states into a .vtu file.
/** Create discrete grid functions and VTK functions from the saved
* states.
* \param path Path to write into
* \param name Filename to write
*/
void write_stored_states (
const std::string& path,
const std::string& name
)
{
const auto vertex_data
= this->inifile.template get<bool>("output.vertexData");
for(auto& member : _member_storage)
{
// fetch data from storage
const auto& state = std::get<std::shared_ptr<GFSolution>>(member);
const auto& name = std::get<std::string>(member);
// stack VTKFunctions into writer
using VTKF = VTKFunction<GFSolution>;
add_vtk_data(std::make_shared<VTKF>(state, name), vertex_data);
}
write_vtk_output(path, name);
}
/// Transform all stored states into fluxes and write these into a file
void write_stored_fluxes (
const std::string& path,
const std::string& name
)
{
for (auto& member : _member_storage)
{
// fetch data from storage
const auto& flux = std::get<std::shared_ptr<
const GFFluxReconstruction>>(member);
const auto& name = std::get<std::string>(member);
// stack VTKFunctions into writer
using VTKF = VTKFunction<GFFluxReconstruction>;
add_vtk_data(std::make_shared<VTKF>(flux, name), true);
}
write_vtk_output(path, name);
}
private:
template<typename VTKWriter>
......@@ -503,6 +626,28 @@ private:
vtkwriter.write(time);
vtkwriter.vtkWriter()->clear();
}
/// Write the data stored in the VTK writer
void write_vtk_output (const std::string& path,
const std::string& name,
const bool clear_writer=true)
{
_vtkwriter.pwrite(name, path, "", Dune::VTK::OutputType::base64);
if (clear_writer)
_vtkwriter.clear();
}
/// Add a VTK grid function to the
template<typename VTKGridFunction>
void add_vtk_data (const std::shared_ptr<VTKGridFunction> vtk_gf,
const bool vertex_data)
{
if (vertex_data)
_vtkwriter.addVertexData(vtk_gf);
else
_vtkwriter.addCellData(vtk_gf);
}
};
} // namespace Dorie
......
#ifndef DUNE_DORIE_RICHARDS_KNOFU_PLOTTING_HH
#define DUNE_DORIE_RICHARDS_KNOFU_PLOTTING_HH
#include <string>
#include <memory>
#include <vector>
#include <dune/common/exceptions.hh>
#include <dune/common/parametertree.hh>
#include <dune/common/parallel/mpihelper.hh>
#include <dune/grid/io/file/vtk/subsamplingvtkwriter.hh>
#include <dune/pdelab/backend/istl.hh>
#include <dune/pdelab/common/vtkexport.hh>
namespace Dune {
namespace Dorie {
/// Simulation used for plotting a state returned by KnoFu
template<typename Traits>
class KnoFuPlotter : public KnoFuInterface<Traits>
{
private:
/// Type of the base class
using Base = KnoFuInterface<Traits>;
/// Type of the DOF vector
using U = typename Base::U;
/// Type of the discrete grid function based on the solution vector
using GFSolution = typename Base::GFSolution;
/// Type of the flux grid function
using GFFluxReconstruction = typename Traits::GFFluxReconstruction;
/// Type of the VTK function adapter based on the solution grid function
template<class GF>
using VTKFunction = Dune::PDELab::VTKGridFunctionAdapter<GF>;
/// VTK writer
Dune::SubsamplingVTKWriter<typename Traits::GV> vtkwriter;
/// State storage (name, solution, time)
std::vector<std::tuple<std::string,
std::shared_ptr<U>,
double>> member_storage;
/// Output file encoding
const Dune::VTK::OutputType output_type;
public:
using GridCreator = typename Traits::GridCreator;
using BackendVector = typename Base::BackendVector;
/// Constructor. Set up Simulation base class and VTK writer
KnoFuPlotter (
Dune::ParameterTree& inifile,
const GridCreator& grid_creator,
Dune::MPIHelper& helper,
const FilterSolutionType solution_type)
:
KnoFuInterface<Traits>(inifile, grid_creator, helper, solution_type),
vtkwriter(this->gv, Dune::refinementLevels(
inifile.get<int>("output.subsamplingLevel"))),
output_type(Dune::VTK::OutputType::base64)
{ }
/// Default destructor
virtual ~KnoFuPlotter () override = default;
/// Add a solution to the VTK output.
/** Create a new backend vector based on GFS and the solution vector
* supplied.
* \param state State vector (water content)
* \param name Name of the state (i.e. member number)
* \param time The simulation time associated with this state
* (required for flux reconstruction)
*/
void add_solution_to_output (
const BackendVector& state,
const std::string& name,
const double time)
{
auto state_copy = std::make_shared<U>(*this->gfs, 0.0);
Dune::PDELab::Backend::native(*state_copy) = state;
member_storage.emplace_back(name, state_copy, time);
}
/// Release the data stored in this object
void clear ()
{
// release data
member_storage.clear();
}
/// Write all stored states into a .vtu file.
/** Create discrete grid functions and VTK functions from the saved
* states.
* \param path Path to write into
* \param name Filename to write
*/
void write_state (const std::string& path, const std::string& name)
{
const auto vertex_data
= this->inifile.template get<bool>("output.vertexData");
for(auto&& member : member_storage)
{
// fetch data from storage
const auto& state = std::get<std::shared_ptr<U>>(member);
const auto& name = std::get<std::string>(member);
// stack VTKFunctions into writer
auto solution = std::make_shared<GFSolution>(this->gfs,
state);
using VTKF = VTKFunction<GFSolution>;
add_vtk_data(std::make_shared<VTKF>(solution, name), vertex_data);
}
write_vtk_output(path, name);
}
/// Transform all stored states into fluxes and write these into a file
void write_flux (const std::string& path, const std::string& name)
{
for(auto&& member : member_storage)
{
// fetch data from storage
const auto& state = std::get<std::shared_ptr<U>>(member);
const auto& name = std::get<std::string>(member);
const auto& time = std::get<double>(member);
// copy the state
const auto state_head = std::make_shared<U>(*state);
// Transform water content into matric head
using GFWaterContentToHead = typename Base::GFWaterContentToHead;
if (this->_solution_type == FilterSolutionType::water_content)
{
const auto wc_solution = std::make_shared<GFSolution>(this->gfs,
state);
GFWaterContentToHead head_gf(this->inifile,
this->gv,
wc_solution,
this->fparam);
Dune::PDELab::interpolate(head_gf, *this->gfs, *state_head);
}
// reconstruct the flux
typename Traits::State state_pack{this->gfs, state_head, time};
auto dgf = this->get_water_flux_reconstructed(state_pack);
// stack VTKFunctions into writer
using VTKF = VTKFunction<GFFluxReconstruction>;
add_vtk_data(std::make_shared<VTKF>(dgf, name), true);
}
write_vtk_output(path, name);
}
private:
/// Write the data stored in the VTK writer
void write_vtk_output (const std::string& path,
const std::string& name,
const bool clear_writer=true)
{
vtkwriter.pwrite(name, path, "", output_type);
if (clear_writer)
vtkwriter.clear();
}
/// Add a VTK grid function to the
template<typename VTKGridFunction>
void add_vtk_data (const std::shared_ptr<VTKGridFunction> vtk_gf,
const bool vertex_data)
{
if (vertex_data)
vtkwriter.addVertexData(vtk_gf);
else
vtkwriter.addCellData(vtk_gf);
}
};
} // namespace Dorie
} // namespace Dune
#endif // DUNE_DORIE_RICHARDS_KNOFU_PLOTTING_HH
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment