Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Thermal rework #32

Merged
merged 92 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
b798e1b
Improve blackoil initialization
moyner Feb 8, 2024
49485f2
Add verbose option to setup_case_from_parsed_data
moyner Feb 8, 2024
974c6ad
Speed up initial state by explicit loop
moyner Feb 8, 2024
da500ba
Speed up initialization with many regions
moyner Feb 8, 2024
7d50304
Remove debug output.
moyner Feb 9, 2024
93f8636
Clamp vapor fraction for k value flash
moyner Feb 10, 2024
5c5e1b6
Improve assert message
moyner Feb 10, 2024
a2996d4
Add two variable defs for CO2 models
moyner Feb 12, 2024
56aa0e7
Fixes to CO2-brine PVT
moyner Feb 13, 2024
4e0e62f
Add P-T tabulated viscosities
moyner Feb 13, 2024
a04b337
Update flash.jl
moyner Feb 13, 2024
232a6d2
Fix typo in saturations computed from density
moyner Feb 13, 2024
77fb9c8
Add KValueWrapper type
moyner Feb 13, 2024
5d8a8bc
Swap default component order for brine mixture
moyner Feb 13, 2024
bce6321
Remove runtime dispatch from loop
moyner Feb 13, 2024
daf5408
Clean up brine density
moyner Feb 13, 2024
c3acd43
Improve RESV weight calculation
moyner Feb 13, 2024
2c7972d
Fix typo in assert
moyner Feb 13, 2024
27505bd
Cleanup in compositional
moyner Feb 14, 2024
6461f5e
Some small performance increases for k values
moyner Feb 14, 2024
6d3c59b
Add a utility, clean up to kr
moyner Feb 14, 2024
3a98b84
Update mrst_input.jl
moyner Feb 14, 2024
951c8b0
Add missing function for composite system
moyner Feb 15, 2024
01f4b2a
A bunch of smaller thermal fixes
moyner Feb 15, 2024
b4e9f17
Fix error in mole fraction increment norm
moyner Feb 15, 2024
8217cea
Improvement to endscale setup
moyner Feb 16, 2024
e78e653
Avoid crash for "nothing" control when split_wells = true
moyner Feb 16, 2024
081253c
Graceful handling of missing increments
moyner Feb 16, 2024
5359ee5
Avoid extra parameters for wells in thermal
moyner Feb 16, 2024
ebeb923
Update multicomponent.jl
moyner Feb 16, 2024
48b5626
Fixes to dt/well mix parsing
moyner Feb 19, 2024
c9bfc94
Turn parser error into warning
moyner Feb 19, 2024
a4f07d3
Handle welopen
moyner Feb 19, 2024
b071cb9
Handle well temperature
moyner Feb 19, 2024
bc42901
Handle single phase "rel perm"
moyner Feb 19, 2024
557b04c
Handle single phase in equilibriation
moyner Feb 19, 2024
1cc7110
Some thermal scaffolding
moyner Feb 19, 2024
a3c71d5
A few thermal fixes
moyner Feb 20, 2024
a621e84
Update controls.jl
moyner Feb 20, 2024
5a6da39
Thermal setup
moyner Feb 20, 2024
d6abf68
Don't use saturations as primary for single phase
moyner Feb 20, 2024
c330367
Update mrst_input.jl
moyner Feb 20, 2024
2aa18a6
More composite fixes
moyner Feb 20, 2024
0f68a81
Thermal fixes
moyner Feb 20, 2024
9d53d75
Handle initialization of thermal conductivities
moyner Feb 20, 2024
677ee35
Transfer over some more thermal properties
moyner Feb 20, 2024
87e8b19
Temperature fix
moyner Feb 20, 2024
435af17
Add subcrossterm to thermal
moyner Feb 21, 2024
a1a4630
Allow passing of custom config to simulate_reservoir
moyner Feb 22, 2024
d7c213f
add PT table variable
moyner Feb 22, 2024
ff9490c
Add heat capacities to reservoir_domain
moyner Feb 22, 2024
b2b72db
Set default maximum temperature to 1 million degrees K
moyner Feb 22, 2024
4972508
Use new thermal properties for default values
moyner Feb 22, 2024
ca0f609
Convergence criterion for energy
moyner Feb 22, 2024
ac1c20a
Add missing kwarg
moyner Feb 22, 2024
c418b81
Fix phase_face_average signature
moyner Feb 22, 2024
77c9140
Use face average for saturations in conductive flux
moyner Feb 22, 2024
525b7b2
Use analytical K-value flash when ncomp = 2 or 3
moyner Feb 23, 2024
02606fb
Fixes to welopen
moyner Feb 23, 2024
ef8c175
Fix to PBVD init
moyner Feb 23, 2024
be3808e
Update init.jl
moyner Feb 23, 2024
095c1d9
Update init.jl
moyner Feb 23, 2024
33fcd5c
Put heat capacity per component instead of phase
moyner Feb 24, 2024
936ff4a
Some thermal related improvements
moyner Feb 24, 2024
114bb0d
Make ThermalSystem hold the flow system
moyner Feb 24, 2024
54ba562
Add some dispatches for different thermal models
moyner Feb 24, 2024
0d272fd
Add compositional specialization of internal energy
moyner Feb 24, 2024
e2adf47
Update equations.jl
moyner Feb 24, 2024
e8d5242
Fix to thermal flux for compositional
moyner Feb 24, 2024
e32ed9a
Move function to fix load order
moyner Feb 24, 2024
f53f80b
Make InjectorControl fully parametric
moyner Feb 24, 2024
1d57f6d
Add more fields to deck types
moyner Feb 25, 2024
12777f8
Add WATDENT to setup (not eval)
moyner Feb 25, 2024
6a566f8
Put in place some more thermal stuff
moyner Feb 25, 2024
cd5f7d6
Switch dp abs to use MPa as scaling
moyner Feb 26, 2024
359e813
Update utils.jl
moyner Feb 26, 2024
6475e97
Update utils.jl
moyner Feb 26, 2024
c6dd975
Quick implementation of thermal viscosities from input file
moyner Feb 26, 2024
c70e279
Support for WATDENT
moyner Feb 26, 2024
bba0e59
Add enthalpy mixing draft
moyner Feb 26, 2024
dddb157
Handle WTEMP order like WEFAC etc
moyner Feb 26, 2024
c4fb95f
Improve thermal viscosity logic
moyner Feb 27, 2024
4aebac9
Make use of InjectorControl enthalpy
moyner Feb 28, 2024
2873192
Go via internal energy for well enthalpy when not specified
moyner Feb 28, 2024
448e8cd
Add diffusion to compositional flux
moyner Feb 28, 2024
0c89a0f
Make thermal variable change configurable
moyner Mar 1, 2024
ccba1aa
Use saturation min for diffusion
moyner Mar 3, 2024
b73ca17
Patch to well enthalpy
moyner Mar 4, 2024
548fd84
Fix to function dispatch for K-values
moyner Mar 4, 2024
6bab313
Clean up old code
moyner Mar 4, 2024
9184a0a
Fix to test
moyner Mar 4, 2024
2c40d6e
Simplify bouyancy term when properties exist
moyner Mar 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/JutulDarcy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,6 @@ module JutulDarcy
include("porousmedia_grids.jl")
include("utils.jl")
include("interpolation.jl")
include("flux.jl")
# Definitions for multiphase flow
include("multiphase.jl")
include("variables/variables.jl")
Expand All @@ -167,6 +166,7 @@ module JutulDarcy
# Wells etc.
include("facility/facility.jl")

include("flux.jl")
include("porousmedia.jl")
# MRST inputs and test cases that use MRST input
# and .DATA file simulation
Expand Down
21 changes: 16 additions & 5 deletions src/blackoil/blackoil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ function cnv_mb_errors_bo(r, Φ, b, dt, rhoS, ::Val{N}) where N
return (Tuple(cnv), Tuple(mb))
end

function handle_alternate_primary_variable_spec!(init, found, sys::StandardBlackOilSystem)
function handle_alternate_primary_variable_spec!(init, found, rmodel, sys::StandardBlackOilSystem)
# Internal utility to handle non-trivial specification of primary variables
nph = number_of_phases(sys)
@assert haskey(init, :Pressure)
Expand Down Expand Up @@ -137,18 +137,29 @@ function handle_alternate_primary_variable_spec!(init, found, sys::StandardBlack
F_rv = sys.rv_max
if has_disgas(sys)
rs = init[:Rs]
rs_var = rmodel[:Rs]
else
rs = zeros(nc)
rs_var = nothing
end
if has_vapoil(sys)
rv = init[:Rs]
rv = init[:Rv]
rv_var = rmodel[:Rv]
else
rv = zeros(nc)
rv_var = nothing
end
so = @. 1.0 - sw - sg
bo = map(
(w, o, g, r, v, p) -> blackoil_unknown_init(F_rs, F_rv, w, o, g, r, v, p),
sw, so, sg, rs, rv, pressure)
bo = Vector{BlackOilX{Float64}}()
sizehint!(bo, nc)
for i in 1:nc
reg_rs = region(rs_var, i)
reg_rv = region(rv_var, i)
F_rs_i = table_by_region(F_rs, reg_rs)
F_rv_i = table_by_region(F_rv, reg_rv)
v = blackoil_unknown_init(F_rs_i, F_rv_i, sw[i], so[i], sg[i], rs[i], rv[i], pressure[i])
push!(bo, v)
end
init[:BlackOilUnknown] = bo
push!(found, :BlackOilUnknown)
end
Expand Down
8 changes: 8 additions & 0 deletions src/blackoil/variables/variables.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ struct Rs{F, R} <: ScalarVariable
regions::R
end

@inline function region(pv::Rs, cell)
return region(pv.regions, cell)
end

function Rs(rs_max::F; regions::R = nothing) where {F, R}
return Rs{F, R}(rs_max, regions)
end
Expand All @@ -49,6 +53,10 @@ function Rv(rv_max::F; regions::R = nothing) where {F, R}
return Rv{F, R}(rv_max, regions)
end

@inline function region(pv::Rv, cell)
return region(pv.regions, cell)
end

function Jutul.subvariable(v::Rv, map::FiniteVolumeGlobalMap)
c = map.cells
regions = Jutul.partition_variable_slice(v.regions, c)
Expand Down
58 changes: 54 additions & 4 deletions src/deck_support.jl
Original file line number Diff line number Diff line change
@@ -1,14 +1,37 @@
@jutul_secondary function update_deck_viscosity!(mu, μ::DeckPhaseViscosities, model, Pressure, ix)
pvt, reg = μ.pvt, μ.regions
@inbounds for ph in axes(mu, 1)
pvt_ph = pvt[ph]
for i in ix
p = Pressure[i]
@inbounds for i in ix
p = Pressure[i]
for ph in axes(mu, 1)
pvt_ph = pvt[ph]
@inbounds mu[ph, i] = viscosity(pvt_ph, reg, p, i)
end
end
end

@jutul_secondary function update_deck_viscosity!(mu, μ::DeckPhaseViscosities{<:Any, Ttab, <:Any}, model, Pressure, Temperature, ix) where Ttab<:DeckThermalViscosityTable
pvt, reg = μ.pvt, μ.regions
for i in ix
r_i = region(μ, i)
p = Pressure[i]
T = Temperature[i]
for ph in axes(mu, 1)
pvt_ph = pvt[ph]
pvt_thermal = table_by_region(μ.thermal.visc_tab[ph], r_i)
p_ref = table_by_region(μ.thermal.p_ref[ph], r_i)
mu_thermal = pvt_thermal(T)
if isfinite(p_ref)
# We have pressure dependence in addition to temperature
# dependence.
mu_p = viscosity(pvt_ph, reg, p, i)
mu_ref = viscosity(pvt_ph, reg, p_ref, i)
mu_thermal *= mu_p/mu_ref
end
mu[ph, i] = mu_thermal
end
end
end

@jutul_secondary function update_deck_density!(rho, ρ::DeckPhaseMassDensities, model, Pressure, ix)
rhos = reference_densities(model.system)
pvt, reg = ρ.pvt, ρ.regions
Expand All @@ -23,6 +46,33 @@ end
end
end

@jutul_secondary function update_deck_density!(rho, ρ::DeckPhaseMassDensities{<:Any, <:WATDENT, <:Any}, model, Pressure, Temperature, ix)
rhos = reference_densities(model.system)
pvt, reg = ρ.pvt, ρ.regions
phases = get_phases(model.system)
# Note immiscible assumption
for i in ix
r_i = region(ρ, i)
p = Pressure[i]
T = Temperature[i]
for ph in axes(rho, 1)
rhos_ph = rhos[ph]
pvt_ph = pvt[ph]
if phases[ph] == AqueousPhase()
T_ref, c1, c2 = ρ.watdent.tab[r_i]
pvtw = pvt_ph.tab[r_i]
p_ref = pvtw.p_ref
B_pref = 1.0/shrinkage(pvt_ph, reg, p_ref, i)
Δp = pvtw.b_c*(p - p_ref)
ΔT = T - T_ref
B_w = B_pref*(1.0 - Δp)*(1.0 + c1*ΔT + c2*ΔT^2)
rho[ph, i] = rhos_ph/B_w
else
rho[ph, i] = rhos_ph*shrinkage(pvt_ph, reg, p, i)
end
end
end
end

@jutul_secondary function update_deck_shrinkage!(b, ρ::DeckShrinkageFactors, model, Pressure, ix)
pvt, reg = ρ.pvt, ρ.regions
Expand Down
70 changes: 61 additions & 9 deletions src/deck_types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ abstract type AbstractTablePVT <: AbstractReservoirDeckTable end
Secondary variable used to evaluate viscosities when a case is generated from a
input file. Typically not instantiated in user scripts.
"""
struct DeckPhaseViscosities{T, R} <: DeckPhaseVariables
struct DeckPhaseViscosities{T, M, R} <: DeckPhaseVariables
pvt::T
thermal::M
regions::R
function DeckPhaseViscosities(pvt; regions = nothing)
function DeckPhaseViscosities(pvt; regions = nothing, thermal = nothing)
check_regions(regions)
pvt_t = Tuple(pvt)
new{typeof(pvt_t), typeof(regions)}(pvt_t, regions)
thermal::Union{Nothing, DeckThermalViscosityTable}
new{typeof(pvt_t), typeof(thermal), typeof(regions)}(pvt_t, thermal, regions)
end
end

Expand All @@ -24,13 +26,15 @@ end
Secondary variable used to evaluate densities when a case is generated from a
input file. Typically not instantiated in user scripts.
"""
struct DeckPhaseMassDensities{T, R} <: DeckPhaseVariables
struct DeckPhaseMassDensities{T, W, R} <: DeckPhaseVariables
pvt::T
watdent::W
regions::R
function DeckPhaseMassDensities(pvt; regions = nothing)
function DeckPhaseMassDensities(pvt; regions = nothing, watdent = nothing)
check_regions(regions)
pvt_t = Tuple(pvt)
new{typeof(pvt_t), typeof(regions)}(pvt_t, regions)
watdent::Union{Nothing, WATDENT}
new{typeof(pvt_t), typeof(watdent), typeof(regions)}(pvt_t, watdent, regions)
end
end

Expand All @@ -40,13 +44,15 @@ DeckShrinkageFactors(pvt, regions = nothing)
Secondary variable used to evaluate shrinkage factors when a case is generated
from a input file. Typically not instantiated in user scripts.
"""
struct DeckShrinkageFactors{T, R} <: DeckPhaseVariables
struct DeckShrinkageFactors{T, W, R} <: DeckPhaseVariables
pvt::T
watdent::W
regions::R
function DeckShrinkageFactors(pvt; regions = nothing)
function DeckShrinkageFactors(pvt; watdent = nothing, regions = nothing)
check_regions(regions)
pvt_t = Tuple(pvt)
new{typeof(pvt_t), typeof(regions)}(pvt_t, regions)
watdent_t = region_wrap(watdent, regions)
new{typeof(pvt_t), typeof(watdent_t), typeof(regions)}(pvt_t, watdent, regions)
end
end

Expand Down Expand Up @@ -376,6 +382,52 @@ function PVTW(pvtw::AbstractArray)
PVTW{N, T}(ct)
end

struct DeckThermalViscosityTable{T, V}
visc_tab::T
p_ref::V
rs_ref::V
end

function DeckThermalViscosityTable(props::AbstractDict, pvt, water, oil, gas)
visc_tab = []
function tab_to_interp(tab)
return map(x -> get_1d_interpolator(x[:, 1] .+ 273.15, x[:, 2]), tab)
end
if water
push!(visc_tab, tab_to_interp(props["WATVISCT"]))
end
if oil
push!(visc_tab, tab_to_interp(props["OILVISCT"]))
end
if gas
push!(visc_tab, tab_to_interp(props["GASVISCT"]))
end
visc_tab = Tuple(visc_tab)
if haskey(props, "VISCREF")
vref = props["VISCREF"]
rs_ref = map(x -> x[2], vref)
p_ref = map(x -> x[1], vref)
else
nreg = length(first(visc_tab))
rs_ref = fill(NaN, nreg)
p_ref = fill(NaN, nreg)
end
return DeckThermalViscosityTable(visc_tab, p_ref, rs_ref)
end


struct WATDENT{N, T} <: AbstractTablePVT
tab::NTuple{N, T}
end

function WATDENT(watdent::AbstractArray)
c = map(rec -> (T = rec[1], c1 = rec[2], c2 = rec[3]), watdent)
ct = Tuple(c)
N = length(ct)
T = typeof(ct[1])
return WATDENT{N, T}(ct)
end

struct PVCDO{N, T} <: AbstractTablePVT
tab::NTuple{N, T}
end
Expand Down
6 changes: 5 additions & 1 deletion src/facility/controls.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ function Jutul.update_before_step_multimodel!(storage_g, model_g::MultiModel, mo
pos = get_well_position(model.domain, key)
q_t[pos] = valid_surface_rate_for_control(q_t[pos], newctrl)
if changed
cfg.limits[key] = merge(cfg.limits[key], as_limit(newctrl.target))
if isnothing(cfg.limits[key])
cfg.limits[key] = as_limit(newctrl.target)
else
cfg.limits[key] = merge(cfg.limits[key], as_limit(newctrl.target))
end
end
end
cfg.step_index = current_step
Expand Down
41 changes: 29 additions & 12 deletions src/facility/cross_terms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,15 @@ function Base.show(io::IO, d::ReservoirFromWellThermalCT)
n = length(d.CI)
print(io, "ReservoirFromWellThermalCT ($n connections)")
end

function Jutul.subcrossterm(ct::ReservoirFromWellThermalCT, ctp, m_t, m_s, map_res::FiniteVolumeGlobalMap, ::TrivialGlobalMap, partition)
(; CI, WI, reservoir_cells, well_cells) = ct
rc = map(
c -> Jutul.local_cell(c, map_res),
reservoir_cells)
return ReservoirFromWellThermalCT(copy(CI), copy(WI), rc, copy(well_cells))
end

struct WellFromFacilityThermalCT <: Jutul.AdditiveCrossTerm
well::Symbol
end
Expand All @@ -305,27 +314,35 @@ function update_cross_term_in_entity!(out, i,
qT += 0*bottom_hole_pressure(state_well)

cell = well_top_node()
H = well_top_node_enthalpy(ctrl, state_well, cell)
H = well_top_node_enthalpy(ctrl, well, state_well, cell)
out[] = -qT*H
end

function well_top_node_enthalpy(ctrl::InjectorControl, state_well, cell)
heat_capacity = state_well.FluidHeatCapacity[cell]
function well_top_node_enthalpy(ctrl::InjectorControl, model, state_well, cell)
p = state_well.Pressure[cell]
density = ctrl.mixture_density
# density = ctrl.mixture_density
T = ctrl.temperature
nph = size(state_well.Saturations, 1)
H = 0
for ph in 1:nph
C = state_well.FluidHeatCapacity[ph, cell]
dens = state_well.PhaseMassDensities[ph, cell]
S = state_well.Saturations[ph, cell]
H += S*(C*T + p/dens)
H_w = ctrl.enthalpy
if ismissing(H_w)
H = 0.0
for ph in axes(state_well.Saturations, 1)
# Define it via the volume weighted internal energy
S = state_well.Saturations[ph, cell]
dens = state_well.PhaseMassDensities[ph, cell]
C = state_well.ComponentHeatCapacity[ph, cell]
H += S*(C*T + p/dens)
end
elseif H_w isa Real
H = H_w
elseif H_w isa Function
H = H_w(p, T)
else
error("InjectorControl.enthalpy must be missing, a real or a function (p, T).")
end
return H
end

function well_top_node_enthalpy(ctrl, state_well, cell)
function well_top_node_enthalpy(ctrl, model, state_well, cell)
H = state_well.FluidEnthalpy
S = state_well.Saturations
H_w = 0.0
Expand Down
Loading
Loading