From 7e8fd2457b60187ebf3ce2280e12849101730e70 Mon Sep 17 00:00:00 2001 From: David Landa Marban Date: Fri, 13 Feb 2026 15:37:03 +0100 Subject: [PATCH] BVEL[G|O|W][I|J|K][|-] summary keywords --- .../discretization/common/fvbaselinearizer.hh | 16 ++ .../discretization/common/tpfalinearizer.hh | 44 +++- opm/simulators/flow/FlowsContainer.cpp | 84 +++++-- opm/simulators/flow/FlowsContainer.hpp | 39 ++- opm/simulators/flow/OutputBlackoilModule.hpp | 225 +++++++++++++++++- 5 files changed, 375 insertions(+), 33 deletions(-) diff --git a/opm/models/discretization/common/fvbaselinearizer.hh b/opm/models/discretization/common/fvbaselinearizer.hh index d9cf6e0977..be0c1277d0 100644 --- a/opm/models/discretization/common/fvbaselinearizer.hh +++ b/opm/models/discretization/common/fvbaselinearizer.hh @@ -333,6 +333,15 @@ public: const auto& getFloresInfo() const { return floresInfo_; } + /*! + * \brief Return constant reference to the velocityInfo. + * + * (This object is only non-empty if dispersion, bioeffects, or block + * velocities are active.) + */ + const auto& getVelocityInfo() const + { return velocityInfo_; } + template void resetSystem_(const SubDomainType& domain) { @@ -684,6 +693,13 @@ private: SparseTable flowsInfo_; SparseTable floresInfo_; + struct VelocityInfo + { + int faceId; + VectorBlock velocity; + }; + SparseTable velocityInfo_; + // the jacobian matrix std::unique_ptr jacobian_; diff --git a/opm/models/discretization/common/tpfalinearizer.hh b/opm/models/discretization/common/tpfalinearizer.hh index aef98fb2e8..f87a7f81db 100644 --- a/opm/models/discretization/common/tpfalinearizer.hh +++ b/opm/models/discretization/common/tpfalinearizer.hh @@ -462,7 +462,8 @@ public: /*! * \brief Return constant reference to the velocityInfo. * - * (This object is only non-empty if the DISPERC keyword is true.) + * (This object is only non-empty if dispersion, bioeffects, or block + * velocities are active.) */ const auto& getVelocityInfo() const { return velocityInfo_; } @@ -675,15 +676,17 @@ private: void createFlows_() { OPM_TIMEBLOCK(createFlows); - // If FLOWS/FLORES is set in any RPTRST in the schedule, then we initializate the sparse tables - // For now, do the same also if any block flows are requested (TODO: only save requested cells...) + // If FLOWS/FLORES is set in any RPTRST in the schedule, then we initializate the sparse tables. // If DISPERC is in the deck, we initialize the sparse table here as well. const bool anyFlows = simulator_().problem().eclWriter().outputModule().getFlows().anyFlows(); const auto& blockFlows = simulator_().problem().eclWriter().outputModule().getFlows().blockFlows(); + const auto& blockVelocity = simulator_().problem().eclWriter().outputModule().getFlows().blockVelocity(); const bool isTemp = simulator_().vanguard().eclState().getSimulationConfig().isTemp(); const bool anyFlores = simulator_().problem().eclWriter().outputModule().getFlows().anyFlores() || isTemp; const bool dispersionActive = simulator_().vanguard().eclState().getSimulationConfig().rock_config().dispersion(); - if (((!(anyFlows || !blockFlows.empty()) || !flowsInfo_.empty()) && (!anyFlores || !floresInfo_.empty())) && (!dispersionActive && !enableBioeffects)) { + if (!dispersionActive && !enableBioeffects && blockVelocity.empty() + && !((anyFlows || !blockFlows.empty()) && flowsInfo_.empty()) + && !(anyFlores && floresInfo_.empty())) { return; } const auto& model = model_(); @@ -715,12 +718,16 @@ private: if (dispersionActive || enableBioeffects) { velocityInfo_.reserve(numCells, 6 * numCells); } + else if (!blockVelocity.empty()) { + velocityInfo_.reserve(numCells, 6 * blockVelocity.size()); + } for (const auto& elem : elements(gridView_())) { stencil.update(elem); for (unsigned primaryDofIdx = 0; primaryDofIdx < stencil.numPrimaryDof(); ++primaryDofIdx) { const unsigned myIdx = stencil.globalSpaceIndex(primaryDofIdx); bool blockFlowFound = false; + bool blockVelocityFound = false; if (!blockFlows.empty()) { if (std::binary_search(blockFlows.begin(), blockFlows.end(), simulator_().vanguard().cartesianIndex(myIdx))) { @@ -728,7 +735,19 @@ private: } else { flowsInfo_.appendRow(loc_flinfo.begin(), loc_flinfo.begin()); - if (!dispersionActive && !enableBioeffects && !anyFlores) { + if (!dispersionActive && !enableBioeffects && !anyFlores && blockVelocity.empty()) { + continue; + } + } + } + if (!blockVelocity.empty() && !(dispersionActive || enableBioeffects)) { + if (std::binary_search(blockVelocity.begin(), blockVelocity.end(), + simulator_().vanguard().cartesianIndex(myIdx))) { + blockVelocityFound = true; + } + else { + velocityInfo_.appendRow(loc_vlinfo.begin(), loc_vlinfo.begin()); + if (!anyFlows && blockFlows.empty() && !anyFlores) { continue; } } @@ -755,7 +774,7 @@ private: } } loc_flinfo[dofIdx - 1] = FlowInfo{faceId, flow, nncId}; - loc_vlinfo[dofIdx - 1] = VelocityInfo{flow}; + loc_vlinfo[dofIdx - 1] = VelocityInfo{faceId, flow}; } } @@ -771,7 +790,7 @@ private: if (anyFlores) { floresInfo_.appendRow(loc_flinfo.begin(), loc_flinfo.end()); } - if (dispersionActive || enableBioeffects) { + if (dispersionActive || enableBioeffects || blockVelocityFound) { velocityInfo_.appendRow(loc_vlinfo.begin(), loc_vlinfo.end()); } } @@ -895,6 +914,7 @@ private: // the full system to zero, not just our part. // Instead, that must be called before starting the linearization. const bool dispersionActive = simulator_().vanguard().eclState().getSimulationConfig().rock_config().dispersion(); + const auto& blockVelocity = simulator_().problem().eclWriter().outputModule().getFlows().blockVelocity(); const unsigned int numCells = domain.cells.size(); // Fetch timestepsize used later in accumulation term. @@ -935,6 +955,15 @@ private: darcyFlux[phaseIdx].value() / nbInfo.res_nbinfo.faceArea; } } + else if (!blockVelocity.empty()) { + if (std::binary_search(blockVelocity.begin(), blockVelocity.end(), + simulator_().vanguard().cartesianIndex(globI))) { + for (unsigned phaseIdx = 0; phaseIdx < numEq; ++phaseIdx) { + velocityInfo_[globI][loc].velocity[phaseIdx] = + darcyFlux[phaseIdx].value() / nbInfo.res_nbinfo.faceArea; + } + } + } setResAndJacobi(res, bMat, adres); residual_[globI] += res; //SparseAdapter syntax: jacobian_->addToBlock(globI, globI, bMat); @@ -1089,6 +1118,7 @@ private: struct VelocityInfo { + int faceId; VectorBlock velocity; }; SparseTable velocityInfo_; diff --git a/opm/simulators/flow/FlowsContainer.cpp b/opm/simulators/flow/FlowsContainer.cpp index 7f24c14a50..70aaa945e8 100644 --- a/opm/simulators/flow/FlowsContainer.cpp +++ b/opm/simulators/flow/FlowsContainer.cpp @@ -89,7 +89,18 @@ FlowsContainer(const Schedule& schedule, const SummaryConfig& summaryConfig, std::function isInterior) { + using namespace std::string_literals; using Dir = FaceDir::DirEnum; + const std::array phaseIdxs = {gasPhaseIdx, oilPhaseIdx, waterPhaseIdx}; + const std::array compIdxs = {gasCompIdx, oilCompIdx, waterCompIdx}; + const auto nameIdxs = std::array{ "G"s, "O"s, "W"s }; + const auto ijkIdxs = std::array{ "I-"s, "I"s, "J-"s, "J"s, "K-"s, "K"s }; + const auto dirIdxs = std::array{ FaceDir::ToIntersectionIndex(Dir::XMinus), + FaceDir::ToIntersectionIndex(Dir::XPlus), + FaceDir::ToIntersectionIndex(Dir::YMinus), + FaceDir::ToIntersectionIndex(Dir::YPlus), + FaceDir::ToIntersectionIndex(Dir::ZMinus), + FaceDir::ToIntersectionIndex(Dir::ZPlus) }; // Check if FLORES/FLOWS is set in any RPTRST in the schedule enableFlores_ = false; // Used for the output of i+, j+, k+ @@ -110,18 +121,31 @@ FlowsContainer(const Schedule& schedule, return rstkw.find("FLOWS") != rstkw.end(); }); + // Check for any BVEL[G|O|W][I|J|K][|-] summary keys + if (summaryConfig.keywords("BVEL*").size() > 0) { + for (unsigned ii = 0; ii < phaseIdxs.size(); ++ii) { + if (FluidSystem::phaseIsActive(phaseIdxs[ii])) { + for (unsigned jj = 0; jj < dirIdxs.size(); ++jj) { + std::string blockid = "BVEL" + nameIdxs[ii] + ijkIdxs[jj]; + if (summaryConfig.keywords(blockid).size() == 0) { + continue; + } + for (const auto& node : summaryConfig.keywords(blockid)) { + if (isInterior(node.number() - 1)) { + blockVelocityIds_[compIdxs[ii]][dirIdxs[jj]].push_back(node.number() - 1); + blockVelocityAllIds_.push_back(node.number() - 1); + } + } + } + } + } + std::sort(blockVelocityAllIds_.begin(), blockVelocityAllIds_.end()); + auto last = std::unique(blockVelocityAllIds_.begin(), blockVelocityAllIds_.end()); + blockVelocityAllIds_.erase(last, blockVelocityAllIds_.end()); + } + // Check for any BFLO[G|O|W][I|J|K][|-] summary keys if (summaryConfig.keywords("BFLO*").size() > 0 && !anyFlows_) { - const std::array phaseIdxs { gasPhaseIdx, oilPhaseIdx, waterPhaseIdx }; - const std::array compIdxs { gasCompIdx, oilCompIdx, waterCompIdx }; - const std::string nameIdxs[3] { "G", "O", "W" }; - const std::string ijkIdxs[6] { "I-", "I", "J-", "J", "K-", "K" }; - const std::array dirIdxs { FaceDir::ToIntersectionIndex(Dir::XMinus), - FaceDir::ToIntersectionIndex(Dir::XPlus), - FaceDir::ToIntersectionIndex(Dir::YMinus), - FaceDir::ToIntersectionIndex(Dir::YPlus), - FaceDir::ToIntersectionIndex(Dir::ZMinus), - FaceDir::ToIntersectionIndex(Dir::ZPlus) }; for (unsigned ii = 0; ii < phaseIdxs.size(); ++ii) { if (FluidSystem::phaseIsActive(phaseIdxs[ii])) { for (unsigned jj = 0; jj < dirIdxs.size(); ++jj) { @@ -152,17 +176,29 @@ allocate(const std::size_t bufferSize, const bool allocRestart, std::map& rstKeywords) { + using namespace std::string_literals; using Dir = FaceDir::DirEnum; - const std::array phaseIdxs { gasPhaseIdx, oilPhaseIdx, waterPhaseIdx }; - const std::array compIdxs { gasCompIdx, oilCompIdx, waterCompIdx }; - const std::string nameIdxs[3] { "G", "O", "W" }; - const std::string ijkIdxs[6] { "I-", "I", "J-", "J", "K-", "K" }; - const std::array dirIdxs { FaceDir::ToIntersectionIndex(Dir::XMinus), - FaceDir::ToIntersectionIndex(Dir::XPlus), - FaceDir::ToIntersectionIndex(Dir::YMinus), - FaceDir::ToIntersectionIndex(Dir::YPlus), - FaceDir::ToIntersectionIndex(Dir::ZMinus), - FaceDir::ToIntersectionIndex(Dir::ZPlus) }; + const std::array phaseIdxs = {gasPhaseIdx, oilPhaseIdx, waterPhaseIdx}; + const std::array compIdxs = {gasCompIdx, oilCompIdx, waterCompIdx}; + const auto nameIdxs = std::array{ "G"s, "O"s, "W"s }; + const auto ijkIdxs = std::array{ "I-"s, "I"s, "J-"s, "J"s, "K-"s, "K"s }; + const auto dirIdxs = std::array{ FaceDir::ToIntersectionIndex(Dir::XMinus), + FaceDir::ToIntersectionIndex(Dir::XPlus), + FaceDir::ToIntersectionIndex(Dir::YMinus), + FaceDir::ToIntersectionIndex(Dir::YPlus), + FaceDir::ToIntersectionIndex(Dir::ZMinus), + FaceDir::ToIntersectionIndex(Dir::ZPlus) }; + + // Allocate vels for BVEL[G|O|W][I|J|K][|-] summary keywords + if (!blockVelocityAllIds_.empty()) { + for (unsigned ii = 0; ii < phaseIdxs.size(); ++ii) { + if (FluidSystem::phaseIsActive(phaseIdxs[ii])) { + for (unsigned jj = 0; jj < dirIdxs.size(); ++jj) { + velocity_[compIdxs[ii]][dirIdxs[jj]].resize(blockVelocityIds_[compIdxs[ii]][dirIdxs[jj]].size(), 0.0); + } + } + } + } // Allocate flows for BFLO[G|O|W][I|J|K][|-] summary keywords if (!blockFlowsAllIds_.empty()) { @@ -304,6 +340,14 @@ assignFlows(const unsigned globalDofIdx, } } +template +void FlowsContainer:: +assignBlockVelocity(const unsigned index, + const int faceId, + const int comp_idx, + const Scalar velocity) +{ velocity_[comp_idx][faceId][index] = velocity; } + template void FlowsContainer:: assignBlockFlows(const unsigned index, diff --git a/opm/simulators/flow/FlowsContainer.hpp b/opm/simulators/flow/FlowsContainer.hpp index 9dc6a63121..ee408894d5 100644 --- a/opm/simulators/flow/FlowsContainer.hpp +++ b/opm/simulators/flow/FlowsContainer.hpp @@ -72,6 +72,11 @@ public: const Scalar oil, const Scalar water); + void assignBlockVelocity(const unsigned globalDofIdx, + const int faceId, + const int comp_idx, + const Scalar velocity); + void assignBlockFlows(const unsigned globalDofIdx, const int faceId, const int comp_idx, @@ -95,6 +100,9 @@ public: bool hasFlows() const { return enableFlows_; } + const std::vector blockVelocity() const + { return blockVelocityAllIds_; } + const std::vector blockFlows() const { return blockFlowsAllIds_; } @@ -107,6 +115,15 @@ public: return std::distance(blockIdxs.begin(), it); } + unsigned blockVelocityIds(const unsigned globalDofIdx, + const int dir, + const int comp_idx) const + { + const auto& blockIdxs = blockVelocityIds_[comp_idx][dir]; + auto it = std::lower_bound(blockIdxs.begin(), blockIdxs.end(), globalDofIdx); + return std::distance(blockIdxs.begin(), it); + } + bool anyFlows() const { return anyFlows_; } @@ -122,14 +139,27 @@ public: bool anyFlores() const { return anyFlores_; } - bool hasBlockValue(const unsigned globalDofIdx, - const int dir, - const int comp_idx) const + bool hasBlockVelocityValue(const unsigned globalDofIdx, + const int dir, + const int comp_idx) const + { + const auto& blockIdxs = blockVelocityIds_[comp_idx][dir]; + return std::binary_search(blockIdxs.begin(), blockIdxs.end(), globalDofIdx); + } + + bool hasBlockFlowValue(const unsigned globalDofIdx, + const int dir, + const int comp_idx) const { const auto& blockIdxs = blockFlowsIds_[comp_idx][dir]; return std::binary_search(blockIdxs.begin(), blockIdxs.end(), globalDofIdx); } + Scalar getVelocity(const unsigned globalDofIdx, + const FaceDir::DirEnum dir, + const int comp_idx) const + { return velocity_[comp_idx][FaceDir::ToIntersectionIndex(dir)][globalDofIdx]; } + Scalar getFlow(const unsigned globalDofIdx, const FaceDir::DirEnum dir, const int comp_idx) const @@ -145,12 +175,15 @@ private: std::array, numPhases> flows_; std::array, numPhases> flores_; + std::array, numPhases> velocity_; std::array, 3> floresn_; std::array, 3> flowsn_; std::vector blockFlowsAllIds_; + std::vector blockVelocityAllIds_; std::array, 6>, numPhases> blockFlowsIds_; + std::array, 6>, numPhases> blockVelocityIds_; }; } // namespace Opm diff --git a/opm/simulators/flow/OutputBlackoilModule.hpp b/opm/simulators/flow/OutputBlackoilModule.hpp index 6b627a23ac..25657548df 100644 --- a/opm/simulators/flow/OutputBlackoilModule.hpp +++ b/opm/simulators/flow/OutputBlackoilModule.hpp @@ -1652,14 +1652,22 @@ private: const std::vector& blockIdxs = flowsC.blockFlows(); const unsigned cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx); if (std::binary_search(blockIdxs.begin(), blockIdxs.end(), cartesianIdx)) { - const std::array compIdxs { gasCompIdx, oilCompIdx, waterCompIdx }; + const auto compIdxs = std::array{ gasCompIdx, oilCompIdx, waterCompIdx }; + const auto compEnabled = std::array{ Indices::gasEnabled, Indices::oilEnabled, Indices::waterEnabled }; for (const auto& flowsInfo : flowsInfos) { + if (flowsInfo.faceId < 0) { + continue; + } for (unsigned ii = 0; ii < compIdxs.size(); ++ii) { - if (flowsC.hasBlockValue(cartesianIdx, flowsInfo.faceId, compIdxs[ii])) {; + if (!compEnabled[ii]) { + continue; + } + if (flowsC.hasBlockFlowValue(cartesianIdx, flowsInfo.faceId, compIdxs[ii])) { flowsC.assignBlockFlows(flowsC.blockFlowsIds(cartesianIdx, flowsInfo.faceId, compIdxs[ii]), flowsInfo.faceId, compIdxs[ii], - flowsInfo.flow[compIdxs[ii]]); + flowsInfo.flow[conti0EqIdx + + FluidSystem::canonicalToActiveCompIdx(compIdxs[ii])]); } } } @@ -1697,6 +1705,37 @@ private: } }, !this->simulator_.problem().model().linearizer().getFloresInfo().empty() }, + Entry{[&velocityInf = this->simulator_.problem().model().linearizer().getVelocityInfo(), + &flowsC = this->flowsC_, + &vanguard = this->simulator_.vanguard()](const Context& ectx) + { + const auto& velocityInfos = velocityInf[ectx.globalDofIdx]; + const std::vector& blockIdxs = flowsC.blockVelocity(); + const unsigned cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx); + if (std::binary_search(blockIdxs.begin(), blockIdxs.end(), cartesianIdx)) { + const auto compIdxs = std::array{ gasCompIdx, oilCompIdx, waterCompIdx }; + const auto compEnabled = std::array{ Indices::gasEnabled, Indices::oilEnabled, Indices::waterEnabled }; + for (const auto& velocityInfo : velocityInfos) { + if (velocityInfo.faceId < 0) { + continue; + } + for (unsigned ii = 0; ii < compIdxs.size(); ++ii) { + if (!compEnabled[ii]) { + continue; + } + if (flowsC.hasBlockVelocityValue(cartesianIdx, velocityInfo.faceId, compIdxs[ii])) { + flowsC.assignBlockVelocity(flowsC.blockVelocityIds(cartesianIdx, velocityInfo.faceId, compIdxs[ii]), + velocityInfo.faceId, + compIdxs[ii], + velocityInfo.velocity[conti0EqIdx + + FluidSystem::canonicalToActiveCompIdx(compIdxs[ii])]); + } + } + } + } + }, !this->flowsC_.blockVelocity().empty() && + !this->simulator_.problem().model().linearizer().getVelocityInfo().empty() + }, // hack to make the intial output of rs and rv Ecl compatible. // For cells with swat == 1 Ecl outputs; rs = rsSat and rv=rvSat, in all but the initial step // where it outputs rs and rv values calculated by the initialization. To be compatible we overwrite @@ -2164,6 +2203,186 @@ private: } } }, + Entry{ScalarEntry{"BVELGI", + [&flowsC = this->flowsC_, + &vanguard = this->simulator_.vanguard()](const Context& ectx) + { + const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx), + FaceDir::ToIntersectionIndex(Dir::XPlus), gasCompIdx); + return flowsC.getVelocity(index, Dir::XPlus, gasCompIdx); + } + } + }, + Entry{ScalarEntry{"BVELGI-", + [&flowsC = this->flowsC_, + &vanguard = this->simulator_.vanguard()](const Context& ectx) + { + const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx), + FaceDir::ToIntersectionIndex(Dir::XMinus), gasCompIdx); + return flowsC.getVelocity(index, Dir::XMinus, gasCompIdx); + } + } + }, + Entry{ScalarEntry{"BVELGJ", + [&flowsC = this->flowsC_, + &vanguard = this->simulator_.vanguard()](const Context& ectx) + { + const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx), + FaceDir::ToIntersectionIndex(Dir::YPlus), gasCompIdx); + return flowsC.getVelocity(index, Dir::YPlus, gasCompIdx); + } + } + }, + Entry{ScalarEntry{"BVELGJ-", + [&flowsC = this->flowsC_, + &vanguard = this->simulator_.vanguard()](const Context& ectx) + { + const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx), + FaceDir::ToIntersectionIndex(Dir::YMinus), gasCompIdx); + return flowsC.getVelocity(index, Dir::YMinus, gasCompIdx); + } + } + }, + Entry{ScalarEntry{"BVELGK", + [&flowsC = this->flowsC_, + &vanguard = this->simulator_.vanguard()](const Context& ectx) + { + const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx), + FaceDir::ToIntersectionIndex(Dir::ZPlus), gasCompIdx); + return flowsC.getVelocity(index, Dir::ZPlus, gasCompIdx); + } + } + }, + Entry{ScalarEntry{"BVELGK-", + [&flowsC = this->flowsC_, + &vanguard = this->simulator_.vanguard()](const Context& ectx) + { + const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx), + FaceDir::ToIntersectionIndex(Dir::ZMinus), gasCompIdx); + return flowsC.getVelocity(index, Dir::ZMinus, gasCompIdx); + } + } + }, + Entry{ScalarEntry{"BVELOI", + [&flowsC = this->flowsC_, + &vanguard = this->simulator_.vanguard()](const Context& ectx) + { + const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx), + FaceDir::ToIntersectionIndex(Dir::XPlus), oilCompIdx); + return flowsC.getVelocity(index, Dir::XPlus, oilCompIdx); + } + } + }, + Entry{ScalarEntry{"BVELOI-", + [&flowsC = this->flowsC_, + &vanguard = this->simulator_.vanguard()](const Context& ectx) + { + const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx), + FaceDir::ToIntersectionIndex(Dir::XMinus), oilCompIdx); + return flowsC.getVelocity(index, Dir::XMinus, oilCompIdx); + } + } + }, + Entry{ScalarEntry{"BVELOJ", + [&flowsC = this->flowsC_, + &vanguard = this->simulator_.vanguard()](const Context& ectx) + { + const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx), + FaceDir::ToIntersectionIndex(Dir::YPlus), oilCompIdx); + return flowsC.getVelocity(index, Dir::YPlus, oilCompIdx); + } + } + }, + Entry{ScalarEntry{"BVELOJ-", + [&flowsC = this->flowsC_, + &vanguard = this->simulator_.vanguard()](const Context& ectx) + { + const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx), + FaceDir::ToIntersectionIndex(Dir::YMinus), oilCompIdx); + return flowsC.getVelocity(index, Dir::YMinus, oilCompIdx); + } + } + }, + Entry{ScalarEntry{"BVELOK", + [&flowsC = this->flowsC_, + &vanguard = this->simulator_.vanguard()](const Context& ectx) + { + const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx), + FaceDir::ToIntersectionIndex(Dir::ZPlus), oilCompIdx); + return flowsC.getVelocity(index, Dir::ZPlus, oilCompIdx); + } + } + }, + Entry{ScalarEntry{"BVELOK-", + [&flowsC = this->flowsC_, + &vanguard = this->simulator_.vanguard()](const Context& ectx) + { + const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx), + FaceDir::ToIntersectionIndex(Dir::ZMinus), oilCompIdx); + return flowsC.getVelocity(index, Dir::ZMinus, oilCompIdx); + } + } + }, + Entry{ScalarEntry{"BVELWI", + [&flowsC = this->flowsC_, + &vanguard = this->simulator_.vanguard()](const Context& ectx) + { + const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx), + FaceDir::ToIntersectionIndex(Dir::XPlus), waterCompIdx); + return flowsC.getVelocity(index, Dir::XPlus, waterCompIdx); + } + } + }, + Entry{ScalarEntry{"BVELWI-", + [&flowsC = this->flowsC_, + &vanguard = this->simulator_.vanguard()](const Context& ectx) + { + const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx), + FaceDir::ToIntersectionIndex(Dir::XMinus), waterCompIdx); + return flowsC.getVelocity(index, Dir::XMinus, waterCompIdx); + } + } + }, + Entry{ScalarEntry{"BVELWJ", + [&flowsC = this->flowsC_, + &vanguard = this->simulator_.vanguard()](const Context& ectx) + { + const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx), + FaceDir::ToIntersectionIndex(Dir::YPlus), waterCompIdx); + return flowsC.getVelocity(index, Dir::YPlus, waterCompIdx); + } + } + }, + Entry{ScalarEntry{"BVELWJ-", + [&flowsC = this->flowsC_, + &vanguard = this->simulator_.vanguard()](const Context& ectx) + { + const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx), + FaceDir::ToIntersectionIndex(Dir::YMinus), waterCompIdx); + return flowsC.getVelocity(index, Dir::YMinus, waterCompIdx); + } + } + }, + Entry{ScalarEntry{"BVELWK", + [&flowsC = this->flowsC_, + &vanguard = this->simulator_.vanguard()](const Context& ectx) + { + const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx), + FaceDir::ToIntersectionIndex(Dir::ZPlus), waterCompIdx); + return flowsC.getVelocity(index, Dir::ZPlus, waterCompIdx); + } + } + }, + Entry{ScalarEntry{"BVELWK-", + [&flowsC = this->flowsC_, + &vanguard = this->simulator_.vanguard()](const Context& ectx) + { + const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx), + FaceDir::ToIntersectionIndex(Dir::ZMinus), waterCompIdx); + return flowsC.getVelocity(index, Dir::ZMinus, waterCompIdx); + } + } + }, Entry{ScalarEntry{"BRPV", [&model = this->simulator_.model()](const Context& ectx) {