23#ifndef DUMUX_MULTIDOMAIN_MULTISTAGE_MULTIDOMAIN_ASSEMBLER_HH
24#define DUMUX_MULTIDOMAIN_MULTISTAGE_MULTIDOMAIN_ASSEMBLER_HH
32#include <dune/common/hybridutilities.hh>
33#include <dune/istl/matrixindexset.hh>
46#include <dumux/multidomain/subdomaincvfelocalassembler_.hh>
63template<
class MDTraits,
class CMType, DiffMethod diffMethod>
66 template<std::
size_t id>
67 using SubDomainTypeTag =
typename MDTraits::template SubDomain<id>::TypeTag;
71 using Scalar =
typename MDTraits::Scalar;
74 template<std::
size_t id>
75 using LocalResidual =
typename MDTraits::template SubDomain<id>::LocalResidual;
77 template<std::
size_t id>
78 using GridVariables =
typename MDTraits::template SubDomain<id>::GridVariables;
80 template<std::
size_t id>
83 template<std::
size_t id>
84 using Problem =
typename MDTraits::template SubDomain<id>::Problem;
92 using ProblemTuple =
typename MDTraits::template TupleOfSharedPtrConst<Problem>;
93 using GridDiscretizationTuple =
typename MDTraits::template TupleOfSharedPtrConst<GridDiscretization>;
94 using GridVariablesTuple =
typename MDTraits::template TupleOfSharedPtr<GridVariables>;
97 template<std::
size_t id>
100 template<
class DiscretizationMethod, std::
size_t id>
101 struct SubDomainAssemblerType;
103 template<std::
size_t id,
class DM>
109 template<std::
size_t id>
110 using SubDomainAssembler =
typename SubDomainAssemblerType<typename GridDiscretization<id>::DiscretizationMethod,
id>::type;
130 , timeSteppingMethod_(msMethod)
131 , problemTuple_(std::move(
problem))
136 std::cout <<
"Instantiated multi-stage multi-domain assembler." << std::endl;
143 maybeComputeColors_();
153 spatialOperatorEvaluations_.back() = 0.0;
154 temporalOperatorEvaluations_.back() = 0.0;
156 if (stageParams_->size() != spatialOperatorEvaluations_.size())
157 DUNE_THROW(Dune::InvalidStateException,
"Wrong number of stage residuals. Call prepareStage first.");
159 using namespace Dune::Hybrid;
160 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
162 auto& jacRow = (*jacobian_)[domainId];
163 auto& spatial = spatialOperatorEvaluations_.back()[domainId];
164 auto& temporal = temporalOperatorEvaluations_.back()[domainId];
166 assemble_(domainId, [&](
const auto& element)
169 SubDomainAssembler<domainId()> subDomainAssembler(view, element, curSol, *
couplingManager_);
170 subDomainAssembler.assembleJacobianAndResidual(
171 jacRow, (*residual_)[domainId],
173 *stageParams_, temporal, spatial,
174 constrainedDofs_[domainId]
179 auto constantResidualComponent = (*residual_)[domainId];
180 constantResidualComponent = 0.0;
181 for (std::size_t k = 0; k < stageParams_->size()-1; ++k)
183 if (!stageParams_->skipTemporal(k))
184 constantResidualComponent.axpy(stageParams_->temporalWeight(k), temporalOperatorEvaluations_[k][domainId]);
185 if (!stageParams_->skipSpatial(k))
186 constantResidualComponent.axpy(stageParams_->spatialWeight(k), spatialOperatorEvaluations_[k][domainId]);
189 for (std::size_t i = 0; i < constantResidualComponent.size(); ++i)
190 for (std::size_t ii = 0; ii < constantResidualComponent[i].size(); ++ii)
191 (*residual_)[domainId][i][ii] += constrainedDofs_[domainId][i][ii] > 0.5 ? 0.0 : constantResidualComponent[i][ii];
193 enforceProblemConstraints_(domainId, (*jacobian_)[domainId], (*residual_)[domainId], curSol[domainId]);
199 { DUNE_THROW(Dune::NotImplemented,
"assembleResidual without Jacobian for multi-stage multi-domain assembly"); }
204 jacobian_ = std::make_shared<JacobianMatrix>();
205 residual_ = std::make_shared<ResidualType>();
207 setJacobianBuildMode_(*jacobian_);
208 setJacobianPattern_(*jacobian_);
209 setResidualSize_(*residual_);
215 using namespace Dune::Hybrid;
216 forEach(integralRange(Dune::Hybrid::size(gridVariablesTuple_)), [&](
const auto domainId)
217 { this->
gridVariables(domainId).update(curSol[domainId]); });
226 using namespace Dune::Hybrid;
227 forEach(integralRange(Dune::Hybrid::size(gridVariablesTuple_)), [&](
const auto domainId)
228 { this->
gridVariables(domainId).resetTimeStep(curSol[domainId]); });
237 template<
class StageParamsPtr>
240 stageParams_ = std::move(params);
241 const auto curStage = stageParams_->size() - 1;
246 using namespace Dune::Hybrid;
247 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
249 setProblemTime_(*std::get<domainId>(problemTuple_), stageParams_->timeAtStage(0));
253 spatialOperatorEvaluations_.push_back(*residual_);
254 temporalOperatorEvaluations_.push_back(*residual_);
255 assembleOperatorEvaluations_(x);
263 if (spatialOperatorEvaluations_.size() != curStage)
264 DUNE_THROW(Dune::InvalidStateException,
"Invalid state. Maybe you forgot to call clearStages()");
266 using namespace Dune::Hybrid;
267 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
269 setProblemTime_(*std::get<domainId>(problemTuple_), stageParams_->timeAtStage(curStage-1));
271 assembleOperatorEvaluations_(x);
274 using namespace Dune::Hybrid;
275 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
277 setProblemTime_(*std::get<domainId>(problemTuple_), stageParams_->timeAtStage(curStage));
281 spatialOperatorEvaluations_.push_back(*residual_);
282 temporalOperatorEvaluations_.push_back(*residual_);
288 spatialOperatorEvaluations_.clear();
289 temporalOperatorEvaluations_.clear();
290 stageParams_.reset();
297 {
return timeSteppingMethod_->implicit(); }
300 template<std::
size_t i>
301 std::size_t
numDofs(Dune::index_constant<i> domainId)
const
302 {
return std::get<domainId>(gridDiscretizationTuple_)->numDofs(); }
305 template<std::
size_t i>
306 const auto&
problem(Dune::index_constant<i> domainId)
const
307 {
return *std::get<domainId>(problemTuple_); }
310 template<std::
size_t i>
312 {
return *std::get<domainId>(gridDiscretizationTuple_); }
315 template<std::
size_t i>
316 const auto&
gridView(Dune::index_constant<i> domainId)
const
320 template<std::
size_t i>
322 {
return *std::get<domainId>(gridVariablesTuple_); }
325 template<std::
size_t i>
327 {
return *std::get<domainId>(gridVariablesTuple_); }
333 {
return *jacobian_; }
336 {
return *residual_; }
339 {
return *prevSol_; }
349 DUNE_THROW(Dune::InvalidStateException,
"No stage params set. Call prepareStage first.");
350 const auto k = stageParams_->size() - 1;
351 return {stageParams_->temporalWeight(k), stageParams_->spatialWeight(k)};
354 template<std::
size_t i>
356 {
return LocalResidual<i>(std::get<domainId>(problemTuple_).get(),
nullptr); }
364 template<std::
size_t i,
class AssembleElementFunc>
368 couplingManager_->assembleMultithreaded(Dune::index_constant<i>{}, std::forward<AssembleElementFunc>(f));
378 using namespace Dune::Hybrid;
379 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
381 auto& spatial = spatialOperatorEvaluations_.back()[domainId];
382 auto& temporal = temporalOperatorEvaluations_.back()[domainId];
385 assemble_(domainId, [&](
const auto& element)
388 SubDomainAssembler<domainId()> subDomainAssembler(view, element, x, *
couplingManager_);
389 subDomainAssembler.assembleCurrentResidual(temporal, spatial);
395 using namespace Dune::Hybrid;
396 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto i)
398 forEach(jac[i], [&](
auto& jacBlock)
400 using BlockType = std::decay_t<
decltype(jacBlock)>;
401 if (jacBlock.buildMode() == BlockType::BuildMode::unknown)
402 jacBlock.setBuildMode(BlockType::BuildMode::random);
403 else if (jacBlock.buildMode() != BlockType::BuildMode::random)
404 DUNE_THROW(Dune::NotImplemented,
"Only BCRS matrices with random build mode are supported");
411 using namespace Dune::Hybrid;
412 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainI)
414 forEach(integralRange(Dune::Hybrid::size(jac[domainI])), [&](
const auto domainJ)
416 const auto pattern = getJacobianPattern_(domainI, domainJ);
417 pattern.exportIdx(jac[domainI][domainJ]);
424 using namespace Dune::Hybrid;
425 forEach(integralRange(Dune::Hybrid::size(res)), [&](
const auto domainId)
426 { res[domainId].resize(this->
numDofs(domainId)); });
429 void resetResidual_()
433 residual_ = std::make_shared<ResidualType>();
434 setResidualSize_(*residual_);
437 setResidualSize_(constrainedDofs_);
439 constrainedDofs_ = 0.0;
442 void resetJacobian_()
446 jacobian_ = std::make_shared<JacobianMatrix>();
447 setJacobianBuildMode_(*jacobian_);
448 setJacobianPattern_(*jacobian_);
453 void maybeComputeColors_()
455 if constexpr (CouplingManagerSupportsMultithreadedAssembly<CouplingManager>::value)
456 if (enableMultithreading_)
460 template<std::
size_t i,
class AssembleElementFunc>
461 void assemble_(Dune::index_constant<i> domainId, AssembleElementFunc&& assembleElement)
const
463 bool succeeded =
false;
466 if constexpr (CouplingManagerSupportsMultithreadedAssembly<CouplingManager>::value)
468 if (enableMultithreading_)
471 domainId, std::forward<AssembleElementFunc>(assembleElement)
477 for (
const auto& element : elements(
gridView(domainId)))
478 assembleElement(element);
482 catch (NumericalProblem& e)
484 std::cout <<
"rank " <<
gridView(domainId).comm().rank()
485 <<
" caught an exception while assembling: " << e.what() <<
"\n";
489 if (
gridView(domainId).comm().size() > 1)
490 succeeded =
gridView(domainId).comm().min(succeeded);
493 DUNE_THROW(NumericalProblem,
"A process did not succeed in linearizing the system");
497 template<std::
size_t i,
class JacRow,
class Res,
class Sol>
498 void enforceProblemConstraints_(Dune::index_constant<i> domainI, JacRow& jacRow, Res& res,
const Sol& curSol)
const
502 auto& jac = jacRow[domainI];
504 auto applyDirichletConstraint = [&](
const auto& dofIdx,
const auto& values,
505 const auto eqIdx,
const auto pvIdx)
507 res[dofIdx][eqIdx] = curSol[dofIdx][pvIdx] - values[pvIdx];
509 auto& row = jac[dofIdx];
510 for (
auto col = row.begin(); col != row.end(); ++col)
511 row[col.index()][eqIdx] = 0.0;
512 jac[dofIdx][dofIdx][eqIdx][pvIdx] = 1.0;
514 using namespace Dune::Hybrid;
517 auto& rowCoupling = jacRow[couplingId][dofIdx];
518 for (
auto c = rowCoupling.begin(); c != rowCoupling.end(); ++c)
519 rowCoupling[c.index()][eqIdx] = 0.0;
523 for (
const auto& constraintData : this->
problem(domainI).constraints())
525 const auto& info = constraintData.constraintInfo();
526 const auto& values = constraintData.values();
527 const auto dofIdx = constraintData.dofIndex();
528 for (
int eqIdx = 0; eqIdx < info.size(); ++eqIdx)
529 if (info.isConstraintEquation(eqIdx))
530 applyDirichletConstraint(dofIdx, values, eqIdx, info.eqToPriVarIndex(eqIdx));
535 template<std::
size_t i, std::
size_t j,
typename std::enable_if_t<(i==j),
int> = 0>
536 Dune::MatrixIndexSet getJacobianPattern_(Dune::index_constant<i> domainI,
537 Dune::index_constant<j>)
const
546 template<std::
size_t i, std::
size_t j,
typename std::enable_if_t<(i!=j),
int> = 0>
547 Dune::MatrixIndexSet getJacobianPattern_(Dune::index_constant<i> domainI,
548 Dune::index_constant<j> domainJ)
const
550 if (timeSteppingMethod_->implicit())
561 void setProblemTime_(
const P& p,
const Scalar t)
563 if constexpr (
requires { p.setTime(t); })
566 static_assert(!
requires (P& q) { q.setTime(
Scalar{}); },
567 "The multi-stage assembler sets the stage time through a const problem: setTime has to be const.");
570 std::shared_ptr<const Experimental::MultiStageMethod<Scalar>> timeSteppingMethod_;
571 std::vector<ResidualType> spatialOperatorEvaluations_;
572 std::vector<ResidualType> temporalOperatorEvaluations_;
574 std::shared_ptr<const StageParams> stageParams_;
576 ProblemTuple problemTuple_;
577 GridDiscretizationTuple gridDiscretizationTuple_;
578 GridVariablesTuple gridVariablesTuple_;
582 std::shared_ptr<JacobianMatrix> jacobian_;
583 std::shared_ptr<ResidualType> residual_;
585 bool enableMultithreading_ =
false;
Subdomain-specific views on multidomain assemblers.
Traits shared by the multi-domain assemblers.
Abstract interface for one-step multi-stage method parameters in Shu/Osher form.
Definition multistagemethods.hh:75
ResidualType & residual()
Definition multistagemultidomainassembler.hh:335
void assembleMultithreaded(Dune::index_constant< i >, AssembleElementFunc &&f) const
Definition multistagemultidomainassembler.hh:365
const SolutionVector & prevSol() const
Definition multistagemultidomainassembler.hh:338
typename MDTraits::JacobianMatrix JacobianMatrix
Definition multistagemultidomainassembler.hh:86
void computeColorsForAssembly()
Definition multistagemultidomainassembler.hh:358
std::size_t numDofs(Dune::index_constant< i > domainId) const
the number of dof locations of domain i
Definition multistagemultidomainassembler.hh:301
GridVariables< i > & gridVariables(Dune::index_constant< i > domainId)
Definition multistagemultidomainassembler.hh:321
const auto & problem(Dune::index_constant< i > domainId) const
Definition multistagemultidomainassembler.hh:306
const auto & gridView(Dune::index_constant< i > domainId) const
the grid view of domain i
Definition multistagemultidomainassembler.hh:316
typename MDTraits::ResidualVector ResidualType
Definition multistagemultidomainassembler.hh:88
typename MDTraits::Scalar Scalar
Definition multistagemultidomainassembler.hh:71
std::shared_ptr< CouplingManager > couplingManager_
Definition multistagemultidomainassembler.hh:372
bool isStationaryProblem() const
Definition multistagemultidomainassembler.hh:293
void resetTimeStep(const SolutionVector &curSol)
Reset the grid variables and the coupling manager to the given solution (e.g. after a failed time ste...
Definition multistagemultidomainassembler.hh:224
void prepareStage(SolutionVector &x, StageParamsPtr params)
Prepare the assembler for the next stage of the time integration.
Definition multistagemultidomainassembler.hh:238
MDTraits Traits
Definition multistagemultidomainassembler.hh:70
CMType CouplingManager
Definition multistagemultidomainassembler.hh:89
typename MDTraits::template SubDomain< id >::LocalResidual LocalResidual
Definition multistagemultidomainassembler.hh:75
typename MDTraits::template SubDomain< id >::Problem Problem
Definition multistagemultidomainassembler.hh:84
JacobianMatrix & jacobian()
Definition multistagemultidomainassembler.hh:332
void updateGridVariables(const SolutionVector &curSol)
Update the grid variables and the coupling manager for the given solution.
Definition multistagemultidomainassembler.hh:213
const GridVariables< i > & gridVariables(Dune::index_constant< i > domainId) const
the grid variables of domain i
Definition multistagemultidomainassembler.hh:326
GetPropType< SubDomainTypeTag< id >, Properties::GridGeometry > GridDiscretization
Definition multistagemultidomainassembler.hh:81
void setPreviousSolution(const SolutionVector &sol)
Set the solution at the previous time level.
Definition multistagemultidomainassembler.hh:342
MultiStageMultiDomainAssembler(ProblemTuple problem, GridDiscretizationTuple gridDiscretization, GridVariablesTuple gridVariables, std::shared_ptr< CouplingManager > couplingManager, std::shared_ptr< const Experimental::MultiStageMethod< Scalar > > msMethod, const SolutionVector &prevSol)
The constructor.
Definition multistagemultidomainassembler.hh:123
void setLinearSystem()
Set up the Jacobian and residual storage.
Definition multistagemultidomainassembler.hh:202
void assembleJacobianAndResidual(const SolutionVector &curSol)
Assembles the Jacobian and residual of the current stage.
Definition multistagemultidomainassembler.hh:149
typename MDTraits::template SubDomain< id >::GridVariables GridVariables
Definition multistagemultidomainassembler.hh:78
void assembleResidual(const SolutionVector &)
Assembling the residual without the Jacobian is not supported.
Definition multistagemultidomainassembler.hh:198
std::pair< Scalar, Scalar > currentStageWeights() const
The temporal and spatial weight of the current stage.
Definition multistagemultidomainassembler.hh:346
LocalResidual< i > localResidual(Dune::index_constant< i > domainId) const
Definition multistagemultidomainassembler.hh:355
bool isImplicit() const
Definition multistagemultidomainassembler.hh:296
Experimental::MultiStageParams< Scalar > StageParams
Definition multistagemultidomainassembler.hh:72
const auto & gridDiscretization(Dune::index_constant< i > domainId) const
Definition multistagemultidomainassembler.hh:311
void clearStages()
Clear all stored stage evaluations.
Definition multistagemultidomainassembler.hh:286
typename MDTraits::SolutionVector SolutionVector
Definition multistagemultidomainassembler.hh:87
const CouplingManager & couplingManager() const
Definition multistagemultidomainassembler.hh:329
Data object for the parameters of a given stage.
Definition multistagetimestepper.hh:31
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.
dune-grid capabilities compatibility layer
Dune::MatrixIndexSet getJacobianPattern(const GridGeometry &gridGeometry)
Helper function to generate Jacobian pattern for cell-centered methods.
Definition jacobianpattern.hh:29
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:33
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.
Parameters for different multistage time stepping methods.
A time stepper performing a single time step of a transient simulation.
constexpr bool hasSubProblemGlobalConstraints()
Definition assemblytraits.hh:30
Definition cvfe/hybrid/elementvariables.hh:32
Definition assembly/assembler.hh:46
bool allGridsSupportsMultithreading(const std::tuple< GridDiscretizations... > &gridDiscretizations)
Whether the grid views of all grid discretizations support multithreading.
Definition gridcapabilities.hh:44
typename Detail::ConcatSeq< decltype(std::make_index_sequence< e >{}), e+1, decltype(std::make_index_sequence<(n > e) ?(n - e - 1) :0 >{})>::type makeIncompleteIntegerSequence
Definition utility.hh:58
Type trait that is specialized for coupling manager supporting multithreaded assembly.
Definition assemblytraits.hh:43
Utilities for template meta programming.