14#ifndef DUMUX_MULTIDOMAIN_ASSEMBLER_HH
15#define DUMUX_MULTIDOMAIN_ASSEMBLER_HH
22#include <dune/common/hybridutilities.hh>
23#include <dune/istl/matrixindexset.hh>
39#include "subdomaincvfelocalassembler_.hh"
45#if HAVE_DUMUX_OLD_STAGGERED
46#include <dumux/multidomain/subdomainstaggeredlocalassembler.hh>
60template<
class MDTraits,
class CMType, DiffMethod diffMethod,
bool useImplicitAssembly = true>
63 template<std::
size_t id>
64 using SubDomainTypeTag =
typename MDTraits::template SubDomain<id>::TypeTag;
69 using Scalar =
typename MDTraits::Scalar;
71 template<std::
size_t id>
72 using LocalResidual =
typename MDTraits::template SubDomain<id>::LocalResidual;
74 template<std::
size_t id>
75 using GridVariables =
typename MDTraits::template SubDomain<id>::GridVariables;
77 template<std::
size_t id>
80 template<std::
size_t id>
81 using Problem =
typename MDTraits::template SubDomain<id>::Problem;
93 {
return useImplicitAssembly; }
97 using ProblemTuple =
typename MDTraits::template TupleOfSharedPtrConst<Problem>;
98 using GridDiscretizationTuple =
typename MDTraits::template TupleOfSharedPtrConst<GridDiscretization>;
99 using GridVariablesTuple =
typename MDTraits::template TupleOfSharedPtr<GridVariables>;
104 template<std::
size_t id>
107 template<
class DiscretizationMethod, std::
size_t id>
108 struct SubDomainAssemblerType;
110 template<std::
size_t id>
116 template<std::
size_t id>
122 template<std::
size_t id,
class DM>
123 struct SubDomainAssemblerType<DiscretizationMethods::CVFE<DM>, id>
128#if HAVE_DUMUX_OLD_STAGGERED
129 template<std::
size_t id>
130 struct SubDomainAssemblerType<DiscretizationMethods::Staggered, id>
132 using type = SubDomainStaggeredLocalAssembler<id, SubDomainTypeTag<id>, SubDomainAssemblerView<id>, diffMethod,
isImplicit()>;
136 template<std::
size_t id>
137 struct SubDomainAssemblerType<DiscretizationMethods::FCStaggered, id>
139 using type = SubDomainFaceCenteredLocalAssembler<id, SubDomainTypeTag<id>, SubDomainAssemblerView<id>, diffMethod,
isImplicit()>;
142 template<std::
size_t id>
143 using SubDomainAssembler =
typename SubDomainAssemblerType<typename GridDiscretization<id>::DiscretizationMethod,
id>::type;
157 , problemTuple_(std::move(
problem))
161 , isStationaryProblem_(true)
162 , warningIssued_(false)
164 static_assert(
isImplicit(),
"Explicit assembler for stationary problem doesn't make sense!");
165 std::cout <<
"Instantiated assembler for a stationary problem." << std::endl;
172 maybeComputeColors_();
184 std::shared_ptr<const TimeLoop> timeLoop,
187 , problemTuple_(std::move(
problem))
190 , timeLoop_(timeLoop)
192 , isStationaryProblem_(false)
193 , warningIssued_(false)
195 std::cout <<
"Instantiated assembler for an instationary problem." << std::endl;
202 maybeComputeColors_();
211 checkAssemblerState_();
215 using namespace Dune::Hybrid;
216 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
218 auto& jacRow = (*jacobian_)[domainId];
219 auto& subRes = (*residual_)[domainId];
220 const auto& subSol = curSol[domainId];
221 this->assembleJacobianAndResidual_(domainId, jacRow, subRes, curSol);
241 checkAssemblerState_();
246 using namespace Dune::Hybrid;
247 forEach(integralRange(Dune::Hybrid::size(r)), [&](
const auto domainId)
249 auto& subRes = r[domainId];
250 const auto& subSol = curSol[domainId];
251 this->assembleResidual_(domainId, subRes, curSol);
265 std::shared_ptr<ResidualType> r)
271 setJacobianPattern_(*jacobian_);
272 setResidualSize_(*residual_);
281 jacobian_ = std::make_shared<JacobianMatrix>();
282 residual_ = std::make_shared<ResidualType>();
285 setJacobianPattern_(*jacobian_);
286 setResidualSize_(*residual_);
294 using namespace Dune::Hybrid;
295 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto i)
297 forEach(jac[i], [&](
auto& jacBlock)
299 using BlockType = std::decay_t<
decltype(jacBlock)>;
300 if (jacBlock.buildMode() == BlockType::BuildMode::unknown)
301 jacBlock.setBuildMode(BlockType::BuildMode::random);
302 else if (jacBlock.buildMode() != BlockType::BuildMode::random)
303 DUNE_THROW(Dune::NotImplemented,
"Only BCRS matrices with random build mode are supported at the moment");
313 setJacobianPattern_(*jacobian_);
314 setResidualSize_(*residual_);
315 maybeComputeColors_();
323 using namespace Dune::Hybrid;
324 forEach(integralRange(Dune::Hybrid::size(gridVariablesTuple_)), [&](
const auto domainId)
325 { this->
gridVariables(domainId).update(curSol[domainId]); });
333 using namespace Dune::Hybrid;
334 forEach(integralRange(Dune::Hybrid::size(gridVariablesTuple_)), [&](
const auto domainId)
335 { this->
gridVariables(domainId).resetTimeStep(curSol[domainId]); });
339 template<std::
size_t i>
340 std::size_t
numDofs(Dune::index_constant<i> domainId)
const
341 {
return std::get<domainId>(gridDiscretizationTuple_)->numDofs(); }
344 template<std::
size_t i>
345 const auto&
problem(Dune::index_constant<i> domainId)
const
346 {
return *std::get<domainId>(problemTuple_); }
349 template<std::
size_t i>
351 {
return *std::get<domainId>(gridDiscretizationTuple_); }
354 template<std::
size_t i>
355 const auto&
gridView(Dune::index_constant<i> domainId)
const
359 template<std::
size_t i>
361 {
return *std::get<domainId>(gridVariablesTuple_); }
364 template<std::
size_t i>
366 {
return *std::get<domainId>(gridVariablesTuple_); }
374 {
return *jacobian_; }
378 {
return *residual_; }
382 {
return *prevSol_; }
389 { timeLoop_ = timeLoop; isStationaryProblem_ = !(
static_cast<bool>(timeLoop)); }
402 {
return isStationaryProblem_; }
407 template<std::
size_t i>
409 {
return LocalResidual<i>(std::get<domainId>(problemTuple_).get(), timeLoop_.get()); }
421 using namespace Dune::Hybrid;
422 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainI)
424 forEach(integralRange(Dune::Hybrid::size(jac[domainI])), [&](
const auto domainJ)
426 const auto pattern = this->getJacobianPattern_(domainI, domainJ);
427 pattern.exportIdx(jac[domainI][domainJ]);
437 using namespace Dune::Hybrid;
438 forEach(integralRange(Dune::Hybrid::size(res)), [&](
const auto domainId)
439 { res[domainId].resize(this->
numDofs(domainId)); });
443 void resetResidual_()
447 residual_ = std::make_shared<ResidualType>();
448 setResidualSize_(*residual_);
455 void resetJacobian_()
459 jacobian_ = std::make_shared<JacobianMatrix>();
461 setJacobianPattern_(*jacobian_);
468 void maybeComputeColors_()
470 if constexpr (CouplingManagerSupportsMultithreadedAssembly<CouplingManager>::value)
471 if (enableMultithreading_)
476 void checkAssemblerState_()
const
478 if (!isStationaryProblem_ && !prevSol_)
479 DUNE_THROW(Dune::InvalidStateException,
"Assembling instationary problem but previous solution was not set!");
481 if (isStationaryProblem_ && prevSol_)
482 DUNE_THROW(Dune::InvalidStateException,
"Assembling stationary problem but a previous solution was set."
483 <<
" Did you forget to set the timeLoop to make this problem instationary?");
486 template<std::
size_t i,
class JacRow,
class SubRes>
487 void assembleJacobianAndResidual_(Dune::index_constant<i> domainId, JacRow& jacRow, SubRes& subRes,
490 assemble_(domainId, [&](
const auto& element)
492 MultiDomainAssemblerSubDomainView view{*
this, domainId};
493 SubDomainAssembler<i> subDomainAssembler(view, element, curSol, *
couplingManager_);
494 subDomainAssembler.assembleJacobianAndResidual(jacRow, subRes, gridVariablesTuple_);
498 template<std::
size_t i,
class SubRes>
499 void assembleResidual_(Dune::index_constant<i> domainId, SubRes& subRes,
502 assemble_(domainId, [&](
const auto& element)
504 MultiDomainAssemblerSubDomainView view{*
this, domainId};
505 SubDomainAssembler<i> subDomainAssembler(view, element, curSol, *
couplingManager_);
506 subDomainAssembler.assembleResidual(subRes);
515 template<std::
size_t i,
class AssembleElementFunc>
516 void assemble_(Dune::index_constant<i> domainId, AssembleElementFunc&& assembleElement)
const
519 bool succeeded =
false;
524 if constexpr (CouplingManagerSupportsMultithreadedAssembly<CouplingManager>::value)
526 if (enableMultithreading_)
529 domainId, std::forward<AssembleElementFunc>(assembleElement)
538 for (
const auto& element : elements(
gridView(domainId)))
539 assembleElement(element);
545 catch (NumericalProblem &e)
547 std::cout <<
"rank " <<
gridView(domainId).comm().rank()
548 <<
" caught an exception while assembling:" << e.what()
554 if (
gridView(domainId).comm().size() > 1)
555 succeeded =
gridView(domainId).comm().min(succeeded);
559 DUNE_THROW(NumericalProblem,
"A process did not succeed in linearizing the system");
563 template<std::
size_t i, std::
size_t j,
typename std::enable_if_t<(i==j),
int> = 0>
564 Dune::MatrixIndexSet getJacobianPattern_(Dune::index_constant<i> domainI,
565 Dune::index_constant<j> domainJ)
const
574 template<std::
size_t i, std::
size_t j,
typename std::enable_if_t<(i!=j),
int> = 0>
575 Dune::MatrixIndexSet getJacobianPattern_(Dune::index_constant<i> domainI,
576 Dune::index_constant<j> domainJ)
const
584 template<std::
size_t i,
class JacRow,
class Res,
class GG,
class Sol>
585 void enforcePeriodicConstraints_(Dune::index_constant<i> domainI, JacRow& jacRow, Res& res,
const GG&
gridDiscretization,
const Sol& curSol)
const
591 if (m.first < m.second)
593 auto& jac = jacRow[domainI];
596 res[m.first] += res[m.second];
598 const auto end = jac[m.second].end();
599 for (
auto it = jac[m.second].begin(); it != end; ++it)
600 jac[m.first][it.index()] += (*it);
604 res[m.second] = curSol[m.second] - curSol[m.first];
607 auto setMatrixBlock = [] (
auto& matrixBlock,
double diagValue)
609 for (
int eIdx = 0; eIdx < matrixBlock.N(); ++eIdx)
610 matrixBlock[eIdx][eIdx] = diagValue;
613 for (
auto it = jac[m.second].begin(); it != end; ++it)
615 auto& matrixBlock = *it;
618 assert(matrixBlock.N() == matrixBlock.M());
619 if(it.index() == m.second)
620 setMatrixBlock(matrixBlock, 1.0);
622 if(it.index() == m.first)
623 setMatrixBlock(matrixBlock, -1.0);
627 using namespace Dune::Hybrid;
630 auto& jacCoupling = jacRow[couplingDomainId];
632 for (
auto it = jacCoupling[m.second].begin(); it != jacCoupling[m.second].end(); ++it)
633 jacCoupling[m.first][it.index()] += (*it);
635 for (
auto it = jacCoupling[m.second].begin(); it != jacCoupling[m.second].end(); ++it)
644 template<std::
size_t i,
class JacRow,
class Res,
class GG,
class Sol>
645 void enforceProblemConstraints_(Dune::index_constant<i> domainI, JacRow& jacRow, Res& res,
const GG&
gridDiscretization,
const Sol& curSol)
const
649 auto& jac = jacRow[domainI];
650 auto applyDirichletConstraint = [&] (
const auto& dofIdx,
655 (res)[dofIdx][eqIdx] = curSol[dofIdx][pvIdx] - values[pvIdx];
657 auto& row = jac[dofIdx];
658 for (
auto col = row.begin(); col != row.end(); ++col)
659 row[col.index()][eqIdx] = 0.0;
661 jac[dofIdx][dofIdx][eqIdx][pvIdx] = 1.0;
663 using namespace Dune::Hybrid;
666 auto& jacCoupling = jacRow[couplingDomainId];
668 auto& rowCoupling = jacCoupling[dofIdx];
669 for (
auto colCoupling = rowCoupling.begin(); colCoupling != rowCoupling.end(); ++colCoupling)
670 rowCoupling[colCoupling.index()][eqIdx] = 0.0;
675 for (
const auto& constraintData : this->
problem(domainI).constraints())
677 const auto& constraintInfo = constraintData.constraintInfo();
678 const auto& values = constraintData.values();
679 const auto dofIdx = constraintData.dofIndex();
681 for (
int eqIdx = 0; eqIdx < constraintInfo.size(); ++eqIdx)
683 if (constraintInfo.isConstraintEquation(eqIdx))
685 const auto pvIdx = constraintInfo.eqToPriVarIndex(eqIdx);
686 assert(0 <= pvIdx && pvIdx < constraintInfo.size());
687 applyDirichletConstraint(dofIdx, values, eqIdx, pvIdx);
695 template<std::
size_t i,
class Res,
class GG,
class Sol>
696 void enforcePeriodicConstraints_(Dune::index_constant<i> domainI, Res& res,
const GG&
gridDiscretization,
const Sol& curSol)
const
702 if (m.first < m.second)
705 res[m.first] += res[m.second];
708 res[m.second] = curSol[m.second] - curSol[m.first];
715 template<std::
size_t i,
class Res,
class GG,
class Sol>
716 void enforceProblemConstraints_(Dune::index_constant<i> domainI, Res& res,
const GG&
gridDiscretization,
const Sol& curSol)
const
720 for (
const auto& constraintData : this->
problem(domainI).constraints())
722 const auto& constraintInfo = constraintData.constraintInfo();
723 const auto& values = constraintData.values();
724 const auto dofIdx = constraintData.dofIndex();
725 for (
int eqIdx = 0; eqIdx < constraintInfo.size(); ++eqIdx)
727 if (constraintInfo.isConstraintEquation(eqIdx))
729 const auto pvIdx = constraintInfo.eqToPriVarIndex(eqIdx);
730 assert(0 <= pvIdx && pvIdx < constraintInfo.size());
731 res[dofIdx][eqIdx] = curSol[dofIdx][pvIdx] - values[pvIdx];
739 ProblemTuple problemTuple_;
742 GridDiscretizationTuple gridDiscretizationTuple_;
745 GridVariablesTuple gridVariablesTuple_;
748 std::shared_ptr<const TimeLoop> timeLoop_;
754 bool isStationaryProblem_;
757 std::shared_ptr<JacobianMatrix> jacobian_;
758 std::shared_ptr<ResidualType> residual_;
761 mutable bool warningIssued_;
764 bool enableMultithreading_ =
false;
Subdomain-specific views on multidomain assemblers.
Traits shared by the multi-domain assemblers.
The interface of the coupling manager for multi domain problems.
Definition multidomain/couplingmanager.hh:37
A linear system assembler (residual and Jacobian) for general schemes (FV, CVFE, FE,...
Definition multidomain/assembler.hh:62
typename MDTraits::ResidualVector ResidualType
Definition multidomain/assembler.hh:85
bool isStationaryProblem() const
Whether we are assembling a stationary or instationary problem.
Definition multidomain/assembler.hh:401
typename MDTraits::template SubDomain< id >::GridVariables GridVariables
Definition multidomain/assembler.hh:75
void setJacobianBuildMode(JacobianMatrix &jac) const
Sets the jacobian build mode.
Definition multidomain/assembler.hh:292
LocalResidual< i > localResidual(Dune::index_constant< i > domainId) const
Create a local residual object (used by the local assembler).
Definition multidomain/assembler.hh:408
GetPropType< SubDomainTypeTag< id >, Properties::GridGeometry > GridDiscretization
Definition multidomain/assembler.hh:78
void updateGridVariables(const SolutionVector &curSol)
Updates the grid variables with the given solution.
Definition multidomain/assembler.hh:321
ResidualType & residual()
the full residual vector
Definition multidomain/assembler.hh:377
void updateAfterGridAdaption()
Resizes jacobian and residual and recomputes colors.
Definition multidomain/assembler.hh:311
void setLinearSystem(std::shared_ptr< JacobianMatrix > A, std::shared_ptr< ResidualType > r)
Tells the assembler which jacobian and residual to use. This also resizes the containers to the requi...
Definition multidomain/assembler.hh:264
const GridVariables< i > & gridVariables(Dune::index_constant< i > domainId) const
the grid variables of domain i
Definition multidomain/assembler.hh:365
std::size_t numDofs(Dune::index_constant< i > domainId) const
the number of dof locations of domain i
Definition multidomain/assembler.hh:340
void setTimeManager(std::shared_ptr< const TimeLoop > timeLoop)
Set time loop for instationary problems.
Definition multidomain/assembler.hh:388
const auto & gridView(Dune::index_constant< i > domainId) const
the grid view of domain i
Definition multidomain/assembler.hh:355
void assembleResidual(ResidualType &r, const SolutionVector &curSol)
assemble a residual r
Definition multidomain/assembler.hh:237
typename MDTraits::SolutionVector SolutionVector
Definition multidomain/assembler.hh:84
std::shared_ptr< CouplingManager > couplingManager_
Definition multidomain/assembler.hh:413
void setPreviousSolution(const SolutionVector &u)
Sets the solution from which to start the time integration. Has to be called prior to assembly for ti...
Definition multidomain/assembler.hh:395
JacobianMatrix & jacobian()
the full Jacobian matrix
Definition multidomain/assembler.hh:373
typename MDTraits::Scalar Scalar
Definition multidomain/assembler.hh:69
const auto & gridDiscretization(Dune::index_constant< i > domainId) const
Definition multidomain/assembler.hh:350
MDTraits Traits
Definition multidomain/assembler.hh:67
typename MDTraits::JacobianMatrix JacobianMatrix
Definition multidomain/assembler.hh:83
void setLinearSystem()
The version without arguments uses the default constructor to create the jacobian and residual object...
Definition multidomain/assembler.hh:279
GridVariables< i > & gridVariables(Dune::index_constant< i > domainId)
Definition multidomain/assembler.hh:360
static constexpr bool isImplicit()
Returns true if the assembler considers implicit assembly.
Definition multidomain/assembler.hh:92
const SolutionVector & prevSol() const
Definition multidomain/assembler.hh:381
typename MDTraits::template SubDomain< id >::LocalResidual LocalResidual
Definition multidomain/assembler.hh:72
MultiDomainAssembler(ProblemTuple problem, GridDiscretizationTuple gridDiscretization, GridVariablesTuple gridVariables, std::shared_ptr< CouplingManager > couplingManager)
The constructor for stationary problems.
Definition multidomain/assembler.hh:152
CMType CouplingManager
Definition multidomain/assembler.hh:87
void resetTimeStep(const SolutionVector &curSol)
Resets the grid variables to the last time step.
Definition multidomain/assembler.hh:331
const auto & problem(Dune::index_constant< i > domainId) const
Definition multidomain/assembler.hh:345
const CouplingManager & couplingManager() const
Definition multidomain/assembler.hh:369
void assembleResidual(const SolutionVector &curSol)
compute the residuals using the internal residual
Definition multidomain/assembler.hh:230
typename MDTraits::template SubDomain< id >::Problem Problem
Definition multidomain/assembler.hh:81
MultiDomainAssembler(ProblemTuple problem, GridDiscretizationTuple gridDiscretization, GridVariablesTuple gridVariables, std::shared_ptr< CouplingManager > couplingManager, std::shared_ptr< const TimeLoop > timeLoop, const SolutionVector &prevSol)
The constructor for instationary problems.
Definition multidomain/assembler.hh:180
void assembleJacobianAndResidual(const SolutionVector &curSol)
Assembles the global Jacobian of the residual and the residual for the current solution.
Definition multidomain/assembler.hh:209
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
The cell-centered scheme multidomain local assembler.
Definition multidomain/subdomaincclocalassembler.hh:270
Manages the handling of time dependent problems.
Definition common/timeloop.hh:84
The default time loop for instationary simulations.
Definition common/timeloop.hh:139
Defines all properties used in Dumux.
Manages the handling of time dependent problems.
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.
A multidomain local assembler for Jacobian and residual contribution per element (cell-centered metho...
Definition cellcentered/mpfa/elementvolumevariables.hh:24
constexpr bool hasPeriodicDofMap()
Definition periodic.hh:24
constexpr bool hasSubProblemGlobalConstraints()
Definition assemblytraits.hh:30
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
const Scalar PengRobinsonMixture< Scalar, StaticParameters >::u
Definition pengrobinsonmixture.hh:138
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
Provides a helper class for nonoverlapping decomposition.
Type traits to detect periodicity support.
Type trait that is specialized for coupling manager supporting multithreaded assembly.
Definition assemblytraits.hh:43
An assembler for Jacobian and residual contribution per element (face-centered staggered methods) for...
Utilities for template meta programming.