Temperature ranges from remote sensing are most available at the 500-mbar level. Variation with latitude:
Use T500 = 128-142 K to cover the widest range. This is 15 values at 1-K resolution. Compare with Voyager occultation temperature values from Gupta++2022:
import numpy as np
# voyager 1 ingress values:
#
print("old, new: ", np.interp(500., [494.47,503.96], [134.16,134.99]), np.interp(500., [497.35,511.78], [137.27,138.24]))
# voyager 1 egress values:
#
print("old, new: ", np.interp(500., [334.40,598.41], [122.20,140.08]), np.interp(500., [352.75,631.25], [126.60,145.13]))
# voyager 2 egress not available at P > 60 mbar,
# voyager 1 ingress not available
#
old, new: 134.6436564805058 137.44813582813583 old, new: 133.41521154501726 136.39728007181327
Voyager 1 T500 values of 137.4 K, 136.4 K fall within the range of infrared retrieval values, so they don't affect the temparature search range here.
Galileo Probe T500 = 132.79 K (Seiff++1998, Table 7), so it doesn't affect the temperature search range here.
Try adiabatic and 90% adiabatic cases (90% follows 0.2 K/km stability in Magalhaes++2002 relative to DALR of 1.94 K/km).
Follow same compositional assumptions as in Simon++2022:
Code var. | Meaning | Jupiter | Saturn | Uranus | Neptune |
---|---|---|---|---|---|
ENRHE | n_He / n_H2 | 0.157 | 0.135 | 0.131 | 0.177 |
ENRCH4 | CH4 mixrat wrt Asplund | 4.02 | 8.98 | 30. | 80. |
ENRH2O | H2O mixrat wrt Asplund | 2.7 | 5.0 | 30. | 80. |
ENRNH3 | NH3 mixrat wrt Asplund | 2.7 | 5.0 | 3. | 8. |
ENRH2S | H2S mixrat wrt Asplund | 2.7 | 5.0 | 30. | 80. |
ENRAR | Ne mixrat wrt Asplund | 0.13 | 0.13 | 2.5 | 2.5 |
Use same code variant:
fresh_cpeq_near.exe - f_p follows equilibrium value (CHECK!), plus ENRAR applies to both Ne and Ar
Final plot will have cloud base pressure on one axis and 0.5-bar temperature on the other axis, with contours of H2O abundance for each point in the space. But ENRH2O is an input parameter, so we guess at the range needed to span the desired pressure range.
Pressure range (cloud base) 4 to 10 bar at 0.5-bar resolution, so 13 points.
Max ENRH2O is for 10-bar cloud at T500 = 142 K, adiabatic. Min ENRH2O is for 4-bar cloud at T500 = 128 K, 90% subadiabatic. Find the ENRH2O range, pad, and divide into 20 values. Full matrix will be 15$\times$20 = 300 cases.
Directories:
Parse output files to generate irregular map of T_P_H2Oabundance, plot it here as a contour plot. Another option would be to create a revised program for this specific calculation, but it would still have to calculate the whole column to match T500 anyways. Might as well do it the brute-force way because the output files might be useful for other things later on.
Note: Using geff = 22.713 m/s2. In the future, re-do for higher latitudes.
~/G/300/c/fresh_cpeq_near.exe
File "<ipython-input-2-d01a86b5189f>", line 1 ~/G/300/c/fresh_cpeq_near.exe ^ SyntaxError: invalid syntax
Max ENRH2O: 20x solar, hot profile, gives cloud base at 10.11 bar.
Min ENRH2O: 0.03x solar, cold profile, gives cloud base at 4.0096 bar.
Probably need to generate log spacing to evenly sample pressure range:
import numpy as np
# find the ln values that match min/max ENRH2O
#
print("log ENRH2O_min, ENRH2O_max: ", np.log(0.025), np.log(22))
# find a spacing that gives about 20 values
#
step = 0.33
print("log spacing, number of steps: ", step, (np.arange(-3.7,3.4,step)).size)
# calculate the resulting ENRH2O values:
#
for ENRH2O in np.exp(np.arange(-3.7,3.4,step)):
print('{:8.4f} {:8.4f}'.format(ENRH2O, np.log(ENRH2O)))
log ENRH2O_min, ENRH2O_max: -3.6888794541139363 3.091042453358316 log spacing, number of steps: 0.33 22 0.0247 -3.7000 0.0344 -3.3700 0.0478 -3.0400 0.0665 -2.7100 0.0926 -2.3800 0.1287 -2.0500 0.1791 -1.7200 0.2491 -1.3900 0.3465 -1.0600 0.4819 -0.7300 0.6703 -0.4000 0.9324 -0.0700 1.2969 0.2600 1.8040 0.5900 2.5093 0.9200 3.4903 1.2500 4.8550 1.5800 6.7531 1.9100 9.3933 2.2400 13.0658 2.5700 18.1741 2.9000 25.2797 3.2300
# alternately, find the sqrt() values that match min/max ENRH2O
#
print("sqrt ENRH2O_min, ENRH2O_max: ", 0.025**(0.5), 22**(0.5))
# find a spacing that gives about 20 values
#
step = 0.22
print("sqrt spacing, number of steps: ", step, (np.arange(0.158,4.69,step)).size)
# calculate the resulting ENRH2O values:
#
for ENRH2O in (np.arange(0.158,4.69,step))**2:
print('{:8.4f} {:8.4f}'.format(ENRH2O, ENRH2O**0.5))
sqrt ENRH2O_min, ENRH2O_max: 0.15811388300841897 4.69041575982343 sqrt spacing, number of steps: 0.22 21 0.0250 0.1580 0.1429 0.3780 0.3576 0.5980 0.6691 0.8180 1.0774 1.0380 1.5826 1.2580 2.1845 1.4780 2.8832 1.6980 3.6787 1.9180 4.5710 2.1380 5.5602 2.3580 6.6461 2.5780 7.8288 2.7980 9.1083 3.0180 10.4846 3.2380 11.9578 3.4580 13.5277 3.6780 15.1944 3.8980 16.9579 4.1180 18.8182 4.3380 20.7754 4.5580
Figure out efficient bounds/trends for model base pressure/temperature. Get new values Emin_Pmax and Emax_Pmin from cloud model. Use to define Pmax and set initial temperatures for all the extreme cases.
Max P: (Max ENRH2O, 20x solar, hot profile, gives cloud base at 10.11 bar.) COLD PROFILE gives cloud base at 25.35 bar.
Min P: (Min ENRH2O, 0.03x solar, cold profile, gives cloud base at 4.0096 bar.) HOT PROFILE gives cloud base at 2.1955 bar.
To span a rectangular grid of P in 4-10 bar and T500 in 128-142 K (considering both adiabatic and 90% adiabatic), we need ENRH2O in 0.03-20.0. This provides a trapezoidal output space in T500 and P, pointing out to P in 2.2-23.4 bar. For accurate results, ECCM calculation has to start below 23.4 bar, so just choose 30 bar as a nice round number (just in case we have to expand a bit in the future). Look at T30bar over the existing boundary cases to guide auto-generation of good inputp.X files below:
inputp | ENRH2O | T500 (K) | Subadiabaticity | P | T30bar (K) |
---|---|---|---|---|---|
Emin_cold_G100 | 0.03 | 128 | 1.0 | 3.18 | 449.9 |
Emin_Pmin | 0.03 | 142 | 1.0 | 2.20 | 494.6 |
Emax_cold_G100 | 20.0 | 128 | 1.0 | 15.15 | 416.4 |
Emax | 20.0 | 142 | 1.0 | 10.11 | 456.9 |
Emin | 0.03 | 128 | 0.9 | 4.01 | 398.5 |
Emin_hot_G090 | 0.03 | 142 | 0.9 | 2.65 | 438.3 |
Emax_Pmax | 20.0 | 128 | 0.9 | 25.35 | 368.5 |
Emax_hot_G090 | 20.0 | 142 | 0.9 | 15.80 | 404.5 |
import numpy as np
from numpy.polynomial import Polynomial as Poly
#numpy.polynomial.set_default_printstyle('unicode')
# https://numpy.org/doc/stable/reference/generated/numpy.polynomial.polynomial.Polynomial.fit.html#numpy.polynomial.polynomial.Polynomial.fit
ba = Poly.fit([128.,142.], [449.9,494.6], deg=1)
print(ba.convert().coef) # coefficients for the unscaled and unshifted basis polynomials
print(41.21428571 + 3.19285714*142.) # works right
# estimate very crude linear relations based on the boundary values already calculated:
#
print("Emin, G100: dT_30bar / dT_500mbar = ", ba.convert().coef[1])
print("Emax, G100: ", (Poly.fit([128.,142.], [416.4,456.9], deg=1)).convert().coef[1])
print("Emin, G090: ", (Poly.fit([128.,142.], [398.5,438.3], deg=1)).convert().coef[1])
print("Emax, G090: ", (Poly.fit([128.,142.], [368.5,404.5], deg=1)).convert().coef[1])
print(" ")
print("cold, G100: dT_30bar / dENRH2O = ", (Poly.fit([0.03,20], [449.9,416.4], deg=1)).convert().coef[1])
print("cold, G090: ", (Poly.fit([0.03,20], [398.5,368.5], deg=1)).convert().coef[1])
print("hot, G100: ", (Poly.fit([0.03,20], [494.6,456.9], deg=1)).convert().coef[1])
print("hot, G090: ", (Poly.fit([0.03,20], [438.3,404.5], deg=1)).convert().coef[1])
print(" ")
# use the crude fits above to estimate T_30bar for any parameter set.
# starting point is T30_0 === T_30bar(Emin,cold) for that lapse rate:t lapse rate:
T30_0 = 449.9 # for 100% adiabatic lapse rate
T30_0 = 398.5 # for 90% adiabatic lapse rate
T500_0 = 128.
Emin = 0.03
def T30(T500,ENRH2O):
T30 = T30_0 + 2.3 * (T500 - T500_0) - 1.9 * (ENRH2O - Emin)
return T30
T500 = 148.
ENRH2O = 20.
ENRH2O = 0.03
#T500 = 128.
print(T30(T500,ENRH2O))
[41.21428571 3.19285714] 494.59999959000004 Emin, G100: dT_30bar / dT_500mbar = 3.192857142857144 Emax, G100: 2.8928571428571406 Emin, G090: 2.8428571428571496 Emax, G090: 2.5714285714285783 cold, G100: dT_30bar / dENRH2O = -1.6775162744116148 cold, G090: -1.502253380070103 hot, G100: -1.8878317476214346 hot, G090: -1.692538808212315 444.5
(second time I am typing this... remember to click the disk icon to "save and checkpoint")
inputp.X extension (run ID) is hardcoded to a max of 100 characters, so we can use readable extensions to span the parameter range:
fgets(suffix,100,stdin);
Use extensions of the form T128_E20p00_G100, T142_E00p03_G090 etc.
The c version of the code (not FORTRAN) is also forgiving on input format, just requires the right number of values, with any kind of field size or exponents. inputp.Emin and inputp.Emax inherited the old format style, Emin_Pmax and Emax_Pmin use a more human-readable version. Here are the input commands from fresh.c for reading inputp.X:
FILE *inputp = fopen(filename, "r");
fscanf(inputp,"%s%*[^\n]",&planet);
fscanf(inputp,"%d %lf %lf %lf %lf %lf %lf %lf %lf", &case_no, &z0, &t[0], &p[0], &g, &dz, &ttrop, &lapse, &super);
fscanf(inputp,"%lf %lf %lf %lf %lf %lf", &coshe, &cosch4, &cosh2o, &cosnh3, &cosh2s, &cosar);
fscanf(inputp,"%lf %lf %lf %lf %lf %lf", &enrhe, &enrch4, &enrh2o, &enrnh3, &enrh2s, &enrar);
fscanf(inputp,"%lf %lf %lf %lf", &pbottom, &ptop, &fpbottom, &fptop);
fscanf(inputp,"%lf %lf %lf %lf", &p_match, &t_match, &t_tolerance, &l_scale);
fclose(inputp);
Draft code to write an inputp.X file here, then save it as a separate "inputp_generator.py" and loop to generate 600+ cases. Upload to KWSS, run matrix/script.exe to calculate all the ECCM runs. [Some edits to fresh_cpeq_near.c were made: ability to read "suffix" from command line argument, program checks for existence of inputsol rather than just trying to read from a null file pointer and crashing with a segmentation fault.]
import numpy as np
T30_0 = 449.9 # for 100% adiabatic lapse rate
T30_0 = 398.5 # for 90% adiabatic lapse rate
T500_0 = 128.
Emin = 0.03
# use temperature factor of 2.3 and composition factor of -1.9
# (see T_P_H2Oabundance.ipynb) to estimate a T_30bar for each input file
def T30(T500,ENRH2O):
T30 = T30_0 + 2.3 * (T500 - T500_0) - 1.9 * (ENRH2O - Emin)
return T30
Gamma_factor = 0.9
T500 = 131.
ENRH2O = 9.1083
#for ENRH2O in (np.arange(0.158,4.69,step))**2:
T_code = 'T{:03d}'.format(int(T500))
T_label = 'T_500 = {:d} K,'.format(int(T500))
E_code = 'E{:02d}p{:02d}'.format(int(ENRH2O), int(round(100 * (ENRH2O - np.fix(ENRH2O)))))
E_label = 'ENRH2O = {:6.3f},'.format(ENRH2O)
G_code = 'G{:03d}'.format(int(100 * Gamma_factor))
G_label = 'Lapse rate {:d}% adiabatic.'.format(int(100 * Gamma_factor))
print(" ")
print(" ")
print("inputp.{:s}_{:s}_{:s}".format(T_code,E_code,G_code))
print(" ----- ")
print(" Jupiter auto-generated (see T_P_H2Oabundance.ipynb),",T_label,E_label,G_label)
print(" ")
print(" 1 0.0 {:5.1f} 30.0 2271.3 2.5e+04 105.0 100.0 {:3.1f}".format(T30(T500,ENRH2O), Gamma_factor))
print(" ")
print(" 0.157 5.90e-04 1.07e-03 1.48e-04 2.89e-05 1.92e-04")
print(" 0.157 4.02 {:5.2f} 2.7 2.7 0.13 ".format(ENRH2O))
print(" ")
print(" 0.5 0.1 0.25 0.33")
print(" 500.0 {:5.1f} 0.05 200.0".format(T500))
print(" ")
print(" ")
print(" ")
print(" ")
print("estimated number of hours to calculate full batch on KWSS: ",4.*600./60.)
inputp.T131_E09p11_G090 ----- Jupiter auto-generated (see T_P_H2Oabundance.ipynb), T_500 = 131 K, ENRH2O = 9.108, Lapse rate 90% adiabatic. 1 0.0 388.2 30.0 2271.3 2.5e+04 105.0 100.0 0.9 0.157 5.90e-04 1.07e-03 1.48e-04 2.89e-05 1.92e-04 0.157 4.02 9.11 2.7 2.7 0.13 0.5 0.1 0.25 0.33 500.0 131.0 0.05 200.0 estimated number of hours to calculate full batch on KWSS: 40.0
Edit all below to correspond to the matrix_v2/ folder, not the matrix/ folder.
The differences are the range of abundances, and the new code to treat neon as a separate species.
Generate two T500 $\times$ ENRH2O arrays (for 90% and 100% adiabatic). Will figure out how to contour-plot them later.
Read cloud base location by searching "mixrat" files for the first nonzero value of delta-H2O, get the corresponding pressure level.
# try one file first before reading in the whole lot
#
suffix = "T128_E00p01_G090"
filename = "matrix_v2/mixrat.{:s}".format(suffix)
tph2o = np.loadtxt(filename, skiprows=7, usecols=(1,2,4))
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import os
# copy some plot commands from freshclouds_simon22.ipynb
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.sans-serif'] = ['Helvetica', 'Roboto', 'Verdana', 'Arial']
plt.rcParams['pdf.fonttype'] = 42
fig,axs=plt.subplots(1,1,figsize=(10, 4.5))
axs.plot(tph2o[:,1], tph2o[:,2])
axs.set_xlim(0.1, 30.)
axs.set_ylim(-1e-5,1e-5)
#axs.set_yscale('log')
axs.set_xlabel('P (bar)')
axs.set_ylabel('delta H2O mixrat')
# exploit the start-from-bottom file order to find the LCL
#
q = ((np.nonzero(tph2o[:,2]))[0])[0]
axs.plot(tph2o[q,1], tph2o[q,2], marker="o", markeredgecolor="red")
print(q, tph2o[q,2], tph2o[q,1])
ENRH2O_seq = (np.arange(0.158, 4.69, 0.22))**2
print(len(ENRH2O_seq), ENRH2O_seq[len(ENRH2O_seq) -1], max(ENRH2O_seq))
T500_seq = np.arange(128.,143.)
print(np.argmin(abs(T500_seq - 134.)), T500_seq[6])
LCL = -1
filename='matrix_v2/mixrat.T132_E22p28_G100'
if os.path.exists(filename):
tph2o = np.loadtxt(filename, skiprows=7, usecols=(1,2,4))
# see cell above, get the condensation level
#
LCL = tph2o[((np.nonzero(tph2o[:,2]))[0])[0], 1]
print("LCL: ",LCL)
ENRH2O_seq = (np.arange(0.1, 4.75, 0.22))**2
print(ENRH2O_seq)
print(ENRH2O_seq**0.5)
414 -4.06e-07 3.3849 21 20.775364000000007 20.775364000000007 6 134.0 LCL: 14.296 [1.00000e-02 1.02400e-01 2.91600e-01 5.77600e-01 9.60400e-01 1.44000e+00 2.01640e+00 2.68960e+00 3.45960e+00 4.32640e+00 5.29000e+00 6.35040e+00 7.50760e+00 8.76160e+00 1.01124e+01 1.15600e+01 1.31044e+01 1.47456e+01 1.64836e+01 1.83184e+01 2.02500e+01 2.22784e+01] [0.1 0.32 0.54 0.76 0.98 1.2 1.42 1.64 1.86 2.08 2.3 2.52 2.74 2.96 3.18 3.4 3.62 3.84 4.06 4.28 4.5 4.72]
import os
# setup the big arrays for storing results
#
ENRH2O_seq = (np.arange(0.158, 4.69, 0.22))**2 # no, this is matrix/... see inputp_generator.py
ENRH2O_seq = (np.arange(0.1, 4.75, 0.22))**2 # yes... see inputp_generator_v2.py
T500_seq = np.arange(128.,143.)
Gamma_seq = np.arange(0.9,1.001,0.1)
n_ENRH2O = len(ENRH2O_seq)
n_T500 = len(T500_seq)
n_Gamma = len(Gamma_seq)
P_H2O = np.zeros((n_T500, n_ENRH2O, n_Gamma))
P_NH3 = np.zeros((n_T500, n_ENRH2O, n_Gamma))
P_NH4SH = np.zeros((n_T500, n_ENRH2O, n_Gamma))
T_5 = np.zeros((n_T500, n_ENRH2O, n_Gamma))
# loop stuff just like in inputp_generator.py
#
for T500 in T500_seq:
for ENRH2O in ENRH2O_seq:
for Gamma_factor in Gamma_seq:
# generate run-ID code / filename suffix from parameter values
#
T_code = 'T{:03d}'.format(int(T500))
E_code = 'E{:02d}p{:02d}'.format(int(ENRH2O), int(round(100 * (ENRH2O - np.fix(ENRH2O)))))
G_code = 'G{:03d}'.format(int(100 * Gamma_factor))
suffix = "{:s}_{:s}_{:s}".format(T_code,E_code,G_code)
filename = "matrix_v2/mixrat.{:s}".format(suffix)
cratname = "matrix_v2/cldrate.{:s}".format(suffix)
# load pressure, temperature, delta-H2O
#
if os.path.exists(filename):
tph2o = np.loadtxt(filename, skiprows=7, usecols=(1,2,4))
tpupper = np.loadtxt(cratname, skiprows=7, usecols=(1,2,3,4,5,6))
# get the condensation levels
#
LCL = tph2o[((np.nonzero(tph2o[:,2]))[0])[0], 1]
LCL_nh3 = tph2o[((np.nonzero(tpupper[:,5]))[0])[0], 1]
LCL_nh4sh = tph2o[((np.nonzero(tpupper[:,4]))[0])[0], 1]
# interpolate to find the temperature at 5 bars
#
T5 = np.interp(5., tph2o[:,1], tph2o[:,0])
# store in the big arrays.
# get indices in a way safe for floating point errors
#
i_T500 = np.argmin(abs(T500_seq - T500))
i_ENRH2O = np.argmin(abs(ENRH2O_seq - ENRH2O))
i_Gamma = np.argmin(abs(Gamma_seq - Gamma_factor))
P_H2O[i_T500,i_ENRH2O, i_Gamma] = LCL
P_NH3[i_T500,i_ENRH2O, i_Gamma] = LCL_nh3
P_NH4SH[i_T500,i_ENRH2O, i_Gamma] = LCL_nh4sh
T_5[i_T500,i_ENRH2O, i_Gamma] = T5
print(np.sum(P_H2O))
6218.282799999999
See: https://matplotlib.org/3.5.0/gallery/images_contours_and_fields/irregulardatagrid.html
grid_ENRH2O, grid_T500 = np.meshgrid(ENRH2O_seq, T500_seq)
print(grid_ENRH2O.shape, grid_T500.shape, (P_H2O[:,:,1].squeeze()).shape)
print((np.ravel(P_H2O[:,:,1])).shape)
print(((P_H2O[:,:,1]).flatten()).shape)
(15, 22) (15, 22) (15, 22) (330,) (330,)
from matplotlib import colors
contour_levels_ENRH2O = [0.05, 0.1, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 7, 10, 20]
contour_levels_ENRH2O = [0.5, 1, 2, 3, 5, 7, 10, 50]
contour_levels_ENRH2O = [0.05, 0.5, 1, 2, 3, 5, 7, 10, 50]
contour_levels_ENRH2O = [0.1, 0.25, 0.5, 1, 2, 3, 5, 7, 10]
fig, (axG090, axG100) = plt.subplots(ncols=2, figsize=(12, 4.5))
CS090 = axG090.tricontour(P_H2O[:,:,0].flatten(), grid_T500.flatten(), grid_ENRH2O.flatten(),
contour_levels_ENRH2O, colors='w')
axG090.clabel(CS090, inline=True, fontsize=10, colors='w', fmt="%5.2f")
axG090.tricontourf(P_H2O[:,:,0].flatten(), grid_T500.flatten(), grid_ENRH2O.flatten(),
contour_levels_ENRH2O, norm=colors.PowerNorm(0.3), extend='both')
axG090.set_ylabel('T at 500 mbar (K)')
axG090.set_xlabel('Water LCL (bar)')
axG090.set_xlim(3.,10.)
axG090.set_ylim(128.,142.)
axG090.set_title('90% adiabatic (stable/cold at depth)')
#cbarG090 = fig.colorbar(CS090, ax=axG090)
#cbarG090.ax.set_ylabel('Supersolar H2O enrichment factor')
CS100 = axG100.tricontour(P_H2O[:,:,1].flatten(), grid_T500.flatten(), grid_ENRH2O.flatten(),
contour_levels_ENRH2O, colors='w')
axG100.clabel(CS100, inline=True, fontsize=10, colors='w', fmt="%5.2f")
axG100.tricontourf(P_H2O[:,:,1].flatten(), grid_T500.flatten(), grid_ENRH2O.flatten(),
contour_levels_ENRH2O, norm=colors.PowerNorm(0.3), extend='both')
axG100.set_ylabel('T at 500 mbar (K)')
axG100.set_xlabel('Water LCL (bar)')
axG100.set_xlim(3.,10.)
axG100.set_ylim(128.,142.)
axG100.set_title('Adiabatic (neutral/warm at depth)')
#cbarG100 = fig.colorbar(CS100, ax=axG100)
#cbarG100.ax.set_ylabel('Supersolar H2O enrichment factor')
plt.savefig('LCL_matrix_v2_orig.pdf')
COSAR: 5.51E-06 COSNE: 1.87E-04 ENRAR: 3.3 ENRNE: 0.12 print(" 0.157 5.90e-04 1.07e-03 1.48e-04 2.89e-05 1.92e-04") print(" 0.157 4.02 {:5.2f} 2.7 2.7 0.13 ".format(ENRH2O)) print(" 0.157 5.90e-04 1.07e-03 1.48e-04 2.89e-05 5.51e-06 1.87e-04") print(" 0.157 4.02 {:5.2f} 2.7 2.7 2.7 0.13 ".format(ENRH2O))
Note: Ar/CH4 treated inconsistently in fresh.c, with a potential bug
. They are treated as condensable in the body of the main loop, but then treated as dry components at the end of the loop (when dry air is refilled so that the sum of all mole fractions is 1). Need to fix this for next time ice giants calculations are done.
Note: van der Waals corrections are included in fresh.c etc., so some of the stuff in freshclouds_simon22.ipynb may be incorrect (double-application of vdW). I think this doesn't affect any conclusions because the additional (double) vdW correction was not applied when making the figure?
~/papers/G526-bjoraker22-review/ECCM/matrix: output from fresh_cpeq_near.c with argon+neon treated as a single gas. Made with inputp_generator.py
.
~/papers/G526-bjoraker22-review/ECCM/matrix_v2: output from fresh_cpeq_ne.c with argon+neon treated separately, results should be the same anyways. But revise to add a ENRH2O = 0.01 set to remove white corner from the cold plot near 3 bar. Made with inputp_generator_v2.py
.
ENRH2O_seq = (np.arange(0.158, 4.69, 0.22))**2
ENRH2O_seq = (np.arange(0.1, 4.75, 0.22))**2
print(len(ENRH2O_seq))
ENRH2O_seq
22
array([1.00000e-02, 1.02400e-01, 2.91600e-01, 5.77600e-01, 9.60400e-01, 1.44000e+00, 2.01640e+00, 2.68960e+00, 3.45960e+00, 4.32640e+00, 5.29000e+00, 6.35040e+00, 7.50760e+00, 8.76160e+00, 1.01124e+01, 1.15600e+01, 1.31044e+01, 1.47456e+01, 1.64836e+01, 1.83184e+01, 2.02500e+01, 2.22784e+01])
- Duplicate jupyter-notebook, re-plot matrix_v2
- Finish SUNBEAR 727-ratio matrix
- Include some deep clouds (no 727) from HST imaging
- Make table of observed P_cloud, T_500 pairs: Bjoraker++2018 GRS, Bjoraker++2022, Li++2006 3-bar in 5-micron hot spots, Banfield++1998 4-bar in GRS wake
# (MATERIAL COPIED FORM FRESHCLOUDS_SIMON22.IPYNB)
# attempt to plot results in python
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
# try to use regular fonts
# --- https://matplotlib.org/stable/gallery/text_labels_and_annotations/font_family_rc_sgskip.html
# --- https://stackoverflow.com/questions/5956182/cannot-edit-text-in-chart-exported-by-matplotlib-and-opened-in-illustrator
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.sans-serif'] = ['Helvetica', 'Roboto', 'Verdana', 'Arial']
plt.rcParams['pdf.fonttype'] = 42
# load observed temperature profiles
#
V1_in = np.loadtxt("gupta++2022_tab07.txt", skiprows=1)
V1_out = np.loadtxt("gupta++2022_tab08.txt", skiprows=1)
# load model profiles
#
# hotdry / hotwet / colddry / coldwet
#
hotdry_ztp = np.loadtxt("matrix_v2/thermal.T142_E00p10_G100", skiprows=45, usecols=(0,1,2))
hotwet_ztp = np.loadtxt("matrix_v2/thermal.T142_E10p11_G100", skiprows=45, usecols=(0,1,2))
colddry_ztp = np.loadtxt("matrix_v2/thermal.T128_E00p10_G090", skiprows=45, usecols=(0,1,2))
coldwet_ztp = np.loadtxt("matrix_v2/thermal.T128_E10p11_G090", skiprows=45, usecols=(0,1,2))
# load model cloud rates
#
hotdry_zcrate = np.loadtxt("matrix_v2/cldrate.T142_E00p10_G100", skiprows=8, usecols=(0,3,4,5,6,7,8))
hotwet_zcrate = np.loadtxt("matrix_v2/cldrate.T142_E10p11_G100", skiprows=8, usecols=(0,3,4,5,6,7,8))
colddry_zcrate = np.loadtxt("matrix_v2/cldrate.T128_E00p10_G090", skiprows=8, usecols=(0,3,4,5,6,7,8))
coldwet_zcrate = np.loadtxt("matrix_v2/cldrate.T128_E10p11_G090", skiprows=8, usecols=(0,3,4,5,6,7,8))
# initialize 4-panel plot
#
fig,axs=plt.subplots(1,4,figsize=(10, 4.5))
fig.tight_layout()
fig.subplots_adjust(wspace=0.45)
fullcolor = cm.get_cmap('jet')
# plot occultation temperature profile
#
axs[0].plot(V1_in[:,1], V1_in[:,0] / 1000., linewidth=3)
axs[1].plot(V1_in[:,1], V1_in[:,0] / 1000., linewidth=3)
axs[2].plot(V1_in[:,1], V1_in[:,0] / 1000., linewidth=3)
axs[3].plot(V1_in[:,1], V1_in[:,0] / 1000., linewidth=3)
axs[0].plot(V1_out[:,1], V1_out[:,0] / 1000., linewidth=3)
axs[1].plot(V1_out[:,1], V1_out[:,0] / 1000., linewidth=3)
axs[2].plot(V1_out[:,1], V1_out[:,0] / 1000., linewidth=3)
axs[3].plot(V1_out[:,1], V1_out[:,0] / 1000., linewidth=3)
# plot model adiabats
#
axs[0].plot(hotdry_ztp[:,1], hotdry_ztp[:,2], color=fullcolor(200))
axs[1].plot(hotwet_ztp[:,1], hotwet_ztp[:,2], color=fullcolor(200))
axs[2].plot(colddry_ztp[:,1], colddry_ztp[:,2], color=fullcolor(200))
axs[3].plot(coldwet_ztp[:,1], coldwet_ztp[:,2], color=fullcolor(200))
# scale and label the axes
#
axs[0].set_xlim(0., 400.)
axs[0].set_ylim(20., 0.25)
axs[0].set_yscale('log')
axs[0].set_ylabel('P (bar)')
axs[0].set_xlabel('T (K)')
axs[0].tick_params(axis='both', which='major', size=6, bottom=True, left=True, right=True)
axs[0].tick_params(axis='both', which='minor', size=3, bottom=True, left=True, right=True)
axs[0].minorticks_on()
axs[1].set_xlim(0., 400.)
axs[1].set_ylim(20., 0.25)
axs[1].set_yscale('log')
axs[1].set_xlabel('T (K)')
axs[1].tick_params(axis='both', which='major', size=6, bottom=True, left=True, right=True)
axs[1].tick_params(axis='both', which='minor', size=3, bottom=True, left=True, right=True)
axs[1].minorticks_on()
axs[2].set_xlim(0., 400.)
axs[2].set_ylim(20., 0.25)
axs[2].set_yscale('log')
axs[2].set_xlabel('T (K)')
axs[2].tick_params(axis='both', which='major', size=6, bottom=True, left=True, right=True)
axs[2].tick_params(axis='both', which='minor', size=3, bottom=True, left=True, right=True)
axs[2].minorticks_on()
axs[3].set_xlim(0., 400.)
axs[3].set_ylim(20., 0.25)
axs[3].set_yscale('log')
axs[3].set_xlabel('T (K)')
axs[3].tick_params(axis='both', which='major', size=6, bottom=True, left=True, right=True)
axs[3].tick_params(axis='both', which='minor', size=3, bottom=True, left=True, right=True)
axs[3].minorticks_on()
# plot water clouds (ax labels kept as j,s,u,n from simon++2022)
#
cdj = axs[0].twiny()
cds = axs[1].twiny()
cdu = axs[2].twiny()
cdn = axs[3].twiny()
cdj.plot(hotdry_zcrate[:,1], hotdry_ztp[:,2], color=fullcolor(60))
cds.plot(hotwet_zcrate[:,1], hotwet_ztp[:,2], color=fullcolor(60))
cdu.plot(colddry_zcrate[:,1], colddry_ztp[:,2], color=fullcolor(60))
cdn.plot(coldwet_zcrate[:,1], coldwet_ztp[:,2], color=fullcolor(60))
cdj.plot(hotdry_zcrate[:,2], hotdry_ztp[:,2], color=fullcolor(80))
cds.plot(hotwet_zcrate[:,2], hotwet_ztp[:,2], color=fullcolor(80))
cdu.plot(colddry_zcrate[:,2], colddry_ztp[:,2], color=fullcolor(80))
cdn.plot(coldwet_zcrate[:,2], coldwet_ztp[:,2], color=fullcolor(80))
# plot NH4SH clouds
#
cdj.plot(hotdry_zcrate[:,3], hotdry_ztp[:,2], color=fullcolor(100))
cds.plot(hotwet_zcrate[:,3], hotwet_ztp[:,2], color=fullcolor(100))
cdu.plot(colddry_zcrate[:,3], colddry_ztp[:,2], color=fullcolor(100))
cdn.plot(coldwet_zcrate[:,3], coldwet_ztp[:,2], color=fullcolor(100))
# plot NH3 clouds
#
cdj.plot(hotdry_zcrate[:,4], hotdry_ztp[:,2], color=fullcolor(140))
cds.plot(hotwet_zcrate[:,4], hotwet_ztp[:,2], color=fullcolor(140))
cdu.plot(colddry_zcrate[:,4], colddry_ztp[:,2], color=fullcolor(140))
cdn.plot(coldwet_zcrate[:,4], coldwet_ztp[:,2], color=fullcolor(140))
cdj.set_xlim(1e-14, 1e-10)
cdj.set_xscale('log')
cdj.set_xlabel('Hot/dry')
cdj.tick_params(axis='x', which='major', size=6, top=True)
cdj.tick_params(axis='x', which='minor', size=3, top=True)
cds.set_xlim(1e-14, 1e-10)
cds.set_xscale('log')
cds.set_xlabel('Hot/wet')
cds.tick_params(axis='x', which='major', size=6, top=True)
cds.tick_params(axis='x', which='minor', size=3, top=True)
cdu.set_xlim(1e-14, 1e-10)
cdu.set_xscale('log')
cdu.set_xlabel('Cold/dry')
cdu.tick_params(axis='x', which='major', size=6, top=True)
cdu.tick_params(axis='x', which='minor', size=3, top=True)
cdn.set_xlim(1e-14, 1e-10)
cdn.set_xscale('log')
cdn.set_xlabel('Cold/wet')
cdn.tick_params(axis='x', which='major', size=6, top=True)
cdn.tick_params(axis='x', which='minor', size=3, top=True)
plt.savefig('ECCM-endmembers_orig.pdf')
import numpy as np
ENRH2O_seq = (np.arange(0.1, 4.75, 0.22))**2
print(len(ENRH2O_seq), ENRH2O_seq)
#Mixing ratios relative to H2 for a pure solar atmosphere:
#He = 1.570E-01, CH4 = 5.90E-04, H2O = 1.07E-03, NH3 = 1.48E-04, H2S = 2.89E-05, Ar = 5.51E-06, Ne = 1.87E-04
#Planets He/H2 ratio and enrichments above solar for the other gases:
#He/H2 = 0.16, CH4 = 4.02, H2O = 5.29, NH3 = 2.70, H2S = 2.70, Ar = 3.30, Ne = 0.12
print("He = ",1.570E-01 * 1)
print("CH4 = ",5.90E-04 * 4.02)
print("H2O = ",1.07E-03 * 5.29)
print("NH3 = ",1.48E-04 * 2.70)
print("H2S = ",2.89E-05 * 2.70)
print("Ar = ",5.51E-06 * 3.30)
print("Ne = ",1.87E-04 * 0.12)
22 [1.00000e-02 1.02400e-01 2.91600e-01 5.77600e-01 9.60400e-01 1.44000e+00 2.01640e+00 2.68960e+00 3.45960e+00 4.32640e+00 5.29000e+00 6.35040e+00 7.50760e+00 8.76160e+00 1.01124e+01 1.15600e+01 1.31044e+01 1.47456e+01 1.64836e+01 1.83184e+01 2.02500e+01 2.22784e+01] He = 0.157 CH4 = 0.0023718 H2O = 0.0056603 NH3 = 0.0003996 H2S = 7.803000000000001e-05 Ar = 1.8183e-05 Ne = 2.244e-05
Sushil: ECCM end member fig, "And, why don't you show the 1x case also? At the very least, state the results for 1x solar in the figure caption for the sake of comparison and completeness."
# get the low-temp P_cloud:
#A = T128_E00p96_G090
#B = T128_E01p44_G090
e_a = 0.96
e_b = 1.44
p_a = 7.6156
p_b = 8.4731
print("COLD: ", p_a + (p_b - p_a)/(e_b - e_a) * (1 - e_a))
#A = T142_E00p96_G100
#B = T142_E01p44_G100
p_a = 3.8050
p_b = 4.1146
print("HOT: ", p_a + (p_b - p_a)/(e_b - e_a) * (1 - e_a))
COLD: 7.687058333333333 HOT: 3.8308