15#ifndef DUMUX_EXPERIMENTAL_MULTISTAGE_MULTIDOMAIN_FV_ASSEMBLER_HH
16#define DUMUX_EXPERIMENTAL_MULTISTAGE_MULTIDOMAIN_FV_ASSEMBLER_HH
23#include <dune/common/hybridutilities.hh>
24#include <dune/istl/matrixindexset.hh>
51template<
class T, std::size_t... I>
93template<
class MDTraits,
class CMType, DiffMethod diffMethod>
96 template<std::
size_t id>
97 using SubDomainTypeTag =
typename MDTraits::template SubDomain<id>::TypeTag;
102 using Scalar =
typename MDTraits::Scalar;
106 template<std::
size_t id>
109 template<std::
size_t id>
110 using GridVariables =
typename MDTraits::template SubDomain<id>::GridVariables;
112 template<std::
size_t id>
113 using GridGeometry =
typename MDTraits::template SubDomain<id>::GridGeometry;
115 template<std::
size_t id>
116 using Problem =
typename MDTraits::template SubDomain<id>::Problem;
126 using ProblemTuple =
typename MDTraits::template TupleOfSharedPtrConst<Problem>;
127 using GridGeometryTuple =
typename MDTraits::template TupleOfSharedPtrConst<GridGeometry>;
128 using GridVariablesTuple =
typename MDTraits::template TupleOfSharedPtr<GridVariables>;
132 template<std::
size_t id>
135 template<
class DiscretizationMethod, std::
size_t id>
136 struct SubDomainAssemblerType;
138 template<std::
size_t id>
139 struct SubDomainAssemblerType<DiscretizationMethods::CCTpfa, id>
144 template<std::
size_t id>
145 struct SubDomainAssemblerType<DiscretizationMethods::CCMpfa, id>
150 template<std::
size_t id,
class DM>
151 struct SubDomainAssemblerType<DiscretizationMethods::CVFE<DM>, id>
156 template<std::
size_t id>
157 using SubDomainAssembler =
typename SubDomainAssemblerType<typename GridGeometry<id>::DiscretizationMethod,
id>::type;
172 , timeSteppingMethod_(msMethod)
173 , problemTuple_(std::move(
problem))
178 std::cout <<
"Instantiated assembler for an instationary problem." << std::endl;
183 && getParam<bool>(
"Assembly.Multithreading",
true);
185 maybeComputeColors_();
197 spatialOperatorEvaluations_.back() = 0.0;
198 temporalOperatorEvaluations_.back() = 0.0;
200 if (stageParams_->size() != spatialOperatorEvaluations_.size())
201 DUNE_THROW(Dune::InvalidStateException,
"Wrong number of residuals");
203 using namespace Dune::Hybrid;
204 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
208 auto& jacRow = (*jacobian_)[domainId];
209 auto& spatial = spatialOperatorEvaluations_.back()[domainId];
210 auto& temporal = temporalOperatorEvaluations_.back()[domainId];
212 assemble_(domainId, [&](
const auto& element)
215 SubDomainAssembler<domainId()> subDomainAssembler(view, element, curSol, *
couplingManager_);
216 subDomainAssembler.assembleJacobianAndResidual(
217 jacRow, (*residual_)[domainId],
219 *stageParams_, temporal, spatial,
220 constrainedDofs_[domainId]
225 auto constantResidualComponent = (*residual_)[domainId];
226 constantResidualComponent = 0.0;
227 for (std::size_t k = 0; k < stageParams_->size()-1; ++k)
229 if (!stageParams_->skipTemporal(k))
230 constantResidualComponent.axpy(stageParams_->temporalWeight(k), temporalOperatorEvaluations_[k][domainId]);
231 if (!stageParams_->skipSpatial(k))
232 constantResidualComponent.axpy(stageParams_->spatialWeight(k), spatialOperatorEvaluations_[k][domainId]);
236 for (std::size_t i = 0; i < constantResidualComponent.size(); ++i)
237 for (std::size_t ii = 0; ii < constantResidualComponent[i].size(); ++ii)
238 (*residual_)[domainId][i][ii] += constrainedDofs_[domainId][i][ii] > 0.5 ? 0.0 : constantResidualComponent[i][ii];
244 { DUNE_THROW(Dune::NotImplemented,
"residual"); }
252 jacobian_ = std::make_shared<JacobianMatrix>();
253 residual_ = std::make_shared<ResidualType>();
255 setJacobianBuildMode_(*jacobian_);
256 setJacobianPattern_(*jacobian_);
257 setResidualSize_(*residual_);
265 using namespace Dune::Hybrid;
266 forEach(integralRange(Dune::Hybrid::size(gridVariablesTuple_)), [&](
const auto domainId)
267 { this->
gridVariables(domainId).update(curSol[domainId]); });
275 using namespace Dune::Hybrid;
276 forEach(integralRange(Dune::Hybrid::size(gridVariablesTuple_)), [&](
const auto domainId)
277 { this->
gridVariables(domainId).resetTimeStep(curSol[domainId]); });
283 template<std::
size_t i>
284 std::size_t
numDofs(Dune::index_constant<i> domainId)
const
285 {
return std::get<domainId>(gridGeometryTuple_)->numDofs(); }
288 template<std::
size_t i>
289 const auto&
problem(Dune::index_constant<i> domainId)
const
290 {
return *std::get<domainId>(problemTuple_); }
293 template<std::
size_t i>
295 {
return *std::get<domainId>(gridGeometryTuple_); }
298 template<std::
size_t i>
299 const auto&
gridView(Dune::index_constant<i> domainId)
const
303 template<std::
size_t i>
305 {
return *std::get<domainId>(gridVariablesTuple_); }
308 template<std::
size_t i>
310 {
return *std::get<domainId>(gridVariablesTuple_); }
318 {
return *jacobian_; }
322 {
return *residual_; }
326 {
return *prevSol_; }
331 template<std::
size_t i>
333 {
return {
LocalResidual<i>{std::get<domainId>(problemTuple_).get(),
nullptr} }; }
337 spatialOperatorEvaluations_.clear();
338 temporalOperatorEvaluations_.clear();
339 stageParams_.reset();
342 template<
class StageParams>
345 stageParams_ = std::move(params);
346 const auto curStage = stageParams_->size() - 1;
352 using namespace Dune::Hybrid;
353 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
355 setProblemTime_(*std::get<domainId>(problemTuple_), stageParams_->timeAtStage(curStage));
359 spatialOperatorEvaluations_.push_back(*residual_);
360 temporalOperatorEvaluations_.push_back(*residual_);
363 using namespace Dune::Hybrid;
364 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
366 auto& spatial = spatialOperatorEvaluations_.back()[domainId];
367 auto& temporal = temporalOperatorEvaluations_.back()[domainId];
368 assemble_(domainId, [&](
const auto& element)
371 SubDomainAssembler<domainId()> subDomainAssembler(view, element, x, *
couplingManager_);
372 subDomainAssembler.localResidual().spatialWeight(1.0);
373 subDomainAssembler.localResidual().temporalWeight(1.0);
374 subDomainAssembler.assembleCurrentResidual(spatial, temporal);
380 using namespace Dune::Hybrid;
381 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
383 setProblemTime_(*std::get<domainId>(problemTuple_), stageParams_->timeAtStage(curStage));
387 spatialOperatorEvaluations_.push_back(*residual_);
388 temporalOperatorEvaluations_.push_back(*residual_);
396 {
return timeSteppingMethod_->implicit(); }
408 using namespace Dune::Hybrid;
409 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto i)
411 forEach(jac[i], [&](
auto& jacBlock)
413 using BlockType = std::decay_t<
decltype(jacBlock)>;
414 if (jacBlock.buildMode() == BlockType::BuildMode::unknown)
415 jacBlock.setBuildMode(BlockType::BuildMode::random);
416 else if (jacBlock.buildMode() != BlockType::BuildMode::random)
417 DUNE_THROW(Dune::NotImplemented,
"Only BCRS matrices with random build mode are supported at the moment");
427 using namespace Dune::Hybrid;
428 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainI)
430 forEach(integralRange(Dune::Hybrid::size(jac[domainI])), [&](
const auto domainJ)
432 const auto pattern = this->getJacobianPattern_(domainI, domainJ);
433 pattern.exportIdx(jac[domainI][domainJ]);
443 using namespace Dune::Hybrid;
444 forEach(integralRange(Dune::Hybrid::size(res)), [&](
const auto domainId)
445 { res[domainId].resize(this->
numDofs(domainId)); });
449 void resetResidual_()
453 residual_ = std::make_shared<ResidualType>();
454 setResidualSize_(*residual_);
457 setResidualSize_(constrainedDofs_);
460 constrainedDofs_ = 0.0;
464 void resetJacobian_()
468 jacobian_ = std::make_shared<JacobianMatrix>();
469 setJacobianBuildMode_(*jacobian_);
470 setJacobianPattern_(*jacobian_);
477 void maybeComputeColors_()
479 if constexpr (CouplingManagerSupportsMultithreadedAssembly<CouplingManager>::value)
480 if (enableMultithreading_)
484 template<std::
size_t i,
class SubRes>
485 void assembleResidual_(Dune::index_constant<i> domainId, SubRes& subRes,
488 DUNE_THROW(Dune::NotImplemented,
"assembleResidual_");
496 template<std::
size_t i,
class AssembleElementFunc>
497 void assemble_(Dune::index_constant<i> domainId, AssembleElementFunc&& assembleElement)
const
500 bool succeeded =
false;
505 if constexpr (CouplingManagerSupportsMultithreadedAssembly<CouplingManager>::value)
507 if (enableMultithreading_)
510 domainId, std::forward<AssembleElementFunc>(assembleElement)
519 for (
const auto& element : elements(
gridView(domainId)))
520 assembleElement(element);
526 catch (NumericalProblem &e)
528 std::cout <<
"rank " <<
gridView(domainId).comm().rank()
529 <<
" caught an exception while assembling:" << e.what()
535 if (
gridView(domainId).comm().size() > 1)
536 succeeded =
gridView(domainId).comm().min(succeeded);
540 DUNE_THROW(NumericalProblem,
"A process did not succeed in linearizing the system");
544 template<std::
size_t i, std::
size_t j,
typename std::enable_if_t<(i==j),
int> = 0>
545 Dune::MatrixIndexSet getJacobianPattern_(Dune::index_constant<i> domainI,
546 Dune::index_constant<j> domainJ)
const
549 if (timeSteppingMethod_->implicit())
551 auto pattern = getJacobianPattern<true>(gg);
557 auto pattern = getJacobianPattern<false>(gg);
564 template<std::
size_t i, std::
size_t j,
typename std::enable_if_t<(i!=j),
int> = 0>
565 Dune::MatrixIndexSet getJacobianPattern_(Dune::index_constant<i> domainI,
566 Dune::index_constant<j> domainJ)
const
568 if (timeSteppingMethod_->implicit())
582 void setProblemTime_(
const P& p,
const Scalar t)
583 { setProblemTimeImpl_(p, t, 0); }
586 auto setProblemTimeImpl_(
const P& p,
const Scalar t,
int) ->
decltype(p.setTime(0))
590 void setProblemTimeImpl_(
const P& p,
const Scalar t,
long)
593 std::shared_ptr<const Experimental::MultiStageMethod<Scalar>> timeSteppingMethod_;
594 std::vector<ResidualType> spatialOperatorEvaluations_;
595 std::vector<ResidualType> temporalOperatorEvaluations_;
597 std::shared_ptr<const StageParams> stageParams_;
600 ProblemTuple problemTuple_;
603 GridGeometryTuple gridGeometryTuple_;
606 GridVariablesTuple gridVariablesTuple_;
612 std::shared_ptr<JacobianMatrix> jacobian_;
613 std::shared_ptr<ResidualType> residual_;
616 bool enableMultithreading_ =
false;
Subdomain-specific views on multidomain assemblers.
Definition: multistagefvlocaloperator.hh:23
Abstract interface for one-step multi-stage method parameters in Shu/Osher form.
Definition: multistagemethods.hh:75
A linear system assembler (residual and Jacobian) for finite volume schemes (box, tpfa,...
Definition: multistagemultidomainfvassembler.hh:95
MDTraits Traits
Definition: multistagemultidomainfvassembler.hh:100
typename MDTraits::SolutionVector SolutionVector
Definition: multistagemultidomainfvassembler.hh:119
GetPropType< SubDomainTypeTag< id >, Properties::LocalResidual > LocalResidual
TODO get rid of this GetPropType.
Definition: multistagemultidomainfvassembler.hh:107
typename MDTraits::JacobianMatrix JacobianMatrix
Definition: multistagemultidomainfvassembler.hh:118
typename MDTraits::Scalar Scalar
Definition: multistagemultidomainfvassembler.hh:102
bool isStationaryProblem() const
TODO get rid of this (called by Newton but shouldn't be necessary)
Definition: multistagemultidomainfvassembler.hh:392
void assembleJacobianAndResidual(const SolutionVector &curSol)
Assembles the global Jacobian of the residual and the residual for the current solution.
Definition: multistagemultidomainfvassembler.hh:192
const GridVariables< i > & gridVariables(Dune::index_constant< i > domainId) const
the grid variables of domain i
Definition: multistagemultidomainfvassembler.hh:309
typename MDTraits::template SubDomain< id >::GridGeometry GridGeometry
Definition: multistagemultidomainfvassembler.hh:113
void clearStages()
Definition: multistagemultidomainfvassembler.hh:335
MultiStageFVLocalOperator< LocalResidual< i > > localResidual(Dune::index_constant< i > domainId) const
Create a local residual object (used by the local assembler)
Definition: multistagemultidomainfvassembler.hh:332
typename MDTraits::template SubDomain< id >::Problem Problem
Definition: multistagemultidomainfvassembler.hh:116
bool isImplicit() const
Definition: multistagemultidomainfvassembler.hh:395
std::shared_ptr< CouplingManager > couplingManager_
the coupling manager coupling the sub domains
Definition: multistagemultidomainfvassembler.hh:400
typename MDTraits::ResidualVector ResidualType
Definition: multistagemultidomainfvassembler.hh:120
const CouplingManager & couplingManager() const
the coupling manager
Definition: multistagemultidomainfvassembler.hh:313
const auto & gridView(Dune::index_constant< i > domainId) const
the grid view of domain i
Definition: multistagemultidomainfvassembler.hh:299
ResidualType & residual()
the full residual vector
Definition: multistagemultidomainfvassembler.hh:321
const SolutionVector & prevSol() const
the solution before time integration
Definition: multistagemultidomainfvassembler.hh:325
void setLinearSystem()
The version without arguments uses the default constructor to create the jacobian and residual object...
Definition: multistagemultidomainfvassembler.hh:250
void resetTimeStep(const SolutionVector &curSol)
Resets the grid variables to the last time step.
Definition: multistagemultidomainfvassembler.hh:273
typename MDTraits::template SubDomain< id >::GridVariables GridVariables
Definition: multistagemultidomainfvassembler.hh:110
CMType CouplingManager
Definition: multistagemultidomainfvassembler.hh:122
std::size_t numDofs(Dune::index_constant< i > domainId) const
the number of dof locations of domain i
Definition: multistagemultidomainfvassembler.hh:284
void updateGridVariables(const SolutionVector &curSol)
Updates the grid variables with the given solution.
Definition: multistagemultidomainfvassembler.hh:263
const auto & problem(Dune::index_constant< i > domainId) const
the problem of domain i
Definition: multistagemultidomainfvassembler.hh:289
const auto & gridGeometry(Dune::index_constant< i > domainId) const
the finite volume grid geometry of domain i
Definition: multistagemultidomainfvassembler.hh:294
void prepareStage(SolutionVector &x, StageParams params)
Definition: multistagemultidomainfvassembler.hh:343
JacobianMatrix & jacobian()
the full Jacobian matrix
Definition: multistagemultidomainfvassembler.hh:317
GridVariables< i > & gridVariables(Dune::index_constant< i > domainId)
the grid variables of domain i
Definition: multistagemultidomainfvassembler.hh:304
MultiStageMultiDomainFVAssembler(ProblemTuple problem, GridGeometryTuple gridGeometry, GridVariablesTuple gridVariables, std::shared_ptr< CouplingManager > couplingManager, std::shared_ptr< const Experimental::MultiStageMethod< Scalar > > msMethod, const SolutionVector &prevSol)
The constructor for instationary problems.
Definition: multistagemultidomainfvassembler.hh:165
void assembleResidual(const SolutionVector &curSol)
compute the residuals using the internal residual
Definition: multistagemultidomainfvassembler.hh:243
Data object for the parameters of a given stage.
Definition: multistagetimestepper.hh:31
The cell-centered scheme multidomain local assembler.
Definition: experimental/assembly/subdomaincclocalassembler.hh:195
The CVFE scheme multidomain local assembler.
Definition: experimental/assembly/subdomaincvfelocalassembler.hh:206
Subdomain-specific view on a multidomain assembler. Allows retrieval of sub-domain specific objects w...
Definition: assemblerview.hh:31
Defines all properties used in Dumux.
Helper function to generate Jacobian pattern for multi domain models.
An enum class to define various differentiation methods available in order to compute the derivatives...
Some exceptions thrown in DuMux
A multidomain local assembler for Jacobian and residual contribution per element (cell-centered metho...
An assembler for Jacobian and residual contribution per element (CVFE methods) for multidomain proble...
dune-grid capabilities compatibility layer
constexpr bool isSerial()
Checking whether the backend is serial.
Definition: multithreading.hh:45
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:296
Helper function to generate Jacobian pattern for different discretization methods.
The available discretization methods in Dumux.
A local operator wrapper for multi-stage time stepping schemes.
Parameters for different multistage time stepping methods.
A time stepper performing a single time step of a transient simulation.
Definition: experimental/assembly/cclocalassembler.hh:36
bool allGridsSupportsMultithreadingImpl(const T &gridGeometries, std::index_sequence< I... >)
Definition: multistagemultidomainfvassembler.hh:52
Definition: gridcapabilities.hh:57
bool allGridsSupportsMultithreading(const std::tuple< GG... > &gridGeometries)
Definition: multistagemultidomainfvassembler.hh:60
bool supportsMultithreading(const GridView &gridView)
Definition: gridcapabilities.hh:74
Provides a helper class for nonoverlapping decomposition.
Type trait that is specialized for coupling manager supporting multithreaded assembly.
Definition: multistagemultidomainfvassembler.hh:78
Utilities for template meta programming.