Commit 446dd263 authored by Müller, Felix's avatar Müller, Felix

Merge branch 'develop' into issue/gridtransfer_basis_update

parents 2de3ebf3 42a8634f
......@@ -80,7 +80,8 @@ namespace AMDiS
static GridTransferInterface* gridTransferInterface(Grid const &grid)
{
Key key = Key(&grid);
auto& gridTransferInterfaceUniquePtr = GridTransferCache::get(key, [&](Key const&)
GridTransferCache cache;
auto& gridTransferInterfaceUniquePtr = cache.get(key, [&](Key const&)
{
return std::make_unique<GridTransfer<Grid>>();
});
......
......@@ -28,23 +28,21 @@ namespace AMDiS
using SystemVector = typename ProblemType::SystemVector;
public:
/// Constructs a ProblemInstat with prob as its stationary problem.
/// Constructs a ProblemInstat with prob as its stationary problem, stored as reference.
ProblemInstat(std::string const& name, ProblemType& prob)
: ProblemInstatBase(name, nullptr)
, problemStat_(prob)
: ProblemInstatBase(name)
, problemStat_(&prob)
{}
/// Constructor. Stores a reference to prob and initialProb.
ProblemInstat(std::string const& name, ProblemType& prob, ProblemStatBase& initialProb)
: ProblemInstatBase(name, &initialProb)
, problemStat_(prob)
: ProblemInstatBase(name, initialProb)
, problemStat_(&prob)
{}
/// Initialisation of the problem.
virtual void initialize(Flag initFlag = INIT_NOTHING);
/// Used in \ref initialize().
virtual void createUhOld();
/// Implementation of \ref ProblemTimeInterface::initTimestep().
virtual void initTimestep(AdaptInfo& adaptInfo) override;
......@@ -52,8 +50,8 @@ namespace AMDiS
virtual void closeTimestep(AdaptInfo& adaptInfo) override;
/// Returns \ref problemStat.
ProblemType& problemStat() { return problemStat_; }
ProblemType const& problemStat() const { return problemStat_; }
ProblemType& problemStat() { return *problemStat_; }
ProblemType const& problemStat() const { return *problemStat_; }
/// Returns \ref oldSolution.
SystemVector const& oldSolutionVector() const
......@@ -83,8 +81,12 @@ namespace AMDiS
virtual void transferInitialSolution(AdaptInfo& adaptInfo) override;
protected:
/// Space problem solved in each timestep.
ProblemType& problemStat_;
/// Used in \ref initialize() to create the \ref oldSolution_.
void createUhOld();
protected:
/// Space problem solved in each timestep. (non-owning pointer)
ProblemType* problemStat_;
/// Solution of the last timestep.
std::unique_ptr<SystemVector> oldSolution_;
......@@ -96,6 +98,10 @@ namespace AMDiS
template <class Traits>
ProblemInstat(std::string const& name, ProblemStat<Traits>& prob)
-> ProblemInstat<Traits>;
template <class Traits>
ProblemInstat(std::string const& name, ProblemStat<Traits>& prob, ProblemStatBase& initialProb)
-> ProblemInstat<Traits>;
#endif
// Generator for ProblemInstat with given ProblemStat
......@@ -105,6 +111,13 @@ namespace AMDiS
return {name, prob};
}
// Generator for ProblemInstat with given ProblemStat and initialization problem
template <class Traits>
ProblemInstat<Traits> makeProblemInstat(std::string const& name, ProblemStat<Traits>& prob, ProblemStatBase& initialProb)
{
return {name, prob, initialProb};
}
} // end namespace AMDiS
#include "ProblemInstat.inc.hpp"
......@@ -16,7 +16,7 @@ void ProblemInstat<Traits>::transferInitialSolution(AdaptInfo& adaptInfo)
test_exit(adaptInfo.time() == adaptInfo.startTime(),
"after initial solution: time != start time");
problemStat_.writeFiles(adaptInfo, true);
problemStat_->writeFiles(adaptInfo, true);
}
......@@ -24,7 +24,7 @@ template <class Traits>
void ProblemInstat<Traits>::closeTimestep(AdaptInfo& adaptInfo)
{
bool force = (adaptInfo.time() >= adaptInfo.endTime());
problemStat_.writeFiles(adaptInfo, force);
problemStat_->writeFiles(adaptInfo, force);
}
......@@ -45,7 +45,7 @@ void ProblemInstat<Traits>::createUhOld()
if (oldSolution_)
warning("oldSolution already created\n");
else // create oldSolution
oldSolution_.reset(new SystemVector(problemStat_.globalBasis()));
oldSolution_.reset(new SystemVector(problemStat_->globalBasis()));
}
......@@ -53,7 +53,7 @@ template <class Traits>
void ProblemInstat<Traits>::initTimestep(AdaptInfo&)
{
if (oldSolution_)
*oldSolution_ = problemStat_.solutionVector();
*oldSolution_ = problemStat_->solutionVector();
}
} // end namespace AMDiS
......@@ -2,6 +2,7 @@
#include "AdaptInfo.hpp"
#include "AdaptStationary.hpp"
#include "ProblemStatBase.hpp"
#include "StandardProblemIteration.hpp"
namespace AMDiS {
......@@ -16,10 +17,11 @@ void ProblemInstatBase::setTime(AdaptInfo& adaptInfo)
void ProblemInstatBase::solveInitialProblem(AdaptInfo& adaptInfo)
{
StandardProblemIteration iteration(*initialProblem_);
AdaptStationary initialAdapt(name_ + "->initial->adapt", iteration, adaptInfo);
initialAdapt.adapt();
if (initialProblem_) {
StandardProblemIteration iteration(*initialProblem_);
AdaptStationary initialAdapt(name_ + "->initial->adapt", iteration, adaptInfo);
initialAdapt.adapt();
}
}
} // end namespace AMDiS
#pragma once
#include "ProblemStatBase.hpp"
#include <string>
#include "ProblemTimeInterface.hpp"
namespace AMDiS
{
// forward declarations
class AdaptInfo;
class ProblemStatBase;
/**
* \ingroup Problem
......@@ -16,14 +18,18 @@ namespace AMDiS
*/
class ProblemInstatBase
: public ProblemTimeInterface
, public ProblemStatBase // NOTE: Why is this derived from ProblemStatBase
{
public:
/// Constructor.
ProblemInstatBase(std::string const& name)
: name_(name)
{}
/// Constructor. Stores a pointer to the provided initialProblem.
ProblemInstatBase(std::string const& name,
ProblemStatBase* initialProb)
ProblemStatBase& initialProblem)
: name_(name)
, initialProblem_(initialProb ? initialProb : this)
, initialProblem_(&initialProblem)
{}
/// Destructor.
......@@ -32,78 +38,50 @@ namespace AMDiS
/// Implementation of \ref ProblemTimeInterface::setTime().
virtual void setTime(AdaptInfo& adaptInfo) override;
void solve(AdaptInfo&) { /* do nothing */ }
/// Implementation of \ref ProblemStatBase::solve().
virtual void solve(AdaptInfo& adaptInfo, bool, bool) override
{
solve(adaptInfo);
}
/// Implementation of \ref ProblemStatBase::estimate().
virtual void estimate(AdaptInfo&) override { /* do nothing */ }
/// Implementation of \ref ProblemStatBase::buildAfterAdapt().
virtual void buildAfterAdapt(AdaptInfo&, Flag, bool, bool) override { /* do nothing */ }
/// Implementation of \ref ProblemStatBase::markElements().
virtual Flag markElements(AdaptInfo&) override
{
return 0;
}
/// Implementation of \ref ProblemStatBase::refineMesh().
virtual Flag adaptGrid(AdaptInfo&) override
{
return 0;
}
/// Implementation of \ref ProblemTimeInterface::closeTimestep().
virtual void closeTimestep(AdaptInfo&) override { /* do nothing */ }
/// Implementation of \ref ProblemTimeInterface::solveInitialProblem().
virtual void solveInitialProblem(AdaptInfo& adaptInfo) override;
/// Implementation of \ref ProblemStatBase::name().
virtual std::string const& name() const override
/// Return the name of the instationary problem \ref name_
virtual std::string const& name() const
{
return name_;
}
/// Implementation of \ref ProblemTimeInterface::solveInitialProblem().
virtual void solveInitialProblem(AdaptInfo& adaptInfo) override;
/// Return reference to current simulation time \ref time_ set in \ref setTime
/// from `adaptInfo->getTime()`.
/// from `AdaptInfo::time()`.
double const& time() const
{
return time_;
}
/// Return reference to current simulation timestep \ref tau_ set in \ref setTime
/// from `adaptInfo->getTimestep()`.
/// from `AdaptInfo::timestep()`.
double const& tau() const&
{
return tau_;
}
/// Return reference to current simulation 1.0/timestep \ref invTau_ set in
/// \ref setTime from `1.0 / adaptInfo->getTimestep()`.
/// \ref setTime from `1.0 / AdaptInfo::timestep()`.
double const& invTau() const
{
return invTau_;
}
protected:
/// Name of the problem.
/// Name of the instationary problem.
std::string name_;
ProblemStatBase* initialProblem_;
/// An initialization problem solved in \ref solveInitialProblem(). non-owning pointer.
ProblemStatBase* initialProblem_ = nullptr;
/// Time
/// The current time, set from adaptInfo.time()
double time_ = 0.0;
/// Timestep
/// Timestep, set from adaptInfo.timestep()
double tau_ = 1.0;
/// 1 / timestep
/// 1 / timestep, calculated after timestep is set
double invTau_ = 1.0;
};
......
......@@ -429,6 +429,11 @@ namespace AMDiS
/// Implementation of \ref ProblemStatBase::markElements.
virtual Flag markElements(AdaptInfo& adaptInfo) override;
/// Uniform global grid coarsening by up to n level
virtual Flag globalCoarsen(int n) override;
/// Uniform global refinement by n level
virtual Flag globalRefine(int n) override;
private:
/// Name of this problem.
......
......@@ -354,6 +354,57 @@ markElements(AdaptInfo& adaptInfo)
}
template <class Traits>
Flag ProblemStat<Traits>::
globalCoarsen(int n)
{
Dune::Timer t;
bool adapted = false;
for (int i = 0; i < n; ++i) {
// mark all entities for grid refinement
for (const auto& element : elements(grid_->leafGridView()))
grid_->mark(-1, element);
adapted |= GridTransferManager::adapt(*grid_);
globalBasis_->update(gridView());
}
msg("globalCoarsen needed {} seconds", t.elapsed());
return adapted ? MESH_ADAPTED : Flag(0);
}
// grid has globalRefine(int, AdaptDataHandleInterface&)
template <class G>
using HasGlobalRefineADHI = decltype(std::declval<G>().globalRefine(1,std::declval<GridTransfer<G>&>()));
template <class Traits>
Flag ProblemStat<Traits>::
globalRefine(int refCount)
{
Dune::Timer t;
bool adapted = false;
Dune::Hybrid::ifElse(Dune::Std::is_detected<HasGlobalRefineADHI, Grid>{},
/*then*/ [&](auto id) {
id(grid_)->globalRefine(refCount, GridTransferManager::gridTransfer(*grid_));
globalBasis_->update(this->gridView());
},
/*else*/ [&](auto id) {
for (int i = 0; i < refCount; ++i) {
// mark all entities for grid refinement
for (const auto& element : elements(grid_->leafGridView()))
grid_->mark(1, element);
adapted |= GridTransferManager::adapt(*id(grid_));
globalBasis_->update(this->gridView());
}
});
msg("globalRefine needed {} seconds", t.elapsed());
return adapted ? MESH_ADAPTED : Flag(0);
}
template <class Traits>
Flag ProblemStat<Traits>::
adaptGrid(AdaptInfo& adaptInfo)
......
......@@ -74,6 +74,14 @@ namespace AMDiS
/// Refinement/coarsening of the grid.
virtual Flag adaptGrid(AdaptInfo& adaptInfo) = 0;
/// Uniform global grid coarsening by up to n level.
/// Returns MESH_ADAPTED if grid was changed
virtual Flag globalCoarsen(int n) = 0;
/// Uniform global refinement by n level
/// Returns MESH_ADAPTED if grid was changed
virtual Flag globalRefine(int n) = 0;
/** \brief
* Solves the assembled system. The result is an approximative solution.
* The last two boolean arguments can be used to controll successive
......
......@@ -11,6 +11,10 @@
namespace AMDiS
{
/// Store cache in instance.
template <class Container>
struct ConsecutivePolicy;
/// Store cache thread local, requires no locking.
template <class Container>
struct ThreadLocalPolicy;
......@@ -29,9 +33,10 @@ namespace AMDiS
* \tparam Key The type of key to access the data.
* \tparam Data The type of the data stored in the cache. The behaviur is undefined if Data is not
* the same type as Container::mapped_type.
* \tparam Policy A policy class template implementing the method `get_or_init()`. Two implementations
* are provided: \ref ThreadLocalPolicy and \ref StaticLockedPolicy. By default, if not
* Policy class template is specified, the `ThreadLocalPolicy` is used. \see ConcurrentCachePolicy
* \tparam Policy A policy class template implementing the method `get_or_init()`. Three implementations
* are provided: \ref ConsecutivePolicy, \ref ThreadLocalPolicy and \ref StaticLockedPolicy.
* By default, if no policy class template is specified, the `ThreadLocalPolicy` is used.
* \see ConcurrentCachePolicy
* \tparam Container The type of the underlying associative container to use to store the data. The
* container must satisfy the requirements of AssociativeContainer. The standard
* containers `std::map` and `std::unordered_map` satisfie this requirement. By default,
......@@ -54,7 +59,7 @@ namespace AMDiS
* Provide a static cache and a `get_or_init()` static method that extracts the data from the cache if it exists or
* creates a new extry by using an initialization functor.
*
* Realizations of this template are \ref ThreadLocalPolicy and \ref StaticLockedPolicy.
* Realizations of this template are \ref ConsecutivePolicy, \ref ThreadLocalPolicy and \ref StaticLockedPolicy.
*
* \tparam Container The Type of the associative container key->data to store the cached data.
**/
......@@ -62,7 +67,54 @@ namespace AMDiS
class ConcurrentCachePolicy;
#endif
// implementation of the ThreadLocal policy
// implementation of the consecutive policy. Data is stored in instance variable.
template <class Container>
struct ConsecutivePolicy
{
using key_type = typename Container::key_type;
using data_type = typename Container::mapped_type;
using container_type = Container;
template <class F, class... Args>
data_type const& get_or_init(key_type const& key, F&& f, Args&&... args) const
{
return impl(std::is_default_constructible<data_type>{},
key, std::forward<F>(f), std::forward<Args>(args)...);
}
private:
// data_type is default_constructible
template <class F, class... Args>
data_type const& impl(std::true_type, key_type const& key, F&& f, Args&&... args) const
{
data_type empty;
auto it = cachedData_.emplace(key, std::move(empty));
if (it.second) {
data_type data = f(key, std::forward<Args>(args)...);
it.first->second = std::move(data);
}
return it.first->second;
}
// data_type is not default_constructible
template <class F, class... Args>
data_type const& impl(std::false_type, key_type const& key, F&& f, Args&&... args) const
{
auto it = cachedData_.find(key);
if (it != cachedData_.end())
return it->second;
else {
data_type data = f(key, std::forward<Args>(args)...);
auto it = cachedData_.emplace(key, std::move(data));
return it.first->second;
}
}
mutable container_type cachedData_;
};
// implementation of the ThreadLocal policy. Data is stored in thread_local variable.
template <class Container>
struct ThreadLocalPolicy
{
......@@ -113,7 +165,7 @@ namespace AMDiS
};
// implementation of the Shared policy
// implementation of the Shared policy. Data is stored in static variable.
template <class Container>
struct StaticLockedPolicy
{
......@@ -151,7 +203,7 @@ namespace AMDiS
template <class Key, class Data, template <class> class Policy, class Container>
class ConcurrentCache
: private Policy<Container>
: protected Policy<Container>
{
using key_type = Key;
using data_type = Data;
......@@ -167,7 +219,7 @@ namespace AMDiS
* \param args... Arguments passed additionally to the functor f
**/
template <class F, class... Args>
static data_type const& get(key_type const& key, F&& f, Args&&... args)
data_type const& get(key_type const& key, F&& f, Args&&... args) const
{
static_assert(Dune::Std::is_callable<F(key_type, Args...), data_type>::value,
"Functor F must have the signature data_type(key_type, Args...)");
......
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