Skip to content

Commit 9ee3b6f

Browse files
committed
Don't perturb composition during jacobian evaluation
1 parent 3249da0 commit 9ee3b6f

2 files changed

Lines changed: 32 additions & 26 deletions

File tree

src/chemistry.jl

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ This module handles chemistry, condensation, and evaporation.
1111
1212
Note the important distinctions between the variables which store atmospheric composition.
1313
* `gas_ovmr` stores VMRs inputted by the user, which are usually constant in height.
14-
* `gas_cvmr` stores VMRs after chemistry is calculated but before rainout/evaporation.
1514
* `gas_vmr` stores the runtime gas volume mixing ratios, after all calculations are performed.
1615
1716
"""
@@ -179,9 +178,10 @@ module chemistry
179178
return any_changed
180179
end
181180

182-
# Recalculate all surface VMRs from partial pressures
181+
# Recalculate VMRs from partial pressures (dalton's law)
182+
# Sets to well-mixed composition
183183
for gas in atmos.gas_names
184-
atmos.gas_vmr[gas][end] = p_gas[gas]/atmos.p_boa
184+
fill!(atmos.gas_vmr[gas], p_gas[gas]/atmos.p_boa)
185185
end
186186

187187
# Generate new pressure grid with updated p_boa
@@ -209,8 +209,7 @@ module chemistry
209209
Disabling evaporation will lead to unclosed energy budget when calculation of latent
210210
heat fluxes is performed.
211211
212-
This function can be called *after* the fastchem calculation. It takes `gas_cvmr` as
213-
input, does not modify it, and writes post-rainout compositions to `gas_vmr`.
212+
This function can be called *after* the fastchem calculation.
214213
215214
Arguments:
216215
- `atmos::Atmos_t` the atmosphere struct instance to be used.
@@ -226,9 +225,8 @@ module chemistry
226225
# Reset phase change flags
227226
# Reset condensation yield values
228227
for g in atmos.gas_names
229-
@. atmos.gas_vmr[g] = atmos.gas_cvmr[g]
230-
fill!(atmos.gas_sat[g], false)
231-
fill!(atmos.cond_yield[g], 0.0) # kg/m2 of condensate produced at levels
228+
fill!(atmos.gas_sat[g], false)
229+
fill!(atmos.cond_yield[g], 0.0) # kg/m2 of condensate produced at levels
232230
end
233231

234232
# Set initial maximum value as surface composition (for cold trapping)
@@ -373,9 +371,6 @@ module chemistry
373371
# recalculate layer properties after re-evaporating this species
374372
atmosphere.calc_layer_props!(atmos)
375373

376-
# sum total condensate as surface + aloft
377-
atmos.ocean_tot[c] += atmos.cond_accum[c]
378-
379374
end # end loop over condensates
380375

381376
# Set water clouds at levels where condensation occurs
@@ -512,7 +507,7 @@ module chemistry
512507

513508
# Get gas abundance from original VMR value
514509
# scale number of atoms by the abundance of the gas
515-
N_g *= atmos.gas_ovmr[gas][end] * atmos.p[end] / (phys.k_B * atmos.tmp[end])
510+
N_g *= atmos.gas_vmr[gas][end] * atmos.p[end] / (phys.k_B * atmos.tmp[end])
516511

517512
# Add atoms from this gas to total atoms in the mixture
518513
N_t += N_g
@@ -597,7 +592,6 @@ module chemistry
597592
# Clear VMRs
598593
for g in atmos.gas_names
599594
fill!(atmos.gas_vmr[g], 0.0)
600-
fill!(atmos.gas_cvmr[g], 0.0)
601595
end
602596

603597
# Parse gas chemistry
@@ -648,7 +642,7 @@ module chemistry
648642
# matched?
649643
if match
650644
N_g = data[i,:] # number densities for this gas
651-
@. atmos.gas_cvmr[g_in] += N_g / N_t # VMR for this gas
645+
@. atmos.gas_vmr[g_in] += N_g / N_t # VMR for this gas
652646
end
653647
end
654648

@@ -668,13 +662,13 @@ module chemistry
668662
# @warn @sprintf("Temperature below FC floor, at p < %.1e Pa", atmos.p[i_trunc])
669663
i_trunc = min(i_trunc, atmos.nlev_c-1)
670664
for g in atmos.gas_names
671-
atmos.gas_cvmr[g][1:i_trunc] .= atmos.gas_cvmr[g][i_trunc+1]
665+
atmos.gas_vmr[g][1:i_trunc] .= atmos.gas_vmr[g][i_trunc+1]
672666
end
673667
end
674668

675-
# Also update result in gas_vmr dictionary
669+
# Also record this result in gas_cvmr dictionary
676670
for g in atmos.gas_names
677-
@. atmos.gas_vmr[g] = atmos.gas_cvmr[g]
671+
@. atmos.gas_cvmr[g] = atmos.gas_vmr[g]
678672
end
679673

680674
# recalculate layer properties
@@ -704,7 +698,7 @@ module chemistry
704698
- `state::Int` fastchem state (0: success, 1: critical_fail, 2: elem_fail, 3: conv_fail, 4: both_fail)
705699
"""
706700
function calc_composition!(atmos::atmosphere.Atmos_t,
707-
do_surf::Bool, do_chem::Bool, do_aloft::Bool)::Int
701+
do_surf::Bool, do_chem::Bool, do_aloft::Bool)::Int
708702

709703
state::Int = 0
710704

@@ -724,6 +718,11 @@ module chemistry
724718
# aloft saturation
725719
if do_aloft
726720
_sat_aloft!(atmos)
721+
722+
# sum total condensate as surface + aloft
723+
for c in atmos.condensates
724+
atmos.ocean_tot[c] += atmos.cond_accum[c]
725+
end
727726
end
728727

729728
return state

src/solver.jl

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ module solver
170170
dx_min::Float64=1e-7, dx_max::Float64=400.0,
171171
tmp_pad::Float64 = 5.0,
172172
max_steps::Int=400, max_runtime::Float64=900.0,
173-
fd_rel::Float64=3.0e-5, fd_abs::Float64=1e-5,
173+
fd_rel::Float64=1e-4, fd_abs::Float64=1e-5,
174174
fdc::Bool=true, fdo::Int=2,
175175
method::Int=1,
176176
easy_start::Bool=false, grey_start::Bool=false,
@@ -329,8 +329,15 @@ module solver
329329
# Set new temperatures
330330
_set_tmps!(x)
331331

332-
# Do condensation and chemistry
333-
chemistry.calc_composition!(atmos, rainout, chem, rainout)
332+
# Do saturation aloft here, only
333+
# chemistry.calc_composition!(atmos, rainout, chem, rainout)
334+
if rainout
335+
# reset back to post-chemistry value
336+
for g in atmos.gas_names
337+
@. atmos.gas_vmr[g] = atmos.gas_cvmr
338+
end
339+
_sat_aloft!(atmos)
340+
end
334341

335342
# Calculate fluxes
336343
step_ok &= energy.calc_fluxes!(atmos, radiative=true,
@@ -341,7 +348,7 @@ module solver
341348
# Calculate residuals subject to the solution type
342349
if (sol_type == 1)
343350
# Zero loss with constant tmp_surf
344-
resid[1:end] .= atmos.flux_dif[1:end]
351+
@. resid = atmos.flux_dif
345352

346353
elseif (sol_type == 2)
347354
# Zero loss
@@ -351,14 +358,14 @@ module solver
351358

352359
elseif (sol_type == 3)
353360
# Zero loss
354-
resid[2:end] .= atmos.flux_dif[1:end]
355-
resid[1] = atmos.flux_tot[1] - atmos.flux_int
361+
resid[1:end-1] .= atmos.flux_dif[1:end]
362+
resid[end] = atmos.flux_tot[end] - atmos.flux_int
356363

357364
elseif (sol_type == 4)
358365
# Zero loss
359-
resid[2:end] .= atmos.flux_dif[1:end]
366+
resid[1:end-1] .= atmos.flux_dif[1:end]
360367
# OLR is equal to target_olr
361-
resid[1] = atmos.target_olr - atmos.flux_u_lw[1]
368+
resid[end] = atmos.target_olr - atmos.flux_u_lw[1]
362369

363370
end
364371

0 commit comments

Comments
 (0)