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>
61#include <unordered_map>
64#include <fmt/format.h>
66#include <opm/common/utility/gpuDecorators.hpp>
69#include <opm/simulators/linalg/gpuistl_hip/GpuBuffer.hpp>
70#include <opm/simulators/linalg/gpuistl_hip/GpuView.hpp>
71#include <opm/simulators/linalg/gpuistl_hip/MiniMatrix.hpp>
72#include <opm/simulators/linalg/gpuistl_hip/MiniVector.hpp>
90template<
class TypeTag>
94template<
class Storage = std::vector<
int>>
100#if HAVE_CUDA && OPM_IS_COMPILING_WITH_GPU_COMPILER
103 if (CPUDomain.
cells.size() == 0) {
104 OPM_THROW(std::runtime_error,
"Cannot copy empty full domain to GPU.");
106 return FullDomain<gpuistl::GpuBuffer<int>>{
107 gpuistl::GpuBuffer<int>(CPUDomain.
cells)
111 FullDomain<gpuistl::GpuView<int>>
make_view(FullDomain<gpuistl::GpuBuffer<int>>& buffer)
113 if (buffer.cells.size() == 0) {
114 OPM_THROW(std::runtime_error,
"Cannot make view of empty full domain buffer.");
116 return FullDomain<gpuistl::GpuView<int>>{
122template <
class Res
idualNBInfoType,
class BlockType>
129 template <
class OtherBlockType>
140 template <
class PtrType>
157#if HAVE_CUDA && OPM_IS_COMPILING_WITH_GPU_COMPILER
159 template<
class MiniMatrixType,
class MatrixBlockType,
class Res
idualNBInfoType>
160 auto copy_to_gpu(
const SparseTable<NeighborInfoStruct<ResidualNBInfoType, MatrixBlockType>>& cpuNeighborInfoTable)
163 using StructWithMinimatrix = NeighborInfoStruct<ResidualNBInfoType, MiniMatrixType>;
164 std::vector<StructWithMinimatrix> minimatrices(cpuNeighborInfoTable.dataSize());
166 for (
auto e : cpuNeighborInfoTable.dataStorage()) {
167 minimatrices[idx++] = StructWithMinimatrix(e);
170 return SparseTable<StructWithMinimatrix, gpuistl::GpuBuffer>(
171 gpuistl::GpuBuffer<StructWithMinimatrix>(minimatrices),
172 gpuistl::GpuBuffer<int>(cpuNeighborInfoTable.rowStarts())
187template<
class TypeTag>
208 using Element =
typename GridView::template Codim<0>::Entity;
209 using ElementIterator =
typename GridView::template Codim<0>::Iterator;
211 using Vector = GlobalEqVector;
213 enum { numEq = getPropValue<TypeTag, Properties::NumEq>() };
214 enum { historySize = getPropValue<TypeTag, Properties::TimeDiscHistorySize>() };
215 enum { dimWorld = GridView::dimensionworld };
217 using MatrixBlock =
typename SparseMatrixAdapter::MatrixBlock;
218 using VectorBlock = Dune::FieldVector<Scalar, numEq>;
221#if HAVE_CUDA && OPM_IS_COMPILING_WITH_GPU_COMPILER
226 static constexpr bool linearizeNonLocalElements =
227 getPropValue<TypeTag, Properties::LinearizeNonLocalElements>();
228 static constexpr bool enableFullyImplicitThermal = (getPropValue<TypeTag, Properties::EnergyModuleType>() == EnergyModules::FullyImplicitThermal);
229 static constexpr bool enableDiffusion = getPropValue<TypeTag, Properties::EnableDiffusion>();
230 static constexpr bool enableDispersion = getPropValue<TypeTag, Properties::EnableDispersion>();
231 static const bool enableBioeffects = getPropValue<TypeTag, Properties::EnableBioeffects>();
240 simulatorPtr_ =
nullptr;
241 separateSparseSourceTerms_ = Parameters::Get<Parameters::SeparateSparseSourceTerms>();
251 Parameters::Register<Parameters::SeparateSparseSourceTerms>
252 (
"Treat well source terms all in one go, instead of on a cell by cell basis.");
266 simulatorPtr_ = &simulator;
314 catch (
const std::exception& e) {
315 std::cout <<
"rank " << simulator_().
gridView().comm().rank()
316 <<
" caught an exception while linearizing:" << e.what()
317 <<
"\n" << std::flush;
321 std::cout <<
"rank " << simulator_().
gridView().comm().rank()
322 <<
" caught an exception while linearizing"
323 <<
"\n" << std::flush;
326 succeeded = simulator_().
gridView().comm().min(succeeded);
329 throw NumericalProblem(
"A process did not succeed in linearizing the system");
346 template <
class SubDomainType>
347 void linearizeDomain(
const SubDomainType& domain,
const bool isNlddLocalSolve =
false)
354 initFirstIteration_();
358 if (isNlddLocalSolve) {
365 linearize_(domain, isNlddLocalSolve);
369 { jacobian_->finalize(); }
377 OPM_TIMEBLOCK(linearizeAuxilaryEquations);
381 auto& model = model_();
382 const auto& comm = simulator_().
gridView().comm();
383 for (
unsigned auxModIdx = 0; auxModIdx < model.numAuxiliaryModules(); ++auxModIdx) {
384 bool succeeded =
true;
386 model.auxiliaryModule(auxModIdx)->linearize(*jacobian_, residual_);
388 catch (
const std::exception& e) {
391 std::cout <<
"rank " << simulator_().
gridView().comm().rank()
392 <<
" caught an exception while linearizing:" << e.what()
393 <<
"\n" << std::flush;
396 succeeded = comm.min(succeeded);
399 throw NumericalProblem(
"linearization of an auxiliary equation failed");
408 {
return *jacobian_; }
411 {
return *jacobian_; }
417 {
return residual_; }
420 {
return residual_; }
425 void exportSystem(
const int idx, std::string& tag,
const char *path=
"export")
427 const bool export_sparsity = exportIndex_ == -1;
430 exportCount_ = exportIndex_ == idx ? ++exportCount_ : 0;
432 tag = fmt::format(
"_{:03d}_{:02d}", exportIndex_, exportCount_);
434 fmt::print(
"index = {:d}\n", exportIndex_);
435 fmt::print(
"count = {:d}\n", exportCount_);
437 Opm::exportSystem(jacobian_->istlMatrix(), residual_, export_sparsity, tag.c_str(), path);
441 { linearizationType_ = linearizationType; }
444 {
return linearizationType_; }
452 {
return flowsInfo_; }
460 {
return floresInfo_; }
468 {
return velocityInfo_; }
471 return neighborInfo_;
477 updateStoredTransmissibilities();
482 for (
auto& bdyInfo : boundaryInfo_) {
483 const auto [type, massrateAD] = problem_().boundaryCondition(bdyInfo.cell, bdyInfo.dir);
486 VectorBlock massrate(0.0);
487 for (std::size_t ii = 0; ii < massrate.size(); ++ii) {
488 massrate[ii] = massrateAD[ii].value();
491 const auto& exFluidState = problem_().boundaryFluidState(bdyInfo.cell, bdyInfo.dir);
492 bdyInfo.bcdata.type = type;
493 bdyInfo.bcdata.massRate = massrate;
494 bdyInfo.bcdata.exFluidState = exFluidState;
507 template <
class SubDomainType>
511 initFirstIteration_();
513 for (
int globI : domain.cells) {
514 residual_[globI] = 0.0;
515 jacobian_->clearRow(globI, 0.0);
521 {
return *simulatorPtr_; }
523 const Simulator& simulator_()
const
524 {
return *simulatorPtr_; }
527 {
return simulator_().
problem(); }
529 const Problem& problem_()
const
530 {
return simulator_().
problem(); }
533 {
return simulator_().
model(); }
535 const Model& model_()
const
536 {
return simulator_().
model(); }
538 const GridView& gridView_()
const
539 {
return problem_().gridView(); }
541 void initFirstIteration_()
547 residual_.resize(model_().numTotalDof());
558 if (!neighborInfo_.empty()) {
563 const auto& model = model_();
564 Stencil stencil(gridView_(), model_().dofMapper());
568 using NeighborSet = std::set<unsigned>;
569 std::vector<NeighborSet> sparsityPattern(model.numTotalDof());
570 const Scalar gravity = problem_().gravity()[dimWorld - 1];
571 unsigned numCells = model.numTotalDof();
572 neighborInfo_.reserve(numCells, 6 * numCells);
573 std::vector<NeighborInfoCPU> loc_nbinfo;
574 for (
const auto& elem : elements(gridView_())) {
575 stencil.update(elem);
577 for (
unsigned primaryDofIdx = 0; primaryDofIdx < stencil.numPrimaryDof(); ++primaryDofIdx) {
578 const unsigned myIdx = stencil.globalSpaceIndex(primaryDofIdx);
579 loc_nbinfo.resize(stencil.numDof() - 1);
581 for (
unsigned dofIdx = 0; dofIdx < stencil.numDof(); ++dofIdx) {
582 const unsigned neighborIdx = stencil.globalSpaceIndex(dofIdx);
583 sparsityPattern[myIdx].insert(neighborIdx);
585 const Scalar trans = problem_().transmissibility(myIdx, neighborIdx);
586 const auto scvfIdx = dofIdx - 1;
587 const auto& scvf = stencil.interiorFace(scvfIdx);
588 const Scalar area = scvf.area();
589 const Scalar Vin = problem_().model().dofTotalVolume(myIdx);
590 const Scalar Vex = problem_().model().dofTotalVolume(neighborIdx);
591 const Scalar zIn = problem_().dofCenterDepth(myIdx);
592 const Scalar zEx = problem_().dofCenterDepth(neighborIdx);
593 const Scalar dZg = (zIn - zEx)*gravity;
594 const Scalar thpres = problem_().thresholdPressure(myIdx, neighborIdx);
595 const auto dirId = scvf.dirId();
596 auto faceDir = dirId < 0 ? FaceDir::DirEnum::Unknown
597 : FaceDir::FromIntersectionIndex(dirId);
598 ResidualNBInfo nbinfo{trans, area, thpres, dZg, faceDir, Vin, Vex, {}, {}, {}, {}};
599 if constexpr (enableFullyImplicitThermal) {
600 nbinfo.inAlpha = problem_().thermalHalfTransmissibility(myIdx, neighborIdx);
601 nbinfo.outAlpha = problem_().thermalHalfTransmissibility(neighborIdx, myIdx);
603 if constexpr (enableDiffusion) {
604 nbinfo.diffusivity = problem_().diffusivity(myIdx, neighborIdx);
606 if constexpr (enableDispersion) {
607 nbinfo.dispersivity = problem_().dispersivity(myIdx, neighborIdx);
609 loc_nbinfo[dofIdx - 1] = NeighborInfoCPU{neighborIdx, nbinfo,
nullptr};
612 neighborInfo_.appendRow(loc_nbinfo.begin(), loc_nbinfo.end());
613 if (problem_().nonTrivialBoundaryConditions()) {
614 for (
unsigned bfIndex = 0; bfIndex < stencil.numBoundaryFaces(); ++bfIndex) {
615 const auto& bf = stencil.boundaryFace(bfIndex);
616 const int dir_id = bf.dirId();
621 const auto [type, massrateAD] = problem_().boundaryCondition(myIdx, dir_id);
623 VectorBlock massrate(0.0);
624 for (std::size_t ii = 0; ii < massrate.size(); ++ii) {
625 massrate[ii] = massrateAD[ii].value();
627 const auto& exFluidState = problem_().boundaryFluidState(myIdx, dir_id);
628 BoundaryConditionData bcdata{type,
630 exFluidState.pvtRegionIndex(),
633 bf.integrationPos()[dimWorld - 1],
635 boundaryInfo_.push_back({myIdx, dir_id, bfIndex, bcdata});
643 const std::size_t numAuxMod = model.numAuxiliaryModules();
644 for (
unsigned auxModIdx = 0; auxModIdx < numAuxMod; ++auxModIdx) {
645 model.auxiliaryModule(auxModIdx)->addNeighbors(sparsityPattern);
649 jacobian_ = std::make_unique<SparseMatrixAdapter>(simulator_());
650 diagMatAddress_.resize(numCells);
652 jacobian_->reserve(sparsityPattern);
653 for (
unsigned globI = 0; globI < numCells; globI++) {
654 const auto& nbInfos = neighborInfo_[globI];
655 diagMatAddress_[globI] = jacobian_->blockAddress(globI, globI);
656 for (
auto& nbInfo : nbInfos) {
657 nbInfo.matBlockAddress = jacobian_->blockAddress(nbInfo.neighbor, globI);
662 fullDomain_.
cells.resize(numCells);
663 std::iota(fullDomain_.
cells.begin(), fullDomain_.
cells.end(), 0);
677 OPM_TIMEBLOCK(createFlows);
681 const bool anyFlows = simulator_().
problem().eclWriter().outputModule().getFlows().anyFlows() ||
682 simulator_().
problem().eclWriter().outputModule().getFlows().hasBlockFlows();
683 const bool anyFlores = simulator_().
problem().eclWriter().outputModule().getFlows().anyFlores();
684 const bool dispersionActive = simulator_().
vanguard().eclState().getSimulationConfig().rock_config().dispersion();
685 if (((!anyFlows || !flowsInfo_.empty()) && (!anyFlores || !floresInfo_.empty())) && (!dispersionActive && !enableBioeffects)) {
688 const auto& model = model_();
689 const auto& nncOutput = simulator_().
problem().eclWriter().getOutputNnc();
690 Stencil stencil(gridView_(), model_().dofMapper());
691 const unsigned numCells = model.numTotalDof();
692 std::unordered_multimap<int, std::pair<int, int>> nncIndices;
693 std::vector<FlowInfo> loc_flinfo;
694 std::vector<VelocityInfo> loc_vlinfo;
695 unsigned int nncId = 0;
696 VectorBlock flow(0.0);
699 for (
unsigned nncIdx = 0; nncIdx < nncOutput.size(); ++nncIdx) {
700 const int ci1 = nncOutput[nncIdx].cell1;
701 const int ci2 = nncOutput[nncIdx].cell2;
702 nncIndices.emplace(ci1, std::make_pair(ci2, nncIdx));
706 flowsInfo_.reserve(numCells, 6 * numCells);
709 floresInfo_.reserve(numCells, 6 * numCells);
711 if (dispersionActive || enableBioeffects) {
712 velocityInfo_.reserve(numCells, 6 * numCells);
715 for (
const auto& elem : elements(gridView_())) {
716 stencil.update(elem);
717 for (
unsigned primaryDofIdx = 0; primaryDofIdx < stencil.numPrimaryDof(); ++primaryDofIdx) {
718 const unsigned myIdx = stencil.globalSpaceIndex(primaryDofIdx);
719 const int numFaces = stencil.numBoundaryFaces() + stencil.numInteriorFaces();
720 loc_flinfo.resize(numFaces);
721 loc_vlinfo.resize(stencil.numDof() - 1);
723 for (
unsigned dofIdx = 0; dofIdx < stencil.numDof(); ++dofIdx) {
724 const unsigned neighborIdx = stencil.globalSpaceIndex(dofIdx);
726 const auto scvfIdx = dofIdx - 1;
727 const auto& scvf = stencil.interiorFace(scvfIdx);
728 int faceId = scvf.dirId();
729 const int cartMyIdx = simulator_().
vanguard().cartesianIndex(myIdx);
730 const int cartNeighborIdx = simulator_().
vanguard().cartesianIndex(neighborIdx);
731 const auto& range = nncIndices.equal_range(cartMyIdx);
732 for (
auto it = range.first; it != range.second; ++it) {
733 if (it->second.first == cartNeighborIdx){
737 nncId = it->second.second;
740 loc_flinfo[dofIdx - 1] = FlowInfo{faceId, flow, nncId};
741 loc_vlinfo[dofIdx - 1] = VelocityInfo{flow};
745 for (
unsigned bdfIdx = 0; bdfIdx < stencil.numBoundaryFaces(); ++bdfIdx) {
746 const auto& scvf = stencil.boundaryFace(bdfIdx);
747 const int faceId = scvf.dirId();
748 loc_flinfo[stencil.numInteriorFaces() + bdfIdx] = FlowInfo{faceId, flow, nncId};
752 flowsInfo_.appendRow(loc_flinfo.begin(), loc_flinfo.end());
755 floresInfo_.appendRow(loc_flinfo.begin(), loc_flinfo.end());
757 if (dispersionActive || enableBioeffects) {
758 velocityInfo_.appendRow(loc_vlinfo.begin(), loc_vlinfo.end());
767 for (
unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
768 res[eqIdx] = resid[eqIdx].value();
771 for (
unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
772 for (
unsigned pvIdx = 0; pvIdx < numEq; ++pvIdx) {
777 bMat[eqIdx][pvIdx] = resid[eqIdx].derivative(pvIdx);
784 OPM_TIMEBLOCK(updateFlows);
785 const bool enableFlows = simulator_().
problem().eclWriter().outputModule().getFlows().hasFlows() ||
786 simulator_().
problem().eclWriter().outputModule().getFlows().hasBlockFlows();
787 const bool enableFlores = simulator_().
problem().eclWriter().outputModule().getFlows().hasFlores();
788 if (!enableFlows && !enableFlores) {
791 const unsigned int numCells = model_().numTotalDof();
793#pragma omp parallel for
795 for (
unsigned globI = 0; globI < numCells; ++globI) {
796 OPM_TIMEBLOCK_LOCAL(linearizationForEachCell, Subsystem::Assembly);
797 const auto& nbInfos = neighborInfo_[globI];
798 ADVectorBlock adres(0.0);
799 ADVectorBlock darcyFlux(0.0);
800 const IntensiveQuantities& intQuantsIn = model_().intensiveQuantities(globI, 0);
803 OPM_TIMEBLOCK_LOCAL(fluxCalculationForEachCell, Subsystem::Assembly);
805 for (
const auto& nbInfo : nbInfos) {
806 OPM_TIMEBLOCK_LOCAL(fluxCalculationForEachFace, Subsystem::Assembly);
807 const unsigned globJ = nbInfo.neighbor;
808 assert(globJ != globI);
811 const IntensiveQuantities& intQuantsEx = model_().intensiveQuantities(globJ, 0);
812 LocalResidual::computeFlux(adres, darcyFlux, globI, globJ, intQuantsIn,
813 intQuantsEx, nbInfo.res_nbinfo, problem_().moduleParams());
814 adres *= nbInfo.res_nbinfo.faceArea;
816 for (
unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
817 flowsInfo_[globI][loc].flow[eqIdx] = adres[eqIdx].value();
821 for (
unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
822 floresInfo_[globI][loc].flow[eqIdx] = darcyFlux[eqIdx].value();
831 for (
const auto& bdyInfo : boundaryInfo_) {
836 ADVectorBlock adres(0.0);
837 const unsigned globI = bdyInfo.cell;
838 const auto& nbInfos = neighborInfo_[globI];
839 const IntensiveQuantities& insideIntQuants = model_().intensiveQuantities(globI, 0);
840 LocalResidual::computeBoundaryFlux(adres, problem_(), bdyInfo.bcdata, insideIntQuants, globI);
841 adres *= bdyInfo.bcdata.faceArea;
842 const unsigned bfIndex = bdyInfo.bfIndex;
844 for (
unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
845 flowsInfo_[globI][nbInfos.size() + bfIndex].flow[eqIdx] = adres[eqIdx].value();
853 template <
class SubDomainType>
854 void linearize_(
const SubDomainType& domain,
bool isNlddLocalSolve)
859 if (!problem_().recycleFirstIterationStorage()) {
860 if (!model_().storeIntensiveQuantities() && !model_().enableStorageCache()) {
861 OPM_THROW(std::runtime_error,
"Must have cached either IQs or storage when we cannot recycle.");
870 const bool dispersionActive = simulator_().
vanguard().eclState().getSimulationConfig().rock_config().dispersion();
871 const unsigned int numCells = domain.cells.size();
877#pragma omp parallel for
879 for (
unsigned ii = 0; ii < numCells; ++ii) {
880 OPM_TIMEBLOCK_LOCAL(linearizationForEachCell, Subsystem::Assembly);
881 const unsigned globI = domain.cells[ii];
882 const auto& nbInfos = neighborInfo_[globI];
883 VectorBlock res(0.0);
884 MatrixBlock bMat(0.0);
885 ADVectorBlock adres(0.0);
886 ADVectorBlock darcyFlux(0.0);
887 const IntensiveQuantities& intQuantsIn = model_().intensiveQuantities(globI, 0);
891 OPM_TIMEBLOCK_LOCAL(fluxCalculationForEachCell, Subsystem::Assembly);
893 for (
const auto& nbInfo : nbInfos) {
894 OPM_TIMEBLOCK_LOCAL(fluxCalculationForEachFace, Subsystem::Assembly);
895 const unsigned globJ = nbInfo.neighbor;
896 assert(globJ != globI);
901 const IntensiveQuantities& intQuantsEx = model_().intensiveQuantities(globJ, 0);
902 LocalResidual::computeFlux(adres, darcyFlux, globI, globJ, intQuantsIn, intQuantsEx,
903 nbInfo.res_nbinfo, problem_().moduleParams());
904 adres *= nbInfo.res_nbinfo.faceArea;
905 if (dispersionActive || enableBioeffects) {
906 for (
unsigned phaseIdx = 0; phaseIdx < numEq; ++phaseIdx) {
907 velocityInfo_[globI][loc].velocity[phaseIdx] =
908 darcyFlux[phaseIdx].value() / nbInfo.res_nbinfo.faceArea;
912 residual_[globI] += res;
914 *diagMatAddress_[globI] += bMat;
917 *nbInfo.matBlockAddress += bMat;
923 const double volume = model_().dofTotalVolume(globI);
924 const Scalar storefac = volume / dt;
927 OPM_TIMEBLOCK_LOCAL(computeStorage, Subsystem::Assembly);
928 LocalResidual::computeStorage(adres, intQuantsIn);
932 if (model_().enableStorageCache()) {
936 model_().updateCachedStorage(globI, 0, res);
943 if (model_().newtonMethod().numIterations() == 0 && !isNlddLocalSolve) {
945 if (problem_().recycleFirstIterationStorage()) {
948 model_().updateCachedStorage(globI, 1, res);
951 Dune::FieldVector<Scalar, numEq> tmp;
952 const IntensiveQuantities intQuantOld = model_().intensiveQuantities(globI, 1);
953 LocalResidual::computeStorage(tmp, intQuantOld);
954 model_().updateCachedStorage(globI, 1, tmp);
957 res -= model_().cachedStorage(globI, 1);
960 OPM_TIMEBLOCK_LOCAL(computeStorage0, Subsystem::Assembly);
961 Dune::FieldVector<Scalar, numEq> tmp;
962 const IntensiveQuantities intQuantOld = model_().intensiveQuantities(globI, 1);
963 LocalResidual::computeStorage(tmp, intQuantOld);
969 residual_[globI] += res;
971 *diagMatAddress_[globI] += bMat;
978 if (separateSparseSourceTerms_) {
979 LocalResidual::computeSourceDense(adres, problem_(), intQuantsIn, globI, 0);
982 LocalResidual::computeSource(adres, problem_(), intQuantsIn, globI, 0);
986 residual_[globI] += res;
988 *diagMatAddress_[globI] += bMat;
992 if (separateSparseSourceTerms_) {
993 problem_().wellModel().addReservoirSourceTerms(residual_, diagMatAddress_);
997 for (
const auto& bdyInfo : boundaryInfo_) {
1002 VectorBlock res(0.0);
1003 MatrixBlock bMat(0.0);
1004 ADVectorBlock adres(0.0);
1005 const unsigned globI = bdyInfo.cell;
1006 const IntensiveQuantities& insideIntQuants = model_().intensiveQuantities(globI, 0);
1007 LocalResidual::computeBoundaryFlux(adres, problem_(), bdyInfo.bcdata, insideIntQuants, globI);
1008 adres *= bdyInfo.bcdata.faceArea;
1010 residual_[globI] += res;
1012 *diagMatAddress_[globI] += bMat;
1016 void updateStoredTransmissibilities()
1018 if (neighborInfo_.empty()) {
1022 initFirstIteration_();
1025 const unsigned numCells = model_().numTotalDof();
1027#pragma omp parallel for
1029 for (
unsigned globI = 0; globI < numCells; globI++) {
1030 auto nbInfos = neighborInfo_[globI];
1031 for (
auto& nbInfo : nbInfos) {
1032 const unsigned globJ = nbInfo.neighbor;
1033 nbInfo.res_nbinfo.trans = problem_().transmissibility(globI, globJ);
1038 Simulator* simulatorPtr_{};
1041 std::unique_ptr<SparseMatrixAdapter> jacobian_{};
1044 GlobalEqVector residual_;
1046 LinearizationType linearizationType_{};
1048 using ResidualNBInfo =
typename LocalResidual::ResidualNBInfo;
1049 using NeighborInfoCPU = NeighborInfoStruct<ResidualNBInfo, MatrixBlock>;
1051 SparseTable<NeighborInfoCPU> neighborInfo_{};
1052 std::vector<MatrixBlock*> diagMatAddress_{};
1060 SparseTable<FlowInfo> flowsInfo_;
1061 SparseTable<FlowInfo> floresInfo_;
1065 VectorBlock velocity;
1067 SparseTable<VelocityInfo> velocityInfo_;
1069 using ScalarFluidState =
typename IntensiveQuantities::ScalarFluidState;
1070 struct BoundaryConditionData
1073 VectorBlock massRate;
1074 unsigned pvtRegionIdx;
1075 unsigned boundaryFaceIndex;
1078 ScalarFluidState exFluidState;
1085 unsigned int bfIndex;
1086 BoundaryConditionData bcdata;
1088 std::vector<BoundaryInfo> boundaryInfo_;
1090 bool separateSparseSourceTerms_ =
false;
1092 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:189
const auto & getFloresInfo() const
Return constant reference to the floresInfo.
Definition: tpfalinearizer.hh:459
const LinearizationType & getLinearizationType() const
Definition: tpfalinearizer.hh:443
const auto & getNeighborInfo() const
Definition: tpfalinearizer.hh:470
void updateBoundaryConditionData()
Definition: tpfalinearizer.hh:480
void linearize()
Linearize the full system of non-linear equations.
Definition: tpfalinearizer.hh:291
SparseMatrixAdapter & jacobian()
Definition: tpfalinearizer.hh:410
const auto & getFlowsInfo() const
Return constant reference to the flowsInfo.
Definition: tpfalinearizer.hh:451
std::map< unsigned, Constraints > constraintsMap() const
Returns the map of constraint degrees of freedom.
Definition: tpfalinearizer.hh:504
TpfaLinearizer()
Definition: tpfalinearizer.hh:238
void finalize()
Definition: tpfalinearizer.hh:368
void init(Simulator &simulator)
Initialize the linearizer.
Definition: tpfalinearizer.hh:264
void updateFlowsInfo()
Definition: tpfalinearizer.hh:782
void setResAndJacobi(VectorBlock &res, MatrixBlock &bMat, const ADVectorBlock &resid) const
Definition: tpfalinearizer.hh:765
static void registerParameters()
Register all run-time parameters for the Jacobian linearizer.
Definition: tpfalinearizer.hh:249
void exportSystem(const int idx, std::string &tag, const char *path="export")
Export block sparse linear system.
Definition: tpfalinearizer.hh:425
void linearizeDomain()
Linearize the part of the non-linear system of equations that is associated with the spatial domain.
Definition: tpfalinearizer.hh:307
const SparseMatrixAdapter & jacobian() const
Return constant reference to global Jacobian matrix backend.
Definition: tpfalinearizer.hh:407
void setLinearizationType(LinearizationType linearizationType)
Definition: tpfalinearizer.hh:440
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:347
GlobalEqVector & residual()
Definition: tpfalinearizer.hh:419
void eraseMatrix()
Causes the Jacobian matrix to be recreated from scratch before the next iteration.
Definition: tpfalinearizer.hh:277
const auto & getVelocityInfo() const
Return constant reference to the velocityInfo.
Definition: tpfalinearizer.hh:467
void updateDiscretizationParameters()
Definition: tpfalinearizer.hh:475
void resetSystem_(const SubDomainType &domain)
Definition: tpfalinearizer.hh:508
void linearizeAuxiliaryEquations()
Linearize the part of the non-linear system of equations that is associated with the spatial domain.
Definition: tpfalinearizer.hh:375
const GlobalEqVector & residual() const
Return constant reference to global residual vector.
Definition: tpfalinearizer.hh:416
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
void exportSystem(const IstlMatrix &jacobian, const GlobalEqVector &residual, const bool export_sparsity, const char *tag, const char *path="export")
Export blocks-sparse linear system.
Definition: exportSystem.hpp:42
Definition: tpfalinearizer.hh:96
Storage cells
Definition: tpfalinearizer.hh:97
Definition: linearizationtype.hh:34
Definition: tpfalinearizer.hh:124
NeighborInfoStruct(unsigned int n, const ResidualNBInfoType &r, PtrType ptr)
Definition: tpfalinearizer.hh:141
NeighborInfoStruct()
Definition: tpfalinearizer.hh:149
NeighborInfoStruct(const NeighborInfoStruct< ResidualNBInfoType, OtherBlockType > &other)
Definition: tpfalinearizer.hh:130
BlockType * matBlockAddress
Definition: tpfalinearizer.hh:127
ResidualNBInfoType res_nbinfo
Definition: tpfalinearizer.hh:126
unsigned int neighbor
Definition: tpfalinearizer.hh:125
Definition: tpfalinearizer.hh:83
static constexpr bool value
Definition: tpfalinearizer.hh:83