28#ifndef EWOMS_FV_BASE_LINEARIZER_HH
29#define EWOMS_FV_BASE_LINEARIZER_HH
31#include <dune/common/fmatrix.hh>
32#include <dune/common/fvector.hh>
33#include <dune/common/version.hh>
35#include <dune/grid/common/gridenums.hh>
37#include <opm/common/Exceptions.hpp>
38#include <opm/common/TimingMacros.hpp>
40#include <opm/grid/utility/SparseTable.hpp>
42#include <opm/material/common/MathToolbox.hpp>
64template<
class TypeTag>
65class EcfvDiscretization;
76template<
class TypeTag>
101 using Toolbox = MathToolbox<Evaluation>;
103 using Element =
typename GridView::template Codim<0>::Entity;
104 using ElementIterator =
typename GridView::template Codim<0>::Iterator;
106 using Vector = GlobalEqVector;
108 using IstlMatrix =
typename SparseMatrixAdapter::IstlMatrix;
110 enum { numEq = getPropValue<TypeTag, Properties::NumEq>() };
111 enum { historySize = getPropValue<TypeTag, Properties::TimeDiscHistorySize>() };
113 using MatrixBlock =
typename SparseMatrixAdapter::MatrixBlock;
114 using VectorBlock = Dune::FieldVector<Scalar, numEq>;
116 static constexpr bool linearizeNonLocalElements = getPropValue<TypeTag, Properties::LinearizeNonLocalElements>();
143 simulatorPtr_ = &simulator;
146 fullDomain_ = std::make_unique<FullDomain>(simulator.
gridView());
191 template <
class SubDomainType>
199 initFirstIteration_();
203 if (isNlddLocalSolve) {
215 catch (
const std::exception& e)
217 std::cout <<
"rank " << simulator_().
gridView().comm().rank()
218 <<
" caught an exception while linearizing:" << e.what()
219 <<
"\n" << std::flush;
224 std::cout <<
"rank " << simulator_().
gridView().comm().rank()
225 <<
" caught an exception while linearizing"
226 <<
"\n" << std::flush;
229 succeeded = simulator_().
gridView().comm().min(succeeded);
232 throw NumericalProblem(
"A process did not succeed in linearizing the system");
237 { jacobian_->finalize(); }
249 auto& model = model_();
250 const auto& comm = simulator_().
gridView().comm();
251 for (
unsigned auxModIdx = 0; auxModIdx < model.numAuxiliaryModules(); ++auxModIdx) {
252 bool succeeded =
true;
254 model.auxiliaryModule(auxModIdx)->linearize(*jacobian_, residual_);
256 catch (
const std::exception& e) {
259 std::cout <<
"rank " << simulator_().
gridView().comm().rank()
260 <<
" caught an exception while linearizing:" << e.what()
261 <<
"\n" << std::flush;
264 succeeded = comm.min(succeeded);
267 throw NumericalProblem(
"linearization of an auxiliary equation failed");
276 {
return *jacobian_; }
279 {
return *jacobian_; }
285 {
return residual_; }
288 {
return residual_; }
320 void exportVector(GlobalEqVector &x,
const char *tag=
"",
const char *name=
"export/x")
322 printf(
"n = %lu\n",x.dim());
337 linearizationType_ = linearizationType;
341 {
return linearizationType_; }
364 {
return constraintsMap_; }
372 {
return flowsInfo_; }
380 {
return floresInfo_; }
382 template <
class SubDomainType>
386 initFirstIteration_();
390 using GridViewType =
decltype(domain.view);
401 const Element& elem = *elemIt;
402 ElementContext& elemCtx = *elementCtx_[threadId];
403 elemCtx.updatePrimaryStencil(elem);
405 for (
unsigned primaryDofIdx = 0;
406 primaryDofIdx < elemCtx.numPrimaryDof(0);
409 const unsigned globI = elemCtx.globalSpaceIndex(primaryDofIdx, 0);
410 residual_[globI] = 0.0;
411 jacobian_->clearRow(globI, 0.0);
419 {
return *simulatorPtr_; }
421 const Simulator& simulator_()
const
422 {
return *simulatorPtr_; }
425 {
return simulator_().
problem(); }
427 const Problem& problem_()
const
428 {
return simulator_().
problem(); }
431 {
return simulator_().
model(); }
433 const Model& model_()
const
434 {
return simulator_().
model(); }
436 const GridView& gridView_()
const
437 {
return problem_().gridView(); }
439 const ElementMapper& elementMapper_()
const
440 {
return model_().elementMapper(); }
442 const DofMapper& dofMapper_()
const
443 {
return model_().dofMapper(); }
445 void initFirstIteration_()
451 residual_.resize(model_().numTotalDof());
458 elementCtx_.push_back(std::make_unique<ElementContext>(simulator_()));
465 const auto& model = model_();
466 Stencil stencil(gridView_(), model_().dofMapper());
470 sparsityPattern_.clear();
471 sparsityPattern_.resize(model.numTotalDof());
473 for (
const auto& elem : elements(gridView_())) {
474 stencil.update(elem);
476 for (
unsigned primaryDofIdx = 0; primaryDofIdx < stencil.numPrimaryDof(); ++primaryDofIdx) {
477 const unsigned myIdx = stencil.globalSpaceIndex(primaryDofIdx);
479 for (
unsigned dofIdx = 0; dofIdx < stencil.numDof(); ++dofIdx) {
480 const unsigned neighborIdx = stencil.globalSpaceIndex(dofIdx);
481 sparsityPattern_[myIdx].insert(neighborIdx);
488 const std::size_t numAuxMod = model.numAuxiliaryModules();
489 for (
unsigned auxModIdx = 0; auxModIdx < numAuxMod; ++auxModIdx) {
490 model.auxiliaryModule(auxModIdx)->addNeighbors(sparsityPattern_);
494 jacobian_ = std::make_unique<SparseMatrixAdapter>(simulator_());
497 jacobian_->reserve(sparsityPattern_);
510 void updateConstraintsMap_()
512 if (!enableConstraints_()) {
517 constraintsMap_.clear();
520 ThreadedEntityIterator<GridView, 0> threadedElemIt(gridView_());
526 ElementIterator elemIt = threadedElemIt.beginParallel();
527 for (; !threadedElemIt.isFinished(elemIt); elemIt = threadedElemIt.increment()) {
530 const Element& elem = *elemIt;
531 ElementContext& elemCtx = *elementCtx_[threadId];
532 elemCtx.updateStencil(elem);
536 for (
unsigned primaryDofIdx = 0;
537 primaryDofIdx < elemCtx.numPrimaryDof(0);
540 Constraints constraints;
541 elemCtx.problem().constraints(constraints,
545 if (constraints.isActive()) {
546 const unsigned globI = elemCtx.globalSpaceIndex(primaryDofIdx, 0);
547 constraintsMap_[globI] = constraints;
556 template <
class SubDomainType>
557 void linearize_(
const SubDomainType& domain)
559 OPM_TIMEBLOCK(linearize_);
568 if (model_().newtonMethod().numIterations() == 0) {
569 updateConstraintsMap_();
572 applyConstraintsToSolution_();
577 std::mutex exceptionLock;
581 std::exception_ptr exceptionPtr =
nullptr;
584 using GridViewType =
decltype(domain.view);
585 ThreadedEntityIterator<GridViewType, 0> threadedElemIt(domain.view);
590 auto elemIt = threadedElemIt.beginParallel();
591 auto nextElemIt = elemIt;
593 for (; !threadedElemIt.isFinished(elemIt); elemIt = nextElemIt) {
596 nextElemIt = threadedElemIt.increment();
597 if (!threadedElemIt.isFinished(nextElemIt)) {
598 const auto& nextElem = *nextElemIt;
599 if (linearizeNonLocalElements ||
600 nextElem.partitionType() == Dune::InteriorEntity)
602 model_().prefetch(nextElem);
603 problem_().prefetch(nextElem);
607 const auto& elem = *elemIt;
608 if (!linearizeNonLocalElements && elem.partitionType() != Dune::InteriorEntity) {
612 linearizeElement_(elem);
625 std::lock_guard<std::mutex> take(exceptionLock);
626 exceptionPtr = std::current_exception();
627 threadedElemIt.setFinished();
635 std::rethrow_exception(exceptionPtr);
638 applyConstraintsToLinearization_();
642 template <
class ElementType>
647 ElementContext& elementCtx = *elementCtx_[threadId];
648 auto& localLinearizer = model_().localLinearizer(threadId);
651 localLinearizer.linearize(elementCtx, elem);
654 if (getPropValue<TypeTag, Properties::UseLinearizationLock>()) {
655 globalMatrixMutex_.lock();
658 const std::size_t numPrimaryDof = elementCtx.numPrimaryDof(0);
659 for (
unsigned primaryDofIdx = 0; primaryDofIdx < numPrimaryDof; ++primaryDofIdx) {
660 const unsigned globI = elementCtx.globalSpaceIndex(primaryDofIdx, 0);
663 residual_[globI] += localLinearizer.residual(primaryDofIdx);
666 for (
unsigned dofIdx = 0; dofIdx < elementCtx.numDof(0); ++dofIdx) {
667 const unsigned globJ = elementCtx.globalSpaceIndex(dofIdx, 0);
669 jacobian_->addToBlock(globJ, globI, localLinearizer.jacobian(dofIdx, primaryDofIdx));
673 if (getPropValue<TypeTag, Properties::UseLinearizationLock>()) {
674 globalMatrixMutex_.unlock();
680 void applyConstraintsToSolution_()
682 if (!enableConstraints_()) {
687 auto& sol = model_().solution(0);
688 auto& oldSol = model_().solution(1);
690 for (
const auto& constraint : constraintsMap_) {
691 sol[constraint.first] = constraint.second;
692 oldSol[constraint.first] = constraint.second;
698 void applyConstraintsToLinearization_()
700 if (!enableConstraints_()) {
704 for (
const auto& constraint : constraintsMap_) {
707 jacobian_->clearRow(constraint.first, Scalar(1.0));
710 residual_[constraint.first] = 0.0;
714 static bool enableConstraints_()
715 {
return getPropValue<TypeTag, Properties::EnableConstraints>(); }
717 Simulator* simulatorPtr_{};
718 std::vector<std::unique_ptr<ElementContext>> elementCtx_;
722 std::map<unsigned, Constraints> constraintsMap_;
730 SparseTable<FlowInfo> flowsInfo_;
731 SparseTable<FlowInfo> floresInfo_;
734 std::unique_ptr<SparseMatrixAdapter> jacobian_;
737 GlobalEqVector residual_;
739 LinearizationType linearizationType_;
741 std::mutex globalMatrixMutex_;
743 std::vector<std::set<unsigned int>> sparsityPattern_;
747 explicit FullDomain(
const GridView& v) : view (v) {}
749 std::vector<bool> interior;
754 std::unique_ptr<FullDomain> fullDomain_;
The common code for the linearizers of non-linear systems of equations.
Definition: fvbaselinearizer.hh:78
const auto & getFlowsInfo() const
Return constant reference to the flowsInfo.
Definition: fvbaselinearizer.hh:371
const GlobalEqVector & residual() const
Return constant reference to global residual vector.
Definition: fvbaselinearizer.hh:284
void setLinearizationType(LinearizationType linearizationType)
Definition: fvbaselinearizer.hh:336
SparseMatrixAdapter & jacobian()
Definition: fvbaselinearizer.hh:278
void printVector(GlobalEqVector &, const char *name="x")
Definition: fvbaselinearizer.hh:290
FvBaseLinearizer()=default
static void registerParameters()
Register all run-time parameters for the Jacobian linearizer.
Definition: fvbaselinearizer.hh:129
void linearize()
Linearize the full system of non-linear equations.
Definition: fvbaselinearizer.hh:170
void exportSparsity(const char *path=".")
Definition: fvbaselinearizer.hh:325
void finalize()
Definition: fvbaselinearizer.hh:236
void init(Simulator &simulator)
Initialize the linearizer.
Definition: fvbaselinearizer.hh:141
void printNonzeros(const char *name="d")
Definition: fvbaselinearizer.hh:305
void exportVector(GlobalEqVector &x, const char *tag="", const char *name="export/x")
Definition: fvbaselinearizer.hh:320
FvBaseLinearizer(const FvBaseLinearizer &)=delete
void updateBoundaryConditionData()
Definition: fvbaselinearizer.hh:348
void linearizeDomain()
Linearize the part of the non-linear system of equations that is associated with the spatial domain.
Definition: fvbaselinearizer.hh:186
void resetSystem_(const SubDomainType &domain)
Definition: fvbaselinearizer.hh:383
void printSparsity(const char *name="s")
Definition: fvbaselinearizer.hh:300
void printResidual(const char *name="r")
Definition: fvbaselinearizer.hh:295
GlobalEqVector & residual()
Definition: fvbaselinearizer.hh:287
const SparseMatrixAdapter & jacobian() const
Return constant reference to global Jacobian matrix backend.
Definition: fvbaselinearizer.hh:275
const auto & getFloresInfo() const
Return constant reference to the floresInfo.
Definition: fvbaselinearizer.hh:379
void linearizeAuxiliaryEquations()
Linearize the part of the non-linear system of equations that is associated with the spatial domain.
Definition: fvbaselinearizer.hh:243
void updateDiscretizationParameters()
Definition: fvbaselinearizer.hh:343
void exportSystem(int idx, char *tag, const char *path="export")
Definition: fvbaselinearizer.hh:315
void printJacobian()
Definition: fvbaselinearizer.hh:310
void exportNonzeros(const char *tag="", const char *path=".")
Definition: fvbaselinearizer.hh:330
const LinearizationType & getLinearizationType() const
Definition: fvbaselinearizer.hh:340
void updateFlowsInfo()
Definition: fvbaselinearizer.hh:353
void linearizeDomain(const SubDomainType &domain, bool isNlddLocalSolve=false)
Definition: fvbaselinearizer.hh:192
const std::map< unsigned, Constraints > & constraintsMap() const
Returns the map of constraint degrees of freedom.
Definition: fvbaselinearizer.hh:363
void eraseMatrix()
Causes the Jacobian matrix to be recreated from scratch before the next iteration.
Definition: fvbaselinearizer.hh:156
Definition: matrixblock.hh:229
Manages the initializing and running of time dependent problems.
Definition: simulator.hh:84
Problem & problem()
Return the object which specifies the pysical setup of the simulation.
Definition: simulator.hh:265
const GridView & gridView() const
Return the grid view for which the simulation is done.
Definition: simulator.hh:246
Model & model()
Return the physical model used in the simulation.
Definition: simulator.hh:252
Simplifies multi-threaded capabilities.
Definition: threadmanager.hpp:36
static unsigned maxThreads()
Return the maximum number of threads of the current process.
Definition: threadmanager.hpp:66
static unsigned threadId()
Return the index of the current OpenMP thread.
Provides an STL-iterator like interface to iterate over the enties of a GridView in OpenMP threaded a...
Definition: threadedentityiterator.hh:42
bool isFinished(const EntityIterator &it) const
Definition: threadedentityiterator.hh:67
EntityIterator increment()
Definition: threadedentityiterator.hh:80
EntityIterator beginParallel()
Definition: threadedentityiterator.hh:54
Declare the properties used by the infrastructure code of the finite volume discretizations.
Provides data handles for parallel communication which operate on DOFs.
Definition: blackoilbioeffectsmodules.hh:43
ElementType
The types of reference elements available.
Definition: vcfvstencil.hh:56
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition: propertysystem.hh:233
Definition: linearizationtype.hh:34