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]); });
234 template<
class StageParamsPtr>
237 stageParams_ = std::move(params);
238 const auto curStage = stageParams_->size() - 1;
243 using namespace Dune::Hybrid;
244 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
246 setProblemTime_(*std::get<domainId>(problemTuple_), stageParams_->timeAtStage(0));
250 spatialOperatorEvaluations_.push_back(*residual_);
251 temporalOperatorEvaluations_.push_back(*residual_);
252 assembleOperatorEvaluations_(x);
260 if (spatialOperatorEvaluations_.size() != curStage)
261 DUNE_THROW(Dune::InvalidStateException,
"Invalid state. Maybe you forgot to call clearStages()");
263 using namespace Dune::Hybrid;
264 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
266 setProblemTime_(*std::get<domainId>(problemTuple_), stageParams_->timeAtStage(curStage-1));
268 assembleOperatorEvaluations_(x);
271 using namespace Dune::Hybrid;
272 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
274 setProblemTime_(*std::get<domainId>(problemTuple_), stageParams_->timeAtStage(curStage));
278 spatialOperatorEvaluations_.push_back(*residual_);
279 temporalOperatorEvaluations_.push_back(*residual_);
285 spatialOperatorEvaluations_.clear();
286 temporalOperatorEvaluations_.clear();
287 stageParams_.reset();
294 {
return timeSteppingMethod_->implicit(); }
297 template<std::
size_t i>
298 std::size_t
numDofs(Dune::index_constant<i> domainId)
const
299 {
return std::get<domainId>(gridDiscretizationTuple_)->numDofs(); }
302 template<std::
size_t i>
303 const auto&
problem(Dune::index_constant<i> domainId)
const
304 {
return *std::get<domainId>(problemTuple_); }
307 template<std::
size_t i>
309 {
return *std::get<domainId>(gridDiscretizationTuple_); }
312 template<std::
size_t i>
313 const auto&
gridView(Dune::index_constant<i> domainId)
const
317 template<std::
size_t i>
319 {
return *std::get<domainId>(gridVariablesTuple_); }
322 template<std::
size_t i>
324 {
return *std::get<domainId>(gridVariablesTuple_); }
330 {
return *jacobian_; }
333 {
return *residual_; }
336 {
return *prevSol_; }
346 DUNE_THROW(Dune::InvalidStateException,
"No stage params set. Call prepareStage first.");
347 const auto k = stageParams_->size() - 1;
348 return {stageParams_->temporalWeight(k), stageParams_->spatialWeight(k)};
351 template<std::
size_t i>
353 {
return LocalResidual<i>(std::get<domainId>(problemTuple_).get(),
nullptr); }
361 template<std::
size_t i,
class AssembleElementFunc>
365 couplingManager_->assembleMultithreaded(Dune::index_constant<i>{}, std::forward<AssembleElementFunc>(f));
375 using namespace Dune::Hybrid;
376 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
378 auto& spatial = spatialOperatorEvaluations_.back()[domainId];
379 auto& temporal = temporalOperatorEvaluations_.back()[domainId];
382 assemble_(domainId, [&](
const auto& element)
385 SubDomainAssembler<domainId()> subDomainAssembler(view, element, x, *
couplingManager_);
386 subDomainAssembler.assembleCurrentResidual(temporal, spatial);
392 using namespace Dune::Hybrid;
393 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto i)
395 forEach(jac[i], [&](
auto& jacBlock)
397 using BlockType = std::decay_t<
decltype(jacBlock)>;
398 if (jacBlock.buildMode() == BlockType::BuildMode::unknown)
399 jacBlock.setBuildMode(BlockType::BuildMode::random);
400 else if (jacBlock.buildMode() != BlockType::BuildMode::random)
401 DUNE_THROW(Dune::NotImplemented,
"Only BCRS matrices with random build mode are supported");
408 using namespace Dune::Hybrid;
409 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainI)
411 forEach(integralRange(Dune::Hybrid::size(jac[domainI])), [&](
const auto domainJ)
413 const auto pattern = getJacobianPattern_(domainI, domainJ);
414 pattern.exportIdx(jac[domainI][domainJ]);
421 using namespace Dune::Hybrid;
422 forEach(integralRange(Dune::Hybrid::size(res)), [&](
const auto domainId)
423 { res[domainId].resize(this->
numDofs(domainId)); });
426 void resetResidual_()
430 residual_ = std::make_shared<ResidualType>();
431 setResidualSize_(*residual_);
434 setResidualSize_(constrainedDofs_);
436 constrainedDofs_ = 0.0;
439 void resetJacobian_()
443 jacobian_ = std::make_shared<JacobianMatrix>();
444 setJacobianBuildMode_(*jacobian_);
445 setJacobianPattern_(*jacobian_);
450 void maybeComputeColors_()
452 if constexpr (CouplingManagerSupportsMultithreadedAssembly<CouplingManager>::value)
453 if (enableMultithreading_)
457 template<std::
size_t i,
class AssembleElementFunc>
458 void assemble_(Dune::index_constant<i> domainId, AssembleElementFunc&& assembleElement)
const
460 bool succeeded =
false;
463 if constexpr (CouplingManagerSupportsMultithreadedAssembly<CouplingManager>::value)
465 if (enableMultithreading_)
468 domainId, std::forward<AssembleElementFunc>(assembleElement)
474 for (
const auto& element : elements(
gridView(domainId)))
475 assembleElement(element);
479 catch (NumericalProblem& e)
481 std::cout <<
"rank " <<
gridView(domainId).comm().rank()
482 <<
" caught an exception while assembling: " << e.what() <<
"\n";
486 if (
gridView(domainId).comm().size() > 1)
487 succeeded =
gridView(domainId).comm().min(succeeded);
490 DUNE_THROW(NumericalProblem,
"A process did not succeed in linearizing the system");
494 template<std::
size_t i,
class JacRow,
class Res,
class Sol>
495 void enforceProblemConstraints_(Dune::index_constant<i> domainI, JacRow& jacRow, Res& res,
const Sol& curSol)
const
499 auto& jac = jacRow[domainI];
501 auto applyDirichletConstraint = [&](
const auto& dofIdx,
const auto& values,
502 const auto eqIdx,
const auto pvIdx)
504 res[dofIdx][eqIdx] = curSol[dofIdx][pvIdx] - values[pvIdx];
506 auto& row = jac[dofIdx];
507 for (
auto col = row.begin(); col != row.end(); ++col)
508 row[col.index()][eqIdx] = 0.0;
509 jac[dofIdx][dofIdx][eqIdx][pvIdx] = 1.0;
511 using namespace Dune::Hybrid;
514 auto& rowCoupling = jacRow[couplingId][dofIdx];
515 for (
auto c = rowCoupling.begin(); c != rowCoupling.end(); ++c)
516 rowCoupling[c.index()][eqIdx] = 0.0;
520 for (
const auto& constraintData : this->
problem(domainI).constraints())
522 const auto& info = constraintData.constraintInfo();
523 const auto& values = constraintData.values();
524 const auto dofIdx = constraintData.dofIndex();
525 for (
int eqIdx = 0; eqIdx < info.size(); ++eqIdx)
526 if (info.isConstraintEquation(eqIdx))
527 applyDirichletConstraint(dofIdx, values, eqIdx, info.eqToPriVarIndex(eqIdx));
532 template<std::
size_t i, std::
size_t j,
typename std::enable_if_t<(i==j),
int> = 0>
533 Dune::MatrixIndexSet getJacobianPattern_(Dune::index_constant<i> domainI,
534 Dune::index_constant<j>)
const
543 template<std::
size_t i, std::
size_t j,
typename std::enable_if_t<(i!=j),
int> = 0>
544 Dune::MatrixIndexSet getJacobianPattern_(Dune::index_constant<i> domainI,
545 Dune::index_constant<j> domainJ)
const
547 if (timeSteppingMethod_->implicit())
558 void setProblemTime_(
const P& p,
const Scalar t)
560 if constexpr (
requires { p.setTime(t); })
563 static_assert(!
requires (P& q) { q.setTime(
Scalar{}); },
564 "The multi-stage assembler sets the stage time through a const problem: setTime has to be const.");
567 std::shared_ptr<const Experimental::MultiStageMethod<Scalar>> timeSteppingMethod_;
568 std::vector<ResidualType> spatialOperatorEvaluations_;
569 std::vector<ResidualType> temporalOperatorEvaluations_;
571 std::shared_ptr<const StageParams> stageParams_;
573 ProblemTuple problemTuple_;
574 GridDiscretizationTuple gridDiscretizationTuple_;
575 GridVariablesTuple gridVariablesTuple_;
579 std::shared_ptr<JacobianMatrix> jacobian_;
580 std::shared_ptr<ResidualType> residual_;
582 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:332
void assembleMultithreaded(Dune::index_constant< i >, AssembleElementFunc &&f) const
Definition multistagemultidomainassembler.hh:362
const SolutionVector & prevSol() const
Definition multistagemultidomainassembler.hh:335
typename MDTraits::JacobianMatrix JacobianMatrix
Definition multistagemultidomainassembler.hh:86
void computeColorsForAssembly()
Definition multistagemultidomainassembler.hh:355
std::size_t numDofs(Dune::index_constant< i > domainId) const
the number of dof locations of domain i
Definition multistagemultidomainassembler.hh:298
GridVariables< i > & gridVariables(Dune::index_constant< i > domainId)
Definition multistagemultidomainassembler.hh:318
const auto & problem(Dune::index_constant< i > domainId) const
Definition multistagemultidomainassembler.hh:303
const auto & gridView(Dune::index_constant< i > domainId) const
the grid view of domain i
Definition multistagemultidomainassembler.hh:313
typename MDTraits::ResidualVector ResidualType
Definition multistagemultidomainassembler.hh:88
typename MDTraits::Scalar Scalar
Definition multistagemultidomainassembler.hh:71
std::shared_ptr< CouplingManager > couplingManager_
Definition multistagemultidomainassembler.hh:369
bool isStationaryProblem() const
Definition multistagemultidomainassembler.hh:290
void resetTimeStep(const SolutionVector &curSol)
Reset the grid variables to the given solution (e.g. after a failed time step).
Definition multistagemultidomainassembler.hh:224
void prepareStage(SolutionVector &x, StageParamsPtr params)
Prepare the assembler for the next stage of the time integration.
Definition multistagemultidomainassembler.hh:235
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:329
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:323
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:339
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:343
LocalResidual< i > localResidual(Dune::index_constant< i > domainId) const
Definition multistagemultidomainassembler.hh:352
bool isImplicit() const
Definition multistagemultidomainassembler.hh:293
Experimental::MultiStageParams< Scalar > StageParams
Definition multistagemultidomainassembler.hh:72
const auto & gridDiscretization(Dune::index_constant< i > domainId) const
Definition multistagemultidomainassembler.hh:308
void clearStages()
Clear all stored stage evaluations.
Definition multistagemultidomainassembler.hh:283
typename MDTraits::SolutionVector SolutionVector
Definition multistagemultidomainassembler.hh:87
const CouplingManager & couplingManager() const
Definition multistagemultidomainassembler.hh:326
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: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.
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:31
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
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.