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>
59template<
class MDTraits,
class CMType, DiffMethod diffMethod>
62 template<std::
size_t id>
63 using SubDomainTypeTag =
typename MDTraits::template SubDomain<id>::TypeTag;
68 using Scalar =
typename MDTraits::Scalar;
72 template<std::
size_t id>
75 template<std::
size_t id>
76 using GridVariables =
typename MDTraits::template SubDomain<id>::GridVariables;
78 template<std::
size_t id>
79 using GridGeometry =
typename MDTraits::template SubDomain<id>::GridGeometry;
81 template<std::
size_t id>
82 using Problem =
typename MDTraits::template SubDomain<id>::Problem;
92 using ProblemTuple =
typename MDTraits::template TupleOfSharedPtrConst<Problem>;
93 using GridGeometryTuple =
typename MDTraits::template TupleOfSharedPtrConst<GridGeometry>;
94 using GridVariablesTuple =
typename MDTraits::template TupleOfSharedPtr<GridVariables>;
98 template<std::
size_t id>
101 template<
class DiscretizationMethod, std::
size_t id>
102 struct SubDomainAssemblerType;
104 template<std::
size_t id>
110 template<std::
size_t id>
116 template<std::
size_t id,
class DM>
122 template<std::
size_t id>
123 using SubDomainAssembler =
typename SubDomainAssemblerType<typename GridGeometry<id>::DiscretizationMethod,
id>::type;
138 , timeSteppingMethod_(msMethod)
139 , problemTuple_(std::move(
problem))
144 std::cout <<
"Instantiated assembler for an instationary problem." << std::endl;
151 maybeComputeColors_();
163 spatialOperatorEvaluations_.back() = 0.0;
164 temporalOperatorEvaluations_.back() = 0.0;
166 if (stageParams_->size() != spatialOperatorEvaluations_.size())
167 DUNE_THROW(Dune::InvalidStateException,
"Wrong number of residuals");
169 using namespace Dune::Hybrid;
170 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
174 auto& jacRow = (*jacobian_)[domainId];
175 auto& spatial = spatialOperatorEvaluations_.back()[domainId];
176 auto& temporal = temporalOperatorEvaluations_.back()[domainId];
178 assemble_(domainId, [&](
const auto& element)
181 SubDomainAssembler<domainId()> subDomainAssembler(view, element, curSol, *
couplingManager_);
182 subDomainAssembler.assembleJacobianAndResidual(
183 jacRow, (*residual_)[domainId],
185 *stageParams_, temporal, spatial,
186 constrainedDofs_[domainId]
191 auto constantResidualComponent = (*residual_)[domainId];
192 constantResidualComponent = 0.0;
193 for (std::size_t k = 0; k < stageParams_->size()-1; ++k)
195 if (!stageParams_->skipTemporal(k))
196 constantResidualComponent.axpy(stageParams_->temporalWeight(k), temporalOperatorEvaluations_[k][domainId]);
197 if (!stageParams_->skipSpatial(k))
198 constantResidualComponent.axpy(stageParams_->spatialWeight(k), spatialOperatorEvaluations_[k][domainId]);
202 for (std::size_t i = 0; i < constantResidualComponent.size(); ++i)
203 for (std::size_t ii = 0; ii < constantResidualComponent[i].size(); ++ii)
204 (*residual_)[domainId][i][ii] += constrainedDofs_[domainId][i][ii] > 0.5 ? 0.0 : constantResidualComponent[i][ii];
229 residual_ = std::make_shared<ResidualType>();
230 setResidualSize_(*residual_);
231 setResidualSize_(constrainedDofs_);
232 constrainedDofs_ = 0.0;
236 spatialOperatorEvaluations_.back() = 0.0;
237 temporalOperatorEvaluations_.back() = 0.0;
239 if (stageParams_->size() != spatialOperatorEvaluations_.size())
240 DUNE_THROW(Dune::InvalidStateException,
"Wrong number of residuals");
242 using namespace Dune::Hybrid;
243 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
245 auto& spatial = spatialOperatorEvaluations_.back()[domainId];
246 auto& temporal = temporalOperatorEvaluations_.back()[domainId];
250 assemble_(domainId, [&](
const auto& element)
253 SubDomainAssembler<domainId()> subDomainAssembler(view, element, curSol, *
couplingManager_);
254 subDomainAssembler.localResidual().spatialWeight(1.0);
255 subDomainAssembler.localResidual().temporalWeight(1.0);
256 subDomainAssembler.assembleCurrentResidual(spatial, temporal);
259 auto& stageResidual = (*residual_)[domainId];
260 for (std::size_t k = 0; k < stageParams_->size(); ++k)
262 if (!stageParams_->skipTemporal(k))
263 stageResidual.axpy(stageParams_->temporalWeight(k), temporalOperatorEvaluations_[k][domainId]);
264 if (!stageParams_->skipSpatial(k))
265 stageResidual.axpy(stageParams_->spatialWeight(k), spatialOperatorEvaluations_[k][domainId]);
268 constrainedDofs_[domainId] = 0.0;
271 assemble_(domainId, [&](
const auto& element)
274 SubDomainAssembler<domainId()> subDomainAssembler(view, element, curSol, *
couplingManager_);
275 subDomainAssembler.bindLocalViews();
276 subDomainAssembler.enforceDirichletConstraints(
277 [&](
const auto& scvI,
const auto& dirichletValues,
const auto eqIdx,
const auto pvIdx)
279 stageResidual[scvI.dofIndex()][eqIdx]
280 = subDomainAssembler.curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
281 constrainedDofs_[domainId][scvI.dofIndex()][eqIdx] = 1.0;
294 jacobian_ = std::make_shared<JacobianMatrix>();
295 residual_ = std::make_shared<ResidualType>();
297 setJacobianBuildMode_(*jacobian_);
298 setJacobianPattern_(*jacobian_);
299 setResidualSize_(*residual_);
307 using namespace Dune::Hybrid;
308 forEach(integralRange(Dune::Hybrid::size(gridVariablesTuple_)), [&](
const auto domainId)
309 { this->
gridVariables(domainId).update(curSol[domainId]); });
317 using namespace Dune::Hybrid;
318 forEach(integralRange(Dune::Hybrid::size(gridVariablesTuple_)), [&](
const auto domainId)
319 { this->
gridVariables(domainId).resetTimeStep(curSol[domainId]); });
325 template<std::
size_t i>
326 std::size_t
numDofs(Dune::index_constant<i> domainId)
const
327 {
return std::get<domainId>(gridGeometryTuple_)->numDofs(); }
330 template<std::
size_t i>
331 const auto&
problem(Dune::index_constant<i> domainId)
const
332 {
return *std::get<domainId>(problemTuple_); }
335 template<std::
size_t i>
337 {
return *std::get<domainId>(gridGeometryTuple_); }
340 template<std::
size_t i>
341 const auto&
gridView(Dune::index_constant<i> domainId)
const
345 template<std::
size_t i>
347 {
return *std::get<domainId>(gridVariablesTuple_); }
350 template<std::
size_t i>
352 {
return *std::get<domainId>(gridVariablesTuple_); }
360 {
return *jacobian_; }
364 {
return *residual_; }
368 {
return *prevSol_; }
373 template<std::
size_t i>
375 {
return {
LocalResidual<i>{std::get<domainId>(problemTuple_).get(),
nullptr} }; }
379 spatialOperatorEvaluations_.clear();
380 temporalOperatorEvaluations_.clear();
381 stageParams_.reset();
384 template<
class StageParams>
387 stageParams_ = std::move(params);
388 const auto curStage = stageParams_->size() - 1;
394 using namespace Dune::Hybrid;
395 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
397 setProblemTime_(*std::get<domainId>(problemTuple_), stageParams_->timeAtStage(0));
401 spatialOperatorEvaluations_.push_back(*residual_);
402 temporalOperatorEvaluations_.push_back(*residual_);
405 using namespace Dune::Hybrid;
406 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
408 auto& spatial = spatialOperatorEvaluations_.back()[domainId];
409 auto& temporal = temporalOperatorEvaluations_.back()[domainId];
410 assemble_(domainId, [&](
const auto& element)
413 SubDomainAssembler<domainId()> subDomainAssembler(view, element, x, *
couplingManager_);
414 subDomainAssembler.localResidual().spatialWeight(1.0);
415 subDomainAssembler.localResidual().temporalWeight(1.0);
416 subDomainAssembler.assembleCurrentResidual(spatial, temporal);
426 if (spatialOperatorEvaluations_.size() != curStage)
427 DUNE_THROW(Dune::InvalidStateException,
"Invalid state. Maybe you forgot to call clearStages()");
429 using namespace Dune::Hybrid;
430 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
432 setProblemTime_(*std::get<domainId>(problemTuple_), stageParams_->timeAtStage(curStage-1));
434 auto& spatial = spatialOperatorEvaluations_.back()[domainId];
435 auto& temporal = temporalOperatorEvaluations_.back()[domainId];
438 assemble_(domainId, [&](
const auto& element)
441 SubDomainAssembler<domainId()> subDomainAssembler(view, element, x, *
couplingManager_);
442 subDomainAssembler.localResidual().spatialWeight(1.0);
443 subDomainAssembler.localResidual().temporalWeight(1.0);
444 subDomainAssembler.assembleCurrentResidual(spatial, temporal);
450 using namespace Dune::Hybrid;
451 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
453 setProblemTime_(*std::get<domainId>(problemTuple_), stageParams_->timeAtStage(curStage));
457 spatialOperatorEvaluations_.push_back(*residual_);
458 temporalOperatorEvaluations_.push_back(*residual_);
466 {
return timeSteppingMethod_->implicit(); }
478 using namespace Dune::Hybrid;
479 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto i)
481 forEach(jac[i], [&](
auto& jacBlock)
483 using BlockType = std::decay_t<
decltype(jacBlock)>;
484 if (jacBlock.buildMode() == BlockType::BuildMode::unknown)
485 jacBlock.setBuildMode(BlockType::BuildMode::random);
486 else if (jacBlock.buildMode() != BlockType::BuildMode::random)
487 DUNE_THROW(Dune::NotImplemented,
"Only BCRS matrices with random build mode are supported at the moment");
497 using namespace Dune::Hybrid;
498 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainI)
500 forEach(integralRange(Dune::Hybrid::size(jac[domainI])), [&](
const auto domainJ)
502 const auto pattern = this->getJacobianPattern_(domainI, domainJ);
503 pattern.exportIdx(jac[domainI][domainJ]);
513 using namespace Dune::Hybrid;
514 forEach(integralRange(Dune::Hybrid::size(res)), [&](
const auto domainId)
515 { res[domainId].resize(this->
numDofs(domainId)); });
519 void resetResidual_()
523 residual_ = std::make_shared<ResidualType>();
524 setResidualSize_(*residual_);
527 setResidualSize_(constrainedDofs_);
530 constrainedDofs_ = 0.0;
534 void resetJacobian_()
538 jacobian_ = std::make_shared<JacobianMatrix>();
539 setJacobianBuildMode_(*jacobian_);
540 setJacobianPattern_(*jacobian_);
547 void maybeComputeColors_()
549 if constexpr (CouplingManagerSupportsMultithreadedAssembly<CouplingManager>::value)
550 if (enableMultithreading_)
554 template<std::
size_t i,
class SubRes>
555 void assembleResidual_(Dune::index_constant<i> domainId, SubRes& subRes,
558 DUNE_THROW(Dune::NotImplemented,
"assembleResidual_");
566 template<std::
size_t i,
class AssembleElementFunc>
567 void assemble_(Dune::index_constant<i> domainId, AssembleElementFunc&& assembleElement)
const
570 bool succeeded =
false;
575 if constexpr (CouplingManagerSupportsMultithreadedAssembly<CouplingManager>::value)
577 if (enableMultithreading_)
580 domainId, std::forward<AssembleElementFunc>(assembleElement)
589 for (
const auto& element : elements(
gridView(domainId)))
590 assembleElement(element);
596 catch (NumericalProblem &e)
598 std::cout <<
"rank " <<
gridView(domainId).comm().rank()
599 <<
" caught an exception while assembling:" << e.what()
605 if (
gridView(domainId).comm().size() > 1)
606 succeeded =
gridView(domainId).comm().min(succeeded);
610 DUNE_THROW(NumericalProblem,
"A process did not succeed in linearizing the system");
614 template<std::
size_t i, std::
size_t j,
typename std::enable_if_t<(i==j),
int> = 0>
615 Dune::MatrixIndexSet getJacobianPattern_(Dune::index_constant<i> domainI,
616 Dune::index_constant<j> domainJ)
const
619 if (timeSteppingMethod_->implicit())
634 template<std::
size_t i, std::
size_t j,
typename std::enable_if_t<(i!=j),
int> = 0>
635 Dune::MatrixIndexSet getJacobianPattern_(Dune::index_constant<i> domainI,
636 Dune::index_constant<j> domainJ)
const
638 if (timeSteppingMethod_->implicit())
651 void setProblemTime_(
const P& p,
const Scalar t)
653 if constexpr (
requires { p.setTime(t); })
656 static_assert(!
requires (P& q) { q.setTime(
Scalar{}); },
657 "The multi-stage assembler sets the stage time through a const problem: setTime has to be const.");
660 std::shared_ptr<const Experimental::MultiStageMethod<Scalar>> timeSteppingMethod_;
661 std::vector<ResidualType> spatialOperatorEvaluations_;
662 std::vector<ResidualType> temporalOperatorEvaluations_;
664 std::shared_ptr<const StageParams> stageParams_;
667 ProblemTuple problemTuple_;
670 GridGeometryTuple gridGeometryTuple_;
673 GridVariablesTuple gridVariablesTuple_;
679 std::shared_ptr<JacobianMatrix> jacobian_;
680 std::shared_ptr<ResidualType> residual_;
683 bool enableMultithreading_ =
false;
Subdomain-specific views on multidomain assemblers.
Traits shared by the multi-domain assemblers.
Definition multistagefvlocaloperator.hh:23
Abstract interface for one-step multi-stage method parameters in Shu/Osher form.
Definition multistagemethods.hh:75
MDTraits Traits
Definition multistagemultidomainfvassembler.hh:66
typename MDTraits::SolutionVector SolutionVector
Definition multistagemultidomainfvassembler.hh:85
GetPropType< SubDomainTypeTag< id >, Properties::LocalResidual > LocalResidual
TODO get rid of this GetPropType.
Definition multistagemultidomainfvassembler.hh:73
typename MDTraits::JacobianMatrix JacobianMatrix
Definition multistagemultidomainfvassembler.hh:84
typename MDTraits::Scalar Scalar
Definition multistagemultidomainfvassembler.hh:68
bool isStationaryProblem() const
TODO get rid of this (called by Newton but shouldn't be necessary).
Definition multistagemultidomainfvassembler.hh:462
void assembleJacobianAndResidual(const SolutionVector &curSol)
Assembles the global Jacobian of the residual and the residual for the current solution.
Definition multistagemultidomainfvassembler.hh:158
const GridVariables< i > & gridVariables(Dune::index_constant< i > domainId) const
the grid variables of domain i
Definition multistagemultidomainfvassembler.hh:351
typename MDTraits::template SubDomain< id >::GridGeometry GridGeometry
Definition multistagemultidomainfvassembler.hh:79
void clearStages()
Definition multistagemultidomainfvassembler.hh:377
MultiStageFVLocalOperator< LocalResidual< i > > localResidual(Dune::index_constant< i > domainId) const
Create a local residual object (used by the local assembler).
Definition multistagemultidomainfvassembler.hh:374
typename MDTraits::template SubDomain< id >::Problem Problem
Definition multistagemultidomainfvassembler.hh:82
bool isImplicit() const
Definition multistagemultidomainfvassembler.hh:465
Experimental::MultiStageParams< Scalar > StageParams
Definition multistagemultidomainfvassembler.hh:69
std::shared_ptr< CouplingManager > couplingManager_
Definition multistagemultidomainfvassembler.hh:470
typename MDTraits::ResidualVector ResidualType
Definition multistagemultidomainfvassembler.hh:86
const CouplingManager & couplingManager() const
Definition multistagemultidomainfvassembler.hh:355
const auto & gridView(Dune::index_constant< i > domainId) const
the grid view of domain i
Definition multistagemultidomainfvassembler.hh:341
ResidualType & residual()
the full residual vector
Definition multistagemultidomainfvassembler.hh:363
const SolutionVector & prevSol() const
Definition multistagemultidomainfvassembler.hh:367
void setLinearSystem()
The version without arguments uses the default constructor to create the jacobian and residual object...
Definition multistagemultidomainfvassembler.hh:292
void resetTimeStep(const SolutionVector &curSol)
Resets the grid variables to the last time step.
Definition multistagemultidomainfvassembler.hh:315
typename MDTraits::template SubDomain< id >::GridVariables GridVariables
Definition multistagemultidomainfvassembler.hh:76
CMType CouplingManager
Definition multistagemultidomainfvassembler.hh:88
std::size_t numDofs(Dune::index_constant< i > domainId) const
the number of dof locations of domain i
Definition multistagemultidomainfvassembler.hh:326
void updateGridVariables(const SolutionVector &curSol)
Updates the grid variables with the given solution.
Definition multistagemultidomainfvassembler.hh:305
const auto & problem(Dune::index_constant< i > domainId) const
Definition multistagemultidomainfvassembler.hh:331
const auto & gridGeometry(Dune::index_constant< i > domainId) const
Definition multistagemultidomainfvassembler.hh:336
void prepareStage(SolutionVector &x, StageParams params)
Definition multistagemultidomainfvassembler.hh:385
JacobianMatrix & jacobian()
the full Jacobian matrix
Definition multistagemultidomainfvassembler.hh:359
GridVariables< i > & gridVariables(Dune::index_constant< i > domainId)
Definition multistagemultidomainfvassembler.hh:346
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:131
void assembleResidual(const SolutionVector &curSol)
Assembles the residual for the given solution without the Jacobian.
Definition multistagemultidomainfvassembler.hh:225
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:207
Subdomain-specific view on a multidomain assembler. Allows retrieval of sub-domain specific objects w...
Definition assemblerview.hh:33
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
Dune::MatrixIndexSet getJacobianPattern(const GridGeometry &gridGeometry)
Helper function to generate Jacobian pattern for cell-centered methods.
Definition jacobianpattern.hh:28
Dune::MatrixIndexSet getCouplingJacobianPattern(const CouplingManager &couplingManager, Dune::index_constant< i > domainI, const GridGeometryI &gridGeometryI, Dune::index_constant< j > domainJ, const GridGeometryJ &gridGeometryJ)
Helper function to generate coupling Jacobian pattern (off-diagonal blocks) for cell-centered schemes...
Definition couplingjacobianpattern.hh:31
constexpr bool isSerial()
Checking whether the backend is serial.
Definition multithreading.hh:45
T getParam(Args &&... args)
A free function to get a parameter from the parameter tree singleton.
Definition parameters.hh:155
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 cellcentered/mpfa/elementvolumevariables.hh:24
Definition interpolate.hh:27
constexpr bool isCVFE
Definition method.hh:67
Definition assembly/assembler.hh:44
bool allGridsSupportsMultithreading(const std::tuple< GridDiscretizations... > &gridDiscretizations)
Whether the grid views of all grid discretizations support multithreading.
Definition gridcapabilities.hh:44
Provides a helper class for nonoverlapping decomposition.
Type trait that is specialized for coupling manager supporting multithreaded assembly.
Definition assemblytraits.hh:43
Utilities for template meta programming.