Skip to content

Commit beab59c

Browse files
committed
Change deepheating code style to match rest of AGNI style: renamed variables, removed redundant code, and consolidated config-parser. Added Andy to collaborators page. Version bump (1.8.7). Deep_heating functionality otherwise unchanged
1 parent 2eb7677 commit beab59c

10 files changed

Lines changed: 130 additions & 180 deletions

File tree

.zenodo.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
}
2323
],
2424
"title": "AGNI: An open-source model for extreme atmospheres on rocky exoplanets",
25-
"version": "1.8.6",
25+
"version": "1.8.7",
2626
"access_right": "open",
2727
"related_identifiers": [
2828
{

CITATION.cff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ title: "AGNI: An open-source model for extreme atmospheres on rocky exoplanets"
1010
doi: 10.21105/joss.07726
1111
date-released: 2025-11-20
1212

13-
version: 1.8.6
13+
version: 1.8.7
1414
url: "https://github.com/nichollsh/AGNI"
1515
type: software
1616
license: "GPL-3.0"

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "AGNI"
22
uuid = "ede838c1-9ec3-4ebe-8ae8-da4091b3f21c"
33
authors = ["Harrison Nicholls <harrison.nicholls@physics.ox.ac.uk>"]
4-
version = "1.8.6"
4+
version = "1.8.7"
55

66
[deps]
77
ArgParse = "c7e460c6-2fb9-53a9-8c5b-16f535851c63"

codemeta.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@
1919
"keywords": "exoplanets, radiation, astronomy, atmosphere, optimization, julia, fortran, convection, chemistry, magma, planetary, physics",
2020
"license": "GPL-3.0",
2121
"title": "AGNI",
22-
"version": "1.8.6"
22+
"version": "1.8.7"
2323
}

docs/src/thanks.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ I would like to thank the following people for their input and assistance during
44

55
* [Tim Lichtenberg](https://www.formingworlds.space/team/tim-lichtenberg)
66
* [Raymond Pierrehumbert](https://users.physics.ox.ac.uk/~pierrehumbert/)
7-
* [Namrah Habib](https://www.physics.ox.ac.uk/our-people/habibn)
8-
* [Claire Marie Guimond](https://clairesworld.github.io/)
97
* [Arjun Savel](https://www.arjunsavel.com/) -- JOSS paper reviewer
108
* [Ryan Macdonald](https://distantworlds.space/) -- JOSS paper reviewer
9+
* [Cheng An Hsieh](https://didymos65803.github.io/)
10+
* [Namrah Habib](https://www.physics.ox.ac.uk/our-people/habibn)
1111
* [Leoni Janssen](https://www.universiteitleiden.nl/en/staffmembers/leoni-janssen)
1212
* [Karen Stuitje](https://github.com/stuitje)
1313
* [Boding Ouyang](https://github.com/OYBDOOO)
1414
* [Soumil Kelkar](https://research.rug.nl/en/persons/soumil-kelkar/)
15+
* [Claire Marie Guimond](https://clairesworld.github.io/)
1516
* [Stuart Daines](https://scholar.google.com/citations?user=EZqVB7wAAAAJ)
1617

1718
Please contact [Harrison Nicholls](https://www.h-nicholls.space/) for any queries relating to AGNI.

res/config/default.toml

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,6 @@ title = "Default" # Name for this configuration file
2222
wind_speed = 2.0 # Effective wind speed for sensible heat [m s-1].
2323
stellar_Teff = 4000.0 # Stellar effective temperature, if using `input_star="blackbody"`
2424

25-
[deep_heating]
26-
active = false # Enable deep atmospheric heating.
27-
P_dep = 1.0e5 # Deposition pressure [Pa] - center of Gaussian heating profile.
28-
sigma_P = 1.0 # Width of Gaussian in log-pressure space [dimensionless].
29-
efficiency = 0.0 # Heating efficiency as fraction of instellation.
30-
normalization = "pressure" # "pressure" (legacy dF/dP) | "mass" (dm-weighted).
31-
below_domain = "clamp" # "clamp" | "boundary_flux" (if P_dep outside domain).
32-
power_mode = "efficiency" # "efficiency" | "flux".
33-
F_total = 0.0 # [W m-2] used when power_mode="flux".
34-
3525
[files]
3626
input_sf = "res/spectral_files/Dayspring/48/Dayspring.sf" # Path to SOCRATES spectral file. Set to "greygas" for grey RT.
3727
input_star = "res/stellar_spectra/sun.txt" # Path to stellar spectrum. Set to "blackbody" to use `planet.stellar_Teff`.
@@ -80,6 +70,15 @@ title = "Default" # Name for this configuration file
8070
convection_crit = "s" # Stability criterion for convection. Options: (s)chwarzschild or (l)edoux.
8171
convection = true # Include heat transport by convection
8272

73+
[physics.deep_heating]
74+
Pmid = 1e-3 # Center of Gaussian heating profile [bar]
75+
Pwid = 1.0 # Width of Gaussian in log-Pascal units.
76+
power_mode = "off" # Power mode for heating (off, rel, abs)
77+
norm_method = "pressure" # Normalisation coordinate: "pressure" (legacy dF/dP), or "mass" (dm-weighted).
78+
domain = "clamp" # How to handle Pmid outside domain (clamp, boundary_flux)
79+
flux_rel = 0.0 # Set flux by fraction of instellation, used for power_mode="rel".
80+
flux_abs = 10.0 # Set flux by [W m-2], used for power_mode="abs".
81+
8382
[plots]
8483
at_runtime = true # Make some plots at runtime?
8584
temperature = true # Plot temperature profile?

src/AGNI.jl

Lines changed: 18 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -486,42 +486,6 @@ module AGNI
486486
io_dir = cfg["files"]["io_dir"]
487487
end
488488

489-
# Deep heating configuration
490-
deep_active::Bool = false
491-
deep_P_dep::Float64 = 1.0e5
492-
deep_sigma_P::Float64 = 1.0
493-
deep_efficiency::Float64 = 0.0
494-
deep_norm::Symbol = :pressure
495-
deep_below::Symbol = :clamp
496-
deep_power_mode::Symbol = :efficiency
497-
deep_F_total::Float64 = 0.0
498-
if haskey(cfg, "deep_heating")
499-
dh = cfg["deep_heating"]
500-
if haskey(dh, "active")
501-
deep_active = Bool(dh["active"])
502-
end
503-
if haskey(dh, "P_dep")
504-
deep_P_dep = Float64(dh["P_dep"])
505-
end
506-
if haskey(dh, "sigma_P")
507-
deep_sigma_P = Float64(dh["sigma_P"])
508-
end
509-
if haskey(dh, "efficiency")
510-
deep_efficiency = Float64(dh["efficiency"])
511-
end
512-
if haskey(dh, "normalization")
513-
deep_norm = Symbol(lowercase(String(dh["normalization"])))
514-
end
515-
if haskey(dh, "below_domain")
516-
deep_below = Symbol(lowercase(String(dh["below_domain"])))
517-
end
518-
if haskey(dh, "power_mode")
519-
deep_power_mode = Symbol(lowercase(String(dh["power_mode"])))
520-
end
521-
if haskey(dh, "F_total")
522-
deep_F_total = Float64(dh["F_total"])
523-
end
524-
end
525489

526490
# Create atmosphere structure
527491
@debug "Instantiate atmosphere"
@@ -567,17 +531,24 @@ module AGNI
567531
atmosphere.allocate!(atmos,star_file; stellar_Teff=star_Teff) || return false
568532

569533
# Configure deep atmospheric heating
570-
if deep_active
534+
if haskey(cfg["physics"],"deep_heating")
535+
dh = cfg["physics"]["deep_heating"]
536+
if ! all(k in keys(dh) for k in ["Pmid","Pwid","flux_rel","flux_abs","norm_method","domain","power_mode"])
537+
@error "Config: deep heating enabled but parameters are not set"
538+
@error " you must provide `Pmid`, `Pwid`, `flux_rel`, `flux_abs`, `norm_method`, `domain`, and `power_mode`"
539+
return false
540+
end
541+
542+
# Pass values, converting Bar->Pa where needed
571543
atmosphere.set_deep_heating!(atmos,
572-
active=deep_active,
573-
P_dep=deep_P_dep,
574-
sigma_P=deep_sigma_P,
575-
efficiency=deep_efficiency,
576-
normalization=deep_norm,
577-
below_domain=deep_below,
578-
power_mode=deep_power_mode,
579-
F_total=deep_F_total)
544+
Float64(dh["Pmid"])*1e5, Float64(dh["Pwid"]),
545+
Float64(dh["flux_rel"]), Float64(dh["flux_abs"]),
546+
Symbol(dh["norm_method"]),
547+
Symbol(dh["domain"]),
548+
Symbol(dh["power_mode"])) || return false
580549
end
550+
incl_deep::Bool = atmos.deepheat_power_mode != :off
551+
581552

582553
# Set temperatures as appropriate
583554
if transparent
@@ -619,6 +590,7 @@ module AGNI
619590
energy.calc_fluxes!(atmos, radiative=true, latent_heat=incl_latent,
620591
convective=incl_convect, sens_heat=incl_sens,
621592
conductive=incl_conduct, advective=incl_advect,
593+
deep=incl_deep,
622594
calc_cf=Bool(cfg["plots"]["contribution"]))
623595

624596
# Transparent atmosphere solver
@@ -711,7 +683,7 @@ module AGNI
711683
plotting.plot_fluxes(atmos, joinpath(atmos.OUT_DIR,"plot_fluxes.png"),
712684
incl_mlt=incl_convect, incl_eff=(sol_type==3),
713685
incl_cdct=incl_conduct, incl_latent=incl_latent,
714-
incl_advect=incl_advect)
686+
incl_advect=incl_advect, incl_deep=incl_deep)
715687
cfg["plots"]["emission"] && \
716688
plotting.plot_emission(atmos, joinpath(atmos.OUT_DIR,"plot_emission.png"))
717689
cfg["plots"]["albedo"] && \

src/atmosphere.jl

Lines changed: 75 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ module atmosphere
3333
import ..spectrum
3434

3535
# Code versions
36-
const AGNI_VERSION::String = "1.8.6" # current agni version
36+
const AGNI_VERSION::String = "1.8.7" # current agni version
3737
const SOCVER_minimum::Float64 = 2407.2 # minimum required socrates version
3838

3939
# Hydrostatic+gravity+mass calculation (constants and limits)
@@ -62,51 +62,6 @@ module atmosphere
6262
# Enum of available radiative transfer schemes
6363
@enum RTSCHEME RT_SOCRATES=1 RT_GREYGAS=2
6464

65-
"""
66-
**Parameters for deep atmospheric heating.**
67-
68-
AGNI treats deep heating as an *additional upward energy flux* that is deposited
69-
within the column following a Gaussian profile in log-pressure space.
70-
71-
Two power modes are supported:
72-
- `:efficiency` — heating flux = `efficiency × instellation` (stellar efficiency)
73-
- `:flux` — heating flux = `F_total` (fixed radiative flux in W m⁻²)
74-
75-
Additional design choices:
76-
- Pressure-normalised deposition (dF/dP profile; legacy behaviour)
77-
- Mass-normalised deposition (dm-weighted; aligns with ∂L/∂m forms)
78-
- Handling deposition below the model bottom as a *bottom boundary flux*
79-
80-
Notes:
81-
- Pressures are in Pa throughout AGNI.
82-
- `efficiency` is always clamped to [0,1].
83-
84-
Fields:
85-
- `active::Bool` Enable/disable deep heating.
86-
- `P_dep::Float64` Deposition pressure centre [Pa].
87-
- `sigma_P::Float64` Width of Gaussian in log-pressure space [dimensionless].
88-
- `efficiency::Float64` Heating efficiency (fraction of instellation), used when `power_mode=:efficiency`.
89-
- `normalization::Symbol` `:pressure` (legacy) or `:mass` (dm-weighted).
90-
- `below_domain::Symbol` `:clamp` or `:boundary_flux`.
91-
- `power_mode::Symbol` `:efficiency` | `:flux`.
92-
- `F_total::Float64` Total deposited flux [W m-2], used when `power_mode=:flux`.
93-
"""
94-
struct DeepHeatingParams
95-
active::Bool
96-
P_dep::Float64
97-
sigma_P::Float64
98-
efficiency::Float64
99-
normalization::Symbol
100-
below_domain::Symbol
101-
power_mode::Symbol
102-
F_total::Float64
103-
end
104-
105-
# Default constructor with heating disabled
106-
DeepHeatingParams() = DeepHeatingParams(false, 1.0e5, 1.0, 0.0,
107-
:pressure, :clamp,
108-
:efficiency, 0.0)
109-
11065
# Contains data pertaining to the atmosphere (fluxes, temperature, etc.)
11166
mutable struct Atmos_t
11267

@@ -331,8 +286,14 @@ module atmosphere
331286
flux_advect::Array{Float64, 1} # Energy flux advected into each cell [W m-2], treated as entering into its bottom edge
332287

333288
# Deep atmospheric heating
334-
deep_heating::DeepHeatingParams # Parameters for deep heating
335-
flux_deep::Array{Float64,1} # Deep heating flux at cell edges [W m-2] # should add at lw flux level
289+
deepheat_norm_method::Symbol # Normalisation method for deep heating (:pressure or :mass)
290+
deepheat_Pmid::Float64 # Deposition pressur centre [Pa]
291+
deepheat_Pwid::Float64 # Width of Gaussian in log-pressure space [logPa]
292+
deepheat_domain::Symbol # Method for treating deep heating below the model domain (:clamp or :boundary_flux)
293+
deepheat_power_mode::Symbol # Method for setting total flux (:off, :rel, or :abs)
294+
deepheat_flux_rel::Float64 # Total heating as fraction of instellation, used when `power_mode=:rel`.
295+
deepheat_flux_abs::Float64 # Total heating flux [W m-2], used when `power_mode=:abs`.
296+
flux_deep::Array{Float64,1} # Deep heating flux at cell edges [W m-2] # should add at lw flux level
336297

337298
# Total energy flux
338299
flux_dif::Array{Float64,1} # Flux lost at each level [W m-2] (positive is heating up)
@@ -1174,7 +1135,13 @@ module atmosphere
11741135
end
11751136

11761137
# Deep atmospheric heating (default: disabled)
1177-
atmos.deep_heating = DeepHeatingParams()
1138+
atmos.deepheat_norm_method = :pressure
1139+
atmos.deepheat_Pmid = 1e5
1140+
atmos.deepheat_Pwid = 1.0
1141+
atmos.deepheat_domain = :clamp
1142+
atmos.deepheat_power_mode = :off
1143+
atmos.deepheat_flux_rel = 0.0
1144+
atmos.deepheat_flux_abs = 0.0
11781145

11791146
# Record that the parameters are set
11801147
atmos.is_param = true
@@ -1193,64 +1160,77 @@ module atmosphere
11931160
which deposits energy as a Gaussian distribution in log-pressure space.
11941161
11951162
Arguments:
1196-
- `atmos::Atmos_t` the atmosphere struct instance to be used.
1197-
- `active::Bool` enable/disable deep heating.
1198-
- `P_dep::Float64` deposition pressure [Pa].
1199-
- `sigma_P::Float64` width of Gaussian in log-pressure space [dimensionless].
1200-
- `efficiency::Float64` heating efficiency as fraction of instellation.
1163+
- `atmos::Atmos_t` the atmosphere struct instance to be used.
1164+
- `Pmid::Float64` deposition pressure [Pa].
1165+
- `Pwid::Float64` width of Gaussian in log-pressure space [logPa].
1166+
- `flux_rel::Float64` heating flux relative to instellation.
1167+
- `flux_abs::Float64` heating flux absolute [W m-2].
1168+
- `norm_method::Symbol` method for normalising the Gaussian (:pressure, :mass).
1169+
- `domain::Symbol` how to handle deposition pressures outside the domain (:clamp, :below_domain).
1170+
- `power_mode::Symbol` off, or relative/absolute flux (:off, :rel, :abs).
12011171
12021172
Returns:
1203-
Nothing
1173+
- `Bool` indicating success or failure of the operation.
12041174
"""
1205-
function set_deep_heating!(atmos::atmosphere.Atmos_t;
1206-
active::Bool=false,
1207-
P_dep::Float64=1.0e5,
1208-
sigma_P::Float64=1.0,
1209-
efficiency::Float64=0.0,
1210-
normalization::Symbol=:pressure,
1211-
below_domain::Symbol=:clamp,
1212-
power_mode::Symbol=:efficiency,
1213-
F_total::Float64=0.0)
1214-
1215-
# Validate/normalise parameters
1216-
sigma_P = max(sigma_P, 0.01) # Prevent division issues
1217-
efficiency = clamp(efficiency, 0.0, 1.0)
1218-
1219-
# Normalise symbols
1220-
if !(normalization in (:pressure, :mass))
1221-
error("Invalid deep heating normalization: $(normalization)")
1222-
end
1223-
if !(below_domain in (:clamp, :boundary_flux))
1224-
error("Invalid deep heating below_domain: $(below_domain)")
1175+
function set_deep_heating!(atmos::atmosphere.Atmos_t,
1176+
Pmid::Float64,
1177+
Pwid::Float64,
1178+
flux_rel::Float64,
1179+
flux_abs::Float64,
1180+
norm_method::Symbol,
1181+
domain::Symbol,
1182+
power_mode::Symbol
1183+
)::Bool
1184+
1185+
# Fail safe mode
1186+
atmos.deepheat_power_mode = :off
1187+
if power_mode == :off
1188+
atmos.deepheat_power_mode = :off
1189+
return true
1190+
elseif !(power_mode in (:rel, :abs))
1191+
@error "Invalid deep heating power mode: $(power_mode)"
1192+
return false
12251193
end
1226-
if !(power_mode in (:efficiency, :flux))
1227-
error("Invalid deep heating power_mode: $(power_mode)")
1194+
1195+
# Normalisation coordinate
1196+
if !(norm_method in (:pressure, :mass))
1197+
@error "Invalid deep heating normalisation: $(norm_method)"
1198+
return false
1199+
else
1200+
atmos.deepheat_norm_method = norm_method
12281201
end
12291202

1203+
# Set centre and width of Gaussian
1204+
atmos.deepheat_Pmid = max(Pmid, 0.0) # Pascals
1205+
atmos.deepheat_Pwid = max(Pwid, 0.01) # relative
1206+
12301207
# Deposition pressure handling
1231-
if below_domain == :clamp
1232-
P_dep = clamp(P_dep, atmos.p_toa, atmos.p_boa)
1208+
if domain == :clamp
1209+
atmos.deepheat_Pmid = clamp(atmos.deepheat_Pmid, atmos.p_toa, atmos.p_boa)
1210+
elseif domain == :below_domain
1211+
# Allow Poutside domain
1212+
atmos.deepheat_Pmid = max(atmos.deepheat_Pmid, atmos.p_toa)
12331213
else
1234-
# Allow P_dep outside domain (used as a signal for boundary-flux mode)
1235-
P_dep = max(P_dep, atmos.p_toa)
1214+
@error "Invalid deep heating domain treatment: $(domain)"
1215+
return false
12361216
end
12371217

1238-
# Create and store the parameters
1239-
atmos.deep_heating = DeepHeatingParams(active, P_dep, sigma_P, efficiency,
1240-
normalization, below_domain,
1241-
power_mode, F_total)
1242-
1243-
if active
1244-
@info @sprintf("Deep heating enabled: norm=%s below=%s mode=%s",
1245-
String(normalization), String(below_domain), String(power_mode))
1246-
if power_mode == :efficiency
1247-
@info @sprintf(" P_dep=%.2e Pa, σ_P=%.2f, ε=%.4f", P_dep, sigma_P, efficiency)
1248-
else
1249-
@info @sprintf(" P_dep=%.2e Pa, σ_P=%.2f, F_total=%.4e W/m²", P_dep, sigma_P, F_total)
1250-
end
1218+
# Set power mode
1219+
atmos.deepheat_power_mode = power_mode
1220+
atmos.deepheat_flux_rel = flux_rel
1221+
atmos.deepheat_flux_abs = flux_abs
1222+
@info "Deep heating configured with power_mode=$(atmos.deepheat_power_mode)"
1223+
if power_mode == :rel
1224+
@info @sprintf(" Pmid=%.2e Pa, Pwid=%.2f, ε=%.4f",
1225+
atmos.deepheat_Pmid, atmos.deepheat_Pwid, flux_rel)
1226+
elseif power_mode == :abs
1227+
@info @sprintf(" Pmid=%.2e Pa, Pwid=%.2f, F_total=%.4e W/m²",
1228+
atmos.deepheat_Pmid, atmos.deepheat_Pwid, flux_abs)
12511229
end
1230+
@info " norm_method=$(atmos.deepheat_norm_method), domain=$(atmos.deepheat_domain)"
12521231

1253-
return nothing
1232+
1233+
return true
12541234
end
12551235

12561236

0 commit comments

Comments
 (0)