14#ifndef DUMUX_MULTIDOMAIN_FV_ASSEMBLER_HH
15#define DUMUX_MULTIDOMAIN_FV_ASSEMBLER_HH
20#include <dune/common/hybridutilities.hh>
21#include <dune/istl/matrixindexset.hh>
50template<
class T, std::size_t... I>
84template<
class MDTraits,
class CMType, DiffMethod diffMethod,
bool useImplicitAssembly = true>
87 template<std::
size_t id>
88 using SubDomainTypeTag =
typename MDTraits::template SubDomain<id>::TypeTag;
93 using Scalar =
typename MDTraits::Scalar;
95 template<std::
size_t id>
96 using LocalResidual =
typename MDTraits::template SubDomain<id>::LocalResidual;
98 template<std::
size_t id>
99 using GridVariables =
typename MDTraits::template SubDomain<id>::GridVariables;
101 template<std::
size_t id>
102 using GridGeometry =
typename MDTraits::template SubDomain<id>::GridGeometry;
104 template<std::
size_t id>
105 using Problem =
typename MDTraits::template SubDomain<id>::Problem;
117 {
return useImplicitAssembly; }
121 using ProblemTuple =
typename MDTraits::template TupleOfSharedPtrConst<Problem>;
122 using GridGeometryTuple =
typename MDTraits::template TupleOfSharedPtrConst<GridGeometry>;
123 using GridVariablesTuple =
typename MDTraits::template TupleOfSharedPtr<GridVariables>;
128 template<std::
size_t id>
131 template<
class DiscretizationMethod, std::
size_t id>
132 struct SubDomainAssemblerType;
134 template<std::
size_t id>
140 template<std::
size_t id>
141 struct SubDomainAssemblerType<DiscretizationMethods::CCMpfa, id>
143 using type = SubDomainCCLocalAssembler<id, SubDomainTypeTag<id>, SubDomainAssemblerView<id>, diffMethod,
isImplicit()>;
146 template<std::
size_t id,
class DM>
147 struct SubDomainAssemblerType<DiscretizationMethods::CVFE<DM>, id>
149 using type = SubDomainCVFELocalAssembler<id, SubDomainTypeTag<id>, SubDomainAssemblerView<id>, diffMethod,
isImplicit()>;
152 template<std::
size_t id>
153 struct SubDomainAssemblerType<DiscretizationMethods::Staggered, id>
155 using type = SubDomainStaggeredLocalAssembler<id, SubDomainTypeTag<id>, SubDomainAssemblerView<id>, diffMethod,
isImplicit()>;
158 template<std::
size_t id>
159 struct SubDomainAssemblerType<DiscretizationMethods::FCStaggered, id>
161 using type = SubDomainFaceCenteredLocalAssembler<id, SubDomainTypeTag<id>, SubDomainAssemblerView<id>, diffMethod,
isImplicit()>;
164 template<std::
size_t id>
165 using SubDomainAssembler =
typename SubDomainAssemblerType<typename GridGeometry<id>::DiscretizationMethod,
id>::type;
180 , problemTuple_(std::move(
problem))
184 , isStationaryProblem_(true)
185 , warningIssued_(false)
187 static_assert(
isImplicit(),
"Explicit assembler for stationary problem doesn't make sense!");
188 std::cout <<
"Instantiated assembler for a stationary problem." << std::endl;
195 maybeComputeColors_();
207 std::shared_ptr<const TimeLoop> timeLoop,
210 , problemTuple_(std::move(
problem))
213 , timeLoop_(timeLoop)
215 , isStationaryProblem_(false)
216 , warningIssued_(false)
218 std::cout <<
"Instantiated assembler for an instationary problem." << std::endl;
225 maybeComputeColors_();
234 checkAssemblerState_();
238 using namespace Dune::Hybrid;
239 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
241 auto& jacRow = (*jacobian_)[domainId];
242 auto& subRes = (*residual_)[domainId];
243 this->assembleJacobianAndResidual_(domainId, jacRow, subRes, curSol);
245 const auto gridGeometry = std::get<domainId>(gridGeometryTuple_);
246 enforcePeriodicConstraints_(domainId, jacRow, subRes, *
gridGeometry, curSol[domainId]);
262 checkAssemblerState_();
267 using namespace Dune::Hybrid;
268 forEach(integralRange(Dune::Hybrid::size(r)), [&](
const auto domainId)
270 auto& subRes = r[domainId];
271 this->assembleResidual_(domainId, subRes, curSol);
281 std::shared_ptr<ResidualType> r)
287 setJacobianPattern_(*jacobian_);
288 setResidualSize_(*residual_);
297 jacobian_ = std::make_shared<JacobianMatrix>();
298 residual_ = std::make_shared<ResidualType>();
301 setJacobianPattern_(*jacobian_);
302 setResidualSize_(*residual_);
310 using namespace Dune::Hybrid;
311 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto i)
313 forEach(jac[i], [&](
auto& jacBlock)
315 using BlockType = std::decay_t<
decltype(jacBlock)>;
316 if (jacBlock.buildMode() == BlockType::BuildMode::unknown)
317 jacBlock.setBuildMode(BlockType::BuildMode::random);
318 else if (jacBlock.buildMode() != BlockType::BuildMode::random)
319 DUNE_THROW(Dune::NotImplemented,
"Only BCRS matrices with random build mode are supported at the moment");
329 setJacobianPattern_(*jacobian_);
330 setResidualSize_(*residual_);
331 maybeComputeColors_();
339 using namespace Dune::Hybrid;
340 forEach(integralRange(Dune::Hybrid::size(gridVariablesTuple_)), [&](
const auto domainId)
341 { this->
gridVariables(domainId).update(curSol[domainId]); });
349 using namespace Dune::Hybrid;
350 forEach(integralRange(Dune::Hybrid::size(gridVariablesTuple_)), [&](
const auto domainId)
351 { this->
gridVariables(domainId).resetTimeStep(curSol[domainId]); });
355 template<std::
size_t i>
356 std::size_t
numDofs(Dune::index_constant<i> domainId)
const
357 {
return std::get<domainId>(gridGeometryTuple_)->numDofs(); }
360 template<std::
size_t i>
361 const auto&
problem(Dune::index_constant<i> domainId)
const
362 {
return *std::get<domainId>(problemTuple_); }
365 template<std::
size_t i>
367 {
return *std::get<domainId>(gridGeometryTuple_); }
370 template<std::
size_t i>
371 const auto&
gridView(Dune::index_constant<i> domainId)
const
375 template<std::
size_t i>
377 {
return *std::get<domainId>(gridVariablesTuple_); }
380 template<std::
size_t i>
382 {
return *std::get<domainId>(gridVariablesTuple_); }
390 {
return *jacobian_; }
394 {
return *residual_; }
398 {
return *prevSol_; }
405 { timeLoop_ = timeLoop; isStationaryProblem_ = !(
static_cast<bool>(timeLoop)); }
418 {
return isStationaryProblem_; }
423 template<std::
size_t i>
425 {
return LocalResidual<i>(std::get<domainId>(problemTuple_).get(), timeLoop_.get()); }
437 using namespace Dune::Hybrid;
438 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainI)
440 forEach(integralRange(Dune::Hybrid::size(jac[domainI])), [&](
const auto domainJ)
442 const auto pattern = this->getJacobianPattern_(domainI, domainJ);
443 pattern.exportIdx(jac[domainI][domainJ]);
453 using namespace Dune::Hybrid;
454 forEach(integralRange(Dune::Hybrid::size(res)), [&](
const auto domainId)
455 { res[domainId].resize(this->
numDofs(domainId)); });
459 void resetResidual_()
463 residual_ = std::make_shared<ResidualType>();
464 setResidualSize_(*residual_);
471 void resetJacobian_()
475 jacobian_ = std::make_shared<JacobianMatrix>();
477 setJacobianPattern_(*jacobian_);
484 void maybeComputeColors_()
486 if constexpr (CouplingManagerSupportsMultithreadedAssembly<CouplingManager>::value)
487 if (enableMultithreading_)
492 void checkAssemblerState_()
const
494 if (!isStationaryProblem_ && !prevSol_)
495 DUNE_THROW(Dune::InvalidStateException,
"Assembling instationary problem but previous solution was not set!");
497 if (isStationaryProblem_ && prevSol_)
498 DUNE_THROW(Dune::InvalidStateException,
"Assembling stationary problem but a previous solution was set."
499 <<
" Did you forget to set the timeLoop to make this problem instationary?");
502 template<std::
size_t i,
class JacRow,
class SubRes>
503 void assembleJacobianAndResidual_(Dune::index_constant<i> domainId, JacRow& jacRow, SubRes& subRes,
506 assemble_(domainId, [&](
const auto& element)
508 MultiDomainAssemblerSubDomainView view{*
this, domainId};
509 SubDomainAssembler<i> subDomainAssembler(view, element, curSol, *
couplingManager_);
510 subDomainAssembler.assembleJacobianAndResidual(jacRow, subRes, gridVariablesTuple_);
514 template<std::
size_t i,
class SubRes>
515 void assembleResidual_(Dune::index_constant<i> domainId, SubRes& subRes,
518 assemble_(domainId, [&](
const auto& element)
520 MultiDomainAssemblerSubDomainView view{*
this, domainId};
521 SubDomainAssembler<i> subDomainAssembler(view, element, curSol, *
couplingManager_);
522 subDomainAssembler.assembleResidual(subRes);
531 template<std::
size_t i,
class AssembleElementFunc>
532 void assemble_(Dune::index_constant<i> domainId, AssembleElementFunc&& assembleElement)
const
535 bool succeeded =
false;
540 if constexpr (CouplingManagerSupportsMultithreadedAssembly<CouplingManager>::value)
542 if (enableMultithreading_)
545 domainId, std::forward<AssembleElementFunc>(assembleElement)
554 for (
const auto& element : elements(
gridView(domainId)))
555 assembleElement(element);
561 catch (NumericalProblem &e)
563 std::cout <<
"rank " <<
gridView(domainId).comm().rank()
564 <<
" caught an exception while assembling:" << e.what()
570 if (
gridView(domainId).comm().size() > 1)
571 succeeded =
gridView(domainId).comm().min(succeeded);
575 DUNE_THROW(NumericalProblem,
"A process did not succeed in linearizing the system");
579 template<std::
size_t i, std::
size_t j,
typename std::enable_if_t<(i==j),
int> = 0>
580 Dune::MatrixIndexSet getJacobianPattern_(Dune::index_constant<i> domainI,
581 Dune::index_constant<j> domainJ)
const
590 template<std::
size_t i, std::
size_t j,
typename std::enable_if_t<(i!=j),
int> = 0>
591 Dune::MatrixIndexSet getJacobianPattern_(Dune::index_constant<i> domainI,
592 Dune::index_constant<j> domainJ)
const
600 template<std::
size_t i,
class JacRow,
class Res,
class GG,
class Sol>
601 void enforcePeriodicConstraints_(Dune::index_constant<i> domainI, JacRow& jacRow, Res& res,
const GG&
gridGeometry,
const Sol& curSol)
607 if (m.first < m.second)
609 auto& jac = jacRow[domainI];
612 res[m.first] += res[m.second];
614 const auto end = jac[m.second].end();
615 for (
auto it = jac[m.second].begin(); it != end; ++it)
616 jac[m.first][it.index()] += (*it);
620 res[m.second] = curSol[m.second] - curSol[m.first];
623 auto setMatrixBlock = [] (
auto& matrixBlock,
double diagValue)
625 for (
int eIdx = 0; eIdx < matrixBlock.N(); ++eIdx)
626 matrixBlock[eIdx][eIdx] = diagValue;
629 for (
auto it = jac[m.second].begin(); it != end; ++it)
631 auto& matrixBlock = *it;
634 assert(matrixBlock.N() == matrixBlock.M());
635 if(it.index() == m.second)
636 setMatrixBlock(matrixBlock, 1.0);
638 if(it.index() == m.first)
639 setMatrixBlock(matrixBlock, -1.0);
643 using namespace Dune::Hybrid;
646 auto& jacCoupling = jacRow[couplingDomainId];
648 for (
auto it = jacCoupling[m.second].begin(); it != jacCoupling[m.second].end(); ++it)
649 jacCoupling[m.first][it.index()] += (*it);
651 for (
auto it = jacCoupling[m.second].begin(); it != jacCoupling[m.second].end(); ++it)
660 ProblemTuple problemTuple_;
663 GridGeometryTuple gridGeometryTuple_;
666 GridVariablesTuple gridVariablesTuple_;
669 std::shared_ptr<const TimeLoop> timeLoop_;
675 bool isStationaryProblem_;
678 std::shared_ptr<JacobianMatrix> jacobian_;
679 std::shared_ptr<ResidualType> residual_;
682 mutable bool warningIssued_;
685 bool enableMultithreading_ =
false;
Subdomain-specific views on multidomain assemblers.
The interface of the coupling manager for multi domain problems.
Definition multidomain/couplingmanager.hh:37
Subdomain-specific view on a multidomain assembler. Allows retrieval of sub-domain specific objects w...
Definition assemblerview.hh:31
A linear system assembler (residual and Jacobian) for finite volume schemes (box, tpfa,...
Definition multidomain/fvassembler.hh:86
std::size_t numDofs(Dune::index_constant< i > domainId) const
the number of dof locations of domain i
Definition multidomain/fvassembler.hh:356
void updateGridVariables(const SolutionVector &curSol)
Updates the grid variables with the given solution.
Definition multidomain/fvassembler.hh:337
void updateAfterGridAdaption()
Resizes jacobian and residual and recomputes colors.
Definition multidomain/fvassembler.hh:327
typename StaggeredMultiDomainTraits< TypeTag, TypeTag >::SolutionVector SolutionVector
Definition multidomain/fvassembler.hh:108
typename StaggeredMultiDomainTraits< TypeTag, TypeTag >::template SubDomain< id >::Problem Problem
Definition multidomain/fvassembler.hh:105
JacobianMatrix & jacobian()
the full Jacobian matrix
Definition multidomain/fvassembler.hh:389
static constexpr bool isImplicit()
Returns true if the assembler considers implicit assembly.
Definition multidomain/fvassembler.hh:116
void assembleResidual(ResidualType &r, const SolutionVector &curSol)
assemble a residual r
Definition multidomain/fvassembler.hh:258
typename StaggeredMultiDomainTraits< TypeTag, TypeTag >::JacobianMatrix JacobianMatrix
Definition multidomain/fvassembler.hh:107
StaggeredCouplingManager< StaggeredMultiDomainTraits< TypeTag, TypeTag > > CouplingManager
Definition multidomain/fvassembler.hh:111
void assembleResidual(const SolutionVector &curSol)
compute the residuals using the internal residual
Definition multidomain/fvassembler.hh:251
void resetTimeStep(const SolutionVector &curSol)
Resets the grid variables to the last time step.
Definition multidomain/fvassembler.hh:347
const GridVariables< i > & gridVariables(Dune::index_constant< i > domainId) const
the grid variables of domain i
Definition multidomain/fvassembler.hh:381
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/fvassembler.hh:411
typename StaggeredMultiDomainTraits< TypeTag, TypeTag >::template SubDomain< id >::GridVariables GridVariables
Definition multidomain/fvassembler.hh:99
const auto & gridGeometry(Dune::index_constant< i > domainId) const
Definition multidomain/fvassembler.hh:366
void setLinearSystem()
The version without arguments uses the default constructor to create the jacobian and residual object...
Definition multidomain/fvassembler.hh:295
const auto & gridView(Dune::index_constant< i > domainId) const
the grid view of domain i
Definition multidomain/fvassembler.hh:371
typename StaggeredMultiDomainTraits< TypeTag, TypeTag >::template SubDomain< id >::GridGeometry GridGeometry
Definition multidomain/fvassembler.hh:102
const CouplingManager & couplingManager() const
Definition multidomain/fvassembler.hh:385
void setTimeManager(std::shared_ptr< const TimeLoop > timeLoop)
Set time loop for instationary problems.
Definition multidomain/fvassembler.hh:404
const SolutionVector & prevSol() const
Definition multidomain/fvassembler.hh:397
GridVariables< i > & gridVariables(Dune::index_constant< i > domainId)
Definition multidomain/fvassembler.hh:376
std::shared_ptr< CouplingManager > couplingManager_
Definition multidomain/fvassembler.hh:429
StaggeredMultiDomainTraits< TypeTag, TypeTag > Traits
Definition multidomain/fvassembler.hh:91
MultiDomainFVAssembler(ProblemTuple problem, GridGeometryTuple gridGeometry, GridVariablesTuple gridVariables, std::shared_ptr< CouplingManager > couplingManager, std::shared_ptr< const TimeLoop > timeLoop, const SolutionVector &prevSol)
The constructor for instationary problems.
Definition multidomain/fvassembler.hh:203
void setJacobianBuildMode(JacobianMatrix &jac) const
Sets the jacobian build mode.
Definition multidomain/fvassembler.hh:308
typename StaggeredMultiDomainTraits< TypeTag, TypeTag >::template SubDomain< id >::LocalResidual LocalResidual
Definition multidomain/fvassembler.hh:96
LocalResidual< i > localResidual(Dune::index_constant< i > domainId) const
Create a local residual object (used by the local assembler)
Definition multidomain/fvassembler.hh:424
const auto & problem(Dune::index_constant< i > domainId) const
Definition multidomain/fvassembler.hh:361
typename StaggeredMultiDomainTraits< TypeTag, TypeTag >::ResidualVector ResidualType
Definition multidomain/fvassembler.hh:109
MultiDomainFVAssembler(ProblemTuple problem, GridGeometryTuple gridGeometry, GridVariablesTuple gridVariables, std::shared_ptr< CouplingManager > couplingManager)
The constructor for stationary problems.
Definition multidomain/fvassembler.hh:175
void assembleJacobianAndResidual(const SolutionVector &curSol)
Assembles the global Jacobian of the residual and the residual for the current solution.
Definition multidomain/fvassembler.hh:232
bool isStationaryProblem() const
Whether we are assembling a stationary or instationary problem.
Definition multidomain/fvassembler.hh:417
typename StaggeredMultiDomainTraits< TypeTag, TypeTag >::Scalar Scalar
Definition multidomain/fvassembler.hh:93
ResidualType & residual()
the full residual vector
Definition multidomain/fvassembler.hh:393
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/fvassembler.hh:280
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:30
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:139
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...
An assembler for Jacobian and residual contribution per element (CVFE methods) for multidomain proble...
constexpr bool hasPeriodicDofMap()
Definition periodic.hh:24
Definition multistagemultidomainfvassembler.hh:49
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
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 multistagemultidomainfvassembler.hh:78
An assembler for Jacobian and residual contribution per element (face-centered staggered methods) for...
A multidomain assembler for Jacobian and residual contribution per element (staggered method)
Utilities for template meta programming.