LET-based family-I saturation functions. New keywords SWOFLET and SGOFLET.
This commit is contained in:
parent
a5d19c4cf0
commit
7496599d41
@ -426,6 +426,89 @@ struct WatdentTable : public FlatTable< WATDENTRecord > {
|
||||
}
|
||||
};
|
||||
|
||||
struct SatFuncLETRecord {
|
||||
static constexpr std::size_t size = 17;
|
||||
|
||||
double s1_residual;
|
||||
double s1_critical;
|
||||
double l1_relperm;
|
||||
double e1_relperm;
|
||||
double t1_relperm;
|
||||
double krt1_relperm;
|
||||
double s2_residual;
|
||||
double s2_critical;
|
||||
double l2_relperm;
|
||||
double e2_relperm;
|
||||
double t2_relperm;
|
||||
double krt2_relperm;
|
||||
double l_pc;
|
||||
double e_pc;
|
||||
double t_pc;
|
||||
double pcir_pc;
|
||||
double pct_pc;
|
||||
|
||||
bool operator==(const SatFuncLETRecord& data) const {
|
||||
return s1_residual == data.s1_residual &&
|
||||
s1_critical == data.s1_critical &&
|
||||
l1_relperm == data.l1_relperm &&
|
||||
e1_relperm == data.e1_relperm &&
|
||||
t1_relperm == data.t1_relperm &&
|
||||
krt1_relperm == data.krt1_relperm &&
|
||||
s2_residual == data.s2_residual &&
|
||||
s2_critical == data.s2_critical &&
|
||||
l2_relperm == data.l2_relperm &&
|
||||
e2_relperm == data.e2_relperm &&
|
||||
t2_relperm == data.t2_relperm &&
|
||||
krt2_relperm == data.krt2_relperm &&
|
||||
l_pc == data.l_pc &&
|
||||
e_pc == data.e_pc &&
|
||||
t_pc == data.t_pc &&
|
||||
pcir_pc == data.pcir_pc &&
|
||||
pct_pc == data.pct_pc;
|
||||
}
|
||||
|
||||
template<class Serializer>
|
||||
void serializeOp(Serializer& serializer)
|
||||
{
|
||||
serializer(s1_residual);
|
||||
serializer(s1_critical);
|
||||
serializer(l1_relperm);
|
||||
serializer(e1_relperm);
|
||||
serializer(t1_relperm);
|
||||
serializer(krt1_relperm);
|
||||
serializer(s2_residual);
|
||||
serializer(s2_critical);
|
||||
serializer(l2_relperm);
|
||||
serializer(e2_relperm);
|
||||
serializer(t2_relperm);
|
||||
serializer(krt2_relperm);
|
||||
serializer(l_pc);
|
||||
serializer(e_pc);
|
||||
serializer(t_pc);
|
||||
serializer(pcir_pc);
|
||||
serializer(pct_pc);
|
||||
}
|
||||
};
|
||||
|
||||
struct SwofletTable : public FlatTable< SatFuncLETRecord > {
|
||||
using FlatTable< SatFuncLETRecord >::FlatTable;
|
||||
|
||||
static SwofletTable serializeObject()
|
||||
{
|
||||
return SwofletTable({{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0}});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct SgofletTable : public FlatTable< SatFuncLETRecord > {
|
||||
using FlatTable< SatFuncLETRecord >::FlatTable;
|
||||
|
||||
static SgofletTable serializeObject()
|
||||
{
|
||||
return SgofletTable({{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0}});
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //OPM_FLAT_TABLE_HPP
|
||||
|
@ -163,6 +163,8 @@ namespace Opm {
|
||||
const ShrateTable& getShrateTable() const;
|
||||
const Stone1exTable& getStone1exTable() const;
|
||||
const WatdentTable& getWatdentTable() const;
|
||||
const SgofletTable& getSgofletTable() const;
|
||||
const SwofletTable& getSwofletTable() const;
|
||||
const std::map<int, PlymwinjTable>& getPlymwinjTables() const;
|
||||
const std::map<int, SkprwatTable>& getSkprwatTables() const;
|
||||
const std::map<int, SkprpolyTable>& getSkprpolyTables() const;
|
||||
@ -217,6 +219,8 @@ namespace Opm {
|
||||
m_stone1exTable.serializeOp(serializer);
|
||||
m_viscrefTable.serializeOp(serializer);
|
||||
m_watdentTable.serializeOp(serializer);
|
||||
m_sgofletTable.serializeOp(serializer);
|
||||
m_swofletTable.serializeOp(serializer);
|
||||
serializer.vector(m_pvtwsaltTables);
|
||||
serializer.vector(m_rwgsaltTables);
|
||||
serializer.vector(m_bdensityTables);
|
||||
@ -356,6 +360,8 @@ namespace Opm {
|
||||
Stone1exTable m_stone1exTable;
|
||||
ViscrefTable m_viscrefTable;
|
||||
WatdentTable m_watdentTable;
|
||||
SgofletTable m_sgofletTable;
|
||||
SwofletTable m_swofletTable;
|
||||
std::vector<PvtwsaltTable> m_pvtwsaltTables;
|
||||
std::vector<RwgsaltTable> m_rwgsaltTables;
|
||||
std::vector<BrineDensityTable> m_bdensityTables;
|
||||
|
@ -93,8 +93,8 @@ namespace {
|
||||
}
|
||||
|
||||
const auto family1 = // SGOF/SLGOF and/or SWOF
|
||||
(gas && (tm.hasTables("SGOF") || tm.hasTables("SLGOF"))) ||
|
||||
(wat && tm.hasTables("SWOF"));
|
||||
(gas && ((tm.hasTables("SGOF") || !tm.getSgofletTable().empty()) || tm.hasTables("SLGOF"))) ||
|
||||
(wat && (tm.hasTables("SWOF") || !tm.getSwofletTable().empty()));
|
||||
// note: we allow for SOF2 to be part of family1 for threeP + solvent simulations.
|
||||
|
||||
const auto family2 = // SGFN, SOF{2,3}, SWFN
|
||||
@ -135,18 +135,27 @@ namespace {
|
||||
return std::vector<double>(num_tables, 0.0);
|
||||
|
||||
const auto& swofTables = tm.getSwofTables();
|
||||
const auto& swofLetTables = tm.getSwofletTable();
|
||||
const auto& swfnTables = tm.getSwfnTables();
|
||||
|
||||
const auto famI = [&swofTables]( int i ) {
|
||||
return swofTables.getTable<Opm::SwofTable>( i ).getSwColumn().front();
|
||||
};
|
||||
|
||||
const auto famI_let = [&swofLetTables]( int i ) {
|
||||
return swofLetTables[i].s1_residual;
|
||||
};
|
||||
|
||||
const auto famII = [&swfnTables]( int i ) {
|
||||
return swfnTables.getTable<Opm::SwfnTable>( i ).getSwColumn().front();
|
||||
};
|
||||
|
||||
switch( getSaturationFunctionFamily( tm, ph ) ) {
|
||||
case SatfuncFamily::I: return map( famI, Opm::fun::iota( num_tables ) );
|
||||
case SatfuncFamily::I:
|
||||
if( !swofTables.empty() )
|
||||
return Opm::fun::map( famI, Opm::fun::iota( num_tables ) );
|
||||
else if ( !swofLetTables.empty() )
|
||||
return Opm::fun::map( famI_let, Opm::fun::iota( num_tables ) );
|
||||
case SatfuncFamily::II: return map( famII, Opm::fun::iota( num_tables ) );
|
||||
default:
|
||||
throw std::domain_error("No valid saturation keyword family specified");
|
||||
@ -163,18 +172,27 @@ namespace {
|
||||
return std::vector<double>(num_tables, 0.0);
|
||||
|
||||
const auto& swofTables = tm.getSwofTables();
|
||||
const auto& swofLetTables = tm.getSwofletTable();
|
||||
const auto& swfnTables = tm.getSwfnTables();
|
||||
|
||||
const auto famI = [&swofTables]( int i ) {
|
||||
return swofTables.getTable<Opm::SwofTable>( i ).getSwColumn().back();
|
||||
};
|
||||
|
||||
const auto famI_let = [&swofLetTables]( int i ) {
|
||||
return 1.0 - swofLetTables[i].s2_residual;
|
||||
};
|
||||
|
||||
const auto famII = [&swfnTables]( int i ) {
|
||||
return swfnTables.getTable<Opm::SwfnTable>( i ).getSwColumn().back();
|
||||
};
|
||||
|
||||
switch( getSaturationFunctionFamily( tm, ph ) ) {
|
||||
case SatfuncFamily::I: return map( famI, Opm::fun::iota( num_tables ) );
|
||||
case SatfuncFamily::I:
|
||||
if( !swofTables.empty() )
|
||||
return map( famI, Opm::fun::iota( num_tables ) );
|
||||
else if ( !swofLetTables.empty() )
|
||||
return Opm::fun::map( famI_let, Opm::fun::iota( num_tables ) );
|
||||
case SatfuncFamily::II: return map( famII, Opm::fun::iota( num_tables ) );
|
||||
default:
|
||||
throw std::domain_error("No valid saturation keyword family specified");
|
||||
@ -191,6 +209,7 @@ namespace {
|
||||
return std::vector<double>(num_tables, 0.0);
|
||||
|
||||
const auto& sgofTables = tm.getSgofTables();
|
||||
const auto& sgofLetTables = tm.getSgofletTable();
|
||||
const auto& slgofTables = tm.getSlgofTables();
|
||||
const auto& sgfnTables = tm.getSgfnTables();
|
||||
|
||||
@ -198,6 +217,10 @@ namespace {
|
||||
return sgofTables.getTable<Opm::SgofTable>( i ).getSgColumn().front();
|
||||
};
|
||||
|
||||
const auto famI_sgof_let = [&sgofLetTables]( int i ) {
|
||||
return sgofLetTables[i].s1_residual;
|
||||
};
|
||||
|
||||
const auto famI_slgof = [&slgofTables]( int i ) {
|
||||
return 1.0 - slgofTables.getTable<Opm::SlgofTable>( i ).getSlColumn().back();
|
||||
};
|
||||
@ -208,11 +231,13 @@ namespace {
|
||||
|
||||
switch( getSaturationFunctionFamily( tm, ph ) ) {
|
||||
case SatfuncFamily::I:
|
||||
if( sgofTables.empty() && slgofTables.empty() )
|
||||
if( sgofTables.empty() && sgofLetTables.empty() && slgofTables.empty() )
|
||||
throw std::runtime_error( "Saturation keyword family I requires either sgof or slgof non-empty" );
|
||||
|
||||
if( !sgofTables.empty() )
|
||||
return Opm::fun::map( famI_sgof, Opm::fun::iota( num_tables ) );
|
||||
else if( !sgofLetTables.empty() )
|
||||
return Opm::fun::map( famI_sgof_let, Opm::fun::iota( num_tables ) );
|
||||
else
|
||||
return Opm::fun::map( famI_slgof, Opm::fun::iota( num_tables ) );
|
||||
|
||||
@ -234,6 +259,8 @@ namespace {
|
||||
return std::vector<double>(num_tables, 0.0);
|
||||
|
||||
const auto& sgofTables = tm.getSgofTables();
|
||||
const auto& sgofLetTables = tm.getSgofletTable();
|
||||
const auto& swofLetTables = tm.getSwofletTable();
|
||||
const auto& slgofTables = tm.getSlgofTables();
|
||||
const auto& sgfnTables = tm.getSgfnTables();
|
||||
|
||||
@ -241,6 +268,11 @@ namespace {
|
||||
return sgofTables.getTable<Opm::SgofTable>( i ).getSgColumn().back();
|
||||
};
|
||||
|
||||
const auto famI_sgof_let = [&swofLetTables]( int i ) {
|
||||
// Assume this to be 1-swco
|
||||
return 1.0 - swofLetTables[i].s1_residual;
|
||||
};
|
||||
|
||||
const auto famI_slgof = [&slgofTables]( int i ) {
|
||||
return 1.0 - slgofTables.getTable<Opm::SlgofTable>( i ).getSlColumn().front();
|
||||
};
|
||||
@ -251,11 +283,13 @@ namespace {
|
||||
|
||||
switch( getSaturationFunctionFamily( tm, ph ) ) {
|
||||
case SatfuncFamily::I:
|
||||
if( sgofTables.empty() && slgofTables.empty() )
|
||||
if( sgofTables.empty() && sgofLetTables.empty() && slgofTables.empty() )
|
||||
throw std::runtime_error( "Saturation keyword family I requires either sgof or slgof non-empty" );
|
||||
|
||||
if( !sgofTables.empty() )
|
||||
return Opm::fun::map( famI_sgof, Opm::fun::iota( num_tables ) );
|
||||
else if( !sgofLetTables.empty() )
|
||||
return Opm::fun::map( famI_sgof_let, Opm::fun::iota( num_tables ) );
|
||||
else
|
||||
return Opm::fun::map( famI_slgof, Opm::fun::iota( num_tables ) );
|
||||
|
||||
@ -335,6 +369,7 @@ namespace {
|
||||
return std::vector<double>(num_tables, 0.0);
|
||||
|
||||
const auto& swofTables = tm.getSwofTables();
|
||||
const auto& swofLetTables = tm.getSwofletTable();
|
||||
const auto& swfnTables = tm.getSwfnTables();
|
||||
|
||||
const auto famI = [&swofTables, tolcrit](const int i) -> double
|
||||
@ -342,13 +377,21 @@ namespace {
|
||||
return critical_water(swofTables.getTable<Opm::SwofTable>(i), tolcrit);
|
||||
};
|
||||
|
||||
const auto famI_let = [&swofLetTables]( int i ) {
|
||||
return swofLetTables[i].s1_critical;
|
||||
};
|
||||
|
||||
const auto famII = [&swfnTables, tolcrit](const int i) -> double
|
||||
{
|
||||
return critical_water(swfnTables.getTable<Opm::SwfnTable>(i), tolcrit);
|
||||
};
|
||||
|
||||
switch( getSaturationFunctionFamily( tm, ph ) ) {
|
||||
case SatfuncFamily::I: return Opm::fun::map( famI, Opm::fun::iota( num_tables ) );
|
||||
case SatfuncFamily::I:
|
||||
if( !swofTables.empty() )
|
||||
return Opm::fun::map( famI, Opm::fun::iota( num_tables ) );
|
||||
else if ( !swofLetTables.empty() )
|
||||
return Opm::fun::map( famI_let, Opm::fun::iota( num_tables ) );
|
||||
case SatfuncFamily::II: return Opm::fun::map( famII, Opm::fun::iota( num_tables ) );
|
||||
default: throw std::domain_error("No valid saturation keyword family specified");
|
||||
}
|
||||
@ -396,6 +439,7 @@ namespace {
|
||||
|
||||
const auto& sgfnTables = tm.getSgfnTables();
|
||||
const auto& sgofTables = tm.getSgofTables();
|
||||
const auto& sgofLetTables = tm.getSgofletTable();
|
||||
const auto& slgofTables = tm.getSlgofTables();
|
||||
|
||||
const auto famI_sgof = [&sgofTables, tolcrit](const int i) -> double
|
||||
@ -403,6 +447,10 @@ namespace {
|
||||
return critical_gas(sgofTables.getTable<Opm::SgofTable>(i), tolcrit);
|
||||
};
|
||||
|
||||
const auto famI_sgof_let = [&sgofLetTables]( int i ) {
|
||||
return sgofLetTables[i].s1_critical;
|
||||
};
|
||||
|
||||
const auto famI_slgof = [&slgofTables, tolcrit](const int i) -> double
|
||||
{
|
||||
return critical_gas(slgofTables.getTable<Opm::SlgofTable>(i), tolcrit);
|
||||
@ -415,11 +463,13 @@ namespace {
|
||||
|
||||
switch( getSaturationFunctionFamily( tm, ph ) ) {
|
||||
case SatfuncFamily::I:
|
||||
if( sgofTables.empty() && slgofTables.empty() )
|
||||
if( sgofTables.empty() && sgofLetTables.empty() && slgofTables.empty() )
|
||||
throw std::runtime_error( "Saturation keyword family I requires either sgof or slgof non-empty" );
|
||||
|
||||
if( !sgofTables.empty() )
|
||||
return Opm::fun::map( famI_sgof, Opm::fun::iota( num_tables ) );
|
||||
else if( !sgofLetTables.empty() )
|
||||
return Opm::fun::map( famI_sgof_let, Opm::fun::iota( num_tables ) );
|
||||
else
|
||||
return Opm::fun::map( famI_slgof, Opm::fun::iota( num_tables ) );
|
||||
|
||||
@ -486,6 +536,7 @@ namespace {
|
||||
return std::vector<double>(num_tables, 0.0);
|
||||
|
||||
const auto& swofTables = tm.getSwofTables();
|
||||
const auto& swofLetTables = tm.getSwofletTable();
|
||||
const auto& sof2Tables = tm.getSof2Tables();
|
||||
const auto& sof3Tables = tm.getSof3Tables();
|
||||
|
||||
@ -494,6 +545,10 @@ namespace {
|
||||
return critical_oil_water(swofTables.getTable<Opm::SwofTable>(i), tolcrit);
|
||||
};
|
||||
|
||||
const auto famI_let = [&swofLetTables]( int i ) {
|
||||
return swofLetTables[i].s2_critical;
|
||||
};
|
||||
|
||||
const auto famII_2p = [&sof2Tables, tolcrit](const int i) -> double
|
||||
{
|
||||
return critical_oil(sof2Tables.getTable<Opm::Sof2Table>(i), tolcrit);
|
||||
@ -506,7 +561,11 @@ namespace {
|
||||
};
|
||||
|
||||
switch( getSaturationFunctionFamily( tm, ph ) ) {
|
||||
case SatfuncFamily::I: return Opm::fun::map( famI, Opm::fun::iota( num_tables ) );
|
||||
case SatfuncFamily::I:
|
||||
if( !swofTables.empty() )
|
||||
return Opm::fun::map( famI, Opm::fun::iota( num_tables ) );
|
||||
else if ( !swofLetTables.empty() )
|
||||
return Opm::fun::map( famI_let, Opm::fun::iota( num_tables ) );
|
||||
case SatfuncFamily::II:
|
||||
return ph.active(::Opm::Phase::GAS)
|
||||
? Opm::fun::map( famII_3p, Opm::fun::iota( num_tables ) )
|
||||
@ -559,6 +618,7 @@ namespace {
|
||||
return std::vector<double>(num_tables, 0.0);
|
||||
|
||||
const auto& sgofTables = tm.getSgofTables();
|
||||
const auto& sgofLetTables = tm.getSgofletTable();
|
||||
const auto& slgofTables = tm.getSlgofTables();
|
||||
const auto& sof2Tables = tm.getSof2Tables();
|
||||
const auto& sof3Tables = tm.getSof3Tables();
|
||||
@ -568,6 +628,10 @@ namespace {
|
||||
return critical_oil_gas(sgofTables.getTable<Opm::SgofTable>(i), tolcrit) - swco[i];
|
||||
};
|
||||
|
||||
const auto famI_sgof_let = [&sgofLetTables]( int i ) {
|
||||
return sgofLetTables[i].s2_critical;
|
||||
};
|
||||
|
||||
const auto famI_slgof = [&slgofTables, &swco, tolcrit](const int i) -> double
|
||||
{
|
||||
return critical_oil_gas(slgofTables.getTable<Opm::SlgofTable>(i), tolcrit) - swco[i];
|
||||
@ -586,11 +650,13 @@ namespace {
|
||||
|
||||
switch( getSaturationFunctionFamily( tm, ph ) ) {
|
||||
case SatfuncFamily::I:
|
||||
if( sgofTables.empty() && slgofTables.empty() )
|
||||
if( sgofTables.empty() && sgofLetTables.empty() && slgofTables.empty() )
|
||||
throw std::runtime_error( "Saturation keyword family I requires either sgof or slgof non-empty" );
|
||||
|
||||
if( !sgofTables.empty() )
|
||||
return Opm::fun::map( famI_sgof, Opm::fun::iota( num_tables ) );
|
||||
else if( !sgofLetTables.empty() )
|
||||
return Opm::fun::map( famI_sgof_let, Opm::fun::iota( num_tables ) );
|
||||
else
|
||||
return Opm::fun::map( famI_slgof, Opm::fun::iota( num_tables ) );
|
||||
|
||||
@ -614,6 +680,7 @@ namespace {
|
||||
return std::vector<double>(num_tables, 0.0);
|
||||
|
||||
const auto& sgofTables = tm.getSgofTables();
|
||||
const auto& sgofLetTables = tm.getSgofletTable();
|
||||
const auto& slgofTables = tm.getSlgofTables();
|
||||
const auto& sgfnTables = tm.getSgfnTables();
|
||||
|
||||
@ -621,6 +688,10 @@ namespace {
|
||||
return sgofTables.getTable<Opm::SgofTable>( i ).getKrgColumn().back();
|
||||
};
|
||||
|
||||
const auto& famI_sgof_let = [&sgofLetTables]( int i ) {
|
||||
return sgofLetTables[i].krt1_relperm;
|
||||
};
|
||||
|
||||
const auto& famI_slgof = [&slgofTables]( int i ) {
|
||||
return slgofTables.getTable<Opm::SlgofTable>( i ).getKrgColumn().front();
|
||||
};
|
||||
@ -631,10 +702,12 @@ namespace {
|
||||
|
||||
switch( getSaturationFunctionFamily( tm, ph ) ) {
|
||||
case SatfuncFamily::I:
|
||||
if( sgofTables.empty() && slgofTables.empty() )
|
||||
if( sgofTables.empty() && sgofLetTables.empty() && slgofTables.empty() )
|
||||
throw std::runtime_error( "Saturation keyword family I requires either sgof or slgof non-empty" );
|
||||
if( !sgofTables.empty() )
|
||||
return Opm::fun::map( famI_sgof, Opm::fun::iota( num_tables ) );
|
||||
else if( !sgofLetTables.empty() )
|
||||
return Opm::fun::map( famI_sgof_let, Opm::fun::iota( num_tables ) );
|
||||
else
|
||||
return Opm::fun::map( famI_slgof, Opm::fun::iota( num_tables ) );
|
||||
case SatfuncFamily::II:
|
||||
@ -655,6 +728,7 @@ namespace {
|
||||
return std::vector<double>(num_tables, 0.0);
|
||||
|
||||
const auto& sgofTables = tm.getSgofTables();
|
||||
const auto& sgofLetTables = tm.getSgofletTable();
|
||||
const auto& slgofTables = tm.getSlgofTables();
|
||||
const auto& sgfnTables = tm.getSgfnTables();
|
||||
|
||||
@ -681,6 +755,11 @@ namespace {
|
||||
return sgof.getKrgColumn().eval(ix);
|
||||
};
|
||||
|
||||
const auto famI_sgof_let = [&sgofLetTables, &sr](const int i) -> double
|
||||
{
|
||||
return sgofLetTables[i].krt1_relperm;
|
||||
};
|
||||
|
||||
const auto famI_slgof = [&slgofTables, &sr](const int i) -> double
|
||||
{
|
||||
const auto& slgof = slgofTables.getTable<Opm::SlgofTable>(i);
|
||||
@ -699,10 +778,12 @@ namespace {
|
||||
|
||||
switch( getSaturationFunctionFamily( tm, ph ) ) {
|
||||
case SatfuncFamily::I:
|
||||
if( sgofTables.empty() && slgofTables.empty() )
|
||||
if( sgofTables.empty() && sgofLetTables.empty() && slgofTables.empty() )
|
||||
throw std::runtime_error( "Saturation keyword family I requires either sgof or slgof non-empty" );
|
||||
if( !sgofTables.empty() )
|
||||
return Opm::fun::map( famI_sgof, Opm::fun::iota( num_tables ) );
|
||||
else if( !sgofLetTables.empty() )
|
||||
return Opm::fun::map( famI_sgof_let, Opm::fun::iota( num_tables ) );
|
||||
else
|
||||
return Opm::fun::map( famI_slgof, Opm::fun::iota( num_tables ) );
|
||||
case SatfuncFamily::II:
|
||||
@ -723,6 +804,7 @@ namespace {
|
||||
return std::vector<double>(num_tables, 0.0);
|
||||
|
||||
const auto& swofTables = tm.getSwofTables();
|
||||
const auto& swofLetTables = tm.getSwofletTable();
|
||||
const auto& swfnTables = tm.getSwfnTables();
|
||||
|
||||
auto sr = std::vector<double>(num_tables, 0.0);
|
||||
@ -748,6 +830,11 @@ namespace {
|
||||
return swof.getKrwColumn().eval(ix);
|
||||
};
|
||||
|
||||
const auto& famI_let = [&swofLetTables, &sr](const int i) -> double
|
||||
{
|
||||
return swofLetTables[i].krt1_relperm;
|
||||
};
|
||||
|
||||
const auto& famII = [&swfnTables, &sr](const int i) -> double
|
||||
{
|
||||
const auto& swfn = swfnTables.getTable<Opm::SwfnTable>(i);
|
||||
@ -758,7 +845,10 @@ namespace {
|
||||
|
||||
switch( getSaturationFunctionFamily( tm, ph ) ) {
|
||||
case SatfuncFamily::I:
|
||||
return Opm::fun::map( famI, Opm::fun::iota( num_tables ) );
|
||||
if( !swofTables.empty() )
|
||||
return Opm::fun::map( famI, Opm::fun::iota( num_tables ) );
|
||||
else if( !swofLetTables.empty() )
|
||||
return Opm::fun::map( famI_let, Opm::fun::iota( num_tables ) );
|
||||
case SatfuncFamily::II:
|
||||
return Opm::fun::map( famII, Opm::fun::iota( num_tables ) );
|
||||
default:
|
||||
@ -778,6 +868,7 @@ namespace {
|
||||
return std::vector<double>(num_tables, 0.0);
|
||||
|
||||
const auto& swofTables = tm.getSwofTables();
|
||||
const auto& swofLetTables = tm.getSwofletTable();
|
||||
const auto& sof2Tables = tm.getSof2Tables();
|
||||
const auto& sof3Tables = tm.getSof3Tables();
|
||||
|
||||
@ -790,6 +881,11 @@ namespace {
|
||||
return swof.getKrowColumn().eval(ix);
|
||||
};
|
||||
|
||||
const auto famI_let = [&swofLetTables, &ep](const int i) -> double
|
||||
{
|
||||
return swofLetTables[i].krt2_relperm;
|
||||
};
|
||||
|
||||
const auto famII_3p = [&sof3Tables, &ep](const int i) -> double
|
||||
{
|
||||
const auto& sof3 = sof3Tables.getTable<Opm::Sof3Table>(i);
|
||||
@ -810,7 +906,10 @@ namespace {
|
||||
|
||||
switch( getSaturationFunctionFamily( tm, ph ) ) {
|
||||
case SatfuncFamily::I:
|
||||
return Opm::fun::map( famI, Opm::fun::iota( num_tables ) );
|
||||
if ( !swofTables.empty() )
|
||||
return Opm::fun::map( famI, Opm::fun::iota( num_tables ) );
|
||||
else if ( !swofLetTables.empty() )
|
||||
return Opm::fun::map( famI_let, Opm::fun::iota( num_tables ) );
|
||||
case SatfuncFamily::II:
|
||||
return ph.active(::Opm::Phase::GAS)
|
||||
? Opm::fun::map( famII_3p, Opm::fun::iota( num_tables ) )
|
||||
@ -832,6 +931,7 @@ namespace {
|
||||
return std::vector<double>(num_tables, 0.0);
|
||||
|
||||
const auto& sgofTables = tm.getSgofTables();
|
||||
const auto& sgofLetTables = tm.getSgofletTable();
|
||||
const auto& slgofTables = tm.getSlgofTables();
|
||||
const auto& sof2Tables = tm.getSof2Tables();
|
||||
const auto& sof3Tables = tm.getSof3Tables();
|
||||
@ -845,6 +945,11 @@ namespace {
|
||||
return sgof.getKrogColumn().eval(ix);
|
||||
};
|
||||
|
||||
const auto famI_sgof_let = [&sgofLetTables, &ep](const int i) -> double
|
||||
{
|
||||
return sgofLetTables[i].krt2_relperm;
|
||||
};
|
||||
|
||||
const auto famI_slgof = [&slgofTables, &ep](const int i) -> double
|
||||
{
|
||||
const auto& slgof = slgofTables.getTable<Opm::SlgofTable>(i);
|
||||
@ -873,10 +978,12 @@ namespace {
|
||||
|
||||
switch( getSaturationFunctionFamily( tm, ph ) ) {
|
||||
case SatfuncFamily::I:
|
||||
if( sgofTables.empty() && slgofTables.empty() )
|
||||
if( sgofTables.empty() && sgofLetTables.empty() && slgofTables.empty() )
|
||||
throw std::runtime_error( "Saturation keyword family I requires either sgof or slgof non-empty" );
|
||||
if( !sgofTables.empty() )
|
||||
return Opm::fun::map( famI_sgof, Opm::fun::iota( num_tables ) );
|
||||
else if( !sgofLetTables.empty() )
|
||||
return Opm::fun::map( famI_sgof_let, Opm::fun::iota( num_tables ) );
|
||||
else
|
||||
return Opm::fun::map( famI_slgof, Opm::fun::iota( num_tables ) );
|
||||
case SatfuncFamily::II:
|
||||
@ -908,6 +1015,7 @@ namespace {
|
||||
return std::vector<double>(num_tables, 0.0);
|
||||
|
||||
const auto& sgofTables = tm.getSgofTables();
|
||||
const auto& sgofLetTables = tm.getSgofletTable();
|
||||
const auto& slgofTables = tm.getSlgofTables();
|
||||
const auto& sgfnTables = tm.getSgfnTables();
|
||||
|
||||
@ -915,6 +1023,10 @@ namespace {
|
||||
return sgofTables.getTable<Opm::SgofTable>( i ).getPcogColumn().back();
|
||||
};
|
||||
|
||||
const auto& famI_sgof_let = [&sgofLetTables]( int i ) {
|
||||
return sgofLetTables[i].pct_pc;
|
||||
};
|
||||
|
||||
const auto& famI_slgof = [&slgofTables]( int i ) {
|
||||
return slgofTables.getTable<Opm::SlgofTable>( i ).getPcogColumn().front();
|
||||
};
|
||||
@ -925,10 +1037,12 @@ namespace {
|
||||
|
||||
switch( getSaturationFunctionFamily( tm, ph ) ) {
|
||||
case SatfuncFamily::I:
|
||||
if( sgofTables.empty() && slgofTables.empty() )
|
||||
if( sgofTables.empty() && sgofLetTables.empty() && slgofTables.empty() )
|
||||
throw std::runtime_error( "Saturation keyword family I requires either sgof or slgof non-empty" );
|
||||
if( !sgofTables.empty() )
|
||||
return Opm::fun::map( famI_sgof, Opm::fun::iota( num_tables ) );
|
||||
else if( !sgofLetTables.empty() )
|
||||
return Opm::fun::map( famI_sgof_let, Opm::fun::iota( num_tables ) );
|
||||
else
|
||||
return Opm::fun::map( famI_slgof, Opm::fun::iota( num_tables ) );
|
||||
case SatfuncFamily::II:
|
||||
@ -949,19 +1063,27 @@ namespace {
|
||||
return std::vector<double>(num_tables, 0.0);
|
||||
|
||||
const auto& swofTables = tm.getSwofTables();
|
||||
const auto& swofLetTables = tm.getSwofletTable();
|
||||
const auto& swfnTables = tm.getSwfnTables();
|
||||
|
||||
const auto& famI = [&swofTables]( int i ) {
|
||||
return swofTables.getTable<Opm::SwofTable>( i ).getPcowColumn().front();
|
||||
};
|
||||
|
||||
const auto& famI_let = [&swofLetTables]( int i ) {
|
||||
return swofLetTables[i].pct_pc;
|
||||
};
|
||||
|
||||
const auto& famII = [&swfnTables]( int i ) {
|
||||
return swfnTables.getTable<Opm::SwfnTable>( i ).getPcowColumn().front();
|
||||
};
|
||||
|
||||
switch( getSaturationFunctionFamily( tm, ph ) ) {
|
||||
case SatfuncFamily::I:
|
||||
return Opm::fun::map( famI, Opm::fun::iota( num_tables ) );
|
||||
if (!swofTables.empty())
|
||||
return Opm::fun::map( famI, Opm::fun::iota( num_tables ) );
|
||||
else if (!swofLetTables.empty())
|
||||
return Opm::fun::map( famI_let, Opm::fun::iota( num_tables ) );
|
||||
case SatfuncFamily::II:
|
||||
return Opm::fun::map( famII, Opm::fun::iota( num_tables ) );
|
||||
default:
|
||||
@ -981,6 +1103,8 @@ namespace {
|
||||
const auto wat = ph.active(::Opm::Phase::WATER);
|
||||
|
||||
const auto& other_f1 = wat ? tm.getSwofTables() : tm.getSgofTables();
|
||||
const auto& wat_f1_let = tm.getSwofletTable();
|
||||
const auto& gas_f1_let = tm.getSgofletTable();
|
||||
const auto& sof2Tables = tm.getSof2Tables();
|
||||
const auto& sof3Tables = tm.getSof3Tables();
|
||||
|
||||
@ -993,6 +1117,18 @@ namespace {
|
||||
: other_f1.getTable<Opm::SgofTable>( i ).getKrogColumn().front();
|
||||
};
|
||||
|
||||
const auto& famI_let_wat = [&wat_f1_let]( int i ) {
|
||||
// In O/W/G runs this relies on Krog(Sg=0) == Krow(Sw=Swco),
|
||||
// meaning that in each region krt2_relperm is equal for SGOFLET and SWOFLET.
|
||||
return wat_f1_let[i].krt2_relperm;
|
||||
};
|
||||
|
||||
const auto& famI_let_gas = [&gas_f1_let]( int i ) {
|
||||
// In O/W/G runs this relies on Krog(Sg=0) == Krow(Sw=Swco),
|
||||
// meaning that in each region krt2_relperm is equal for SGOFLET and SWOFLET.
|
||||
return gas_f1_let[i].krt2_relperm;
|
||||
};
|
||||
|
||||
const auto& famII_2p = [&sof2Tables]( int i ) {
|
||||
return sof2Tables.getTable<Opm::Sof2Table>( i ).getKroColumn().back();
|
||||
};
|
||||
@ -1003,7 +1139,12 @@ namespace {
|
||||
|
||||
switch( getSaturationFunctionFamily( tm, ph ) ) {
|
||||
case SatfuncFamily::I:
|
||||
return Opm::fun::map( famI, Opm::fun::iota( num_tables ) );
|
||||
if ( !other_f1.empty() )
|
||||
return Opm::fun::map( famI, Opm::fun::iota( num_tables ) );
|
||||
else if ( !wat_f1_let.empty() )
|
||||
return Opm::fun::map( famI_let_wat, Opm::fun::iota( num_tables ) );
|
||||
else if ( !gas_f1_let.empty() )
|
||||
return Opm::fun::map( famI_let_gas, Opm::fun::iota( num_tables ) );
|
||||
case SatfuncFamily::II:
|
||||
return ph.active(::Opm::Phase::GAS) && ph.active(::Opm::Phase::WATER)
|
||||
? Opm::fun::map( famII_3p, Opm::fun::iota( num_tables ) )
|
||||
@ -1023,19 +1164,28 @@ namespace {
|
||||
return std::vector<double>(num_tables, 0.0);
|
||||
|
||||
const auto& swofTables = tm.getSwofTables();
|
||||
const auto& swofLetTables = tm.getSwofletTable();
|
||||
const auto& swfnTables = tm.getSwfnTables();
|
||||
|
||||
const auto& famI = [&swofTables]( int i ) {
|
||||
return swofTables.getTable<Opm::SwofTable>( i ).getKrwColumn().back();
|
||||
};
|
||||
|
||||
const auto& famI_let = [&swofLetTables]( int i ) {
|
||||
return swofLetTables[i].krt1_relperm;
|
||||
};
|
||||
|
||||
const auto& famII = [&swfnTables]( int i ) {
|
||||
return swfnTables.getTable<Opm::SwfnTable>( i ).getKrwColumn().back();
|
||||
};
|
||||
|
||||
switch( getSaturationFunctionFamily( tm, ph ) ) {
|
||||
case SatfuncFamily::I:
|
||||
return Opm::fun::map( famI, Opm::fun::iota( num_tables ) );
|
||||
if( !swofTables.empty() )
|
||||
return Opm::fun::map( famI, Opm::fun::iota( num_tables ) );
|
||||
else if( !swofLetTables.empty() )
|
||||
return Opm::fun::map( famI_let, Opm::fun::iota( num_tables ) );
|
||||
|
||||
case SatfuncFamily::II:
|
||||
return Opm::fun::map( famII, Opm::fun::iota( num_tables ) );
|
||||
default:
|
||||
|
@ -88,7 +88,8 @@ namespace {
|
||||
const auto family1 = // SGOF/SLGOF and/or SWOF
|
||||
(gas && (deck.hasKeyword<Opm::ParserKeywords::SGOF>() ||
|
||||
deck.hasKeyword<Opm::ParserKeywords::SLGOF>())) ||
|
||||
(wat && deck.hasKeyword<Opm::ParserKeywords::SWOF>());
|
||||
(wat && deck.hasKeyword<Opm::ParserKeywords::SWOF>()) ||
|
||||
(wat && deck.hasKeyword<Opm::ParserKeywords::SWOFLET>());
|
||||
|
||||
// note: we allow for SOF2 to be part of family1 for threeP +
|
||||
// solvent simulations.
|
||||
|
@ -211,6 +211,12 @@ DensityTable make_density_table(const GravityTable& gravity) {
|
||||
if( deck.hasKeyword( "WATDENT" ) )
|
||||
this->m_watdentTable = WatdentTable( deck["WATDENT"].back() );
|
||||
|
||||
if( deck.hasKeyword( "SGOFLET" ) )
|
||||
this->m_sgofletTable = SgofletTable( deck["SGOFLET"].back() );
|
||||
|
||||
if( deck.hasKeyword( "SWOFLET" ) )
|
||||
this->m_swofletTable = SwofletTable( deck["SWOFLET"].back() );
|
||||
|
||||
if( deck.hasKeyword( "RTEMP" ) )
|
||||
m_rtemp = deck["RTEMP"].back().getRecord(0).getItem("TEMP").getSIDouble( 0 );
|
||||
else if (deck.hasKeyword( "RTEMPA" ) )
|
||||
@ -297,6 +303,8 @@ DensityTable make_density_table(const GravityTable& gravity) {
|
||||
result.m_stone1exTable = Stone1exTable::serializeObject();
|
||||
result.m_viscrefTable = ViscrefTable::serializeObject();
|
||||
result.m_watdentTable = WatdentTable::serializeObject();
|
||||
result.m_sgofletTable = SgofletTable::serializeObject();
|
||||
result.m_swofletTable = SwofletTable::serializeObject();
|
||||
result.m_pvtwsaltTables = {PvtwsaltTable::serializeObject()};
|
||||
result.m_rwgsaltTables = {RwgsaltTable::serializeObject()};
|
||||
result.m_bdensityTables = {BrineDensityTable::serializeObject()};
|
||||
@ -1117,6 +1125,14 @@ DensityTable make_density_table(const GravityTable& gravity) {
|
||||
return this->m_watdentTable;
|
||||
}
|
||||
|
||||
const SgofletTable& TableManager::getSgofletTable() const {
|
||||
return this->m_sgofletTable;
|
||||
}
|
||||
|
||||
const SwofletTable& TableManager::getSwofletTable() const {
|
||||
return this->m_swofletTable;
|
||||
}
|
||||
|
||||
const TableContainer& TableManager::getMsfnTables() const {
|
||||
return getTables("MSFN");
|
||||
}
|
||||
@ -1241,6 +1257,8 @@ DensityTable make_density_table(const GravityTable& gravity) {
|
||||
m_stone1exTable == data.m_stone1exTable &&
|
||||
m_viscrefTable == data.m_viscrefTable &&
|
||||
m_watdentTable == data.m_watdentTable &&
|
||||
m_sgofletTable == data.m_sgofletTable &&
|
||||
m_swofletTable == data.m_swofletTable &&
|
||||
m_pvtwsaltTables == data.m_pvtwsaltTables &&
|
||||
m_rwgsaltTables == data.m_rwgsaltTables &&
|
||||
m_bdensityTables == data.m_bdensityTables &&
|
||||
|
@ -1551,5 +1551,6 @@ template FlatTable< ShrateRecord >::FlatTable( const DeckKeyword& );
|
||||
template FlatTable< Stone1exRecord >::FlatTable( const DeckKeyword& );
|
||||
template FlatTable< TlmixparRecord>::FlatTable( const DeckKeyword& );
|
||||
template FlatTable< WATDENTRecord >::FlatTable( const DeckKeyword& );
|
||||
template FlatTable< SatFuncLETRecord >::FlatTable( const DeckKeyword& );
|
||||
|
||||
} // namespace Opm
|
||||
|
@ -1119,6 +1119,7 @@ set( keywords
|
||||
900_OPM/S/SALTSOL
|
||||
900_OPM/S/SBIOF
|
||||
900_OPM/S/SCALC
|
||||
900_OPM/S/SGOFLET
|
||||
900_OPM/S/SKPRPOLY
|
||||
900_OPM/S/SKPRWAT
|
||||
900_OPM/S/SMICR
|
||||
@ -1126,6 +1127,7 @@ set( keywords
|
||||
900_OPM/S/SPIDER
|
||||
900_OPM/S/SPOLYMW
|
||||
900_OPM/S/SUREA
|
||||
900_OPM/S/SWOFLET
|
||||
900_OPM/T/TLPMIXPA
|
||||
900_OPM/V/VAPWAT
|
||||
900_OPM/W/WMICP
|
||||
|
115
src/opm/parser/eclipse/share/keywords/900_OPM/S/SGOFLET
Normal file
115
src/opm/parser/eclipse/share/keywords/900_OPM/S/SGOFLET
Normal file
@ -0,0 +1,115 @@
|
||||
{
|
||||
"name": "SGOFLET",
|
||||
"sections": [
|
||||
"PROPS"
|
||||
],
|
||||
"size": {
|
||||
"keyword": "TABDIMS",
|
||||
"item": "NTSFUN"
|
||||
},
|
||||
"requires": ["GAS", "OIL"],
|
||||
"items": [
|
||||
{
|
||||
"name": "SG_0",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 0,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "SG_CRITICAL",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 0,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "L_GAS",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "E_GAS",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "T_GAS",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "KRT_GAS",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "SO_0",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 0,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "SO_CRITICAL",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 0,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "L_OIL",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "E_OIL",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "T_OIL",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "KRT_OIL",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "L_PC",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "E_PC",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "T_PC",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "PCIR",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 0,
|
||||
"dimension": "Pressure"
|
||||
},
|
||||
{
|
||||
"name": "PCT",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 0,
|
||||
"dimension": "Pressure"
|
||||
}
|
||||
]
|
||||
}
|
115
src/opm/parser/eclipse/share/keywords/900_OPM/S/SWOFLET
Normal file
115
src/opm/parser/eclipse/share/keywords/900_OPM/S/SWOFLET
Normal file
@ -0,0 +1,115 @@
|
||||
{
|
||||
"name": "SWOFLET",
|
||||
"sections": [
|
||||
"PROPS"
|
||||
],
|
||||
"size": {
|
||||
"keyword": "TABDIMS",
|
||||
"item": "NTSFUN"
|
||||
},
|
||||
"requires": ["OIL", "WATER"],
|
||||
"items": [
|
||||
{
|
||||
"name": "SW_RESIDUAL",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 0,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "SW_CRITICAL",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 0,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "L_WATER",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "E_WATER",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "T_WATER",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "KRT_WATER",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "SO_RESIDUAL",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 0,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "SO_CRITICAL",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 0,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "L_OIL",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "E_OIL",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "T_OIL",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "KRT_OIL",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "L_PC",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "E_PC",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "T_PC",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 1,
|
||||
"dimension": "1"
|
||||
},
|
||||
{
|
||||
"name": "PCIR",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 0,
|
||||
"dimension": "Pressure"
|
||||
},
|
||||
{
|
||||
"name": "PCT",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 0,
|
||||
"dimension": "Pressure"
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user