28#ifndef TPFA_LINEARIZER_HH
29#define TPFA_LINEARIZER_HH
31#include <dune/common/version.hh>
32#include <dune/common/fvector.hh>
33#include <dune/common/fmatrix.hh>
35#include <opm/common/Exceptions.hpp>
36#include <opm/common/TimingMacros.hpp>
38#include <opm/grid/utility/SparseTable.hpp>
40#include <opm/material/common/ConditionalStorage.hpp>
42#include <opm/input/eclipse/EclipseState/Grid/FaceDir.hpp>
43#include <opm/input/eclipse/Schedule/BCProp.hpp>
60#include <unordered_map>
63#include <opm/common/utility/gpuDecorators.hpp>
66#include <opm/simulators/linalg/gpuistl_hip/GpuBuffer.hpp>
67#include <opm/simulators/linalg/gpuistl_hip/GpuView.hpp>
68#include <opm/simulators/linalg/gpuistl_hip/MiniMatrix.hpp>
69#include <opm/simulators/linalg/gpuistl_hip/MiniVector.hpp>
87template<
class TypeTag>
91template<
class Storage = std::vector<
int>>
97#if HAVE_CUDA && OPM_IS_COMPILING_WITH_GPU_COMPILER
100 if (CPUDomain.
cells.size() == 0) {
101 OPM_THROW(std::runtime_error,
"Cannot copy empty full domain to GPU.");
103 return FullDomain<gpuistl::GpuBuffer<int>>{
104 gpuistl::GpuBuffer<int>(CPUDomain.
cells)
108 FullDomain<gpuistl::GpuView<int>>
make_view(FullDomain<gpuistl::GpuBuffer<int>>& buffer)
110 if (buffer.cells.size() == 0) {
111 OPM_THROW(std::runtime_error,
"Cannot make view of empty full domain buffer.");
113 return FullDomain<gpuistl::GpuView<int>>{
119template <
class Res
idualNBInfoType,
class BlockType>
126 template <
class OtherBlockType>
137 template <
class PtrType>
154#if HAVE_CUDA && OPM_IS_COMPILING_WITH_GPU_COMPILER
156 template<
class MiniMatrixType,
class MatrixBlockType,
class Res
idualNBInfoType>
157 auto copy_to_gpu(
const SparseTable<NeighborInfoStruct<ResidualNBInfoType, MatrixBlockType>>& cpuNeighborInfoTable)
160 using StructWithMinimatrix = NeighborInfoStruct<ResidualNBInfoType, MiniMatrixType>;
161 std::vector<StructWithMinimatrix> minimatrices(cpuNeighborInfoTable.dataSize());
163 for (
auto e : cpuNeighborInfoTable.dataStorage()) {
164 minimatrices[idx++] = StructWithMinimatrix(e);
167 return SparseTable<StructWithMinimatrix, gpuistl::GpuBuffer>(
168 gpuistl::GpuBuffer<StructWithMinimatrix>(minimatrices),
169 gpuistl::GpuBuffer<int>(cpuNeighborInfoTable.rowStarts())
184template<
class TypeTag>
205 using Element =
typename GridView::template Codim<0>::Entity;
206 using ElementIterator =
typename GridView::template Codim<0>::Iterator;
208 using Vector = GlobalEqVector;
210 enum { numEq = getPropValue<TypeTag, Properties::NumEq>() };
211 enum { historySize = getPropValue<TypeTag, Properties::TimeDiscHistorySize>() };
212 enum { dimWorld = GridView::dimensionworld };
214 using MatrixBlock =
typename SparseMatrixAdapter::MatrixBlock;
215 using VectorBlock = Dune::FieldVector<Scalar, numEq>;
218#if HAVE_CUDA && OPM_IS_COMPILING_WITH_GPU_COMPILER
223 static constexpr bool linearizeNonLocalElements =
224 getPropValue<TypeTag, Properties::LinearizeNonLocalElements>();
225 static constexpr bool enableFullyImplicitThermal = (getPropValue<TypeTag, Properties::EnergyModuleType>() == EnergyModules::FullyImplicitThermal);
226 static constexpr bool enableDiffusion = getPropValue<TypeTag, Properties::EnableDiffusion>();
227 static constexpr bool enableDispersion = getPropValue<TypeTag, Properties::EnableDispersion>();
228 static const bool enableBioeffects = getPropValue<TypeTag, Properties::EnableBioeffects>();
237 simulatorPtr_ =
nullptr;
238 separateSparseSourceTerms_ = Parameters::Get<Parameters::SeparateSparseSourceTerms>();
246 Parameters::Register<Parameters::SeparateSparseSourceTerms>
247 (
"Treat well source terms all in one go, instead of on a cell by cell basis.");
261 simulatorPtr_ = &simulator;
309 catch (
const std::exception& e) {
310 std::cout <<
"rank " << simulator_().
gridView().comm().rank()
311 <<
" caught an exception while linearizing:" << e.what()
312 <<
"\n" << std::flush;
316 std::cout <<
"rank " << simulator_().
gridView().comm().rank()
317 <<
" caught an exception while linearizing"
318 <<
"\n" << std::flush;
321 succeeded = simulator_().
gridView().comm().min(succeeded);
324 throw NumericalProblem(
"A process did not succeed in linearizing the system");
341 template <
class SubDomainType>
342 void linearizeDomain(
const SubDomainType& domain,
const bool isNlddLocalSolve =
false)
349 initFirstIteration_();
353 if (isNlddLocalSolve) {
360 linearize_(domain, isNlddLocalSolve);
364 { jacobian_->finalize(); }
372 OPM_TIMEBLOCK(linearizeAuxilaryEquations);
376 auto& model = model_();
377 const auto& comm = simulator_().
gridView().comm();
378 for (
unsigned auxModIdx = 0; auxModIdx < model.numAuxiliaryModules(); ++auxModIdx) {
379 bool succeeded =
true;
381 model.auxiliaryModule(auxModIdx)->linearize(*jacobian_, residual_);
383 catch (
const std::exception& e) {
386 std::cout <<
"rank " << simulator_().
gridView().comm().rank()
387 <<
" caught an exception while linearizing:" << e.what()
388 <<
"\n" << std::flush;
391 succeeded = comm.min(succeeded);
394 throw NumericalProblem(
"linearization of an auxiliary equation failed");
403 {
return *jacobian_; }
406 {
return *jacobian_; }
412 {
return residual_; }
415 {
return residual_; }
418 { linearizationType_ = linearizationType; }
421 {
return linearizationType_; }
429 {
return flowsInfo_; }
437 {
return floresInfo_; }
445 {
return velocityInfo_; }
448 return neighborInfo_;
454 updateStoredTransmissibilities();
459 for (
auto& bdyInfo : boundaryInfo_) {
460 const auto [type, massrateAD] = problem_().boundaryCondition(bdyInfo.cell, bdyInfo.dir);
463 VectorBlock massrate(0.0);
464 for (std::size_t ii = 0; ii < massrate.size(); ++ii) {
465 massrate[ii] = massrateAD[ii].value();
468 const auto& exFluidState = problem_().boundaryFluidState(bdyInfo.cell, bdyInfo.dir);
469 bdyInfo.bcdata.type = type;
470 bdyInfo.bcdata.massRate = massrate;
471 bdyInfo.bcdata.exFluidState = exFluidState;
484 template <
class SubDomainType>
488 initFirstIteration_();
490 for (
int globI : domain.cells) {
491 residual_[globI] = 0.0;
492 jacobian_->clearRow(globI, 0.0);
498 {
return *simulatorPtr_; }
500 const Simulator& simulator_()
const
501 {
return *simulatorPtr_; }
504 {
return simulator_().
problem(); }
506 const Problem& problem_()
const
507 {
return simulator_().
problem(); }
510 {
return simulator_().
model(); }
512 const Model& model_()
const
513 {
return simulator_().
model(); }
515 const GridView& gridView_()
const
516 {
return problem_().gridView(); }
518 void initFirstIteration_()
524 residual_.resize(model_().numTotalDof());
535 if (!neighborInfo_.empty()) {
540 const auto& model = model_();
541 Stencil stencil(gridView_(), model_().dofMapper());
545 using NeighborSet = std::set<unsigned>;
546 std::vector<NeighborSet> sparsityPattern(model.numTotalDof());
547 const Scalar gravity = problem_().gravity()[dimWorld - 1];
548 unsigned numCells = model.numTotalDof();
549 neighborInfo_.reserve(numCells, 6 * numCells);
550 std::vector<NeighborInfoCPU> loc_nbinfo;
551 for (
const auto& elem : elements(gridView_())) {
552 stencil.update(elem);
554 for (
unsigned primaryDofIdx = 0; primaryDofIdx < stencil.numPrimaryDof(); ++primaryDofIdx) {
555 const unsigned myIdx = stencil.globalSpaceIndex(primaryDofIdx);
556 loc_nbinfo.resize(stencil.numDof() - 1);
558 for (
unsigned dofIdx = 0; dofIdx < stencil.numDof(); ++dofIdx) {
559 const unsigned neighborIdx = stencil.globalSpaceIndex(dofIdx);
560 sparsityPattern[myIdx].insert(neighborIdx);
562 const Scalar trans = problem_().transmissibility(myIdx, neighborIdx);
563 const auto scvfIdx = dofIdx - 1;
564 const auto& scvf = stencil.interiorFace(scvfIdx);
565 const Scalar area = scvf.area();
566 const Scalar Vin = problem_().model().dofTotalVolume(myIdx);
567 const Scalar Vex = problem_().model().dofTotalVolume(neighborIdx);
568 const Scalar zIn = problem_().dofCenterDepth(myIdx);
569 const Scalar zEx = problem_().dofCenterDepth(neighborIdx);
570 const Scalar dZg = (zIn - zEx)*gravity;
571 const Scalar thpres = problem_().thresholdPressure(myIdx, neighborIdx);
572 const auto dirId = scvf.dirId();
573 auto faceDir = dirId < 0 ? FaceDir::DirEnum::Unknown
574 : FaceDir::FromIntersectionIndex(dirId);
575 ResidualNBInfo nbinfo{trans, area, thpres, dZg, faceDir, Vin, Vex, {}, {}, {}, {}};
576 if constexpr (enableFullyImplicitThermal) {
577 nbinfo.inAlpha = problem_().thermalHalfTransmissibility(myIdx, neighborIdx);
578 nbinfo.outAlpha = problem_().thermalHalfTransmissibility(neighborIdx, myIdx);
580 if constexpr (enableDiffusion) {
581 nbinfo.diffusivity = problem_().diffusivity(myIdx, neighborIdx);
583 if constexpr (enableDispersion) {
584 nbinfo.dispersivity = problem_().dispersivity(myIdx, neighborIdx);
586 loc_nbinfo[dofIdx - 1] = NeighborInfoCPU{neighborIdx, nbinfo,
nullptr};
589 neighborInfo_.appendRow(loc_nbinfo.begin(), loc_nbinfo.end());
590 if (problem_().nonTrivialBoundaryConditions()) {
591 for (
unsigned bfIndex = 0; bfIndex < stencil.numBoundaryFaces(); ++bfIndex) {
592 const auto& bf = stencil.boundaryFace(bfIndex);
593 const int dir_id = bf.dirId();
598 const auto [type, massrateAD] = problem_().boundaryCondition(myIdx, dir_id);
600 VectorBlock massrate(0.0);
601 for (std::size_t ii = 0; ii < massrate.size(); ++ii) {
602 massrate[ii] = massrateAD[ii].value();
604 const auto& exFluidState = problem_().boundaryFluidState(myIdx, dir_id);
605 BoundaryConditionData bcdata{type,
607 exFluidState.pvtRegionIndex(),
610 bf.integrationPos()[dimWorld - 1],
612 boundaryInfo_.push_back({myIdx, dir_id, bfIndex, bcdata});
620 const std::size_t numAuxMod = model.numAuxiliaryModules();
621 for (
unsigned auxModIdx = 0; auxModIdx < numAuxMod; ++auxModIdx) {
622 model.auxiliaryModule(auxModIdx)->addNeighbors(sparsityPattern);
626 jacobian_ = std::make_unique<SparseMatrixAdapter>(simulator_());
627 diagMatAddress_.resize(numCells);
629 jacobian_->reserve(sparsityPattern);
630 for (
unsigned globI = 0; globI < numCells; globI++) {
631 const auto& nbInfos = neighborInfo_[globI];
632 diagMatAddress_[globI] = jacobian_->blockAddress(globI, globI);
633 for (
auto& nbInfo : nbInfos) {
634 nbInfo.matBlockAddress = jacobian_->blockAddress(nbInfo.neighbor, globI);
639 fullDomain_.
cells.resize(numCells);
640 std::iota(fullDomain_.
cells.begin(), fullDomain_.
cells.end(), 0);
654 OPM_TIMEBLOCK(createFlows);
658 const bool anyFlows = simulator_().
problem().eclWriter().outputModule().getFlows().anyFlows() ||
659 simulator_().
problem().eclWriter().outputModule().getFlows().hasBlockFlows();
660 const bool anyFlores = simulator_().
problem().eclWriter().outputModule().getFlows().anyFlores();
661 const bool dispersionActive = simulator_().
vanguard().eclState().getSimulationConfig().rock_config().dispersion();
662 if (((!anyFlows || !flowsInfo_.empty()) && (!anyFlores || !floresInfo_.empty())) && (!dispersionActive && !enableBioeffects)) {
665 const auto& model = model_();
666 const auto& nncOutput = simulator_().
problem().eclWriter().getOutputNnc();
667 Stencil stencil(gridView_(), model_().dofMapper());
668 const unsigned numCells = model.numTotalDof();
669 std::unordered_multimap<int, std::pair<int, int>> nncIndices;
670 std::vector<FlowInfo> loc_flinfo;
671 std::vector<VelocityInfo> loc_vlinfo;
672 unsigned int nncId = 0;
673 VectorBlock flow(0.0);
676 for (
unsigned nncIdx = 0; nncIdx < nncOutput.size(); ++nncIdx) {
677 const int ci1 = nncOutput[nncIdx].cell1;
678 const int ci2 = nncOutput[nncIdx].cell2;
679 nncIndices.emplace(ci1, std::make_pair(ci2, nncIdx));
683 flowsInfo_.reserve(numCells, 6 * numCells);
686 floresInfo_.reserve(numCells, 6 * numCells);
688 if (dispersionActive || enableBioeffects) {
689 velocityInfo_.reserve(numCells, 6 * numCells);
692 for (
const auto& elem : elements(gridView_())) {
693 stencil.update(elem);
694 for (
unsigned primaryDofIdx = 0; primaryDofIdx < stencil.numPrimaryDof(); ++primaryDofIdx) {
695 const unsigned myIdx = stencil.globalSpaceIndex(primaryDofIdx);
696 const int numFaces = stencil.numBoundaryFaces() + stencil.numInteriorFaces();
697 loc_flinfo.resize(numFaces);
698 loc_vlinfo.resize(stencil.numDof() - 1);
700 for (
unsigned dofIdx = 0; dofIdx < stencil.numDof(); ++dofIdx) {
701 const unsigned neighborIdx = stencil.globalSpaceIndex(dofIdx);
703 const auto scvfIdx = dofIdx - 1;
704 const auto& scvf = stencil.interiorFace(scvfIdx);
705 int faceId = scvf.dirId();
706 const int cartMyIdx = simulator_().
vanguard().cartesianIndex(myIdx);
707 const int cartNeighborIdx = simulator_().
vanguard().cartesianIndex(neighborIdx);
708 const auto& range = nncIndices.equal_range(cartMyIdx);
709 for (
auto it = range.first; it != range.second; ++it) {
710 if (it->second.first == cartNeighborIdx){
714 nncId = it->second.second;
717 loc_flinfo[dofIdx - 1] = FlowInfo{faceId, flow, nncId};
718 loc_vlinfo[dofIdx - 1] = VelocityInfo{flow};
722 for (
unsigned bdfIdx = 0; bdfIdx < stencil.numBoundaryFaces(); ++bdfIdx) {
723 const auto& scvf = stencil.boundaryFace(bdfIdx);
724 const int faceId = scvf.dirId();
725 loc_flinfo[stencil.numInteriorFaces() + bdfIdx] = FlowInfo{faceId, flow, nncId};
729 flowsInfo_.appendRow(loc_flinfo.begin(), loc_flinfo.end());
732 floresInfo_.appendRow(loc_flinfo.begin(), loc_flinfo.end());
734 if (dispersionActive || enableBioeffects) {
735 velocityInfo_.appendRow(loc_vlinfo.begin(), loc_vlinfo.end());
744 for (
unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
745 res[eqIdx] = resid[eqIdx].value();
748 for (
unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
749 for (
unsigned pvIdx = 0; pvIdx < numEq; ++pvIdx) {
754 bMat[eqIdx][pvIdx] = resid[eqIdx].derivative(pvIdx);
761 OPM_TIMEBLOCK(updateFlows);
762 const bool enableFlows = simulator_().
problem().eclWriter().outputModule().getFlows().hasFlows() ||
763 simulator_().
problem().eclWriter().outputModule().getFlows().hasBlockFlows();
764 const bool enableFlores = simulator_().
problem().eclWriter().outputModule().getFlows().hasFlores();
765 if (!enableFlows && !enableFlores) {
768 const unsigned int numCells = model_().numTotalDof();
770#pragma omp parallel for
772 for (
unsigned globI = 0; globI < numCells; ++globI) {
773 OPM_TIMEBLOCK_LOCAL(linearizationForEachCell, Subsystem::Assembly);
774 const auto& nbInfos = neighborInfo_[globI];
775 ADVectorBlock adres(0.0);
776 ADVectorBlock darcyFlux(0.0);
777 const IntensiveQuantities& intQuantsIn = model_().intensiveQuantities(globI, 0);
780 OPM_TIMEBLOCK_LOCAL(fluxCalculationForEachCell, Subsystem::Assembly);
782 for (
const auto& nbInfo : nbInfos) {
783 OPM_TIMEBLOCK_LOCAL(fluxCalculationForEachFace, Subsystem::Assembly);
784 const unsigned globJ = nbInfo.neighbor;
785 assert(globJ != globI);
788 const IntensiveQuantities& intQuantsEx = model_().intensiveQuantities(globJ, 0);
789 LocalResidual::computeFlux(adres, darcyFlux, globI, globJ, intQuantsIn,
790 intQuantsEx, nbInfo.res_nbinfo, problem_().moduleParams());
791 adres *= nbInfo.res_nbinfo.faceArea;
793 for (
unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
794 flowsInfo_[globI][loc].flow[eqIdx] = adres[eqIdx].value();
798 for (
unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
799 floresInfo_[globI][loc].flow[eqIdx] = darcyFlux[eqIdx].value();
808 for (
const auto& bdyInfo : boundaryInfo_) {
813 ADVectorBlock adres(0.0);
814 const unsigned globI = bdyInfo.cell;
815 const auto& nbInfos = neighborInfo_[globI];
816 const IntensiveQuantities& insideIntQuants = model_().intensiveQuantities(globI, 0);
817 LocalResidual::computeBoundaryFlux(adres, problem_(), bdyInfo.bcdata, insideIntQuants, globI);
818 adres *= bdyInfo.bcdata.faceArea;
819 const unsigned bfIndex = bdyInfo.bfIndex;
821 for (
unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
822 flowsInfo_[globI][nbInfos.size() + bfIndex].flow[eqIdx] = adres[eqIdx].value();
830 template <
class SubDomainType>
831 void linearize_(
const SubDomainType& domain,
bool isNlddLocalSolve)
836 if (!problem_().recycleFirstIterationStorage()) {
837 if (!model_().storeIntensiveQuantities() && !model_().enableStorageCache()) {
838 OPM_THROW(std::runtime_error,
"Must have cached either IQs or storage when we cannot recycle.");
847 const bool dispersionActive = simulator_().
vanguard().eclState().getSimulationConfig().rock_config().dispersion();
848 const unsigned int numCells = domain.cells.size();
854#pragma omp parallel for
856 for (
unsigned ii = 0; ii < numCells; ++ii) {
857 OPM_TIMEBLOCK_LOCAL(linearizationForEachCell, Subsystem::Assembly);
858 const unsigned globI = domain.cells[ii];
859 const auto& nbInfos = neighborInfo_[globI];
860 VectorBlock res(0.0);
861 MatrixBlock bMat(0.0);
862 ADVectorBlock adres(0.0);
863 ADVectorBlock darcyFlux(0.0);
864 const IntensiveQuantities& intQuantsIn = model_().intensiveQuantities(globI, 0);
868 OPM_TIMEBLOCK_LOCAL(fluxCalculationForEachCell, Subsystem::Assembly);
870 for (
const auto& nbInfo : nbInfos) {
871 OPM_TIMEBLOCK_LOCAL(fluxCalculationForEachFace, Subsystem::Assembly);
872 const unsigned globJ = nbInfo.neighbor;
873 assert(globJ != globI);
878 const IntensiveQuantities& intQuantsEx = model_().intensiveQuantities(globJ, 0);
879 LocalResidual::computeFlux(adres, darcyFlux, globI, globJ, intQuantsIn, intQuantsEx,
880 nbInfo.res_nbinfo, problem_().moduleParams());
881 adres *= nbInfo.res_nbinfo.faceArea;
882 if (dispersionActive || enableBioeffects) {
883 for (
unsigned phaseIdx = 0; phaseIdx < numEq; ++phaseIdx) {
884 velocityInfo_[globI][loc].velocity[phaseIdx] =
885 darcyFlux[phaseIdx].value() / nbInfo.res_nbinfo.faceArea;
889 residual_[globI] += res;
891 *diagMatAddress_[globI] += bMat;
894 *nbInfo.matBlockAddress += bMat;
900 const double volume = model_().dofTotalVolume(globI);
901 const Scalar storefac = volume / dt;
904 OPM_TIMEBLOCK_LOCAL(computeStorage, Subsystem::Assembly);
905 LocalResidual::computeStorage(adres, intQuantsIn);
909 if (model_().enableStorageCache()) {
913 model_().updateCachedStorage(globI, 0, res);
920 if (model_().newtonMethod().numIterations() == 0 && !isNlddLocalSolve) {
922 if (problem_().recycleFirstIterationStorage()) {
925 model_().updateCachedStorage(globI, 1, res);
928 Dune::FieldVector<Scalar, numEq> tmp;
929 const IntensiveQuantities intQuantOld = model_().intensiveQuantities(globI, 1);
930 LocalResidual::computeStorage(tmp, intQuantOld);
931 model_().updateCachedStorage(globI, 1, tmp);
934 res -= model_().cachedStorage(globI, 1);
937 OPM_TIMEBLOCK_LOCAL(computeStorage0, Subsystem::Assembly);
938 Dune::FieldVector<Scalar, numEq> tmp;
939 const IntensiveQuantities intQuantOld = model_().intensiveQuantities(globI, 1);
940 LocalResidual::computeStorage(tmp, intQuantOld);
946 residual_[globI] += res;
948 *diagMatAddress_[globI] += bMat;
955 if (separateSparseSourceTerms_) {
956 LocalResidual::computeSourceDense(adres, problem_(), intQuantsIn, globI, 0);
959 LocalResidual::computeSource(adres, problem_(), intQuantsIn, globI, 0);
963 residual_[globI] += res;
965 *diagMatAddress_[globI] += bMat;
969 if (separateSparseSourceTerms_) {
970 problem_().wellModel().addReservoirSourceTerms(residual_, diagMatAddress_);
974 for (
const auto& bdyInfo : boundaryInfo_) {
979 VectorBlock res(0.0);
980 MatrixBlock bMat(0.0);
981 ADVectorBlock adres(0.0);
982 const unsigned globI = bdyInfo.cell;
983 const IntensiveQuantities& insideIntQuants = model_().intensiveQuantities(globI, 0);
984 LocalResidual::computeBoundaryFlux(adres, problem_(), bdyInfo.bcdata, insideIntQuants, globI);
985 adres *= bdyInfo.bcdata.faceArea;
987 residual_[globI] += res;
989 *diagMatAddress_[globI] += bMat;
993 void updateStoredTransmissibilities()
995 if (neighborInfo_.empty()) {
999 initFirstIteration_();
1002 const unsigned numCells = model_().numTotalDof();
1004#pragma omp parallel for
1006 for (
unsigned globI = 0; globI < numCells; globI++) {
1007 auto nbInfos = neighborInfo_[globI];
1008 for (
auto& nbInfo : nbInfos) {
1009 const unsigned globJ = nbInfo.neighbor;
1010 nbInfo.res_nbinfo.trans = problem_().transmissibility(globI, globJ);
1015 Simulator* simulatorPtr_{};
1018 std::unique_ptr<SparseMatrixAdapter> jacobian_{};
1021 GlobalEqVector residual_;
1023 LinearizationType linearizationType_{};
1025 using ResidualNBInfo =
typename LocalResidual::ResidualNBInfo;
1026 using NeighborInfoCPU = NeighborInfoStruct<ResidualNBInfo, MatrixBlock>;
1028 SparseTable<NeighborInfoCPU> neighborInfo_{};
1029 std::vector<MatrixBlock*> diagMatAddress_{};
1037 SparseTable<FlowInfo> flowsInfo_;
1038 SparseTable<FlowInfo> floresInfo_;
1042 VectorBlock velocity;
1044 SparseTable<VelocityInfo> velocityInfo_;
1046 using ScalarFluidState =
typename IntensiveQuantities::ScalarFluidState;
1047 struct BoundaryConditionData
1050 VectorBlock massRate;
1051 unsigned pvtRegionIdx;
1052 unsigned boundaryFaceIndex;
1055 ScalarFluidState exFluidState;
1062 unsigned int bfIndex;
1063 BoundaryConditionData bcdata;
1065 std::vector<BoundaryInfo> boundaryInfo_;
1067 bool separateSparseSourceTerms_ =
false;
1069 FullDomain<> fullDomain_;
Declares the properties required by the black oil model.
The base class for the element-centered finite-volume discretization scheme.
Definition: ecfvdiscretization.hh:160
Definition: matrixblock.hh:229
Manages the initializing and running of time dependent problems.
Definition: simulator.hh:84
Scalar timeStepSize() const
Returns the time step length so that we don't miss the beginning of the next episode or cross the en...
Definition: simulator.hh:413
Vanguard & vanguard()
Return a reference to the grid manager of simulation.
Definition: simulator.hh:234
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
The common code for the linearizers of non-linear systems of equations.
Definition: tpfalinearizer.hh:186
const auto & getFloresInfo() const
Return constant reference to the floresInfo.
Definition: tpfalinearizer.hh:436
const LinearizationType & getLinearizationType() const
Definition: tpfalinearizer.hh:420
const auto & getNeighborInfo() const
Definition: tpfalinearizer.hh:447
void updateBoundaryConditionData()
Definition: tpfalinearizer.hh:457
void linearize()
Linearize the full system of non-linear equations.
Definition: tpfalinearizer.hh:286
SparseMatrixAdapter & jacobian()
Definition: tpfalinearizer.hh:405
const auto & getFlowsInfo() const
Return constant reference to the flowsInfo.
Definition: tpfalinearizer.hh:428
std::map< unsigned, Constraints > constraintsMap() const
Returns the map of constraint degrees of freedom.
Definition: tpfalinearizer.hh:481
TpfaLinearizer()
Definition: tpfalinearizer.hh:235
void finalize()
Definition: tpfalinearizer.hh:363
void init(Simulator &simulator)
Initialize the linearizer.
Definition: tpfalinearizer.hh:259
void updateFlowsInfo()
Definition: tpfalinearizer.hh:759
void setResAndJacobi(VectorBlock &res, MatrixBlock &bMat, const ADVectorBlock &resid) const
Definition: tpfalinearizer.hh:742
static void registerParameters()
Register all run-time parameters for the Jacobian linearizer.
Definition: tpfalinearizer.hh:244
void linearizeDomain()
Linearize the part of the non-linear system of equations that is associated with the spatial domain.
Definition: tpfalinearizer.hh:302
const SparseMatrixAdapter & jacobian() const
Return constant reference to global Jacobian matrix backend.
Definition: tpfalinearizer.hh:402
void setLinearizationType(LinearizationType linearizationType)
Definition: tpfalinearizer.hh:417
void linearizeDomain(const SubDomainType &domain, const bool isNlddLocalSolve=false)
Linearize the part of the non-linear system of equations that is associated with a part of the spatia...
Definition: tpfalinearizer.hh:342
GlobalEqVector & residual()
Definition: tpfalinearizer.hh:414
void eraseMatrix()
Causes the Jacobian matrix to be recreated from scratch before the next iteration.
Definition: tpfalinearizer.hh:272
const auto & getVelocityInfo() const
Return constant reference to the velocityInfo.
Definition: tpfalinearizer.hh:444
void updateDiscretizationParameters()
Definition: tpfalinearizer.hh:452
void resetSystem_(const SubDomainType &domain)
Definition: tpfalinearizer.hh:485
void linearizeAuxiliaryEquations()
Linearize the part of the non-linear system of equations that is associated with the spatial domain.
Definition: tpfalinearizer.hh:370
const GlobalEqVector & residual() const
Return constant reference to global residual vector.
Definition: tpfalinearizer.hh:411
A small fixed-size square matrix class for use in CUDA kernels.
Definition: MiniMatrix.hpp:37
Definition: MiniVector.hpp:52
Declare the properties used by the infrastructure code of the finite volume discretizations.
Defines the common properties required by the porous medium multi-phase models.
@ NONE
Definition: DeferredLogger.hpp:46
Definition: blackoilnewtonmethodparams.hpp:31
HYPRE_IJMatrix createMatrix(HYPRE_Int N, HYPRE_Int dof_offset, const CommType &comm)
Create Hypre matrix.
Definition: HypreSetup.hpp:170
PointerView< T > make_view(const std::shared_ptr< T > &ptr)
Definition: gpu_smart_pointer.hpp:318
Definition: blackoilbioeffectsmodules.hh:43
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: tpfalinearizer.hh:93
Storage cells
Definition: tpfalinearizer.hh:94
Definition: linearizationtype.hh:34
Definition: tpfalinearizer.hh:121
NeighborInfoStruct(unsigned int n, const ResidualNBInfoType &r, PtrType ptr)
Definition: tpfalinearizer.hh:138
NeighborInfoStruct()
Definition: tpfalinearizer.hh:146
NeighborInfoStruct(const NeighborInfoStruct< ResidualNBInfoType, OtherBlockType > &other)
Definition: tpfalinearizer.hh:127
BlockType * matBlockAddress
Definition: tpfalinearizer.hh:124
ResidualNBInfoType res_nbinfo
Definition: tpfalinearizer.hh:123
unsigned int neighbor
Definition: tpfalinearizer.hh:122
Definition: tpfalinearizer.hh:80
static constexpr bool value
Definition: tpfalinearizer.hh:80