Merge pull request #763 from totto82/support_dissolved_gas_in_water

Support dissolved gas in water
This commit is contained in:
Tor Harald Sandve
2022-12-21 13:40:16 +01:00
committed by GitHub
8 changed files with 168 additions and 57 deletions

View File

@@ -123,7 +123,12 @@ public:
}
// no diffusion in water for blackoil models
if (FluidSystem::waterPhaseIdx == phaseIdx) {
if (!FluidSystem::enableDissolvedGasInWater() && FluidSystem::waterPhaseIdx == phaseIdx) {
continue;
}
// no diffusion in gas phase in water + gas system.
if (FluidSystem::gasPhaseIdx == phaseIdx && !FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
continue;
}
@@ -137,16 +142,21 @@ public:
continue;
Evaluation convFactor = 1.0;
Evaluation diffR = 0.0;
if (FluidSystem::enableDissolvedGas() && phaseIdx == FluidSystem::oilPhaseIdx) {
if (FluidSystem::enableDissolvedGas() && FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx) && phaseIdx == FluidSystem::oilPhaseIdx) {
Evaluation rsAvg = (fluidStateI.Rs() + Toolbox::value(fluidStateJ.Rs())) / 2;
convFactor = 1.0 / (fraction(pvtRegionIndex) + rsAvg);
convFactor = 1.0 / (toMolFractionGasOil(pvtRegionIndex) + rsAvg);
diffR = fluidStateI.Rs() - Toolbox::value(fluidStateJ.Rs());
}
if (FluidSystem::enableVaporizedOil() && phaseIdx == FluidSystem::gasPhaseIdx) {
if (FluidSystem::enableVaporizedOil() && FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx) && phaseIdx == FluidSystem::gasPhaseIdx) {
Evaluation rvAvg = (fluidStateI.Rv() + Toolbox::value(fluidStateJ.Rv())) / 2;
convFactor = fraction(pvtRegionIndex) / (1.0 + rvAvg*fraction(pvtRegionIndex));
convFactor = toMolFractionGasOil(pvtRegionIndex) / (1.0 + rvAvg*toMolFractionGasOil(pvtRegionIndex));
diffR = fluidStateI.Rv() - Toolbox::value(fluidStateJ.Rv());
}
if (FluidSystem::enableDissolvedGasInWater() && phaseIdx == FluidSystem::waterPhaseIdx) {
Evaluation rsAvg = (fluidStateI.Rsw() + Toolbox::value(fluidStateJ.Rsw())) / 2;
convFactor = 1.0 / (toMolFractionGasWater(pvtRegionIndex) + rsAvg);
diffR = fluidStateI.Rsw() - Toolbox::value(fluidStateJ.Rsw());
}
// mass flux of solvent component (oil in oil or gas in gas)
unsigned solventCompIdx = FluidSystem::solventComponentIndex(phaseIdx);
@@ -170,13 +180,20 @@ public:
}
private:
static Scalar fraction (unsigned regionIdx) {
static Scalar toMolFractionGasOil (unsigned regionIdx) {
Scalar mMOil = FluidSystem::molarMass(FluidSystem::oilCompIdx, regionIdx);
Scalar rhoO = FluidSystem::referenceDensity(FluidSystem::oilPhaseIdx, regionIdx);
Scalar mMGas = FluidSystem::molarMass(FluidSystem::gasCompIdx, regionIdx);
Scalar rhoG = FluidSystem::referenceDensity(FluidSystem::gasPhaseIdx, regionIdx);
return rhoO * mMGas / (rhoG * mMOil);
}
static Scalar toMolFractionGasWater (unsigned regionIdx) {
Scalar mMWater = FluidSystem::molarMass(FluidSystem::waterCompIdx, regionIdx);
Scalar rhoW = FluidSystem::referenceDensity(FluidSystem::waterPhaseIdx, regionIdx);
Scalar mMGas = FluidSystem::molarMass(FluidSystem::gasCompIdx, regionIdx);
Scalar rhoG = FluidSystem::referenceDensity(FluidSystem::gasPhaseIdx, regionIdx);
return rhoW * mMGas / (rhoG * mMWater);
}
};
/*!
@@ -331,7 +348,7 @@ protected:
}
// no diffusion in water for blackoil models
if (FluidSystem::waterPhaseIdx == phaseIdx) {
if (!FluidSystem::enableDissolvedGasInWater() && FluidSystem::waterPhaseIdx == phaseIdx) {
continue;
}
@@ -469,7 +486,7 @@ protected:
continue;
}
// no diffusion in water for blackoil models
if (FluidSystem::waterPhaseIdx == phaseIdx) {
if (!FluidSystem::enableDissolvedGasInWater() && FluidSystem::waterPhaseIdx == phaseIdx) {
continue;
}
for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {

View File

@@ -92,6 +92,7 @@ class BlackOilIntensiveQuantities
enum { enableFoam = getPropValue<TypeTag, Properties::EnableFoam>() };
enum { enableBrine = getPropValue<TypeTag, Properties::EnableBrine>() };
enum { enableEvaporation = getPropValue<TypeTag, Properties::EnableEvaporation>() };
enum { has_disgas_in_water = getPropValue<TypeTag, Properties::EnableDisgasInWater>() };
enum { enableSaltPrecipitation = getPropValue<TypeTag, Properties::EnableSaltPrecipitation>() };
enum { enableTemperature = getPropValue<TypeTag, Properties::EnableTemperature>() };
enum { enableEnergy = getPropValue<TypeTag, Properties::EnableEnergy>() };
@@ -130,6 +131,7 @@ public:
enableEvaporation,
enableBrine,
enableSaltPrecipitation,
has_disgas_in_water,
Indices::numPhases>;
using ScalarFluidState = BlackOilFluidState<Scalar,
FluidSystem,
@@ -139,6 +141,7 @@ public:
enableEvaporation,
enableBrine,
enableSaltPrecipitation,
has_disgas_in_water,
Indices::numPhases>;
using Problem = GetPropType<TypeTag, Properties::Problem>;
@@ -151,6 +154,9 @@ public:
if (enableEvaporation) {
fluidState_.setRvw(0.0);
}
if (has_disgas_in_water) {
fluidState_.setRsw(0.0);
}
}
BlackOilIntensiveQuantities(const BlackOilIntensiveQuantities& other) = default;
@@ -186,10 +192,12 @@ public:
if constexpr (waterEnabled) {
if (priVars.primaryVarsMeaningWater() == PrimaryVariables::WaterMeaning::Sw) {
Sw = priVars.makeEvaluation(Indices::waterSwitchIdx, timeIdx);
} else if (priVars.primaryVarsMeaningWater() == PrimaryVariables::WaterMeaning::Disabled){
// water is enabled but is not a primary variable i.e. one phase case
} else if(priVars.primaryVarsMeaningWater() == PrimaryVariables::WaterMeaning::Rsw ||
priVars.primaryVarsMeaningWater() == PrimaryVariables::WaterMeaning::Disabled) {
// water is enabled but is not a primary variable i.e. one component/phase case
// or two-phase water + gas with only water present
Sw = 1.0;
}
} // else i.e. for MeaningWater() = Rvw, Sw is still 0.0;
}
Evaluation Sg = 0.0;
if constexpr (gasEnabled) {
@@ -238,13 +246,13 @@ public:
for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
if (FluidSystem::phaseIsActive(phaseIdx))
fluidState_.setPressure(phaseIdx, pg + (pC[phaseIdx] - pC[gasPhaseIdx]));
//} else if (priVars.primaryVarsMeaningPressure() == PrimaryVariables::Pw) {
// const Evaluation& pw = priVars.makeEvaluation(Indices::pressureSwitchIdx, timeIdx);
// for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
// if (FluidSystem::phaseIsActive(phaseIdx))
// fluidState_.setPressure(phaseIdx, pw + (pC[phaseIdx] - pC[waterPhaseIdx]));
} else if (priVars.primaryVarsMeaningPressure() == PrimaryVariables::PressureMeaning::Pw) {
const Evaluation& pw = priVars.makeEvaluation(Indices::pressureSwitchIdx, timeIdx);
for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
if (FluidSystem::phaseIsActive(phaseIdx))
fluidState_.setPressure(phaseIdx, pw + (pC[phaseIdx] - pC[waterPhaseIdx]));
} else {
//assert(FluidSystem::phaseIsActive(oilPhaseIdx));
assert(FluidSystem::phaseIsActive(oilPhaseIdx));
const Evaluation& po = priVars.makeEvaluation(Indices::pressureSwitchIdx, timeIdx);
for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
if (FluidSystem::phaseIsActive(phaseIdx))
@@ -309,6 +317,18 @@ public:
}
}
if (priVars.primaryVarsMeaningWater() == PrimaryVariables::WaterMeaning::Rsw) {
const auto& Rsw = priVars.makeEvaluation(Indices::waterSwitchIdx, timeIdx);
fluidState_.setRsw(Rsw);
} else {
if (FluidSystem::enableDissolvedGasInWater()) {
const Evaluation& RswSat = FluidSystem::saturatedDissolutionFactor(fluidState_,
waterPhaseIdx,
pvtRegionIdx);
fluidState_.setRsw(RswSat);
}
}
typename FluidSystem::template ParameterCache<Evaluation> paramCache;
paramCache.setRegionIndex(pvtRegionIdx);
if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
@@ -350,6 +370,12 @@ public:
if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
rho = fluidState_.invB(waterPhaseIdx);
rho *= FluidSystem::referenceDensity(waterPhaseIdx, pvtRegionIdx);
if (FluidSystem::enableDissolvedGasInWater()) {
rho +=
fluidState_.invB(waterPhaseIdx) *
fluidState_.Rsw() *
FluidSystem::referenceDensity(gasPhaseIdx, pvtRegionIdx);
}
fluidState_.setDensity(waterPhaseIdx, rho);
}
@@ -450,6 +476,7 @@ public:
}
assert(isfinite(fluidState_.Rs()));
assert(isfinite(fluidState_.Rv()));
#endif
}

View File

@@ -135,6 +135,14 @@ public:
* surfaceVolume;
}
// account for dissolved gas in water phase
if (phaseIdx == waterPhaseIdx && FluidSystem::enableDissolvedGasInWater()) {
unsigned activeGasCompIdx = Indices::canonicalToActiveComponentIndex(gasCompIdx);
storage[conti0EqIdx + activeGasCompIdx] +=
Toolbox::template decay<LhsEval>(intQuants.fluidState().Rsw())
* surfaceVolume;
}
// account for vaporized oil
if (phaseIdx == gasPhaseIdx && FluidSystem::enableVaporizedOil()) {
unsigned activeOilCompIdx = Indices::canonicalToActiveComponentIndex(oilCompIdx);
@@ -277,6 +285,17 @@ public:
else
flux[conti0EqIdx + activeGasCompIdx] += Rs*surfaceVolumeFlux*FluidSystem::referenceDensity(gasPhaseIdx, pvtRegionIdx);
}
} else if (phaseIdx == waterPhaseIdx) {
// dissolved gas (in the water phase).
if (FluidSystem::enableDissolvedGasInWater()) {
const auto& Rsw = BlackOil::getRsw_<FluidSystem, FluidState, UpEval>(upFs, pvtRegionIdx);
unsigned activeGasCompIdx = Indices::canonicalToActiveComponentIndex(gasCompIdx);
if (blackoilConserveSurfaceVolume)
flux[conti0EqIdx + activeGasCompIdx] += Rsw*surfaceVolumeFlux;
else
flux[conti0EqIdx + activeGasCompIdx] += Rsw*surfaceVolumeFlux*FluidSystem::referenceDensity(gasPhaseIdx, pvtRegionIdx);
}
}
else if (phaseIdx == gasPhaseIdx) {
// vaporized oil (in the gas phase).

View File

@@ -148,6 +148,14 @@ public:
* surfaceVolume;
}
// account for dissolved gas in water
if (phaseIdx == waterPhaseIdx && FluidSystem::enableDissolvedGasInWater()) {
unsigned activeGasCompIdx = Indices::canonicalToActiveComponentIndex(gasCompIdx);
storage[conti0EqIdx + activeGasCompIdx] +=
Toolbox::template decay<LhsEval>(intQuants.fluidState().Rsw())
* surfaceVolume;
}
// account for vaporized oil
if (phaseIdx == gasPhaseIdx && FluidSystem::enableVaporizedOil()) {
unsigned activeOilCompIdx = Indices::canonicalToActiveComponentIndex(oilCompIdx);
@@ -601,6 +609,17 @@ public:
else
flux[conti0EqIdx + activeGasCompIdx] += Rs*surfaceVolumeFlux*FluidSystem::referenceDensity(gasPhaseIdx, pvtRegionIdx);
}
} else if (phaseIdx == waterPhaseIdx) {
// dissolved gas (in the water phase).
if (FluidSystem::enableDissolvedGasInWater()) {
const auto& Rsw = BlackOil::getRsw_<FluidSystem, FluidState, UpEval>(upFs, pvtRegionIdx);
unsigned activeGasCompIdx = Indices::canonicalToActiveComponentIndex(gasCompIdx);
if (blackoilConserveSurfaceVolume)
flux[conti0EqIdx + activeGasCompIdx] += Rsw*surfaceVolumeFlux;
else
flux[conti0EqIdx + activeGasCompIdx] += Rsw*surfaceVolumeFlux*FluidSystem::referenceDensity(gasPhaseIdx, pvtRegionIdx);
}
}
else if (phaseIdx == gasPhaseIdx) {
// vaporized oil (in the gas phase).

View File

@@ -163,6 +163,8 @@ struct EnableBrine<TypeTag, TTag::BlackOilModel> { static constexpr bool value =
template<class TypeTag>
struct EnableEvaporation<TypeTag, TTag::BlackOilModel> { static constexpr bool value = false; };
template<class TypeTag>
struct EnableDisgasInWater<TypeTag, TTag::BlackOilModel> { static constexpr bool value = false; };
template<class TypeTag>
struct EnableSaltPrecipitation<TypeTag, TTag::BlackOilModel> { static constexpr bool value = false; };
template<class TypeTag>
struct EnableMICP<TypeTag, TTag::BlackOilModel> { static constexpr bool value = false; };

View File

@@ -308,7 +308,7 @@ protected:
if (currentValue.primaryVarsMeaningWater() == PrimaryVariables::WaterMeaning::Sw)
delta *= satAlpha;
else {
//Ensure Rvw factor does not become negative
//Ensure Rvw and Rsw factor does not become negative
if (delta > currentValue[ Indices::waterSwitchIdx])
delta = currentValue[ Indices::waterSwitchIdx];
}

View File

@@ -127,6 +127,7 @@ public:
enum class WaterMeaning {
Sw, // water saturation
Rvw, // vaporized water
Rsw, // dissolved gas in water
Disabled, // The primary variable is not used
};
@@ -138,7 +139,6 @@ public:
enum class GasMeaning {
Sg, // gas saturation
Rs, // dissolved gas in oil
//Rsw, // dissolved gas in water
Rv, // vapporized oil
Disabled, // The primary variable is not used
};
@@ -349,6 +349,8 @@ public:
primaryVarsMeaningPressure_ = PressureMeaning::Pg;
} else if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
primaryVarsMeaningPressure_ = PressureMeaning::Po;
} else if ( waterPresent && FluidSystem::enableDissolvedGasInWater() && !gasPresent){
primaryVarsMeaningPressure_ = PressureMeaning::Pw;
} else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
primaryVarsMeaningPressure_ = PressureMeaning::Pg;
} else {
@@ -364,6 +366,8 @@ public:
primaryVarsMeaningWater_ = WaterMeaning::Sw;
} else if (gasPresent && FluidSystem::enableVaporizedWater()) {
primaryVarsMeaningWater_ = WaterMeaning::Rvw;
} else if (waterPresent && FluidSystem::enableDissolvedGasInWater()) {
primaryVarsMeaningWater_ = WaterMeaning::Rsw;
} else if (FluidSystem::phaseIsActive(waterPhaseIdx) && !oneActivePhases) {
primaryVarsMeaningWater_ = WaterMeaning::Sw;
} else {
@@ -381,8 +385,6 @@ public:
primaryVarsMeaningGas_ = GasMeaning::Rs;
} else if (gasPresent && FluidSystem::enableVaporizedOil()){
primaryVarsMeaningGas_ = GasMeaning::Rv;
//} else if (waterPresent && FluidSystem::enableDissolvedGasInWater()) {
// primaryVarsMeaningGas_ = Rsw;
} else if (FluidSystem::phaseIsActive(gasPhaseIdx) && FluidSystem::phaseIsActive(oilPhaseIdx)) {
primaryVarsMeaningGas_ = GasMeaning::Sg;
} else {
@@ -425,6 +427,12 @@ public:
(*this)[waterSwitchIdx] = rvw;
break;
}
case WaterMeaning::Rsw:
{
const auto& Rsw = BlackOil::getRsw_<FluidSystem, FluidState, Scalar>(fluidState, pvtRegionIdx_);
(*this)[waterSwitchIdx] = Rsw;
break;
}
case WaterMeaning::Disabled:
{
break;
@@ -450,12 +458,6 @@ public:
(*this)[compositionSwitchIdx] = rv;
break;
}
//case Rsw:
//{
//const auto& Rsw = BlackOil::getRsw_<FluidSystem, FluidState, Scalar>(fluidState, pvtRegionIdx_);
//(*this)[waterSwitchIdx] = Rsw;
// break;
//}
case GasMeaning::Disabled:
{
break;
@@ -530,7 +532,7 @@ public:
// keep track if any meaning has changed
bool changed = false;
// special case for cells with almost only water
// special case cells with almost only water
// use both saturations (if the phase is enabled)
if (sw >= thresholdWaterFilledCell) {
@@ -541,25 +543,20 @@ public:
if constexpr (compositionSwitchEnabled)
(*this)[Indices::compositionSwitchIdx] = 0.0;
//const Scalar& po = (*this)[pressureSwitchIdx];
changed = primaryVarsMeaningWater() != WaterMeaning::Sw || primaryVarsMeaningGas() != GasMeaning::Sg;
changed = primaryVarsMeaningGas() != GasMeaning::Sg;
if(changed) {
if constexpr (waterEnabled)
setPrimaryVarsMeaningWater(WaterMeaning::Sw);
if constexpr (compositionSwitchEnabled)
setPrimaryVarsMeaningGas(GasMeaning::Sg);
//setPrimaryVarsMeaningPressure(PressureMeaning::Po);
// use water pressure?
}
return changed;
}
// if water phase disappeares: Sw (water saturation) -> Rvw (fraction of water in gas phase)
// if water phase appears: Rvw (fraction of water in gas phase) -> Sw (water saturation)
switch(primaryVarsMeaningWater()) {
case WaterMeaning::Sw:
{
// if water phase disappeares: Sw (water saturation) -> Rvw (fraction of water in gas phase)
if(sw < -eps && sg > eps && FluidSystem::enableVaporizedWater()) {
Scalar p = (*this)[pressureSwitchIdx];
if(primaryVarsMeaningPressure() == PressureMeaning::Po) {
@@ -578,6 +575,27 @@ public:
changed = true;
break;
}
// if gas phase disappeares: Sw (water saturation) -> Rsw (fraction of gas in water phase)
// and Pg (gas pressure) -> Pw ( water pressure)
if(sg < -eps && sw > eps && FluidSystem::enableDissolvedGasInWater()) {
const Scalar& pg = (*this)[pressureSwitchIdx];
assert(primaryVarsMeaningPressure() == PressureMeaning::Pg);
std::array<Scalar, numPhases> pC = { 0.0 };
const MaterialLawParams& matParams = problem.materialLawParams(globalDofIdx);
Scalar so = 1.0 - sw - solventSaturation_();
computeCapillaryPressures_(pC, so, /*sg=*/ 0.0, sw, matParams);
Scalar pw = pg + (pC[waterPhaseIdx] - pC[gasPhaseIdx]);
Scalar rswSat = FluidSystem::waterPvt().saturatedGasDissolutionFactor(pvtRegionIdx_,
T,
pw,
saltConcentration);
setPrimaryVarsMeaningWater(WaterMeaning::Rsw);
(*this)[Indices::waterSwitchIdx] = rswSat; //primary variable becomes Rsw
setPrimaryVarsMeaningPressure(PressureMeaning::Pw);
(*this)[Indices::pressureSwitchIdx] = pw;
changed = true;
break;
}
break;
}
case WaterMeaning::Rvw:
@@ -595,14 +613,41 @@ public:
T,
p,
saltConcentration);
// if water phase appears: Rvw (fraction of water in gas phase) -> Sw (water saturation)
if (rvw > rvwSat*(1.0 + eps)) {
// water phase appears
setPrimaryVarsMeaningWater(WaterMeaning::Sw);
(*this)[Indices::waterSwitchIdx] = 0.0; // water saturation
changed = true;
}
break;
}
case WaterMeaning::Rsw:
{
// Gas phase not present. The hydrocarbon gas phase
// appears as soon as more of the gas component is present in the water phase
// than what saturated water can hold.
const Scalar& pw = (*this)[pressureSwitchIdx];
assert(primaryVarsMeaningPressure() == PressureMeaning::Pw);
Scalar rswSat = FluidSystem::waterPvt().saturatedGasDissolutionFactor(pvtRegionIdx_,
T,
pw,
saltConcentration);
Scalar rsw = (*this)[Indices::waterSwitchIdx];
if (rsw > rswSat) {
// the gas phase appears, i.e., switch the primary variables to WaterMeaning::Sw
setPrimaryVarsMeaningWater(WaterMeaning::Sw);
(*this)[Indices::waterSwitchIdx] = 1.0; // hydrocarbon water saturation
setPrimaryVarsMeaningPressure(PressureMeaning::Pg);
std::array<Scalar, numPhases> pC = { 0.0 };
const MaterialLawParams& matParams = problem.materialLawParams(globalDofIdx);
computeCapillaryPressures_(pC, /*so=*/ 0.0, /*sg=*/ 0.0, /*sw=*/ 1.0, matParams);
Scalar pg = pw + (pC[gasPhaseIdx] - pC[waterPhaseIdx]);
(*this)[Indices::pressureSwitchIdx] = pg;
changed = true;
}
break;
}
case WaterMeaning::Disabled:
{
break;
@@ -669,22 +714,6 @@ public:
(*this)[Indices::compositionSwitchIdx] = std::min(rvMax, rvSat);
changed = true;
}
//if(sg < -eps && sw > eps && FluidSystem::enableDissolvedGasInWater()) {
// const Scalar& po = (*this)[pressureSwitchIdx];
// std::array<Scalar, numPhases> pC = { 0.0 };
// const MaterialLawParams& matParams = problem.materialLawParams(globalDofIdx);
// Scalar so = 1.0 - sw - solventSaturation_();
// computeCapillaryPressures_(pC, so, /*sg=*/ 0.0, sw, matParams);
// Scalar pw = po + (pC[waterPhaseIdx] - pC[oilPhaseIdx]);
// Scalar rswSat = FluidSystem::waterPvt().saturatedWaterDissolutionFactor(pvtRegionIdx_,
// T,
// pw,
// saltConcentration);
// setPrimaryVarsMeaningWater(Rsw);
// (*this)[Indices::waterSwitchIdx] = rswSat; //primary variable becomes Rsw
// changed = true;
// break;
//}
break;
}
case GasMeaning::Rs:
@@ -755,11 +784,6 @@ public:
}
break;
}
//case Rsw:
//{
//TODO
// break;
//}
case GasMeaning::Disabled:
{
break;

View File

@@ -64,6 +64,9 @@ struct EnableSaltPrecipitation { using type = UndefinedProperty; };
//! Enable the ECL-blackoil extension for water evaporation
template<class TypeTag, class MyTypeTag>
struct EnableEvaporation { using type = UndefinedProperty; };
//! Enable the ECL-blackoil extension for disolution of gas into water
template<class TypeTag, class MyTypeTag>
struct EnableDisgasInWater { using type = UndefinedProperty; };
//! Enable the ECL-blackoil extension for MICP.
template<class TypeTag, class MyTypeTag>
struct EnableMICP { using type = UndefinedProperty; };