Skip to content

Commit

Permalink
Simplify thermal implementation (#53)
Browse files Browse the repository at this point in the history
* Refactor thermal to not use composite system

* Remove export of undefined system

* Don't add rock parameters for wells

* Update thermal test

* Clean up thermal tests

* input file: Use simpler thermal system

* Thermal: Apply perforation mask to perforation flow
  • Loading branch information
moyner authored Aug 23, 2024
1 parent ed49bd2 commit 3431e8b
Show file tree
Hide file tree
Showing 12 changed files with 108 additions and 150 deletions.
3 changes: 1 addition & 2 deletions docs/src/man/basics/systems.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,5 @@ For additional details, please see Chapter 8 - Compositional Simulation with the

```@docs
reservoir_system
ThermalSystem
Jutul.CompositeSystem
JutulDarcy.add_thermal_to_model!
```
1 change: 0 additions & 1 deletion src/JutulDarcy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ module JutulDarcy
export StandardVolumeSource, VolumeSource, MassSource
export OverallMoleFractions
export ImmiscibleSaturation
export ThermalSystem
export PhaseMassDensities, ConstantCompressibilityDensities
export BrooksCoreyRelativePermeabilities, TabulatedSimpleRelativePermeabilities

Expand Down
8 changes: 7 additions & 1 deletion src/facility/cross_terms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ function update_cross_term_in_entity!(out, i,
model_res, model_well,
ct::ReservoirFromWellThermalCT, eq, dt, ldisc = local_discretization(ct, i))
# Unpack properties
sys = thermal_system(model_res.system)
sys = model_res.system
nph = number_of_phases(sys)
@inbounds begin
reservoir_cell = ct.reservoir_cells[i]
Expand Down Expand Up @@ -303,6 +303,12 @@ function Jutul.subcrossterm(ct::ReservoirFromWellThermalCT, ctp, m_t, m_s, map_r
return ReservoirFromWellThermalCT(copy(CI), copy(WI), rc, copy(well_cells))
end

function Jutul.apply_force_to_cross_term!(ct_s, cross_term::ReservoirFromWellThermalCT, target, source, model, storage, dt, force::PerforationMask; time = time)
mask = force.values
apply_perforation_mask!(ct_s.target, mask)
apply_perforation_mask!(ct_s.source, mask)
end

struct WellFromFacilityThermalCT <: Jutul.AdditiveCrossTerm
well::Symbol
end
Expand Down
2 changes: 1 addition & 1 deletion src/flux.jl
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ function face_average_density(model, state, tpfa, phase)
return 0.5*(ρ_i + ρ_c)
end

function face_average_density(model::Union{CompositionalModel, ThermalCompositionalModel}, state, tpfa, phase)
function face_average_density(model::CompositionalModel, state, tpfa, phase)
sys = flow_system(model.system)
ρ = state.PhaseMassDensities
l = tpfa.left
Expand Down
13 changes: 8 additions & 5 deletions src/input_simulation/data_input.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ function setup_case_from_parsed_data(datafile;
flow_sys = flow_system(sys)
is_blackoil = flow_sys isa StandardBlackOilSystem
is_compositional = flow_sys isa CompositionalSystem
is_thermal = sys isa CompositeSystem && haskey(sys.systems, :thermal)
is_thermal = haskey(datafile["RUNSPEC"], "THERMAL")

rs = datafile["RUNSPEC"]
oil = haskey(rs, "OIL")
Expand Down Expand Up @@ -116,7 +116,13 @@ function setup_case_from_parsed_data(datafile;
push!(wells_systems, sys_w)
end

model = setup_reservoir_model(domain, sys; wells = wells, extra_out = false, wells_systems = wells_systems, kwarg...)
model = setup_reservoir_model(domain, sys;
thermal = is_thermal,
wells = wells,
extra_out = false,
wells_systems = wells_systems,
kwarg...
)
for (k, submodel) in pairs(model.models)
if model_or_domain_is_well(submodel) || k == :Reservoir
# Modify secondary variables
Expand Down Expand Up @@ -1167,9 +1173,6 @@ function parse_physics_types(datafile; pvt_region = missing)
end
sys = pick_system_from_pvt(pvt, rhoS, phases, is_immiscible)
end
if has("THERMAL")
sys = reservoir_system(flow = sys, thermal = ThermalSystem(sys))
end
return (system = sys, pvt = pvt)
end

Expand Down
2 changes: 1 addition & 1 deletion src/multiphase.jl
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ end
# @tullio acc[ph, ix[i]] = acc[ph, ix[i]] - phase_source(sources[i].cell, sources[i], rhoS[ph], kr, mu, ph)
# end

function convergence_criterion(model::SimulationModel{D, S}, storage, eq::ConservationLaw, eq_s, r; dt = 1, update_report = missing) where {D, S<:MultiPhaseSystem}
function convergence_criterion(model::SimulationModel{D, S}, storage, eq::ConservationLaw{:TotalMasses}, eq_s, r; dt = 1, update_report = missing) where {D, S<:MultiPhaseSystem}
M = global_map(model.domain)
v = x -> as_value(Jutul.active_view(x, M, for_variables = false))
Φ = v(storage.state.FluidVolume)
Expand Down
9 changes: 2 additions & 7 deletions src/thermal/equations.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
function select_equations!(eqs, sys::ThermalSystem, model::SimulationModel)
disc = model.domain.discretizations.heat_flow
eqs[:energy_conservation] = ConservationLaw(disc, :TotalThermalEnergy, 1)
end

@inline function Jutul.face_flux!(Q, left, right, face, face_sign, eq::ConservationLaw{:TotalThermalEnergy, <:Any}, state, model::ThermalModel, dt, flow_disc::TwoPointPotentialFlowHardCoded)
@inline function Jutul.face_flux!(Q, left, right, face, face_sign, eq::ConservationLaw{:TotalThermalEnergy, <:Any}, state, model, dt, flow_disc::TwoPointPotentialFlowHardCoded)
# Specific version for tpfa flux
# TODO: Add general version for thermal
grad = TPFA(left, right, face_sign)
Expand All @@ -14,7 +9,7 @@ end
return setindex(Q, q, 1)
end

@inline function Jutul.face_flux!(q_i, face, eq::ConservationLaw{:TotalThermalEnergy, <:Any}, state, model::ThermalModel, dt, flow_disc::PotentialFlow, ldisc)
@inline function Jutul.face_flux!(q_i, face, eq::ConservationLaw{:TotalThermalEnergy, <:Any}, state, model, dt, flow_disc::PotentialFlow, ldisc)
# Inner version, for generic flux
kgrad, upw = ldisc.face_disc(face)
ft = Jutul.flux_type(eq)
Expand Down
103 changes: 33 additions & 70 deletions src/thermal/thermal.jl
Original file line number Diff line number Diff line change
@@ -1,33 +1,3 @@


"""
ThermalSystem(flow_system, formulation = :Temperature)
Geothermal system that defines heat transfer through fluid advection and through
the rock itself. Can be combined with a multiphase system using
[`Jutul.CompositeSystem`](@ref).
"""
struct ThermalSystem{T, F} <: JutulSystem
flow_system::F
function ThermalSystem(sys::T;
formulation = :Temperature
) where T<:Union{MultiPhaseSystem, Missing}
@assert formulation == :Temperature
new{formulation, T}(sys)
end
end

thermal_system(sys::ThermalSystem) = sys
thermal_system(sys::CompositeSystem) = sys.systems.thermal
flow_system(sys::ThermalSystem) = sys.flow_system

const ThermalModel = SimulationModel{<:JutulDomain, <:ThermalSystem, <:Any, <:Any}

const ThermalCompositionalModel = SimulationModel{<:JutulDomain, <:ThermalSystem{<:Any, <:CompositionalSystem}, <:Any, <:Any}
const ThermalBlackOilModel = SimulationModel{<:JutulDomain, <:ThermalSystem{<:Any, <:StandardBlackOilModel}, <:Any, <:Any}
const ThermalImmiscibleModel = SimulationModel{<:JutulDomain, <:ThermalSystem{<:Any, <:ImmiscibleSystem}, <:Any, <:Any}
const ThermalSinglePhaseModel = SimulationModel{<:JutulDomain, <:ThermalSystem{<:Any, <:SinglePhaseSystem}, <:Any, <:Any}

struct BulkVolume <: ScalarVariable end
function Jutul.default_values(model, ::BulkVolume)
return 1.0
Expand Down Expand Up @@ -168,7 +138,7 @@ function Jutul.values_per_entity(model, ::PressureTemperatureDependentEnthalpy{T
return N
end

@jutul_secondary function update_temperature_dependent_enthalpy!(H_phases, var::PressureTemperatureDependentEnthalpy{T, R, N}, model::ThermalCompositionalModel, Pressure, Temperature, LiquidMassFractions, VaporMassFractions, PhaseMassDensities, ix) where {T, R, N}
@jutul_secondary function update_temperature_dependent_enthalpy!(H_phases, var::PressureTemperatureDependentEnthalpy{T, R, N}, model::CompositionalModel, Pressure, Temperature, LiquidMassFractions, VaporMassFractions, PhaseMassDensities, ix) where {T, R, N}
fsys = flow_system(model.system)
@assert !has_other_phase(fsys)
@assert N == number_of_components(fsys)
Expand Down Expand Up @@ -249,52 +219,45 @@ function Jutul.default_parameter_values(data_domain, model, param::RockThermalCo
return T
end

number_of_phases(t::ThermalSystem) = number_of_phases(flow_system(t))
number_of_components(t::ThermalSystem) = number_of_components(flow_system(t))

function select_primary_variables!(S, system::ThermalSystem, model)
S[:Temperature] = Temperature()
end

function select_parameters!(S, system::ThermalSystem, model)
nph = number_of_phases(system)
# Rock itself
S[:RockHeatCapacity] = RockHeatCapacity()
S[:RockDensity] = RockDensity()
S[:BulkVolume] = BulkVolume()
# Fluid heat related parameters
S[:ComponentHeatCapacity] = ComponentHeatCapacity()
S[:FluidVolume] = FluidVolume()
# Fluid flow related parameters
S[:PhaseMassDensities] = ConstantCompressibilityDensities(nph)
S[:Pressure] = Pressure()
S[:Saturations] = Saturations()
S[:PhaseViscosities] = PhaseViscosities()
if !model_or_domain_is_well(model)
S[:PhaseMassMobilities] = PhaseMassMobilities()
S[:RelativePermeabilities] = RelativePermeabilitiesParameter()
function add_thermal_to_model!(model::MultiModel)
for (k, m) in pairs(model.models)
if m.system isa MultiPhaseSystem
add_thermal_to_model!(m)
end
end
return m
end

function select_parameters!(prm, disc::D, model::ThermalModel) where D<:Union{TwoPointPotentialFlowHardCoded, Jutul.PotentialFlow}
if !model_or_domain_is_well(model)
prm[:FluidThermalConductivities] = FluidThermalConductivities()
prm[:RockThermalConductivities] = RockThermalConductivities()
prm[:Transmissibilities] = Transmissibilities()
prm[:TwoPointGravityDifference] = TwoPointGravityDifference()
function add_thermal_to_model!(model)
set_primary_variables!(model, Temperature = Temperature())
set_parameters!(model,
RockHeatCapacity = RockHeatCapacity(),
RockDensity = RockDensity(),
BulkVolume = BulkVolume(),
ComponentHeatCapacity = ComponentHeatCapacity(),
)
set_secondary_variables!(model,
FluidInternalEnergy = FluidInternalEnergy(),
FluidEnthalpy = FluidEnthalpy(),
RockInternalEnergy = RockInternalEnergy(),
TotalThermalEnergy = TotalThermalEnergy()
)
is_reservoir = !model_or_domain_is_well(model)
if is_reservoir
set_parameters!(model,
RockThermalConductivities = RockThermalConductivities(),
FluidThermalConductivities = FluidThermalConductivities()
)
end
end

function select_secondary_variables!(S, system::ThermalSystem, model)
S[:FluidInternalEnergy] = FluidInternalEnergy()
S[:FluidEnthalpy] = FluidEnthalpy()
S[:RockInternalEnergy] = RockInternalEnergy()
S[:TotalThermalEnergy] = TotalThermalEnergy()
end
disc = model.domain.discretizations.heat_flow
model.equations[:energy_conservation] = ConservationLaw(disc, :TotalThermalEnergy, 1)

function select_minimum_output_variables!(out, system::ThermalSystem, model)
out = model.output_variables
push!(out, :TotalThermalEnergy)
push!(out, :FluidEnthalpy)

unique!(out)
return model
end

include("variables.jl")
Expand Down
12 changes: 6 additions & 6 deletions src/thermal/variables.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@jutul_secondary function update_fluid_internal_energy!(U, fe::FluidInternalEnergy, model::ThermalImmiscibleModel, Temperature, ComponentHeatCapacity, ix)
@jutul_secondary function update_fluid_internal_energy!(U, fe::FluidInternalEnergy, model, Temperature, ComponentHeatCapacity, ix)
C = ComponentHeatCapacity
@assert size(U) == size(C) "This fluid internal energy implementation assumes immiscible phases."
for i in ix
Expand All @@ -9,7 +9,7 @@
end
end

@jutul_secondary function update_fluid_internal_energy!(U, fe::FluidInternalEnergy, model::ThermalSinglePhaseModel, Temperature, ComponentHeatCapacity, ix)
@jutul_secondary function update_fluid_internal_energy!(U, fe::FluidInternalEnergy, model::SinglePhaseModel, Temperature, ComponentHeatCapacity, ix)
C = ComponentHeatCapacity
@assert size(U) == size(C) "This fluid internal energy implementation assumes immiscible phases."
for i in ix
Expand All @@ -20,7 +20,7 @@ end
end
end

@jutul_secondary function update_fluid_internal_energy!(U, fe::FluidInternalEnergy, model::ThermalCompositionalModel, Temperature, ComponentHeatCapacity, LiquidMassFractions, VaporMassFractions, ix)
@jutul_secondary function update_fluid_internal_energy!(U, fe::FluidInternalEnergy, model::CompositionalModel, Temperature, ComponentHeatCapacity, LiquidMassFractions, VaporMassFractions, ix)
fsys = flow_system(model.system)
C = ComponentHeatCapacity
X = LiquidMassFractions
Expand Down Expand Up @@ -50,7 +50,7 @@ end
end
end

@jutul_secondary function update_fluid_enthalpy!(H, fe::FluidEnthalpy, model::ThermalModel, FluidInternalEnergy, Pressure, PhaseMassDensities, ix)
@jutul_secondary function update_fluid_enthalpy!(H, fe::FluidEnthalpy, model, FluidInternalEnergy, Pressure, PhaseMassDensities, ix)
for i in ix
p = Pressure[i]
for ph in axes(H, 1)
Expand All @@ -59,13 +59,13 @@ end
end
end

@jutul_secondary function update_rock_internal_energy!(U_r, e::RockInternalEnergy, model::ThermalModel, RockHeatCapacity, Temperature, ix)
@jutul_secondary function update_rock_internal_energy!(U_r, e::RockInternalEnergy, model, RockHeatCapacity, Temperature, ix)
for i in ix
U_r[i] = RockHeatCapacity[i]*Temperature[i]
end
end

@jutul_secondary function update_total_thermal_energy!(E_total, te::TotalThermalEnergy, model::ThermalModel, Saturations, PhaseMassDensities, FluidInternalEnergy, RockDensity, RockInternalEnergy, BulkVolume, FluidVolume, ix)
@jutul_secondary function update_total_thermal_energy!(E_total, te::TotalThermalEnergy, model, Saturations, PhaseMassDensities, FluidInternalEnergy, RockDensity, RockInternalEnergy, BulkVolume, FluidVolume, ix)
U_f = FluidInternalEnergy
U_r = RockInternalEnergy
ρ_f = PhaseMassDensities
Expand Down
4 changes: 4 additions & 0 deletions src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,8 @@ struct SinglePhaseSystem{P, F} <: MultiPhaseSystem where {P, F<:AbstractFloat}
rho_ref::F
end

const ImmiscibleModel = SimulationModel{D, S, F, C} where {D, S<:ImmiscibleSystem, F, C}

"""
SinglePhaseSystem(phase = LiquidPhase(); reference_density = 1.0)
Expand All @@ -226,6 +228,8 @@ function SinglePhaseSystem(phase = LiquidPhase(); reference_density = 1.0)
return SinglePhaseSystem{typeof(phase), typeof(reference_density)}(phase, reference_density)
end

const SinglePhaseModel = SimulationModel{D, S, F, C} where {D, S<:SinglePhaseSystem, F, C}

number_of_components(sys::SinglePhaseSystem) = 1

abstract type AbstractPhaseRelativePermeability{T, N} end
Expand Down
24 changes: 12 additions & 12 deletions src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ function setup_reservoir_model(reservoir::DataDomain, system::JutulSystem;
reservoir_context = nothing,
general_ad = false,
backend = :csc,
thermal = false,
extra_outputs = [:LiquidMassFractions, :VaporMassFractions, :Rs, :Rv, :Saturations],
split_wells = false,
assemble_wells_together = true,
Expand Down Expand Up @@ -275,6 +276,9 @@ function setup_reservoir_model(reservoir::DataDomain, system::JutulSystem;
general_ad = general_ad,
kgrad = kgrad
)
if thermal
rmodel = add_thermal_to_model!(rmodel)
end
set_discretization_variables!(rmodel)
set_reservoir_variable_defaults!(rmodel,
dp_max_abs = dp_max_abs,
Expand Down Expand Up @@ -328,6 +332,9 @@ function setup_reservoir_model(reservoir::DataDomain, system::JutulSystem;
end
wname = w.name
wmodel = SimulationModel(w_domain, system, context = context)
if thermal
wmodel = add_thermal_to_model!(wmodel)
end
set_reservoir_variable_defaults!(wmodel,
dp_max_abs = dp_max_abs_well,
dp_max_rel = dp_max_rel_well,
Expand Down Expand Up @@ -792,18 +799,11 @@ end
function setup_reservoir_cross_terms!(model::MultiModel)
rmodel = reservoir_model(model)
has_composite = rmodel isa Jutul.CompositeModel
if has_composite
systems = rmodel.system.systems
has_flow = haskey(systems, :flow)
has_thermal = haskey(systems, :thermal)
conservation = Pair(:flow, :mass_conservation)
energy = Pair(:thermal, :energy_conservation)
else
has_flow = rmodel.system isa MultiPhaseSystem
has_thermal = !has_flow
conservation = :mass_conservation
energy = :energy_conservation
end

has_flow = rmodel.system isa MultiPhaseSystem
has_thermal = haskey(rmodel.equations, :energy_conservation)
conservation = :mass_conservation
energy = :energy_conservation
for (k, m) in pairs(model.models)
if k == :Reservoir
# These are set up from wells via symmetry
Expand Down
Loading

0 comments on commit 3431e8b

Please sign in to comment.