105 using Element =
typename GridView::template Codim<0>::Entity;
106 using ElementIterator =
typename GridView::template Codim<0>::Iterator;
108 using Vector = GlobalEqVector;
112 enum { dimWorld = GridView::dimensionworld };
114 using MatrixBlock =
typename SparseMatrixAdapter::MatrixBlock;
115 using VectorBlock = Dune::FieldVector<Scalar, numEq>;
132 simulatorPtr_ =
nullptr;
133 separateSparseSourceTerms_ = Parameters::Get<Parameters::SeparateSparseSourceTerms>();
141 Parameters::Register<Parameters::SeparateSparseSourceTerms>
142 (
"Treat well source terms all in one go, instead of on a cell by cell basis.");
156 simulatorPtr_ = &simulator;
204 catch (
const std::exception&
e) {
205 std::cout <<
"rank " << simulator_().
gridView().comm().rank()
206 <<
" caught an exception while linearizing:" <<
e.what()
207 <<
"\n" << std::flush;
211 std::cout <<
"rank " << simulator_().
gridView().comm().rank()
212 <<
" caught an exception while linearizing"
213 <<
"\n" << std::flush;
219 throw NumericalProblem(
"A process did not succeed in linearizing the system");
233 template <
class SubDomainType>
241 initFirstIteration_();
245 if (
domain.cells.size() == model_().numTotalDof()) {
257 { jacobian_->finalize(); }
269 auto& model = model_();
270 const auto& comm = simulator_().
gridView().comm();
274 model.auxiliaryModule(
auxModIdx)->linearize(*jacobian_, residual_);
276 catch (
const std::exception&
e) {
279 std::cout <<
"rank " << simulator_().
gridView().comm().rank()
280 <<
" caught an exception while linearizing:" <<
e.what()
281 <<
"\n" << std::flush;
296 {
return *jacobian_; }
299 {
return *jacobian_; }
305 {
return residual_; }
308 {
return residual_; }
310 void setLinearizationType(LinearizationType linearizationType)
311 { linearizationType_ = linearizationType; }
313 const LinearizationType& getLinearizationType()
const
314 {
return linearizationType_; }
322 {
return flowsInfo_; }
330 {
return floresInfo_; }
338 {
return velocityInfo_; }
340 void updateDiscretizationParameters()
342 updateStoredTransmissibilities();
345 void updateBoundaryConditionData()
347 for (
auto&
bdyInfo : boundaryInfo_) {
355 if (type != BCType::NONE) {
356 const auto& exFluidState = problem_().boundaryFluidState(
bdyInfo.cell,
bdyInfo.dir);
359 bdyInfo.bcdata.exFluidState = exFluidState;
372 template <
class SubDomainType>
376 initFirstIteration_();
379 residual_[
globI] = 0.0;
380 jacobian_->clearRow(
globI, 0.0);
385 Simulator& simulator_()
386 {
return *simulatorPtr_; }
388 const Simulator& simulator_()
const
389 {
return *simulatorPtr_; }
392 {
return simulator_().
problem(); }
394 const Problem& problem_()
const
395 {
return simulator_().
problem(); }
398 {
return simulator_().
model(); }
400 const Model& model_()
const
401 {
return simulator_().
model(); }
403 const GridView& gridView_()
const
404 {
return problem_().gridView(); }
406 void initFirstIteration_()
412 residual_.resize(model_().numTotalDof());
423 if (!neighborInfo_.empty()) {
428 const auto& model = model_();
429 Stencil stencil(gridView_(), model_().dofMapper());
433 using NeighborSet = std::set<unsigned>;
435 const Scalar gravity = problem_().gravity()[dimWorld - 1];
436 unsigned numCells = model.numTotalDof();
437 neighborInfo_.reserve(numCells, 6 * numCells);
440 stencil.update(
elem);
446 for (
unsigned dofIdx = 0; dofIdx < stencil.numDof(); ++dofIdx) {
447 const unsigned neighborIdx = stencil.globalSpaceIndex(dofIdx);
451 const auto scvfIdx = dofIdx - 1;
453 const Scalar area =
scvf.area();
454 const Scalar Vin = problem_().model().dofTotalVolume(
myIdx);
455 const Scalar Vex = problem_().model().dofTotalVolume(
neighborIdx);
456 const Scalar
zIn = problem_().dofCenterDepth(
myIdx);
458 const Scalar dZg = (
zIn -
zEx)*gravity;
460 const auto dirId =
scvf.dirId();
461 auto faceDir = dirId < 0 ? FaceDir::DirEnum::Unknown
462 : FaceDir::FromIntersectionIndex(dirId);
463 ResidualNBInfo
nbinfo{trans, area, thpres, dZg, faceDir, Vin, Vex, {}, {}, {}, {}};
464 if constexpr (enableEnergy) {
468 if constexpr (enableDiffusion) {
471 if constexpr (enableDispersion) {
478 if (problem_().nonTrivialBoundaryConditions()) {
479 for (
unsigned bfIndex = 0; bfIndex < stencil.numBoundaryFaces(); ++bfIndex) {
480 const auto&
bf = stencil.boundaryFace(bfIndex);
492 const auto& exFluidState = problem_().boundaryFluidState(
myIdx,
dir_id);
493 BoundaryConditionData bcdata{type,
495 exFluidState.pvtRegionIndex(),
498 bf.integrationPos()[dimWorld - 1],
500 boundaryInfo_.push_back({
myIdx,
dir_id, bfIndex, bcdata});
508 const std::size_t
numAuxMod = model.numAuxiliaryModules();
514 jacobian_ = std::make_unique<SparseMatrixAdapter>(simulator_());
515 diagMatAddress_.resize(numCells);
527 fullDomain_.cells.resize(numCells);
528 std::iota(fullDomain_.cells.begin(), fullDomain_.cells.end(), 0);
546 const bool anyFlows = simulator_().
problem().eclWriter().outputModule().getFlows().anyFlows() ||
547 simulator_().
problem().eclWriter().outputModule().getFlows().hasBlockFlows();
548 const bool anyFlores = simulator_().
problem().eclWriter().outputModule().getFlows().anyFlores();
550 if (((!anyFlows || !flowsInfo_.empty()) && (!anyFlores || !floresInfo_.empty())) && (!
dispersionActive && !enableBioeffects)) {
553 const auto& model = model_();
555 Stencil stencil(gridView_(), model_().dofMapper());
556 const unsigned numCells = model.numTotalDof();
557 std::unordered_multimap<int, std::pair<int, int>>
nncIndices;
560 unsigned int nncId = 0;
561 VectorBlock flow(0.0);
571 flowsInfo_.reserve(numCells, 6 * numCells);
574 floresInfo_.reserve(numCells, 6 * numCells);
577 velocityInfo_.reserve(numCells, 6 * numCells);
581 stencil.update(
elem);
584 const int numFaces = stencil.numBoundaryFaces() + stencil.numInteriorFaces();
588 for (
unsigned dofIdx = 0; dofIdx < stencil.numDof(); ++dofIdx) {
589 const unsigned neighborIdx = stencil.globalSpaceIndex(dofIdx);
591 const auto scvfIdx = dofIdx - 1;
593 int faceId =
scvf.dirId();
597 for (
auto it =
range.first; it !=
range.second; ++it) {
602 nncId = it->second.second;
605 loc_flinfo[dofIdx - 1] = FlowInfo{faceId, flow, nncId};
611 const auto&
scvf = stencil.boundaryFace(
bdfIdx);
612 const int faceId =
scvf.dirId();
613 loc_flinfo[stencil.numInteriorFaces() +
bdfIdx] = FlowInfo{faceId, flow, nncId};
647 void updateFlowsInfo()
650 const bool enableFlows = simulator_().
problem().eclWriter().outputModule().getFlows().hasFlows() ||
651 simulator_().
problem().eclWriter().outputModule().getFlows().hasBlockFlows();
652 const bool enableFlores = simulator_().
problem().eclWriter().outputModule().getFlows().hasFlores();
656 const unsigned int numCells = model_().numTotalDof();
658#pragma omp parallel for
665 const IntensiveQuantities&
intQuantsIn = model_().intensiveQuantities(
globI, 0);
676 const IntensiveQuantities&
intQuantsEx = model_().intensiveQuantities(
globJ, 0);
696 for (
const auto&
bdyInfo : boundaryInfo_) {
697 if (
bdyInfo.bcdata.type == BCType::NONE) {
707 const unsigned bfIndex =
bdyInfo.bfIndex;
718 template <
class SubDomainType>
724 if (!problem_().recycleFirstIterationStorage()) {
725 if (!model_().storeIntensiveQuantities() && !model_().enableStorageCache()) {
726 OPM_THROW(std::runtime_error,
"Must have cached either IQs or storage when we cannot recycle.");
736 const unsigned int numCells =
domain.cells.size();
743#pragma omp parallel for
745 for (
unsigned ii = 0;
ii < numCells; ++
ii) {
749 VectorBlock
res(0.0);
750 MatrixBlock
bMat(0.0);
753 const IntensiveQuantities&
intQuantsIn = model_().intensiveQuantities(
globI, 0);
767 const IntensiveQuantities&
intQuantsEx = model_().intensiveQuantities(
globJ, 0);
769 nbInfo.res_nbinfo, problem_().moduleParams());
789 const double volume = model_().dofTotalVolume(
globI);
798 if (model_().enableStorageCache()) {
802 model_().updateCachedStorage(
globI, 0,
res);
803 if (model_().newtonMethod().numIterations() == 0) {
805 if (problem_().recycleFirstIterationStorage()) {
815 model_().updateCachedStorage(
globI, 1,
res);
819 Dune::FieldVector<Scalar, numEq> tmp;
820 const IntensiveQuantities
intQuantOld = model_().intensiveQuantities(
globI, 1);
822 model_().updateCachedStorage(
globI, 1, tmp);
825 res -= model_().cachedStorage(
globI, 1);
829 Dune::FieldVector<Scalar, numEq> tmp;
830 const IntensiveQuantities
intQuantOld = model_().intensiveQuantities(
globI, 1);
846 if (separateSparseSourceTerms_) {
860 if (separateSparseSourceTerms_) {
861 problem_().wellModel().addReservoirSourceTerms(residual_, diagMatAddress_);
865 for (
const auto&
bdyInfo : boundaryInfo_) {
866 if (
bdyInfo.bcdata.type == BCType::NONE) {
870 VectorBlock
res(0.0);
871 MatrixBlock
bMat(0.0);
884 void updateStoredTransmissibilities()
886 if (neighborInfo_.empty()) {
890 initFirstIteration_();
893 const unsigned numCells = model_().numTotalDof();
895#pragma omp parallel for
906 Simulator* simulatorPtr_{};
909 std::unique_ptr<SparseMatrixAdapter> jacobian_{};
912 GlobalEqVector residual_;
914 LinearizationType linearizationType_{};
916 using ResidualNBInfo =
typename LocalResidual::ResidualNBInfo;
919 unsigned int neighbor;
920 ResidualNBInfo res_nbinfo;
921 MatrixBlock* matBlockAddress;
923 SparseTable<NeighborInfo> neighborInfo_{};
924 std::vector<MatrixBlock*> diagMatAddress_{};
932 SparseTable<FlowInfo> flowsInfo_;
933 SparseTable<FlowInfo> floresInfo_;
937 VectorBlock velocity;
939 SparseTable<VelocityInfo> velocityInfo_;
941 using ScalarFluidState =
typename IntensiveQuantities::ScalarFluidState;
942 struct BoundaryConditionData
945 VectorBlock massRate;
946 unsigned pvtRegionIdx;
947 unsigned boundaryFaceIndex;
950 ScalarFluidState exFluidState;
957 unsigned int bfIndex;
958 BoundaryConditionData bcdata;
960 std::vector<BoundaryInfo> boundaryInfo_;
962 bool separateSparseSourceTerms_ =
false;
966 std::vector<int> cells;
967 std::vector<bool> interior;
969 FullDomain fullDomain_;