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>
51template<
class T, std::size_t... I>
93template<
class MDTraits,
class CMType, DiffMethod diffMethod>
96 template<std::
size_t id>
97 using SubDomainTypeTag =
typename MDTraits::template SubDomain<id>::TypeTag;
102 using Scalar =
typename MDTraits::Scalar;
106 template<std::
size_t id>
109 template<std::
size_t id>
110 using GridVariables =
typename MDTraits::template SubDomain<id>::GridVariables;
112 template<std::
size_t id>
113 using GridGeometry =
typename MDTraits::template SubDomain<id>::GridGeometry;
115 template<std::
size_t id>
116 using Problem =
typename MDTraits::template SubDomain<id>::Problem;
126 using ProblemTuple =
typename MDTraits::template TupleOfSharedPtrConst<Problem>;
127 using GridGeometryTuple =
typename MDTraits::template TupleOfSharedPtrConst<GridGeometry>;
128 using GridVariablesTuple =
typename MDTraits::template TupleOfSharedPtr<GridVariables>;
132 template<std::
size_t id>
135 template<
class DiscretizationMethod, std::
size_t id>
136 struct SubDomainAssemblerType;
138 template<std::
size_t id>
139 struct SubDomainAssemblerType<DiscretizationMethods::CCTpfa, id>
144 template<std::
size_t id>
145 struct SubDomainAssemblerType<DiscretizationMethods::CCMpfa, id>
150 template<std::
size_t id,
class DM>
151 struct SubDomainAssemblerType<DiscretizationMethods::CVFE<DM>, id>
156 template<std::
size_t id>
157 using SubDomainAssembler =
typename SubDomainAssemblerType<typename GridGeometry<id>::DiscretizationMethod,
id>::type;
172 , timeSteppingMethod_(msMethod)
173 , problemTuple_(std::move(
problem))
178 std::cout <<
"Instantiated assembler for an instationary problem." << std::endl;
183 && getParam<bool>(
"Assembly.Multithreading",
true);
185 maybeComputeColors_();
197 spatialOperatorEvaluations_.back() = 0.0;
198 temporalOperatorEvaluations_.back() = 0.0;
200 if (stageParams_->size() != spatialOperatorEvaluations_.size())
201 DUNE_THROW(Dune::InvalidStateException,
"Wrong number of residuals");
203 using namespace Dune::Hybrid;
204 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
208 auto& jacRow = (*jacobian_)[domainId];
209 auto& spatial = spatialOperatorEvaluations_.back()[domainId];
210 auto& temporal = temporalOperatorEvaluations_.back()[domainId];
212 assemble_(domainId, [&](
const auto& element)
215 SubDomainAssembler<domainId()> subDomainAssembler(view, element, curSol, *
couplingManager_);
216 subDomainAssembler.assembleJacobianAndResidual(
217 jacRow, (*residual_)[domainId],
219 *stageParams_, temporal, spatial,
220 constrainedDofs_[domainId]
225 auto constantResidualComponent = (*residual_)[domainId];
226 constantResidualComponent = 0.0;
227 for (std::size_t k = 0; k < stageParams_->size()-1; ++k)
229 if (!stageParams_->skipTemporal(k))
230 constantResidualComponent.axpy(stageParams_->temporalWeight(k), temporalOperatorEvaluations_[k][domainId]);
231 if (!stageParams_->skipSpatial(k))
232 constantResidualComponent.axpy(stageParams_->spatialWeight(k), spatialOperatorEvaluations_[k][domainId]);
236 for (std::size_t i = 0; i < constantResidualComponent.size(); ++i)
237 for (std::size_t ii = 0; ii < constantResidualComponent[i].size(); ++ii)
238 (*residual_)[domainId][i][ii] += constrainedDofs_[domainId][i][ii] > 0.5 ? 0.0 : constantResidualComponent[i][ii];
244 { DUNE_THROW(Dune::NotImplemented,
"residual"); }
252 jacobian_ = std::make_shared<JacobianMatrix>();
253 residual_ = std::make_shared<ResidualType>();
255 setJacobianBuildMode_(*jacobian_);
256 setJacobianPattern_(*jacobian_);
257 setResidualSize_(*residual_);
265 using namespace Dune::Hybrid;
266 forEach(integralRange(Dune::Hybrid::size(gridVariablesTuple_)), [&](
const auto domainId)
267 { this->
gridVariables(domainId).update(curSol[domainId]); });
275 using namespace Dune::Hybrid;
276 forEach(integralRange(Dune::Hybrid::size(gridVariablesTuple_)), [&](
const auto domainId)
277 { this->
gridVariables(domainId).resetTimeStep(curSol[domainId]); });
281 template<std::
size_t i>
282 std::size_t
numDofs(Dune::index_constant<i> domainId)
const
283 {
return std::get<domainId>(gridGeometryTuple_)->numDofs(); }
286 template<std::
size_t i>
287 const auto&
problem(Dune::index_constant<i> domainId)
const
288 {
return *std::get<domainId>(problemTuple_); }
291 template<std::
size_t i>
293 {
return *std::get<domainId>(gridGeometryTuple_); }
296 template<std::
size_t i>
297 const auto&
gridView(Dune::index_constant<i> domainId)
const
301 template<std::
size_t i>
303 {
return *std::get<domainId>(gridVariablesTuple_); }
306 template<std::
size_t i>
308 {
return *std::get<domainId>(gridVariablesTuple_); }
316 {
return *jacobian_; }
320 {
return *residual_; }
324 {
return *prevSol_; }
329 template<std::
size_t i>
331 {
return {
LocalResidual<i>{std::get<domainId>(problemTuple_).get(),
nullptr} }; }
335 spatialOperatorEvaluations_.clear();
336 temporalOperatorEvaluations_.clear();
337 stageParams_.reset();
340 template<
class StageParams>
343 stageParams_ = std::move(params);
344 const auto curStage = stageParams_->size() - 1;
350 using namespace Dune::Hybrid;
351 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
353 setProblemTime_(*std::get<domainId>(problemTuple_), stageParams_->timeAtStage(curStage));
357 spatialOperatorEvaluations_.push_back(*residual_);
358 temporalOperatorEvaluations_.push_back(*residual_);
361 using namespace Dune::Hybrid;
362 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
364 auto& spatial = spatialOperatorEvaluations_.back()[domainId];
365 auto& temporal = temporalOperatorEvaluations_.back()[domainId];
366 assemble_(domainId, [&](
const auto& element)
369 SubDomainAssembler<domainId()> subDomainAssembler(view, element, x, *
couplingManager_);
370 subDomainAssembler.localResidual().spatialWeight(1.0);
371 subDomainAssembler.localResidual().temporalWeight(1.0);
372 subDomainAssembler.assembleCurrentResidual(spatial, temporal);
378 using namespace Dune::Hybrid;
379 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainId)
381 setProblemTime_(*std::get<domainId>(problemTuple_), stageParams_->timeAtStage(curStage));
385 spatialOperatorEvaluations_.push_back(*residual_);
386 temporalOperatorEvaluations_.push_back(*residual_);
394 {
return timeSteppingMethod_->implicit(); }
406 using namespace Dune::Hybrid;
407 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto i)
409 forEach(jac[i], [&](
auto& jacBlock)
411 using BlockType = std::decay_t<
decltype(jacBlock)>;
412 if (jacBlock.buildMode() == BlockType::BuildMode::unknown)
413 jacBlock.setBuildMode(BlockType::BuildMode::random);
414 else if (jacBlock.buildMode() != BlockType::BuildMode::random)
415 DUNE_THROW(Dune::NotImplemented,
"Only BCRS matrices with random build mode are supported at the moment");
425 using namespace Dune::Hybrid;
426 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](
const auto domainI)
428 forEach(integralRange(Dune::Hybrid::size(jac[domainI])), [&](
const auto domainJ)
430 const auto pattern = this->getJacobianPattern_(domainI, domainJ);
431 pattern.exportIdx(jac[domainI][domainJ]);
441 using namespace Dune::Hybrid;
442 forEach(integralRange(Dune::Hybrid::size(res)), [&](
const auto domainId)
443 { res[domainId].resize(this->
numDofs(domainId)); });
447 void resetResidual_()
451 residual_ = std::make_shared<ResidualType>();
452 setResidualSize_(*residual_);
455 setResidualSize_(constrainedDofs_);
458 constrainedDofs_ = 0.0;
462 void resetJacobian_()
466 jacobian_ = std::make_shared<JacobianMatrix>();
467 setJacobianBuildMode_(*jacobian_);
468 setJacobianPattern_(*jacobian_);
475 void maybeComputeColors_()
477 if constexpr (CouplingManagerSupportsMultithreadedAssembly<CouplingManager>::value)
478 if (enableMultithreading_)
482 template<std::
size_t i,
class SubRes>
483 void assembleResidual_(Dune::index_constant<i> domainId, SubRes& subRes,
486 DUNE_THROW(Dune::NotImplemented,
"assembleResidual_");
494 template<std::
size_t i,
class AssembleElementFunc>
495 void assemble_(Dune::index_constant<i> domainId, AssembleElementFunc&& assembleElement)
const
498 bool succeeded =
false;
503 if constexpr (CouplingManagerSupportsMultithreadedAssembly<CouplingManager>::value)
505 if (enableMultithreading_)
508 domainId, std::forward<AssembleElementFunc>(assembleElement)
517 for (
const auto& element : elements(
gridView(domainId)))
518 assembleElement(element);
524 catch (NumericalProblem &e)
526 std::cout <<
"rank " <<
gridView(domainId).comm().rank()
527 <<
" caught an exception while assembling:" << e.what()
533 if (
gridView(domainId).comm().size() > 1)
534 succeeded =
gridView(domainId).comm().min(succeeded);
538 DUNE_THROW(NumericalProblem,
"A process did not succeed in linearizing the system");
542 template<std::
size_t i, std::
size_t j,
typename std::enable_if_t<(i==j),
int> = 0>
543 Dune::MatrixIndexSet getJacobianPattern_(Dune::index_constant<i> domainI,
544 Dune::index_constant<j> domainJ)
const
547 if (timeSteppingMethod_->implicit())
549 auto pattern = getJacobianPattern<true>(gg);
555 auto pattern = getJacobianPattern<false>(gg);
562 template<std::
size_t i, std::
size_t j,
typename std::enable_if_t<(i!=j),
int> = 0>
563 Dune::MatrixIndexSet getJacobianPattern_(Dune::index_constant<i> domainI,
564 Dune::index_constant<j> domainJ)
const
566 if (timeSteppingMethod_->implicit())
580 void setProblemTime_(
const P& p,
const Scalar t)
581 { setProblemTimeImpl_(p, t, 0); }
584 auto setProblemTimeImpl_(
const P& p,
const Scalar t,
int) ->
decltype(p.setTime(0))
588 void setProblemTimeImpl_(
const P& p,
const Scalar t,
long)
591 std::shared_ptr<const Experimental::MultiStageMethod<Scalar>> timeSteppingMethod_;
592 std::vector<ResidualType> spatialOperatorEvaluations_;
593 std::vector<ResidualType> temporalOperatorEvaluations_;
595 std::shared_ptr<const StageParams> stageParams_;
598 ProblemTuple problemTuple_;
601 GridGeometryTuple gridGeometryTuple_;
604 GridVariablesTuple gridVariablesTuple_;
610 std::shared_ptr<JacobianMatrix> jacobian_;
611 std::shared_ptr<ResidualType> residual_;
614 bool enableMultithreading_ =
false;
Subdomain-specific views on multidomain assemblers.
Definition: multistagefvlocaloperator.hh:23
Abstract interface for one-step multi-stage method parameters in Shu/Osher form.
Definition: multistagemethods.hh:75
A linear system assembler (residual and Jacobian) for finite volume schemes (box, tpfa,...
Definition: multistagemultidomainfvassembler.hh:95
MDTraits Traits
Definition: multistagemultidomainfvassembler.hh:100
typename MDTraits::SolutionVector SolutionVector
Definition: multistagemultidomainfvassembler.hh:119
GetPropType< SubDomainTypeTag< id >, Properties::LocalResidual > LocalResidual
TODO get rid of this GetPropType.
Definition: multistagemultidomainfvassembler.hh:107
typename MDTraits::JacobianMatrix JacobianMatrix
Definition: multistagemultidomainfvassembler.hh:118
typename MDTraits::Scalar Scalar
Definition: multistagemultidomainfvassembler.hh:102
bool isStationaryProblem() const
TODO get rid of this (called by Newton but shouldn't be necessary)
Definition: multistagemultidomainfvassembler.hh:390
void assembleJacobianAndResidual(const SolutionVector &curSol)
Assembles the global Jacobian of the residual and the residual for the current solution.
Definition: multistagemultidomainfvassembler.hh:192
const GridVariables< i > & gridVariables(Dune::index_constant< i > domainId) const
the grid variables of domain i
Definition: multistagemultidomainfvassembler.hh:307
typename MDTraits::template SubDomain< id >::GridGeometry GridGeometry
Definition: multistagemultidomainfvassembler.hh:113
void clearStages()
Definition: multistagemultidomainfvassembler.hh:333
MultiStageFVLocalOperator< LocalResidual< i > > localResidual(Dune::index_constant< i > domainId) const
Create a local residual object (used by the local assembler)
Definition: multistagemultidomainfvassembler.hh:330
typename MDTraits::template SubDomain< id >::Problem Problem
Definition: multistagemultidomainfvassembler.hh:116
bool isImplicit() const
Definition: multistagemultidomainfvassembler.hh:393
std::shared_ptr< CouplingManager > couplingManager_
the coupling manager coupling the sub domains
Definition: multistagemultidomainfvassembler.hh:398
typename MDTraits::ResidualVector ResidualType
Definition: multistagemultidomainfvassembler.hh:120
const CouplingManager & couplingManager() const
the coupling manager
Definition: multistagemultidomainfvassembler.hh:311
const auto & gridView(Dune::index_constant< i > domainId) const
the grid view of domain i
Definition: multistagemultidomainfvassembler.hh:297
ResidualType & residual()
the full residual vector
Definition: multistagemultidomainfvassembler.hh:319
const SolutionVector & prevSol() const
the solution before time integration
Definition: multistagemultidomainfvassembler.hh:323
void setLinearSystem()
The version without arguments uses the default constructor to create the jacobian and residual object...
Definition: multistagemultidomainfvassembler.hh:250
void resetTimeStep(const SolutionVector &curSol)
Resets the grid variables to the last time step.
Definition: multistagemultidomainfvassembler.hh:273
typename MDTraits::template SubDomain< id >::GridVariables GridVariables
Definition: multistagemultidomainfvassembler.hh:110
CMType CouplingManager
Definition: multistagemultidomainfvassembler.hh:122
std::size_t numDofs(Dune::index_constant< i > domainId) const
the number of dof locations of domain i
Definition: multistagemultidomainfvassembler.hh:282
void updateGridVariables(const SolutionVector &curSol)
Updates the grid variables with the given solution.
Definition: multistagemultidomainfvassembler.hh:263
const auto & problem(Dune::index_constant< i > domainId) const
the problem of domain i
Definition: multistagemultidomainfvassembler.hh:287
const auto & gridGeometry(Dune::index_constant< i > domainId) const
the finite volume grid geometry of domain i
Definition: multistagemultidomainfvassembler.hh:292
void prepareStage(SolutionVector &x, StageParams params)
Definition: multistagemultidomainfvassembler.hh:341
JacobianMatrix & jacobian()
the full Jacobian matrix
Definition: multistagemultidomainfvassembler.hh:315
GridVariables< i > & gridVariables(Dune::index_constant< i > domainId)
the grid variables of domain i
Definition: multistagemultidomainfvassembler.hh:302
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:165
void assembleResidual(const SolutionVector &curSol)
compute the residuals using the internal residual
Definition: multistagemultidomainfvassembler.hh:243
Data object for the parameters of a given stage.
Definition: multistagetimestepper.hh:29
The cell-centered scheme multidomain local assembler.
Definition: experimental/assembly/subdomaincclocalassembler.hh:195
The CVFE scheme multidomain local assembler.
Definition: experimental/assembly/subdomaincvfelocalassembler.hh:206
Subdomain-specific view on a multidomain assembler. Allows retrieval of sub-domain specific objects w...
Definition: assemblerview.hh:31
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
constexpr bool isSerial()
Checking whether the backend is serial.
Definition: multithreading.hh:45
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: experimental/assembly/cclocalassembler.hh:36
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
Provides a helper class for nonoverlapping decomposition.
Type trait that is specialized for coupling manager supporting multithreaded assembly.
Definition: multistagemultidomainfvassembler.hh:78
Utilities for template meta programming.