The TS-GitLab will have to shut down towards the end of the year — please think about migrating your projects to GitLab.com or GitHub.
(This is still a very early message, meant to keep you informed. There will be more urgent ones in the future.)

Commit 940254dd authored by Lukas Riedel's avatar Lukas Riedel

Restructure parameterization source files and remove deprecated ones

* Delete old parameterization, factory, and parameterization base class
* Delete FlowParameters method for copying parameters from the old
    parameterization instances
* Rename 'param_interface.hh' to 'richards_param.hh', to comply to
    other source files directly related to the local operator.
* Rename 'param_richards.hh' to 'param_interface.hh'.
parent e3743fea
......@@ -17,7 +17,7 @@
#include "util.hh"
#include "adaptivity.hh"
#include "../solver/util_interpolator.hh"
#include "../solver/param_interface.hh"
#include "../solver/richards_param.hh"
#include "../solver/richards_initial.hh"
#include "../solver/richards_boundary.hh"
#include "../solver/richards_source.hh"
......
#ifndef DUNE_DORIE_CONDUCTIVITY_ADAPTER_HH
#define DUNE_DORIE_CONDUCTIVITY_ADAPTER_HH
#include "../param_richards.hh"
namespace Dune{
namespace Dorie{
......
// -*- tab-width: 4; indent-tabs-mode: nil -*-
#ifndef DUNE_DORIE_PARAMETERS_BASE_HH
#define DUNE_DORIE_PARAMETERS_BASE_HH
#include <string>
#include <cmath>
#include <dune/common/exceptions.hh>
#include <dune/common/parametertree.hh>
#include <dune/common/parallel/mpihelper.hh>
#include "util_h5tools.hh"
namespace Dune {
namespace Dorie {
/// Simple class providing a data structure for storing parameters
template<typename T>
class Parameter
{
private:
typedef typename T::RangeField RF;
typedef typename T::Array Array;
const RF min, max;
Array values;
const bool check_bounds;
bool initialized;
public:
const std::string name; //!< Name of the parameter
Parameter(const std::string name_, const RF min_, const RF max_)
: min(min_), max(max_), check_bounds(true), initialized(false), name(name_)
{}
Parameter(const std::string name_)
: min(0), max(0), check_bounds(false), initialized(false), name(name_)
{}
void set_values(const Array values_)
{
values = values_;
if (check_bounds) {
for (std::size_t i = 0; i < values.size(); i++){
const auto& v = values[i];
if ((v < min) || (v > max))
{
DUNE_THROW(Dune::IOError, "Invalid parameter value encontered for"
<< " parameter " << name << " at (" << i << "): " << v
<< " (must be between "<< min << " and "<< max <<")");
}
}
}
initialized = true;
}
const Array& get_values() const
{
if(!initialized)
DUNE_THROW(Exception,"Parameter must be initialized before accessing it");
return values;
}
};
/// Base class for all parameterizations
template<typename T, class Interpolator>
class ParameterizationBase
{
private:
enum {dim = T::dim};
typedef typename T::RangeField RF;
typedef typename T::Vector Vector;
typedef typename T::Domain Domain;
typedef typename T::Element Element;
typedef typename T::Array Array;
typedef typename T::Index Index;
typedef std::vector<Parameter<T>*> ParameterArray;
protected:
const ParameterTree& config; //!< ini file parser
const std::string parName; //!< Identifier of the parameterization (main group name in H5 file)
public:
ParameterArray& parameters; //!< Array containing all defined parameters
protected:
const Dune::MPIHelper& helper; //!< MPI helper
Interpolator& interpolator; //!< Interpolation handler instance
H5File& h5file; //!< HDF5 interface
const int verbose; //!< verbosity level
const Domain pf_extensions; //!< Extensions of the parameter field
public:
const bool millerSimilarity; //!< Switches miller similarity on or off
const RF variance; //!< Random field variance, needed for Miller Similarity
protected:
const Domain grid_extensions; //!< Spatial extensions of the model grid
const Domain scale; //!< Scaling factor of the random field
const Domain offset; //!< Position of the origin of the random field
public:
Parameter<T> millerField; //!< Random field used for Miller similarity
protected:
Vector gVector; //!< Unit length vector pointing towards gravitational force
Domain fieldCells; //!< Random field extensions in cells
bool array_open;
public:
explicit ParameterizationBase(const ParameterTree& config_, const std::string parName_,
ParameterArray& parameters_, const Dune::MPIHelper& helper_,
Interpolator& interpolator_, H5File& h5file_,
const int verbose_)
: config(config_), parName(parName_), parameters(parameters_), helper(helper_)
, interpolator(interpolator_), h5file(h5file_), verbose(verbose_)
, pf_extensions(h5file.read_attribute<Domain>("extensions","parameters"))
, millerSimilarity(h5file.read_attribute<bool>("millerSimilarity","parameters"))
, variance(h5file.read_attribute<RF>("variance","parameters"))
, grid_extensions(config.get<Domain>("grid.extensions"))
, scale(config.get<Domain>("parameters.scale"))
, offset(config.get<Domain>("parameters.offset"))
, millerField("raw_field")
{
gVector=0;
gVector[dim-1]=-1.;
for(Index i=0; i<dim; i++)
{
if(pf_extensions[i]*scale[i] - offset[i] < grid_extensions[i])
DUNE_THROW(IOError,"Random field extensions are smaller than model grid extensions");
}
}
virtual ~ParameterizationBase () = default;
/// Iterate through parameter array and read each one from the H5 file
void read_parameters()
{
open_array("parameters/" + parName);
read_parameter(millerField);
for (auto &p: parameters)
{
Domain fieldCells_old = fieldCells;
read_parameter(*p);
if (fieldCells_old != fieldCells) // consistency check
DUNE_THROW(Exception,"Varying array sizes encountered in random field array");
}
close_array();
Domain scaled_extensions;
for(typename Domain::size_type i=0; i<dim; i++)
scaled_extensions[i] = pf_extensions[i] * scale[i];
interpolator.initialize(fieldCells, scaled_extensions);
}
// Purely virtual functions queried by the DG operator
virtual RF saturation(const RF& h, const Domain& pos) const =0;
virtual RF waterContent(const RF& h, const Domain& pos) const =0;
virtual RF condFactor(const RF& h, const Domain& pos) const =0;
virtual RF K(const Domain& pos) const =0;
virtual RF matricHead(const RF waterContent, const Domain& pos) const = 0;
/******************************************
* MILLER SIMILARITY QUERIES
* According to Miller and Roth
******************************************/
/// Transformation: Head: Reference to Miller similar (if activated)
/** \f[ h^* = h \exp\left( - (v - \text{Var}(v))\right) \f]
* with the raw random field value \f$v\f$ and its variance.
* \param h Matric head
* \param pos Position in global coordinates
* \return Transformed value
*/
RF headRefToMiller (const RF& h, const Domain& pos) const
{
if (!millerSimilarity)
return h;
return h * exp(-(interpolate(millerField, pos)-variance));
}
/// Transformation: Head: Miller similar to Reference (if activated)
/** \see headRefToMiller
*/
RF headMillerToRef (const RF& h, const Domain& pos) const
{
if (!millerSimilarity)
return h;
return h * exp(interpolate(millerField, pos)-variance);
}
/// Transformation: Conductivity: Reference to Miller similar (if activated)
/** \f[ K^* = K \exp\left( 2 (v - \text{Var}(v))\right) \f]
* with the raw random field value \f$v\f$ and its variance.
* \param h Matric head
* \param pos Position in global coordinates
* \return Transformed value
*/
RF condRefToMiller (const RF& K, const Domain& pos) const
{
if (!millerSimilarity)
return K;
return K * exp (2.0*(interpolate(millerField, pos)-variance));
}
/// Transformation: Conductivity: Miller similar to Reference (if activated)
/** \see condRefToMiller
*/
RF condMillerToRef (const RF& k, const Domain& pos) const
{
if (!millerSimilarity)
return k;
return k * exp (-2.0*(interpolate(millerField, pos)-variance));
}
/// Return gravity vector
const Vector& gravity() const
{
return gVector;
}
public:
/******************************************
* UTILITY FUNCTIONS
******************************************/
/// Thin wrapper around the interpolator evaluation function
RF interpolate(const Parameter<T>& par, const Domain& pos) const
{
return interpolator.evaluate(par.get_values(),pos + offset);
}
protected:
/// Opens H5 array for reading
void open_array(std::string groupName)
{
h5file.open(groupName);
array_open = true;
}
/// Reads parameter array for Parameter p from H5 file
void read_parameter(Parameter<T>& p)
{
if (!array_open)
DUNE_THROW(Exception,"Array file must be opened before reading a parameter");
Array fieldArray;
h5file.read_dataset(fieldArray, fieldCells, p.name);
p.set_values(fieldArray);
}
/// Closes H5 file
void close_array()
{
if (!array_open)
DUNE_THROW(Exception,"Array file already closed");
h5file.close();
array_open = false;
}
};
}
}
#endif // DUNE_DORIE_PARAMETERS_BASE_HH
// -*- tab-width: 4; indent-tabs-mode: nil -*-
#ifndef DUNE_DORIE_PARAMETERS_FACTORY_HH
#define DUNE_DORIE_PARAMETERS_FACTORY_HH
#include <string>
#include <memory>
#include <dune/common/exceptions.hh>
#include <dune/common/parametertree.hh>
#include <dune/common/parallel/mpihelper.hh>
#include "param_van_genuchten.hh"
namespace Dune {
namespace Dorie {
/// Factory class for a generic parameterization (base class of ParameterizationBase)
template<typename T, class Interpolator>
class ParameterizationFactory
{
protected:
const ParameterTree& config;
const Dune::MPIHelper& helper;
Interpolator& interpolator;
const int verbose;
const std::string arrayPath;
const std::string interpMethod;
H5File h5array;
std::string parType;
public:
explicit ParameterizationFactory(const ParameterTree& config_,
const Dune::MPIHelper& helper_,
Interpolator& interpolator_,
const int verbose_)
: config(config_), helper(helper_), interpolator(interpolator_), verbose(verbose_)
, arrayPath(config.get<std::string>("parameters.arrayFile"))
, interpMethod(config.get<std::string>("parameters.interpolation"))
, h5array(arrayPath,verbose)
, parType(h5array.read_attribute<std::string>("parameterization","parameters"))
{}
std::unique_ptr<ParameterizationBase<T, Interpolator>> create()
{
std::unique_ptr<ParameterizationBase<T, Interpolator>> param;
if(parType == "vanGenuchten")
param = std::make_unique<MualemVanGenuchten<T, Interpolator>>(config, helper, interpolator, h5array, verbose);
else
DUNE_THROW(Dune::IOError,"Unrecognized parameterization type encountered in array file: " + parType);
return param;
}
};
}
}
#endif
#ifndef DUNE_DORIE_PARAM_INTERFACE_HH
#define DUNE_DORIE_PARAM_INTERFACE_HH
#ifndef DUNE_DORIE_PARAM_RICHARDS_HH
#define DUNE_DORIE_PARAM_RICHARDS_HH
#include <cmath>
#include <vector>
#include <map>
#include <utility>
#include <functional>
#include <memory>
#include <yaml-cpp/yaml.h>
#include <dune/common/exceptions.hh>
#include <dune/grid/common/mcmgmapper.hh>
#include <dune/dorie/solver/param_richards.hh>
#include <dune/dorie/solver/param_mvg.hh>
#include <string>
#include <map>
namespace Dune {
namespace Dorie {
/// Top-level parameterization interface.
/** This class stores the parameters, maps them to grid entities, and provides
* functions to access the parameterization. For doing so, the
* FlowParameters::bind function has to be called first to cache the
* parameters of the given grid entity. Parameters are only stored for entities
* of codim 0.
*
* \detail The parameterization consists of three structures:
* - This top-level class serves as interface and storage. It also casts to
* data types used by the DUNE operators
* - The Dorie::RichardsParameterization interface that provides strong
* data types for the base parameters and purely virtual functions that
* need to be defined by derived parameterizations
* - The actual parameterization defining all parameters and functions
*/
/// Class defining the interface for parameterizations of Richards equation
template <typename Traits>
class FlowParameters
class RichardsParameterization
{
private:
using RF = typename Traits::RF;
using Grid = typename Traits::Grid;
using LevelGridView = typename Grid::LevelGridView;
using Mapper = typename Dune::MultipleCodimMultipleGeomTypeMapper<
LevelGridView
>;
using Vector = typename Traits::Vector;
// Define the storage and cache for parameterizations and scaling
/// Index type used by the element mapper
using Index = typename Mapper::Index;
/// Base class of the parameterization
using Parameterization = Dorie::RichardsParameterization<Traits>;
using ScalingType = typename Parameterization::Scaling::Type;
using ScalingFactor = typename Parameterization::ScalingFactor;
/// Storage for parameters and skaling factors
using ParameterStorage = std::vector<
std::tuple<std::shared_ptr<Parameterization>,
ScalingType,
ScalingFactor
>
>;
/// Need this gruesome typedef because 'map::value_type' has const key
using Cache = typename ParameterStorage::value_type;
/// Configuration file tree
const Dune::ParameterTree& _config;
/// Grid view of the coarsest grid configuration (level 0)
const LevelGridView _gv;
/// Mapper for mapping grid elements to indices
Mapper _mapper;
/// Map for storing parameterization information for each grid entity
ParameterStorage _param;
/// Currently cached parameterization (bound to element)
mutable Cache _cache;
/// Gravity vector
Vector _gravity;
private:
/// Check if an entity has been cached
void verify_cache () const
{
if (not std::get<std::shared_ptr<Parameterization>>(_cache)) {
DUNE_THROW(Dune::Exception, "No parameterization cached. "
<< "Call 'bind' before accessing the parameterization.");
}
}
public:
/// Constructor.
/** Create a level grid view of level 0, create a mapper on it, and store
* the config tree.
* \param config Configuration file tree
* \param grid Shared pointer to the grid
* \param element_index_map The mapping from grid entity index to
* parameterization index.
*/
FlowParameters (
const Dune::ParameterTree& config,
const std::shared_ptr<Grid> grid,
const std::vector<int>& element_index_map
):
_config(config),
_gv(grid->levelGridView(0)),
_mapper(_gv, Dune::mcmgElementLayout()),
_gravity(0.0)
{
_gravity[Traits::dim - 1] = -1.0;
build_parameterization(element_index_map);
}
/// Return normalized gravity vector
const Vector& gravity() const { return _gravity; }
/// Return the current cache
const Cache& cache() const
// These are standard types for all parameterizations of Richards Equation
/// Type of water saturation
struct Saturation
{
verify_cache();
return _cache;
}
/// Bind to a grid entity. Required to call parameterization functions!
/** \param entity Grid entity (codim 0) to bind to
*/
template <class Entity>
void bind (Entity entity) const
{
// retrieve index of top father element of chosen entity
while(entity.hasFather()) {
entity = entity.father();
}
const auto index = _mapper.index(entity);
_cache = _param.at(index);
}
/// Return a scaled version of the Conductivity function
/** Uses the function of the underlying parameterization and applies
* scaling as specified by SkalingType. Cast to operator-internal RF.
* \return Function: Saturation -> Conductivity
*/
std::function<RF(RF)> conductivity_f () const
{
verify_cache();
const auto& par =
std::get<std::shared_ptr<Parameterization>>(_cache);
const auto& type = std::get<ScalingType>(_cache);
const auto cond_f = par->conductivity_f();
using Saturation = typename Parameterization::Saturation;
if (type == ScalingType::Miller) {
auto& scale = std::get<ScalingFactor>(_cache).value;
return [cond_f, &scale](const RF saturation){
return cond_f(Saturation{saturation}).value * scale * scale;
RF value;
};
}
return [cond_f](const RF saturation){
return cond_f(Saturation{saturation}).value;
/// Type of volumetric water content
struct WaterContent
{
RF value;
};
}
/// Return a scaled version of the Saturation function
/** Uses the function of the underlying parameterization and applies
* scaling as specified by SkalingType. Cast to operator-internal RF.
* \return Function: Matric Head -> Saturation
*/
std::function<RF(RF)> saturation_f () const
/// Type of hydraulic conductivity
struct Conductivity
{
verify_cache();
const auto& par =
std::get<std::shared_ptr<Parameterization>>(_cache);
const auto& type = std::get<ScalingType>(_cache);
const auto sat_f = par->saturation_f();
using MatricHead = typename Parameterization::MatricHead;
if (type == ScalingType::Miller) {
const auto& scale = std::get<ScalingFactor>(_cache).value;
return [sat_f, &scale](const RF matric_head){
return sat_f(MatricHead{matric_head * scale}).value;
RF value;
};
}
return [sat_f](const RF matric_head){
return sat_f(MatricHead{matric_head}).value;
/// Type of matric head
struct MatricHead
{
RF value;
};
}
/// Return a scaled version of the Water Content function
/** Uses the function of the underlying parameterization and applies
* scaling as specified by SkalingType. Cast to operator-internal RF.
* \return Function: Saturation -> Water Content
*/
std::function<RF(RF)> water_content_f () const
/// Generic scaling factor
struct ScalingFactor
{
verify_cache();
const auto& par =
std::get<std::shared_ptr<Parameterization>>(_cache);
const auto wc_f = par->water_content_f();
using Saturation = typename Parameterization::Saturation;
return [wc_f](const RF saturation) {
return wc_f(Saturation{saturation}).value;
RF value;
};
}
/// Copy parameters from the 'old' parameterization implementation
/** \todo Remove once new interface is established
* \param p_base Old parameterization base class
*/
template <class Param>
void copy_from_old_parameters (const Param& p_base)
/// Define scaling types for parameterization
struct Scaling
{
// iterate over grid elements
for (auto&& entity: elements(_gv))
enum Type
{
const auto pos = entity.geometry().center();
auto get_param_value = [&p_base, &pos](auto param) {
return p_base.interpolate(*param, pos);
Miller, //!< Geometric similarity
Warrick,
None //!< No scaling applied
};
};
std::vector<RF> p_values;
std::transform(p_base.parameters.begin(), p_base.parameters.end(),
std::back_inserter(p_values),
get_param_value
);