22#ifndef HYBRID_NEWTON_HPP
23#define HYBRID_NEWTON_HPP
28#include <opm/input/eclipse/Units/UnitSystem.hpp>
30#include <opm/ml/ml_model.hpp>
57template <
typename TypeTag>
102 if (!Parameters::Get<Parameters::UseHyNe>())
108 std::string config_file = Parameters::Get<Parameters::HyNeConfigFile>();
113 configs_.push_back(std::move(config));
120 for (
const auto& config :
configs_) {
122 runHybridNewton(config);
152 const auto& eclState =
simulator_.vanguard().eclState();
153 const auto& phases = eclState.runspec().phases();
155 bool hasWater = phases.active(Phase::WATER);
156 bool hasGas = phases.active(Phase::GAS);
157 bool hasOil = phases.active(Phase::OIL);
158 bool hasSolvent = phases.active(Phase::SOLVENT);
161 if (!(hasWater && hasOil && hasGas && !hasSolvent)) {
162 OPM_THROW(std::runtime_error,
163 "HybridNewton: Unsupported fluid system. Only three-phase black oil is supported.");
191 constexpr Scalar tolerance = 1e-6;
192 bool apply = std::abs(current_time - config.
apply_times[0]) < tolerance;
199 bool apply = (current_time >= start_time) && (current_time <= end_time);
232 ML::Tensor<Evaluation>
238 std::size_t input_tensor_length = 0;
239 for (
const auto& feature : features) {
242 input_tensor_length += 1;
244 input_tensor_length += config.
n_cells;
248 ML::Tensor<Evaluation> input(input_tensor_length);
249 std::size_t offset = 0;
252 for (
const auto& feature: features) {
257 input(offset++) = value;
259 for (std::size_t i = 0; i < config.
n_cells; ++i) {
263 input(offset + i) = value;
293 OPM_THROW(std::runtime_error,
"Unknown scalar feature: " + spec.
actual_name);
319 const auto& intQuants =
simulator_.model().intensiveQuantities(cell_index, 0);
320 const auto& fs = intQuants.fluidState();
321 const auto& unitSyst =
simulator_.vanguard().schedule().getUnits();
327 value = unitSyst.from_si(UnitSystem::measure::pressure, value);
335 value = getValue(fs.Rs());
336 value = unitSyst.from_si(UnitSystem::measure::gas_oil_ratio, value);
338 value = getValue(fs.Rv());
339 value = unitSyst.from_si(UnitSystem::measure::oil_gas_ratio, value);
341 const auto& eclState =
simulator_.vanguard().eclState();
342 const auto& fp = eclState.fieldProps();
343 auto permX = fp.get_double(
"PERMX");
344 value = permX[cell_index];
345 value = unitSyst.from_si(UnitSystem::measure::permeability, value);
347 OPM_THROW(std::runtime_error,
"Unknown per-cell feature: " + spec.
actual_name);
374 ML::Tensor<Evaluation>
379 const int n_features = features.size();
381 ML::NNModel<Evaluation> model;
384 ML::Tensor<Evaluation> output(1, config.
n_cells * n_features);
385 model.apply(input, output);
424 const auto& unitSyst =
simulator_.vanguard().schedule().getUnits();
426 for (std::size_t i = 0; i < config.
n_cells; ++i) {
428 const auto& intQuants =
simulator_.model().intensiveQuantities(cell_idx, 0);
429 auto fs = intQuants.fluidState();
439 for (
const auto& [name, spec] : features) {
441 auto scaled_value = getValue(output(feature_idx * config.
n_cells + i));
444 Scalar raw_value = spec.scaler.unscale(scaled_value);
447 raw_value = spec.transform.applyInverse(raw_value);
450 if (spec.actual_name ==
"PRESSURE") {
451 raw_value = raw_value + unitSyst.from_si(UnitSystem::measure::pressure, getValue(fs.pressure(
oilPhaseIdx)));
452 }
else if (spec.actual_name ==
"SWAT") {
454 }
else if (spec.actual_name ==
"SOIL") {
456 }
else if (spec.actual_name ==
"SGAS") {
458 }
else if (spec.actual_name ==
"RS") {
459 raw_value = raw_value + unitSyst.from_si(UnitSystem::measure::gas_oil_ratio, getValue(fs.Rs()));
460 }
else if (spec.actual_name ==
"RV") {
461 raw_value = raw_value + unitSyst.from_si(UnitSystem::measure::oil_gas_ratio, getValue(fs.Rv()));
463 OPM_THROW(std::runtime_error,
"Unknown delta feature: " + name);
467 if (spec.actual_name ==
"PRESSURE") {
468 po_val = unitSyst.to_si(UnitSystem::measure::pressure, raw_value);
469 }
else if (spec.actual_name ==
"SWAT") {
471 }
else if (spec.actual_name ==
"SOIL") {
473 }
else if (spec.actual_name ==
"SGAS") {
475 }
else if (spec.actual_name ==
"RS") {
477 raw_value = unitSyst.to_si(UnitSystem::measure::gas_oil_ratio, raw_value);
480 }
else if (spec.actual_name ==
"RV") {
482 raw_value = unitSyst.to_si(UnitSystem::measure::oil_gas_ratio, raw_value);
486 OPM_THROW(std::runtime_error,
"Unknown output feature: " + name);
492 int sat_count =
static_cast<int>(flags.
has_SWAT) +
496 if (sat_count >= 2) {
509 sw = max(0.0, min(sw, 1.0));
510 so = max(0.0, min(so, 1.0));
511 sg = max(0.0, min(sg, 1.0));
513 Scalar sum = sw + so + sg;
515 OPM_THROW(std::runtime_error,
"Saturation sum is zero in cell " +
std::to_string(cell_idx));
524 std::array<Evaluation, numPhases> pC;
525 const auto& materialParams =
simulator_.problem().materialLawParams(cell_idx);
526 MaterialLaw::capillaryPressures(pC, materialParams, fs);
528 for (
unsigned phaseIdx = 0; phaseIdx <
numPhases; ++phaseIdx) {
529 if (!FluidSystem::phaseIsActive(phaseIdx))
continue;
531 fs.setPressure(phaseIdx, po_val);
533 fs.setPressure(phaseIdx, po_val - pC[phaseIdx]);
538 auto& primaryVars =
simulator_.model().solution(0)[cell_idx];
539 primaryVars.assignNaive(fs);
542 simulator_.model().invalidateAndUpdateIntensiveQuantities(0);
557 for (
const auto& [name, spec] : features) {
559 if (spec.actual_name ==
"SWAT") {
561 }
else if (spec.actual_name ==
"SOIL") {
563 }
else if (spec.actual_name ==
"SGAS") {
565 }
else if (spec.actual_name ==
"PRESSURE") {
Hybrid Newton solver extension for the black-oil model.
Definition: HybridNewton.hpp:59
bool configsLoaded_
Definition: HybridNewton.hpp:576
GetPropType< TypeTag, Properties::Indices > Indices
Definition: HybridNewton.hpp:65
@ oilPhaseIdx
Definition: HybridNewton.hpp:71
void tryApplyHybridNewton()
Attempt to apply the Hybrid Newton correction at the current timestep.
Definition: HybridNewton.hpp:99
@ numPhases
Definition: HybridNewton.hpp:68
FeatureFlags flagFeatures(const std::vector< std::pair< std::string, FeatureSpec > > &features)
Definition: HybridNewton.hpp:553
@ gasPhaseIdx
Definition: HybridNewton.hpp:70
GetPropType< TypeTag, Properties::Evaluation > Evaluation
Definition: HybridNewton.hpp:62
BlackOilHybridNewton(Simulator &simulator)
Definition: HybridNewton.hpp:77
Scalar getPerCellFeatureValue(const FeatureSpec &spec, int cell_index)
Retrieve and transform a per-cell feature value.
Definition: HybridNewton.hpp:317
std::vector< HybridNewtonConfig > configs_
Definition: HybridNewton.hpp:575
bool shouldApplyHybridNewton(Scalar current_time, const HybridNewtonConfig &config) const
Check whether the Hybrid Newton method should be applied at the given time.
Definition: HybridNewton.hpp:187
static constexpr bool compositionSwitchEnabled
Definition: HybridNewton.hpp:74
GetPropType< TypeTag, Properties::MaterialLaw > MaterialLaw
Definition: HybridNewton.hpp:64
GetPropType< TypeTag, Properties::Scalar > Scalar
Definition: HybridNewton.hpp:66
ML::Tensor< Evaluation > constructOutputTensor(const ML::Tensor< Evaluation > &input, const HybridNewtonConfig &config)
Run the Hybrid Newton model to produce output predictions.
Definition: HybridNewton.hpp:375
GetPropType< TypeTag, Properties::Simulator > Simulator
Definition: HybridNewton.hpp:61
GetPropType< TypeTag, Properties::FluidSystem > FluidSystem
Definition: HybridNewton.hpp:63
Scalar getScalarFeatureValue(const FeatureSpec &spec)
Retrieve and transform a scalar feature (global across the domain).
Definition: HybridNewton.hpp:286
void updateInitialGuess(ML::Tensor< Evaluation > &output, const HybridNewtonConfig &config)
Update the nonlinear solver's initial guess using ML predictions.
Definition: HybridNewton.hpp:417
void validateFluidSystem()
Definition: HybridNewton.hpp:150
@ waterPhaseIdx
Definition: HybridNewton.hpp:72
ML::Tensor< Evaluation > constructInputTensor(const HybridNewtonConfig &config)
Construct the input feature tensor for the Hybrid Newton model.
Definition: HybridNewton.hpp:233
Simulator & simulator_
Definition: HybridNewton.hpp:574
Configuration for a Hybrid Newton ML model.
Definition: HybridNewtonConfig.hpp:136
std::vector< double > apply_times
Definition: HybridNewtonConfig.hpp:142
std::vector< std::pair< std::string, FeatureSpec > > input_features
Definition: HybridNewtonConfig.hpp:143
std::vector< std::pair< std::string, FeatureSpec > > output_features
Definition: HybridNewtonConfig.hpp:144
void validateConfig(bool compositionSwitchEnabled) const
Validate feature compatibility with simulator settings.
std::size_t n_cells
Definition: HybridNewtonConfig.hpp:141
std::vector< int > cell_indices
Definition: HybridNewtonConfig.hpp:140
std::string model_path
Definition: HybridNewtonConfig.hpp:138
Hierarchical collection of key/value pairs.
Definition: PropertyTree.hpp:39
std::vector< std::string > get_child_keys() const
PropertyTree get_child(const std::string &key) const
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
std::string to_string(const ConvergenceReport::ReservoirFailure::Type t)
Definition: HybridNewton.hpp:546
bool has_SOIL
Definition: HybridNewton.hpp:548
bool has_SWAT
Definition: HybridNewton.hpp:547
bool has_SGAS
Definition: HybridNewton.hpp:549
bool has_PRESSURE
Definition: HybridNewton.hpp:550
Metadata for a single feature (input or output).
Definition: HybridNewtonConfig.hpp:120
Transform transform
Definition: HybridNewtonConfig.hpp:121
std::string actual_name
Definition: HybridNewtonConfig.hpp:124
Scaler scaler
Definition: HybridNewtonConfig.hpp:122
double scale(double raw_value) const
Definition: HybridNewtonConfig.hpp:46