First SOCRATES run
This tutorial walks through computing thermal (longwave) radiative fluxes through a simple single-column water-vapour atmosphere. By the end you will have:
- downloaded a PROTEUS spectral file,
- prepared it for use with SOCRATES,
- assembled a minimal set of atmospheric input files,
- run SOCRATES, and
- understood the output.
Prerequisites: SOCRATES installed with RAD_DIR set and the FWL_DATA environment variable set (see Installation). Make sure you also have a working Python environment with the necessary dependencies.
Spectral file used in this tutorial
We use Frostflow-256, a water-vapour-only file with 256 spectral bands from the DACE opacity database. For quick debugging runs, a 16-band version is available on Zenodo. For production work, the 4096-band version provides the highest resolution.
1. Download the spectral file
PROTEUS spectral files are hosted on Zenodo. Each spectral file and band count is a separate record. Download Frostflow at 256 bands (Zenodo record 10.5281/zenodo.15799754):
mkdir -p $FWL_DATA/spectral_files/Frostflow/256
wget "https://zenodo.org/records/15799754/files/Frostflow.sf?download=1" -O $FWL_DATA/spectral_files/Frostflow/256/Frostflow.sf
wget "https://zenodo.org/records/15799754/files/Frostflow.sf_k?download=1" -O $FWL_DATA/spectral_files/Frostflow/256/Frostflow.sf_k
2. Create a working directory
mkdir -p socrates_tutorial/out
cd socrates_tutorial
3. Prepare the spectral file
The downloaded spectral file needs a thermal source function (Block 6) added before it
can be used for longwave calculations. Copy it into your working directory first, then
modify the local copy, leaving the original in $FWL_DATA untouched. While in socrates_tutorial:
cp $FWL_DATA/spectral_files/Frostflow/256/Frostflow.sf Frostflow.sf
cp $FWL_DATA/spectral_files/Frostflow/256/Frostflow.sf_k Frostflow.sf_k
Source the SOCRATES environment to put prep_spec on your path:
source $RAD_DIR/set_rad_env
Now add Block 6 (thermal source function, tabulated over 100–4000 K at 250 temperature
points). This uses the prep_spec utility interactively:
printf "%s\n" \
"Frostflow.sf" \
"a" \
"6" \
"n" \
"T" \
"100 4000" \
"250" \
"-1" \
| prep_spec
What each input does:
| Input | Prompt | Meaning |
|---|---|---|
$HOME/socrates_tutorial/Frostflow.sf |
File name | Full path to the local copy |
a |
Append or new? | Append to existing file |
6 |
Block type | Block 6: thermal source function |
n |
Filter required? | No |
T |
Table or polynomial? | Tabulate |
100 4000 |
Temperature range (K) | Covers cold stratospheres to magma ocean surfaces |
250 |
Number of temperature points | Standard resolution |
-1 |
Next block | Write file and exit |
Set a shell variable pointing to the prepared spectral file:
SPECTRUM=Frostflow.sf
N_BANDS=256
4. Prepare the atmospheric input files
SOCRATES reads the atmospheric state from a set of netCDF files that share a common
basename and differ only by their suffix. Here we use the basename atm.
The atmosphere is divided into N homogeneous layers, bounded by N+1 levels. Layer
mid-point values go into most files; level-edge temperatures go into .tl.
We will set up a 10-layer hot steam atmosphere, the kind of conditions relevant to a post-magma-ocean planet.
4.1 Install dependencies
If you have not yet installed the necessary Python dependencies:
pip install -r "$RAD_DIR/python/requirements.txt"
4.2 Write the input script
Save the following as make_inputs.py in socrates_tutorial/:
import sys
import os
import numpy as np
import f90nml
# Import netCDF helpers from SOCRATES
sys.path.insert(0, os.path.join(os.environ['RAD_DIR'], 'python'))
from nctools import ncout_surf, ncout2d, ncout3d
BASENAME = "out/atm"
# --- Atmosphere structure ---
N_LAYERS = 10
p_surf = 1.0e7 # Pa (100 bar)
p_top = 1.0e2 # Pa (1 mbar)
p_mid = np.logspace(np.log10(p_surf), np.log10(p_top), N_LAYERS)
T_surf = 1500.0 # K
T_top = 200.0 # K
t_mid = np.linspace(T_surf, T_top, N_LAYERS)
# Level-edge values (N+1)
p_lev = np.concatenate([[p_surf * 1.05],
0.5 * (p_mid[:-1] + p_mid[1:]),
[p_top * 0.95]])
t_lev = np.interp(p_lev, p_mid[::-1], t_mid[::-1])[::-1]
# H2O mass mixing ratio: pure steam
h2o = np.ones(N_LAYERS)
# --- Write input files ---
ncout3d(f"{BASENAME}.t", 0, 0, p_mid, t_mid, 't', longname="Temperature", units='K')
ncout3d(f"{BASENAME}.tl", 0, 0, p_lev, t_lev, 'tl', longname="Temperature", units='K')
ncout3d(f"{BASENAME}.p", 0, 0, p_mid, p_mid, 'p', longname="Pressure", units='Pa')
ncout3d(f"{BASENAME}.q", 0, 0, p_mid, h2o, 'q', longname="q", units='kg/kg')
ncout2d(f"{BASENAME}.tstar", 0, 0, T_surf, 'tstar', longname="Surface Temperature", units='K')
ncout2d(f"{BASENAME}.pstar", 0, 0, p_surf, 'pstar', longname="Surface Pressure", units='Pa')
ncout_surf(f"{BASENAME}.surf", 0, 0, 1, 0.0)
# Planetary namelist — SOCRATES uses Earth defaults without this
nml = {
'socrates_constants': {
'planet_radius': 6.371e6, # m
'grav_acc': 9.81, # m s-2
'mol_weight_air': 0.018, # kg mol-1 (pure H2O)
'r_gas_dry': 462.0, # J kg-1 K-1
'cp_air_dry': 1996.0, # J kg-1 K-1
}
}
f90nml.write(nml, f"{BASENAME}.nml")
print("Input files written:")
for f in sorted(os.listdir("out")):
if f.startswith("atm."):
print(f" out/{f}")
Run it:
python make_inputs.py
You should see eight files under out/: out/atm.nml, out/atm.p, out/atm.pstar, out/atm.q, out/atm.surf,
out/atm.t, out/atm.tl, out/atm.tstar.
5. Run SOCRATES
Run the longwave calculation, writing all output to the out/ subdirectory:
Cl_run_cdf \
-B out/atm \
-s $SPECTRUM \
-R 1 $N_BANDS \
-ch $N_BANDS \
-I \
-g 2 \
-C 5 \
-u \
-N out/atm.nml
| Option | Meaning |
|---|---|
-B out/atm |
Basename: output files written to out/ with prefix atm |
-s $SPECTRUM |
Path to the prepared spectral file |
-R 1 $N_BANDS |
Use spectral bands 1 to N_BANDS |
-ch $N_BANDS |
Number of channels (must match -R) |
-I |
Solve for thermal (longwave) source |
-g 2 |
Correlated-k gas overlap |
-C 5 |
Cloud scheme 5 (clear-sky — no cloud input files needed) |
-u |
Write upward flux output files |
-N out/atm.nml |
Namelist file with planetary parameters |
Additionally, you can use the -o flag for verbose output.
Adjust options
The command shown above can be adjusted if preferred. use man CL_run_cdf for all options and information.
6. Inspect the output
SOCRATES writes one netCDF output file per flux quantity under out/. These are netCDF files, although their file extensions are different. Each file also contains the wavelengths of each spectral band, and the pressure grid used.
| File | Contents |
|---|---|
out/atm.uflx |
Upward flux (W m\(^{-2}\)) |
out/atm.dflx |
Diffuse downward flux (W m\(^{-2}\)) |
out/atm.vflx |
Total downward flux (W m\(^{-2}\)) |
out/atm.nflx |
Net downward flux (W m\(^{-2}\)) |
out/atm.hrts |
Heating rates (K day\(^{-1}\)) |
Read and plot the upward flux profile by pasting the following code in plot.py:
import netCDF4 as nc
import matplotlib.pyplot as plt
import numpy as np
# Open the NetCDF file
ds = nc.Dataset("out/atm.uflx")
# Read the spectral upward-longwave fluxes at each layer
spec_flux = ds.variables["uflx"][:, :, 0, 0]
# Sum over all spectral bands to get bolometric flux
bolo_flux = np.sum(spec_flux, axis=0)
# Read pressure grid
pres = ds.variables["plev"][:]
# close the file
ds.close()
# Make the plot of flux versus pressure (i.e. height)
plt.figure(dpi=300)
plt.plot(bolo_flux, pres / 1e5, "b-o")
plt.gca().invert_yaxis()
plt.yscale("log")
plt.xlabel(r"Upward flux (W m$^{-2}$)")
plt.ylabel("Pressure (bar)")
plt.title(r"Upward bolometric longwave flux, Frostflow-256, pure H$_2$O")
plt.tight_layout()
plt.savefig("out/flux_profile.pdf", bbox_inches="tight")
# Print the outgoing longwave radiation flux
olr = bolo_flux[0]
print(f"OLR: {olr:.1f} W/m^2")
plt.show()
Then:
python plot.py
The upward flux at the top of atmosphere is the outgoing longwave radiation (OLR), the rate at which the atmosphere thermally emits radiation energy to space.
Alternatively, you can use the ncdump command to view the content of netCDF files in the terminal directly. For example, to view header information from the upward flux file, run:
ncdump -h out/atm.uflx
7. Next steps
- Add more gases. Supply
.co2,.n2etc. files and use a multi-gas spectral file such as Dayspring or Honeyside. - Add a stellar source. Run with
-Sinstead of-I, supplying.stoa,.szen, and.saziminput files. - Change planetary parameters. Edit
atm.nmlto set the correct gravity, radius, and molecular weight for your target planet. - Increase resolution. The 4096-band Frostflow provides higher-resolution results.
For information on all available spectral files and their absorbers, see PROTEUS spectral files.