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;
113 using MatrixBlock =
typename SparseMatrixAdapter::MatrixBlock;
114 using VectorBlock = Dune::FieldVector<Scalar, numEq>;
121 FvBaseLinearizer() =
default;
124 FvBaseLinearizer(
const FvBaseLinearizer&) =
delete;
143 simulatorPtr_ = &simulator;
146 fullDomain_ = std::make_unique<FullDomain>(simulator.
gridView());
191 template <
class SubDomainType>
199 initFirstIteration_();
203 if (
static_cast<std::size_t
>(domain.view.size(0)) == model_().numTotalDof()) {
208 resetSystem_(domain);
216 catch (
const std::exception& e)
218 std::cout <<
"rank " << simulator_().gridView().comm().rank()
219 <<
" caught an exception while linearizing:" << e.what()
220 <<
"\n" << std::flush;
225 std::cout <<
"rank " << simulator_().gridView().comm().rank()
226 <<
" caught an exception while linearizing"
227 <<
"\n" << std::flush;
230 succeeded = simulator_().gridView().comm().min(succeeded);
233 throw NumericalProblem(
"A process did not succeed in linearizing the system");
238 { jacobian_->finalize(); }
250 auto& model = model_();
251 const auto& comm = simulator_().gridView().comm();
252 for (
unsigned auxModIdx = 0; auxModIdx < model.numAuxiliaryModules(); ++auxModIdx) {
253 bool succeeded =
true;
255 model.auxiliaryModule(auxModIdx)->linearize(*jacobian_, residual_);
257 catch (
const std::exception& e) {
260 std::cout <<
"rank " << simulator_().gridView().comm().rank()
261 <<
" caught an exception while linearizing:" << e.what()
262 <<
"\n" << std::flush;
265 succeeded = comm.min(succeeded);
268 throw NumericalProblem(
"linearization of an auxiliary equation failed");
277 {
return *jacobian_; }
280 {
return *jacobian_; }
286 {
return residual_; }
289 {
return residual_; }
291 void setLinearizationType(LinearizationType linearizationType)
292 { linearizationType_ = linearizationType; }
294 const LinearizationType& getLinearizationType()
const
295 {
return linearizationType_; }
297 void updateDiscretizationParameters()
302 void updateBoundaryConditionData()
307 void updateFlowsInfo()
318 {
return constraintsMap_; }
326 {
return flowsInfo_; }
334 {
return floresInfo_; }
336 template <
class SubDomainType>
337 void resetSystem_(
const SubDomainType& domain)
340 initFirstIteration_();
344 using GridViewType =
decltype(domain.view);
345 ThreadedEntityIterator<GridViewType, 0> threadedElemIt(domain.view);
351 auto elemIt = threadedElemIt.beginParallel();
352 MatrixBlock zeroBlock;
354 for (; !threadedElemIt.isFinished(elemIt); elemIt = threadedElemIt.increment()) {
355 const Element& elem = *elemIt;
356 ElementContext& elemCtx = *elementCtx_[threadId];
357 elemCtx.updatePrimaryStencil(elem);
359 for (
unsigned primaryDofIdx = 0;
360 primaryDofIdx < elemCtx.numPrimaryDof(0);
363 const unsigned globI = elemCtx.globalSpaceIndex(primaryDofIdx, 0);
364 residual_[globI] = 0.0;
365 jacobian_->clearRow(globI, 0.0);
372 Simulator& simulator_()
373 {
return *simulatorPtr_; }
375 const Simulator& simulator_()
const
376 {
return *simulatorPtr_; }
379 {
return simulator_().problem(); }
381 const Problem& problem_()
const
382 {
return simulator_().problem(); }
385 {
return simulator_().model(); }
387 const Model& model_()
const
388 {
return simulator_().model(); }
390 const GridView& gridView_()
const
391 {
return problem_().gridView(); }
393 const ElementMapper& elementMapper_()
const
394 {
return model_().elementMapper(); }
396 const DofMapper& dofMapper_()
const
397 {
return model_().dofMapper(); }
399 void initFirstIteration_()
405 residual_.resize(model_().numTotalDof());
412 elementCtx_.push_back(std::make_unique<ElementContext>(simulator_()));
419 const auto& model = model_();
420 Stencil stencil(gridView_(), model_().dofMapper());
424 sparsityPattern_.clear();
425 sparsityPattern_.resize(model.numTotalDof());
427 for (
const auto& elem : elements(gridView_())) {
428 stencil.update(elem);
430 for (
unsigned primaryDofIdx = 0; primaryDofIdx < stencil.numPrimaryDof(); ++primaryDofIdx) {
431 const unsigned myIdx = stencil.globalSpaceIndex(primaryDofIdx);
433 for (
unsigned dofIdx = 0; dofIdx < stencil.numDof(); ++dofIdx) {
434 const unsigned neighborIdx = stencil.globalSpaceIndex(dofIdx);
435 sparsityPattern_[myIdx].insert(neighborIdx);
442 const std::size_t numAuxMod = model.numAuxiliaryModules();
443 for (
unsigned auxModIdx = 0; auxModIdx < numAuxMod; ++auxModIdx) {
444 model.auxiliaryModule(auxModIdx)->addNeighbors(sparsityPattern_);
448 jacobian_ = std::make_unique<SparseMatrixAdapter>(simulator_());
451 jacobian_->reserve(sparsityPattern_);
464 void updateConstraintsMap_()
466 if (!enableConstraints_()) {
471 constraintsMap_.clear();
474 ThreadedEntityIterator<GridView, 0> threadedElemIt(gridView_());
480 ElementIterator elemIt = threadedElemIt.beginParallel();
481 for (; !threadedElemIt.isFinished(elemIt); elemIt = threadedElemIt.increment()) {
484 const Element& elem = *elemIt;
485 ElementContext& elemCtx = *elementCtx_[threadId];
486 elemCtx.updateStencil(elem);
490 for (
unsigned primaryDofIdx = 0;
491 primaryDofIdx < elemCtx.numPrimaryDof(0);
494 Constraints constraints;
495 elemCtx.problem().constraints(constraints,
499 if (constraints.isActive()) {
500 const unsigned globI = elemCtx.globalSpaceIndex(primaryDofIdx, 0);
501 constraintsMap_[globI] = constraints;
510 template <
class SubDomainType>
511 void linearize_(
const SubDomainType& domain)
513 OPM_TIMEBLOCK(linearize_);
522 if (model_().newtonMethod().numIterations() == 0) {
523 updateConstraintsMap_();
526 applyConstraintsToSolution_();
531 std::mutex exceptionLock;
535 std::exception_ptr exceptionPtr =
nullptr;
538 using GridViewType =
decltype(domain.view);
539 ThreadedEntityIterator<GridViewType, 0> threadedElemIt(domain.view);
544 auto elemIt = threadedElemIt.beginParallel();
545 auto nextElemIt = elemIt;
547 for (; !threadedElemIt.isFinished(elemIt); elemIt = nextElemIt) {
550 nextElemIt = threadedElemIt.increment();
551 if (!threadedElemIt.isFinished(nextElemIt)) {
552 const auto& nextElem = *nextElemIt;
553 if (linearizeNonLocalElements ||
554 nextElem.partitionType() == Dune::InteriorEntity)
556 model_().prefetch(nextElem);
557 problem_().prefetch(nextElem);
561 const auto& elem = *elemIt;
562 if (!linearizeNonLocalElements && elem.partitionType() != Dune::InteriorEntity) {
566 linearizeElement_(elem);
579 std::lock_guard<std::mutex> take(exceptionLock);
580 exceptionPtr = std::current_exception();
581 threadedElemIt.setFinished();
589 std::rethrow_exception(exceptionPtr);
592 applyConstraintsToLinearization_();
596 template <
class ElementType>
601 ElementContext& elementCtx = *elementCtx_[threadId];
602 auto& localLinearizer = model_().localLinearizer(threadId);
605 localLinearizer.linearize(elementCtx, elem);
609 globalMatrixMutex_.lock();
612 const std::size_t numPrimaryDof = elementCtx.numPrimaryDof(0);
613 for (
unsigned primaryDofIdx = 0; primaryDofIdx < numPrimaryDof; ++primaryDofIdx) {
614 const unsigned globI = elementCtx.globalSpaceIndex(primaryDofIdx, 0);
617 residual_[globI] += localLinearizer.residual(primaryDofIdx);
620 for (
unsigned dofIdx = 0; dofIdx < elementCtx.numDof(0); ++dofIdx) {
621 const unsigned globJ = elementCtx.globalSpaceIndex(dofIdx, 0);
623 jacobian_->addToBlock(globJ, globI, localLinearizer.jacobian(dofIdx, primaryDofIdx));
628 globalMatrixMutex_.unlock();
634 void applyConstraintsToSolution_()
636 if (!enableConstraints_()) {
641 auto& sol = model_().solution(0);
642 auto& oldSol = model_().solution(1);
644 for (
const auto& constraint : constraintsMap_) {
645 sol[constraint.first] = constraint.second;
646 oldSol[constraint.first] = constraint.second;
652 void applyConstraintsToLinearization_()
654 if (!enableConstraints_()) {
658 for (
const auto& constraint : constraintsMap_) {
661 jacobian_->clearRow(constraint.first, Scalar(1.0));
664 residual_[constraint.first] = 0.0;
668 static bool enableConstraints_()
671 Simulator* simulatorPtr_{};
672 std::vector<std::unique_ptr<ElementContext>> elementCtx_;
676 std::map<unsigned, Constraints> constraintsMap_;
684 SparseTable<FlowInfo> flowsInfo_;
685 SparseTable<FlowInfo> floresInfo_;
688 std::unique_ptr<SparseMatrixAdapter> jacobian_;
691 GlobalEqVector residual_;
693 LinearizationType linearizationType_;
695 std::mutex globalMatrixMutex_;
697 std::vector<std::set<unsigned int>> sparsityPattern_;
701 explicit FullDomain(
const GridView& v) : view (v) {}
703 std::vector<bool> interior;
708 std::unique_ptr<FullDomain> fullDomain_;