From 14bafc428a5d1cd2d6f686ff2b825a2248d6d276 Mon Sep 17 00:00:00 2001 From: Thomas Fischer <thomas.fischer@ufz.de> Date: Thu, 18 Jul 2019 21:19:26 +0200 Subject: [PATCH] [Param] Impl. TimeDependentHeterogeneousParameter. --- .../TimeDependentHeterogeneousParameter.cpp | 149 ++++++++++++++++++ .../TimeDependentHeterogeneousParameter.h | 45 ++++++ 2 files changed, 194 insertions(+) create mode 100644 ParameterLib/TimeDependentHeterogeneousParameter.cpp create mode 100644 ParameterLib/TimeDependentHeterogeneousParameter.h diff --git a/ParameterLib/TimeDependentHeterogeneousParameter.cpp b/ParameterLib/TimeDependentHeterogeneousParameter.cpp new file mode 100644 index 00000000000..ecae53379e5 --- /dev/null +++ b/ParameterLib/TimeDependentHeterogeneousParameter.cpp @@ -0,0 +1,149 @@ +/** + * \copyright + * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + * + */ + +#include "TimeDependentHeterogeneousParameter.h" + +#include "BaseLib/ConfigTree.h" +#include "BaseLib/Error.h" +#include "Utils.h" + +namespace ParameterLib +{ +TimeDependentHeterogeneousParameter::TimeDependentHeterogeneousParameter( + std::string name, + std::vector<PairTimeParameterName> + time_parameter_name_mapping) + : Parameter<double>(std::move(name), nullptr), + _time_parameter_name_mapping(time_parameter_name_mapping) +{ +} + +int TimeDependentHeterogeneousParameter::getNumberOfComponents() const +{ + return _time_parameter_mapping[0].second->getNumberOfComponents(); +} + +bool TimeDependentHeterogeneousParameter::isTimeDependent() const +{ + return true; +} + +std::vector<double> TimeDependentHeterogeneousParameter::operator()( + double const t, SpatialPosition const& pos) const +{ + // No local coordinate transformation here, which might happen twice + // otherwise. + assert(!this->_coordinate_system || + "Coordinate system not expected to be set for curve scaled " + "parameters."); + if (t < _time_parameter_mapping[0].first) + { + return _time_parameter_mapping[0].second->operator()(t, pos); + } + if (_time_parameter_mapping.back().first <= t) + { + return _time_parameter_mapping.back().second->operator()(t, pos); + } + std::size_t k(1); + for (; k < _time_parameter_mapping.size(); ++k) + { + if (_time_parameter_mapping[k - 1].first <= t && + t < _time_parameter_mapping[k].first) + { + break; + } + } + auto const t0 = _time_parameter_mapping[k - 1].first; + auto const t1 = _time_parameter_mapping[k].first; + auto const alpha = (t - t0) / (t1 - t0); + + auto r0 = _time_parameter_mapping[k - 1].second->operator()(t, pos); + std::transform(r0.begin(), r0.end(), r0.begin(), + [alpha](auto& v) { return (1 - alpha) * v; }); + auto r1 = _time_parameter_mapping[k].second->operator()(t, pos); + std::transform(r1.begin(), r1.end(), r1.begin(), + [alpha](auto& v) { return alpha * v; }); + std::transform(r0.begin(), r0.end(), r1.begin(), r0.begin(), + [](auto& v0, auto const& v1) { return v0 + v1; }); + return r0; +} + +void TimeDependentHeterogeneousParameter::initialize( + std::vector<std::unique_ptr<ParameterBase>> const& parameters) +{ + DBUG("TimeDependentHeterogeneousParameter init %d time series entries.", + _time_parameter_name_mapping.size()); + for (auto const& time_parameter_map : _time_parameter_name_mapping) + { + auto parameter = + &findParameter<double>(time_parameter_map.second, parameters, 0); + _time_parameter_mapping.emplace_back(time_parameter_map.first, + parameter); + } + + // check that all parameters have the same number of components + auto const n = _time_parameter_mapping[0].second->getNumberOfComponents(); + if (!std::all_of(_time_parameter_mapping.begin(), + _time_parameter_mapping.end(), + [n](auto const p) { + return n == p.second->getNumberOfComponents(); + })) + { + OGS_FATAL( + "All referenced parameters in time dependent heterogeneous " + "parameter '%s' have to have the same number of components.", + name.c_str()); + } +} + +std::unique_ptr<ParameterBase> createTimeDependentHeterogeneousParameter( + std::string const& name, BaseLib::ConfigTree const& config) +{ + //! \ogs_file_param{prj__parameters__parameter__type} + config.checkConfigParameter("type", "TimeDependentHeterogeneousParameter"); + auto const time_series_config = + //! //\ogs_file_param{prj__parameters__parameter__TimeDependentHeterogeneousParameter__time_serie} + config.getConfigSubtree("time_series"); + + std::vector<TimeDependentHeterogeneousParameter::PairTimeParameterName> + time_series; + for (auto const p : time_series_config.getConfigSubtreeList("pair")) + { + auto time = p.getConfigParameter<double>("time"); + auto parameter_name = + p.getConfigParameter<std::string>("parameter_name"); + time_series.emplace_back(time, parameter_name); + } + + if (time_series.empty()) + { + OGS_FATAL( + "Time dependent heterogeneous parameter '%s' doesn't contain " + "necessary time series data.", + name.c_str()); + } + + if (!std::is_sorted( + time_series.begin(), time_series.end(), + [](TimeDependentHeterogeneousParameter::PairTimeParameterName const& + p0, + TimeDependentHeterogeneousParameter::PairTimeParameterName const& + p1) { return p0.first < p1.first; })) + { + OGS_FATAL( + "The points in time in the time series '%s' aren't in ascending " + "order.", + name.c_str()); + } + + return std::make_unique<TimeDependentHeterogeneousParameter>( + name, std::move(time_series)); +} + +} // namespace ParameterLib diff --git a/ParameterLib/TimeDependentHeterogeneousParameter.h b/ParameterLib/TimeDependentHeterogeneousParameter.h new file mode 100644 index 00000000000..270caed94b8 --- /dev/null +++ b/ParameterLib/TimeDependentHeterogeneousParameter.h @@ -0,0 +1,45 @@ +/** + * \copyright + * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + * + */ + +#pragma once + +#include <algorithm> + +#include "Parameter.h" + +namespace ParameterLib +{ +class TimeDependentHeterogeneousParameter final : public Parameter<double> +{ +public: + using PairTimeParameterName = std::pair<double, std::string>; + using PairTimeParameter = std::pair<double, Parameter<double> const* const>; + + TimeDependentHeterogeneousParameter(std::string name, + std::vector<PairTimeParameterName> + time_parameter_name_mapping); + + int getNumberOfComponents() const override; + + bool isTimeDependent() const override; + + std::vector<double> operator()(double const t, + SpatialPosition const& pos) const override; + + void initialize( + std::vector<std::unique_ptr<ParameterBase>> const& parameters) override; + +private: + std::vector<PairTimeParameterName> _time_parameter_name_mapping; + std::vector<PairTimeParameter> _time_parameter_mapping; +}; + +std::unique_ptr<ParameterBase> createTimeDependentHeterogeneousParameter( + std::string const& name, BaseLib::ConfigTree const& config); +} // namespace ParameterLib -- GitLab