JURASSIC
Data Structures | Macros | Enumerations | Functions
jurassic.h File Reference

JURASSIC library declarations. More...

#include <errno.h>
#include <fcntl.h>
#include <gsl/gsl_math.h>
#include <gsl/gsl_blas.h>
#include <gsl/gsl_linalg.h>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_statistics.h>
#include <math.h>
#include <netcdf.h>
#include <omp.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

Go to the source code of this file.

Data Structures

struct  atm_t
 Atmospheric profile data. More...
 
struct  ctl_t
 Control parameters. More...
 
struct  los_t
 Line-of-sight data. More...
 
struct  obs_t
 Observation geometry and radiance data. More...
 
struct  ret_t
 Retrieval control parameters. More...
 
struct  tbl_t
 Emissivity look-up tables. More...
 

Macros

#define C1   1.19104259e-8
 First spectroscopic constant (c_1 = 2 h c^2) [W/(m^2 sr cm^-4)]. More...
 
#define C2   1.43877506
 Second spectroscopic constant (c_2 = h c / k) [K/cm^-1]. More...
 
#define EPSMIN   0
 Minimum emissivity. More...
 
#define EPSMAX   1
 Maximum emissivity. More...
 
#define G0   9.80665
 Standard gravity [m/s^2]. More...
 
#define H0   7.0
 Standard scale height [km]. More...
 
#define KB   1.3806504e-23
 Boltzmann constant [kg m^2/(K s^2)]. More...
 
#define ME   5.976e24
 Mass of Earth [kg]. More...
 
#define NA   6.02214199e23
 Avogadro's number. More...
 
#define N2   0.78084
 Nitrogen concentration. More...
 
#define O2   0.20946
 Oxygen concentration. More...
 
#define P0   1013.25
 Standard pressure [hPa]. More...
 
#define RE   6367.421
 Mean radius of Earth [km]. More...
 
#define RI   8.3144598
 Ideal gas constant [J/(mol K)]. More...
 
#define T0   273.15
 Standard temperature [K]. More...
 
#define TMAX   400.
 Maximum temperature for source function [K]. More...
 
#define TMIN   100.
 Minimum temperature for source function [K]. More...
 
#define TSUN   5780.
 Effective temperature of the sun [K]. More...
 
#define UMIN   0
 Minimum column density [molecules/cm^2]. More...
 
#define UMAX   1e30
 Maximum column density [molecules/cm^2]. More...
 
#define LEN   10000
 Maximum length of ASCII data lines. More...
 
#define M   (NR*ND)
 Maximum size of measurement vector. More...
 
#define N   ((2 + NG + NW) * NP + NCL + NSF + 3)
 Maximum size of state vector. More...
 
#define NCL   8
 Maximum number of cloud layer spectral grid points. More...
 
#define ND   128
 Maximum number of radiance channels. More...
 
#define NFOV   5
 Number of ray paths used for FOV calculations. More...
 
#define NG   8
 Maximum number of emitters. More...
 
#define NLOS   4096
 Maximum number of LOS points. More...
 
#define NP   256
 Maximum number of atmospheric data points. More...
 
#define NQ   (5 + NG + NW + NCL + NSF)
 Maximum number of quantities. More...
 
#define NR   256
 Maximum number of ray paths. More...
 
#define NSF   8
 Maximum number of surface layer spectral grid points. More...
 
#define NSHAPE   20000
 Maximum number of shape function grid points. More...
 
#define NTIMER   100
 Maximum number of aggregated timers. More...
 
#define NW   4
 Maximum number of spectral windows. More...
 
#define RFMNPTS   10000000
 Maximum number of RFM spectral grid points. More...
 
#define TBLNP   41
 Maximum number of pressure levels in emissivity tables. More...
 
#define TBLNS   1200
 Maximum number of source function temperature levels. More...
 
#define TBLNT   30
 Maximum number of temperatures in emissivity tables. More...
 
#define TBLNU   512
 Maximum number of column densities per emissivity curve. More...
 
#define IDXP   0
 Index for pressure. More...
 
#define IDXT   1
 Index for temperature. More...
 
#define IDXQ(ig)   (2 + (ig))
 Indices for volume mixing ratios. More...
 
#define IDXK(iw)   (2 + (ctl->ng) + (iw))
 Indices for extinction. More...
 
#define IDXCLZ   (2 + (ctl->ng) + (ctl->nw))
 Index for cloud layer height. More...
 
#define IDXCLDZ   (3 + (ctl->ng) + (ctl->nw))
 Index for cloud layer depth. More...
 
#define IDXCLK(icl)   (4 + (ctl->ng) + (ctl->nw) + (icl))
 Indices for cloud layer extinction. More...
 
#define IDXSFT   (4 + (ctl->ng) + (ctl->nw) + (ctl->ncl))
 Index for surface layer temperature. More...
 
#define IDXSFEPS(isf)   (5 + (ctl->ng) + (ctl->nw) + (ctl->ncl) + (isf))
 Indices for surface layer emissivity. More...
 
#define ALLOC(ptr, type, n)
 Allocate memory for an array. More...
 
#define BRIGHT(rad, nu)    (C2 * (nu) / gsl_log1p(C1 * POW3(nu) / (rad)))
 Compute brightness temperature from radiance. More...
 
#define CLAMP(v, lo, hi)    (((v) < (lo)) ? (lo) : (((v) > (hi)) ? (hi) : (v)))
 Clamp a value to a specified range. More...
 
#define CO2_FIT(TIME)
 Climatological CO2 volume mixing ratio as a quadratic function of time. More...
 
#define DEG2RAD(deg)   ((deg) * (M_PI / 180.0))
 Convert degrees to radians. More...
 
#define DIST(a, b)   sqrt(DIST2(a, b))
 Compute Cartesian distance between two 3D vectors. More...
 
#define DIST2(a, b)    ((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])+(a[2]-b[2])*(a[2]-b[2]))
 Compute squared distance between two 3D vectors. More...
 
#define DOTP(a, b)   (a[0]*b[0]+a[1]*b[1]+a[2]*b[2])
 Compute dot product of two 3D vectors. More...
 
#define FREAD(ptr, type, size, out)
 Read binary data from a file. More...
 
#define FWRITE(ptr, type, size, out)
 Write binary data to a file. More...
 
#define LIN(x0, y0, x1, y1, x)    ((y0)+((y1)-(y0))/((x1)-(x0))*((x)-(x0)))
 Compute linear interpolation. More...
 
#define LOGY(x0, y0, x1, y1, x)
 Compute logarithmic interpolation in y. More...
 
#define MAX(a, b)   (((a)>(b))?(a):(b))
 Determine the maximum of two values. More...
 
#define MIN(a, b)   (((a)<(b))?(a):(b))
 Determine the minimum of two values. More...
 
#define NC(cmd)
 Execute a NetCDF command and check for errors. More...
 
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units, level, quant)
 Define a NetCDF variable with attributes. More...
 
#define NC_DEF_VAR_QUANTIZE(quant)
 Enable quantization for the current NetCDF variable. More...
 
#define NC_GET_DOUBLE(varname, ptr, force)
 Retrieve a double-precision variable from a NetCDF file. More...
 
#define NC_INQ_DIM(dimname, ptr, min, max, check)
 Inquire the length of a dimension in a NetCDF file. More...
 
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
 Write double precision data to a NetCDF variable. More...
 
#define NC_PUT_FLOAT(varname, ptr, hyperslab)
 Write a float array to a NetCDF file. More...
 
#define NC_PUT_INT(varname, ptr, hyperslab)
 Write integer data to a NetCDF variable. More...
 
#define NC_PUT_ATT(varname, attname, text)
 Add a text attribute to a NetCDF variable. More...
 
#define NC_PUT_ATT_GLOBAL(attname, text)    NC(nc_put_att_text(ncid, NC_GLOBAL, attname, strnlen(text, LEN), text));
 Add a global text attribute to a NetCDF file. More...
 
#define NEDT(t_bg, nesr, nu)    (BRIGHT(PLANCK((t_bg), (nu)) + (nesr), (nu)) - (t_bg))
 Convert noise-equivalent spectral radiance (NESR) to noise-equivalent delta temperature (NEDT). More...
 
#define NESR(t_bg, nedt, nu)    (PLANCK((t_bg) + (nedt), (nu)) - PLANCK((t_bg), (nu)))
 Convert noise-equivalent delta temperature (NEDT) to noise-equivalent spectral radiance (NESR). More...
 
#define NORM(a)   sqrt(DOTP(a, a))
 Compute the norm (magnitude) of a 3D vector. More...
 
#define PLANCK(T, nu)    (C1 * POW3(nu) / gsl_expm1(C2 * (nu) / (T)))
 Compute spectral radiance using Planck’s law. More...
 
#define POW2(x)   ((x)*(x))
 Compute the square of a value. More...
 
#define POW3(x)   ((x)*(x)*(x))
 Compute the cube of a value. More...
 
#define RAD2DEG(rad)   ((rad) * (180.0 / M_PI))
 Convert radians to degrees. More...
 
#define REFRAC_SW53(p, T, h2o)    (1e-6 * (77.6 * (p) / (T) + 3.73e5 * (h2o) * (p) / ((T) * (T))))
 Compute moist-air refractivity (n - 1) with Smith-Weintraub. More...
 
#define REFRAC_EDLEN(p, T)
 Compute dry-air refractivity (n - 1) with an Edlen-type relation. More...
 
#define TBL_LOG(tbl, id, ig)
 Log detailed statistics of an emissivity look-up table. More...
 
#define SELECT_TIMER(id, group)    {timer_group(id, group, 0);}
 Switch to a named aggregated timer. More...
 
#define PRINT_TIMERS    {timer_group("END", "END", 1);}
 Print aggregated timer statistics. More...
 
#define TOK(line, tok, format, var)
 Tokenize a string and parse a variable. More...
 
#define USAGE
 Print usage information on -h or --help. More...
 
#define LOGLEV   2
 Level of log messages (0=none, 1=basic, 2=detailed, 3=debug). More...
 
#define LOG(level, ...)
 Print a log message with a specified logging level. More...
 
#define WARN(...)
 Print a warning message with contextual information. More...
 
#define ERRMSG(...)
 Print an error message with contextual information and terminate the program. More...
 
#define PRINT(format, var)
 Print the value of a variable with contextual information. More...
 

Enumerations

enum  {
  FORMOD_STATUS_OK = 0 , FORMOD_STATUS_RFM_UNSUPPORTED = 1 , FORMOD_STATUS_FOV_DATA_MISSING = 2 , FORMOD_STATUS_OBSERVER_BELOW_SURFACE = 3 ,
  FORMOD_STATUS_TOO_MANY_LOS_POINTS = 4
}
 

Functions

void analyze_avk (const ret_t *ret, const ctl_t *ctl, const atm_t *atm, const int *iqa, const int *ipa, const gsl_matrix *avk)
 Analyze averaging kernel (AVK) matrix for retrieval diagnostics. More...
 
void analyze_avk_quantity (const gsl_matrix *avk, const int iq, const int *ipa, const size_t *n0, const size_t *n1, double *cont, double *res)
 Analyze averaging kernel submatrix for a specific retrieved quantity. More...
 
size_t atm2x (const ctl_t *ctl, const atm_t *atm, gsl_vector *x, int *iqa, int *ipa)
 Convert atmospheric data to state vector elements. More...
 
void atm2x_help (const double value, const int value_iqa, const int value_ip, gsl_vector *x, int *iqa, int *ipa, size_t *n)
 Append a single atmospheric value to the state vector. More...
 
void cart2geo (const double *x, double *z, double *lon, double *lat)
 Converts Cartesian coordinates to geographic coordinates. More...
 
void climatology (const ctl_t *ctl, atm_t *atm)
 Initializes atmospheric climatology profiles. More...
 
double cos_sza (const double sec, const double lon, const double lat)
 Calculates the cosine of the solar zenith angle. More...
 
double cost_function (const gsl_vector *dx, const gsl_vector *dy, const gsl_matrix *s_a_inv, const gsl_vector *sig_eps_inv)
 Compute the normalized quadratic cost function for optimal estimation. More...
 
double ctmco2 (const double nu, const double p, const double t, const double u)
 Compute carbon dioxide continuum optical depth. More...
 
double ctmh2o (const double nu, const double p, const double t, const double q, const double u)
 Compute the MT_CKD 4.1 water vapor continuum (optical depth). More...
 
double ctmn2 (const double nu, const double p, const double t)
 Compute N₂ collision-induced absorption coefficient. More...
 
double ctmo2 (const double nu, const double p, const double t)
 Compute O₂ collision-induced absorption coefficient. More...
 
void copy_atm (const ctl_t *ctl, atm_t *atm_dest, const atm_t *atm_src, const int init)
 Copy or initialize atmospheric profile data. More...
 
void copy_obs (const ctl_t *ctl, obs_t *obs_dest, const obs_t *obs_src, const int init)
 Copy or initialize observation geometry and radiance data. More...
 
void day2doy (int year, int mon, int day, int *doy)
 Convert a calendar date to day-of-year. More...
 
void doy2day (int year, int doy, int *mon, int *day)
 Convert a day-of-year value to a calendar date. More...
 
int find_emitter (const ctl_t *ctl, const char *emitter)
 Find gas species index by name. More...
 
int formod (const ctl_t *ctl, const tbl_t *tbl, atm_t *atm, obs_t *obs, los_t *los_scratch, obs_t *obs_scratch)
 Execute one complete forward-model calculation. More...
 
void formod_batch (const ctl_t *ctl, const tbl_t *tbl, atm_t *atm, obs_t *obs, const int nbatch, int *status, los_t *los_scratch, obs_t *obs_scratch)
 Execute the forward model for a batch of independent cases. More...
 
void formod_continua (const ctl_t *ctl, const los_t *los, const int ip, double *beta)
 Compute total extinction including gaseous continua. More...
 
int formod_fov (const ctl_t *ctl, obs_t *obs, obs_t *obs_scratch)
 Apply field-of-view (FOV) convolution to modeled radiances. More...
 
int formod_pencil (const ctl_t *ctl, const tbl_t *tbl, const atm_t *atm, obs_t *obs, const int ir, los_t *los)
 Compute line-of-sight radiances using the pencil-beam forward model. More...
 
void formod_rfm (const ctl_t *ctl, const tbl_t *tbl, const atm_t *atm, obs_t *obs)
 Forward-model radiance and transmittance with the Reference Forward Model (RFM). More...
 
void formod_srcfunc (const ctl_t *ctl, const tbl_t *tbl, const double t, double *src)
 Interpolate the source function (Planck radiance) at a given temperature. More...
 
void geo2cart (const double z, const double lon, const double lat, double *x)
 Converts geographic coordinates (longitude, latitude, altitude) to Cartesian coordinates. More...
 
void hydrostatic (const ctl_t *ctl, atm_t *atm)
 Adjust pressure profile using the hydrostatic equation. More...
 
void idx2name (const ctl_t *ctl, const int idx, char *quantity)
 Convert a quantity index to a descriptive name string. More...
 
void init_srcfunc (const ctl_t *ctl, tbl_t *tbl)
 Initialize source function lookup tables from emissivity data. More...
 
void intpol_atm (const ctl_t *ctl, const atm_t *atm, const double z, double *p, double *t, double *q, double *k)
 Interpolate atmospheric state variables at a given altitude. More...
 
void intpol_tbl_cga (const ctl_t *ctl, const tbl_t *tbl, const los_t *los, const int ip, double tau_path[ND][NG], double tau_seg[ND])
 Interpolate emissivities and transmittances using the Curtis–Godson approximation (CGA). More...
 
void intpol_tbl_ega (const ctl_t *ctl, const tbl_t *tbl, const los_t *los, const int ip, double tau_path[ND][NG], double tau_seg[ND])
 Interpolate emissivities and transmittances using the Emissivity Growth Approximation (EGA). More...
 
double intpol_tbl_eps (const tbl_t *tbl, const int ig, const int id, const int ip, const int it, const double logu)
 Interpolate gas emissivity as a function of column amount. More...
 
double intpol_tbl_u (const tbl_t *tbl, const int ig, const int id, const int ip, const int it, const double logeps)
 Interpolate column amount as a function of emissivity. More...
 
void jsec2time (const double jsec, int *year, int *mon, int *day, int *hour, int *min, int *sec, double *remain)
 Converts Julian seconds to calendar date and time components. More...
 
void kernel (const ctl_t *ctl, const tbl_t *tbl, atm_t *atm, obs_t *obs, gsl_matrix *k)
 Compute the Jacobian (kernel) matrix by finite differences. More...
 
int locate_irr (const double *xx, const int n, const double x)
 Locate index for interpolation on an irregular grid. More...
 
int locate_reg (const double *xx, const int n, const double x)
 Locate index for interpolation on a regular (uniform) grid. More...
 
int locate_tbl (const float *xx, const int n, const double x)
 Locate index for interpolation within emissivity table grids. More...
 
void matrix_invert (gsl_matrix *a)
 Invert a square matrix, optimized for diagonal or symmetric positive-definite matrices. More...
 
void matrix_product (const gsl_matrix *a, const gsl_vector *b, const int transpose, gsl_matrix *c)
 Compute structured matrix products of the form \(A^T B A\) or \(A B A^T\). More...
 
size_t obs2y (const ctl_t *ctl, const obs_t *obs, gsl_vector *y, int *ida, int *ira)
 Convert observation radiances into a measurement vector. More...
 
void optimal_estimation (ret_t *ret, ctl_t *ctl, tbl_t *tbl, obs_t *obs_meas, obs_t *obs_i, atm_t *atm_apr, atm_t *atm_i, double *chisq)
 Perform optimal estimation retrieval using Levenberg–Marquardt minimization. More...
 
int raytrace (const ctl_t *ctl, const atm_t *atm, obs_t *obs, los_t *los, const int ir)
 Perform line-of-sight (LOS) ray tracing through the atmosphere. More...
 
void read_atm (const char *dirname, const char *filename, const ctl_t *ctl, atm_t *atm, int profile)
 Read atmospheric input data from a file. More...
 
void read_atm_asc (const char *filename, const ctl_t *ctl, atm_t *atm)
 Read atmospheric data in ASCII format. More...
 
void read_atm_bin (const char *filename, const ctl_t *ctl, atm_t *atm)
 Read atmospheric data in binary format. More...
 
void read_atm_nc (const char *filename, const ctl_t *ctl, atm_t *atm, int profile)
 Read one atmospheric profile from a netCDF file. More...
 
void read_ctl (int argc, char *argv[], ctl_t *ctl)
 Read model control parameters from command-line and configuration input. More...
 
void read_matrix (const char *dirname, const char *filename, const ctl_t *ctl, gsl_matrix *matrix, int dataset)
 Read a numerical matrix from a file. More...
 
void read_matrix_asc (const char *dirname, const char *filename, gsl_matrix *matrix)
 Read a numerical matrix from an ASCII file. More...
 
void read_matrix_bin (const char *dirname, const char *filename, gsl_matrix *matrix)
 Read a numerical matrix from a binary file. More...
 
void read_matrix_nc (const char *dirname, const char *filename, gsl_matrix *matrix, int dataset)
 Read a numerical matrix from a netCDF file. More...
 
void read_obs (const char *dirname, const char *filename, const ctl_t *ctl, obs_t *obs, int profile)
 Read observation data from an input file. More...
 
void read_obs_asc (const char *filename, const ctl_t *ctl, obs_t *obs)
 Read ASCII-formatted observation data from a file. More...
 
void read_obs_bin (const char *filename, const ctl_t *ctl, obs_t *obs)
 Read binary-formatted observation data from a file. More...
 
void read_obs_nc (const char *filename, const ctl_t *ctl, obs_t *obs, const int profile)
 Read one observation profile from a NetCDF file. More...
 
double read_obs_rfm (const char *basename, const double z, const double *nu, const double *f, const int n)
 Read and spectrally convolve an RFM output spectrum. More...
 
void read_ret (int argc, char *argv[], const ctl_t *ctl, ret_t *ret)
 Read retrieval configuration and error parameters. More...
 
void read_rfm_spec (const char *filename, double *nu, double *rad, int *npts)
 Read a Reference Forward Model (RFM) ASCII spectrum. More...
 
void read_shape (const char *filename, double *x, double *y, int *n)
 Read a two-column shape function from an ASCII file. More...
 
tbl_t * read_tbl (const ctl_t *ctl)
 Read emissivity lookup tables from disk. More...
 
void read_tbl_asc (const ctl_t *ctl, tbl_t *tbl, const int id, const int ig)
 Read a single ASCII emissivity lookup table. More...
 
void read_tbl_bin (const ctl_t *ctl, tbl_t *tbl, const int id, const int ig)
 Read a single compact binary emissivity lookup table. More...
 
void read_tbl_nc_channel (const ctl_t *ctl, tbl_t *tbl, int id, int ig, int ncid)
 Read one packed emissivity lookup table from an open NetCDF file. More...
 
double scan_ctl (int argc, char *argv[], const char *varname, const int arridx, const char *defvalue, char *value)
 Scan control file or command-line arguments for a configuration variable. More...
 
void set_cov_apr (const ret_t *ret, const ctl_t *ctl, const atm_t *atm, const int *iqa, const int *ipa, gsl_matrix *s_a)
 Construct the a priori covariance matrix \(\mathbf{S_a}\) for retrieval parameters. More...
 
void set_cov_meas (const ret_t *ret, const ctl_t *ctl, const obs_t *obs, gsl_vector *sig_noise, gsl_vector *sig_formod, gsl_vector *sig_eps_inv)
 Construct measurement error standard deviations and their inverse. More...
 
const char * shared_io_input_target (const ret_t *ret, const char *shared_file, const char *legacy_file, const char **dirname, int *profile)
 Resolve retrieval input target for legacy-directory and shared-file modes. More...
 
const char * shared_io_output_target (const ret_t *ret, const char *shared_file, const char *legacy_file, const char **dirname, int *profile)
 Resolve retrieval output target for legacy-directory and shared-file modes. More...
 
int shared_io_lock (const ret_t *ret)
 Acquire an exclusive lock for shared retrieval output files. More...
 
void shared_io_unlock (int fd)
 Release a shared retrieval output lock. More...
 
const char * shared_io_output_file (const ret_t *ret)
 Return the primary shared retrieval output file configured for locking. More...
 
void tangent_point (const los_t *los, double *tpz, double *tplon, double *tplat)
 Determine the tangent point along a line of sight (LOS). More...
 
void tbl_free (const ctl_t *ctl, tbl_t *tbl)
 Free lookup table and all internally allocated memory. More...
 
void tbl_pack (const tbl_t *tbl, int id, int ig, uint8_t *buf, size_t *bytes_used)
 Pack a lookup table into a contiguous binary buffer. More...
 
size_t tbl_packed_size (const tbl_t *tbl, int id, int ig)
 Compute required buffer size (in bytes) for tbl_pack(). More...
 
size_t tbl_unpack (tbl_t *tbl, int id, int ig, const uint8_t *buf)
 Unpack a lookup table from a contiguous binary buffer. More...
 
void time2jsec (const int year, const int mon, const int day, const int hour, const int min, const int sec, const double remain, double *jsec)
 Converts time components to seconds since January 1, 2000, 12:00:00 UTC. More...
 
void timer_group (const char *name, const char *group, int output)
 Aggregate wall-clock timings for named code phases. More...
 
void write_atm (const char *dirname, const char *filename, const ctl_t *ctl, const atm_t *atm, int profile)
 Write atmospheric data to a file. More...
 
void write_atm_asc (const char *filename, const ctl_t *ctl, const atm_t *atm)
 Write atmospheric data to an ASCII file. More...
 
void write_atm_bin (const char *filename, const ctl_t *ctl, const atm_t *atm)
 Write atmospheric data to a binary file. More...
 
void write_atm_nc (const char *filename, const ctl_t *ctl, const atm_t *atm, int profile)
 Write one atmospheric profile to a netCDF file. More...
 
void write_atm_rfm (const char *filename, const ctl_t *ctl, const atm_t *atm)
 Write atmospheric profile in RFM-compatible format. More...
 
void write_matrix (const char *dirname, const char *filename, const ctl_t *ctl, const gsl_matrix *matrix, const atm_t *atm, const obs_t *obs, const char *rowspace, const char *colspace, const char *sort, int dataset)
 Write a fully annotated matrix (e.g., Jacobian or gain matrix) to file. More...
 
void write_matrix_asc (const char *dirname, const char *filename, const ctl_t *ctl, const gsl_matrix *matrix, const atm_t *atm, const obs_t *obs, const char *rowspace, const char *colspace, const char *sort)
 Write a fully annotated matrix (e.g., Jacobian or gain matrix) to an ASCII file. More...
 
void write_matrix_bin (const char *dirname, const char *filename, const gsl_matrix *matrix)
 Write a numerical matrix to a binary file. More...
 
void write_matrix_nc (const char *dirname, const char *filename, const ctl_t *ctl, const gsl_matrix *matrix, const atm_t *atm, const obs_t *obs, const char *rowspace, const char *colspace, const char *sort, int dataset)
 Write a numerical matrix to a netCDF file. More...
 
void write_obs (const char *dirname, const char *filename, const ctl_t *ctl, const obs_t *obs, int profile)
 Write observation data to an output file in ASCII or binary format. More...
 
void write_obs_asc (const char *filename, const ctl_t *ctl, const obs_t *obs)
 Write observation data to an ASCII text file. More...
 
void write_obs_bin (const char *filename, const ctl_t *ctl, const obs_t *obs)
 Write observation data in binary format to a file. More...
 
void write_obs_nc (const char *filename, const ctl_t *ctl, const obs_t *obs, const int profile)
 Write one observation profile to a NetCDF file. More...
 
void write_shape (const char *filename, const double *x, const double *y, const int n)
 Write tabulated shape function data to a text file. More...
 
void write_stddev (const char *quantity, const ret_t *ret, const ctl_t *ctl, const atm_t *atm, const gsl_matrix *s)
 Write retrieval standard deviation profiles to disk. More...
 
void write_tbl (const ctl_t *ctl, const tbl_t *tbl)
 Write emissivity lookup tables to disk. More...
 
void write_tbl_asc (const ctl_t *ctl, const tbl_t *tbl, const int id, const int ig)
 Write one emissivity lookup table in human-readable ASCII format. More...
 
void write_tbl_bin (const ctl_t *ctl, const tbl_t *tbl, const int id, const int ig)
 Write one emissivity lookup table in compact binary format. More...
 
void write_tbl_nc (const ctl_t *ctl, const tbl_t *tbl, const int id, const int ig)
 Write one packed lookup table to a NetCDF file. More...
 
void x2atm (const ctl_t *ctl, const gsl_vector *x, atm_t *atm)
 Map retrieval state vector back to atmospheric structure. More...
 
void x2atm_help (double *value, const gsl_vector *x, size_t *n)
 Helper function to extract a single value from the retrieval state vector. More...
 
void y2obs (const ctl_t *ctl, const gsl_vector *y, obs_t *obs)
 Copy elements from the measurement vector y into the observation structure. More...
 

Detailed Description

JURASSIC library declarations.

Definition in file jurassic.h.

Macro Definition Documentation

◆ C1

#define C1   1.19104259e-8

First spectroscopic constant (c_1 = 2 h c^2) [W/(m^2 sr cm^-4)].

Definition at line 172 of file jurassic.h.

◆ C2

#define C2   1.43877506

Second spectroscopic constant (c_2 = h c / k) [K/cm^-1].

Definition at line 177 of file jurassic.h.

◆ EPSMIN

#define EPSMIN   0

Minimum emissivity.

Definition at line 182 of file jurassic.h.

◆ EPSMAX

#define EPSMAX   1

Maximum emissivity.

Definition at line 187 of file jurassic.h.

◆ G0

#define G0   9.80665

Standard gravity [m/s^2].

Definition at line 192 of file jurassic.h.

◆ H0

#define H0   7.0

Standard scale height [km].

Definition at line 197 of file jurassic.h.

◆ KB

#define KB   1.3806504e-23

Boltzmann constant [kg m^2/(K s^2)].

Definition at line 202 of file jurassic.h.

◆ ME

#define ME   5.976e24

Mass of Earth [kg].

Definition at line 207 of file jurassic.h.

◆ NA

#define NA   6.02214199e23

Avogadro's number.

Definition at line 212 of file jurassic.h.

◆ N2

#define N2   0.78084

Nitrogen concentration.

Definition at line 217 of file jurassic.h.

◆ O2

#define O2   0.20946

Oxygen concentration.

Definition at line 222 of file jurassic.h.

◆ P0

#define P0   1013.25

Standard pressure [hPa].

Definition at line 227 of file jurassic.h.

◆ RE

#define RE   6367.421

Mean radius of Earth [km].

Definition at line 232 of file jurassic.h.

◆ RI

#define RI   8.3144598

Ideal gas constant [J/(mol K)].

Definition at line 237 of file jurassic.h.

◆ T0

#define T0   273.15

Standard temperature [K].

Definition at line 242 of file jurassic.h.

◆ TMAX

#define TMAX   400.

Maximum temperature for source function [K].

Definition at line 247 of file jurassic.h.

◆ TMIN

#define TMIN   100.

Minimum temperature for source function [K].

Definition at line 252 of file jurassic.h.

◆ TSUN

#define TSUN   5780.

Effective temperature of the sun [K].

Definition at line 257 of file jurassic.h.

◆ UMIN

#define UMIN   0

Minimum column density [molecules/cm^2].

Definition at line 262 of file jurassic.h.

◆ UMAX

#define UMAX   1e30

Maximum column density [molecules/cm^2].

Definition at line 267 of file jurassic.h.

◆ LEN

#define LEN   10000

Maximum length of ASCII data lines.

Definition at line 276 of file jurassic.h.

◆ M

#define M   (NR*ND)

Maximum size of measurement vector.

Definition at line 281 of file jurassic.h.

◆ N

#define N   ((2 + NG + NW) * NP + NCL + NSF + 3)

Maximum size of state vector.

Definition at line 286 of file jurassic.h.

◆ NCL

#define NCL   8

Maximum number of cloud layer spectral grid points.

Definition at line 291 of file jurassic.h.

◆ ND

#define ND   128

Maximum number of radiance channels.

Definition at line 296 of file jurassic.h.

◆ NFOV

#define NFOV   5

Number of ray paths used for FOV calculations.

Definition at line 301 of file jurassic.h.

◆ NG

#define NG   8

Maximum number of emitters.

Definition at line 306 of file jurassic.h.

◆ NLOS

#define NLOS   4096

Maximum number of LOS points.

Definition at line 311 of file jurassic.h.

◆ NP

#define NP   256

Maximum number of atmospheric data points.

Definition at line 316 of file jurassic.h.

◆ NQ

#define NQ   (5 + NG + NW + NCL + NSF)

Maximum number of quantities.

Definition at line 321 of file jurassic.h.

◆ NR

#define NR   256

Maximum number of ray paths.

Definition at line 326 of file jurassic.h.

◆ NSF

#define NSF   8

Maximum number of surface layer spectral grid points.

Definition at line 331 of file jurassic.h.

◆ NSHAPE

#define NSHAPE   20000

Maximum number of shape function grid points.

Definition at line 336 of file jurassic.h.

◆ NTIMER

#define NTIMER   100

Maximum number of aggregated timers.

Definition at line 341 of file jurassic.h.

◆ NW

#define NW   4

Maximum number of spectral windows.

Definition at line 346 of file jurassic.h.

◆ RFMNPTS

#define RFMNPTS   10000000

Maximum number of RFM spectral grid points.

Definition at line 351 of file jurassic.h.

◆ TBLNP

#define TBLNP   41

Maximum number of pressure levels in emissivity tables.

Definition at line 356 of file jurassic.h.

◆ TBLNS

#define TBLNS   1200

Maximum number of source function temperature levels.

Definition at line 361 of file jurassic.h.

◆ TBLNT

#define TBLNT   30

Maximum number of temperatures in emissivity tables.

Definition at line 366 of file jurassic.h.

◆ TBLNU

#define TBLNU   512

Maximum number of column densities per emissivity curve.

Definition at line 371 of file jurassic.h.

◆ IDXP

#define IDXP   0

Index for pressure.

Definition at line 379 of file jurassic.h.

◆ IDXT

#define IDXT   1

Index for temperature.

Definition at line 382 of file jurassic.h.

◆ IDXQ

#define IDXQ (   ig)    (2 + (ig))

Indices for volume mixing ratios.

Definition at line 385 of file jurassic.h.

◆ IDXK

#define IDXK (   iw)    (2 + (ctl->ng) + (iw))

Indices for extinction.

Definition at line 388 of file jurassic.h.

◆ IDXCLZ

#define IDXCLZ   (2 + (ctl->ng) + (ctl->nw))

Index for cloud layer height.

Definition at line 391 of file jurassic.h.

◆ IDXCLDZ

#define IDXCLDZ   (3 + (ctl->ng) + (ctl->nw))

Index for cloud layer depth.

Definition at line 394 of file jurassic.h.

◆ IDXCLK

#define IDXCLK (   icl)    (4 + (ctl->ng) + (ctl->nw) + (icl))

Indices for cloud layer extinction.

Definition at line 397 of file jurassic.h.

◆ IDXSFT

#define IDXSFT   (4 + (ctl->ng) + (ctl->nw) + (ctl->ncl))

Index for surface layer temperature.

Definition at line 400 of file jurassic.h.

◆ IDXSFEPS

#define IDXSFEPS (   isf)    (5 + (ctl->ng) + (ctl->nw) + (ctl->ncl) + (isf))

Indices for surface layer emissivity.

Definition at line 403 of file jurassic.h.

◆ ALLOC

#define ALLOC (   ptr,
  type,
  n 
)
Value:
if((ptr=calloc((size_t)(n), sizeof(type)))==NULL) \
ERRMSG("Out of memory!");

Allocate memory for an array.

Allocates a contiguous block of memory for an array of n elements of type type and assigns the pointer to ptr. If allocation fails, the program prints an error message and terminates.

Parameters
[out]ptrPointer to be allocated.
[in]typeData type of the elements to allocate.
[in]nNumber of elements to allocate.
Note
Wraps malloc() with built-in error handling.
See also
FREAD, FWRITE
Author
Lars Hoffmann

Definition at line 426 of file jurassic.h.

◆ BRIGHT

#define BRIGHT (   rad,
  nu 
)     (C2 * (nu) / gsl_log1p(C1 * POW3(nu) / (rad)))

Compute brightness temperature from radiance.

Computes the equivalent blackbody (brightness) temperature corresponding to a given spectral radiance and wavenumber, using the inverse Planck function. This form assumes the spectroscopic constants C1 and C2 are defined for wavenumber units (cm⁻¹).

Parameters
[in]radSpectral radiance [W·m⁻²·sr⁻¹·(cm⁻¹)⁻¹].
[in]nuWavenumber [cm⁻¹].
Returns
Brightness temperature [K].
See also
PLANCK, C1, C2
Note
Based on Planck’s law in wavenumber form: \( T_b = \frac{c_2 \nu}{\ln\!\left(1 + \frac{c_1 \nu^3}{L_\nu}\right)} \) where \(L_\nu\) is the radiance. The ν³ dependence reflects the definition of C1 for radiance per unit wavenumber in cm⁻¹.
Warning
The radiance MUST be in W·m⁻²·sr⁻¹·(cm⁻¹)⁻¹. Using radiance per meter will produce brightness temperatures incorrect by six orders of magnitude.
Author
Lars Hoffmann

Definition at line 456 of file jurassic.h.

◆ CLAMP

#define CLAMP (   v,
  lo,
  hi 
)     (((v) < (lo)) ? (lo) : (((v) > (hi)) ? (hi) : (v)))

Clamp a value to a specified range.

Ensures that v lies between lo and hi. If v < lo, returns lo. If v > hi, returns hi. Otherwise, returns v unchanged.

This macro works with any numeric type (e.g., int, float, double). All arguments are evaluated exactly once — avoid passing expressions with side effects (e.g., ++ operators or function calls).

Parameters
vInput value to clamp.
loLower bound.
hiUpper bound.
Returns
The clamped value between lo and hi.
Author
Lars Hoffmann

Definition at line 478 of file jurassic.h.

◆ CO2_FIT

#define CO2_FIT (   TIME)
Value:
(373.87884731310215e-6 \
+ 1.9021498612395775e-6 * (((TIME) - 94694400.) / 31557600.) \
+ 0.016490044598136553e-6 \
* POW2((((TIME) - 94694400.) / 31557600.)))
#define POW2(x)
Compute the square of a value.
Definition: jurassic.h:1049

Climatological CO2 volume mixing ratio as a quadratic function of time.

This macro evaluates a hardwired quadratic fit of the global mean CO2 volume mixing ratio in [ppv]. The fit is based on NOAA global annual mean CO2 data covering the period from 1980 to 2025.

Parameters
TIMETime in seconds since 2000-01-01T00:00Z.
Returns
Climatological CO2 volume mixing ratio in [ppv].
Author
Lars Hoffmann

Definition at line 493 of file jurassic.h.

◆ DEG2RAD

#define DEG2RAD (   deg)    ((deg) * (M_PI / 180.0))

Convert degrees to radians.

Converts an angle measured in degrees to radians using: \( \text{radians} = \text{degrees} \times \frac{\pi}{180} \).

Parameters
[in]degAngle in degrees.
Returns
Angle in radians.
See also
RAD2DEG
Author
Lars Hoffmann

Definition at line 513 of file jurassic.h.

◆ DIST

#define DIST (   a,
  b 
)    sqrt(DIST2(a, b))

Compute Cartesian distance between two 3D vectors.

Computes the Euclidean distance between two 3D vectors or points.

Parameters
[in]aFirst vector (array of length 3).
[in]bSecond vector (array of length 3).
Returns
Euclidean distance between a and b.
See also
DIST2
Note
Equivalent to \( \sqrt{(x_1-x_2)^2 + (y_1-y_2)^2 + (z_1-z_2)^2} \).
Author
Lars Hoffmann

Definition at line 531 of file jurassic.h.

◆ DIST2

#define DIST2 (   a,
  b 
)     ((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])+(a[2]-b[2])*(a[2]-b[2]))

Compute squared distance between two 3D vectors.

Computes the square of the Euclidean distance between two 3D vectors. Useful when only relative distances are needed (avoids square root).

Parameters
[in]aFirst vector (array of length 3).
[in]bSecond vector (array of length 3).
Returns
Squared distance between a and b.
See also
DIST
Author
Lars Hoffmann

Definition at line 548 of file jurassic.h.

◆ DOTP

#define DOTP (   a,
  b 
)    (a[0]*b[0]+a[1]*b[1]+a[2]*b[2])

Compute dot product of two 3D vectors.

Computes the scalar (dot) product between two 3-element vectors: \( a \cdot b = a_x b_x + a_y b_y + a_z b_z \).

Parameters
[in]aFirst vector (array of length 3).
[in]bSecond vector (array of length 3).
Returns
Scalar dot product of a and b.
See also
NORM
Author
Lars Hoffmann

Definition at line 566 of file jurassic.h.

◆ FREAD

#define FREAD (   ptr,
  type,
  size,
  out 
)
Value:
{ \
if(fread(ptr, sizeof(type), size, out)!=size) \
ERRMSG("Error while reading!"); \
}

Read binary data from a file.

Reads size elements of type type from the file stream out into the memory pointed to by ptr. If the number of elements read differs from size, an error message is printed and the program terminates.

Parameters
[out]ptrPointer to destination memory buffer.
[in]typeType of each element to read.
[in]sizeNumber of elements to read.
[in,out]outFile stream opened for reading.
See also
FWRITE, ALLOC
Note
Wraps fread() with error handling.
Author
Lars Hoffmann

Definition at line 586 of file jurassic.h.

◆ FWRITE

#define FWRITE (   ptr,
  type,
  size,
  out 
)
Value:
{ \
if(fwrite(ptr, sizeof(type), size, out)!=size) \
ERRMSG("Error while writing!"); \
}

Write binary data to a file.

Writes size elements of type type from the memory pointed to by ptr to the file stream out. If the number of elements written differs from size, an error message is printed and the program terminates.

Parameters
[in]ptrPointer to memory buffer containing data to write.
[in]typeType of each element to write.
[in]sizeNumber of elements to write.
[in,out]outFile stream opened for writing.
See also
FREAD
Note
Wraps fwrite() with error handling.
Author
Lars Hoffmann

Definition at line 609 of file jurassic.h.

◆ LIN

#define LIN (   x0,
  y0,
  x1,
  y1,
  x 
)     ((y0)+((y1)-(y0))/((x1)-(x0))*((x)-(x0)))

Compute linear interpolation.

Performs simple linear interpolation between two known points (x₀, y₀) and (x₁, y₁) to estimate the value of y at a given x.

Parameters
[in]x0Lower x-value.
[in]y0Function value at x₀.
[in]x1Upper x-value.
[in]y1Function value at x₁.
[in]xInterpolation point.
Returns
Linearly interpolated y-value at x.
See also
LOGY
Author
Lars Hoffmann

Definition at line 632 of file jurassic.h.

◆ LOGY

#define LOGY (   x0,
  y0,
  x1,
  y1,
  x 
)
Value:
(((y1)/(y0)>0) \
? ((y0)*exp(log((y1)/(y0))/((x1)-(x0))*((x)-(x0)))) \
: LIN(x0, y0, x1, y1, x))
#define LIN(x0, y0, x1, y1, x)
Compute linear interpolation.
Definition: jurassic.h:632

Compute logarithmic interpolation in y.

Performs interpolation assuming exponential variation in the y-axis (logarithmic in y). If y₁/y₀ is nonpositive, reverts to linear interpolation.

Parameters
[in]x0Lower x-value.
[in]y0Function value at x₀.
[in]x1Upper x-value.
[in]y1Function value at x₁.
[in]xInterpolation point.
Returns
Interpolated y-value at x.
See also
LIN
Author
Lars Hoffmann

Definition at line 653 of file jurassic.h.

◆ MAX

#define MAX (   a,
  b 
)    (((a)>(b))?(a):(b))

Determine the maximum of two values.

Returns the greater of two scalar values.

Parameters
[in]aFirst value.
[in]bSecond value.
Returns
Maximum of a and b.
See also
MIN
Note
Both arguments are evaluated multiple times; avoid side effects.
Author
Lars Hoffmann

Definition at line 674 of file jurassic.h.

◆ MIN

#define MIN (   a,
  b 
)    (((a)<(b))?(a):(b))

Determine the minimum of two values.

Returns the smaller of two scalar values.

Parameters
[in]aFirst value.
[in]bSecond value.
Returns
Minimum of a and b.
See also
MAX
Note
Both arguments are evaluated multiple times; avoid side effects.
Author
Lars Hoffmann

Definition at line 692 of file jurassic.h.

◆ NC

#define NC (   cmd)
Value:
{ \
int nc_result=(cmd); \
if(nc_result!=NC_NOERR) \
ERRMSG("%s", nc_strerror(nc_result)); \
}

Execute a NetCDF command and check for errors.

This macro executes a NetCDF command and checks the result. If the result indicates an error, it prints the error message using ERRMSG.

Parameters
cmdNetCDF command to execute.
Author
Lars Hoffmann

Definition at line 705 of file jurassic.h.

◆ NC_DEF_VAR

#define NC_DEF_VAR (   varname,
  type,
  ndims,
  dims,
  long_name,
  units,
  level,
  quant 
)
Value:
{ \
NC(nc_def_var(ncid, varname, type, ndims, dims, &varid)); \
NC(nc_put_att_text(ncid, varid, "long_name", strnlen(long_name, LEN), long_name)); \
NC(nc_put_att_text(ncid, varid, "units", strnlen(units, LEN), units)); \
NC_DEF_VAR_QUANTIZE(quant); \
if((level) != 0) { \
NC(nc_def_var_deflate(ncid, varid, 1, 1, level)); \
/* unsigned int ulevel = (unsigned int)level; */ \
/* NC(nc_def_var_filter(ncid, varid, 32015, 1, (unsigned int[]){ulevel})); */ \
} \
}
#define LEN
Maximum length of ASCII data lines.
Definition: jurassic.h:276

Define a NetCDF variable with attributes.

This macro defines a NetCDF variable with the specified name, data type, dimensions, long name, and units. It also sets the long_name and units attributes for the variable. It enables compression and quantizatio of the data.

Parameters
varnameName of the variable.
typeData type of the variable.
ndimsNumber of dimensions for the variable.
dimsArray of dimension IDs.
long_nameLong name of the variable.
unitsUnits of the variable.
levelzlib compression level (0 = off).
quantNumber of digits for quantization (0 = off).
Note
To enable ZSTD compression, replace nc_def_var_deflate() by nc_def_var_filter() below. Use dynamic linking, static linking does not work. Set environment variable HDF5_PLUGIN_PATH to ./libs/build/share/netcdf-plugins/.
Author
Lars Hoffmann

Definition at line 735 of file jurassic.h.

◆ NC_DEF_VAR_QUANTIZE

#define NC_DEF_VAR_QUANTIZE (   quant)
Value:
do { \
if((quant) > 0) \
ERRMSG("NetCDF quantization is not supported by this NetCDF version"); \
} while(0)

Enable quantization for the current NetCDF variable.

This macro applies Granular BitRound quantization to the variable identified by varid in the NetCDF file identified by ncid. If the installed NetCDF version does not support quantization, requesting it raises an error.

Parameters
quantNumber of significant digits to retain (0 = off).
Author
Lars Hoffmann

Definition at line 764 of file jurassic.h.

◆ NC_GET_DOUBLE

#define NC_GET_DOUBLE (   varname,
  ptr,
  force 
)
Value:
{ \
if(force) { \
NC(nc_inq_varid(ncid, varname, &varid)); \
NC(nc_get_var_double(ncid, varid, ptr)); \
} else { \
if(nc_inq_varid(ncid, varname, &varid) == NC_NOERR) { \
NC(nc_get_var_double(ncid, varid, ptr)); \
WARN("netCDF variable %s is missing!", varname); \
} \
}
#define WARN(...)
Print a warning message with contextual information.
Definition: jurassic.h:1323

Retrieve a double-precision variable from a NetCDF file.

This macro retrieves a double-precision variable from a NetCDF file. It first checks if the variable exists in the file and then reads its data into the specified pointer. If the force parameter is set to true, it forces the retrieval of the variable, raising an error if the variable does not exist. If force is false, it retrieves the variable if it exists and issues a warning if it does not.

Parameters
varnameName of the variable to retrieve.
ptrPointer to the memory location where the data will be stored.
forceBoolean flag indicating whether to force retrieval (true) or not (false).
Author
Lars Hoffmann

Definition at line 787 of file jurassic.h.

◆ NC_INQ_DIM

#define NC_INQ_DIM (   dimname,
  ptr,
  min,
  max,
  check 
)
Value:
{ \
int dimid; size_t naux; \
NC(nc_inq_dimid(ncid, dimname, &dimid)); \
NC(nc_inq_dimlen(ncid, dimid, &naux)); \
*ptr = (int)naux; \
if (check) \
if ((*ptr) < (min) || (*ptr) > (max)) \
ERRMSG("Dimension %s is out of range!", dimname); \
}

Inquire the length of a dimension in a NetCDF file.

This macro retrieves the length of a specified dimension from a NetCDF file. It checks if the length of the dimension is within a specified range and assigns the length to the provided pointer. If the length is outside the specified range, an error message is raised.

Parameters
dimnameName of the dimension to inquire.
ptrPointer to an integer where the dimension length will be stored.
minMinimum acceptable length for the dimension.
maxMaximum acceptable length for the dimension.
checkFlag to check bounds. Set to 1 for bounds check.
Author
Lars Hoffmann

Definition at line 816 of file jurassic.h.

◆ NC_PUT_DOUBLE

#define NC_PUT_DOUBLE (   varname,
  ptr,
  hyperslab 
)
Value:
{ \
NC(nc_inq_varid(ncid, varname, &varid)); \
if(hyperslab) { \
NC(nc_put_vara_double(ncid, varid, start, count, ptr)); \
} else { \
NC(nc_put_var_double(ncid, varid, ptr)); \
} \
}

Write double precision data to a NetCDF variable.

This macro writes data to a specified NetCDF variable. It can handle both full variable writes and hyperslab writes depending on the hyperslab parameter. If hyperslab is true, the data is written as a hyperslab; otherwise, the entire variable is written.

Parameters
varnameName of the NetCDF variable to write to.
ptrPointer to the data to be written.
hyperslabBoolean indicating whether to write the data as a hyperslab.
Author
Lars Hoffmann

Definition at line 840 of file jurassic.h.

◆ NC_PUT_FLOAT

#define NC_PUT_FLOAT (   varname,
  ptr,
  hyperslab 
)
Value:
{ \
NC(nc_inq_varid(ncid, varname, &varid)); \
if(hyperslab) { \
NC(nc_put_vara_float(ncid, varid, start, count, ptr)); \
} else { \
NC(nc_put_var_float(ncid, varid, ptr)); \
} \
}

Write a float array to a NetCDF file.

This macro writes a float array to a specified variable in a NetCDF file. Depending on the value of the hyperslab parameter, the data can be written as a hyperslab or as a whole variable.

Parameters
varnameName of the variable to which the float array will be written.
ptrPointer to the float array to be written.
hyperslabBoolean flag indicating if the data should be written as a hyperslab.
  • If true, the data will be written as a hyperslab using the start and count arrays.
  • If false, the data will be written to the entire variable.
Author
Lars Hoffmann

Definition at line 864 of file jurassic.h.

◆ NC_PUT_INT

#define NC_PUT_INT (   varname,
  ptr,
  hyperslab 
)
Value:
{ \
NC(nc_inq_varid(ncid, varname, &varid)); \
if(hyperslab) { \
NC(nc_put_vara_int(ncid, varid, start, count, ptr)); \
} else { \
NC(nc_put_var_int(ncid, varid, ptr)); \
} \
}

Write integer data to a NetCDF variable.

This macro writes data to a specified NetCDF variable. It can handle both full variable writes and hyperslab writes depending on the hyperslab parameter. If hyperslab is true, the data is written as a hyperslab; otherwise, the entire variable is written.

Parameters
varnameName of the NetCDF variable to write to.
ptrPointer to the data to be written.
hyperslabBoolean indicating whether to write the data as a hyperslab.
Author
Lars Hoffmann

Definition at line 887 of file jurassic.h.

◆ NC_PUT_ATT

#define NC_PUT_ATT (   varname,
  attname,
  text 
)
Value:
{ \
NC(nc_inq_varid(ncid, varname, &varid)); \
NC(nc_put_att_text(ncid, varid, attname, strnlen(text, LEN), text)); \
}

Add a text attribute to a NetCDF variable.

This macro adds a text attribute to a specified NetCDF variable. It first retrieves the variable ID using its name, then it attaches the text attribute to the variable.

Parameters
varnameName of the NetCDF variable to which the attribute will be added.
attnameName of the attribute to be added.
textText of the attribute to be added.
Author
Lars Hoffmann

Definition at line 909 of file jurassic.h.

◆ NC_PUT_ATT_GLOBAL

#define NC_PUT_ATT_GLOBAL (   attname,
  text 
)     NC(nc_put_att_text(ncid, NC_GLOBAL, attname, strnlen(text, LEN), text));

Add a global text attribute to a NetCDF file.

This macro adds a text attribute to the global attributes of a NetCDF file. It directly attaches the attribute to the file, rather than to a specific variable.

Parameters
attnameName of the global attribute to be added.
textText of the attribute to be added.
Author
Lars Hoffmann

Definition at line 926 of file jurassic.h.

◆ NEDT

#define NEDT (   t_bg,
  nesr,
  nu 
)     (BRIGHT(PLANCK((t_bg), (nu)) + (nesr), (nu)) - (t_bg))

Convert noise-equivalent spectral radiance (NESR) to noise-equivalent delta temperature (NEDT).

Computes the temperature noise level corresponding to a given NESR at a background radiance, using the inverse Planck function. The NEDT expresses radiometric sensitivity in temperature units, assuming blackbody emission.

Parameters
[in]t_bgBackground (scene) brightness temperature [K].
[in]nesrNoise-equivalent spectral radiance [W·m⁻²·sr⁻¹·(cm⁻¹)⁻¹].
[in]nuWavenumber [cm⁻¹].
Returns
Noise-equivalent delta temperature [K].
Note
This macro computes

\[ \mathrm{NEDT} = T_b(L_\nu(T_\mathrm{bg}) + \mathrm{NESR}) - T_\mathrm{bg} \]

where \(T_b\) is the brightness temperature from the inverse Planck function.
Warning
All units must be consistent with PLANCK and BRIGHT. Mixing radiance units per meter instead of per cm⁻¹ will yield incorrect results by orders of magnitude.
See also
NESR, PLANCK, BRIGHT, C1, C2

Definition at line 958 of file jurassic.h.

◆ NESR

#define NESR (   t_bg,
  nedt,
  nu 
)     (PLANCK((t_bg) + (nedt), (nu)) - PLANCK((t_bg), (nu)))

Convert noise-equivalent delta temperature (NEDT) to noise-equivalent spectral radiance (NESR).

Computes the radiance difference corresponding to a temperature noise level at a given background temperature and wavenumber, using Planck’s law. The NESR quantifies the radiometric sensitivity in spectral radiance units.

Parameters
[in]t_bgBackground (scene) brightness temperature [K].
[in]nedtNoise-equivalent delta temperature [K].
[in]nuWavenumber [cm⁻¹].
Returns
Noise-equivalent spectral radiance [W·m⁻²·sr⁻¹·(cm⁻¹)⁻¹].
Note
This macro computes

\[ \mathrm{NESR} = L_\nu(T_\mathrm{bg} + \mathrm{NEDT}) - L_\nu(T_\mathrm{bg}) \]

where \(L_\nu\) is spectral radiance from Planck’s law.
Warning
All units must be consistent with PLANCK. In particular, nu must be given in cm⁻¹.
See also
PLANCK, NEDT, BRIGHT

Definition at line 987 of file jurassic.h.

◆ NORM

#define NORM (   a)    sqrt(DOTP(a, a))

Compute the norm (magnitude) of a 3D vector.

Computes the Euclidean norm using the dot product: \( |a| = \sqrt{a \cdot a} \).

Parameters
[in]aInput vector (array of length 3).
Returns
Magnitude (norm) of vector a.
See also
DOTP
Author
Lars Hoffmann

Definition at line 1004 of file jurassic.h.

◆ PLANCK

#define PLANCK (   T,
  nu 
)     (C1 * POW3(nu) / gsl_expm1(C2 * (nu) / (T)))

Compute spectral radiance using Planck’s law.

Evaluates Planck’s blackbody spectral radiance for a given temperature and wavenumber. The expression is formulated in wavenumber space (cm⁻¹) and uses the spectroscopic constants C1 and C2 in wavenumber units.

Parameters
[in]nuWavenumber [cm⁻¹].
[in]TTemperature [K].
Returns
Spectral radiance \(L_\nu\) in [W·m⁻²·sr⁻¹·(cm⁻¹)⁻¹].
Note
The Planck law implemented here is

\[ L_\nu = \frac{C_{1}\,\nu^{3}} {\exp\!\left(\frac{C_{2}\,\nu}{T}\right) - 1} \]

with \(\nu\) in cm⁻¹. The \(\nu^{3}\) dependence follows from the definition of C1 for radiance per wavenumber in cm⁻¹.
Warning
The units of all inputs MUST be consistent: nu in cm⁻¹ and T in kelvin. Mixing wavenumber and frequency formulations, or using radiance per meter instead of per cm⁻¹, will produce results off by orders of magnitude.
See also
BRIGHT, C1, C2

Definition at line 1035 of file jurassic.h.

◆ POW2

#define POW2 (   x)    ((x)*(x))

Compute the square of a value.

Returns x². Inline alternative to pow(x,2).

Parameters
[in]xInput value.
Returns
x squared.
Author
Lars Hoffmann

Definition at line 1049 of file jurassic.h.

◆ POW3

#define POW3 (   x)    ((x)*(x)*(x))

Compute the cube of a value.

Returns x³. Inline alternative to pow(x,3).

Parameters
[in]xInput value.
Returns
x cubed.
Author
Lars Hoffmann

Definition at line 1062 of file jurassic.h.

◆ RAD2DEG

#define RAD2DEG (   rad)    ((rad) * (180.0 / M_PI))

Convert radians to degrees.

Converts an angle measured in radians to degrees using: \( \text{degrees} = \text{radians} \times \frac{180}{\pi} \).

Parameters
[in]radAngle in radians.
Returns
Angle in degrees.
See also
DEG2RAD
Author
Lars Hoffmann

Definition at line 1078 of file jurassic.h.

◆ REFRAC_SW53

#define REFRAC_SW53 (   p,
  T,
  h2o 
)     (1e-6 * (77.6 * (p) / (T) + 3.73e5 * (h2o) * (p) / ((T) * (T))))

Compute moist-air refractivity (n - 1) with Smith-Weintraub.

Approximates the refractivity of moist air using the Smith-Weintraub relation for radio and microwave frequencies: \( (n - 1) \times 10^6 = k_1 \frac{p}{T} + k_2 \frac{e}{T^2} \), with \( k_1 = 77.6 \,\mathrm{K/hPa} \) and \( k_2 = 3.73\times10^5 \,\mathrm{K^2/hPa} \). Here p is total pressure (hPa), T is temperature (K), and \( e = \mathrm{h2o} \cdot p \) is the water-vapor partial pressure (hPa) derived from the H2O volume mixing ratio in [ppv].

In the current raytracer this relation is used as a fallback for refractivity models that are not explicitly wavelength-dependent.

Reference: Smith, E. K., and S. Weintraub: The constants in the equation for atmospheric refractive index at radio frequencies, Proc. IRE, 41, 1035-1037, https://doi.org/10.1109/JRPROC.1953.274297, 1953.

Parameters
[in]pPressure [hPa].
[in]TTemperature [K].
[in]h2oWater-vapor volume mixing ratio [ppv].
Returns
Refractivity (dimensionless, n - 1).
Author
Lars Hoffmann

Definition at line 1108 of file jurassic.h.

◆ REFRAC_EDLEN

#define REFRAC_EDLEN (   p,
  T 
)
Value:
((1e-8 \
* (8342.54 + 2406147.0 / (130.0 - 1.0 / (10.0 * 10.0)) \
+ 15998.0 / (38.9 - 1.0 / (10.0 * 10.0)))) \
* ((p) / 1013.25) * (288.15 / (T)))

Compute dry-air refractivity (n - 1) with an Edlen-type relation.

Approximates dry-air refractivity using the wavelength-dependent relation documented for RFM: \( (n - 1) = 10^{-8}\left[8342.54 + \frac{2406147}{130-\sigma^2} + \frac{15998}{38.9-\sigma^2}\right]\frac{\rho}{\rho_\mathrm{ref}} \), where \( \sigma = 1 / \lambda \) is the wavenumber in inverse microns. The density ratio is approximated here as \( (\rho/\rho_\mathrm{ref}) \approx (p/1013.25)(288.15/T) \). In the current raytracer the reference wavelength is fixed at 10 um.

Reference: Dudhia, A.: The Reference Forward Model (RFM), J. Quant. Spectrosc. Radiat. Transfer, 186, 243-253, https://doi.org/10.1016/j.jqsrt.2016.06.018, 2017.

Parameters
[in]pPressure [hPa].
[in]TTemperature [K].
Returns
Refractivity (dimensionless, n - 1).
Author
Lars Hoffmann

Definition at line 1135 of file jurassic.h.

◆ TBL_LOG

#define TBL_LOG (   tbl,
  id,
  ig 
)
Value:
do { \
for (int ip = 0; ip < (tbl)->np[(id)][(ig)]; ip++) \
LOG(2, \
"p[%2d]= %.5e hPa | T[0:%2d]= %.2f ... %.2f K | " \
"u[0:%3d]= %.5e ... %.5e molec/cm^2 | " \
"eps[0:%3d]= %.5e ... %.5e", \
(ip), \
(tbl)->p[(id)][(ig)][(ip)], \
(tbl)->nt[(id)][(ig)][(ip)] - 1, \
(tbl)->t[(id)][(ig)][(ip)][0], \
(tbl)->t[(id)][(ig)][(ip)] \
[(tbl)->nt[(id)][(ig)][(ip)] - 1], \
(tbl)->nu[(id)][(ig)][(ip)][0] - 1, \
exp((tbl)->logu[(id)][(ig)][(ip)][0][0]), \
exp((tbl)->logu[(id)][(ig)][(ip)][0] \
[(tbl)->nu[(id)][(ig)][(ip)][0] - 1]), \
(tbl)->nu[(id)][(ig)][(ip)][0] - 1, \
exp((tbl)->logeps[(id)][(ig)][(ip)][0][0]), \
exp((tbl)->logeps[(id)][(ig)][(ip)][0] \
[(tbl)->nu[(id)][(ig)][(ip)][0] - 1])); \
} while (0)
#define LOG(level,...)
Print a log message with a specified logging level.
Definition: jurassic.h:1286

Log detailed statistics of an emissivity look-up table.

This macro logs pressure, temperature, absorber column, and emissivity ranges for all pressure levels of a given (channel, emitter) table. Output is written at verbosity level 2 and is intended for diagnostics and debugging.

Parameters
tblPointer to the look-up table structure.
idChannel (detector) index.
igEmitter (trace gas) index.
Author
Lars Hoffmann

Definition at line 1155 of file jurassic.h.

◆ SELECT_TIMER

#define SELECT_TIMER (   id,
  group 
)     {timer_group(id, group, 0);}

Switch to a named aggregated timer.

Stops the previously selected aggregated timer, accumulates its runtime, and starts timing the new id within the given group.

Parameters
[in]idIdentifier of the timer to activate.
[in]groupGroup label used for coarse runtime summaries.
See also
timer_group, PRINT_TIMERS

Definition at line 1189 of file jurassic.h.

◆ PRINT_TIMERS

#define PRINT_TIMERS    {timer_group("END", "END", 1);}

Print aggregated timer statistics.

Writes accumulated per-timer and per-group runtimes to the log.

See also
timer_group, SELECT_TIMER

Definition at line 1199 of file jurassic.h.

◆ TOK

#define TOK (   line,
  tok,
  format,
  var 
)
Value:
{ \
if(((tok)=strtok((line), " \t"))) { \
if(sscanf(tok, format, &(var))!=1) continue; \
} else ERRMSG("Error while reading!"); \
}
#define ERRMSG(...)
Print an error message with contextual information and terminate the program.
Definition: jurassic.h:1356

Tokenize a string and parse a variable.

Splits a text line into tokens separated by spaces or tabs, and reads a value from the first token using sscanf() and the provided format. If tokenization or parsing fails, an error message is printed.

Parameters
[in,out]lineInput string buffer to tokenize (modified by strtok()).
[out]tokPointer to token string.
[in]formatFormat string for sscanf().
[out]varVariable to store parsed value.
Note
Uses strtok() internally and modifies the input buffer.
See also
FREAD, FWRITE
Author
Lars Hoffmann

Definition at line 1220 of file jurassic.h.

◆ USAGE

#define USAGE
Value:
do { \
int iusage; \
for (iusage = 1; iusage < argc; iusage++) \
if (!strcmp(argv[iusage], "-h") \
|| !strcmp(argv[iusage], "--help")) { \
usage(); \
return EXIT_SUCCESS; \
} \
} while (0)

Print usage information on -h or --help.

Calls the local usage() function and exits successfully when any command argument is -h or --help.

Note
This macro expects local argc and argv variables and a local usage() function.
Author
Lars Hoffmann

Definition at line 1237 of file jurassic.h.

◆ LOGLEV

#define LOGLEV   2

Level of log messages (0=none, 1=basic, 2=detailed, 3=debug).

Definition at line 1254 of file jurassic.h.

◆ LOG

#define LOG (   level,
  ... 
)
Value:
{ \
if(level >= 2) \
printf(" "); \
if(level <= LOGLEV) { \
printf(__VA_ARGS__); \
printf("\n"); \
} \
}
#define LOGLEV
Level of log messages (0=none, 1=basic, 2=detailed, 3=debug).
Definition: jurassic.h:1254

Print a log message with a specified logging level.

This macro prints a formatted log message to the standard output if the specified logging level meets certain conditions. The message will be indented if the logging level is greater than or equal to 2.

Parameters
levelThe logging level of the message. This should be an integer value.
...The formatted message string and its arguments, similar to printf.

The LOG macro provides a simple way to log messages with different levels of importance. The message is only printed if the specified level is less than or equal to the pre-defined LOGLEV macro. If the level is greater than or equal to 2, the message is preceded by two spaces for indentation.

The macro expands to a block of code that:

  • Checks if the level is greater than or equal to 2, and if so, prints two spaces.
  • Checks if the level is less than or equal to LOGLEV, and if so, prints the formatted message followed by a newline.
Note
The LOGLEV macro must be defined with an appropriate logging level before using the LOG macro.
Author
Lars Hoffmann

Definition at line 1286 of file jurassic.h.

◆ WARN

#define WARN (   ...)
Value:
{ \
printf("\nWarning (%s, %s, l%d): ", __FILE__, __func__, __LINE__); \
LOG(0, __VA_ARGS__); \
}

Print a warning message with contextual information.

This macro prints a formatted warning message to the standard output, including the file name, function name, and line number where the warning occurred. The message is then passed to the LOG macro with a logging level of 0.

Parameters
...The formatted warning message string and its arguments, similar to printf.

The WARN macro is used to print warning messages with additional context about where the warning was triggered. The message includes the following contextual information:

  • The name of the source file where the macro is called (__FILE__).
  • The name of the function where the macro is called (__func__).
  • The line number in the source file where the macro is called (__LINE__).

After printing this contextual information, the macro uses the LOG macro with a logging level of 0 to print the actual warning message. This ensures that warning messages are always logged, regardless of the value of LOGLEV.

Note
The LOG macro must be defined before using the WARN macro.
Author
Lars Hoffmann

Definition at line 1323 of file jurassic.h.

◆ ERRMSG

#define ERRMSG (   ...)
Value:
{ \
printf("\nError (%s, %s, l%d): ", __FILE__, __func__, __LINE__); \
LOG(0, __VA_ARGS__); \
exit(EXIT_FAILURE); \
}

Print an error message with contextual information and terminate the program.

This macro prints a formatted error message to the standard output, including the file name, function name, and line number where the error occurred. After printing the message, the program is terminated with an exit status indicating failure.

Parameters
...The formatted error message string and its arguments, similar to printf.

The ERRMSG macro is used to report critical errors that require the program to terminate immediately. The message includes the following contextual information:

  • The name of the source file where the macro is called (__FILE__).
  • The name of the function where the macro is called (__func__).
  • The line number in the source file where the macro is called (__LINE__).

After printing this contextual information, the macro uses the LOG macro with a logging level of 0 to print the actual error message. Finally, the program exits with a failure status (EXIT_FAILURE).

Note
The LOG macro must be defined before using the ERRMSG macro.
Author
Lars Hoffmann

Definition at line 1356 of file jurassic.h.

◆ PRINT

#define PRINT (   format,
  var 
)
Value:
printf("Print (%s, %s, l%d): %s= "format"\n", \
__FILE__, __func__, __LINE__, #var, var);

Print the value of a variable with contextual information.

This macro prints the value of a variable to the standard output, including the file name, function name, and line number where the macro is called. The output also includes the variable's name and value in a formatted string.

Parameters
formatThe format string used to print the variable's value, similar to printf.
varThe variable to be printed.

The PRINT macro is used to output the value of a variable along with additional context about where the macro is called. The message includes:

  • The name of the source file where the macro is called (__FILE__).
  • The name of the function where the macro is called (__func__).
  • The line number in the source file where the macro is called (__LINE__).
  • The name of the variable being printed (#var).
  • The value of the variable, formatted according to the provided format string (format).

This macro is particularly useful for debugging purposes, providing a convenient way to trace variable values and their locations in the code.

Note
The format string must be compatible with the type of the variable being printed.
Author
Lars Hoffmann

Definition at line 1391 of file jurassic.h.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
FORMOD_STATUS_OK 
FORMOD_STATUS_RFM_UNSUPPORTED 
FORMOD_STATUS_FOV_DATA_MISSING 
FORMOD_STATUS_OBSERVER_BELOW_SURFACE 
FORMOD_STATUS_TOO_MANY_LOS_POINTS 

Definition at line 158 of file jurassic.h.

158 {
164};
@ FORMOD_STATUS_TOO_MANY_LOS_POINTS
Definition: jurassic.h:163
@ FORMOD_STATUS_OK
Definition: jurassic.h:159
@ FORMOD_STATUS_FOV_DATA_MISSING
Definition: jurassic.h:161
@ FORMOD_STATUS_RFM_UNSUPPORTED
Definition: jurassic.h:160
@ FORMOD_STATUS_OBSERVER_BELOW_SURFACE
Definition: jurassic.h:162

Function Documentation

◆ analyze_avk()

void analyze_avk ( const ret_t *  ret,
const ctl_t *  ctl,
const atm_t *  atm,
const int *  iqa,
const int *  ipa,
const gsl_matrix *  avk 
)

Analyze averaging kernel (AVK) matrix for retrieval diagnostics.

Decomposes and evaluates the averaging kernel matrix \(\mathbf{A}\) to quantify the retrieval sensitivity and vertical resolution for each retrieved quantity (pressure, temperature, trace gases, extinction, etc.). The results are written to diagnostic atmospheric files for visualization.

Parameters
[in]retRetrieval control and configuration structure (ret_t).
[in]ctlGlobal control structure (ctl_t) defining retrieval setup and quantities.
[in]atmRetrieved atmospheric state structure (atm_t).
[in]iqaArray mapping state vector indices to physical quantities (e.g., IDXP, IDXT, IDXQ(...)).
[in]ipaArray mapping state vector indices to atmospheric grid points.
[in]avkAveraging kernel matrix \(\mathbf{A}\) (gsl_matrix, n×n).

The averaging kernel matrix \(\mathbf{A}\) describes the sensitivity of the retrieved state \(\hat{x}\) to the true state \(x\):

\[ \hat{x} - x_a = \mathbf{A} (x - x_a) \]

where \(x_a\) is the a priori state.
This function separates and evaluates:

  • Contribution profiles: diagonal dominance or total response (sensitivity).
  • Resolution profiles: width or spread of the averaging kernels.

Internally, this function:

  1. Identifies submatrices of \(\mathbf{A}\) corresponding to each physical quantity (pressure, temperature, VMRs, extinction, clouds, surface).
  2. Calls analyze_avk_quantity() for each retrieved parameter type to compute quantitative measures of contribution and resolution.
  3. Writes the results as atmospheric profiles:
    • atm_cont.tab — contribution functions (sensitivity).
    • atm_res.tab — resolution functions (vertical response width).
See also
analyze_avk_quantity, write_atm, set_cov_apr, set_cov_meas
Note
  • Submatrices are identified by matching the quantity index iqa[i] to the quantity constants (e.g., IDXT, IDXQ(ig), etc.).
  • Cloud and surface quantities are treated as scalar elements.
  • Output files are written to the retrieval working directory (ret->dir).
Warning
  • The averaging kernel must be fully computed and dimensionally consistent with the state vector before calling this function.
  • File writing will overwrite existing diagnostics in ret->dir.
Author
Lars Hoffmann

Definition at line 29 of file jurassic.c.

35 {
36
37 /* Allocate... */
38 atm_t *atm_cont, *atm_res;
39 ALLOC(atm_cont, atm_t, 1);
40 ALLOC(atm_res, atm_t, 1);
41
42 /* Get sizes... */
43 const size_t n = avk->size1;
44
45 /* Find sub-matrices for different quantities... */
46 size_t n0[NQ], n1[NQ];
47 for (int iq = 0; iq < NQ; iq++) {
48 n0[iq] = N;
49 for (size_t i = 0; i < n; i++) {
50 if (iqa[i] == iq && n0[iq] == N)
51 n0[iq] = i;
52 if (iqa[i] == iq)
53 n1[iq] = i - n0[iq] + 1;
54 }
55 }
56
57 /* Initialize... */
58 copy_atm(ctl, atm_cont, atm, 1);
59 copy_atm(ctl, atm_res, atm, 1);
60
61 /* Analyze quantities... */
62 analyze_avk_quantity(avk, IDXP, ipa, n0, n1, atm_cont->p, atm_res->p);
63 analyze_avk_quantity(avk, IDXT, ipa, n0, n1, atm_cont->t, atm_res->t);
64 for (int ig = 0; ig < ctl->ng; ig++)
65 analyze_avk_quantity(avk, IDXQ(ig), ipa, n0, n1,
66 atm_cont->q[ig], atm_res->q[ig]);
67 for (int iw = 0; iw < ctl->nw; iw++)
68 analyze_avk_quantity(avk, IDXK(iw), ipa, n0, n1,
69 atm_cont->k[iw], atm_res->k[iw]);
70 analyze_avk_quantity(avk, IDXCLZ, ipa, n0, n1, &atm_cont->clz,
71 &atm_res->clz);
72 analyze_avk_quantity(avk, IDXCLDZ, ipa, n0, n1, &atm_cont->cldz,
73 &atm_res->cldz);
74 for (int icl = 0; icl < ctl->ncl; icl++)
75 analyze_avk_quantity(avk, IDXCLK(icl), ipa, n0, n1,
76 &atm_cont->clk[icl], &atm_res->clk[icl]);
77 analyze_avk_quantity(avk, IDXSFT, ipa, n0, n1, &atm_cont->sft,
78 &atm_res->sft);
79 for (int isf = 0; isf < ctl->nsf; isf++)
80 analyze_avk_quantity(avk, IDXSFEPS(isf), ipa, n0, n1,
81 &atm_cont->sfeps[isf], &atm_res->sfeps[isf]);
82
83 /* Write results to disk... */
84 const char *dirname;
85 int profile;
86 const char *filename =
87 shared_io_output_target(ret, ret->shared_io_atm_cont_file, "atm_cont.tab",
88 &dirname, &profile);
89 write_atm(dirname, filename, ctl, atm_cont, profile);
91 "atm_res.tab", &dirname, &profile);
92 write_atm(dirname, filename, ctl, atm_res, profile);
93
94 /* Free... */
95 free(atm_cont);
96 free(atm_res);
97}
void write_atm(const char *dirname, const char *filename, const ctl_t *ctl, const atm_t *atm, int profile)
Write atmospheric data to a file.
Definition: jurassic.c:7308
void analyze_avk_quantity(const gsl_matrix *avk, const int iq, const int *ipa, const size_t *n0, const size_t *n1, double *cont, double *res)
Analyze averaging kernel submatrix for a specific retrieved quantity.
Definition: jurassic.c:101
const char * shared_io_output_target(const ret_t *ret, const char *shared_file, const char *legacy_file, const char **dirname, int *profile)
Resolve retrieval output target for legacy-directory and shared-file modes.
Definition: jurassic.c:6861
void copy_atm(const ctl_t *ctl, atm_t *atm_dest, const atm_t *atm_src, const int init)
Copy or initialize atmospheric profile data.
Definition: jurassic.c:3114
#define N
Maximum size of state vector.
Definition: jurassic.h:286
#define IDXCLZ
Index for cloud layer height.
Definition: jurassic.h:391
#define IDXCLDZ
Index for cloud layer depth.
Definition: jurassic.h:394
#define IDXK(iw)
Indices for extinction.
Definition: jurassic.h:388
#define NQ
Maximum number of quantities.
Definition: jurassic.h:321
#define IDXSFT
Index for surface layer temperature.
Definition: jurassic.h:400
#define IDXSFEPS(isf)
Indices for surface layer emissivity.
Definition: jurassic.h:403
#define IDXCLK(icl)
Indices for cloud layer extinction.
Definition: jurassic.h:397
#define IDXP
Index for pressure.
Definition: jurassic.h:379
#define ALLOC(ptr, type, n)
Allocate memory for an array.
Definition: jurassic.h:426
#define IDXQ(ig)
Indices for volume mixing ratios.
Definition: jurassic.h:385
#define IDXT
Index for temperature.
Definition: jurassic.h:382
Atmospheric profile data.
Definition: jurassic.h:1406
double sfeps[NSF]
Surface emissivity.
Definition: jurassic.h:1448
double k[NW][NP]
Extinction [km^-1].
Definition: jurassic.h:1433
double t[NP]
Temperature [K].
Definition: jurassic.h:1427
double clz
Cloud layer height [km].
Definition: jurassic.h:1436
double cldz
Cloud layer depth [km].
Definition: jurassic.h:1439
double sft
Surface temperature [K].
Definition: jurassic.h:1445
double clk[NCL]
Cloud layer extinction [km^-1].
Definition: jurassic.h:1442
double q[NG][NP]
Volume mixing ratio [ppv].
Definition: jurassic.h:1430
double p[NP]
Pressure [hPa].
Definition: jurassic.h:1424
int nw
Number of spectral windows.
Definition: jurassic.h:1486
int ng
Number of emitters.
Definition: jurassic.h:1462
int ncl
Number of cloud layer spectral grid points.
Definition: jurassic.h:1492
int nsf
Number of surface layer spectral grid points.
Definition: jurassic.h:1498
char shared_io_atm_res_file[LEN]
Optional shared averaging-kernel resolution output file.
Definition: jurassic.h:1866
char shared_io_atm_cont_file[LEN]
Optional shared averaging-kernel contribution output file.
Definition: jurassic.h:1863
Here is the call graph for this function:

◆ analyze_avk_quantity()

void analyze_avk_quantity ( const gsl_matrix *  avk,
const int  iq,
const int *  ipa,
const size_t *  n0,
const size_t *  n1,
double *  cont,
double *  res 
)

Analyze averaging kernel submatrix for a specific retrieved quantity.

Computes the contribution (sensitivity) and resolution (information density) profiles for a given physical quantity from its corresponding submatrix of the full averaging kernel matrix \(\mathbf{A}\).

Parameters
[in]avkAveraging kernel matrix \(\mathbf{A}\) (gsl_matrix, n×n), describing the sensitivity of the retrieved state to the true state.
[in]iqQuantity index identifier (e.g., IDXP, IDXT, IDXQ(ig), IDXK(iw), IDXCLZ, etc.).
[in]ipaArray mapping state vector indices to atmospheric grid indices.
[in]n0Array of starting indices for each quantity sub-block in the state vector.
[in]n1Array of lengths (number of elements) for each quantity sub-block.
[out]contArray of contribution values, representing the total sensitivity or response of the retrieval at each grid point.
[out]resArray of resolution measures, representing the vertical information density or averaging kernel width at each grid point.

For a given quantity \(q\), the function extracts its corresponding block \(\mathbf{A}_q\) from the full averaging kernel matrix and computes:

  • Contribution function

    \[ \text{cont}_i = \sum_j A_{ij}^{(q)} \]

    giving the total response of retrieved element \(i\) to perturbations in all true elements \(j\) of the same quantity.
  • Resolution (information density)

    \[ \text{res}_i = \frac{1}{A_{ii}^{(q)}} \]

    approximating the degree of vertical resolution or smoothing at level \(i\).

The results are stored in the provided arrays cont[] and res[], indexed according to the atmospheric profile index via ipa[].

See also
analyze_avk, write_atm, set_cov_apr
Note
  • Only elements associated with the specified quantity index (iq) are processed.
  • The function assumes the averaging kernel matrix is square and symmetric.
  • The contribution and resolution arrays must be preallocated to at least the number of atmospheric grid points (atm->np).
Warning
  • If the diagonal element A_ii is zero or near-zero, the corresponding resolution value may be undefined or numerically unstable.
  • Input indices n0[iq] and n1[iq] must have been computed by analyze_avk().
Author
Lars Hoffmann

Definition at line 101 of file jurassic.c.

108 {
109
110 /* Loop over state vector elements... */
111 if (n0[iq] < N)
112 for (size_t i = 0; i < n1[iq]; i++) {
113
114 /* Get area of averaging kernel... */
115 for (size_t j = 0; j < n1[iq]; j++)
116 cont[ipa[n0[iq] + i]] += gsl_matrix_get(avk, n0[iq] + i, n0[iq] + j);
117
118 /* Get information density... */
119 res[ipa[n0[iq] + i]] = 1 / gsl_matrix_get(avk, n0[iq] + i, n0[iq] + i);
120 }
121}

◆ atm2x()

size_t atm2x ( const ctl_t *  ctl,
const atm_t *  atm,
gsl_vector *  x,
int *  iqa,
int *  ipa 
)

Convert atmospheric data to state vector elements.

Extracts selected quantities from an atmospheric profile (atm_t) according to retrieval settings in ctl_t, and appends them to the state vector x. For each included quantity, the function also stores its quantity index (iqa) and profile index (ipa).

The function respects retrieval altitude limits defined in ctl (e.g., retp_zmin/zmax, rett_zmin/zmax, etc.) and includes only variables flagged for retrieval (e.g., ret_clz, ret_sft, etc.).

Parameters
[in]ctlControl settings defining retrieval configuration and limits.
[in]atmAtmospheric profile data to extract from.
[out]xGSL vector to store state-vector elements.
[out]iqaQuantity index array corresponding to elements in x.
[out]ipaProfile index array corresponding to elements in x.
Returns
Number of elements written to the state vector.
Note
Internally calls atm2x_help() to append individual values.
See also
atm_t, ctl_t, atm2x_help
Author
Lars Hoffmann

Definition at line 125 of file jurassic.c.

130 {
131
132 size_t n = 0;
133
134 /* Add pressure... */
135 for (int ip = 0; ip < atm->np; ip++)
136 if (atm->z[ip] >= ctl->retp_zmin && atm->z[ip] <= ctl->retp_zmax)
137 atm2x_help(atm->p[ip], IDXP, ip, x, iqa, ipa, &n);
138
139 /* Add temperature... */
140 for (int ip = 0; ip < atm->np; ip++)
141 if (atm->z[ip] >= ctl->rett_zmin && atm->z[ip] <= ctl->rett_zmax)
142 atm2x_help(atm->t[ip], IDXT, ip, x, iqa, ipa, &n);
143
144 /* Add volume mixing ratios... */
145 for (int ig = 0; ig < ctl->ng; ig++)
146 for (int ip = 0; ip < atm->np; ip++)
147 if (atm->z[ip] >= ctl->retq_zmin[ig]
148 && atm->z[ip] <= ctl->retq_zmax[ig])
149 atm2x_help(atm->q[ig][ip], IDXQ(ig), ip, x, iqa, ipa, &n);
150
151 /* Add extinction... */
152 for (int iw = 0; iw < ctl->nw; iw++)
153 for (int ip = 0; ip < atm->np; ip++)
154 if (atm->z[ip] >= ctl->retk_zmin[iw]
155 && atm->z[ip] <= ctl->retk_zmax[iw])
156 atm2x_help(atm->k[iw][ip], IDXK(iw), ip, x, iqa, ipa, &n);
157
158 /* Add cloud variables... */
159 if (ctl->ret_clz)
160 atm2x_help(atm->clz, IDXCLZ, 0, x, iqa, ipa, &n);
161 if (ctl->ret_cldz)
162 atm2x_help(atm->cldz, IDXCLDZ, 0, x, iqa, ipa, &n);
163 if (ctl->ret_clk)
164 for (int icl = 0; icl < ctl->ncl; icl++)
165 atm2x_help(atm->clk[icl], IDXCLK(icl), 0, x, iqa, ipa, &n);
166
167 /* Add surface variables... */
168 if (ctl->ret_sft)
169 atm2x_help(atm->sft, IDXSFT, 0, x, iqa, ipa, &n);
170 if (ctl->ret_sfeps)
171 for (int isf = 0; isf < ctl->nsf; isf++)
172 atm2x_help(atm->sfeps[isf], IDXSFEPS(isf), 0, x, iqa, ipa, &n);
173
174 return n;
175}
void atm2x_help(const double value, const int value_iqa, const int value_ip, gsl_vector *x, int *iqa, int *ipa, size_t *n)
Append a single atmospheric value to the state vector.
Definition: jurassic.c:179
int np
Number of data points.
Definition: jurassic.h:1409
double z[NP]
Altitude [km].
Definition: jurassic.h:1415
double retp_zmin
Minimum altitude for pressure retrieval [km].
Definition: jurassic.h:1561
double retk_zmax[NW]
Maximum altitude for extinction retrieval [km].
Definition: jurassic.h:1582
double rett_zmax
Maximum altitude for temperature retrieval [km].
Definition: jurassic.h:1570
int ret_sfeps
Retrieve surface layer emissivity (0=no, 1=yes).
Definition: jurassic.h:1597
int ret_sft
Retrieve surface layer temperature (0=no, 1=yes).
Definition: jurassic.h:1594
int ret_clz
Retrieve cloud layer height (0=no, 1=yes).
Definition: jurassic.h:1585
double retq_zmax[NG]
Maximum altitude for volume mixing ratio retrieval [km].
Definition: jurassic.h:1576
double retq_zmin[NG]
Minimum altitude for volume mixing ratio retrieval [km].
Definition: jurassic.h:1573
double rett_zmin
Minimum altitude for temperature retrieval [km].
Definition: jurassic.h:1567
double retk_zmin[NW]
Minimum altitude for extinction retrieval [km].
Definition: jurassic.h:1579
int ret_clk
Retrieve cloud layer extinction (0=no, 1=yes).
Definition: jurassic.h:1591
int ret_cldz
Retrieve cloud layer depth (0=no, 1=yes).
Definition: jurassic.h:1588
double retp_zmax
Maximum altitude for pressure retrieval [km].
Definition: jurassic.h:1564
Here is the call graph for this function:

◆ atm2x_help()

void atm2x_help ( const double  value,
const int  value_iqa,
const int  value_ip,
gsl_vector *  x,
int *  iqa,
int *  ipa,
size_t *  n 
)

Append a single atmospheric value to the state vector.

Helper routine for atm2x(). Inserts one scalar value and its corresponding quantity and profile indices into the state vector and tracking arrays, then increments the element counter.

Parameters
[in]valueValue to add to the state vector.
[in]value_iqaQuantity index (e.g., IDXP, IDXT, etc.).
[in]value_ipProfile index within the atmospheric profile.
[out]xGSL vector containing state-vector elements (may be NULL).
[out]iqaQuantity index array corresponding to x (may be NULL).
[out]ipaProfile index array corresponding to x (may be NULL).
[in,out]nCurrent number of elements in the state vector; incremented on return.
Note
This function performs no range checking and assumes valid array bounds.
See also
atm2x
Author
Lars Hoffmann

Definition at line 179 of file jurassic.c.

186 {
187
188 /* Add element to state vector... */
189 if (x != NULL)
190 gsl_vector_set(x, *n, value);
191 if (iqa != NULL)
192 iqa[*n] = value_iqa;
193 if (ipa != NULL)
194 ipa[*n] = value_ip;
195 (*n)++;
196}

◆ cart2geo()

void cart2geo ( const double *  x,
double *  z,
double *  lon,
double *  lat 
)

Converts Cartesian coordinates to geographic coordinates.

This function converts a point from Cartesian coordinates (x, y, z) to geographic coordinates (longitude, latitude, and altitude). It uses the spherical Earth approximation for the conversion.

Parameters
xPointer to an array containing the Cartesian coordinates (x, y, z) in kilometers.
zPointer to a double where the computed altitude (above the reference ellipsoid) will be stored, in kilometers.
lonPointer to a double where the computed longitude (in degrees) will be stored.
latPointer to a double where the computed latitude (in degrees) will be stored.
Author
Lars Hoffmann

Definition at line 200 of file jurassic.c.

204 {
205
206 const double radius = NORM(x);
207
208 *lat = RAD2DEG(asin(x[2] / radius));
209 *lon = RAD2DEG(atan2(x[1], x[0]));
210 *z = radius - RE;
211}
#define RE
Mean radius of Earth [km].
Definition: jurassic.h:232
#define NORM(a)
Compute the norm (magnitude) of a 3D vector.
Definition: jurassic.h:1004
#define RAD2DEG(rad)
Convert radians to degrees.
Definition: jurassic.h:1078

◆ climatology()

void climatology ( const ctl_t *  ctl,
atm_t *  atm 
)

Initializes atmospheric climatology profiles.

This function populates the atmospheric state (atm) with standard climatological profiles of pressure, temperature, and trace gas concentrations (e.g., H2O, CH4, CO, O3, etc.) as a function of altitude. The profiles are based on reference climatological datasets and are used for atmospheric modeling and radiative transfer calculations.

Parameters
[in]ctlControl parameters structure.
[out]atmAtmospheric state structure to be populated with climatological data.
Author
Lars Hoffmann

Definition at line 215 of file jurassic.c.

217 {
218
219 static const double z[121] = {
220 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
221 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
222 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
223 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
224 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
225 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
226 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120
227 };
228
229 static const double pre[121] = {
230 1017, 901.083, 796.45, 702.227, 617.614, 541.644, 473.437, 412.288,
231 357.603, 308.96, 265.994, 228.348, 195.619, 167.351, 143.039, 122.198,
232 104.369, 89.141, 76.1528, 65.0804, 55.641, 47.591, 40.7233, 34.8637,
233 29.8633, 25.5956, 21.9534, 18.8445, 16.1909, 13.9258, 11.9913,
234 10.34, 8.92988, 7.72454, 6.6924, 5.80701, 5.04654, 4.39238, 3.82902,
235 3.34337, 2.92413, 2.56128, 2.2464, 1.97258, 1.73384, 1.52519, 1.34242,
236 1.18197, 1.04086, 0.916546, 0.806832, 0.709875, 0.624101, 0.548176,
237 0.480974, 0.421507, 0.368904, 0.322408, 0.281386, 0.245249, 0.213465,
238 0.185549, 0.161072, 0.139644, 0.120913, 0.104568, 0.0903249, 0.0779269,
239 0.0671493, 0.0577962, 0.0496902, 0.0426736, 0.0366093, 0.0313743,
240 0.0268598, 0.0229699, 0.0196206, 0.0167399, 0.0142646, 0.0121397,
241 0.0103181, 0.00875775, 0.00742226, 0.00628076, 0.00530519, 0.00447183,
242 0.00376124, 0.00315632, 0.00264248, 0.00220738, 0.00184003, 0.00153095,
243 0.00127204, 0.00105608, 0.000876652, 0.00072798, 0.00060492,
244 0.000503201, 0.000419226, 0.000349896, 0.000292659, 0.000245421,
245 0.000206394, 0.000174125, 0.000147441, 0.000125333, 0.000106985,
246 9.173e-05, 7.90172e-05, 6.84172e-05, 5.95574e-05, 5.21183e-05,
247 4.58348e-05, 4.05127e-05, 3.59987e-05, 3.21583e-05, 2.88718e-05,
248 2.60322e-05, 2.35687e-05, 2.14263e-05, 1.95489e-05
249 };
250
251 static const double tem[121] = {
252 285.14, 279.34, 273.91, 268.3, 263.24, 256.55, 250.2, 242.82, 236.17,
253 229.87, 225.04, 221.19, 218.85, 217.19, 216.2, 215.68, 215.42, 215.55,
254 215.92, 216.4, 216.93, 217.45, 218, 218.68, 219.39, 220.25, 221.3,
255 222.41, 223.88, 225.42, 227.2, 229.52, 231.89, 234.51, 236.85, 239.42,
256 241.94, 244.57, 247.36, 250.32, 253.34, 255.82, 258.27, 260.39,
257 262.03, 263.45, 264.2, 264.78, 264.67, 264.38, 263.24, 262.03, 260.02,
258 258.09, 255.63, 253.28, 250.43, 247.81, 245.26, 242.77, 240.38,
259 237.94, 235.79, 233.53, 231.5, 229.53, 227.6, 225.62, 223.77, 222.06,
260 220.33, 218.69, 217.18, 215.64, 214.13, 212.52, 210.86, 209.25,
261 207.49, 205.81, 204.11, 202.22, 200.32, 198.39, 195.92, 193.46,
262 190.94, 188.31, 185.82, 183.57, 181.43, 179.74, 178.64, 178.1, 178.25,
263 178.7, 179.41, 180.67, 182.31, 184.18, 186.6, 189.53, 192.66, 196.54,
264 201.13, 205.93, 211.73, 217.86, 225, 233.53, 242.57, 252.14, 261.48,
265 272.97, 285.26, 299.12, 312.2, 324.17, 338.34, 352.56, 365.28
266 };
267
268 static const double c2h2[121] = {
269 1.352e-09, 2.83e-10, 1.269e-10, 6.926e-11, 4.346e-11, 2.909e-11,
270 2.014e-11, 1.363e-11, 8.71e-12, 5.237e-12, 2.718e-12, 1.375e-12,
271 5.786e-13, 2.16e-13, 7.317e-14, 2.551e-14, 1.055e-14, 4.758e-15,
272 2.056e-15, 7.703e-16, 2.82e-16, 1.035e-16, 4.382e-17, 1.946e-17,
273 9.638e-18, 5.2e-18, 2.811e-18, 1.494e-18, 7.925e-19, 4.213e-19,
274 1.998e-19, 8.78e-20, 3.877e-20, 1.728e-20, 7.743e-21, 3.536e-21,
275 1.623e-21, 7.508e-22, 3.508e-22, 1.65e-22, 7.837e-23, 3.733e-23,
276 1.808e-23, 8.77e-24, 4.285e-24, 2.095e-24, 1.032e-24, 5.082e-25,
277 2.506e-25, 1.236e-25, 6.088e-26, 2.996e-26, 1.465e-26, 0, 0, 0,
278 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
279 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
280 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
281 };
282
283 static const double c2h6[121] = {
284 2.667e-09, 2.02e-09, 1.658e-09, 1.404e-09, 1.234e-09, 1.109e-09,
285 1.012e-09, 9.262e-10, 8.472e-10, 7.71e-10, 6.932e-10, 6.216e-10,
286 5.503e-10, 4.87e-10, 4.342e-10, 3.861e-10, 3.347e-10, 2.772e-10,
287 2.209e-10, 1.672e-10, 1.197e-10, 8.536e-11, 5.783e-11, 3.846e-11,
288 2.495e-11, 1.592e-11, 1.017e-11, 6.327e-12, 3.895e-12, 2.403e-12,
289 1.416e-12, 8.101e-13, 4.649e-13, 2.686e-13, 1.557e-13, 9.14e-14,
290 5.386e-14, 3.19e-14, 1.903e-14, 1.14e-14, 6.875e-15, 4.154e-15,
291 2.538e-15, 1.553e-15, 9.548e-16, 5.872e-16, 3.63e-16, 2.244e-16,
292 1.388e-16, 8.587e-17, 5.308e-17, 3.279e-17, 2.017e-17, 1.238e-17,
293 7.542e-18, 4.585e-18, 2.776e-18, 1.671e-18, 9.985e-19, 5.937e-19,
294 3.518e-19, 2.07e-19, 1.215e-19, 7.06e-20, 4.097e-20, 2.37e-20,
295 1.363e-20, 7.802e-21, 4.441e-21, 2.523e-21, 1.424e-21, 8.015e-22,
296 4.497e-22, 2.505e-22, 1.391e-22, 7.691e-23, 4.238e-23, 2.331e-23,
297 1.274e-23, 6.929e-24, 3.752e-24, 2.02e-24, 1.083e-24, 5.774e-25,
298 3.041e-25, 1.593e-25, 8.308e-26, 4.299e-26, 2.195e-26, 1.112e-26,
299 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
300 0, 0, 0, 0, 0, 0, 0, 0, 0
301 };
302
303 static const double ccl4[121] = {
304 1.075e-10, 1.075e-10, 1.075e-10, 1.075e-10, 1.075e-10, 1.075e-10,
305 1.075e-10, 1.075e-10, 1.075e-10, 1.06e-10, 1.024e-10, 9.69e-11,
306 8.93e-11, 8.078e-11, 7.213e-11, 6.307e-11, 5.383e-11, 4.49e-11,
307 3.609e-11, 2.705e-11, 1.935e-11, 1.385e-11, 8.35e-12, 5.485e-12,
308 3.853e-12, 2.22e-12, 5.875e-13, 3.445e-13, 1.015e-13, 6.075e-14,
309 4.383e-14, 2.692e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14,
310 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14,
311 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14,
312 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14,
313 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14,
314 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14,
315 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14,
316 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14,
317 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14, 1e-14,
318 1e-14, 1e-14, 1e-14
319 };
320
321 static const double ch3oh[121] = {
322 5.01099e-10, 5.01099e-10, 5.01099e-10, 5.01099e-10, 5.01099e-10,
323 5.01099e-10, 5.50999e-10, 5.7313e-10, 5.75638e-10, 5.4086e-10,
324 4.77601e-10, 4.12907e-10, 3.6274e-10, 3.26448e-10, 2.9706e-10,
325 2.27698e-10, 1.96999e-10, 1.66212e-10, 1.17941e-10, 1.19844e-10,
326 1.11211e-10, 1.02714e-10, 9.86138e-11, 9.45133e-11, 9.04127e-11,
327 8.05243e-11, 6.3678e-11, 4.68317e-11, 4.00618e-11, 3.95786e-11,
328 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11,
329 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11,
330 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11,
331 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11,
332 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11,
333 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11,
334 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11,
335 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11,
336 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11,
337 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11,
338 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11,
339 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11,
340 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11,
341 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11,
342 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11,
343 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11,
344 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11,
345 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11, 3.95786e-11,
346 3.95786e-11
347 };
348
349 static const double ch4[121] = {
350 1.864e-06, 1.835e-06, 1.819e-06, 1.805e-06, 1.796e-06, 1.788e-06,
351 1.782e-06, 1.776e-06, 1.769e-06, 1.761e-06, 1.749e-06, 1.734e-06,
352 1.716e-06, 1.692e-06, 1.654e-06, 1.61e-06, 1.567e-06, 1.502e-06,
353 1.433e-06, 1.371e-06, 1.323e-06, 1.277e-06, 1.232e-06, 1.188e-06,
354 1.147e-06, 1.108e-06, 1.07e-06, 1.027e-06, 9.854e-07, 9.416e-07,
355 8.933e-07, 8.478e-07, 7.988e-07, 7.515e-07, 7.07e-07, 6.64e-07,
356 6.239e-07, 5.864e-07, 5.512e-07, 5.184e-07, 4.87e-07, 4.571e-07,
357 4.296e-07, 4.04e-07, 3.802e-07, 3.578e-07, 3.383e-07, 3.203e-07,
358 3.032e-07, 2.889e-07, 2.76e-07, 2.635e-07, 2.519e-07, 2.409e-07,
359 2.302e-07, 2.219e-07, 2.144e-07, 2.071e-07, 1.999e-07, 1.93e-07,
360 1.862e-07, 1.795e-07, 1.731e-07, 1.668e-07, 1.607e-07, 1.548e-07,
361 1.49e-07, 1.434e-07, 1.38e-07, 1.328e-07, 1.277e-07, 1.227e-07,
362 1.18e-07, 1.134e-07, 1.089e-07, 1.046e-07, 1.004e-07, 9.635e-08,
363 9.245e-08, 8.867e-08, 8.502e-08, 8.15e-08, 7.809e-08, 7.48e-08,
364 7.159e-08, 6.849e-08, 6.55e-08, 6.262e-08, 5.98e-08, 5.708e-08,
365 5.448e-08, 5.194e-08, 4.951e-08, 4.72e-08, 4.5e-08, 4.291e-08,
366 4.093e-08, 3.905e-08, 3.729e-08, 3.563e-08, 3.408e-08, 3.265e-08,
367 3.128e-08, 2.996e-08, 2.87e-08, 2.76e-08, 2.657e-08, 2.558e-08,
368 2.467e-08, 2.385e-08, 2.307e-08, 2.234e-08, 2.168e-08, 2.108e-08,
369 2.05e-08, 1.998e-08, 1.947e-08, 1.902e-08, 1.86e-08, 1.819e-08,
370 1.782e-08
371 };
372
373 static const double clo[121] = {
374 7.419e-15, 1.061e-14, 1.518e-14, 2.195e-14, 3.175e-14, 4.666e-14,
375 6.872e-14, 1.03e-13, 1.553e-13, 2.375e-13, 3.664e-13, 5.684e-13,
376 8.915e-13, 1.402e-12, 2.269e-12, 4.125e-12, 7.501e-12, 1.257e-11,
377 2.048e-11, 3.338e-11, 5.44e-11, 8.846e-11, 1.008e-10, 1.082e-10,
378 1.157e-10, 1.232e-10, 1.312e-10, 1.539e-10, 1.822e-10, 2.118e-10,
379 2.387e-10, 2.687e-10, 2.875e-10, 3.031e-10, 3.23e-10, 3.648e-10,
380 4.117e-10, 4.477e-10, 4.633e-10, 4.794e-10, 4.95e-10, 5.104e-10,
381 5.259e-10, 5.062e-10, 4.742e-10, 4.443e-10, 4.051e-10, 3.659e-10,
382 3.305e-10, 2.911e-10, 2.54e-10, 2.215e-10, 1.927e-10, 1.675e-10,
383 1.452e-10, 1.259e-10, 1.09e-10, 9.416e-11, 8.119e-11, 6.991e-11,
384 6.015e-11, 5.163e-11, 4.43e-11, 3.789e-11, 3.24e-11, 2.769e-11,
385 2.361e-11, 2.011e-11, 1.71e-11, 1.453e-11, 1.233e-11, 1.045e-11,
386 8.851e-12, 7.48e-12, 6.316e-12, 5.326e-12, 4.487e-12, 3.778e-12,
387 3.176e-12, 2.665e-12, 2.234e-12, 1.87e-12, 1.563e-12, 1.304e-12,
388 1.085e-12, 9.007e-13, 7.468e-13, 6.179e-13, 5.092e-13, 4.188e-13,
389 3.442e-13, 2.816e-13, 2.304e-13, 1.885e-13, 1.542e-13, 1.263e-13,
390 1.035e-13, 8.5e-14, 7.004e-14, 5.783e-14, 4.795e-14, 4.007e-14,
391 3.345e-14, 2.792e-14, 2.33e-14, 1.978e-14, 1.686e-14, 1.438e-14,
392 1.234e-14, 1.07e-14, 9.312e-15, 8.131e-15, 7.164e-15, 6.367e-15,
393 5.67e-15, 5.088e-15, 4.565e-15, 4.138e-15, 3.769e-15, 3.432e-15,
394 3.148e-15
395 };
396
397 static const double clono2[121] = {
398 1.011e-13, 1.515e-13, 2.272e-13, 3.446e-13, 5.231e-13, 8.085e-13,
399 1.253e-12, 1.979e-12, 3.149e-12, 5.092e-12, 8.312e-12, 1.366e-11,
400 2.272e-11, 3.791e-11, 6.209e-11, 9.101e-11, 1.334e-10, 1.951e-10,
401 2.853e-10, 3.94e-10, 4.771e-10, 5.771e-10, 6.675e-10, 7.665e-10,
402 8.504e-10, 8.924e-10, 9.363e-10, 8.923e-10, 8.411e-10, 7.646e-10,
403 6.525e-10, 5.576e-10, 4.398e-10, 3.403e-10, 2.612e-10, 1.915e-10,
404 1.407e-10, 1.028e-10, 7.455e-11, 5.42e-11, 3.708e-11, 2.438e-11,
405 1.618e-11, 1.075e-11, 7.17e-12, 4.784e-12, 3.205e-12, 2.147e-12,
406 1.44e-12, 9.654e-13, 6.469e-13, 4.332e-13, 2.891e-13, 1.926e-13,
407 1.274e-13, 8.422e-14, 5.547e-14, 3.636e-14, 2.368e-14, 1.536e-14,
408 9.937e-15, 6.39e-15, 4.101e-15, 2.61e-15, 1.659e-15, 1.052e-15,
409 6.638e-16, 4.172e-16, 2.61e-16, 1.63e-16, 1.013e-16, 6.275e-17,
410 3.879e-17, 2.383e-17, 1.461e-17, 8.918e-18, 5.43e-18, 3.301e-18,
411 1.997e-18, 1.203e-18, 7.216e-19, 4.311e-19, 2.564e-19, 1.519e-19,
412 8.911e-20, 5.203e-20, 3.026e-20, 1.748e-20, 9.99e-21, 5.673e-21,
413 3.215e-21, 1.799e-21, 1.006e-21, 5.628e-22, 3.146e-22, 1.766e-22,
414 9.94e-23, 5.614e-23, 3.206e-23, 1.841e-23, 1.071e-23, 6.366e-24,
415 3.776e-24, 2.238e-24, 1.326e-24, 8.253e-25, 5.201e-25, 3.279e-25,
416 2.108e-25, 1.395e-25, 9.326e-26, 6.299e-26, 4.365e-26, 3.104e-26,
417 2.219e-26, 1.621e-26, 1.185e-26, 8.92e-27, 6.804e-27, 5.191e-27,
418 4.041e-27
419 };
420
421 static const double co[121] = {
422 1.907e-07, 1.553e-07, 1.362e-07, 1.216e-07, 1.114e-07, 1.036e-07,
423 9.737e-08, 9.152e-08, 8.559e-08, 7.966e-08, 7.277e-08, 6.615e-08,
424 5.884e-08, 5.22e-08, 4.699e-08, 4.284e-08, 3.776e-08, 3.274e-08,
425 2.845e-08, 2.479e-08, 2.246e-08, 2.054e-08, 1.991e-08, 1.951e-08,
426 1.94e-08, 2.009e-08, 2.1e-08, 2.201e-08, 2.322e-08, 2.45e-08,
427 2.602e-08, 2.73e-08, 2.867e-08, 2.998e-08, 3.135e-08, 3.255e-08,
428 3.352e-08, 3.426e-08, 3.484e-08, 3.53e-08, 3.593e-08, 3.671e-08,
429 3.759e-08, 3.945e-08, 4.192e-08, 4.49e-08, 5.03e-08, 5.703e-08,
430 6.538e-08, 7.878e-08, 9.644e-08, 1.196e-07, 1.498e-07, 1.904e-07,
431 2.422e-07, 3.055e-07, 3.804e-07, 4.747e-07, 5.899e-07, 7.272e-07,
432 8.91e-07, 1.071e-06, 1.296e-06, 1.546e-06, 1.823e-06, 2.135e-06,
433 2.44e-06, 2.714e-06, 2.967e-06, 3.189e-06, 3.391e-06, 3.58e-06,
434 3.773e-06, 4.022e-06, 4.346e-06, 4.749e-06, 5.199e-06, 5.668e-06,
435 6.157e-06, 6.688e-06, 7.254e-06, 7.867e-06, 8.539e-06, 9.26e-06,
436 1.009e-05, 1.119e-05, 1.228e-05, 1.365e-05, 1.506e-05, 1.641e-05,
437 1.784e-05, 1.952e-05, 2.132e-05, 2.323e-05, 2.531e-05, 2.754e-05,
438 3.047e-05, 3.459e-05, 3.922e-05, 4.439e-05, 4.825e-05, 5.077e-05,
439 5.34e-05, 5.618e-05, 5.909e-05, 6.207e-05, 6.519e-05, 6.845e-05,
440 6.819e-05, 6.726e-05, 6.622e-05, 6.512e-05, 6.671e-05, 6.862e-05,
441 7.048e-05, 7.264e-05, 7.3e-05, 7.3e-05, 7.3e-05, 7.3e-05, 7.3e-05
442 };
443
444 static const double cof2[121] = {
445 7.5e-14, 1.055e-13, 1.485e-13, 2.111e-13, 3.001e-13, 4.333e-13,
446 6.269e-13, 9.221e-13, 1.364e-12, 2.046e-12, 3.093e-12, 4.703e-12,
447 7.225e-12, 1.113e-11, 1.66e-11, 2.088e-11, 2.626e-11, 3.433e-11,
448 4.549e-11, 5.886e-11, 7.21e-11, 8.824e-11, 1.015e-10, 1.155e-10,
449 1.288e-10, 1.388e-10, 1.497e-10, 1.554e-10, 1.606e-10, 1.639e-10,
450 1.64e-10, 1.64e-10, 1.596e-10, 1.542e-10, 1.482e-10, 1.382e-10,
451 1.289e-10, 1.198e-10, 1.109e-10, 1.026e-10, 9.484e-11, 8.75e-11,
452 8.086e-11, 7.49e-11, 6.948e-11, 6.446e-11, 5.961e-11, 5.505e-11,
453 5.085e-11, 4.586e-11, 4.1e-11, 3.665e-11, 3.235e-11, 2.842e-11,
454 2.491e-11, 2.11e-11, 1.769e-11, 1.479e-11, 1.197e-11, 9.631e-12,
455 7.74e-12, 6.201e-12, 4.963e-12, 3.956e-12, 3.151e-12, 2.507e-12,
456 1.99e-12, 1.576e-12, 1.245e-12, 9.83e-13, 7.742e-13, 6.088e-13,
457 4.782e-13, 3.745e-13, 2.929e-13, 2.286e-13, 1.782e-13, 1.388e-13,
458 1.079e-13, 8.362e-14, 6.471e-14, 4.996e-14, 3.85e-14, 2.96e-14,
459 2.265e-14, 1.729e-14, 1.317e-14, 9.998e-15, 7.549e-15, 5.683e-15,
460 4.273e-15, 3.193e-15, 2.385e-15, 1.782e-15, 1.331e-15, 9.957e-16,
461 7.461e-16, 5.601e-16, 4.228e-16, 3.201e-16, 2.438e-16, 1.878e-16,
462 1.445e-16, 1.111e-16, 8.544e-17, 6.734e-17, 5.341e-17, 4.237e-17,
463 3.394e-17, 2.759e-17, 2.254e-17, 1.851e-17, 1.54e-17, 1.297e-17,
464 1.096e-17, 9.365e-18, 8e-18, 6.938e-18, 6.056e-18, 5.287e-18,
465 4.662e-18
466 };
467
468 static const double f11[121] = {
469 2.65e-10, 2.65e-10, 2.65e-10, 2.65e-10, 2.65e-10, 2.65e-10, 2.65e-10,
470 2.65e-10, 2.65e-10, 2.65e-10, 2.65e-10, 2.65e-10, 2.635e-10, 2.536e-10,
471 2.44e-10, 2.348e-10, 2.258e-10, 2.153e-10, 2.046e-10, 1.929e-10,
472 1.782e-10, 1.648e-10, 1.463e-10, 1.291e-10, 1.1e-10, 8.874e-11,
473 7.165e-11, 5.201e-11, 3.744e-11, 2.577e-11, 1.64e-11, 1.048e-11,
474 5.993e-12, 3.345e-12, 1.839e-12, 9.264e-13, 4.688e-13, 2.329e-13,
475 1.129e-13, 5.505e-14, 2.825e-14, 1.492e-14, 7.997e-15, 5.384e-15,
476 3.988e-15, 2.955e-15, 2.196e-15, 1.632e-15, 1.214e-15, 9.025e-16,
477 6.708e-16, 4.984e-16, 3.693e-16, 2.733e-16, 2.013e-16, 1.481e-16,
478 1.087e-16, 7.945e-17, 5.782e-17, 4.195e-17, 3.038e-17, 2.19e-17,
479 1.577e-17, 1.128e-17, 8.063e-18, 5.753e-18, 4.09e-18, 2.899e-18,
480 2.048e-18, 1.444e-18, 1.015e-18, 7.12e-19, 4.985e-19, 3.474e-19,
481 2.417e-19, 1.677e-19, 1.161e-19, 8.029e-20, 5.533e-20, 3.799e-20,
482 2.602e-20, 1.776e-20, 1.209e-20, 8.202e-21, 5.522e-21, 3.707e-21,
483 2.48e-21, 1.652e-21, 1.091e-21, 7.174e-22, 4.709e-22, 3.063e-22,
484 1.991e-22, 1.294e-22, 8.412e-23, 5.483e-23, 3.581e-23, 2.345e-23,
485 1.548e-23, 1.027e-23, 6.869e-24, 4.673e-24, 3.173e-24, 2.153e-24,
486 1.461e-24, 1.028e-24, 7.302e-25, 5.188e-25, 3.739e-25, 2.753e-25,
487 2.043e-25, 1.528e-25, 1.164e-25, 9.041e-26, 7.051e-26, 5.587e-26,
488 4.428e-26, 3.588e-26, 2.936e-26, 2.402e-26, 1.995e-26
489 };
490
491 static const double f113[121] = {
492 1.9e-11, 1.9e-11, 1.899e-11, 1.899e-11, 1.898e-11, 1.898e-11,
493 1.897e-11, 1.896e-11, 1.895e-11, 1.894e-11, 1.893e-11, 1.89e-11,
494 1.887e-11, 1.871e-11, 1.854e-11, 1.803e-11, 1.751e-11, 1.664e-11,
495 1.576e-11, 1.466e-11, 1.356e-11, 1.236e-11, 1.116e-11, 9.931e-12,
496 8.702e-12, 7.515e-12, 6.4238e-12, 5.3326e-12, 4.3652e-12, 3.5216e-12,
497 2.678e-12, 2.1532e-12, 1.6284e-12, 1.2202e-12, 9.286e-13, 6.37e-13,
498 4.95e-13, 3.53e-13, 2.5004e-13, 1.8612e-13, 1.222e-13, 9.704e-14,
499 7.188e-14, 5.3338e-14, 4.1414e-14, 2.949e-14, 2.3722e-14, 1.7954e-14,
500 1.37794e-14, 1.11982e-14, 8.617e-15, 7.6036e-15, 6.5902e-15,
501 5.5768e-15, 4.5634e-15, 3.55e-15, 3.1008e-15, 2.6516e-15, 2.2024e-15,
502 1.7532e-15, 1.304e-15, 1.1354e-15, 9.668e-16, 7.982e-16, 6.296e-16,
503 4.61e-16, 3.9734e-16, 3.3368e-16, 2.7002e-16, 2.0636e-16, 1.427e-16,
504 1.22804e-16, 1.02908e-16, 8.3012e-17, 6.3116e-17, 4.322e-17,
505 3.6838e-17, 3.0456e-17, 2.4074e-17, 1.7692e-17, 1.131e-17,
506 9.6202e-18, 7.9304e-18, 6.2406e-18, 4.5508e-18, 2.861e-18,
507 2.40476e-18, 1.94852e-18, 1.49228e-18, 1.03604e-18, 5.798e-19,
508 4.8502e-19, 3.9024e-19, 2.9546e-19, 2.0068e-19, 1.059e-19,
509 8.7084e-20, 6.8268e-20, 4.9452e-20, 3.0636e-20, 1.182e-20,
510 9.64344e-21, 7.46688e-21, 5.29032e-21, 3.11376e-21, 9.372e-22,
511 7.5685e-22, 5.765e-22, 3.9615e-22, 2.158e-22, 3.545e-23,
512 2.86046e-23, 2.17592e-23, 1.49138e-23, 8.0684e-24, 1.223e-24,
513 9.92358e-25, 7.61716e-25, 5.31074e-25, 3.00432e-25, 6.979e-26
514 };
515
516 static const double f114[121] = {
517 1.2e-11, 1.2e-11, 1.2e-11, 1.2e-11, 1.199e-11, 1.199e-11,
518 1.199e-11, 1.199e-11, 1.198e-11, 1.198e-11, 1.198e-11, 1.197e-11,
519 1.196e-11, 1.191e-11, 1.185e-11, 1.167e-11, 1.149e-11, 1.12e-11,
520 1.09e-11, 1.053e-11, 1.015e-11, 9.731e-12, 9.311e-12, 8.865e-12,
521 8.419e-12, 7.949e-12, 7.4774e-12, 7.0058e-12, 6.54e-12, 6.08e-12,
522 5.62e-12, 5.1908e-12, 4.7616e-12, 4.3622e-12, 3.9926e-12, 3.623e-12,
523 3.3274e-12, 3.0318e-12, 2.7702e-12, 2.5426e-12, 2.315e-12, 2.1514e-12,
524 1.9878e-12, 1.8448e-12, 1.7224e-12, 1.6e-12, 1.51e-12, 1.42e-12,
525 1.3462e-12, 1.2886e-12, 1.231e-12, 1.1922e-12, 1.1534e-12, 1.1146e-12,
526 1.0758e-12, 1.037e-12, 1.0025e-12, 9.68e-13, 9.335e-13, 8.99e-13,
527 8.645e-13, 8.344e-13, 8.043e-13, 7.742e-13, 7.441e-13, 7.14e-13,
528 6.8718e-13, 6.6036e-13, 6.3354e-13, 6.0672e-13, 5.799e-13, 5.5612e-13,
529 5.3234e-13, 5.0856e-13, 4.8478e-13, 4.61e-13, 4.394e-13, 4.178e-13,
530 3.962e-13, 3.746e-13, 3.53e-13, 3.3288e-13, 3.1276e-13, 2.9264e-13,
531 2.7252e-13, 2.524e-13, 2.3368e-13, 2.1496e-13, 1.9624e-13, 1.7752e-13,
532 1.588e-13, 1.4221e-13, 1.2562e-13, 1.0903e-13, 9.244e-14, 7.585e-14,
533 6.4942e-14, 5.4034e-14, 4.3126e-14, 3.2218e-14, 2.131e-14, 1.76694e-14,
534 1.40288e-14, 1.03882e-14, 6.7476e-15, 3.107e-15, 2.52738e-15,
535 1.94776e-15, 1.36814e-15, 7.8852e-16, 2.089e-16, 1.69288e-16,
536 1.29676e-16, 9.0064e-17, 5.0452e-17, 1.084e-17, 8.85136e-18,
537 6.86272e-18, 4.87408e-18, 2.88544e-18, 8.968e-19
538 };
539
540 static const double f12[121] = {
541 5.45e-10, 5.45e-10, 5.45e-10, 5.45e-10, 5.45e-10, 5.45e-10, 5.45e-10,
542 5.45e-10, 5.45e-10, 5.45e-10, 5.45e-10, 5.45e-10, 5.429e-10, 5.291e-10,
543 5.155e-10, 5.022e-10, 4.893e-10, 4.772e-10, 4.655e-10, 4.497e-10,
544 4.249e-10, 4.015e-10, 3.632e-10, 3.261e-10, 2.858e-10, 2.408e-10,
545 2.03e-10, 1.685e-10, 1.4e-10, 1.163e-10, 9.65e-11, 8.02e-11, 6.705e-11,
546 5.624e-11, 4.764e-11, 4.249e-11, 3.792e-11, 3.315e-11, 2.819e-11,
547 2.4e-11, 1.999e-11, 1.64e-11, 1.352e-11, 1.14e-11, 9.714e-12,
548 8.28e-12, 7.176e-12, 6.251e-12, 5.446e-12, 4.72e-12, 4.081e-12,
549 3.528e-12, 3.08e-12, 2.699e-12, 2.359e-12, 2.111e-12, 1.901e-12,
550 1.709e-12, 1.534e-12, 1.376e-12, 1.233e-12, 1.103e-12, 9.869e-13,
551 8.808e-13, 7.859e-13, 7.008e-13, 6.241e-13, 5.553e-13, 4.935e-13,
552 4.383e-13, 3.889e-13, 3.447e-13, 3.054e-13, 2.702e-13, 2.389e-13,
553 2.11e-13, 1.862e-13, 1.643e-13, 1.448e-13, 1.274e-13, 1.121e-13,
554 9.844e-14, 8.638e-14, 7.572e-14, 6.62e-14, 5.782e-14, 5.045e-14,
555 4.394e-14, 3.817e-14, 3.311e-14, 2.87e-14, 2.48e-14, 2.142e-14,
556 1.851e-14, 1.599e-14, 1.383e-14, 1.196e-14, 1.036e-14, 9e-15,
557 7.828e-15, 6.829e-15, 5.992e-15, 5.254e-15, 4.606e-15, 4.037e-15,
558 3.583e-15, 3.19e-15, 2.841e-15, 2.542e-15, 2.291e-15, 2.07e-15,
559 1.875e-15, 1.71e-15, 1.57e-15, 1.442e-15, 1.333e-15, 1.232e-15,
560 1.147e-15, 1.071e-15, 1.001e-15, 9.396e-16
561 };
562
563 static const double f14[121] = {
564 9e-11, 9e-11, 9e-11, 9e-11, 9e-11, 9e-11, 9e-11, 9e-11, 9e-11, 9e-11,
565 9e-11, 9e-11, 9e-11, 9e-11, 9e-11, 8.91e-11, 8.73e-11, 8.46e-11,
566 8.19e-11, 7.92e-11, 7.74e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11,
567 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11,
568 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11,
569 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11,
570 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11,
571 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11,
572 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11,
573 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11,
574 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11,
575 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11,
576 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11,
577 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11,
578 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11,
579 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11,
580 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11, 7.65e-11
581 };
582
583 static const double f22[121] = {
584 1.4e-10, 1.4e-10, 1.4e-10, 1.4e-10, 1.4e-10, 1.4e-10, 1.4e-10,
585 1.4e-10, 1.4e-10, 1.4e-10, 1.372e-10, 1.317e-10, 1.235e-10, 1.153e-10,
586 1.075e-10, 1.002e-10, 9.332e-11, 8.738e-11, 8.194e-11, 7.7e-11,
587 7.165e-11, 6.753e-11, 6.341e-11, 5.971e-11, 5.6e-11, 5.229e-11,
588 4.859e-11, 4.488e-11, 4.118e-11, 3.83e-11, 3.568e-11, 3.308e-11,
589 3.047e-11, 2.82e-11, 2.594e-11, 2.409e-11, 2.237e-11, 2.065e-11,
590 1.894e-11, 1.771e-11, 1.647e-11, 1.532e-11, 1.416e-11, 1.332e-11,
591 1.246e-11, 1.161e-11, 1.087e-11, 1.017e-11, 9.471e-12, 8.853e-12,
592 8.235e-12, 7.741e-12, 7.247e-12, 6.836e-12, 6.506e-12, 6.176e-12,
593 5.913e-12, 5.65e-12, 5.419e-12, 5.221e-12, 5.024e-12, 4.859e-12,
594 4.694e-12, 4.546e-12, 4.414e-12, 4.282e-12, 4.15e-12, 4.019e-12,
595 3.903e-12, 3.805e-12, 3.706e-12, 3.607e-12, 3.508e-12, 3.41e-12,
596 3.31e-12, 3.212e-12, 3.129e-12, 3.047e-12, 2.964e-12, 2.882e-12,
597 2.8e-12, 2.734e-12, 2.668e-12, 2.602e-12, 2.537e-12, 2.471e-12,
598 2.421e-12, 2.372e-12, 2.322e-12, 2.273e-12, 2.224e-12, 2.182e-12,
599 2.141e-12, 2.1e-12, 2.059e-12, 2.018e-12, 1.977e-12, 1.935e-12,
600 1.894e-12, 1.853e-12, 1.812e-12, 1.77e-12, 1.73e-12, 1.688e-12,
601 1.647e-12, 1.606e-12, 1.565e-12, 1.524e-12, 1.483e-12, 1.441e-12,
602 1.4e-12, 1.359e-12, 1.317e-12, 1.276e-12, 1.235e-12, 1.194e-12,
603 1.153e-12, 1.112e-12, 1.071e-12, 1.029e-12, 9.883e-13
604 };
605
606 static const double h2co[121] = {
607 8.71857e-11, 8.71857e-11, 8.71857e-11, 8.71857e-11, 8.71857e-11,
608 8.71857e-11, 7.72315e-11, 6.85464e-11, 6.0758e-11, 5.32087e-11,
609 4.5719e-11, 3.79458e-11, 3.07607e-11, 2.46025e-11, 1.94038e-11,
610 1.40882e-11, 1.0623e-11, 8.35457e-12, 6.87427e-12, 7.09071e-12,
611 8.96183e-12, 1.09012e-11, 1.50545e-11, 1.92077e-11, 2.3361e-11,
612 2.7054e-11, 3.01936e-11, 3.33333e-11, 3.69281e-11, 4.08069e-11,
613 4.57318e-11, 5.1348e-11, 5.69642e-11, 6.33173e-11, 6.98984e-11,
614 7.63144e-11, 8.22774e-11, 8.82405e-11, 9.3746e-11, 9.92074e-11,
615 1.04669e-10, 1.10055e-10, 1.15293e-10, 1.20531e-10, 1.26293e-10,
616 1.32585e-10, 1.35966e-10, 1.36242e-10, 1.36519e-10, 1.61155e-10,
617 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10,
618 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10,
619 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10,
620 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10,
621 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10,
622 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10,
623 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10,
624 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10,
625 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10,
626 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10,
627 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10,
628 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10,
629 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10,
630 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10, 1.99157e-10,
631 1.99157e-10
632 };
633
634 static const double h2o[121] = {
635 0.01166, 0.008269, 0.005742, 0.003845, 0.00277, 0.001897, 0.001272,
636 0.000827, 0.000539, 0.0003469, 0.0001579, 3.134e-05, 1.341e-05,
637 6.764e-06, 4.498e-06, 3.703e-06, 3.724e-06, 3.899e-06, 4.002e-06,
638 4.122e-06, 4.277e-06, 4.438e-06, 4.558e-06, 4.673e-06, 4.763e-06,
639 4.809e-06, 4.856e-06, 4.936e-06, 5.021e-06, 5.114e-06, 5.222e-06,
640 5.331e-06, 5.414e-06, 5.488e-06, 5.563e-06, 5.633e-06, 5.704e-06,
641 5.767e-06, 5.819e-06, 5.872e-06, 5.914e-06, 5.949e-06, 5.984e-06,
642 6.015e-06, 6.044e-06, 6.073e-06, 6.104e-06, 6.136e-06, 6.167e-06,
643 6.189e-06, 6.208e-06, 6.226e-06, 6.212e-06, 6.185e-06, 6.158e-06,
644 6.114e-06, 6.066e-06, 6.018e-06, 5.877e-06, 5.728e-06, 5.582e-06,
645 5.437e-06, 5.296e-06, 5.156e-06, 5.02e-06, 4.886e-06, 4.754e-06,
646 4.625e-06, 4.498e-06, 4.374e-06, 4.242e-06, 4.096e-06, 3.955e-06,
647 3.817e-06, 3.683e-06, 3.491e-06, 3.204e-06, 2.94e-06, 2.696e-06,
648 2.47e-06, 2.252e-06, 2.019e-06, 1.808e-06, 1.618e-06, 1.445e-06,
649 1.285e-06, 1.105e-06, 9.489e-07, 8.121e-07, 6.938e-07, 5.924e-07,
650 5.04e-07, 4.288e-07, 3.648e-07, 3.103e-07, 2.642e-07, 2.252e-07,
651 1.921e-07, 1.643e-07, 1.408e-07, 1.211e-07, 1.048e-07, 9.063e-08,
652 7.835e-08, 6.774e-08, 5.936e-08, 5.221e-08, 4.592e-08, 4.061e-08,
653 3.62e-08, 3.236e-08, 2.902e-08, 2.62e-08, 2.383e-08, 2.171e-08,
654 1.989e-08, 1.823e-08, 1.684e-08, 1.562e-08, 1.449e-08, 1.351e-08
655 };
656
657 static const double h2o2[121] = {
658 1.779e-10, 7.938e-10, 8.953e-10, 8.032e-10, 6.564e-10, 5.159e-10,
659 4.003e-10, 3.026e-10, 2.222e-10, 1.58e-10, 1.044e-10, 6.605e-11,
660 3.413e-11, 1.453e-11, 1.062e-11, 1.009e-11, 9.597e-12, 1.175e-11,
661 1.572e-11, 2.091e-11, 2.746e-11, 3.603e-11, 4.791e-11, 6.387e-11,
662 8.239e-11, 1.007e-10, 1.23e-10, 1.363e-10, 1.489e-10, 1.585e-10,
663 1.608e-10, 1.632e-10, 1.576e-10, 1.502e-10, 1.423e-10, 1.302e-10,
664 1.192e-10, 1.085e-10, 9.795e-11, 8.854e-11, 8.057e-11, 7.36e-11,
665 6.736e-11, 6.362e-11, 6.087e-11, 5.825e-11, 5.623e-11, 5.443e-11,
666 5.27e-11, 5.098e-11, 4.931e-11, 4.769e-11, 4.611e-11, 4.458e-11,
667 4.308e-11, 4.102e-11, 3.887e-11, 3.682e-11, 3.521e-11, 3.369e-11,
668 3.224e-11, 3.082e-11, 2.946e-11, 2.814e-11, 2.687e-11, 2.566e-11,
669 2.449e-11, 2.336e-11, 2.227e-11, 2.123e-11, 2.023e-11, 1.927e-11,
670 1.835e-11, 1.746e-11, 1.661e-11, 1.58e-11, 1.502e-11, 1.428e-11,
671 1.357e-11, 1.289e-11, 1.224e-11, 1.161e-11, 1.102e-11, 1.045e-11,
672 9.895e-12, 9.369e-12, 8.866e-12, 8.386e-12, 7.922e-12, 7.479e-12,
673 7.06e-12, 6.656e-12, 6.274e-12, 5.914e-12, 5.575e-12, 5.257e-12,
674 4.959e-12, 4.679e-12, 4.42e-12, 4.178e-12, 3.954e-12, 3.75e-12,
675 3.557e-12, 3.372e-12, 3.198e-12, 3.047e-12, 2.908e-12, 2.775e-12,
676 2.653e-12, 2.544e-12, 2.442e-12, 2.346e-12, 2.26e-12, 2.183e-12,
677 2.11e-12, 2.044e-12, 1.98e-12, 1.924e-12, 1.871e-12, 1.821e-12,
678 1.775e-12
679 };
680
681 static const double hcl[121] = {
682 3.70385e-11, 3.70385e-11, 3.70385e-11, 3.70385e-11, 3.70385e-11,
683 3.70385e-11, 2.21247e-11, 1.88117e-11, 2.36957e-11, 3.72192e-11,
684 5.79399e-11, 8.04158e-11, 1.01779e-10, 1.2301e-10, 1.53924e-10,
685 1.93737e-10, 2.5561e-10, 3.84228e-10, 6.18248e-10, 6.31222e-10,
686 7.84907e-10, 9.36932e-10, 1.03508e-09, 1.13323e-09, 1.23138e-09,
687 1.31985e-09, 1.39669e-09, 1.47352e-09, 1.56375e-09, 1.66234e-09,
688 1.78086e-09, 1.91256e-09, 2.04425e-09, 2.16629e-09, 2.28535e-09,
689 2.39439e-09, 2.47597e-09, 2.55755e-09, 2.60873e-09, 2.65696e-09,
690 2.70519e-09, 2.75658e-09, 2.81422e-09, 2.87187e-09, 2.94013e-09,
691 3.01911e-09, 3.09497e-09, 3.16749e-09, 3.24001e-09, 3.30525e-09,
692 3.3665e-09, 3.42424e-09, 3.4619e-09, 3.49956e-09, 3.52273e-09,
693 3.54214e-09, 3.56154e-09, 3.57918e-09, 3.59049e-09, 3.6018e-09,
694 3.6132e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09,
695 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09,
696 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09,
697 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09,
698 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09,
699 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09,
700 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09,
701 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09,
702 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09,
703 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09,
704 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09,
705 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09, 3.62476e-09,
706 3.62476e-09
707 };
708
709 static const double hcn[121] = {
710 5.5e-10, 5.5e-10, 5.5e-10, 5.5e-10, 5.5e-10, 5.5e-10, 5.5e-10,
711 5.5e-10, 5.5e-10, 5.5e-10, 5.5e-10, 5.498e-10, 5.495e-10, 5.493e-10,
712 5.49e-10, 5.488e-10, 4.717e-10, 3.946e-10, 3.174e-10, 2.4e-10,
713 1.626e-10, 1.619e-10, 1.612e-10, 1.602e-10, 1.593e-10, 1.582e-10,
714 1.572e-10, 1.56e-10, 1.549e-10, 1.539e-10, 1.53e-10, 1.519e-10,
715 1.506e-10, 1.487e-10, 1.467e-10, 1.449e-10, 1.43e-10, 1.413e-10,
716 1.397e-10, 1.382e-10, 1.368e-10, 1.354e-10, 1.337e-10, 1.315e-10,
717 1.292e-10, 1.267e-10, 1.241e-10, 1.215e-10, 1.19e-10, 1.165e-10,
718 1.141e-10, 1.118e-10, 1.096e-10, 1.072e-10, 1.047e-10, 1.021e-10,
719 9.968e-11, 9.739e-11, 9.539e-11, 9.339e-11, 9.135e-11, 8.898e-11,
720 8.664e-11, 8.439e-11, 8.249e-11, 8.075e-11, 7.904e-11, 7.735e-11,
721 7.565e-11, 7.399e-11, 7.245e-11, 7.109e-11, 6.982e-11, 6.863e-11,
722 6.755e-11, 6.657e-11, 6.587e-11, 6.527e-11, 6.476e-11, 6.428e-11,
723 6.382e-11, 6.343e-11, 6.307e-11, 6.272e-11, 6.238e-11, 6.205e-11,
724 6.17e-11, 6.137e-11, 6.102e-11, 6.072e-11, 6.046e-11, 6.03e-11,
725 6.018e-11, 6.01e-11, 6.001e-11, 5.992e-11, 5.984e-11, 5.975e-11,
726 5.967e-11, 5.958e-11, 5.95e-11, 5.941e-11, 5.933e-11, 5.925e-11,
727 5.916e-11, 5.908e-11, 5.899e-11, 5.891e-11, 5.883e-11, 5.874e-11,
728 5.866e-11, 5.858e-11, 5.85e-11, 5.841e-11, 5.833e-11, 5.825e-11,
729 5.817e-11, 5.808e-11, 5.8e-11, 5.792e-11, 5.784e-11
730 };
731
732 static const double hf[121] = {
733 2.64279e-11, 2.64279e-11, 2.64279e-11, 2.64279e-11, 2.64279e-11,
734 2.64279e-11, 2.64279e-11, 2.64279e-11, 2.64279e-11, 2.64279e-11,
735 2.64279e-11, 2.64279e-11, 2.64279e-11, 3.86691e-11, 5.22002e-11,
736 6.92471e-11, 9.13979e-11, 1.37918e-10, 2.24918e-10, 2.29824e-10,
737 2.94241e-10, 3.58363e-10, 4.12881e-10, 4.67399e-10, 5.21917e-10,
738 5.74229e-10, 6.23889e-10, 6.73549e-10, 7.24119e-10, 7.75256e-10,
739 8.319e-10, 8.92185e-10, 9.52469e-10, 1.01325e-09, 1.07419e-09,
740 1.13565e-09, 1.19856e-09, 1.26146e-09, 1.31439e-09, 1.36635e-09,
741 1.41831e-09, 1.46549e-09, 1.50321e-09, 1.54093e-09, 1.57986e-09,
742 1.62e-09, 1.66286e-09, 1.70863e-09, 1.75439e-09, 1.79827e-09,
743 1.84111e-09, 1.88125e-09, 1.90603e-09, 1.93081e-09, 1.9413e-09,
744 1.94807e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09,
745 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09,
746 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09,
747 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09,
748 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09,
749 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09,
750 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09,
751 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09,
752 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09,
753 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09,
754 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09,
755 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09,
756 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09, 1.95485e-09,
757 1.95485e-09
758 };
759
760 static const double hno3[121] = {
761 1.809e-10, 7.234e-10, 5.899e-10, 4.342e-10, 3.277e-10, 2.661e-10,
762 2.35e-10, 2.267e-10, 2.389e-10, 2.651e-10, 3.255e-10, 4.099e-10,
763 5.42e-10, 6.978e-10, 8.807e-10, 1.112e-09, 1.405e-09, 2.04e-09,
764 3.111e-09, 4.5e-09, 5.762e-09, 7.37e-09, 7.852e-09, 8.109e-09,
765 8.067e-09, 7.554e-09, 7.076e-09, 6.268e-09, 5.524e-09, 4.749e-09,
766 3.909e-09, 3.223e-09, 2.517e-09, 1.942e-09, 1.493e-09, 1.122e-09,
767 8.449e-10, 6.361e-10, 4.787e-10, 3.611e-10, 2.804e-10, 2.215e-10,
768 1.758e-10, 1.441e-10, 1.197e-10, 9.953e-11, 8.505e-11, 7.334e-11,
769 6.325e-11, 5.625e-11, 5.058e-11, 4.548e-11, 4.122e-11, 3.748e-11,
770 3.402e-11, 3.088e-11, 2.8e-11, 2.536e-11, 2.293e-11, 2.072e-11,
771 1.871e-11, 1.687e-11, 1.52e-11, 1.368e-11, 1.23e-11, 1.105e-11,
772 9.922e-12, 8.898e-12, 7.972e-12, 7.139e-12, 6.385e-12, 5.708e-12,
773 5.099e-12, 4.549e-12, 4.056e-12, 3.613e-12, 3.216e-12, 2.862e-12,
774 2.544e-12, 2.259e-12, 2.004e-12, 1.776e-12, 1.572e-12, 1.391e-12,
775 1.227e-12, 1.082e-12, 9.528e-13, 8.379e-13, 7.349e-13, 6.436e-13,
776 5.634e-13, 4.917e-13, 4.291e-13, 3.745e-13, 3.267e-13, 2.854e-13,
777 2.494e-13, 2.181e-13, 1.913e-13, 1.68e-13, 1.479e-13, 1.31e-13,
778 1.159e-13, 1.025e-13, 9.067e-14, 8.113e-14, 7.281e-14, 6.535e-14,
779 5.892e-14, 5.348e-14, 4.867e-14, 4.439e-14, 4.073e-14, 3.76e-14,
780 3.476e-14, 3.229e-14, 3e-14, 2.807e-14, 2.635e-14, 2.473e-14,
781 2.332e-14
782 };
783
784 static const double hno4[121] = {
785 6.118e-12, 3.594e-12, 2.807e-12, 3.04e-12, 4.458e-12, 7.986e-12,
786 1.509e-11, 2.661e-11, 3.738e-11, 4.652e-11, 4.429e-11, 3.992e-11,
787 3.347e-11, 3.005e-11, 3.173e-11, 4.055e-11, 5.812e-11, 8.489e-11,
788 1.19e-10, 1.482e-10, 1.766e-10, 2.103e-10, 2.35e-10, 2.598e-10,
789 2.801e-10, 2.899e-10, 3e-10, 2.817e-10, 2.617e-10, 2.332e-10,
790 1.933e-10, 1.605e-10, 1.232e-10, 9.285e-11, 6.941e-11, 4.951e-11,
791 3.539e-11, 2.402e-11, 1.522e-11, 9.676e-12, 6.056e-12, 3.745e-12,
792 2.34e-12, 1.463e-12, 9.186e-13, 5.769e-13, 3.322e-13, 1.853e-13,
793 1.035e-13, 7.173e-14, 5.382e-14, 4.036e-14, 3.401e-14, 2.997e-14,
794 2.635e-14, 2.316e-14, 2.034e-14, 1.783e-14, 1.56e-14, 1.363e-14,
795 1.19e-14, 1.037e-14, 9.032e-15, 7.846e-15, 6.813e-15, 5.912e-15,
796 5.121e-15, 4.431e-15, 3.829e-15, 3.306e-15, 2.851e-15, 2.456e-15,
797 2.114e-15, 1.816e-15, 1.559e-15, 1.337e-15, 1.146e-15, 9.811e-16,
798 8.389e-16, 7.162e-16, 6.109e-16, 5.203e-16, 4.425e-16, 3.76e-16,
799 3.184e-16, 2.692e-16, 2.274e-16, 1.917e-16, 1.61e-16, 1.35e-16,
800 1.131e-16, 9.437e-17, 7.874e-17, 6.57e-17, 5.481e-17, 4.579e-17,
801 3.828e-17, 3.204e-17, 2.691e-17, 2.264e-17, 1.912e-17, 1.626e-17,
802 1.382e-17, 1.174e-17, 9.972e-18, 8.603e-18, 7.45e-18, 6.453e-18,
803 5.623e-18, 4.944e-18, 4.361e-18, 3.859e-18, 3.443e-18, 3.096e-18,
804 2.788e-18, 2.528e-18, 2.293e-18, 2.099e-18, 1.929e-18, 1.773e-18,
805 1.64e-18
806 };
807
808 static const double hocl[121] = {
809 1.056e-12, 1.194e-12, 1.35e-12, 1.531e-12, 1.737e-12, 1.982e-12,
810 2.263e-12, 2.599e-12, 2.991e-12, 3.459e-12, 4.012e-12, 4.662e-12,
811 5.438e-12, 6.35e-12, 7.425e-12, 8.686e-12, 1.016e-11, 1.188e-11,
812 1.389e-11, 1.659e-11, 2.087e-11, 2.621e-11, 3.265e-11, 4.064e-11,
813 4.859e-11, 5.441e-11, 6.09e-11, 6.373e-11, 6.611e-11, 6.94e-11,
814 7.44e-11, 7.97e-11, 8.775e-11, 9.722e-11, 1.064e-10, 1.089e-10,
815 1.114e-10, 1.106e-10, 1.053e-10, 1.004e-10, 9.006e-11, 7.778e-11,
816 6.739e-11, 5.636e-11, 4.655e-11, 3.845e-11, 3.042e-11, 2.368e-11,
817 1.845e-11, 1.442e-11, 1.127e-11, 8.814e-12, 6.544e-12, 4.763e-12,
818 3.449e-12, 2.612e-12, 1.999e-12, 1.526e-12, 1.16e-12, 8.793e-13,
819 6.655e-13, 5.017e-13, 3.778e-13, 2.829e-13, 2.117e-13, 1.582e-13,
820 1.178e-13, 8.755e-14, 6.486e-14, 4.799e-14, 3.54e-14, 2.606e-14,
821 1.916e-14, 1.403e-14, 1.026e-14, 7.48e-15, 5.446e-15, 3.961e-15,
822 2.872e-15, 2.076e-15, 1.498e-15, 1.077e-15, 7.726e-16, 5.528e-16,
823 3.929e-16, 2.785e-16, 1.969e-16, 1.386e-16, 9.69e-17, 6.747e-17,
824 4.692e-17, 3.236e-17, 2.232e-17, 1.539e-17, 1.061e-17, 7.332e-18,
825 5.076e-18, 3.522e-18, 2.461e-18, 1.726e-18, 1.22e-18, 8.75e-19,
826 6.264e-19, 4.482e-19, 3.207e-19, 2.368e-19, 1.762e-19, 1.312e-19,
827 9.891e-20, 7.595e-20, 5.87e-20, 4.567e-20, 3.612e-20, 2.904e-20,
828 2.343e-20, 1.917e-20, 1.568e-20, 1.308e-20, 1.1e-20, 9.25e-21,
829 7.881e-21
830 };
831
832 static const double n2o[121] = {
833 3.17e-07, 3.17e-07, 3.17e-07, 3.17e-07, 3.17e-07, 3.17e-07, 3.17e-07,
834 3.17e-07, 3.17e-07, 3.17e-07, 3.124e-07, 3.077e-07, 3.03e-07,
835 2.984e-07, 2.938e-07, 2.892e-07, 2.847e-07, 2.779e-07, 2.705e-07,
836 2.631e-07, 2.557e-07, 2.484e-07, 2.345e-07, 2.201e-07, 2.01e-07,
837 1.754e-07, 1.532e-07, 1.329e-07, 1.154e-07, 1.003e-07, 8.735e-08,
838 7.617e-08, 6.512e-08, 5.547e-08, 4.709e-08, 3.915e-08, 3.259e-08,
839 2.738e-08, 2.327e-08, 1.98e-08, 1.711e-08, 1.493e-08, 1.306e-08,
840 1.165e-08, 1.049e-08, 9.439e-09, 8.375e-09, 7.391e-09, 6.525e-09,
841 5.759e-09, 5.083e-09, 4.485e-09, 3.953e-09, 3.601e-09, 3.27e-09,
842 2.975e-09, 2.757e-09, 2.556e-09, 2.37e-09, 2.195e-09, 2.032e-09,
843 1.912e-09, 1.79e-09, 1.679e-09, 1.572e-09, 1.482e-09, 1.402e-09,
844 1.326e-09, 1.254e-09, 1.187e-09, 1.127e-09, 1.071e-09, 1.02e-09,
845 9.673e-10, 9.193e-10, 8.752e-10, 8.379e-10, 8.017e-10, 7.66e-10,
846 7.319e-10, 7.004e-10, 6.721e-10, 6.459e-10, 6.199e-10, 5.942e-10,
847 5.703e-10, 5.488e-10, 5.283e-10, 5.082e-10, 4.877e-10, 4.696e-10,
848 4.52e-10, 4.355e-10, 4.198e-10, 4.039e-10, 3.888e-10, 3.754e-10,
849 3.624e-10, 3.499e-10, 3.381e-10, 3.267e-10, 3.163e-10, 3.058e-10,
850 2.959e-10, 2.864e-10, 2.77e-10, 2.686e-10, 2.604e-10, 2.534e-10,
851 2.462e-10, 2.386e-10, 2.318e-10, 2.247e-10, 2.189e-10, 2.133e-10,
852 2.071e-10, 2.014e-10, 1.955e-10, 1.908e-10, 1.86e-10, 1.817e-10
853 };
854
855 static const double n2o5[121] = {
856 1.231e-11, 3.035e-12, 1.702e-12, 9.877e-13, 8.081e-13, 9.039e-13,
857 1.169e-12, 1.474e-12, 1.651e-12, 1.795e-12, 1.998e-12, 2.543e-12,
858 4.398e-12, 7.698e-12, 1.28e-11, 2.131e-11, 3.548e-11, 5.894e-11,
859 7.645e-11, 1.089e-10, 1.391e-10, 1.886e-10, 2.386e-10, 2.986e-10,
860 3.487e-10, 3.994e-10, 4.5e-10, 4.6e-10, 4.591e-10, 4.1e-10, 3.488e-10,
861 2.846e-10, 2.287e-10, 1.696e-10, 1.011e-10, 6.428e-11, 4.324e-11,
862 2.225e-11, 6.214e-12, 3.608e-12, 8.793e-13, 4.491e-13, 1.04e-13,
863 6.1e-14, 3.436e-14, 6.671e-15, 1.171e-15, 5.848e-16, 1.212e-16,
864 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16,
865 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16,
866 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16,
867 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16,
868 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16,
869 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16,
870 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16, 1e-16,
871 1e-16, 1e-16
872 };
873
874 static const double nh3[121] = {
875 1e-10, 1e-10, 1e-10, 1e-10, 1e-10, 1e-10, 1e-10, 1e-10, 1e-10, 1e-10,
876 1e-10, 1e-10, 1e-10, 1e-10, 9.444e-11, 8.488e-11, 7.241e-11, 5.785e-11,
877 4.178e-11, 3.018e-11, 2.18e-11, 1.574e-11, 1.137e-11, 8.211e-12,
878 5.973e-12, 4.327e-12, 3.118e-12, 2.234e-12, 1.573e-12, 1.04e-12,
879 6.762e-13, 4.202e-13, 2.406e-13, 1.335e-13, 6.938e-14, 3.105e-14,
880 1.609e-14, 1.033e-14, 6.432e-15, 4.031e-15, 2.555e-15, 1.656e-15,
881 1.115e-15, 7.904e-16, 5.63e-16, 4.048e-16, 2.876e-16, 2.004e-16,
882 1.356e-16, 9.237e-17, 6.235e-17, 4.223e-17, 3.009e-17, 2.328e-17,
883 2.002e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17,
884 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17,
885 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17,
886 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17,
887 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17,
888 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17,
889 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17,
890 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17,
891 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17,
892 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17,
893 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17, 1.914e-17,
894 1.914e-17
895 };
896
897 static const double no[121] = {
898 2.586e-10, 4.143e-11, 1.566e-11, 9.591e-12, 8.088e-12, 8.462e-12,
899 1.013e-11, 1.328e-11, 1.855e-11, 2.678e-11, 3.926e-11, 5.464e-11,
900 7.012e-11, 8.912e-11, 1.127e-10, 1.347e-10, 1.498e-10, 1.544e-10,
901 1.602e-10, 1.824e-10, 2.078e-10, 2.366e-10, 2.691e-10, 5.141e-10,
902 8.259e-10, 1.254e-09, 1.849e-09, 2.473e-09, 3.294e-09, 4.16e-09,
903 5.095e-09, 6.11e-09, 6.93e-09, 7.888e-09, 8.903e-09, 9.713e-09,
904 1.052e-08, 1.115e-08, 1.173e-08, 1.21e-08, 1.228e-08, 1.239e-08,
905 1.231e-08, 1.213e-08, 1.192e-08, 1.138e-08, 1.085e-08, 1.008e-08,
906 9.224e-09, 8.389e-09, 7.262e-09, 6.278e-09, 5.335e-09, 4.388e-09,
907 3.589e-09, 2.761e-09, 2.129e-09, 1.633e-09, 1.243e-09, 9.681e-10,
908 8.355e-10, 7.665e-10, 7.442e-10, 8.584e-10, 9.732e-10, 1.063e-09,
909 1.163e-09, 1.286e-09, 1.472e-09, 1.707e-09, 2.032e-09, 2.474e-09,
910 2.977e-09, 3.506e-09, 4.102e-09, 5.013e-09, 6.493e-09, 8.414e-09,
911 1.077e-08, 1.367e-08, 1.777e-08, 2.625e-08, 3.926e-08, 5.545e-08,
912 7.195e-08, 9.464e-08, 1.404e-07, 2.183e-07, 3.329e-07, 4.535e-07,
913 6.158e-07, 8.187e-07, 1.075e-06, 1.422e-06, 1.979e-06, 2.71e-06,
914 3.58e-06, 4.573e-06, 5.951e-06, 7.999e-06, 1.072e-05, 1.372e-05,
915 1.697e-05, 2.112e-05, 2.643e-05, 3.288e-05, 3.994e-05, 4.794e-05,
916 5.606e-05, 6.383e-05, 7.286e-05, 8.156e-05, 8.883e-05, 9.469e-05,
917 9.848e-05, 0.0001023, 0.0001066, 0.0001115, 0.0001145, 0.0001142,
918 0.0001133
919 };
920
921 static const double no2[121] = {
922 3.036e-09, 2.945e-10, 9.982e-11, 5.069e-11, 3.485e-11, 2.982e-11,
923 2.947e-11, 3.164e-11, 3.714e-11, 4.586e-11, 6.164e-11, 8.041e-11,
924 9.982e-11, 1.283e-10, 1.73e-10, 2.56e-10, 3.909e-10, 5.959e-10,
925 9.081e-10, 1.384e-09, 1.788e-09, 2.189e-09, 2.686e-09, 3.091e-09,
926 3.49e-09, 3.796e-09, 4.2e-09, 5.103e-09, 6.005e-09, 6.3e-09, 6.706e-09,
927 7.07e-09, 7.434e-09, 7.663e-09, 7.788e-09, 7.8e-09, 7.597e-09,
928 7.482e-09, 7.227e-09, 6.403e-09, 5.585e-09, 4.606e-09, 3.703e-09,
929 2.984e-09, 2.183e-09, 1.48e-09, 8.441e-10, 5.994e-10, 3.799e-10,
930 2.751e-10, 1.927e-10, 1.507e-10, 1.102e-10, 6.971e-11, 5.839e-11,
931 3.904e-11, 3.087e-11, 2.176e-11, 1.464e-11, 1.209e-11, 8.497e-12,
932 6.477e-12, 4.371e-12, 2.914e-12, 2.424e-12, 1.753e-12, 1.35e-12,
933 9.417e-13, 6.622e-13, 5.148e-13, 3.841e-13, 3.446e-13, 3.01e-13,
934 2.551e-13, 2.151e-13, 1.829e-13, 1.64e-13, 1.475e-13, 1.352e-13,
935 1.155e-13, 9.963e-14, 9.771e-14, 9.577e-14, 9.384e-14, 9.186e-14,
936 9e-14, 9e-14, 9e-14, 9e-14, 9e-14, 9e-14, 9e-14, 9e-14, 9e-14, 9e-14,
937 9e-14, 9e-14, 9e-14, 9e-14, 9e-14, 9e-14, 9e-14, 9e-14, 9e-14, 9e-14,
938 9e-14, 9e-14, 9e-14, 9e-14, 9e-14, 9e-14, 9e-14, 9e-14, 9e-14, 9e-14,
939 9e-14, 9e-14, 9e-14, 9e-14, 9e-14, 9e-14
940 };
941
942 static const double o3[121] = {
943 2.218e-08, 3.394e-08, 3.869e-08, 4.219e-08, 4.501e-08, 4.778e-08,
944 5.067e-08, 5.402e-08, 5.872e-08, 6.521e-08, 7.709e-08, 9.461e-08,
945 1.269e-07, 1.853e-07, 2.723e-07, 3.964e-07, 5.773e-07, 8.2e-07,
946 1.155e-06, 1.59e-06, 2.076e-06, 2.706e-06, 3.249e-06, 3.848e-06,
947 4.459e-06, 4.986e-06, 5.573e-06, 5.958e-06, 6.328e-06, 6.661e-06,
948 6.9e-06, 7.146e-06, 7.276e-06, 7.374e-06, 7.447e-06, 7.383e-06,
949 7.321e-06, 7.161e-06, 6.879e-06, 6.611e-06, 6.216e-06, 5.765e-06,
950 5.355e-06, 4.905e-06, 4.471e-06, 4.075e-06, 3.728e-06, 3.413e-06,
951 3.125e-06, 2.856e-06, 2.607e-06, 2.379e-06, 2.17e-06, 1.978e-06,
952 1.8e-06, 1.646e-06, 1.506e-06, 1.376e-06, 1.233e-06, 1.102e-06,
953 9.839e-07, 8.771e-07, 7.814e-07, 6.947e-07, 6.102e-07, 5.228e-07,
954 4.509e-07, 3.922e-07, 3.501e-07, 3.183e-07, 2.909e-07, 2.686e-07,
955 2.476e-07, 2.284e-07, 2.109e-07, 2.003e-07, 2.013e-07, 2.022e-07,
956 2.032e-07, 2.042e-07, 2.097e-07, 2.361e-07, 2.656e-07, 2.989e-07,
957 3.37e-07, 3.826e-07, 4.489e-07, 5.26e-07, 6.189e-07, 7.312e-07,
958 8.496e-07, 8.444e-07, 8.392e-07, 8.339e-07, 8.286e-07, 8.234e-07,
959 8.181e-07, 8.129e-07, 8.077e-07, 8.026e-07, 6.918e-07, 5.176e-07,
960 3.865e-07, 2.885e-07, 2.156e-07, 1.619e-07, 1.219e-07, 9.161e-08,
961 6.972e-08, 5.399e-08, 3.498e-08, 2.111e-08, 1.322e-08, 8.482e-09,
962 5.527e-09, 3.423e-09, 2.071e-09, 1.314e-09, 8.529e-10, 5.503e-10,
963 3.665e-10
964 };
965
966 static const double ocs[121] = {
967 6e-10, 6e-10, 6e-10, 6e-10, 6e-10, 6e-10, 6e-10, 6e-10, 6e-10, 5.997e-10,
968 5.989e-10, 5.881e-10, 5.765e-10, 5.433e-10, 5.074e-10, 4.567e-10,
969 4.067e-10, 3.601e-10, 3.093e-10, 2.619e-10, 2.232e-10, 1.805e-10,
970 1.46e-10, 1.187e-10, 8.03e-11, 5.435e-11, 3.686e-11, 2.217e-11,
971 1.341e-11, 8.756e-12, 4.511e-12, 2.37e-12, 1.264e-12, 8.28e-13,
972 5.263e-13, 3.209e-13, 1.717e-13, 9.068e-14, 4.709e-14, 2.389e-14,
973 1.236e-14, 1.127e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14,
974 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14,
975 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14,
976 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14,
977 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14,
978 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14,
979 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14,
980 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14,
981 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14,
982 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14,
983 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14,
984 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14,
985 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14, 1.091e-14,
986 1.091e-14, 1.091e-14, 1.091e-14
987 };
988
989 static const double sf6[121] = {
990 4.103e-12, 4.103e-12, 4.103e-12, 4.103e-12, 4.103e-12, 4.103e-12,
991 4.103e-12, 4.103e-12, 4.103e-12, 4.087e-12, 4.064e-12, 4.023e-12,
992 3.988e-12, 3.941e-12, 3.884e-12, 3.755e-12, 3.622e-12, 3.484e-12,
993 3.32e-12, 3.144e-12, 2.978e-12, 2.811e-12, 2.653e-12, 2.489e-12,
994 2.332e-12, 2.199e-12, 2.089e-12, 2.013e-12, 1.953e-12, 1.898e-12,
995 1.859e-12, 1.826e-12, 1.798e-12, 1.776e-12, 1.757e-12, 1.742e-12,
996 1.728e-12, 1.717e-12, 1.707e-12, 1.698e-12, 1.691e-12, 1.685e-12,
997 1.679e-12, 1.675e-12, 1.671e-12, 1.668e-12, 1.665e-12, 1.663e-12,
998 1.661e-12, 1.659e-12, 1.658e-12, 1.657e-12, 1.656e-12, 1.655e-12,
999 1.654e-12, 1.653e-12, 1.653e-12, 1.652e-12, 1.652e-12, 1.652e-12,
1000 1.651e-12, 1.651e-12, 1.651e-12, 1.651e-12, 1.651e-12, 1.651e-12,
1001 1.651e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12,
1002 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12,
1003 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12,
1004 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12,
1005 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12,
1006 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12,
1007 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12,
1008 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12, 1.65e-12
1009 };
1010
1011 static const double so2[121] = {
1012 1e-10, 1e-10, 1e-10, 1e-10, 1e-10, 1e-10, 1e-10, 1e-10, 1e-10, 1e-10,
1013 1e-10, 1e-10, 9.867e-11, 9.537e-11, 9e-11, 8.404e-11, 7.799e-11,
1014 7.205e-11, 6.616e-11, 6.036e-11, 5.475e-11, 5.007e-11, 4.638e-11,
1015 4.346e-11, 4.055e-11, 3.763e-11, 3.471e-11, 3.186e-11, 2.905e-11,
1016 2.631e-11, 2.358e-11, 2.415e-11, 2.949e-11, 3.952e-11, 5.155e-11,
1017 6.76e-11, 8.741e-11, 1.099e-10, 1.278e-10, 1.414e-10, 1.512e-10,
1018 1.607e-10, 1.699e-10, 1.774e-10, 1.832e-10, 1.871e-10, 1.907e-10,
1019 1.943e-10, 1.974e-10, 1.993e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10,
1020 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10,
1021 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10,
1022 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10,
1023 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10,
1024 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10,
1025 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10,
1026 2e-10, 2e-10, 2e-10, 2e-10, 2e-10, 2e-10
1027 };
1028
1029 const double *q[NG] = { NULL };
1030
1031 /* Identify variable... */
1032 for (int ig = 0; ig < ctl->ng; ig++) {
1033 q[ig] = NULL;
1034 if (strcasecmp(ctl->emitter[ig], "C2H2") == 0)
1035 q[ig] = c2h2;
1036 if (strcasecmp(ctl->emitter[ig], "C2H6") == 0)
1037 q[ig] = c2h6;
1038 if (strcasecmp(ctl->emitter[ig], "CCl4") == 0)
1039 q[ig] = ccl4;
1040 if (strcasecmp(ctl->emitter[ig], "CH3OH") == 0)
1041 q[ig] = ch3oh;
1042 if (strcasecmp(ctl->emitter[ig], "CH4") == 0)
1043 q[ig] = ch4;
1044 if (strcasecmp(ctl->emitter[ig], "ClO") == 0)
1045 q[ig] = clo;
1046 if (strcasecmp(ctl->emitter[ig], "ClONO2") == 0)
1047 q[ig] = clono2;
1048 if (strcasecmp(ctl->emitter[ig], "CO") == 0)
1049 q[ig] = co;
1050 if (strcasecmp(ctl->emitter[ig], "COF2") == 0)
1051 q[ig] = cof2;
1052 if (strcasecmp(ctl->emitter[ig], "F11") == 0)
1053 q[ig] = f11;
1054 if (strcasecmp(ctl->emitter[ig], "F113") == 0)
1055 q[ig] = f113;
1056 if (strcasecmp(ctl->emitter[ig], "F114") == 0)
1057 q[ig] = f114;
1058 if (strcasecmp(ctl->emitter[ig], "F12") == 0)
1059 q[ig] = f12;
1060 if (strcasecmp(ctl->emitter[ig], "F14") == 0)
1061 q[ig] = f14;
1062 if (strcasecmp(ctl->emitter[ig], "F22") == 0)
1063 q[ig] = f22;
1064 if (strcasecmp(ctl->emitter[ig], "H2CO") == 0)
1065 q[ig] = h2co;
1066 if (strcasecmp(ctl->emitter[ig], "H2O") == 0)
1067 q[ig] = h2o;
1068 if (strcasecmp(ctl->emitter[ig], "H2O2") == 0)
1069 q[ig] = h2o2;
1070 if (strcasecmp(ctl->emitter[ig], "HCl") == 0)
1071 q[ig] = hcl;
1072 if (strcasecmp(ctl->emitter[ig], "HCN") == 0)
1073 q[ig] = hcn;
1074 if (strcasecmp(ctl->emitter[ig], "HF") == 0)
1075 q[ig] = hf;
1076 if (strcasecmp(ctl->emitter[ig], "HNO3") == 0)
1077 q[ig] = hno3;
1078 if (strcasecmp(ctl->emitter[ig], "HNO4") == 0)
1079 q[ig] = hno4;
1080 if (strcasecmp(ctl->emitter[ig], "HOCl") == 0)
1081 q[ig] = hocl;
1082 if (strcasecmp(ctl->emitter[ig], "N2O") == 0)
1083 q[ig] = n2o;
1084 if (strcasecmp(ctl->emitter[ig], "N2O5") == 0)
1085 q[ig] = n2o5;
1086 if (strcasecmp(ctl->emitter[ig], "NH3") == 0)
1087 q[ig] = nh3;
1088 if (strcasecmp(ctl->emitter[ig], "NO") == 0)
1089 q[ig] = no;
1090 if (strcasecmp(ctl->emitter[ig], "NO2") == 0)
1091 q[ig] = no2;
1092 if (strcasecmp(ctl->emitter[ig], "O3") == 0)
1093 q[ig] = o3;
1094 if (strcasecmp(ctl->emitter[ig], "OCS") == 0)
1095 q[ig] = ocs;
1096 if (strcasecmp(ctl->emitter[ig], "SF6") == 0)
1097 q[ig] = sf6;
1098 if (strcasecmp(ctl->emitter[ig], "SO2") == 0)
1099 q[ig] = so2;
1100 }
1101
1102 /* Loop over atmospheric data points... */
1103 for (int ip = 0; ip < atm->np; ip++) {
1104
1105 /* Get altitude index... */
1106 const int iz = locate_reg(z, 121, atm->z[ip]);
1107
1108 /* Interpolate pressure... */
1109 atm->p[ip] = LOGY(z[iz], pre[iz], z[iz + 1], pre[iz + 1], atm->z[ip]);
1110
1111 /* Interpolate temperature... */
1112 atm->t[ip] = LIN(z[iz], tem[iz], z[iz + 1], tem[iz + 1], atm->z[ip]);
1113
1114 /* Interpolate trace gases... */
1115 for (int ig = 0; ig < ctl->ng; ig++)
1116 if (q[ig] != NULL)
1117 atm->q[ig][ip] =
1118 LIN(z[iz], q[ig][iz], z[iz + 1], q[ig][iz + 1], atm->z[ip]);
1119 else
1120 atm->q[ig][ip] = 0;
1121
1122 /* Set CO2... */
1123 if (ctl->ig_co2 >= 0)
1124 atm->q[ctl->ig_co2][ip] = CO2_FIT(atm->time[ip]);
1125
1126 /* Set N2... */
1127 if (ctl->ig_n2 >= 0)
1128 atm->q[ctl->ig_n2][ip] = N2;
1129
1130 /* Set O2... */
1131 if (ctl->ig_o2 >= 0)
1132 atm->q[ctl->ig_o2][ip] = O2;
1133
1134 /* Set extinction to zero... */
1135 for (int iw = 0; iw < ctl->nw; iw++)
1136 atm->k[iw][ip] = 0;
1137
1138 /* Set cloud layer... */
1139 atm->clz = atm->cldz = 0;
1140 for (int icl = 0; icl < ctl->ncl; icl++)
1141 atm->clk[icl] = 0;
1142
1143 /* Set surface... */
1144 atm->sft = 0;
1145 for (int isf = 0; isf < ctl->nsf; isf++)
1146 atm->sfeps[isf] = 1;
1147 }
1148}
int locate_reg(const double *xx, const int n, const double x)
Locate index for interpolation on a regular (uniform) grid.
Definition: jurassic.c:4519
#define O2
Oxygen concentration.
Definition: jurassic.h:222
#define CO2_FIT(TIME)
Climatological CO2 volume mixing ratio as a quadratic function of time.
Definition: jurassic.h:493
#define LOGY(x0, y0, x1, y1, x)
Compute logarithmic interpolation in y.
Definition: jurassic.h:653
#define NG
Maximum number of emitters.
Definition: jurassic.h:306
#define N2
Nitrogen concentration.
Definition: jurassic.h:217
double time[NP]
Time (seconds since 2000-01-01T00:00Z).
Definition: jurassic.h:1412
int ig_co2
Emitter index of CO2.
Definition: jurassic.h:1468
int ig_o2
Emitter index of O2.
Definition: jurassic.h:1477
int ig_n2
Emitter index of N2.
Definition: jurassic.h:1474
char emitter[NG][LEN]
Name of each emitter.
Definition: jurassic.h:1465
Here is the call graph for this function:

◆ cos_sza()

double cos_sza ( const double  sec,
const double  lon,
const double  lat 
)

Calculates the cosine of the solar zenith angle.

This function computes the cosine of the solar zenith angle (SZA), which describes the angle between the local zenith (straight up) and the line connecting the observer to the center of the Sun. The cosine of the SZA is often used directly in radiative transfer and photochemical calculations to avoid unnecessary use of trigonometric inverse functions.

Parameters
secSeconds elapsed since 2000-01-01T12:00Z.
lonObserver's longitude in degrees.
latObserver's latitude in degrees.
Returns
The cosine of the solar zenith angle (dimensionless, range [-1, 1]).

The cosine of the solar zenith angle is computed based on the observer's position (longitude and latitude) and the specified time in seconds elapsed since 2000-01-01T12:00Z.

Note
The input longitude and latitude must be specified in degrees.
See also
acos() — can be used to convert the returned value to the solar zenith angle in radians if needed.
Author
Lars Hoffmann

Definition at line 1152 of file jurassic.c.

1155 {
1156
1157 /* Number of days and fraction with respect to 2000-01-01T12:00Z... */
1158 const double D = sec / 86400 - 0.5;
1159
1160 /* Geocentric apparent ecliptic longitude [rad]... */
1161 const double g = DEG2RAD(357.529 + 0.98560028 * D);
1162 const double q = 280.459 + 0.98564736 * D;
1163 const double L = DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
1164
1165 /* Mean obliquity of the ecliptic [rad]... */
1166 const double e = DEG2RAD(23.439 - 0.00000036 * D);
1167
1168 /* Declination [rad]... */
1169 const double sindec = sin(e) * sin(L);
1170
1171 /* Right ascension [rad]... */
1172 const double ra = atan2(cos(e) * sin(L), cos(L));
1173
1174 /* Greenwich Mean Sidereal Time [h]... */
1175 const double GMST = 18.697374558 + 24.06570982441908 * D;
1176
1177 /* Local Sidereal Time [h]... */
1178 const double LST = GMST + lon / 15;
1179
1180 /* Hour angle [rad]... */
1181 const double h = LST / 12 * M_PI - ra;
1182
1183 /* Convert latitude... */
1184 const double lat_help = DEG2RAD(lat);
1185
1186 /* Return cosine of solar zenith angle... */
1187 return sin(lat_help) * sindec + cos(lat_help)
1188 * sqrt(1 - POW2(sindec)) * cos(h);
1189}
#define DEG2RAD(deg)
Convert degrees to radians.
Definition: jurassic.h:513

◆ cost_function()

double cost_function ( const gsl_vector *  dx,
const gsl_vector *  dy,
const gsl_matrix *  s_a_inv,
const gsl_vector *  sig_eps_inv 
)

Compute the normalized quadratic cost function for optimal estimation.

Evaluates the cost function

\[ J = \frac{1}{m} \left[ (\mathbf{y} - \mathbf{y_a})^T \mathbf{S_\epsilon^{-1}} (\mathbf{y} - \mathbf{y_a}) + (\mathbf{x} - \mathbf{x_a})^T \mathbf{S_a^{-1}} (\mathbf{x} - \mathbf{x_a}) \right] \]

where \(\mathbf{dx} = \mathbf{x} - \mathbf{x_a}\) and \(\mathbf{dy} = \mathbf{y} - \mathbf{y_a}\) represent the deviations from a priori state and measurement vectors, respectively.

Parameters
[in]dxState deviation vector (x - x_a).
[in]dyMeasurement deviation vector (y - y_a).
[in]s_a_invInverse of the a priori covariance matrix ( \(\mathbf{S_a^{-1}}\)).
[in]sig_eps_invVector of inverse measurement uncertainties ( \(\mathbf{S_\epsilon^{-1/2}}\) diagonal elements).
Returns
Normalized cost function value (dimensionless).
  • Implements the standard Optimal Estimation Method (Rodgers, 2000) cost function.
  • The first term ( \(\chi^2_m\)) measures the weighted measurement residuals: \(\chi^2_m = \sum_i (dy_i / \sigma_{\epsilon,i})^2\).
  • The second term ( \(\chi^2_a\)) measures the deviation from the a priori state: \(\chi^2_a = dx^T \mathbf{S_a^{-1}} dx\).
  • The result is normalized by the number of measurements \(m\) for scale consistency.
See also
retrieval, s_a_inv, sig_eps_inv
Note
  • Assumes diagonal measurement error covariance (independent measurements).
  • The covariance matrices must be positive-definite and properly dimensioned.
  • The function does not modify the input vectors.
Author
Lars Hoffmann

Definition at line 1193 of file jurassic.c.

1197 {
1198
1199 double chisq_a, chisq_m = 0;
1200
1201 /* Get sizes... */
1202 const size_t m = dy->size;
1203 const size_t n = dx->size;
1204
1205 /* Allocate... */
1206 gsl_vector *x_aux = gsl_vector_alloc(n);
1207
1208 /* Determine normalized cost function...
1209 (chi^2 = 1/m * [dy^T * S_eps^{-1} * dy + dx^T * S_a^{-1} * dx]) */
1210 for (size_t i = 0; i < m; i++)
1211 chisq_m += POW2(gsl_vector_get(dy, i) * gsl_vector_get(sig_eps_inv, i));
1212 gsl_blas_dgemv(CblasNoTrans, 1.0, s_a_inv, dx, 0.0, x_aux);
1213 gsl_blas_ddot(dx, x_aux, &chisq_a);
1214
1215 /* Free... */
1216 gsl_vector_free(x_aux);
1217
1218 /* Return cost function value... */
1219 return (chisq_m + chisq_a) / (double) m;
1220}

◆ ctmco2()

double ctmco2 ( const double  nu,
const double  p,
const double  t,
const double  u 
)

Compute carbon dioxide continuum optical depth.

Uses the RFM CO2 continuum coefficients tabulated from 0 to 4000 cm^-1 at 230, 260, and 296 K. The coefficients represent residual CO2 line-wing absorption outside the +/-25 cm^-1 line-calculation interval.

Parameters
[in]nuWavenumber [cm^-1].
[in]pPressure [hPa].
[in]tTemperature [K].
[in]uCO2 column density [molecules cm^-2].
Returns
CO2 continuum optical depth.
References
Clough et al., Proc. SPIE 277, 152–166 (1981).

Clough et al., Current Issues in Atmospheric Transparency, CUEN (1987).

Author
Lars Hoffmann

Definition at line 1224 of file jurassic.c.

1228 {
1229
1230 static const double co2296[2001] =
1231 { 9.3388e-5, 9.7711e-5, 1.0224e-4, 1.0697e-4,
1232 1.1193e-4, 1.1712e-4, 1.2255e-4, 1.2824e-4, 1.3419e-4, 1.4043e-4,
1233 1.4695e-4, 1.5378e-4, 1.6094e-4, 1.6842e-4, 1.7626e-4, 1.8447e-4,
1234 1.9307e-4, 2.0207e-4, 2.1149e-4, 2.2136e-4, 2.3169e-4, 2.4251e-4,
1235 2.5384e-4, 2.657e-4, 2.7813e-4, 2.9114e-4, 3.0477e-4, 3.1904e-4,
1236 3.3399e-4, 3.4965e-4, 3.6604e-4, 3.8322e-4, 4.0121e-4, 4.2006e-4,
1237 4.398e-4, 4.6047e-4, 4.8214e-4, 5.0483e-4, 5.286e-4, 5.535e-4,
1238 5.7959e-4, 6.0693e-4, 6.3557e-4, 6.6558e-4, 6.9702e-4, 7.2996e-4,
1239 7.6449e-4, 8.0066e-4, 8.3856e-4, 8.7829e-4, 9.1991e-4, 9.6354e-4,
1240 .0010093, .0010572, .0011074, .00116, .0012152, .001273,
1241 .0013336, .0013972, .0014638, .0015336, .0016068, .0016835,
1242 .001764, .0018483, .0019367, .0020295, .0021267, .0022286,
1243 .0023355, .0024476, .0025652, .0026885, .0028178, .0029534,
1244 .0030956, .0032448, .0034012, .0035654, .0037375, .0039181,
1245 .0041076, .0043063, .0045148, .0047336, .0049632, .005204,
1246 .0054567, .0057219, .0060002, .0062923, .0065988, .0069204,
1247 .007258, .0076123, .0079842, .0083746, .0087844, .0092146,
1248 .0096663, .01014, .010638, .011161, .01171, .012286, .012891,
1249 .013527, .014194, .014895, .015631, .016404, .017217, .01807,
1250 .018966, .019908, .020897, .021936, .023028, .024176, .025382,
1251 .026649, .027981, .02938, .030851, .032397, .034023, .035732,
1252 .037528, .039416, .041402, .04349, .045685, .047994, .050422,
1253 .052975, .055661, .058486, .061458, .064584, .067873, .071334,
1254 .074975, .078807, .082839, .087082, .091549, .096249, .1012,
1255 .10641, .11189, .11767, .12375, .13015, .13689, .14399, .15147,
1256 .15935, .16765, .17639, .18561, .19531, .20554, .21632, .22769,
1257 .23967, .25229, .2656, .27964, .29443, .31004, .3265, .34386,
1258 .36218, .3815, .40188, .42339, .44609, .47004, .49533, .52202,
1259 .5502, .57995, .61137, .64455, .6796, .71663, .75574, .79707,
1260 .84075, .88691, .9357, .98728, 1.0418, 1.0995, 1.1605, 1.225,
1261 1.2932, 1.3654, 1.4418, 1.5227, 1.6083, 1.6989, 1.7948, 1.8964,
1262 2.004, 2.118, 2.2388, 2.3668, 2.5025, 2.6463, 2.7988, 2.9606,
1263 3.1321, 3.314, 3.5071, 3.712, 3.9296, 4.1605, 4.4058, 4.6663,
1264 4.9431, 5.2374, 5.5501, 5.8818, 6.2353, 6.6114, 7.0115, 7.4372,
1265 7.8905, 8.3731, 8.8871, 9.4349, 10.019, 10.641, 11.305, 12.013,
1266 12.769, 13.576, 14.437, 15.358, 16.342, 17.39, 18.513, 19.716,
1267 21.003, 22.379, 23.854, 25.436, 27.126, 28.942, 30.89, 32.973,
1268 35.219, 37.634, 40.224, 43.021, 46.037, 49.29, 52.803, 56.447,
1269 60.418, 64.792, 69.526, 74.637, 80.182, 86.193, 92.713, 99.786,
1270 107.47, 115.84, 124.94, 134.86, 145.69, 157.49, 170.3, 184.39,
1271 199.83, 216.4, 234.55, 254.72, 276.82, 299.85, 326.16, 354.99,
1272 386.51, 416.68, 449.89, 490.12, 534.35, 578.25, 632.26, 692.61,
1273 756.43, 834.75, 924.11, 1016.9, 996.96, 1102.7, 1219.2, 1351.9,
1274 1494.3, 1654.1, 1826.5, 2027.9, 2249., 2453.8, 2714.4, 2999.4,
1275 3209.5, 3509., 3840.4, 3907.5, 4190.7, 4533.5, 4648.3, 5059.1,
1276 5561.6, 6191.4, 6820.8, 7905.9, 9362.2, 2431.3, 2211.3, 2046.8,
1277 2023.8, 1985.9, 1905.9, 1491.1, 1369.8, 1262.2, 1200.7, 887.74,
1278 820.25, 885.23, 887.21, 816.73, 1126.9, 1216.2, 1272.4, 1579.5,
1279 1634.2, 1656.3, 1657.9, 1789.5, 1670.8, 1509.5, 8474.6, 7489.2,
1280 6793.6, 6117., 5574.1, 5141.2, 5084.6, 4745.1, 4413.2, 4102.8,
1281 4024.7, 3715., 3398.6, 3100.8, 2900.4, 2629.2, 2374., 2144.7,
1282 1955.8, 1760.8, 1591.2, 1435.2, 1296.2, 1174., 1065.1, 967.76,
1283 999.48, 897.45, 809.23, 732.77, 670.26, 611.93, 560.11, 518.77,
1284 476.84, 438.8, 408.48, 380.21, 349.24, 322.71, 296.65, 272.85,
1285 251.96, 232.04, 213.88, 197.69, 182.41, 168.41, 155.79, 144.05,
1286 133.31, 123.48, 114.5, 106.21, 98.591, 91.612, 85.156, 79.204,
1287 73.719, 68.666, 63.975, 59.637, 56.35, 52.545, 49.042, 45.788,
1288 42.78, 39.992, 37.441, 35.037, 32.8, 30.744, 28.801, 26.986,
1289 25.297, 23.731, 22.258, 20.883, 19.603, 18.403, 17.295, 16.249,
1290 15.271, 14.356, 13.501, 12.701, 11.954, 11.254, 10.6, 9.9864,
1291 9.4118, 8.8745, 8.3714, 7.8997, 7.4578, 7.0446, 6.6573, 6.2949,
1292 5.9577, 5.6395, 5.3419, 5.063, 4.8037, 4.5608, 4.3452, 4.1364,
1293 3.9413, 3.7394, 3.562, 3.3932, 3.2325, 3.0789, 2.9318, 2.7898,
1294 2.6537, 2.5225, 2.3958, 2.2305, 2.1215, 2.0245, 1.9427, 1.8795,
1295 1.8336, 1.7604, 1.7016, 1.6419, 1.5282, 1.4611, 1.3443, 1.27,
1296 1.1675, 1.0824, 1.0534, .99833, .95854, .92981, .90887, .89346,
1297 .88113, .87068, .86102, .85096, .88262, .86151, .83565, .80518,
1298 .77045, .73736, .74744, .74954, .75773, .82267, .83493, .89402,
1299 .89725, .93426, .95564, .94045, .94174, .93404, .92035, .90456,
1300 .88621, .86673, .78117, .7515, .72056, .68822, .65658, .62764,
1301 .55984, .55598, .57407, .60963, .63763, .66198, .61132, .60972,
1302 .52496, .50649, .41872, .3964, .32422, .27276, .24048, .23772,
1303 .2286, .22711, .23999, .32038, .34371, .36621, .38561, .39953,
1304 .40636, .44913, .42716, .3919, .35477, .33935, .3351, .39746,
1305 .40993, .49398, .49956, .56157, .54742, .57295, .57386, .55417,
1306 .50745, .471, .43446, .39102, .34993, .31269, .27888, .24912,
1307 .22291, .19994, .17972, .16197, .14633, .13252, .12029, .10942,
1308 .099745, .091118, .083404, .076494, .070292, .064716, .059697,
1309 .055173, .051093, .047411, .044089, .041092, .038392, .035965,
1310 .033789, .031846, .030122, .028607, .02729, .026169, .025209,
1311 .024405, .023766, .023288, .022925, .022716, .022681, .022685,
1312 .022768, .023133, .023325, .023486, .024004, .024126, .024083,
1313 .023785, .024023, .023029, .021649, .021108, .019454, .017809,
1314 .017292, .016635, .017037, .018068, .018977, .018756, .017847,
1315 .016557, .016142, .014459, .012869, .012381, .010875, .0098701,
1316 .009285, .0091698, .0091701, .0096145, .010553, .01106, .012613,
1317 .014362, .015017, .016507, .017741, .01768, .017784, .0171,
1318 .016357, .016172, .017257, .018978, .020935, .021741, .023567,
1319 .025183, .025589, .026732, .027648, .028278, .028215, .02856,
1320 .029015, .029062, .028851, .028497, .027825, .027801, .026523,
1321 .02487, .022967, .022168, .020194, .018605, .017903, .018439,
1322 .019697, .020311, .020855, .020057, .018608, .016738, .015963,
1323 .013844, .011801, .011134, .0097573, .0086007, .0086226,
1324 .0083721, .0090978, .0097616, .0098426, .011317, .012853, .01447,
1325 .014657, .015771, .016351, .016079, .014829, .013431, .013185,
1326 .013207, .01448, .016176, .017971, .018265, .019526, .020455,
1327 .019797, .019802, .0194, .018176, .017505, .016197, .015339,
1328 .014401, .013213, .012203, .011186, .010236, .0093288, .0084854,
1329 .0076837, .0069375, .0062614, .0056628, .0051153, .0046015,
1330 .0041501, .003752, .0033996, .0030865, .0028077, .0025586,
1331 .0023355, .0021353, .0019553, .0017931, .0016466, .0015141,
1332 .0013941, .0012852, .0011862, .0010962, .0010142, 9.3935e-4,
1333 8.71e-4, 8.0851e-4, 7.5132e-4, 6.9894e-4, 6.5093e-4, 6.0689e-4,
1334 5.6647e-4, 5.2935e-4, 4.9525e-4, 4.6391e-4, 4.3509e-4, 4.086e-4,
1335 3.8424e-4, 3.6185e-4, 3.4126e-4, 3.2235e-4, 3.0498e-4, 2.8904e-4,
1336 2.7444e-4, 2.6106e-4, 2.4883e-4, 2.3766e-4, 2.275e-4, 2.1827e-4,
1337 2.0992e-4, 2.0239e-4, 1.9563e-4, 1.896e-4, 1.8427e-4, 1.796e-4,
1338 1.7555e-4, 1.7209e-4, 1.692e-4, 1.6687e-4, 1.6505e-4, 1.6375e-4,
1339 1.6294e-4, 1.6261e-4, 1.6274e-4, 1.6334e-4, 1.6438e-4, 1.6587e-4,
1340 1.678e-4, 1.7017e-4, 1.7297e-4, 1.762e-4, 1.7988e-4, 1.8399e-4,
1341 1.8855e-4, 1.9355e-4, 1.9902e-4, 2.0494e-4, 2.1134e-4, 2.1823e-4,
1342 2.2561e-4, 2.335e-4, 2.4192e-4, 2.5088e-4, 2.604e-4, 2.705e-4,
1343 2.8119e-4, 2.9251e-4, 3.0447e-4, 3.171e-4, 3.3042e-4, 3.4447e-4,
1344 3.5927e-4, 3.7486e-4, 3.9127e-4, 4.0854e-4, 4.267e-4, 4.4579e-4,
1345 4.6586e-4, 4.8696e-4, 5.0912e-4, 5.324e-4, 5.5685e-4, 5.8253e-4,
1346 6.0949e-4, 6.378e-4, 6.6753e-4, 6.9873e-4, 7.3149e-4, 7.6588e-4,
1347 8.0198e-4, 8.3987e-4, 8.7964e-4, 9.2139e-4, 9.6522e-4, .0010112,
1348 .0010595, .0011102, .0011634, .0012193, .001278, .0013396,
1349 .0014043, .0014722, .0015436, .0016185, .0016972, .0017799,
1350 .0018668, .001958, .0020539, .0021547, .0022606, .0023719,
1351 .002489, .002612, .0027414, .0028775, .0030206, .0031712,
1352 .0033295, .0034962, .0036716, .0038563, .0040506, .0042553,
1353 .0044709, .004698, .0049373, .0051894, .0054552, .0057354,
1354 .006031, .0063427, .0066717, .0070188, .0073854, .0077726,
1355 .0081816, .0086138, .0090709, .0095543, .010066, .010607,
1356 .011181, .011789, .012433, .013116, .013842, .014613, .015432,
1357 .016304, .017233, .018224, .019281, .020394, .021574, .022836,
1358 .024181, .025594, .027088, .028707, .030401, .032245, .034219,
1359 .036262, .038539, .040987, .043578, .04641, .04949, .052726,
1360 .056326, .0602, .064093, .068521, .073278, .077734, .083064,
1361 .088731, .093885, .1003, .1072, .11365, .12187, .13078, .13989,
1362 .15095, .16299, .17634, .19116, .20628, .22419, .24386, .26587,
1363 .28811, .31399, .34321, .36606, .39675, .42742, .44243, .47197,
1364 .49993, .49027, .51147, .52803, .48931, .49729, .5026, .43854,
1365 .441, .44766, .43414, .46151, .50029, .55247, .43855, .32115,
1366 .32607, .3431, .36119, .38029, .41179, .43996, .47144, .51853,
1367 .55362, .59122, .66338, .69877, .74001, .82923, .86907, .90361,
1368 1.0025, 1.031, 1.0559, 1.104, 1.1178, 1.1341, 1.1547, 1.351,
1369 1.4772, 1.4812, 1.4907, 1.512, 1.5442, 1.5853, 1.6358, 1.6963,
1370 1.7674, 1.8474, 1.9353, 2.0335, 2.143, 2.2592, 2.3853, 2.5217,
1371 2.6686, 2.8273, 2.9998, 3.183, 3.3868, 3.6109, 3.8564, 4.1159,
1372 4.4079, 4.7278, 5.0497, 5.3695, 5.758, 6.0834, 6.4976, 6.9312,
1373 7.38, 7.5746, 7.9833, 8.3791, 8.3956, 8.7501, 9.1067, 9.072,
1374 9.4649, 9.9112, 10.402, 10.829, 11.605, 12.54, 12.713, 10.443,
1375 10.825, 11.375, 11.955, 12.623, 13.326, 14.101, 15.041, 15.547,
1376 16.461, 17.439, 18.716, 19.84, 21.036, 22.642, 23.901, 25.244,
1377 27.03, 28.411, 29.871, 31.403, 33.147, 34.744, 36.456, 39.239,
1378 43.605, 45.162, 47.004, 49.093, 51.391, 53.946, 56.673, 59.629,
1379 63.167, 66.576, 70.254, 74.222, 78.477, 83.034, 87.914, 93.18,
1380 98.77, 104.74, 111.15, 117.95, 125.23, 133.01, 141.33, 150.21,
1381 159.71, 169.89, 180.93, 192.54, 204.99, 218.34, 232.65, 248.,
1382 264.47, 282.14, 301.13, 321.53, 343.48, 367.08, 392.5, 419.88,
1383 449.4, 481.26, 515.64, 552.79, 592.99, 636.48, 683.61, 734.65,
1384 789.99, 850.02, 915.14, 985.81, 1062.5, 1147.1, 1237.8, 1336.4,
1385 1443.2, 1558.9, 1684.2, 1819.2, 1965.2, 2122.6, 2291.7, 2470.8,
1386 2665.7, 2874.9, 3099.4, 3337.9, 3541., 3813.3, 4111.9, 4439.3,
1387 4798.9, 5196., 5639.2, 6087.5, 6657.7, 7306.7, 8040.7, 8845.5,
1388 9702.2, 10670., 11739., 12842., 14141., 15498., 17068., 18729.,
1389 20557., 22559., 25248., 27664., 30207., 32915., 35611., 38081.,
1390 40715., 43191., 41651., 42750., 43785., 44353., 44366., 44189.,
1391 43618., 42862., 41878., 35133., 35215., 36383., 39420., 44055.,
1392 44155., 45850., 46853., 39197., 38274., 29942., 28553., 21792.,
1393 21228., 17106., 14955., 18181., 19557., 21427., 23728., 26301.,
1394 28584., 30775., 32536., 33867., 40089., 39204., 37329., 34452.,
1395 31373., 33921., 34800., 36043., 44415., 45162., 52181., 50895.,
1396 54140., 50840., 50468., 48302., 44915., 40910., 36754., 32755.,
1397 29093., 25860., 22962., 20448., 18247., 16326., 14645., 13165.,
1398 11861., 10708., 9686.9, 8779.7, 7971.9, 7250.8, 6605.7, 6027.2,
1399 5507.3, 5039.1, 4616.6, 4234.8, 3889., 3575.4, 3290.5, 3031.3,
1400 2795.2, 2579.9, 2383.1, 2203.3, 2038.6, 1887.6, 1749.1, 1621.9,
1401 1505., 1397.4, 1298.3, 1207., 1122.8, 1045., 973.1, 906.64,
1402 845.16, 788.22, 735.48, 686.57, 641.21, 599.1, 559.99, 523.64,
1403 489.85, 458.42, 429.16, 401.92, 376.54, 352.88, 330.82, 310.24,
1404 291.03, 273.09, 256.34, 240.69, 226.05, 212.37, 199.57, 187.59,
1405 176.37, 165.87, 156.03, 146.82, 138.17, 130.07, 122.47, 115.34,
1406 108.65, 102.37, 96.473, 90.934, 85.73, 80.84, 76.243, 71.922,
1407 67.858, 64.034, 60.438, 57.052, 53.866, 50.866, 48.04, 45.379,
1408 42.872, 40.51, 38.285, 36.188, 34.211, 32.347, 30.588, 28.929,
1409 27.362, 25.884, 24.489, 23.171, 21.929, 20.755, 19.646, 18.599,
1410 17.61, 16.677, 15.795, 14.961, 14.174, 13.43, 12.725, 12.06,
1411 11.431, 10.834, 10.27, 9.7361, 9.2302, 8.7518, 8.2997, 7.8724,
1412 7.4674, 7.0848, 6.7226, 6.3794, 6.054, 5.745, 5.4525, 5.1752,
1413 4.9121, 4.6625, 4.4259, 4.2015, 3.9888, 3.7872, 3.5961, 3.4149,
1414 3.2431, 3.0802, 2.9257, 2.7792, 2.6402, 2.5084, 2.3834, 2.2648,
1415 2.1522, 2.0455, 1.9441, 1.848, 1.7567, 1.6701, 1.5878, 1.5097,
1416 1.4356, 1.3651, 1.2981, 1.2345, 1.174, 1.1167, 1.062, 1.0101,
1417 .96087, .91414, .86986, .82781, .78777, .74971, .71339, .67882,
1418 .64604, .61473, .58507, .55676, .52987, .5044, .48014, .45715,
1419 .43527, .41453, .3948, .37609, .35831, .34142, .32524, .30995,
1420 .29536, .28142, .26807, .25527, .24311, .23166, .22077, .21053,
1421 .20081, .19143, .18261, .17407, .16603, .15833, .15089, .14385,
1422 .13707, .13065, .12449, .11865, .11306, .10774, .10266, .097818,
1423 .093203, .088815, .084641, .080671, .076892, .073296, .069873,
1424 .066613, .06351, .060555, .05774, .055058, .052504, .050071,
1425 .047752, .045543, .043438, .041432, .039521, .037699, .035962,
1426 .034307, .032729, .031225, .029791, .028423, .02712, .025877,
1427 .024692, .023563, .022485, .021458, .020478, .019543, .018652,
1428 .017802, .016992, .016219, .015481, .014778, .014107, .013467,
1429 .012856, .012274, .011718, .011188, .010682, .0102, .0097393,
1430 .0093001, .008881, .0084812, .0080997, .0077358, .0073885,
1431 .0070571, .0067409, .0064393, .0061514, .0058768, .0056147,
1432 .0053647, .0051262, .0048987, .0046816, .0044745, .0042769,
1433 .0040884, .0039088, .0037373, .0035739, .003418, .0032693,
1434 .0031277, .0029926, .0028639, .0027413, .0026245, .0025133,
1435 .0024074, .0023066, .0022108, .0021196, .002033, .0019507,
1436 .0018726, .0017985, .0017282, .0016617, .0015988, .0015394,
1437 .0014834, .0014306, .0013811, .0013346, .0012911, .0012506,
1438 .0012131, .0011784, .0011465, .0011175, .0010912, .0010678,
1439 .0010472, .0010295, .0010147, .001003, 9.9428e-4, 9.8883e-4,
1440 9.8673e-4, 9.8821e-4, 9.9343e-4, .0010027, .0010164, .0010348,
1441 .0010586, .0010882, .0011245, .0011685, .0012145, .0012666,
1442 .0013095, .0013688, .0014048, .0014663, .0015309, .0015499,
1443 .0016144, .0016312, .001705, .0017892, .0018499, .0019715,
1444 .0021102, .0022442, .0024284, .0025893, .0027703, .0029445,
1445 .0031193, .003346, .0034552, .0036906, .0037584, .0040084,
1446 .0041934, .0044587, .0047093, .0049759, .0053421, .0055134,
1447 .0059048, .0058663, .0061036, .0063259, .0059657, .0060653,
1448 .0060972, .0055539, .0055653, .0055772, .005331, .0054953,
1449 .0055919, .0058684, .006183, .0066675, .0069808, .0075142,
1450 .0078536, .0084282, .0089454, .0094625, .0093703, .0095857,
1451 .0099283, .010063, .010521, .0097778, .0098175, .010379, .010447,
1452 .0105, .010617, .010706, .01078, .011177, .011212, .011304,
1453 .011446, .011603, .011816, .012165, .012545, .013069, .013539,
1454 .01411, .014776, .016103, .017016, .017994, .018978, .01998,
1455 .021799, .022745, .023681, .024627, .025562, .026992, .027958,
1456 .029013, .030154, .031402, .03228, .033651, .035272, .037088,
1457 .039021, .041213, .043597, .045977, .04877, .051809, .054943,
1458 .058064, .061528, .06537, .069309, .071928, .075752, .079589,
1459 .083352, .084096, .087497, .090817, .091198, .094966, .099045,
1460 .10429, .10867, .11518, .12269, .13126, .14087, .15161, .16388,
1461 .16423, .1759, .18721, .19994, .21275, .22513, .23041, .24231,
1462 .25299, .25396, .26396, .27696, .27929, .2908, .30595, .31433,
1463 .3282, .3429, .35944, .37467, .39277, .41245, .43326, .45649,
1464 .48152, .51897, .54686, .57877, .61263, .64962, .68983, .73945,
1465 .78619, .83537, .89622, .95002, 1.0067, 1.0742, 1.1355, 1.2007,
1466 1.2738, 1.347, 1.4254, 1.5094, 1.6009, 1.6976, 1.8019, 1.9148,
1467 2.0357, 2.166, 2.3066, 2.4579, 2.6208, 2.7966, 2.986, 3.188,
1468 3.4081, 3.6456, 3.9, 4.1747, 4.4712, 4.7931, 5.1359, 5.5097,
1469 5.9117, 6.3435, 6.8003, 7.3001, 7.8385, 8.3945, 9.011, 9.6869,
1470 10.392, 11.18, 12.036, 12.938, 13.944, 14.881, 16.029, 17.255,
1471 18.574, 19.945, 21.38, 22.9, 24.477, 26.128, 27.87, 29.037,
1472 30.988, 33.145, 35.506, 37.76, 40.885, 44.487, 48.505, 52.911,
1473 57.56, 61.964, 67.217, 72.26, 78.343, 85.08, 91.867, 99.435,
1474 107.68, 116.97, 127.12, 138.32, 150.26, 163.04, 174.81, 189.26,
1475 205.61, 224.68, 240.98, 261.88, 285.1, 307.58, 334.35, 363.53,
1476 394.68, 427.85, 458.85, 489.25, 472.87, 486.93, 496.27, 501.52,
1477 501.57, 497.14, 488.09, 476.32, 393.76, 388.51, 393.42, 414.45,
1478 455.12, 514.62, 520.38, 547.42, 562.6, 487.47, 480.83, 391.06,
1479 376.92, 303.7, 295.91, 256.03, 236.73, 280.38, 310.71, 335.53,
1480 367.88, 401.94, 435.52, 469.13, 497.94, 588.82, 597.94, 597.2,
1481 588.28, 571.2, 555.75, 603.56, 638.15, 680.75, 801.72, 848.01,
1482 962.15, 990.06, 1068.1, 1076.2, 1115.3, 1134.2, 1136.6, 1119.1,
1483 1108.9, 1090.6, 1068.7, 1041.9, 1005.4, 967.98, 927.08, 780.1,
1484 751.41, 733.12, 742.65, 785.56, 855.16, 852.45, 878.1, 784.59,
1485 777.81, 765.13, 622.93, 498.09, 474.89, 386.9, 378.48, 336.17,
1486 322.04, 329.57, 350.5, 383.38, 420.02, 462.39, 499.71, 531.98,
1487 654.99, 653.43, 639.99, 605.16, 554.16, 504.42, 540.64, 552.33,
1488 679.46, 699.51, 713.91, 832.17, 919.91, 884.96, 907.57, 846.56,
1489 818.56, 768.93, 706.71, 642.17, 575.95, 515.38, 459.07, 409.02,
1490 364.61, 325.46, 291.1, 260.89, 234.39, 211.01, 190.38, 172.11,
1491 155.91, 141.49, 128.63, 117.13, 106.84, 97.584, 89.262, 81.756,
1492 74.975, 68.842, 63.28, 58.232, 53.641, 49.46, 45.649, 42.168,
1493 38.991, 36.078, 33.409, 30.96, 28.71, 26.642, 24.737, 22.985,
1494 21.37, 19.882, 18.512, 17.242, 16.073, 14.987, 13.984, 13.05,
1495 12.186, 11.384, 10.637, 9.9436, 9.2988, 8.6991, 8.141, 7.6215,
1496 7.1378, 6.6872, 6.2671, 5.8754, 5.51, 5.1691, 4.851, 4.5539,
1497 4.2764, 4.0169, 3.7742, 3.5472, 3.3348, 3.1359, 2.9495, 2.7749,
1498 2.6113, 2.4578, 2.3139, 2.1789, 2.0523, 1.9334, 1.8219, 1.7171,
1499 1.6188, 1.5263, 1.4395, 1.3579, 1.2812, 1.209, 1.1411, 1.0773,
1500 1.0171, .96048, .90713, .85684, .80959, .76495, .72282, .68309,
1501 .64563, .61035, .57707, .54573, .51622, .48834, .46199, .43709,
1502 .41359, .39129, .37034, .35064, .33198, .31442, .29784, .28218,
1503 .26732, .25337, .24017, .22774, .21601, .20479, .19426
1504 };
1505
1506 static const double co2260[2001] =
1507 { 5.7971e-5, 6.0733e-5, 6.3628e-5, 6.6662e-5,
1508 6.9843e-5, 7.3176e-5, 7.6671e-5, 8.0334e-5, 8.4175e-5, 8.8201e-5,
1509 9.2421e-5, 9.6846e-5, 1.0149e-4, 1.0635e-4, 1.1145e-4, 1.1679e-4,
1510 1.224e-4, 1.2828e-4, 1.3444e-4, 1.409e-4, 1.4768e-4, 1.5479e-4,
1511 1.6224e-4, 1.7006e-4, 1.7826e-4, 1.8685e-4, 1.9587e-4, 2.0532e-4,
1512 2.1524e-4, 2.2565e-4, 2.3656e-4, 2.48e-4, 2.6001e-4, 2.7261e-4,
1513 2.8582e-4, 2.9968e-4, 3.1422e-4, 3.2948e-4, 3.4548e-4, 3.6228e-4,
1514 3.799e-4, 3.9838e-4, 4.1778e-4, 4.3814e-4, 4.595e-4, 4.8191e-4,
1515 5.0543e-4, 5.3012e-4, 5.5603e-4, 5.8321e-4, 6.1175e-4, 6.417e-4,
1516 6.7314e-4, 7.0614e-4, 7.4078e-4, 7.7714e-4, 8.1531e-4, 8.5538e-4,
1517 8.9745e-4, 9.4162e-4, 9.8798e-4, .0010367, .0010878, .0011415,
1518 .0011978, .001257, .0013191, .0013844, .001453, .0015249,
1519 .0016006, .00168, .0017634, .001851, .001943, .0020397, .0021412,
1520 .0022479, .00236, .0024778, .0026015, .0027316, .0028682,
1521 .0030117, .0031626, .0033211, .0034877, .0036628, .0038469,
1522 .0040403, .0042436, .0044574, .004682, .0049182, .0051665,
1523 .0054276, .0057021, .0059907, .0062942, .0066133, .0069489,
1524 .0073018, .0076729, .0080632, .0084738, .0089056, .0093599,
1525 .0098377, .01034, .010869, .011426, .012011, .012627, .013276,
1526 .013958, .014676, .015431, .016226, .017063, .017944, .018872,
1527 .019848, .020876, .021958, .023098, .024298, .025561, .026892,
1528 .028293, .029769, .031323, .032961, .034686, .036503, .038418,
1529 .040435, .042561, .044801, .047161, .049649, .052271, .055035,
1530 .057948, .061019, .064256, .06767, .07127, .075066, .079069,
1531 .083291, .087744, .092441, .097396, .10262, .10814, .11396,
1532 .1201, .12658, .13342, .14064, .14826, .1563, .1648, .17376,
1533 .18323, .19324, .2038, .21496, .22674, .23919, .25234, .26624,
1534 .28093, .29646, .31287, .33021, .34855, .36794, .38844, .41012,
1535 .43305, .45731, .48297, .51011, .53884, .56924, .60141, .63547,
1536 .67152, .70969, .75012, .79292, .83826, .8863, .93718, .99111,
1537 1.0482, 1.1088, 1.173, 1.2411, 1.3133, 1.3898, 1.471, 1.5571,
1538 1.6485, 1.7455, 1.8485, 1.9577, 2.0737, 2.197, 2.3278, 2.4668,
1539 2.6145, 2.7715, 2.9383, 3.1156, 3.3042, 3.5047, 3.7181, 3.9451,
1540 4.1866, 4.4437, 4.7174, 5.0089, 5.3192, 5.65, 6.0025, 6.3782,
1541 6.7787, 7.206, 7.6617, 8.1479, 8.6669, 9.221, 9.8128, 10.445,
1542 11.12, 11.843, 12.615, 13.441, 14.325, 15.271, 16.283, 17.367,
1543 18.529, 19.776, 21.111, 22.544, 24.082, 25.731, 27.504, 29.409,
1544 31.452, 33.654, 36.024, 38.573, 41.323, 44.29, 47.492, 50.951,
1545 54.608, 58.588, 62.929, 67.629, 72.712, 78.226, 84.207, 90.699,
1546 97.749, 105.42, 113.77, 122.86, 132.78, 143.61, 155.44, 168.33,
1547 182.48, 198.01, 214.87, 233.39, 253.86, 276.34, 300.3, 327.28,
1548 356.89, 389.48, 422.29, 458.99, 501.39, 548.13, 595.62, 652.74,
1549 716.54, 784.57, 866.78, 960.59, 1062.8, 1072.5, 1189.5, 1319.4,
1550 1467.6, 1630.2, 1813.7, 2016.9, 2253., 2515.3, 2773.5, 3092.8,
1551 3444.4, 3720.4, 4104.3, 4527.5, 4645.9, 5021.7, 5462.2, 5597.,
1552 6110.6, 6732.5, 7513.8, 8270.6, 9640.6, 11487., 2796.1, 2680.1,
1553 2441.6, 2404.2, 2334.8, 2215.2, 1642.5, 1477.9, 1328.1, 1223.5,
1554 843.34, 766.96, 831.65, 834.84, 774.85, 1156.3, 1275.6, 1366.1,
1555 1795.6, 1885., 1936.5, 1953.4, 2154.4, 2002.7, 1789.8, 10381.,
1556 9040., 8216.5, 7384.7, 6721.9, 6187.7, 6143.8, 5703.9, 5276.6,
1557 4873.1, 4736., 4325.3, 3927., 3554.1, 3286.1, 2950.1, 2642.4,
1558 2368.7, 2138.9, 1914., 1719.6, 1543.9, 1388.6, 1252.1, 1132.2,
1559 1024.1, 1025.4, 920.58, 829.59, 750.54, 685.01, 624.25, 570.14,
1560 525.81, 481.85, 441.95, 408.71, 377.23, 345.86, 318.51, 292.26,
1561 268.34, 247.04, 227.14, 209.02, 192.69, 177.59, 163.78, 151.26,
1562 139.73, 129.19, 119.53, 110.7, 102.57, 95.109, 88.264, 81.948,
1563 76.13, 70.768, 65.827, 61.251, 57.022, 53.495, 49.824, 46.443,
1564 43.307, 40.405, 37.716, 35.241, 32.923, 30.77, 28.78, 26.915,
1565 25.177, 23.56, 22.059, 20.654, 19.345, 18.126, 16.988, 15.93,
1566 14.939, 14.014, 13.149, 12.343, 11.589, 10.884, 10.225, 9.6093,
1567 9.0327, 8.4934, 7.9889, 7.5166, 7.0744, 6.6604, 6.2727, 5.9098,
1568 5.5701, 5.2529, 4.955, 4.676, 4.4148, 4.171, 3.9426, 3.7332,
1569 3.5347, 3.3493, 3.1677, 3.0025, 2.8466, 2.6994, 2.5601, 2.4277,
1570 2.3016, 2.1814, 2.0664, 1.9564, 1.8279, 1.7311, 1.6427, 1.5645,
1571 1.4982, 1.443, 1.374, 1.3146, 1.2562, 1.17, 1.1105, 1.0272,
1572 .96863, .89718, .83654, .80226, .75908, .72431, .69573, .67174,
1573 .65126, .63315, .61693, .60182, .58715, .59554, .57649, .55526,
1574 .53177, .50622, .48176, .4813, .47642, .47492, .50273, .50293,
1575 .52687, .52239, .53419, .53814, .52626, .52211, .51492, .50622,
1576 .49746, .48841, .4792, .43534, .41999, .40349, .38586, .36799,
1577 .35108, .31089, .30803, .3171, .33599, .35041, .36149, .32924,
1578 .32462, .27309, .25961, .20922, .19504, .15683, .13098, .11588,
1579 .11478, .11204, .11363, .12135, .16423, .17785, .19094, .20236,
1580 .21084, .2154, .24108, .22848, .20871, .18797, .17963, .17834,
1581 .21552, .22284, .26945, .27052, .30108, .28977, .29772, .29224,
1582 .27658, .24956, .22777, .20654, .18392, .16338, .1452, .12916,
1583 .1152, .10304, .092437, .083163, .075031, .067878, .061564,
1584 .055976, .051018, .046609, .042679, .03917, .036032, .033223,
1585 .030706, .02845, .026428, .024617, .022998, .021554, .02027,
1586 .019136, .018141, .017278, .016541, .015926, .015432, .015058,
1587 .014807, .014666, .014635, .014728, .014947, .01527, .015728,
1588 .016345, .017026, .017798, .018839, .019752, .020636, .021886,
1589 .022695, .02327, .023478, .024292, .023544, .022222, .021932,
1590 .020052, .018143, .017722, .017031, .017782, .01938, .020734,
1591 .020476, .019255, .017477, .016878, .014617, .012489, .011765,
1592 .0099077, .0086446, .0079446, .0078644, .0079763, .008671,
1593 .01001, .0108, .012933, .015349, .016341, .018484, .020254,
1594 .020254, .020478, .019591, .018595, .018385, .019913, .022254,
1595 .024847, .025809, .028053, .029924, .030212, .031367, .03222,
1596 .032739, .032537, .03286, .033344, .033507, .033499, .033339,
1597 .032809, .033041, .031723, .029837, .027511, .026603, .024032,
1598 .021914, .020948, .021701, .023425, .024259, .024987, .023818,
1599 .021768, .019223, .018144, .015282, .012604, .01163, .0097907,
1600 .008336, .0082473, .0079582, .0088077, .009779, .010129, .012145,
1601 .014378, .016761, .01726, .018997, .019998, .019809, .01819,
1602 .016358, .016099, .01617, .017939, .020223, .022521, .02277,
1603 .024279, .025247, .024222, .023989, .023224, .021493, .020362,
1604 .018596, .017309, .015975, .014466, .013171, .011921, .01078,
1605 .0097229, .0087612, .0078729, .0070682, .0063494, .0057156,
1606 .0051459, .0046273, .0041712, .0037686, .0034119, .003095,
1607 .0028126, .0025603, .0023342, .0021314, .0019489, .0017845,
1608 .001636, .0015017, .00138, .0012697, .0011694, .0010782,
1609 9.9507e-4, 9.1931e-4, 8.5013e-4, 7.869e-4, 7.2907e-4, 6.7611e-4,
1610 6.2758e-4, 5.8308e-4, 5.4223e-4, 5.0473e-4, 4.7027e-4, 4.3859e-4,
1611 4.0946e-4, 3.8265e-4, 3.5798e-4, 3.3526e-4, 3.1436e-4, 2.9511e-4,
1612 2.7739e-4, 2.6109e-4, 2.4609e-4, 2.3229e-4, 2.1961e-4, 2.0797e-4,
1613 1.9729e-4, 1.875e-4, 1.7855e-4, 1.7038e-4, 1.6294e-4, 1.5619e-4,
1614 1.5007e-4, 1.4456e-4, 1.3961e-4, 1.3521e-4, 1.3131e-4, 1.2789e-4,
1615 1.2494e-4, 1.2242e-4, 1.2032e-4, 1.1863e-4, 1.1733e-4, 1.1641e-4,
1616 1.1585e-4, 1.1565e-4, 1.158e-4, 1.1629e-4, 1.1712e-4, 1.1827e-4,
1617 1.1976e-4, 1.2158e-4, 1.2373e-4, 1.262e-4, 1.2901e-4, 1.3214e-4,
1618 1.3562e-4, 1.3944e-4, 1.4361e-4, 1.4814e-4, 1.5303e-4, 1.5829e-4,
1619 1.6394e-4, 1.6999e-4, 1.7644e-4, 1.8332e-4, 1.9063e-4, 1.984e-4,
1620 2.0663e-4, 2.1536e-4, 2.246e-4, 2.3436e-4, 2.4468e-4, 2.5558e-4,
1621 2.6708e-4, 2.7921e-4, 2.92e-4, 3.0548e-4, 3.1968e-4, 3.3464e-4,
1622 3.5039e-4, 3.6698e-4, 3.8443e-4, 4.0281e-4, 4.2214e-4, 4.4248e-4,
1623 4.6389e-4, 4.864e-4, 5.1009e-4, 5.3501e-4, 5.6123e-4, 5.888e-4,
1624 6.1781e-4, 6.4833e-4, 6.8043e-4, 7.142e-4, 7.4973e-4, 7.8711e-4,
1625 8.2644e-4, 8.6783e-4, 9.1137e-4, 9.5721e-4, .0010054, .0010562,
1626 .0011096, .0011659, .0012251, .0012875, .0013532, .0014224,
1627 .0014953, .001572, .0016529, .0017381, .0018279, .0019226,
1628 .0020224, .0021277, .0022386, .0023557, .0024792, .0026095,
1629 .002747, .0028921, .0030453, .0032071, .003378, .0035586,
1630 .0037494, .003951, .0041642, .0043897, .0046282, .0048805,
1631 .0051476, .0054304, .00573, .0060473, .0063837, .0067404,
1632 .0071188, .0075203, .0079466, .0083994, .0088806, .0093922,
1633 .0099366, .010516, .011134, .011792, .012494, .013244, .014046,
1634 .014898, .015808, .016781, .017822, .018929, .020108, .02138,
1635 .022729, .02419, .02576, .027412, .029233, .031198, .033301,
1636 .035594, .038092, .040767, .04372, .046918, .050246, .053974,
1637 .058009, .061976, .066586, .071537, .076209, .081856, .087998,
1638 .093821, .10113, .10913, .11731, .12724, .13821, .15025, .1639,
1639 .17807, .19472, .21356, .23496, .25758, .28387, .31389, .34104,
1640 .37469, .40989, .43309, .46845, .5042, .5023, .52981, .55275,
1641 .51075, .51976, .52457, .44779, .44721, .4503, .4243, .45244,
1642 .49491, .55399, .39021, .24802, .2501, .2618, .27475, .28879,
1643 .31317, .33643, .36257, .4018, .43275, .46525, .53333, .56599,
1644 .60557, .70142, .74194, .77736, .88567, .91182, .93294, .98407,
1645 .98772, .99176, .9995, 1.2405, 1.3602, 1.338, 1.3255, 1.3267,
1646 1.3404, 1.3634, 1.3967, 1.4407, 1.4961, 1.5603, 1.6328, 1.7153,
1647 1.8094, 1.9091, 2.018, 2.1367, 2.264, 2.4035, 2.5562, 2.7179,
1648 2.9017, 3.1052, 3.3304, 3.5731, 3.8488, 4.1553, 4.4769, 4.7818,
1649 5.1711, 5.5204, 5.9516, 6.4097, 6.8899, 7.1118, 7.5469, 7.9735,
1650 7.9511, 8.3014, 8.6418, 8.4757, 8.8256, 9.2294, 9.6923, 10.033,
1651 10.842, 11.851, 11.78, 8.8435, 9.1381, 9.5956, 10.076, 10.629,
1652 11.22, 11.883, 12.69, 13.163, 13.974, 14.846, 16.027, 17.053,
1653 18.148, 19.715, 20.907, 22.163, 23.956, 25.235, 26.566, 27.94,
1654 29.576, 30.956, 32.432, 35.337, 39.911, 41.128, 42.625, 44.386,
1655 46.369, 48.619, 51.031, 53.674, 56.825, 59.921, 63.286, 66.929,
1656 70.859, 75.081, 79.618, 84.513, 89.739, 95.335, 101.35, 107.76,
1657 114.63, 121.98, 129.87, 138.3, 147.34, 157.04, 167.56, 178.67,
1658 190.61, 203.43, 217.19, 231.99, 247.88, 264.98, 283.37, 303.17,
1659 324.49, 347.47, 372.25, 398.98, 427.85, 459.06, 492.8, 529.31,
1660 568.89, 611.79, 658.35, 708.91, 763.87, 823.65, 888.72, 959.58,
1661 1036.8, 1121.8, 1213.9, 1314.3, 1423.8, 1543., 1672.8, 1813.4,
1662 1966.1, 2131.4, 2309.5, 2499.3, 2705., 2925.7, 3161.6, 3411.3,
1663 3611.5, 3889.2, 4191.1, 4519.3, 4877.9, 5272.9, 5712.9, 6142.7,
1664 6719.6, 7385., 8145., 8977.7, 9831.9, 10827., 11934., 13063.,
1665 14434., 15878., 17591., 19435., 21510., 23835., 26835., 29740.,
1666 32878., 36305., 39830., 43273., 46931., 50499., 49586., 51598.,
1667 53429., 54619., 55081., 55102., 54485., 53487., 52042., 42689.,
1668 42607., 44020., 47994., 54169., 53916., 55808., 56642., 46049.,
1669 44243., 32929., 30658., 21963., 20835., 15962., 13679., 17652.,
1670 19680., 22388., 25625., 29184., 32520., 35720., 38414., 40523.,
1671 49228., 48173., 45678., 41768., 37600., 41313., 42654., 44465.,
1672 55736., 56630., 65409., 63308., 66572., 61845., 60379., 56777.,
1673 51920., 46601., 41367., 36529., 32219., 28470., 25192., 22362.,
1674 19907., 17772., 15907., 14273., 12835., 11567., 10445., 9450.2,
1675 8565.1, 7776., 7070.8, 6439.2, 5872.3, 5362.4, 4903., 4488.3,
1676 4113.4, 3773.8, 3465.8, 3186.1, 2931.7, 2700.1, 2488.8, 2296.,
1677 2119.8, 1958.6, 1810.9, 1675.6, 1551.4, 1437.3, 1332.4, 1236.,
1678 1147.2, 1065.3, 989.86, 920.22, 855.91, 796.48, 741.53, 690.69,
1679 643.62, 600.02, 559.6, 522.13, 487.35, 455.06, 425.08, 397.21,
1680 371.3, 347.2, 324.78, 303.9, 284.46, 266.34, 249.45, 233.7,
1681 219.01, 205.3, 192.5, 180.55, 169.38, 158.95, 149.2, 140.07,
1682 131.54, 123.56, 116.09, 109.09, 102.54, 96.405, 90.655, 85.266,
1683 80.213, 75.475, 71.031, 66.861, 62.948, 59.275, 55.827, 52.587,
1684 49.544, 46.686, 43.998, 41.473, 39.099, 36.867, 34.768, 32.795,
1685 30.939, 29.192, 27.546, 25.998, 24.539, 23.164, 21.869, 20.65,
1686 19.501, 18.419, 17.399, 16.438, 15.532, 14.678, 13.874, 13.115,
1687 12.4, 11.726, 11.088, 10.488, 9.921, 9.3846, 8.8784, 8.3996,
1688 7.9469, 7.5197, 7.1174, 6.738, 6.379, 6.0409, 5.7213, 5.419,
1689 5.1327, 4.8611, 4.6046, 4.3617, 4.1316, 3.9138, 3.7077, 3.5125,
1690 3.3281, 3.1536, 2.9885, 2.8323, 2.6846, 2.5447, 2.4124, 2.2871,
1691 2.1686, 2.0564, 1.9501, 1.8495, 1.7543, 1.6641, 1.5787, 1.4978,
1692 1.4212, 1.3486, 1.2799, 1.2147, 1.1529, 1.0943, 1.0388, .98602,
1693 .93596, .8886, .84352, .80078, .76029, .722, .68585, .65161,
1694 .61901, .58808, .55854, .53044, .5039, .47853, .45459, .43173,
1695 .41008, .38965, .37021, .35186, .33444, .31797, .30234, .28758,
1696 .2736, .26036, .24764, .2357, .22431, .21342, .20295, .19288,
1697 .18334, .17444, .166, .15815, .15072, .14348, .13674, .13015,
1698 .12399, .11807, .11231, .10689, .10164, .096696, .091955,
1699 .087476, .083183, .079113, .075229, .071536, .068026, .064698,
1700 .06154, .058544, .055699, .052997, .050431, .047993, .045676,
1701 .043475, .041382, .039392, .037501, .035702, .033991, .032364,
1702 .030817, .029345, .027945, .026613, .025345, .024139, .022991,
1703 .021899, .02086, .019871, .018929, .018033, .01718, .016368,
1704 .015595, .014859, .014158, .013491, .012856, .012251, .011675,
1705 .011126, .010604, .010107, .0096331, .009182, .0087523, .0083431,
1706 .0079533, .0075821, .0072284, .0068915, .0065706, .0062649,
1707 .0059737, .0056963, .005432, .0051802, .0049404, .0047118,
1708 .0044941, .0042867, .0040891, .0039009, .0037216, .0035507,
1709 .003388, .0032329, .0030852, .0029445, .0028105, .0026829,
1710 .0025613, .0024455, .0023353, .0022303, .0021304, .0020353,
1711 .0019448, .0018587, .0017767, .0016988, .0016247, .0015543,
1712 .0014874, .0014238, .0013635, .0013062, .0012519, .0012005,
1713 .0011517, .0011057, .0010621, .001021, 9.8233e-4, 9.4589e-4,
1714 9.1167e-4, 8.7961e-4, 8.4964e-4, 8.2173e-4, 7.9582e-4, 7.7189e-4,
1715 7.499e-4, 7.2983e-4, 7.1167e-4, 6.9542e-4, 6.8108e-4, 6.6866e-4,
1716 6.5819e-4, 6.4971e-4, 6.4328e-4, 6.3895e-4, 6.3681e-4, 6.3697e-4,
1717 6.3956e-4, 6.4472e-4, 6.5266e-4, 6.6359e-4, 6.778e-4, 6.9563e-4,
1718 7.1749e-4, 7.4392e-4, 7.7556e-4, 8.1028e-4, 8.4994e-4, 8.8709e-4,
1719 9.3413e-4, 9.6953e-4, .0010202, .0010738, .0010976, .0011507,
1720 .0011686, .0012264, .001291, .0013346, .0014246, .0015293,
1721 .0016359, .0017824, .0019255, .0020854, .002247, .0024148,
1722 .0026199, .0027523, .0029704, .0030702, .0033047, .0035013,
1723 .0037576, .0040275, .0043089, .0046927, .0049307, .0053486,
1724 .0053809, .0056699, .0059325, .0055488, .005634, .0056392,
1725 .004946, .0048855, .0048208, .0044386, .0045498, .0046377,
1726 .0048939, .0052396, .0057324, .0060859, .0066906, .0071148,
1727 .0077224, .0082687, .008769, .0084471, .008572, .0087729,
1728 .008775, .0090742, .0080704, .0080288, .0085747, .0086087,
1729 .0086408, .0088752, .0089381, .0089757, .0093532, .0092824,
1730 .0092566, .0092645, .0092735, .009342, .0095806, .0097991,
1731 .010213, .010611, .011129, .011756, .013237, .01412, .015034,
1732 .015936, .01682, .018597, .019315, .019995, .020658, .021289,
1733 .022363, .022996, .023716, .024512, .025434, .026067, .027118,
1734 .028396, .029865, .031442, .033253, .03525, .037296, .039701,
1735 .042356, .045154, .048059, .051294, .054893, .058636, .061407,
1736 .065172, .068974, .072676, .073379, .076547, .079556, .079134,
1737 .082308, .085739, .090192, .09359, .099599, .10669, .11496,
1738 .1244, .13512, .14752, .14494, .15647, .1668, .17863, .19029,
1739 .20124, .20254, .21179, .21982, .21625, .22364, .23405, .23382,
1740 .2434, .25708, .26406, .27621, .28909, .30395, .31717, .33271,
1741 .3496, .36765, .38774, .40949, .446, .46985, .49846, .5287, .562,
1742 .59841, .64598, .68834, .7327, .78978, .8373, .88708, .94744,
1743 1.0006, 1.0574, 1.1215, 1.1856, 1.2546, 1.3292, 1.4107, 1.4974,
1744 1.5913, 1.6931, 1.8028, 1.9212, 2.0492, 2.1874, 2.3365, 2.4978,
1745 2.6718, 2.8588, 3.062, 3.2818, 3.5188, 3.7752, 4.0527, 4.3542,
1746 4.6782, 5.0312, 5.4123, 5.8246, 6.2639, 6.7435, 7.2636, 7.8064,
1747 8.4091, 9.0696, 9.7677, 10.548, 11.4, 12.309, 13.324, 14.284,
1748 15.445, 16.687, 18.019, 19.403, 20.847, 22.366, 23.925, 25.537,
1749 27.213, 28.069, 29.864, 31.829, 33.988, 35.856, 38.829, 42.321,
1750 46.319, 50.606, 55.126, 59.126, 64.162, 68.708, 74.615, 81.176,
1751 87.739, 95.494, 103.83, 113.38, 123.99, 135.8, 148.7, 162.58,
1752 176.32, 192.6, 211.47, 232.7, 252.64, 277.41, 305.38, 333.44,
1753 366.42, 402.66, 442.14, 484.53, 526.42, 568.15, 558.78, 582.6,
1754 600.98, 613.94, 619.44, 618.24, 609.84, 595.96, 484.86, 475.59,
1755 478.49, 501.56, 552.19, 628.44, 630.39, 658.92, 671.96, 562.7,
1756 545.88, 423.43, 400.14, 306.59, 294.13, 246.8, 226.51, 278.21,
1757 314.39, 347.22, 389.13, 433.16, 477.48, 521.67, 560.54, 683.6,
1758 696.37, 695.91, 683.1, 658.24, 634.89, 698.85, 742.87, 796.66,
1759 954.49, 1009.5, 1150.5, 1179.1, 1267.9, 1272.4, 1312.7, 1330.4,
1760 1331.6, 1315.8, 1308.3, 1293.3, 1274.6, 1249.5, 1213.2, 1172.1,
1761 1124.4, 930.33, 893.36, 871.27, 883.54, 940.76, 1036., 1025.6,
1762 1053.1, 914.51, 894.15, 865.03, 670.63, 508.41, 475.15, 370.85,
1763 361.06, 319.38, 312.75, 331.87, 367.13, 415., 467.94, 525.49,
1764 578.41, 624.66, 794.82, 796.97, 780.29, 736.49, 670.18, 603.75,
1765 659.67, 679.8, 857.12, 884.05, 900.65, 1046.1, 1141.9, 1083.,
1766 1089.2, 1e3, 947.08, 872.31, 787.91, 704.75, 624.93, 553.68,
1767 489.91, 434.21, 385.64, 343.3, 306.42, 274.18, 245.94, 221.11,
1768 199.23, 179.88, 162.73, 147.48, 133.88, 121.73, 110.86, 101.1,
1769 92.323, 84.417, 77.281, 70.831, 64.991, 59.694, 54.884, 50.509,
1770 46.526, 42.893, 39.58, 36.549, 33.776, 31.236, 28.907, 26.77,
1771 24.805, 23., 21.339, 19.81, 18.404, 17.105, 15.909, 14.801,
1772 13.778, 12.83, 11.954, 11.142, 10.389, 9.691, 9.0434, 8.4423,
1773 7.8842, 7.3657, 6.8838, 6.4357, 6.0189, 5.6308, 5.2696, 4.9332,
1774 4.6198, 4.3277, 4.0553, 3.8012, 3.5639, 3.3424, 3.1355, 2.9422,
1775 2.7614, 2.5924, 2.4343, 2.2864, 2.148, 2.0184, 1.8971, 1.7835,
1776 1.677, 1.5773, 1.4838, 1.3961, 1.3139, 1.2369, 1.1645, 1.0966,
1777 1.0329, .97309, .91686, .86406, .81439, .76767, .72381, .68252,
1778 .64359, .60695, .57247, .54008, .50957, .48092, .45401, .42862,
1779 .40465, .38202, .36072, .34052, .3216, .30386, .28711, .27135,
1780 .25651, .24252, .2293, .21689, .20517, .19416, .18381, .17396,
1781 .16469
1782 };
1783
1784 static const double co2230[2001] =
1785 { 2.743e-5, 2.8815e-5, 3.027e-5, 3.1798e-5,
1786 3.3405e-5, 3.5094e-5, 3.6869e-5, 3.8734e-5, 4.0694e-5, 4.2754e-5,
1787 4.492e-5, 4.7196e-5, 4.9588e-5, 5.2103e-5, 5.4747e-5, 5.7525e-5,
1788 6.0446e-5, 6.3516e-5, 6.6744e-5, 7.0137e-5, 7.3704e-5, 7.7455e-5,
1789 8.1397e-5, 8.5543e-5, 8.9901e-5, 9.4484e-5, 9.9302e-5, 1.0437e-4,
1790 1.097e-4, 1.153e-4, 1.2119e-4, 1.2738e-4, 1.3389e-4, 1.4074e-4,
1791 1.4795e-4, 1.5552e-4, 1.6349e-4, 1.7187e-4, 1.8068e-4, 1.8995e-4,
1792 1.997e-4, 2.0996e-4, 2.2075e-4, 2.321e-4, 2.4403e-4, 2.5659e-4,
1793 2.698e-4, 2.837e-4, 2.9832e-4, 3.137e-4, 3.2988e-4, 3.4691e-4,
1794 3.6483e-4, 3.8368e-4, 4.0351e-4, 4.2439e-4, 4.4635e-4, 4.6947e-4,
1795 4.9379e-4, 5.1939e-4, 5.4633e-4, 5.7468e-4, 6.0452e-4, 6.3593e-4,
1796 6.69e-4, 7.038e-4, 7.4043e-4, 7.79e-4, 8.1959e-4, 8.6233e-4,
1797 9.0732e-4, 9.5469e-4, .0010046, .0010571, .0011124, .0011706,
1798 .0012319, .0012964, .0013644, .001436, .0015114, .0015908,
1799 .0016745, .0017625, .0018553, .0019531, .002056, .0021645,
1800 .0022788, .0023992, .002526, .0026596, .0028004, .0029488,
1801 .0031052, .0032699, .0034436, .0036265, .0038194, .0040227,
1802 .0042369, .0044628, .0047008, .0049518, .0052164, .0054953,
1803 .0057894, .0060995, .0064265, .0067713, .007135, .0075184,
1804 .0079228, .0083494, .0087993, .0092738, .0097745, .010303,
1805 .01086, .011448, .012068, .012722, .013413, .014142, .014911,
1806 .015723, .01658, .017484, .018439, .019447, .020511, .021635,
1807 .022821, .024074, .025397, .026794, .02827, .029829, .031475,
1808 .033215, .035052, .036994, .039045, .041213, .043504, .045926,
1809 .048485, .05119, .05405, .057074, .060271, .063651, .067225,
1810 .071006, .075004, .079233, .083708, .088441, .093449, .098749,
1811 .10436, .11029, .11657, .12322, .13026, .13772, .14561, .15397,
1812 .16282, .1722, .18214, .19266, .20381, .21563, .22816, .24143,
1813 .2555, .27043, .28625, .30303, .32082, .3397, .35972, .38097,
1814 .40352, .42746, .45286, .47983, .50847, .53888, .57119, .6055,
1815 .64196, .6807, .72187, .76564, .81217, .86165, .91427, .97025,
1816 1.0298, 1.0932, 1.1606, 1.2324, 1.3088, 1.3902, 1.477, 1.5693,
1817 1.6678, 1.7727, 1.8845, 2.0038, 2.131, 2.2666, 2.4114, 2.5659,
1818 2.7309, 2.907, 3.0951, 3.2961, 3.5109, 3.7405, 3.986, 4.2485,
1819 4.5293, 4.8299, 5.1516, 5.4961, 5.8651, 6.2605, 6.6842, 7.1385,
1820 7.6256, 8.1481, 8.7089, 9.3109, 9.9573, 10.652, 11.398, 12.2,
1821 13.063, 13.992, 14.99, 16.064, 17.222, 18.469, 19.813, 21.263,
1822 22.828, 24.516, 26.34, 28.31, 30.437, 32.738, 35.226, 37.914,
1823 40.824, 43.974, 47.377, 51.061, 55.011, 59.299, 63.961, 69.013,
1824 74.492, 80.444, 86.919, 93.836, 101.23, 109.25, 117.98, 127.47,
1825 137.81, 149.07, 161.35, 174.75, 189.42, 205.49, 223.02, 242.26,
1826 263.45, 286.75, 311.94, 340.01, 370.86, 404.92, 440.44, 480.27,
1827 525.17, 574.71, 626.22, 686.8, 754.38, 827.07, 913.38, 1011.7,
1828 1121.5, 1161.6, 1289.5, 1432.2, 1595.4, 1777., 1983.3, 2216.1,
1829 2485.7, 2788.3, 3101.5, 3481., 3902.1, 4257.1, 4740., 5272.8,
1830 5457.9, 5946.2, 6505.3, 6668.4, 7302.4, 8061.6, 9015.8, 9908.3,
1831 11613., 13956., 3249.6, 3243., 2901.5, 2841.3, 2729.6, 2558.2,
1832 1797.8, 1583.2, 1386., 1233.5, 787.74, 701.46, 761.66, 767.21,
1833 722.83, 1180.6, 1332.1, 1461.6, 2032.9, 2166., 2255.9, 2294.7,
1834 2587.2, 2396.5, 2122.4, 12553., 10784., 9832.5, 8827.3, 8029.1,
1835 7377.9, 7347.1, 6783.8, 6239.1, 5721.1, 5503., 4975.1, 4477.8,
1836 4021.3, 3676.8, 3275.3, 2914.9, 2597.4, 2328.2, 2075.4, 1857.6,
1837 1663.6, 1493.3, 1343.8, 1213.3, 1095.6, 1066.5, 958.91, 865.15,
1838 783.31, 714.35, 650.77, 593.98, 546.2, 499.9, 457.87, 421.75,
1839 387.61, 355.25, 326.62, 299.7, 275.21, 253.17, 232.83, 214.31,
1840 197.5, 182.08, 167.98, 155.12, 143.32, 132.5, 122.58, 113.48,
1841 105.11, 97.415, 90.182, 83.463, 77.281, 71.587, 66.341, 61.493,
1842 57.014, 53.062, 49.21, 45.663, 42.38, 39.348, 36.547, 33.967,
1843 31.573, 29.357, 27.314, 25.415, 23.658, 22.03, 20.524, 19.125,
1844 17.829, 16.627, 15.511, 14.476, 13.514, 12.618, 11.786, 11.013,
1845 10.294, 9.6246, 9.0018, 8.4218, 7.8816, 7.3783, 6.9092, 6.4719,
1846 6.0641, 5.6838, 5.3289, 4.998, 4.6893, 4.4014, 4.1325, 3.8813,
1847 3.6469, 3.4283, 3.2241, 3.035, 2.8576, 2.6922, 2.5348, 2.3896,
1848 2.2535, 2.1258, 2.0059, 1.8929, 1.7862, 1.6854, 1.5898, 1.4992,
1849 1.4017, 1.3218, 1.2479, 1.1809, 1.1215, 1.0693, 1.0116, .96016,
1850 .9105, .84859, .80105, .74381, .69982, .65127, .60899, .57843,
1851 .54592, .51792, .49336, .47155, .45201, .43426, .41807, .40303,
1852 .38876, .3863, .37098, .35492, .33801, .32032, .30341, .29874,
1853 .29193, .28689, .29584, .29155, .29826, .29195, .29287, .2904,
1854 .28199, .27709, .27162, .26622, .26133, .25676, .25235, .23137,
1855 .22365, .21519, .20597, .19636, .18699, .16485, .16262, .16643,
1856 .17542, .18198, .18631, .16759, .16338, .13505, .1267, .10053,
1857 .092554, .074093, .062159, .055523, .054849, .05401, .05528,
1858 .058982, .07952, .08647, .093244, .099285, .10393, .10661,
1859 .12072, .11417, .10396, .093265, .089137, .088909, .10902,
1860 .11277, .13625, .13565, .14907, .14167, .1428, .13744, .12768,
1861 .11382, .10244, .091686, .08109, .071739, .063616, .056579,
1862 .050504, .045251, .040689, .036715, .033237, .030181, .027488,
1863 .025107, .022998, .021125, .01946, .017979, .016661, .015489,
1864 .014448, .013526, .012712, .011998, .011375, .010839, .010384,
1865 .010007, .0097053, .0094783, .0093257, .0092489, .0092504,
1866 .0093346, .0095077, .0097676, .01012, .01058, .011157, .011844,
1867 .012672, .013665, .014766, .015999, .017509, .018972, .020444,
1868 .022311, .023742, .0249, .025599, .026981, .026462, .025143,
1869 .025066, .022814, .020458, .020026, .019142, .020189, .022371,
1870 .024163, .023728, .02199, .019506, .018591, .015576, .012784,
1871 .011744, .0094777, .0079148, .0070652, .006986, .0071758,
1872 .008086, .0098025, .01087, .013609, .016764, .018137, .021061,
1873 .023498, .023576, .023965, .022828, .021519, .021283, .023364,
1874 .026457, .029782, .030856, .033486, .035515, .035543, .036558,
1875 .037198, .037472, .037045, .037284, .03777, .038085, .038366,
1876 .038526, .038282, .038915, .037697, .035667, .032941, .031959,
1877 .028692, .025918, .024596, .025592, .027873, .028935, .02984,
1878 .028148, .025305, .021912, .020454, .016732, .013357, .01205,
1879 .009731, .0079881, .0077704, .0074387, .0083895, .0096776,
1880 .010326, .01293, .015955, .019247, .020145, .02267, .024231,
1881 .024184, .022131, .019784, .01955, .01971, .022119, .025116,
1882 .027978, .028107, .029808, .030701, .029164, .028551, .027286,
1883 .024946, .023259, .020982, .019221, .017471, .015643, .014074,
1884 .01261, .011301, .010116, .0090582, .0081036, .0072542, .0065034,
1885 .0058436, .0052571, .0047321, .0042697, .0038607, .0034977,
1886 .0031747, .0028864, .0026284, .002397, .002189, .0020017,
1887 .0018326, .0016798, .0015414, .0014159, .0013019, .0011983,
1888 .0011039, .0010177, 9.391e-4, 8.6717e-4, 8.0131e-4, 7.4093e-4,
1889 6.8553e-4, 6.3464e-4, 5.8787e-4, 5.4487e-4, 5.0533e-4, 4.69e-4,
1890 4.3556e-4, 4.0474e-4, 3.7629e-4, 3.5e-4, 3.2569e-4, 3.032e-4,
1891 2.8239e-4, 2.6314e-4, 2.4535e-4, 2.2891e-4, 2.1374e-4, 1.9975e-4,
1892 1.8685e-4, 1.7498e-4, 1.6406e-4, 1.5401e-4, 1.4479e-4, 1.3633e-4,
1893 1.2858e-4, 1.2148e-4, 1.1499e-4, 1.0907e-4, 1.0369e-4, 9.8791e-5,
1894 9.4359e-5, 9.0359e-5, 8.6766e-5, 8.3555e-5, 8.0703e-5, 7.8192e-5,
1895 7.6003e-5, 7.4119e-5, 7.2528e-5, 7.1216e-5, 7.0171e-5, 6.9385e-5,
1896 6.8848e-5, 6.8554e-5, 6.8496e-5, 6.8669e-5, 6.9069e-5, 6.9694e-5,
1897 7.054e-5, 7.1608e-5, 7.2896e-5, 7.4406e-5, 7.6139e-5, 7.8097e-5,
1898 8.0283e-5, 8.2702e-5, 8.5357e-5, 8.8255e-5, 9.1402e-5, 9.4806e-5,
1899 9.8473e-5, 1.0241e-4, 1.0664e-4, 1.1115e-4, 1.1598e-4, 1.2112e-4,
1900 1.2659e-4, 1.3241e-4, 1.3859e-4, 1.4515e-4, 1.521e-4, 1.5947e-4,
1901 1.6728e-4, 1.7555e-4, 1.8429e-4, 1.9355e-4, 2.0334e-4, 2.1369e-4,
1902 2.2463e-4, 2.3619e-4, 2.4841e-4, 2.6132e-4, 2.7497e-4, 2.8938e-4,
1903 3.0462e-4, 3.2071e-4, 3.3771e-4, 3.5567e-4, 3.7465e-4, 3.947e-4,
1904 4.1588e-4, 4.3828e-4, 4.6194e-4, 4.8695e-4, 5.1338e-4, 5.4133e-4,
1905 5.7087e-4, 6.0211e-4, 6.3515e-4, 6.701e-4, 7.0706e-4, 7.4617e-4,
1906 7.8756e-4, 8.3136e-4, 8.7772e-4, 9.2681e-4, 9.788e-4, .0010339,
1907 .0010922, .001154, .0012195, .0012889, .0013626, .0014407,
1908 .0015235, .0016114, .0017048, .0018038, .001909, .0020207,
1909 .0021395, .0022657, .0023998, .0025426, .0026944, .002856,
1910 .0030281, .0032114, .0034068, .003615, .0038371, .004074,
1911 .004327, .0045971, .0048857, .0051942, .0055239, .0058766,
1912 .0062538, .0066573, .0070891, .007551, .0080455, .0085747,
1913 .0091412, .0097481, .010397, .011092, .011837, .012638, .013495,
1914 .014415, .01541, .016475, .017621, .018857, .020175, .02162,
1915 .023185, .024876, .02672, .028732, .030916, .033319, .035939,
1916 .038736, .041847, .04524, .048715, .052678, .056977, .061203,
1917 .066184, .07164, .076952, .083477, .090674, .098049, .10697,
1918 .1169, .1277, .14011, .15323, .1684, .18601, .20626, .22831,
1919 .25417, .28407, .31405, .34957, .38823, .41923, .46026, .50409,
1920 .51227, .54805, .57976, .53818, .55056, .557, .46741, .46403,
1921 .4636, .42265, .45166, .49852, .56663, .34306, .17779, .17697,
1922 .18346, .19129, .20014, .21778, .23604, .25649, .28676, .31238,
1923 .33856, .39998, .4288, .46568, .56654, .60786, .64473, .76466,
1924 .7897, .80778, .86443, .85736, .84798, .84157, 1.1385, 1.2446,
1925 1.1923, 1.1552, 1.1338, 1.1266, 1.1292, 1.1431, 1.1683, 1.2059,
1926 1.2521, 1.3069, 1.3712, 1.4471, 1.5275, 1.6165, 1.7145, 1.8189,
1927 1.9359, 2.065, 2.2007, 2.3591, 2.5362, 2.7346, 2.9515, 3.2021,
1928 3.4851, 3.7935, 4.0694, 4.4463, 4.807, 5.2443, 5.7178, 6.2231,
1929 6.4796, 6.9461, 7.4099, 7.3652, 7.7182, 8.048, 7.7373, 8.0363,
1930 8.3855, 8.8044, 9.0257, 9.8574, 10.948, 10.563, 6.8979, 7.0744,
1931 7.4121, 7.7663, 8.1768, 8.6243, 9.1437, 9.7847, 10.182, 10.849,
1932 11.572, 12.602, 13.482, 14.431, 15.907, 16.983, 18.11, 19.884,
1933 21.02, 22.18, 23.355, 24.848, 25.954, 27.13, 30.186, 34.893,
1934 35.682, 36.755, 38.111, 39.703, 41.58, 43.606, 45.868, 48.573,
1935 51.298, 54.291, 57.559, 61.116, 64.964, 69.124, 73.628, 78.471,
1936 83.683, 89.307, 95.341, 101.84, 108.83, 116.36, 124.46, 133.18,
1937 142.57, 152.79, 163.69, 175.43, 188.11, 201.79, 216.55, 232.51,
1938 249.74, 268.38, 288.54, 310.35, 333.97, 359.55, 387.26, 417.3,
1939 449.88, 485.2, 523.54, 565.14, 610.28, 659.31, 712.56, 770.43,
1940 833.36, 901.82, 976.36, 1057.6, 1146.8, 1243.8, 1350., 1466.3,
1941 1593.6, 1732.7, 1884.1, 2049.1, 2228.2, 2421.9, 2629.4, 2853.7,
1942 3094.4, 3351.1, 3622.3, 3829.8, 4123.1, 4438.3, 4777.2, 5144.1,
1943 5545.4, 5990.5, 6404.5, 6996.8, 7687.6, 8482.9, 9349.4, 10203.,
1944 11223., 12358., 13493., 14916., 16416., 18236., 20222., 22501.,
1945 25102., 28358., 31707., 35404., 39538., 43911., 48391., 53193.,
1946 58028., 58082., 61276., 64193., 66294., 67480., 67921., 67423.,
1947 66254., 64341., 51737., 51420., 53072., 58145., 66195., 65358.,
1948 67377., 67869., 53509., 50553., 35737., 32425., 21704., 19974.,
1949 14457., 12142., 16798., 19489., 23049., 27270., 31910., 36457.,
1950 40877., 44748., 47876., 59793., 58626., 55454., 50337., 44893.,
1951 50228., 52216., 54747., 69541., 70455., 81014., 77694., 80533.,
1952 73953., 70927., 65539., 59002., 52281., 45953., 40292., 35360.,
1953 31124., 27478., 24346., 21647., 19308., 17271., 15491., 13927.,
1954 12550., 11331., 10250., 9288.8, 8431.4, 7664.9, 6978.3, 6361.8,
1955 5807.4, 5307.7, 4856.8, 4449., 4079.8, 3744.9, 3440.8, 3164.2,
1956 2912.3, 2682.7, 2473., 2281.4, 2106., 1945.3, 1797.9, 1662.5,
1957 1538.1, 1423.6, 1318.1, 1221., 1131.5, 1049., 972.99, 902.87,
1958 838.01, 777.95, 722.2, 670.44, 622.35, 577.68, 536.21, 497.76,
1959 462.12, 429.13, 398.61, 370.39, 344.29, 320.16, 297.85, 277.2,
1960 258.08, 240.38, 223.97, 208.77, 194.66, 181.58, 169.43, 158.15,
1961 147.67, 137.92, 128.86, 120.44, 112.6, 105.3, 98.499, 92.166,
1962 86.264, 80.763, 75.632, 70.846, 66.381, 62.213, 58.321, 54.685,
1963 51.288, 48.114, 45.145, 42.368, 39.772, 37.341, 35.065, 32.937,
1964 30.943, 29.077, 27.33, 25.693, 24.158, 22.717, 21.367, 20.099,
1965 18.909, 17.792, 16.744, 15.761, 14.838, 13.971, 13.157, 12.393,
1966 11.676, 11.003, 10.369, 9.775, 9.2165, 8.6902, 8.1963, 7.7314,
1967 7.2923, 6.8794, 6.4898, 6.122, 5.7764, 5.4525, 5.1484, 4.8611,
1968 4.5918, 4.3379, 4.0982, 3.8716, 3.6567, 3.4545, 3.2634, 3.0828,
1969 2.9122, 2.7512, 2.5993, 2.4561, 2.3211, 2.1938, 2.0737, 1.9603,
1970 1.8534, 1.7525, 1.6572, 1.5673, 1.4824, 1.4022, 1.3265, 1.2551,
1971 1.1876, 1.1239, 1.0637, 1.0069, .9532, .90248, .85454, .80921,
1972 .76631, .72569, .6872, .65072, .61635, .5836, .55261, .52336,
1973 .49581, .46998, .44559, .42236, .40036, .37929, .35924, .34043,
1974 .32238, .30547, .28931, .27405, .25975, .24616, .23341, .22133,
1975 .20997, .19924, .18917, .17967, .17075, .16211, .15411, .14646,
1976 .13912, .13201, .12509, .11857, .11261, .10698, .10186, .097039,
1977 .092236, .087844, .083443, .07938, .075452, .071564, .067931,
1978 .064389, .061078, .057901, .054921, .052061, .049364, .046789,
1979 .04435, .042044, .039866, .037808, .035863, .034023, .032282,
1980 .030634, .029073, .027595, .026194, .024866, .023608, .022415,
1981 .021283, .02021, .019193, .018228, .017312, .016443, .015619,
1982 .014837, .014094, .01339, .012721, .012086, .011483, .010911,
1983 .010368, .009852, .0093623, .0088972, .0084556, .0080362,
1984 .0076379, .0072596, .0069003, .006559, .0062349, .0059269,
1985 .0056344, .0053565, .0050925, .0048417, .0046034, .004377,
1986 .0041618, .0039575, .0037633, .0035788, .0034034, .0032368,
1987 .0030785, .002928, .0027851, .0026492, .0025201, .0023975,
1988 .0022809, .0021701, .0020649, .0019649, .0018699, .0017796,
1989 .0016938, .0016122, .0015348, .0014612, .0013913, .001325,
1990 .0012619, .0012021, .0011452, .0010913, .0010401, 9.9149e-4,
1991 9.454e-4, 9.0169e-4, 8.6024e-4, 8.2097e-4, 7.8377e-4, 7.4854e-4,
1992 7.1522e-4, 6.8371e-4, 6.5393e-4, 6.2582e-4, 5.9932e-4, 5.7435e-4,
1993 5.5087e-4, 5.2882e-4, 5.0814e-4, 4.8881e-4, 4.7076e-4, 4.5398e-4,
1994 4.3843e-4, 4.2407e-4, 4.109e-4, 3.9888e-4, 3.88e-4, 3.7826e-4,
1995 3.6963e-4, 3.6213e-4, 3.5575e-4, 3.505e-4, 3.464e-4, 3.4346e-4,
1996 3.4173e-4, 3.4125e-4, 3.4206e-4, 3.4424e-4, 3.4787e-4, 3.5303e-4,
1997 3.5986e-4, 3.6847e-4, 3.7903e-4, 3.9174e-4, 4.0681e-4, 4.2455e-4,
1998 4.4527e-4, 4.6942e-4, 4.9637e-4, 5.2698e-4, 5.5808e-4, 5.9514e-4,
1999 6.2757e-4, 6.689e-4, 7.1298e-4, 7.3955e-4, 7.8403e-4, 8.0449e-4,
2000 8.5131e-4, 9.0256e-4, 9.3692e-4, .0010051, .0010846, .0011678,
2001 .001282, .0014016, .0015355, .0016764, .0018272, .0020055,
2002 .0021455, .0023421, .0024615, .0026786, .0028787, .0031259,
2003 .0034046, .0036985, .0040917, .0043902, .0048349, .0049531,
2004 .0052989, .0056148, .0052452, .0053357, .005333, .0045069,
2005 .0043851, .004253, .003738, .0038084, .0039013, .0041505,
2006 .0045372, .0050569, .0054507, .0061267, .0066122, .0072449,
2007 .0078012, .0082651, .0076538, .0076573, .0076806, .0075227,
2008 .0076269, .0063758, .006254, .0067749, .0067909, .0068231,
2009 .0072143, .0072762, .0072954, .007679, .0075107, .0073658,
2010 .0072441, .0071074, .0070378, .007176, .0072472, .0075844,
2011 .0079291, .008412, .0090165, .010688, .011535, .012375, .013166,
2012 .013895, .015567, .016011, .016392, .016737, .017043, .017731,
2013 .018031, .018419, .018877, .019474, .019868, .020604, .021538,
2014 .022653, .023869, .025288, .026879, .028547, .030524, .03274,
2015 .035132, .03769, .040567, .043793, .047188, .049962, .053542,
2016 .057205, .060776, .061489, .064419, .067124, .065945, .068487,
2017 .071209, .074783, .077039, .082444, .08902, .09692, .10617,
2018 .11687, .12952, .12362, .13498, .14412, .15492, .16519, .1744,
2019 .17096, .17714, .18208, .17363, .17813, .18564, .18295, .19045,
2020 .20252, .20815, .21844, .22929, .24229, .25321, .26588, .2797,
2021 .29465, .31136, .32961, .36529, .38486, .41027, .43694, .4667,
2022 .49943, .54542, .58348, .62303, .67633, .71755, .76054, .81371,
2023 .85934, .90841, .96438, 1.0207, 1.0821, 1.1491, 1.2226, 1.3018,
2024 1.388, 1.4818, 1.5835, 1.6939, 1.8137, 1.9435, 2.0843, 2.237,
2025 2.4026, 2.5818, 2.7767, 2.9885, 3.2182, 3.4679, 3.7391, 4.0349,
2026 4.3554, 4.7053, 5.0849, 5.4986, 5.9436, 6.4294, 6.9598, 7.5203,
2027 8.143, 8.8253, 9.5568, 10.371, 11.267, 12.233, 13.31, 14.357,
2028 15.598, 16.93, 18.358, 19.849, 21.408, 23.04, 24.706, 26.409,
2029 28.153, 28.795, 30.549, 32.43, 34.49, 36.027, 38.955, 42.465,
2030 46.565, 50.875, 55.378, 59.002, 63.882, 67.949, 73.693, 80.095,
2031 86.403, 94.264, 102.65, 112.37, 123.3, 135.54, 149.14, 163.83,
2032 179.17, 196.89, 217.91, 240.94, 264.13, 292.39, 324.83, 358.21,
2033 397.16, 440.5, 488.6, 541.04, 595.3, 650.43, 652.03, 688.74,
2034 719.47, 743.54, 757.68, 762.35, 756.43, 741.42, 595.43, 580.97,
2035 580.83, 605.68, 667.88, 764.49, 759.93, 789.12, 798.17, 645.66,
2036 615.65, 455.05, 421.09, 306.45, 289.14, 235.7, 215.52, 274.57,
2037 316.53, 357.73, 409.89, 465.06, 521.84, 579.02, 630.64, 794.46,
2038 813., 813.56, 796.25, 761.57, 727.97, 812.14, 866.75, 932.5,
2039 1132.8, 1194.8, 1362.2, 1387.2, 1482.3, 1479.7, 1517.9, 1533.1,
2040 1534.2, 1523.3, 1522.5, 1515.5, 1505.2, 1486.5, 1454., 1412.,
2041 1358.8, 1107.8, 1060.9, 1033.5, 1048.2, 1122.4, 1248.9, 1227.1,
2042 1255.4, 1058.9, 1020.7, 970.59, 715.24, 512.56, 468.47, 349.3,
2043 338.26, 299.22, 301.26, 332.38, 382.08, 445.49, 515.87, 590.85,
2044 662.3, 726.05, 955.59, 964.11, 945.17, 891.48, 807.11, 720.9,
2045 803.36, 834.46, 1073.9, 1107.1, 1123.6, 1296., 1393.7, 1303.1,
2046 1284.3, 1161.8, 1078.8, 976.13, 868.72, 767.4, 674.72, 593.73,
2047 523.12, 462.24, 409.75, 364.34, 325., 290.73, 260.76, 234.46,
2048 211.28, 190.78, 172.61, 156.44, 142.01, 129.12, 117.57, 107.2,
2049 97.877, 89.47, 81.882, 75.021, 68.807, 63.171, 58.052, 53.396,
2050 49.155, 45.288, 41.759, 38.531, 35.576, 32.868, 30.384, 28.102,
2051 26.003, 24.071, 22.293, 20.655, 19.147, 17.756, 16.476, 15.292,
2052 14.198, 13.183, 12.241, 11.367, 10.554, 9.7989, 9.0978, 8.4475,
2053 7.845, 7.2868, 6.7704, 6.2927, 5.8508, 5.4421, 5.064, 4.714,
2054 4.3902, 4.0902, 3.8121, 3.5543, 3.315, 3.093, 2.8869, 2.6953,
2055 2.5172, 2.3517, 2.1977, 2.0544, 1.9211, 1.7969, 1.6812, 1.5735,
2056 1.4731, 1.3794, 1.2921, 1.2107, 1.1346, 1.0637, .99744, .93554,
2057 .87771, .82368, .77313, .72587, .6816, .64014, .60134, .565,
2058 .53086, .49883, .46881, .44074, .4144, .38979, .36679, .34513,
2059 .32474, .30552, .28751, .27045, .25458, .23976, .22584, .21278,
2060 .20051, .18899, .17815, .16801, .15846, .14954, .14117, .13328,
2061 .12584
2062 };
2063
2064 /* Get CO2 continuum absorption... */
2065 const double xw = nu / 2 + 1;
2066 if (xw >= 1 && xw < 2001) {
2067 const int iw = (int) xw;
2068 const double dw = xw - iw;
2069 const double ew = 1 - dw;
2070 const double cw296 = ew * co2296[iw - 1] + dw * co2296[iw];
2071 const double cw260 = ew * co2260[iw - 1] + dw * co2260[iw];
2072 const double cw230 = ew * co2230[iw - 1] + dw * co2230[iw];
2073 const double dt230 = t - 230;
2074 const double dt260 = t - 260;
2075 const double dt296 = t - 296;
2076 const double ctw =
2077 dt260 * 5.050505e-4 * dt296 * cw230 -
2078 dt230 * 9.259259e-4 * dt296 * cw260 +
2079 dt230 * 4.208754e-4 * dt260 * cw296;
2080 return u / NA / 1000 * p / P0 * ctw;
2081 } else
2082 return 0;
2083}
#define P0
Standard pressure [hPa].
Definition: jurassic.h:227
#define NA
Avogadro's number.
Definition: jurassic.h:212

◆ ctmh2o()

double ctmh2o ( const double  nu,
const double  p,
const double  t,
const double  q,
const double  u 
)

Compute the MT_CKD 4.1 water vapor continuum (optical depth).

Author
Lars Hoffmann

Definition at line 2087 of file jurassic.c.

2092 {
2093
2094 /* MT_CKD 4.1 coefficients from RFM 5.21 (0 to 20000 cm^-1). */
2095 static const double h2oslf[2001] =
2096 { 2.877e-21, 2.855e-21, 2.731e-21, 2.49e-21, 2.178e-21, 1.863e-21, 1.595e-21,
2097 1.381e-21, 1.221e-21, 1.095e-21, 9.882e-22, 8.926e-22, 8.041e-22, 7.217e-22,
2098 6.45e-22, 5.74e-22, 5.088e-22, 4.492e-22, 3.952e-22, 3.466e-22, 3.031e-22,
2099 2.644e-22, 2.302e-22, 2.001e-22, 1.738e-22, 1.509e-22, 1.311e-22, 1.139e-22,
2100 9.913e-23, 8.639e-23, 7.544e-23, 6.603e-23, 5.794e-23, 5.096e-23, 4.495e-23,
2101 3.974e-23, 3.523e-23, 3.13e-23, 2.786e-23, 2.485e-23, 2.221e-23, 1.987e-23,
2102 1.78e-23, 1.596e-23, 1.433e-23, 1.287e-23, 1.156e-23, 1.04e-23, 9.349e-24,
2103 8.41e-24, 7.568e-24, 6.81e-24, 6.13e-24, 5.517e-24, 4.967e-24, 4.471e-24,
2104 4.025e-24, 3.624e-24, 3.262e-24, 2.937e-24, 2.644e-24, 2.381e-24, 2.143e-24,
2105 1.93e-24, 1.737e-24, 1.564e-24, 1.413e-24, 1.284e-24, 1.176e-24, 1.087e-24,
2106 1.013e-24, 9.489e-25, 8.961e-25, 8.451e-25, 7.943e-25, 7.43e-25, 6.912e-25,
2107 6.447e-25, 6.025e-25, 5.642e-25, 5.292e-25, 4.971e-25, 4.69e-25, 4.444e-25,
2108 4.216e-25, 4.012e-25, 3.814e-25, 3.621e-25, 3.442e-25, 3.268e-25, 3.1e-25,
2109 2.957e-25, 2.78e-25, 2.617e-25, 2.445e-25, 2.305e-25, 2.187e-25, 2.08e-25,
2110 1.98e-25, 1.885e-25, 1.796e-25, 1.711e-25, 1.633e-25, 1.559e-25, 1.49e-25,
2111 1.426e-25, 1.367e-25, 1.312e-25, 1.263e-25, 1.218e-25, 1.178e-25, 1.143e-25,
2112 1.112e-25, 1.088e-25, 1.07e-25, 1.057e-25, 1.05e-25, 1.051e-25, 1.059e-25,
2113 1.076e-25, 1.1e-25, 1.133e-25, 1.18e-25, 1.237e-25, 1.308e-25, 1.393e-25,
2114 1.483e-25, 1.614e-25, 1.758e-25, 1.93e-25, 2.123e-25, 2.346e-25, 2.647e-25,
2115 2.93e-25, 3.279e-25, 3.745e-25, 4.152e-25, 4.813e-25, 5.477e-25, 6.203e-25,
2116 7.331e-25, 8.056e-25, 9.882e-25, 1.05e-24, 1.21e-24, 1.341e-24, 1.572e-24,
2117 1.698e-24, 1.968e-24, 2.175e-24, 2.431e-24, 2.735e-24, 2.867e-24, 3.19e-24,
2118 3.371e-24, 3.554e-24, 3.726e-24, 3.837e-24, 3.878e-24, 3.864e-24, 3.858e-24,
2119 3.841e-24, 3.852e-24, 3.815e-24, 3.762e-24, 3.618e-24, 3.579e-24, 3.45e-24,
2120 3.202e-24, 3.018e-24, 2.785e-24, 2.602e-24, 2.416e-24, 2.097e-24, 1.939e-24,
2121 1.689e-24, 1.498e-24, 1.308e-24, 1.17e-24, 1.011e-24, 9.237e-25, 7.909e-25,
2122 7.006e-25, 6.112e-25, 5.401e-25, 4.914e-25, 4.266e-25, 3.963e-25, 3.316e-25,
2123 3.037e-25, 2.598e-25, 2.294e-25, 2.066e-25, 1.813e-25, 1.583e-25, 1.423e-25,
2124 1.247e-25, 1.116e-25, 9.76e-26, 8.596e-26, 7.72e-26, 7.091e-26, 6.499e-26,
2125 5.801e-26, 5.15e-26, 4.5e-26, 4e-26, 3.509e-26, 3.1e-26, 2.714e-26,
2126 2.406e-26, 2.108e-26, 1.875e-26, 1.669e-26, 1.555e-26, 1.444e-26, 1.345e-26,
2127 1.257e-26, 1.175e-26, 1.102e-26, 1.035e-26, 9.745e-27, 9.194e-27, 8.685e-27,
2128 8.222e-27, 7.798e-27, 7.412e-27, 7.052e-27, 6.724e-27, 6.42e-27, 6.143e-27,
2129 5.886e-27, 5.649e-27, 5.43e-27, 5.228e-27, 5.041e-27, 4.868e-27, 4.708e-27,
2130 4.559e-27, 4.421e-27, 4.293e-27, 4.174e-27, 4.064e-27, 3.961e-27, 3.865e-27,
2131 3.775e-27, 3.692e-27, 3.614e-27, 3.542e-27, 3.474e-27, 3.411e-27, 3.353e-27,
2132 3.298e-27, 3.248e-27, 3.201e-27, 3.158e-27, 3.119e-27, 3.084e-27, 3.053e-27,
2133 3.025e-27, 3.003e-27, 2.988e-27, 2.976e-27, 2.977e-27, 2.989e-27, 3.015e-27,
2134 3.057e-27, 3.112e-27, 3.161e-27, 3.186e-27, 3.176e-27, 3.142e-27, 3.099e-27,
2135 3.065e-27, 3.011e-27, 2.955e-27, 2.914e-27, 2.884e-27, 2.864e-27, 2.858e-27,
2136 2.851e-27, 2.857e-27, 2.87e-27, 2.888e-27, 2.914e-27, 2.948e-27, 2.99e-27,
2137 3.042e-27, 3.105e-27, 3.185e-27, 3.276e-27, 3.385e-27, 3.511e-27, 3.646e-27,
2138 3.858e-27, 4.081e-27, 4.335e-27, 4.643e-27, 5.011e-27, 5.494e-27, 5.953e-27,
2139 6.354e-27, 7.116e-27, 7.498e-27, 8.613e-27, 9.35e-27, 1.002e-26, 1.09e-26,
2140 1.174e-26, 1.23e-26, 1.288e-26, 1.334e-26, 1.383e-26, 1.38e-26, 1.39e-26,
2141 1.373e-26, 1.354e-26, 1.335e-26, 1.343e-26, 1.323e-26, 1.349e-26, 1.353e-26,
2142 1.362e-26, 1.344e-26, 1.329e-26, 1.336e-26, 1.327e-26, 1.325e-26, 1.359e-26,
2143 1.374e-26, 1.415e-26, 1.462e-26, 1.526e-26, 1.619e-26, 1.735e-26, 1.863e-26,
2144 2.034e-26, 2.265e-26, 2.482e-26, 2.756e-26, 3.103e-26, 3.466e-26, 3.832e-26,
2145 4.378e-26, 4.913e-26, 5.651e-26, 6.311e-26, 7.169e-26, 8.057e-26, 9.253e-26,
2146 1.047e-25, 1.212e-25, 1.36e-25, 1.569e-25, 1.776e-25, 2.02e-25, 2.281e-25,
2147 2.683e-25, 2.994e-25, 3.488e-25, 3.896e-25, 4.499e-25, 5.175e-25, 6.035e-25,
2148 6.34e-25, 7.281e-25, 7.923e-25, 8.348e-25, 9.631e-25, 1.044e-24, 1.102e-24,
2149 1.176e-24, 1.244e-24, 1.283e-24, 1.326e-24, 1.4e-24, 1.395e-24, 1.387e-24,
2150 1.363e-24, 1.314e-24, 1.241e-24, 1.228e-24, 1.148e-24, 1.086e-24, 1.018e-24,
2151 8.89e-25, 8.316e-25, 7.292e-25, 6.452e-25, 5.625e-25, 5.045e-25, 4.38e-25,
2152 3.762e-25, 3.29e-25, 2.836e-25, 2.485e-25, 2.168e-25, 1.895e-25, 1.659e-25,
2153 1.453e-25, 1.282e-25, 1.132e-25, 1.001e-25, 8.836e-26, 7.804e-26, 6.922e-26,
2154 6.116e-26, 5.429e-26, 4.824e-26, 4.278e-26, 3.788e-26, 3.371e-26, 2.985e-26,
2155 2.649e-26, 2.357e-26, 2.09e-26, 1.858e-26, 1.647e-26, 1.462e-26, 1.299e-26,
2156 1.155e-26, 1.028e-26, 9.142e-27, 8.132e-27, 7.246e-27, 6.418e-27, 5.726e-27,
2157 5.221e-27, 4.89e-27, 4.666e-27, 4.443e-27, 4.203e-27, 3.978e-27, 3.77e-27,
2158 3.575e-27, 3.395e-27, 3.227e-27, 3.07e-27, 2.924e-27, 2.788e-27, 2.661e-27,
2159 2.543e-27, 2.433e-27, 2.329e-27, 2.233e-27, 2.143e-27, 2.058e-27, 1.98e-27,
2160 1.906e-27, 1.837e-27, 1.773e-27, 1.713e-27, 1.657e-27, 1.605e-27, 1.557e-27,
2161 1.514e-27, 1.472e-27, 1.435e-27, 1.404e-27, 1.377e-27, 1.354e-27, 1.332e-27,
2162 1.308e-27, 1.282e-27, 1.256e-27, 1.227e-27, 1.192e-27, 1.159e-27, 1.134e-27,
2163 1.114e-27, 1.098e-27, 1.081e-27, 1.066e-27, 1.055e-27, 1.045e-27, 1.036e-27,
2164 1.03e-27, 1.026e-27, 1.025e-27, 1.025e-27, 1.028e-27, 1.033e-27, 1.041e-27,
2165 1.049e-27, 1.06e-27, 1.075e-27, 1.093e-27, 1.114e-27, 1.139e-27, 1.166e-27,
2166 1.199e-27, 1.239e-27, 1.282e-27, 1.316e-27, 1.355e-27, 1.436e-27, 1.588e-27,
2167 1.807e-27, 2.06e-27, 2.337e-27, 2.645e-27, 2.996e-27, 3.393e-27, 3.843e-27,
2168 4.363e-27, 4.935e-27, 5.607e-27, 6.363e-27, 7.242e-27, 8.23e-27, 9.411e-27,
2169 1.071e-26, 1.232e-26, 1.402e-26, 1.6e-26, 1.82e-26, 2.128e-26, 2.386e-26,
2170 2.781e-26, 3.242e-26, 3.653e-26, 4.323e-26, 4.747e-26, 5.321e-26, 5.919e-26,
2171 6.681e-26, 7.101e-26, 7.983e-26, 8.342e-26, 8.741e-26, 9.431e-26, 9.952e-26,
2172 1.026e-25, 1.055e-25, 1.095e-25, 1.095e-25, 1.087e-25, 1.056e-25, 1.026e-25,
2173 9.715e-26, 9.252e-26, 8.452e-26, 7.958e-26, 7.268e-26, 6.295e-26, 6.003e-26,
2174 5e-26, 4.591e-26, 3.983e-26, 3.479e-26, 3.058e-26, 2.667e-26, 2.293e-26,
2175 1.995e-26, 1.747e-26, 1.517e-26, 1.335e-26, 1.165e-26, 1.028e-26, 9.007e-27,
2176 7.956e-27, 7.015e-27, 6.192e-27, 5.491e-27, 4.859e-27, 4.297e-27, 3.799e-27,
2177 3.38e-27, 3.002e-27, 2.659e-27, 2.366e-27, 2.103e-27, 1.861e-27, 1.655e-27,
2178 1.469e-27, 1.309e-27, 1.162e-27, 1.032e-27, 9.198e-28, 8.181e-28, 7.294e-28,
2179 6.516e-28, 5.787e-28, 5.163e-28, 4.612e-28, 4.096e-28, 3.654e-28, 3.299e-28,
2180 3.052e-28, 2.856e-28, 2.683e-28, 2.507e-28, 2.346e-28, 2.194e-28, 2.053e-28,
2181 1.921e-28, 1.799e-28, 1.686e-28, 1.58e-28, 1.481e-28, 1.389e-28, 1.304e-28,
2182 1.226e-28, 1.151e-28, 1.083e-28, 1.02e-28, 9.618e-29, 9.08e-29, 8.575e-29,
2183 8.08e-29, 7.624e-29, 7.176e-29, 6.761e-29, 6.37e-29, 6.004e-29, 5.672e-29,
2184 5.371e-29, 5.097e-29, 4.845e-29, 4.608e-29, 4.39e-29, 4.192e-29, 4.011e-29,
2185 3.846e-29, 3.698e-29, 3.568e-29, 3.45e-29, 3.351e-29, 3.268e-29, 3.195e-29,
2186 3.131e-29, 3.091e-29, 3.06e-29, 3.039e-29, 3.034e-29, 3.045e-29, 3.072e-29,
2187 3.116e-29, 3.176e-29, 3.253e-29, 3.347e-29, 3.467e-29, 3.605e-29, 3.763e-29,
2188 3.946e-29, 4.162e-29, 4.399e-29, 4.677e-29, 4.983e-29, 5.336e-29, 5.728e-29,
2189 6.168e-29, 6.684e-29, 7.214e-29, 7.861e-29, 8.62e-29, 9.481e-29, 1.032e-28,
2190 1.135e-28, 1.264e-28, 1.396e-28, 1.567e-28, 1.74e-28, 1.977e-28, 2.2e-28,
2191 2.563e-28, 2.935e-28, 3.386e-28, 3.993e-28, 4.828e-28, 5.714e-28, 6.877e-28,
2192 8.135e-28, 9.779e-28, 1.132e-27, 1.344e-27, 1.544e-27, 1.82e-27, 2.207e-27,
2193 2.509e-27, 2.854e-27, 3.026e-27, 3.278e-27, 3.474e-27, 3.693e-27, 3.93e-27,
2194 4.104e-27, 4.22e-27, 4.439e-27, 4.545e-27, 4.778e-27, 4.812e-27, 5.018e-27,
2195 4.899e-27, 5.075e-27, 5.073e-27, 5.171e-27, 5.131e-27, 5.25e-27, 5.617e-27,
2196 5.846e-27, 6.239e-27, 6.696e-27, 7.398e-27, 8.073e-27, 9.15e-27, 1.009e-26,
2197 1.116e-26, 1.264e-26, 1.439e-26, 1.644e-26, 1.856e-26, 2.147e-26, 2.317e-26,
2198 2.713e-26, 2.882e-26, 2.99e-26, 3.489e-26, 3.581e-26, 4.033e-26, 4.26e-26,
2199 4.543e-26, 4.84e-26, 4.826e-26, 5.013e-26, 5.252e-26, 5.277e-26, 5.306e-26,
2200 5.234e-26, 5.111e-26, 5.134e-26, 4.748e-26, 4.434e-26, 4.109e-26, 3.605e-26,
2201 3.252e-26, 2.731e-26, 2.369e-26, 1.922e-26, 1.558e-26, 1.321e-26, 1.058e-26,
2202 8.515e-27, 6.811e-27, 5.431e-27, 4.348e-27, 3.51e-27, 2.853e-27, 2.344e-27,
2203 1.949e-27, 1.649e-27, 1.409e-27, 1.232e-27, 1.098e-27, 9.866e-28, 8.899e-28,
2204 8.135e-28, 7.409e-28, 6.809e-28, 6.237e-28, 5.728e-28, 5.267e-28, 4.865e-28,
2205 4.482e-28, 4.169e-28, 3.841e-28, 3.573e-28, 3.304e-28, 3.065e-28, 2.851e-28,
2206 2.634e-28, 2.448e-28, 2.275e-28, 2.114e-28, 1.965e-28, 1.83e-28, 1.707e-28,
2207 1.591e-28, 1.484e-28, 1.386e-28, 1.294e-28, 1.209e-28, 1.131e-28, 1.056e-28,
2208 9.901e-29, 9.263e-29, 8.68e-29, 8.137e-29, 7.627e-29, 7.158e-29, 6.715e-29,
2209 6.305e-29, 5.927e-29, 5.568e-29, 5.242e-29, 4.935e-29, 4.648e-29, 4.383e-29,
2210 4.137e-29, 3.909e-29, 3.697e-29, 3.5e-29, 3.321e-29, 3.156e-29, 3.006e-29,
2211 2.868e-29, 2.745e-29, 2.638e-29, 2.545e-29, 2.469e-29, 2.405e-29, 2.369e-29,
2212 2.344e-29, 2.35e-29, 2.371e-29, 2.491e-29, 2.535e-29, 2.73e-29, 3.067e-29,
2213 3.322e-29, 3.63e-29, 4.045e-29, 4.524e-29, 4.981e-29, 5.613e-29, 6.051e-29,
2214 6.538e-29, 6.892e-29, 7.601e-29, 8.194e-29, 8.806e-29, 9.45e-29, 9.745e-29,
2215 1.009e-28, 1.017e-28, 1.039e-28, 1.061e-28, 1.076e-28, 1.086e-28, 1.111e-28,
2216 1.142e-28, 1.16e-28, 1.174e-28, 1.18e-28, 1.187e-28, 1.194e-28, 1.192e-28,
2217 1.224e-28, 1.245e-28, 1.246e-28, 1.318e-28, 1.377e-28, 1.471e-28, 1.582e-28,
2218 1.713e-28, 1.853e-28, 2.063e-28, 2.27e-28, 2.567e-28, 2.891e-28, 3.264e-28,
2219 3.744e-28, 4.286e-28, 4.915e-28, 5.623e-28, 6.336e-28, 7.293e-28, 8.309e-28,
2220 9.319e-28, 1.091e-27, 1.243e-27, 1.348e-27, 1.449e-27, 1.62e-27, 1.846e-27,
2221 1.937e-27, 2.04e-27, 2.179e-27, 2.298e-27, 2.433e-27, 2.439e-27, 2.464e-27,
2222 2.611e-27, 2.617e-27, 2.582e-27, 2.453e-27, 2.401e-27, 2.349e-27, 2.203e-27,
2223 2.066e-27, 1.939e-27, 1.78e-27, 1.558e-27, 1.391e-27, 1.203e-27, 1.048e-27,
2224 9.464e-28, 8.306e-28, 7.239e-28, 6.317e-28, 5.52e-28, 4.847e-28, 4.282e-28,
2225 3.796e-28, 3.377e-28, 2.996e-28, 2.678e-28, 2.4e-28, 2.134e-28, 1.904e-28,
2226 1.705e-28, 1.523e-28, 1.35e-28, 1.204e-28, 1.07e-28, 9.408e-29, 8.476e-29,
2227 7.47e-29, 6.679e-29, 5.929e-29, 5.267e-29, 4.711e-29, 4.172e-29, 3.761e-29,
2228 3.288e-29, 2.929e-29, 2.609e-29, 2.315e-29, 2.042e-29, 1.844e-29, 1.64e-29,
2229 1.47e-29, 1.31e-29, 1.176e-29, 1.049e-29, 9.377e-30, 8.462e-30, 7.616e-30,
2230 6.818e-30, 6.119e-30, 5.558e-30, 5.152e-30, 4.832e-30, 4.546e-30, 4.267e-30,
2231 4.009e-30, 3.77e-30, 3.546e-30, 3.34e-30, 3.149e-30, 2.971e-30, 2.805e-30,
2232 2.652e-30, 2.509e-30, 2.377e-30, 2.255e-30, 2.142e-30, 2.038e-30, 1.943e-30,
2233 1.855e-30, 1.776e-30, 1.703e-30, 1.64e-30, 1.586e-30, 1.536e-30, 1.494e-30,
2234 1.466e-30, 1.446e-30, 1.44e-30, 1.439e-30, 1.455e-30, 1.461e-30, 1.479e-30,
2235 1.514e-30, 1.538e-30, 1.59e-30, 1.652e-30, 1.75e-30, 1.811e-30, 1.88e-30,
2236 1.933e-30, 2.027e-30, 2.078e-30, 2.17e-30, 2.249e-30, 2.323e-30, 2.408e-30,
2237 2.461e-30, 2.536e-30, 2.581e-30, 2.615e-30, 2.721e-30, 2.782e-30, 2.866e-30,
2238 2.938e-30, 2.958e-30, 3.011e-30, 3.155e-30, 3.237e-30, 3.589e-30, 3.838e-30,
2239 4.083e-30, 4.354e-30, 4.745e-30, 5.148e-30, 5.648e-30, 6.194e-30, 6.748e-30,
2240 7.566e-30, 8.421e-30, 9.427e-30, 1.042e-29, 1.165e-29, 1.341e-29, 1.518e-29,
2241 1.686e-29, 2.036e-29, 2.362e-29, 2.811e-29, 3.296e-29, 4.07e-29, 4.695e-29,
2242 6.152e-29, 7.572e-29, 9.557e-29, 1.135e-28, 1.279e-28, 1.364e-28, 1.436e-28,
2243 1.54e-28, 1.672e-28, 1.793e-28, 1.906e-28, 2.036e-28, 2.144e-28, 2.292e-28,
2244 2.371e-28, 2.493e-28, 2.606e-28, 2.706e-28, 2.866e-28, 3.036e-28, 3.136e-28,
2245 3.405e-28, 3.665e-28, 3.837e-28, 4.229e-28, 4.748e-28, 5.32e-28, 5.763e-28,
2246 6.677e-28, 7.216e-28, 7.716e-28, 8.958e-28, 9.419e-28, 1.036e-27, 1.108e-27,
2247 1.189e-27, 1.246e-27, 1.348e-27, 1.31e-27, 1.361e-27, 1.364e-27, 1.363e-27,
2248 1.343e-27, 1.293e-27, 1.254e-27, 1.235e-27, 1.158e-27, 1.107e-27, 9.961e-28,
2249 9.011e-28, 7.91e-28, 6.916e-28, 6.338e-28, 5.564e-28, 4.827e-28, 4.198e-28,
2250 3.695e-28, 3.276e-28, 2.929e-28, 2.633e-28, 2.391e-28, 2.192e-28, 2.021e-28,
2251 1.89e-28, 1.772e-28, 1.667e-28, 1.603e-28, 1.547e-28, 1.537e-28, 1.492e-28,
2252 1.515e-28, 1.479e-28, 1.45e-28, 1.513e-28, 1.495e-28, 1.529e-28, 1.565e-28,
2253 1.564e-28, 1.553e-28, 1.569e-28, 1.584e-28, 1.57e-28, 1.538e-28, 1.531e-28,
2254 1.346e-28, 1.199e-28, 1.044e-28, 8.892e-29, 7.076e-29, 5.884e-29, 5.039e-29,
2255 4.129e-29, 3.663e-29, 2.993e-29, 2.622e-29, 2.232e-29, 1.884e-29, 1.569e-29,
2256 1.348e-29, 1.144e-29, 1.009e-29, 8.833e-30, 7.907e-30, 7.079e-30, 6.514e-30,
2257 5.823e-30, 5.312e-30, 4.883e-30, 4.458e-30, 4.094e-30, 3.734e-30, 3.458e-30,
2258 3.205e-30, 2.962e-30, 2.733e-30, 2.532e-30, 2.351e-30, 2.187e-30, 2.034e-30,
2259 1.889e-30, 1.764e-30, 1.648e-30, 1.541e-30, 1.443e-30, 1.355e-30, 1.274e-30,
2260 1.198e-30, 1.133e-30, 1.071e-30, 1.015e-30, 9.648e-31, 9.195e-31, 8.791e-31,
2261 8.435e-31, 8.125e-31, 7.859e-31, 7.621e-31, 7.481e-31, 7.351e-31, 7.228e-31,
2262 7.295e-31, 7.339e-31, 7.588e-31, 7.701e-31, 7.886e-31, 8.511e-31, 9.061e-31,
2263 9.926e-31, 1.083e-30, 1.241e-30, 1.469e-30, 1.736e-30, 1.966e-30, 2.132e-30,
2264 2.28e-30, 2.473e-30, 2.718e-30, 2.922e-30, 3.128e-30, 3.361e-30, 3.641e-30,
2265 3.91e-30, 4.196e-30, 4.501e-30, 4.932e-30, 5.258e-30, 5.755e-30, 6.253e-30,
2266 6.664e-30, 7.344e-30, 7.985e-30, 8.877e-30, 1.005e-29, 1.118e-29, 1.251e-29,
2267 1.428e-29, 1.61e-29, 1.888e-29, 2.077e-29, 2.331e-29, 2.751e-29, 3.061e-29,
2268 3.522e-29, 3.805e-29, 4.181e-29, 4.575e-29, 5.167e-29, 5.634e-29, 6.007e-29,
2269 6.501e-29, 6.829e-29, 7.211e-29, 7.262e-29, 7.696e-29, 7.832e-29, 7.799e-29,
2270 7.651e-29, 7.304e-29, 7.15e-29, 6.977e-29, 6.603e-29, 6.209e-29, 5.69e-29,
2271 5.432e-29, 4.764e-29, 4.189e-29, 3.64e-29, 3.203e-29, 2.848e-29, 2.51e-29,
2272 2.194e-29, 1.946e-29, 1.75e-29, 1.567e-29, 1.426e-29, 1.302e-29, 1.197e-29,
2273 1.109e-29, 1.035e-29, 9.719e-30, 9.207e-30, 8.957e-30, 8.578e-30, 8.262e-30,
2274 8.117e-30, 7.987e-30, 7.875e-30, 7.741e-30, 7.762e-30, 7.537e-30, 7.424e-30,
2275 7.474e-30, 7.294e-30, 7.216e-30, 7.233e-30, 7.14e-30, 7.085e-30, 6.434e-30,
2276 5.585e-30, 5.015e-30, 3.956e-30, 3.337e-30, 2.545e-30, 2.141e-30, 1.761e-30,
2277 1.685e-30, 1.507e-30, 1.241e-30, 1.081e-30, 9.675e-31, 7.964e-31, 6.93e-31,
2278 5.79e-31, 5.069e-31, 4.452e-31, 3.97e-31, 3.551e-31, 3.228e-31, 2.939e-31,
2279 2.682e-31, 2.471e-31, 2.278e-31, 2.106e-31, 1.95e-31, 1.811e-31, 1.682e-31,
2280 1.563e-31, 1.458e-31, 1.363e-31, 1.278e-31, 1.2e-31, 1.129e-31, 1.066e-31,
2281 1.007e-31, 9.545e-32, 9.075e-32, 8.656e-32, 8.285e-32, 7.958e-32, 7.674e-32,
2282 7.431e-32, 7.227e-32, 7.061e-32, 6.934e-32, 6.843e-32, 6.79e-32, 6.775e-32,
2283 6.798e-32, 6.859e-32, 6.96e-32, 7.102e-32, 7.287e-32, 7.517e-32, 7.795e-32,
2284 8.123e-32, 8.504e-32, 8.945e-32, 9.45e-32, 1.003e-31, 1.07e-31, 1.148e-31,
2285 1.232e-31, 1.327e-31, 1.441e-31, 1.535e-31, 1.655e-31, 1.814e-31, 2.02e-31,
2286 2.307e-31, 2.622e-31, 2.962e-31, 3.369e-31, 3.819e-31, 4.329e-31, 4.932e-31,
2287 5.589e-31, 6.364e-31, 7.284e-31, 8.236e-31, 9.447e-31, 1.078e-30, 1.229e-30,
2288 1.417e-30, 1.614e-30, 1.843e-30, 2.107e-30, 2.406e-30, 2.728e-30, 3.195e-30,
2289 3.595e-30, 4.153e-30, 4.736e-30, 5.41e-30, 6.088e-30, 6.769e-30, 7.691e-30,
2290 8.545e-30, 9.621e-30, 1.047e-29, 1.161e-29, 1.296e-29, 1.424e-29, 1.576e-29,
2291 1.739e-29, 1.893e-29, 2.08e-29, 2.336e-29, 2.604e-29, 2.76e-29, 3.001e-29,
2292 3.365e-29, 3.55e-29, 3.895e-29, 4.183e-29, 4.614e-29, 4.846e-29, 5.068e-29,
2293 5.427e-29, 5.541e-29, 5.864e-29, 5.997e-29, 5.997e-29, 6.061e-29, 5.944e-29,
2294 5.855e-29, 5.661e-29, 5.523e-29, 5.374e-29, 4.94e-29, 4.688e-29, 4.17e-29,
2295 3.913e-29, 3.423e-29, 2.997e-29, 2.598e-29, 2.253e-29, 1.946e-29, 1.71e-29,
2296 1.507e-29, 1.336e-29, 1.19e-29, 1.068e-29, 9.623e-30, 8.772e-30, 8.007e-30,
2297 7.42e-30, 6.884e-30, 6.483e-30, 6.162e-30, 5.922e-30, 5.688e-30, 5.654e-30,
2298 5.637e-30, 5.701e-30, 5.781e-30, 5.874e-30, 6.268e-30, 6.357e-30, 6.525e-30,
2299 7.137e-30, 7.441e-30, 8.024e-30, 8.485e-30, 9.143e-30, 9.536e-30, 9.717e-30,
2300 1.018e-29, 1.042e-29, 1.054e-29, 1.092e-29, 1.093e-29, 1.072e-29, 1.046e-29,
2301 9.283e-30, 8.053e-30, 6.68e-30, 5.63e-30, 4.933e-30, 3.488e-30, 3.324e-30,
2302 2.826e-30, 2.429e-30, 2.051e-30, 1.679e-30, 1.411e-30, 1.24e-30, 1.098e-30,
2303 9.668e-31, 8.529e-31, 7.848e-31, 7.098e-31, 6.117e-31, 5.246e-31, 4.521e-31,
2304 4.059e-31, 3.783e-31, 3.502e-31, 3.271e-31, 2.956e-31, 2.636e-31, 2.464e-31,
2305 2.19e-31, 1.986e-31, 1.791e-31, 1.638e-31, 1.491e-31, 1.383e-31, 1.271e-31,
2306 1.166e-31, 1.082e-31, 1.002e-31, 9.317e-32, 8.697e-32, 8.157e-32, 7.678e-32,
2307 7.252e-32, 6.874e-32, 6.539e-32, 6.243e-32, 5.985e-32, 5.763e-32, 5.575e-32,
2308 5.421e-32, 5.3e-32, 5.212e-32, 5.157e-32, 5.138e-32, 5.156e-32, 5.214e-32,
2309 5.313e-32, 5.457e-32, 5.686e-32, 5.953e-32, 6.284e-32, 6.856e-32, 7.351e-32,
2310 8.006e-32, 8.957e-32, 1.031e-31, 1.17e-31, 1.345e-31, 1.623e-31, 1.999e-31,
2311 2.507e-31, 3.004e-31, 3.378e-31, 3.688e-31, 4.118e-31, 4.569e-31, 5.025e-31,
2312 5.66e-31, 6.231e-31, 6.881e-31, 7.996e-31, 8.526e-31, 9.694e-31, 1.106e-30,
2313 1.222e-30, 1.355e-30, 1.525e-30, 1.775e-30, 1.924e-30, 2.181e-30, 2.379e-30,
2314 2.662e-30, 2.907e-30, 3.154e-30, 3.366e-30, 3.579e-30, 3.858e-30, 4.046e-30,
2315 4.196e-30, 4.166e-30, 4.457e-30, 4.466e-30, 4.404e-30, 4.337e-30, 4.15e-30,
2316 4.083e-30, 3.91e-30, 3.723e-30, 3.514e-30, 3.303e-30, 2.847e-30, 2.546e-30,
2317 2.23e-30, 1.994e-30, 1.733e-30, 1.488e-30, 1.297e-30, 1.144e-30, 1.004e-30,
2318 8.741e-31, 7.928e-31, 7.034e-31, 6.323e-31, 5.754e-31, 5.25e-31, 4.85e-31,
2319 4.502e-31, 4.286e-31, 4.028e-31, 3.899e-31, 3.824e-31, 3.761e-31, 3.804e-31,
2320 3.839e-31, 3.845e-31, 4.244e-31, 4.382e-31, 4.582e-31, 4.847e-31, 5.209e-31,
2321 5.384e-31, 5.887e-31, 6.371e-31, 6.737e-31, 7.168e-31, 7.415e-31, 7.827e-31,
2322 8.037e-31, 8.12e-31, 8.154e-31, 7.981e-31, 7.783e-31, 6.9e-31, 6.03e-31,
2323 4.9e-31, 3.878e-31, 3.068e-31, 2.533e-31, 2.255e-31, 2.056e-31, 1.569e-31,
2324 1.398e-31, 1.149e-31, 9.249e-32, 7.706e-32, 6.436e-32, 5.514e-32, 4.782e-32,
2325 4.202e-32, 3.721e-32, 3.336e-32, 3.015e-32, 2.744e-32, 2.512e-32, 2.312e-32,
2326 2.138e-32, 1.987e-32, 1.855e-32, 1.741e-32, 1.642e-32, 1.557e-32, 1.483e-32,
2327 1.422e-32, 1.37e-32, 1.329e-32, 1.297e-32, 1.274e-32, 1.259e-32, 1.253e-32,
2328 1.255e-32, 1.266e-32, 1.284e-32, 1.312e-32, 1.348e-32, 1.393e-32, 1.448e-32,
2329 1.512e-32, 1.587e-32, 1.672e-32, 1.77e-32, 1.88e-32, 1.99e-32, 2.11e-32,
2330 2.274e-32, 2.516e-32, 2.844e-32, 3.231e-32, 3.661e-32, 4.153e-32, 4.717e-32,
2331 5.36e-32, 6.094e-32, 6.93e-32, 7.882e-32, 8.966e-32, 1.02e-31, 1.162e-31,
2332 1.324e-31, 1.51e-31, 1.72e-31, 1.965e-31, 2.237e-31, 2.56e-31, 2.927e-31,
2333 3.371e-31, 3.842e-31, 4.429e-31, 5.139e-31, 5.798e-31, 6.697e-31, 7.626e-31,
2334 8.647e-31, 1.022e-30, 1.136e-30, 1.3e-30, 1.481e-30, 1.672e-30, 1.871e-30,
2335 2.126e-30, 2.357e-30, 2.583e-30, 2.997e-30, 3.289e-30, 3.702e-30, 4.012e-30,
2336 4.319e-30, 4.527e-30, 5.001e-30, 5.448e-30, 5.611e-30, 5.76e-30, 5.965e-30,
2337 6.079e-30, 6.207e-30, 6.276e-30, 6.222e-30, 6.137e-30, 6e-30, 5.814e-30,
2338 5.393e-30, 5.35e-30, 4.947e-30, 4.629e-30, 4.117e-30, 3.712e-30, 3.372e-30,
2339 2.923e-30, 2.55e-30, 2.232e-30, 1.929e-30, 1.679e-30, 1.46e-30, 1.289e-30,
2340 1.13e-30, 9.953e-31, 8.763e-31, 7.76e-31, 6.9e-31, 6.16e-31, 5.525e-31,
2341 4.958e-31, 4.489e-31, 4.072e-31, 3.728e-31, 3.438e-31, 3.205e-31, 3.006e-31,
2342 2.848e-31, 2.766e-31, 2.688e-31, 2.664e-31, 2.67e-31, 2.696e-31, 2.786e-31,
2343 2.861e-31, 3.009e-31, 3.178e-31, 3.389e-31, 3.587e-31, 3.819e-31, 4.054e-31,
2344 4.417e-31, 4.703e-31, 5.137e-31, 5.46e-31, 6.055e-31, 6.333e-31, 6.773e-31,
2345 7.219e-31, 7.717e-31, 8.131e-31, 8.491e-31, 8.574e-31, 9.01e-31, 9.017e-31,
2346 8.999e-31, 8.959e-31, 8.838e-31, 8.579e-31, 8.162e-31, 8.098e-31, 7.472e-31,
2347 7.108e-31, 6.559e-31, 5.994e-31, 5.172e-31, 4.424e-31, 3.951e-31, 3.34e-31,
2348 2.902e-31, 2.541e-31, 2.215e-31, 1.945e-31, 1.716e-31, 1.503e-31, 1.339e-31,
2349 1.185e-31, 1.05e-31, 9.336e-32, 8.307e-32, 7.312e-32, 6.55e-32, 5.836e-32,
2350 5.178e-32, 4.6e-32, 4.086e-32, 3.639e-32, 3.247e-32, 2.904e-32, 2.604e-32,
2351 2.341e-32, 2.112e-32, 1.914e-32, 1.744e-32, 1.598e-32, 1.476e-32, 1.374e-32,
2352 1.293e-32, 1.23e-32, 1.185e-32, 1.158e-32, 1.147e-32, 1.154e-32, 1.177e-32,
2353 1.219e-32, 1.28e-32, 1.36e-32, 1.463e-32, 1.591e-32, 1.75e-32, 1.94e-32,
2354 2.156e-32, 2.43e-32, 2.748e-32, 3.052e-32, 3.533e-32, 3.967e-32, 4.471e-32,
2355 5.041e-32, 5.86e-32, 6.664e-32, 7.522e-32, 8.342e-32, 9.412e-32, 1.072e-31,
2356 1.213e-31, 1.343e-31, 1.496e-31, 1.664e-31, 1.822e-31, 2.029e-31, 2.233e-31,
2357 2.457e-31, 2.709e-31, 2.928e-31, 3.115e-31, 3.356e-31, 3.592e-31, 3.818e-31,
2358 3.936e-31, 4.061e-31, 4.149e-31, 4.299e-31, 4.223e-31, 4.251e-31, 4.287e-31,
2359 4.177e-31, 4.094e-31, 3.942e-31, 3.772e-31, 3.614e-31, 3.394e-31, 3.222e-31,
2360 2.791e-31, 2.665e-31, 2.309e-31, 2.032e-31, 1.74e-31, 1.535e-31, 1.323e-31,
2361 1.151e-31, 9.803e-32, 8.65e-32, 7.54e-32, 6.619e-32, 5.832e-32, 5.113e-32,
2362 4.503e-32, 3.975e-32, 3.52e-32, 3.112e-32, 2.797e-32, 2.5e-32, 2.24e-32,
2363 2.013e-32, 1.819e-32, 1.653e-32, 1.513e-32, 1.395e-32, 1.299e-32, 1.225e-32,
2364 1.168e-32, 1.124e-32, 1.148e-32, 1.107e-32, 1.128e-32, 1.169e-32, 1.233e-32,
2365 1.307e-32, 1.359e-32, 1.543e-32, 1.686e-32, 1.794e-32, 2.028e-32, 2.21e-32,
2366 2.441e-32, 2.653e-32, 2.828e-32, 3.093e-32, 3.28e-32, 3.551e-32, 3.677e-32,
2367 3.803e-32, 3.844e-32, 4.068e-32, 4.093e-32, 4.002e-32, 3.904e-32, 3.624e-32,
2368 3.633e-32, 3.622e-32, 3.443e-32, 3.184e-32, 2.934e-32, 2.476e-32, 2.212e-32,
2369 1.867e-32, 1.594e-32, 1.37e-32, 1.192e-32, 1.045e-32, 9.211e-33, 8.17e-33,
2370 7.29e-33, 6.55e-33, 5.929e-33, 5.415e-33, 4.995e-33, 4.661e-33, 4.406e-33,
2371 4.225e-33, 4.116e-33, 4.075e-33, 4.102e-33, 4.198e-33, 4.365e-33, 4.606e-33,
2372 4.925e-33, 5.326e-33, 5.818e-33, 6.407e-33, 7.104e-33, 7.92e-33, 8.868e-33,
2373 9.964e-33, 1.123e-32, 1.268e-32, 1.434e-32, 1.626e-32, 1.848e-32, 2.107e-32,
2374 2.422e-32, 2.772e-32, 3.145e-32, 3.704e-32, 4.27e-32, 4.721e-32, 5.361e-32,
2375 6.083e-32, 7.095e-32, 7.968e-32, 9.228e-32, 1.048e-31, 1.187e-31, 1.336e-31,
2376 1.577e-31, 1.772e-31, 2.017e-31, 2.25e-31, 2.63e-31, 2.911e-31, 3.356e-31,
2377 3.82e-31, 4.173e-31, 4.811e-31, 5.254e-31, 5.839e-31, 6.187e-31, 6.805e-31,
2378 7.118e-31, 7.369e-31, 7.664e-31, 7.794e-31, 7.947e-31, 8.036e-31, 7.954e-31,
2379 7.849e-31, 7.518e-31, 7.462e-31, 6.926e-31, 6.531e-31, 6.197e-31, 5.421e-31,
2380 4.777e-31, 4.111e-31, 3.679e-31, 3.166e-31, 2.786e-31, 2.436e-31, 2.144e-31,
2381 1.859e-31, 1.628e-31, 1.414e-31, 1.237e-31, 1.093e-31, 9.558e-32
2382 };
2383
2384 static const double h2ofrn[2001] =
2385 { 8.563e-23, 8.828e-23, 9.182e-23, 9.796e-23, 1.14e-22, 1.376e-22, 1.545e-22,
2386 1.508e-22, 1.386e-22, 1.215e-22, 1.063e-22, 9.151e-23, 8.008e-23, 6.97e-23,
2387 6.055e-23, 5.243e-23, 4.559e-23, 3.763e-23, 3.055e-23, 2.563e-23, 2.197e-23,
2388 1.809e-23, 1.483e-23, 1.167e-23, 8.809e-24, 7.131e-24, 5.933e-24, 5.172e-24,
2389 4.22e-24, 3.427e-24, 2.648e-24, 2.123e-24, 1.825e-24, 1.476e-24, 1.101e-24,
2390 8.588e-25, 6.499e-25, 4.875e-25, 3.861e-25, 3.001e-25, 2.343e-25, 2.087e-25,
2391 1.771e-25, 1.588e-25, 1.408e-25, 1.181e-25, 1.024e-25, 9.223e-26, 7.916e-26,
2392 6.692e-26, 5.72e-26, 5.125e-26, 4.478e-26, 3.844e-26, 3.267e-26, 2.851e-26,
2393 2.473e-26, 2.124e-26, 1.768e-26, 1.481e-26, 1.267e-26, 1.075e-26, 9.212e-27,
2394 7.849e-27, 6.601e-27, 5.599e-27, 4.768e-27, 4.098e-27, 3.558e-27, 3.089e-27,
2395 2.678e-27, 2.339e-27, 2.038e-27, 1.755e-27, 1.497e-27, 1.294e-27, 1.129e-27,
2396 9.878e-28, 8.603e-28, 7.494e-28, 6.568e-28, 5.747e-28, 5.025e-28, 4.345e-28,
2397 3.758e-28, 3.272e-28, 2.862e-28, 2.508e-28, 2.198e-28, 1.918e-28, 1.68e-28,
2398 1.471e-28, 1.289e-28, 1.135e-28, 9.962e-29, 8.767e-29, 7.699e-29, 6.798e-29,
2399 6.007e-29, 5.336e-29, 4.75e-29, 4.232e-29, 3.807e-29, 3.476e-29, 3.237e-29,
2400 3.002e-29, 2.821e-29, 2.757e-29, 2.816e-29, 2.92e-29, 3.044e-29, 3.42e-29,
2401 3.745e-29, 4.197e-29, 4.816e-29, 5.987e-29, 7.098e-29, 8.082e-29, 9.622e-29,
2402 1.211e-28, 1.502e-28, 1.766e-28, 2.223e-28, 2.901e-28, 3.951e-28, 5.072e-28,
2403 6.232e-28, 7.904e-28, 1.034e-27, 1.438e-27, 1.89e-27, 2.59e-27, 3.592e-27,
2404 4.973e-27, 7.159e-27, 9.987e-27, 1.382e-26, 1.93e-26, 2.592e-26, 3.454e-26,
2405 4.572e-26, 5.932e-26, 7.554e-26, 9.559e-26, 1.183e-25, 1.425e-25, 1.681e-25,
2406 1.978e-25, 2.336e-25, 2.669e-25, 3.023e-25, 3.372e-25, 3.716e-25, 3.968e-25,
2407 4.061e-25, 4.011e-25, 3.81e-25, 3.491e-25, 3.155e-25, 2.848e-25, 2.678e-25,
2408 2.66e-25, 2.811e-25, 3.071e-25, 3.294e-25, 3.459e-25, 3.569e-25, 3.56e-25,
2409 3.434e-25, 3.186e-25, 2.916e-25, 2.622e-25, 2.275e-25, 1.918e-25, 1.62e-25,
2410 1.373e-25, 1.182e-25, 1.006e-25, 8.556e-26, 7.26e-26, 6.11e-26, 5.04e-26,
2411 4.23e-26, 3.456e-26, 2.903e-26, 2.486e-26, 2.039e-26, 1.672e-26, 1.285e-26,
2412 1.054e-26, 8.302e-27, 6.667e-27, 5.503e-27, 4.562e-27, 3.948e-27, 3.198e-27,
2413 2.586e-27, 2.225e-27, 1.807e-27, 1.53e-27, 1.294e-27, 1.126e-27, 9.604e-28,
2414 7.85e-28, 6.813e-28, 5.583e-28, 4.69e-28, 3.996e-28, 3.373e-28, 2.93e-28,
2415 2.417e-28, 2.061e-28, 1.743e-28, 1.475e-28, 1.273e-28, 1.084e-28, 9.368e-29,
2416 7.985e-29, 6.785e-29, 5.804e-29, 4.975e-29, 4.311e-29, 3.738e-29, 3.275e-29,
2417 2.847e-29, 2.469e-29, 2.149e-29, 1.884e-29, 1.631e-29, 1.393e-29, 1.201e-29,
2418 1.027e-29, 8.807e-30, 7.521e-30, 6.436e-30, 5.509e-30, 4.729e-30, 4.055e-30,
2419 3.49e-30, 3.006e-30, 2.599e-30, 2.246e-30, 1.942e-30, 1.685e-30, 1.464e-30,
2420 1.273e-30, 1.115e-30, 9.794e-31, 8.729e-31, 7.893e-31, 7.313e-31, 7.069e-31,
2421 7.19e-31, 7.828e-31, 9.295e-31, 1.174e-30, 1.578e-30, 2.184e-30, 3.053e-30,
2422 4.212e-30, 5.733e-30, 7.497e-30, 9.487e-30, 1.153e-29, 1.343e-29, 1.503e-29,
2423 1.623e-29, 1.696e-29, 1.746e-29, 1.789e-29, 1.852e-29, 1.862e-29, 1.886e-29,
2424 1.912e-29, 1.942e-29, 1.938e-29, 1.914e-29, 1.898e-29, 1.864e-29, 1.77e-29,
2425 1.635e-29, 1.464e-29, 1.279e-29, 1.099e-29, 9.528e-30, 8.433e-30, 7.794e-30,
2426 7.793e-30, 8.241e-30, 9.417e-30, 1.179e-29, 1.616e-29, 2.144e-29, 2.992e-29,
2427 4.344e-29, 6.415e-29, 9.242e-29, 1.31e-28, 1.847e-28, 2.567e-28, 3.39e-28,
2428 4.357e-28, 5.301e-28, 6.364e-28, 7.438e-28, 8.381e-28, 9.294e-28, 1.013e-27,
2429 1.103e-27, 1.17e-27, 1.2e-27, 1.19e-27, 1.133e-27, 1.04e-27, 9.475e-28,
2430 8.601e-28, 8.074e-28, 8.023e-28, 8.473e-28, 9.256e-28, 9.989e-28, 1.056e-27,
2431 1.079e-27, 1.079e-27, 1.049e-27, 1e-27, 9.35e-28, 8.662e-28, 7.88e-28,
2432 7.137e-28, 6.438e-28, 5.706e-28, 5.132e-28, 4.815e-28, 4.736e-28, 4.709e-28,
2433 4.918e-28, 5.227e-28, 5.603e-28, 6.023e-28, 6.567e-28, 7.403e-28, 8.695e-28,
2434 9.929e-28, 1.163e-27, 1.379e-27, 1.658e-27, 2.01e-27, 2.425e-27, 2.92e-27,
2435 3.562e-27, 4.274e-27, 5.173e-27, 6.285e-27, 7.787e-27, 9.563e-27, 1.194e-26,
2436 1.517e-26, 1.934e-26, 2.511e-26, 3.197e-26, 4.024e-26, 4.981e-26, 6.09e-26,
2437 7.229e-26, 8.439e-26, 9.367e-26, 1.016e-25, 1.057e-25, 1.088e-25, 1.108e-25,
2438 1.129e-25, 1.159e-25, 1.19e-25, 1.21e-25, 1.21e-25, 1.2e-25, 1.19e-25,
2439 1.18e-25, 1.19e-25, 1.23e-25, 1.28e-25, 1.3e-25, 1.29e-25, 1.21e-25,
2440 1.09e-25, 9.44e-26, 7.79e-26, 6.22e-26, 4.64e-26, 3.4e-26, 2.47e-26,
2441 1.78e-26, 1.29e-26, 9.26e-27, 7e-27, 5.36e-27, 4.26e-27, 3.41e-27,
2442 2.79e-27, 2.36e-27, 2.01e-27, 1.75e-27, 1.52e-27, 1.33e-27, 1.16e-27,
2443 1.01e-27, 8.83e-28, 7.71e-28, 6.77e-28, 6.01e-28, 5.34e-28, 4.72e-28,
2444 4.2e-28, 3.69e-28, 3.27e-28, 2.92e-28, 2.57e-28, 2.27e-28, 2e-28,
2445 1.77e-28, 1.56e-28, 1.37e-28, 1.2e-28, 1.05e-28, 9.18e-29, 8e-29,
2446 6.98e-29, 6.08e-29, 5.27e-29, 4.56e-29, 3.94e-29, 3.4e-29, 2.93e-29,
2447 2.51e-29, 2.15e-29, 1.84e-29, 1.57e-29, 1.34e-29, 1.14e-29, 9.66e-30,
2448 8.19e-30, 6.93e-30, 5.86e-30, 4.95e-30, 4.19e-30, 3.56e-30, 3.06e-30,
2449 2.67e-30, 2.41e-30, 2.26e-30, 2.25e-30, 2.36e-30, 2.57e-30, 2.84e-30,
2450 3.18e-30, 3.49e-30, 3.71e-30, 3.81e-30, 3.84e-30, 3.8e-30, 3.59e-30,
2451 3.37e-30, 3.08e-30, 2.77e-30, 2.47e-30, 2.2e-30, 2.05e-30, 1.99e-30,
2452 2.03e-30, 2.13e-30, 2.25e-30, 2.34e-30, 2.41e-30, 2.47e-30, 2.48e-30,
2453 2.5e-30, 2.52e-30, 2.58e-30, 2.64e-30, 2.69e-30, 2.79e-30, 2.95e-30,
2454 3.13e-30, 3.34e-30, 3.57e-30, 3.84e-30, 4.2e-30, 4.66e-30, 5.21e-30,
2455 5.96e-30, 6.89e-30, 8.01e-30, 9.32e-30, 1.08e-29, 1.24e-29, 1.45e-29,
2456 1.71e-29, 2.01e-29, 2.36e-29, 2.82e-29, 3.38e-29, 4.01e-29, 4.79e-29,
2457 5.74e-29, 6.92e-29, 8.338e-29, 1.015e-28, 1.246e-28, 1.512e-28, 1.851e-28,
2458 2.32e-28, 2.988e-28, 3.989e-28, 5.351e-28, 7.256e-28, 1.011e-27, 1.388e-27,
2459 1.914e-27, 2.512e-27, 3.257e-27, 4.075e-27, 4.991e-27, 5.914e-27, 6.638e-27,
2460 7.16e-27, 7.45e-27, 7.59e-27, 7.54e-27, 7.47e-27, 7.53e-27, 7.94e-27,
2461 8.46e-27, 8.95e-27, 9.36e-27, 9.84e-27, 1.02e-26, 1.05e-26, 1.06e-26,
2462 1.07e-26, 1.07e-26, 1.04e-26, 9.79e-27, 8.8e-27, 7.66e-27, 6.38e-27,
2463 5.142e-27, 3.982e-27, 2.94e-27, 2.177e-27, 1.612e-27, 1.185e-27, 8.966e-28,
2464 6.735e-28, 5.219e-28, 4.14e-28, 3.403e-28, 2.811e-28, 2.358e-28, 1.969e-28,
2465 1.684e-28, 1.462e-28, 1.285e-28, 1.134e-28, 9.916e-29, 8.65e-29, 7.55e-29,
2466 6.62e-29, 5.83e-29, 5.14e-29, 4.51e-29, 3.98e-29, 3.53e-29, 3.12e-29,
2467 2.78e-29, 2.48e-29, 2.18e-29, 1.93e-29, 1.7e-29, 1.5e-29, 1.33e-29,
2468 1.16e-29, 1.03e-29, 9.01e-30, 7.86e-30, 6.88e-30, 6.02e-30, 5.25e-30,
2469 4.57e-30, 3.96e-30, 3.44e-30, 2.98e-30, 2.57e-30, 2.21e-30, 1.9e-30,
2470 1.63e-30, 1.4e-30, 1.21e-30, 1.04e-30, 9.09e-31, 7.96e-31, 7.05e-31,
2471 6.3e-31, 5.67e-31, 5.09e-31, 4.55e-31, 4.04e-31, 3.55e-31, 3.09e-31,
2472 2.64e-31, 2.26e-31, 1.9e-31, 1.6e-31, 1.34e-31, 1.14e-31, 1.01e-31,
2473 9.17e-32, 8.69e-32, 8.47e-32, 8.33e-32, 8.2e-32, 8.04e-32, 7.95e-32,
2474 7.98e-32, 8.25e-32, 8.47e-32, 8.74e-32, 8.87e-32, 8.92e-32, 8.71e-32,
2475 8.3e-32, 7.89e-32, 7.59e-32, 7.5e-32, 7.63e-32, 8.06e-32, 8.89e-32,
2476 1e-31, 1.14e-31, 1.28e-31, 1.45e-31, 1.64e-31, 1.87e-31, 2.12e-31,
2477 2.44e-31, 2.85e-31, 3.31e-31, 3.83e-31, 4.46e-31, 5.23e-31, 6.15e-31,
2478 7.35e-31, 8.84e-31, 1.07e-30, 1.29e-30, 1.59e-30, 1.99e-30, 2.49e-30,
2479 3.12e-30, 3.91e-30, 4.98e-30, 6.28e-30, 7.86e-30, 9.66e-30, 1.16e-29,
2480 1.41e-29, 1.7e-29, 2.06e-29, 2.54e-29, 3.17e-29, 4.08e-29, 5.24e-29,
2481 6.8e-29, 8.92e-29, 1.13e-28, 1.4e-28, 1.7e-28, 2.05e-28, 2.37e-28,
2482 2.61e-28, 2.77e-28, 2.85e-28, 2.86e-28, 2.78e-28, 2.72e-28, 2.74e-28,
2483 2.83e-28, 3.01e-28, 3.22e-28, 3.52e-28, 3.78e-28, 4.03e-28, 4.21e-28,
2484 4.33e-28, 4.39e-28, 4.34e-28, 4.25e-28, 4.07e-28, 3.88e-28, 3.67e-28,
2485 3.56e-28, 3.52e-28, 3.67e-28, 4.02e-28, 4.64e-28, 5.63e-28, 6.89e-28,
2486 8.82e-28, 1.11e-27, 1.41e-27, 1.73e-27, 2.12e-27, 2.57e-27, 2.99e-27,
2487 3.45e-27, 3.79e-27, 4.09e-27, 4.23e-27, 4.3e-27, 4.33e-27, 4.35e-27,
2488 4.44e-27, 4.54e-27, 4.62e-27, 4.67e-27, 4.71e-27, 4.77e-27, 4.93e-27,
2489 5.19e-27, 5.54e-27, 5.9e-27, 6.12e-27, 6.15e-27, 5.81e-27, 5.21e-27,
2490 4.51e-27, 3.69e-27, 2.89e-27, 2.14e-27, 1.55e-27, 1.11e-27, 7.78e-28,
2491 5.46e-28, 3.93e-28, 2.93e-28, 2.26e-28, 1.82e-28, 1.52e-28, 1.31e-28,
2492 1.15e-28, 1.02e-28, 9.01e-29, 7.95e-29, 7.04e-29, 6.2e-29, 5.49e-29,
2493 4.86e-29, 4.34e-29, 3.88e-29, 3.46e-29, 3.07e-29, 2.71e-29, 2.38e-29,
2494 2.09e-29, 1.82e-29, 1.59e-29, 1.38e-29, 1.2e-29, 1.04e-29, 9.08e-30,
2495 7.88e-30, 6.85e-30, 5.96e-30, 5.2e-30, 4.53e-30, 3.94e-30, 3.43e-30,
2496 2.97e-30, 2.58e-30, 2.23e-30, 1.92e-30, 1.66e-30, 1.43e-30, 1.24e-30,
2497 1.06e-30, 9.1e-31, 7.79e-31, 6.65e-31, 5.68e-31, 4.84e-31, 4.11e-31,
2498 3.51e-31, 2.99e-31, 2.54e-31, 2.17e-31, 1.86e-31, 1.59e-31, 1.37e-31,
2499 1.18e-31, 1.04e-31, 9.24e-32, 8.39e-32, 7.86e-32, 7.7e-32, 7.85e-32,
2500 8.41e-32, 9.62e-32, 1.16e-31, 1.47e-31, 1.94e-31, 2.58e-31, 3.51e-31,
2501 4.73e-31, 6.26e-31, 7.98e-31, 9.95e-31, 1.21e-30, 1.4e-30, 1.58e-30,
2502 1.77e-30, 1.98e-30, 2.22e-30, 2.47e-30, 2.79e-30, 3.14e-30, 3.55e-30,
2503 4e-30, 4.51e-30, 5.15e-30, 5.73e-30, 6.25e-30, 6.65e-30, 6.91e-30,
2504 6.98e-30, 6.83e-30, 6.67e-30, 6.57e-30, 6.6e-30, 6.84e-30, 7.39e-30,
2505 8.04e-30, 8.73e-30, 9.44e-30, 9.95e-30, 1.03e-29, 1.01e-29, 9.8e-30,
2506 9.32e-30, 8.67e-30, 7.99e-30, 7.29e-30, 6.67e-30, 6.14e-30, 5.78e-30,
2507 5.65e-30, 5.65e-30, 5.88e-30, 6.43e-30, 7.5e-30, 9.16e-30, 1.16e-29,
2508 1.51e-29, 1.99e-29, 2.7e-29, 3.66e-29, 4.95e-29, 6.41e-29, 8.16e-29,
2509 1.02e-28, 1.24e-28, 1.46e-28, 1.64e-28, 1.79e-28, 1.87e-28, 1.93e-28,
2510 1.93e-28, 1.93e-28, 1.95e-28, 2.07e-28, 2.23e-28, 2.34e-28, 2.44e-28,
2511 2.55e-28, 2.67e-28, 2.76e-28, 2.81e-28, 2.9e-28, 2.94e-28, 2.91e-28,
2512 2.77e-28, 2.52e-28, 2.21e-28, 1.84e-28, 1.49e-28, 1.15e-28, 8.64e-29,
2513 6.44e-29, 4.79e-29, 3.64e-29, 2.75e-29, 2.14e-29, 1.75e-29, 1.48e-29,
2514 1.3e-29, 1.16e-29, 1.05e-29, 9.46e-30, 8.55e-30, 7.66e-30, 6.79e-30,
2515 6.01e-30, 5.3e-30, 4.67e-30, 4.13e-30, 3.67e-30, 3.29e-30, 2.92e-30,
2516 2.57e-30, 2.27e-30, 1.96e-30, 1.7e-30, 1.47e-30, 1.27e-30, 1.1e-30,
2517 9.19e-31, 7.79e-31, 6.59e-31, 5.61e-31, 4.81e-31, 4.07e-31, 3.54e-31,
2518 3.04e-31, 2.62e-31, 2.3e-31, 1.97e-31, 1.71e-31, 1.48e-31, 1.28e-31,
2519 1.1e-31, 9.44e-32, 8.08e-32, 6.94e-32, 5.93e-32, 5.06e-32, 4.31e-32,
2520 3.66e-32, 3.12e-32, 2.67e-32, 2.28e-32, 1.95e-32, 1.67e-32, 1.43e-32,
2521 1.22e-32, 1.05e-32, 9.06e-33, 7.86e-33, 6.87e-33, 6.09e-33, 5.5e-33,
2522 5.07e-33, 4.78e-33, 4.66e-33, 4.77e-33, 5.21e-33, 5.94e-33, 7.44e-33,
2523 9.71e-33, 1.35e-32, 1.87e-32, 2.63e-32, 3.67e-32, 4.95e-32, 6.39e-32,
2524 8e-32, 9.88e-32, 1.15e-31, 1.28e-31, 1.37e-31, 1.43e-31, 1.47e-31,
2525 1.45e-31, 1.42e-31, 1.4e-31, 1.41e-31, 1.43e-31, 1.51e-31, 1.65e-31,
2526 1.83e-31, 2.07e-31, 2.25e-31, 2.38e-31, 2.42e-31, 2.38e-31, 2.27e-31,
2527 2.1e-31, 1.98e-31, 1.89e-31, 1.79e-31, 1.72e-31, 1.62e-31, 1.54e-31,
2528 1.43e-31, 1.35e-31, 1.35e-31, 1.42e-31, 1.57e-31, 1.77e-31, 2.06e-31,
2529 2.42e-31, 2.85e-31, 3.43e-31, 4.16e-31, 5.24e-31, 6.82e-31, 8.92e-31,
2530 1.2e-30, 1.6e-30, 2.15e-30, 2.89e-30, 3.77e-30, 4.8e-30, 5.93e-30,
2531 7.25e-30, 8.53e-30, 9.6e-30, 1.04e-29, 1.08e-29, 1.1e-29, 1.09e-29,
2532 1.07e-29, 1.07e-29, 1.12e-29, 1.21e-29, 1.33e-29, 1.48e-29, 1.64e-29,
2533 1.79e-29, 1.94e-29, 2.05e-29, 2.17e-29, 2.28e-29, 2.4e-29, 2.53e-29,
2534 2.74e-29, 3.03e-29, 3.42e-29, 3.87e-29, 4.47e-29, 5.19e-29, 5.91e-29,
2535 6.77e-29, 7.5e-29, 8.28e-29, 8.83e-29, 9.36e-29, 9.91e-29, 1.03e-28,
2536 1.09e-28, 1.14e-28, 1.17e-28, 1.18e-28, 1.18e-28, 1.18e-28, 1.21e-28,
2537 1.26e-28, 1.35e-28, 1.43e-28, 1.49e-28, 1.49e-28, 1.4e-28, 1.25e-28,
2538 1.07e-28, 8.61e-29, 6.57e-29, 4.8e-29, 3.47e-29, 2.47e-29, 1.78e-29,
2539 1.33e-29, 1.05e-29, 8.72e-30, 7.51e-30, 6.76e-30, 6.27e-30, 6e-30,
2540 5.99e-30, 6.26e-30, 6.86e-30, 7.58e-30, 8.49e-30, 9.53e-30, 1.05e-29,
2541 1.14e-29, 1.2e-29, 1.25e-29, 1.28e-29, 1.3e-29, 1.31e-29, 1.32e-29,
2542 1.33e-29, 1.33e-29, 1.31e-29, 1.27e-29, 1.23e-29, 1.19e-29, 1.2e-29,
2543 1.25e-29, 1.33e-29, 1.42e-29, 1.48e-29, 1.49e-29, 1.41e-29, 1.26e-29,
2544 1.08e-29, 8.8e-30, 6.78e-30, 4.95e-30, 3.58e-30, 2.54e-30, 1.78e-30,
2545 1.26e-30, 9.28e-31, 7.13e-31, 5.56e-31, 4.5e-31, 3.75e-31, 3.21e-31,
2546 2.76e-31, 2.41e-31, 2.09e-31, 1.82e-31, 1.59e-31, 1.36e-31, 1.18e-31,
2547 1.03e-31, 9.01e-32, 7.94e-32, 6.9e-32, 6.02e-32, 5.26e-32, 4.62e-32,
2548 4.06e-32, 3.55e-32, 3.13e-32, 2.76e-32, 2.43e-32, 2.15e-32, 1.9e-32,
2549 1.68e-32, 1.49e-32, 1.32e-32, 1.17e-32, 1.04e-32, 9.35e-33, 8.47e-33,
2550 7.79e-33, 7.3e-33, 6.96e-33, 6.88e-33, 7.11e-33, 7.6e-33, 8.67e-33,
2551 1.04e-32, 1.31e-32, 1.71e-32, 2.2e-32, 2.93e-32, 3.8e-32, 4.97e-32,
2552 6.22e-32, 7.63e-32, 9.29e-32, 1.1e-31, 1.24e-31, 1.34e-31, 1.41e-31,
2553 1.44e-31, 1.44e-31, 1.39e-31, 1.38e-31, 1.41e-31, 1.49e-31, 1.64e-31,
2554 1.86e-31, 2.11e-31, 2.38e-31, 2.65e-31, 2.89e-31, 3.04e-31, 3.14e-31,
2555 3.29e-31, 3.43e-31, 3.6e-31, 3.91e-31, 4.44e-31, 5.21e-31, 6.43e-31,
2556 8.18e-31, 1.06e-30, 1.4e-30, 1.78e-30, 2.24e-30, 2.77e-30, 3.35e-30,
2557 3.95e-30, 4.47e-30, 4.92e-30, 5.2e-30, 5.39e-30, 5.46e-30, 5.53e-30,
2558 5.66e-30, 6.02e-30, 6.43e-30, 6.68e-30, 6.91e-30, 7.12e-30, 7.42e-30,
2559 7.55e-30, 7.75e-30, 8.09e-30, 8.3e-30, 8.35e-30, 7.95e-30, 7.22e-30,
2560 6.3e-30, 5.23e-30, 4.2e-30, 3.19e-30, 2.39e-30, 1.79e-30, 1.36e-30,
2561 1.05e-30, 8.32e-31, 6.89e-31, 5.89e-31, 5.14e-31, 4.6e-31, 4.19e-31,
2562 3.94e-31, 3.9e-31, 4.07e-31, 4.39e-31, 4.82e-31, 5.29e-31, 5.75e-31,
2563 6.09e-31, 6.28e-31, 6.31e-31, 6.19e-31, 6.04e-31, 5.85e-31, 5.71e-31,
2564 5.68e-31, 5.68e-31, 5.64e-31, 5.58e-31, 5.51e-31, 5.48e-31, 5.45e-31,
2565 5.57e-31, 5.77e-31, 5.96e-31, 6.05e-31, 5.89e-31, 5.43e-31, 4.77e-31,
2566 4.02e-31, 3.25e-31, 2.5e-31, 1.82e-31, 1.31e-31, 9.32e-32, 6.58e-32,
2567 4.64e-32, 3.35e-32, 2.53e-32, 1.96e-32, 1.58e-32, 1.31e-32, 1.11e-32,
2568 9.58e-33, 8.32e-33, 7.31e-33, 6.43e-33, 5.62e-33, 4.89e-33, 4.27e-33,
2569 3.73e-33, 3.25e-33, 2.84e-33, 2.5e-33, 2.21e-33, 1.95e-33, 1.72e-33,
2570 1.52e-33, 1.34e-33, 1.18e-33, 1.05e-33, 9.26e-34, 8.21e-34, 7.29e-34,
2571 6.48e-34, 5.77e-34, 5.15e-34, 4.62e-34, 4.17e-34, 3.79e-34, 3.49e-34,
2572 3.26e-34, 3.09e-34, 3e-34, 2.98e-34, 3.04e-34, 3.2e-34, 3.49e-34,
2573 3.96e-34, 4.68e-34, 5.78e-34, 7.42e-34, 9.8e-34, 1.32e-33, 1.79e-33,
2574 2.23e-33, 2.65e-33, 3.02e-33, 3.38e-33, 3.74e-33, 4.05e-33, 4.42e-33,
2575 4.94e-33, 5.48e-33, 6.11e-33, 6.77e-33, 7.56e-33, 8.49e-33, 9.59e-33,
2576 1.09e-32, 1.27e-32, 1.48e-32, 1.73e-32, 2.08e-32, 2.48e-32, 3.03e-32,
2577 3.88e-32, 4.86e-32, 6.25e-32, 8.05e-32, 1.04e-31, 1.37e-31, 1.75e-31,
2578 2.2e-31, 2.75e-31, 3.35e-31, 4.08e-31, 4.79e-31, 5.44e-31, 5.99e-31,
2579 6.46e-31, 6.82e-31, 7.13e-31, 7.62e-31, 8.36e-31, 9.59e-31, 1.15e-30,
2580 1.38e-30, 1.67e-30, 1.99e-30, 2.35e-30, 2.74e-30, 3.11e-30, 3.51e-30,
2581 3.89e-30, 4.21e-30, 4.49e-30, 4.66e-30, 4.86e-30, 4.96e-30, 5.08e-30,
2582 5.2e-30, 5.29e-30, 5.3e-30, 5.22e-30, 5.16e-30, 5.18e-30, 5.35e-30,
2583 5.68e-30, 6.07e-30, 6.42e-30, 6.6e-30, 6.39e-30, 5.83e-30, 5.03e-30,
2584 4.11e-30, 3.2e-30, 2.35e-30, 1.7e-30, 1.2e-30, 8.54e-31, 6.31e-31,
2585 4.92e-31, 4.01e-31, 3.38e-31, 2.97e-31, 2.71e-31, 2.55e-31, 2.45e-31,
2586 2.42e-31, 2.43e-31, 2.49e-31, 2.6e-31, 2.73e-31, 2.91e-31, 3.16e-31,
2587 3.45e-31, 3.81e-31, 4.14e-31, 4.54e-31, 5.02e-31, 5.48e-31, 6.11e-31,
2588 6.72e-31, 7.37e-31, 7.99e-31, 8.5e-31, 9.01e-31, 9.3e-31, 9.52e-31,
2589 9.64e-31, 9.59e-31, 9.39e-31, 9.14e-31, 8.95e-31, 8.97e-31, 9.3e-31,
2590 9.91e-31, 1.06e-30, 1.12e-30, 1.14e-30, 1.1e-30, 1e-30, 8.68e-31,
2591 7.14e-31, 5.61e-31, 4.17e-31, 3.05e-31, 2.18e-31, 1.55e-31, 1.11e-31,
2592 8.29e-32, 6.38e-32, 5.07e-32, 4.2e-32, 3.64e-32, 3.28e-32, 3.03e-32,
2593 2.9e-32, 2.78e-32, 2.67e-32, 2.52e-32, 2.34e-32, 2.15e-32, 1.95e-32,
2594 1.75e-32, 1.54e-32, 1.32e-32, 1.13e-32, 9.55e-33, 7.9e-33, 6.44e-33,
2595 5.18e-33, 4.14e-33, 3.32e-33, 2.67e-33, 2.18e-33, 1.83e-33, 1.56e-33,
2596 1.35e-33, 1.18e-33, 1.05e-33, 9.31e-34, 8.35e-34, 7.55e-34, 6.89e-34,
2597 6.36e-34, 5.96e-34, 5.69e-34, 5.56e-34, 5.6e-34, 5.86e-34, 6.42e-34,
2598 7.33e-34, 8.85e-34, 1.14e-33, 1.49e-33, 1.97e-33, 2.69e-33, 3.61e-33,
2599 4.79e-33, 6.04e-33, 7.51e-33, 9.2e-33, 1.09e-32, 1.26e-32, 1.39e-32,
2600 1.53e-32, 1.64e-32, 1.71e-32, 1.77e-32, 1.88e-32, 2.08e-32, 2.37e-32,
2601 2.82e-32, 3.42e-32, 4.18e-32, 5.18e-32, 6.47e-32, 7.98e-32, 9.97e-32,
2602 1.22e-31, 1.47e-31, 1.75e-31, 2.05e-31, 2.38e-31, 2.66e-31, 2.91e-31,
2603 3.09e-31, 3.21e-31, 3.29e-31, 3.31e-31, 3.37e-31, 3.49e-31, 3.69e-31,
2604 3.82e-31, 3.92e-31, 4.05e-31, 4.17e-31, 4.3e-31, 4.42e-31, 4.61e-31,
2605 4.78e-31, 4.83e-31, 4.69e-31, 4.31e-31, 3.81e-31, 3.21e-31, 2.61e-31,
2606 2.04e-31, 1.56e-31, 1.2e-31, 9.2e-32, 7.1e-32, 5.65e-32, 4.63e-32,
2607 3.86e-32, 3.27e-32, 2.83e-32, 2.48e-32, 2.22e-32, 2.03e-32, 1.91e-32,
2608 1.84e-32, 1.82e-32, 1.82e-32, 1.86e-32, 1.94e-32, 2.11e-32, 2.36e-32,
2609 2.6e-32, 2.94e-32, 3.31e-32, 3.73e-32, 4.17e-32, 4.57e-32, 4.98e-32,
2610 5.26e-32, 5.54e-32, 5.79e-32, 6.05e-32, 6.38e-32, 6.71e-32, 6.93e-32,
2611 7.03e-32, 7.05e-32, 7.05e-32, 7.16e-32, 7.37e-32, 7.79e-32, 8.3e-32,
2612 8.65e-32, 8.76e-32, 8.32e-32, 7.51e-32, 6.48e-32, 5.31e-32, 4.18e-32,
2613 3.07e-32, 2.22e-32, 1.57e-32, 1.09e-32, 7.39e-33, 5.11e-33, 3.66e-33,
2614 2.68e-33, 2e-33, 1.56e-33, 1.27e-33, 1.06e-33, 9.05e-34, 7.85e-34,
2615 6.9e-34, 6.1e-34, 5.42e-34, 4.84e-34, 4.32e-34, 3.87e-34, 3.47e-34,
2616 3.12e-34, 2.8e-34, 2.52e-34, 2.27e-34, 2.05e-34, 1.86e-34, 1.69e-34,
2617 1.55e-34, 1.43e-34, 1.33e-34, 1.25e-34, 1.2e-34, 1.16e-34, 1.15e-34,
2618 1.16e-34, 1.19e-34, 1.25e-34, 1.34e-34, 1.45e-34, 1.6e-34, 1.78e-34,
2619 2.01e-34, 2.27e-34, 2.59e-34, 2.96e-34, 3.4e-34, 3.92e-34, 4.53e-34,
2620 5.24e-34, 6.08e-34, 7.09e-34, 8.31e-34, 9.81e-34, 1.17e-33, 1.42e-33,
2621 1.78e-33, 2.25e-33, 2.79e-33, 3.5e-33, 4.4e-33, 5.53e-33, 6.92e-33,
2622 8.92e-33, 1.15e-32, 1.48e-32, 1.92e-32, 2.54e-32, 3.37e-32, 4.37e-32,
2623 5.71e-32, 7.26e-32, 8.98e-32, 1.1e-31, 1.34e-31, 1.59e-31, 1.86e-31,
2624 2.14e-31, 2.4e-31, 2.69e-31, 2.98e-31, 3.33e-31, 3.77e-31, 4.25e-31,
2625 4.75e-31, 5.11e-31, 5.37e-31, 5.56e-31, 5.61e-31, 5.67e-31, 5.68e-31,
2626 5.78e-31, 5.86e-31, 5.91e-31, 5.93e-31, 5.91e-31, 5.92e-31, 5.93e-31,
2627 5.94e-31, 5.87e-31, 5.65e-31, 5.21e-31, 4.54e-31, 3.82e-31, 3.07e-31,
2628 2.37e-31, 1.78e-31, 1.32e-31, 9.82e-32, 7.34e-32, 5.59e-32, 4.33e-32,
2629 3.42e-32, 2.74e-32, 2.23e-32, 1.86e-32, 1.56e-32, 1.35e-32, 1.17e-32,
2630 1.05e-32, 9.54e-33, 8.83e-33, 8.34e-33, 8.1e-33, 8.11e-33, 8.2e-33,
2631 8.46e-33, 8.83e-33, 9.33e-33, 9.92e-33, 1.07e-32, 1.19e-32, 1.35e-32,
2632 1.58e-32, 1.86e-32, 2.17e-32, 2.52e-32, 2.92e-32, 3.36e-32, 3.83e-32,
2633 4.3e-32, 4.83e-32, 5.37e-32, 5.81e-32, 6.23e-32, 6.48e-32, 6.77e-32,
2634 6.99e-32, 7.17e-32, 7.47e-32, 7.66e-32, 7.77e-32, 7.77e-32, 7.72e-32,
2635 7.77e-32, 7.97e-32, 8.4e-32, 8.9e-32, 9.42e-32, 9.71e-32, 9.55e-32,
2636 8.85e-32, 7.68e-32, 6.39e-32, 5.02e-32, 3.74e-32, 2.68e-32, 1.87e-32,
2637 1.33e-32, 9.48e-33, 7e-33, 5.37e-33, 4.17e-33, 3.33e-33, 2.76e-33,
2638 2.35e-33, 2.04e-33, 1.78e-33, 1.59e-33, 1.42e-33, 1.23e-33, 1.06e-33,
2639 8.95e-34, 7.45e-34, 6.06e-34, 5.02e-34, 4.22e-34, 3.61e-34, 3.13e-34,
2640 2.75e-34, 2.45e-34, 2.19e-34, 1.97e-34, 1.79e-34, 1.63e-34, 1.49e-34,
2641 1.38e-34, 1.29e-34, 1.22e-34, 1.17e-34, 1.14e-34, 1.14e-34, 1.18e-34,
2642 1.26e-34, 1.41e-34, 1.65e-34, 2.04e-34, 2.65e-34, 3.59e-34, 4.87e-34,
2643 6.41e-34, 8.47e-34, 1.07e-33, 1.32e-33, 1.66e-33, 2.07e-33, 2.62e-33,
2644 3.21e-33, 3.94e-33, 4.84e-33, 5.81e-33, 6.84e-33, 7.73e-33, 8.67e-33,
2645 9.62e-33, 1.06e-32, 1.19e-32, 1.35e-32, 1.56e-32, 1.85e-32, 2.21e-32,
2646 2.66e-32, 3.14e-32, 3.6e-32, 3.99e-32, 4.22e-32, 4.36e-32, 4.35e-32,
2647 4.25e-32, 4.1e-32, 3.99e-32, 3.95e-32, 3.87e-32, 3.83e-32, 3.82e-32,
2648 3.89e-32, 3.98e-32, 4.06e-32, 4.19e-32, 4.22e-32, 4.17e-32, 3.9e-32,
2649 3.5e-32, 3.03e-32, 2.49e-32, 1.99e-32, 1.51e-32, 1.15e-32, 8.68e-33,
2650 6.53e-33, 4.89e-33, 3.78e-33, 2.92e-33, 2.25e-33, 1.74e-33, 1.35e-33,
2651 1.07e-33, 8.54e-34, 7.02e-34, 5.95e-34, 5.13e-34, 4.48e-34, 3.89e-34,
2652 3.34e-34, 2.94e-34, 2.63e-34, 2.42e-34, 2.3e-34, 2.27e-34, 2.37e-34,
2653 2.56e-34, 2.78e-34, 3.16e-34, 3.8e-34, 4.86e-34, 6.25e-34, 8.15e-34,
2654 1.01e-33, 1.24e-33, 1.49e-33, 1.73e-33, 1.99e-33, 2.22e-33, 2.44e-33,
2655 2.61e-33, 2.72e-33, 2.85e-33, 2.94e-33, 3.1e-33, 3.29e-33, 3.5e-33,
2656 3.62e-33, 3.66e-33, 3.7e-33, 3.72e-33, 3.83e-33, 4.01e-33, 4.26e-33,
2657 4.51e-33, 4.64e-33, 4.49e-33, 4.05e-33, 3.45e-33, 2.79e-33, 2.12e-33,
2658 1.46e-33, 9.67e-34, 6.18e-34, 3.98e-34, 2.63e-34, 1.81e-34, 1.32e-34,
2659 1.03e-34, 8.42e-35, 7.22e-35, 6.39e-35, 5.78e-35, 5.33e-35, 5e-35,
2660 4.76e-35, 4.61e-35, 4.54e-35, 4.55e-35, 4.64e-35, 4.81e-35, 5.06e-35,
2661 5.41e-35, 5.87e-35, 6.44e-35, 7.15e-35, 8.02e-35, 9.1e-35, 1.05e-34,
2662 1.22e-34, 1.46e-34, 1.8e-34, 2.28e-34, 2.98e-34, 4.02e-34, 5.53e-34,
2663 7.81e-34, 1.04e-33, 1.31e-33, 1.58e-33, 1.89e-33, 2.2e-33, 2.54e-33,
2664 3.01e-33, 3.67e-33, 4.43e-33, 5.42e-33, 6.85e-33, 8.44e-33, 1.04e-32,
2665 1.31e-32, 1.61e-32, 1.95e-32, 2.38e-32, 2.88e-32, 3.42e-32, 4.03e-32,
2666 4.65e-32, 5.24e-32, 5.7e-32, 6.09e-32, 6.39e-32, 6.48e-32, 6.58e-32,
2667 6.66e-32, 6.7e-32, 6.66e-32, 6.65e-32, 6.8e-32, 7.09e-32, 7.54e-32,
2668 8.06e-32, 8.62e-32, 8.89e-32, 8.68e-32, 8.04e-32, 7e-32, 5.83e-32,
2669 4.58e-32, 3.49e-32, 2.71e-32, 2.1e-32, 1.65e-32, 1.31e-32, 1.06e-32,
2670 8.35e-33, 6.45e-33, 5.02e-33, 3.94e-33, 3.09e-33, 2.46e-33
2671 };
2672
2673 static const double tcoslf_table[2001] =
2674 { 6.413, 6.414, 6.275, 6.049, 5.789, 5.557, 5.33,
2675 5.107, 4.893, 4.685, 4.481, 4.282, 4.09, 3.905,
2676 3.72, 3.548, 3.379, 3.215, 3.056, 2.903, 2.756,
2677 2.614, 2.475, 2.344, 2.219, 2.1, 1.983, 1.873,
2678 1.768, 1.67, 1.575, 1.486, 1.45, 1.432, 1.429,
2679 1.431, 1.428, 1.458, 1.517, 1.57, 1.628, 1.689,
2680 1.753, 1.819, 1.886, 1.976, 2.032, 2.106, 2.19,
2681 2.259, 2.33, 2.397, 2.466, 2.537, 2.613, 2.675,
2682 2.746, 2.819, 2.893, 2.97, 3.058, 3.168, 3.319,
2683 3.456, 3.601, 3.752, 3.9, 4.04, 4.183, 4.327,
2684 4.47, 4.602, 4.753, 4.897, 5.039, 5.214, 5.409,
2685 5.608, 5.782, 5.917, 5.983, 5.998, 6.016, 6.016,
2686 6.037, 6.026, 6.018, 6.021, 6.006, 6.005, 5.988,
2687 5.978, 5.956, 5.947, 5.898, 5.91, 5.88, 5.842,
2688 5.819, 5.772, 5.775, 5.74, 5.712, 5.685, 5.659,
2689 5.631, 5.601, 5.574, 5.541, 5.509, 5.474, 5.437,
2690 5.399, 5.359, 5.314, 5.261, 5.205, 5.146, 5.075,
2691 4.997, 4.909, 4.818, 4.709, 4.575, 4.411, 4.245,
2692 4.075, 3.889, 3.672, 3.387, 3.173, 2.907, 2.708,
2693 2.536, 2.35, 2.273, 2.196, 2.178, 2.201, 2.238,
2694 2.309, 2.382, 2.462, 2.579, 2.679, 2.737, 2.81,
2695 2.887, 2.964, 2.98, 3.011, 3.098, 3.157, 3.211,
2696 3.274, 3.388, 3.475, 3.527, 3.618, 3.772, 3.864,
2697 3.884, 3.889, 3.894, 3.884, 3.821, 3.758, 3.703,
2698 3.657, 3.567, 3.49, 3.435, 3.377, 3.29, 3.204,
2699 3.178, 3.146, 3.103, 3.088, 3.108, 3.116, 3.07,
2700 3.046, 3.029, 3.017, 3.001, 3.007, 2.984, 2.98,
2701 2.936, 2.908, 2.896, 2.875, 2.893, 2.888, 2.948,
2702 3.028, 3.064, 3.182, 3.228, 3.26, 3.335, 3.412,
2703 3.468, 3.523, 3.616, 3.659, 3.704, 3.81, 3.833,
2704 3.966, 4.026, 4.088, 4.141, 4.2, 4.269, 4.377,
2705 4.459, 4.566, 4.638, 4.709, 4.802, 4.878, 4.974,
2706 5.047, 5.147, 5.211, 5.315, 5.391, 5.483, 5.566,
2707 5.603, 5.643, 5.767, 5.807, 5.843, 5.904, 5.924,
2708 5.983, 5.993, 6.059, 6.095, 6.13, 6.153, 6.174,
2709 6.18, 6.201, 6.202, 6.21, 6.206, 6.209, 6.187,
2710 6.172, 6.138, 6.129, 6.085, 6.066, 6.043, 6.001,
2711 5.951, 5.93, 5.869, 5.822, 5.809, 5.777, 5.739,
2712 5.7, 5.68, 5.659, 5.598, 5.558, 5.519, 5.465,
2713 5.399, 5.358, 5.294, 5.225, 5.158, 5.094, 5.023,
2714 4.94, 4.846, 4.759, 4.662, 4.557, 4.435, 4.304,
2715 4.188, 4.042, 3.954, 3.803, 3.695, 3.619, 3.51,
2716 3.414, 3.366, 3.284, 3.217, 3.152, 3.044, 2.983,
2717 2.898, 2.784, 2.68, 2.627, 2.634, 2.704, 2.637,
2718 2.756, 2.79, 2.941, 3.091, 3.203, 3.308, 3.431,
2719 3.49, 3.57, 3.652, 3.683, 3.708, 3.722, 3.687,
2720 3.631, 3.584, 3.566, 3.536, 3.459, 3.401, 3.326,
2721 3.216, 3.103, 2.944, 2.828, 2.652, 2.597, 2.559,
2722 2.522, 2.468, 2.466, 2.43, 2.412, 2.383, 2.357,
2723 2.338, 2.312, 2.287, 2.25, 2.221, 2.174, 2.174,
2724 2.135, 2.109, 2.107, 2.106, 2.062, 2.075, 2.08,
2725 2.136, 2.219, 2.291, 2.415, 2.52, 2.663, 2.797,
2726 2.936, 3.112, 3.244, 3.347, 3.437, 3.501, 3.513,
2727 3.511, 3.515, 3.553, 3.553, 3.568, 3.621, 3.713,
2728 3.836, 3.888, 3.897, 3.874, 3.825, 3.743, 3.626,
2729 3.503, 3.365, 3.225, 3.077, 2.914, 2.764, 2.623,
2730 2.508, 2.433, 2.42, 2.41, 2.445, 2.49, 2.623,
2731 2.753, 2.871, 2.981, 3.069, 3.176, 3.27, 3.339,
2732 3.394, 3.45, 3.511, 3.572, 3.623, 3.668, 3.742,
2733 3.807, 3.893, 3.961, 4.019, 4.106, 4.194, 4.286,
2734 4.364, 4.447, 4.532, 4.629, 4.719, 4.815, 4.9,
2735 4.989, 5.067, 5.16, 5.245, 5.326, 5.406, 5.479,
2736 5.558, 5.632, 5.702, 5.772, 5.831, 5.893, 5.953,
2737 6.009, 6.056, 6.103, 6.143, 6.183, 6.21, 6.239,
2738 6.258, 6.264, 6.263, 6.247, 6.229, 6.201, 6.176,
2739 6.141, 6.11, 6.096, 6.085, 6.071, 6.05, 6.053,
2740 6.042, 6.035, 6.018, 6.005, 5.99, 5.955, 5.931,
2741 5.884, 5.833, 5.782, 5.724, 5.664, 5.594, 5.542,
2742 5.484, 5.422, 5.351, 5.284, 5.222, 5.143, 5.063,
2743 4.978, 4.896, 4.81, 4.723, 4.625, 4.525, 4.431,
2744 4.334, 4.231, 4.123, 4.022, 3.918, 3.831, 3.726,
2745 3.624, 3.537, 3.454, 3.367, 3.279, 3.211, 3.137,
2746 3.056, 2.968, 2.876, 2.764, 2.638, 2.486, 2.392,
2747 2.28, 2.193, 2.08, 2.056, 2.097, 2.155, 2.239,
2748 2.327, 2.461, 2.617, 2.759, 2.925, 3.082, 3.253,
2749 3.366, 3.491, 3.58, 3.67, 3.733, 3.756, 3.735,
2750 3.663, 3.612, 3.604, 3.655, 3.671, 3.68, 3.721,
2751 3.769, 3.769, 3.71, 3.605, 3.493, 3.383, 3.231,
2752 3.109, 2.936, 2.781, 2.645, 2.514, 2.397, 2.304,
2753 2.236, 2.212, 2.195, 2.204, 2.248, 2.337, 2.464,
2754 2.575, 2.714, 2.815, 2.941, 3.072, 3.173, 3.263,
2755 3.331, 3.398, 3.471, 3.531, 3.597, 3.657, 3.737,
2756 3.8, 3.844, 3.932, 3.997, 4.062, 4.135, 4.214,
2757 4.303, 4.378, 4.46, 4.563, 4.642, 4.72, 4.808,
2758 4.885, 4.978, 5.063, 5.142, 5.234, 5.318, 5.395,
2759 5.482, 5.553, 5.624, 5.684, 5.737, 5.792, 5.84,
2760 5.886, 5.925, 5.969, 6.01, 6.043, 6.078, 6.109,
2761 6.142, 6.159, 6.184, 6.201, 6.207, 6.211, 6.207,
2762 6.204, 6.187, 6.17, 6.151, 6.126, 6.099, 6.067,
2763 6.033, 5.992, 5.956, 5.919, 5.885, 5.847, 5.813,
2764 5.787, 5.755, 5.725, 5.687, 5.651, 5.607, 5.557,
2765 5.51, 5.458, 5.406, 5.35, 5.29, 5.225, 5.163,
2766 5.094, 5.013, 4.933, 4.852, 4.756, 4.661, 4.554,
2767 4.44, 4.326, 4.198, 4.078, 3.961, 3.823, 3.714,
2768 3.606, 3.527, 3.43, 3.345, 3.28, 3.216, 3.151,
2769 3.057, 2.985, 2.902, 2.786, 2.694, 2.64, 2.634,
2770 2.655, 2.667, 2.741, 2.824, 2.955, 3.069, 3.196,
2771 3.298, 3.408, 3.501, 3.577, 3.642, 3.673, 3.712,
2772 3.712, 3.688, 3.632, 3.598, 3.567, 3.536, 3.461,
2773 3.398, 3.331, 3.211, 3.099, 2.947, 2.825, 2.651,
2774 2.467, 2.338, 2.184, 2.098, 2.061, 2.037, 2.101,
2775 2.154, 2.279, 2.397, 2.514, 2.669, 2.799, 2.946,
2776 3.099, 3.232, 3.331, 3.404, 3.471, 3.481, 3.516,
2777 3.537, 3.587, 3.613, 3.637, 3.702, 3.772, 3.874,
2778 3.898, 3.883, 3.84, 3.771, 3.692, 3.566, 3.436,
2779 3.29, 3.133, 3.002, 2.833, 2.686, 2.565, 2.498,
2780 2.489, 2.51, 2.575, 2.69, 2.836, 2.967, 3.067,
2781 3.15, 3.215, 3.275, 3.333, 3.369, 3.416, 3.478,
2782 3.526, 3.563, 3.603, 3.649, 3.678, 3.694, 3.716,
2783 3.74, 3.761, 3.8, 3.831, 3.874, 3.942, 4.005,
2784 4.099, 4.193, 4.29, 4.387, 4.497, 4.617, 4.715,
2785 4.805, 4.894, 4.991, 5.084, 5.161, 5.236, 5.3,
2786 5.368, 5.454, 5.529, 5.589, 5.654, 5.714, 5.786,
2787 5.838, 5.886, 5.947, 5.987, 6.032, 6.071, 6.099,
2788 6.122, 6.136, 6.147, 6.151, 6.144, 6.129, 6.104,
2789 6.063, 6.008, 5.936, 5.835, 5.713, 5.572, 5.404,
2790 5.225, 5.042, 4.88, 4.718, 4.576, 4.46, 4.355,
2791 4.234, 4.111, 3.975, 3.888, 3.766, 3.683, 3.633,
2792 3.637, 3.669, 3.702, 3.739, 3.804, 3.87, 3.916,
2793 3.948, 3.943, 3.971, 3.98, 3.982, 3.967, 3.95,
2794 3.947, 3.92, 3.888, 3.819, 3.756, 3.689, 3.618,
2795 3.523, 3.405, 3.303, 3.206, 3.098, 2.963, 2.816,
2796 2.667, 2.521, 2.39, 2.261, 2.135, 2.031, 1.988,
2797 1.995, 2.044, 2.105, 2.189, 2.315, 2.445, 2.592,
2798 2.745, 2.907, 3.07, 3.231, 3.34, 3.45, 3.547,
2799 3.617, 3.682, 3.683, 3.653, 3.577, 3.558, 3.572,
2800 3.597, 3.648, 3.693, 3.772, 3.801, 3.772, 3.703,
2801 3.597, 3.459, 3.335, 3.189, 3.054, 2.901, 2.756,
2802 2.629, 2.519, 2.415, 2.379, 2.391, 2.433, 2.485,
2803 2.612, 2.787, 2.913, 3.033, 3.11, 3.185, 3.21,
2804 3.254, 3.286, 3.316, 3.334, 3.376, 3.422, 3.443,
2805 3.471, 3.492, 3.496, 3.491, 3.491, 3.481, 3.46,
2806 3.475, 3.466, 3.471, 3.485, 3.482, 3.548, 3.566,
2807 3.643, 3.748, 3.8, 3.956, 4.068, 4.223, 4.357,
2808 4.506, 4.634, 4.752, 4.839, 4.89, 4.95, 5.034,
2809 5.113, 5.176, 5.228, 5.383, 5.523, 5.62, 5.705,
2810 5.775, 5.823, 5.885, 5.931, 5.96, 5.985, 6.006,
2811 6.019, 6.021, 6.015, 5.997, 5.954, 5.901, 5.817,
2812 5.716, 5.554, 5.389, 5.18, 4.951, 4.772, 4.646,
2813 4.551, 4.424, 4.389, 4.41, 4.457, 4.471, 4.473,
2814 4.545, 4.605, 4.644, 4.652, 4.669, 4.666, 4.639,
2815 4.603, 4.531, 4.493, 4.449, 4.411, 4.361, 4.304,
2816 4.269, 4.212, 4.17, 4.152, 4.133, 4.119, 4.1,
2817 4.105, 4.096, 4.042, 3.964, 3.876, 3.779, 3.652,
2818 3.513, 3.359, 3.201, 3.075, 2.935, 2.775, 2.682,
2819 2.601, 2.613, 2.64, 2.663, 2.73, 2.82, 2.936,
2820 3.052, 3.149, 3.243, 3.322, 3.394, 3.441, 3.479,
2821 3.449, 3.423, 3.388, 3.331, 3.253, 3.153, 3.109,
2822 3.05, 2.952, 2.864, 2.808, 2.708, 2.657, 2.594,
2823 2.554, 2.543, 2.549, 2.623, 2.708, 2.798, 2.909,
2824 3.039, 3.161, 3.244, 3.293, 3.358, 3.389, 3.424,
2825 3.489, 3.559, 3.601, 3.641, 3.707, 3.791, 3.879,
2826 3.902, 3.873, 3.811, 3.726, 3.637, 3.519, 3.357,
2827 3.205, 3.055, 2.898, 2.737, 2.612, 2.543, 2.531,
2828 2.589, 2.697, 2.819, 2.914, 2.991, 3.045, 3.067,
2829 3.06, 3.082, 3.087, 3.11, 3.145, 3.183, 3.249,
2830 3.296, 3.346, 3.399, 3.409, 3.449, 3.472, 3.497,
2831 3.55, 3.593, 3.638, 3.674, 3.731, 3.795, 3.863,
2832 3.874, 3.845, 3.808, 3.739, 3.661, 3.556, 3.411,
2833 3.273, 3.139, 3.009, 2.865, 2.736, 2.675, 2.674,
2834 2.73, 2.845, 2.969, 3.148, 3.3, 3.429, 3.55,
2835 3.642, 3.721, 3.797, 3.866, 3.918, 3.992, 4.054,
2836 4.117, 4.18, 4.237, 4.318, 4.4, 4.482, 4.567,
2837 4.648, 4.735, 4.813, 4.886, 4.958, 5.022, 5.083,
2838 5.137, 5.186, 5.231, 5.266, 5.295, 5.317, 5.324,
2839 5.311, 5.287, 5.248, 5.178, 5.076, 4.954, 4.793,
2840 4.605, 4.349, 4.099, 3.939, 3.72, 3.578, 3.462,
2841 3.431, 3.463, 3.48, 3.528, 3.564, 3.631, 3.705,
2842 3.747, 3.782, 3.802, 3.825, 3.821, 3.787, 3.737,
2843 3.698, 3.642, 3.563, 3.445, 3.32, 3.2, 3.072,
2844 2.931, 2.722, 2.582, 2.409, 2.311, 2.237, 2.194,
2845 2.209, 2.256, 2.352, 2.45, 2.584, 2.72, 2.87,
2846 3.018, 3.184, 3.316, 3.408, 3.506, 3.577, 3.623,
2847 3.604, 3.565, 3.555, 3.562, 3.585, 3.603, 3.681,
2848 3.774, 3.838, 3.83, 3.779, 3.711, 3.592, 3.455,
2849 3.326, 3.157, 3.007, 2.847, 2.702, 2.583, 2.503,
2850 2.479, 2.513, 2.588, 2.656, 2.78, 2.894, 2.967,
2851 3.026, 3.076, 3.122, 3.164, 3.212, 3.282, 3.335,
2852 3.405, 3.468, 3.508, 3.546, 3.57, 3.591, 3.575,
2853 3.576, 3.611, 3.619, 3.649, 3.675, 3.764, 3.854,
2854 3.88, 3.873, 3.83, 3.767, 3.673, 3.556, 3.44,
2855 3.309, 3.188, 3.07, 2.969, 2.906, 2.871, 2.904,
2856 3.003, 3.162, 3.317, 3.469, 3.647, 3.774, 3.884,
2857 3.98, 4.066, 4.143, 4.225, 4.323, 4.419, 4.515,
2858 4.603, 4.707, 4.809, 4.893, 4.984, 5.071, 5.156,
2859 5.251, 5.329, 5.407, 5.478, 5.543, 5.594, 5.641,
2860 5.684, 5.708, 5.73, 5.741, 5.745, 5.738, 5.727,
2861 5.701, 5.676, 5.633, 5.591, 5.547, 5.489, 5.431,
2862 5.368, 5.299, 5.224, 5.154, 5.069, 4.99, 4.903,
2863 4.812, 4.717, 4.615, 4.513, 4.404, 4.29, 4.162,
2864 4.023, 3.904, 3.796, 3.683, 3.552, 3.424, 3.295,
2865 3.189, 3.034, 2.878, 2.751, 2.577, 2.47, 2.358,
2866 2.215, 2.154, 2.105, 2.104, 2.117, 2.129, 2.184,
2867 2.237, 2.298, 2.374, 2.462, 2.52, 2.606, 2.6,
2868 2.596, 2.619, 2.618, 2.572, 2.536, 2.573, 2.618,
2869 2.634, 2.646, 2.714, 2.787, 2.875, 2.963, 3.065,
2870 3.179, 3.253, 3.316, 3.352, 3.393, 3.404, 3.445,
2871 3.496, 3.547, 3.597, 3.632, 3.712, 3.787, 3.846,
2872 3.85, 3.806, 3.747, 3.662, 3.573, 3.424, 3.274,
2873 3.142, 3.017, 2.87, 2.765, 2.73, 2.781, 2.864,
2874 2.937, 3.002, 3.032, 3.044, 3.027, 3.007, 2.979,
2875 2.934, 2.897, 2.887, 2.875, 2.853, 2.848, 2.859,
2876 2.903, 2.925, 2.953, 3.006, 3.061, 3.12, 3.184,
2877 3.277, 3.343, 3.374, 3.422, 3.481, 3.521, 3.588,
2878 3.641, 3.695, 3.742, 3.776, 3.85, 3.899, 3.919,
2879 3.891, 3.84, 3.761, 3.662, 3.562, 3.395, 3.261,
2880 3.131, 3.018, 2.887, 2.802, 2.796, 2.87, 2.986,
2881 3.102, 3.247, 3.332, 3.4, 3.455, 3.511, 3.567,
2882 3.624, 3.671, 3.702, 3.734, 3.782, 3.823, 3.835,
2883 3.851, 3.883, 3.919, 3.949, 3.975, 4.014, 4.061,
2884 4.13, 4.218, 4.317, 4.422, 4.559, 4.68, 4.776,
2885 4.862, 4.932, 4.991, 5.033, 5.078, 5.106, 5.117,
2886 5.119, 5.095, 5.053, 4.988, 4.896, 4.785, 4.648,
2887 4.498, 4.352, 4.161, 4.005, 3.841, 3.673, 3.543,
2888 3.398, 3.323, 3.23, 3.17, 3.118, 3.049, 3,
2889 2.932, 2.83, 2.744, 2.617, 2.49, 2.368, 2.261,
2890 2.172, 2.135, 2.165, 2.189, 2.229, 2.313, 2.407,
2891 2.503, 2.601, 2.723, 2.853, 2.968, 3.109, 3.253,
2892 3.342, 3.43, 3.521, 3.572, 3.613, 3.582, 3.603,
2893 3.622, 3.633, 3.662, 3.702, 3.806, 3.86, 3.85,
2894 3.796, 3.722, 3.618, 3.481, 3.347, 3.2, 3.082,
2895 2.952, 2.846, 2.798, 2.783, 2.848, 2.912, 2.97,
2896 3.023, 3.085, 3.107, 3.104, 3.067, 3.034, 2.996,
2897 2.941, 2.914, 2.897, 2.887, 2.903, 2.915, 2.92,
2898 2.969, 3.023, 3.104, 3.174, 3.268, 3.393, 3.481,
2899 3.557, 3.633, 3.662, 3.664, 3.665, 3.712, 3.729,
2900 3.739, 3.774, 3.844, 3.971, 4.023, 4.02, 3.983,
2901 3.913, 3.853, 3.703, 3.511, 3.351, 3.168, 3.014,
2902 2.897, 2.844, 2.918, 3.074, 3.295, 3.464, 3.614,
2903 3.74, 3.858, 3.972, 4.079, 4.188, 4.286, 4.385,
2904 4.486, 4.581, 4.678, 4.767, 4.855, 4.937, 5.008,
2905 5.079, 5.137, 5.187, 5.225, 5.255, 5.271, 5.273,
2906 5.264, 5.247, 5.216, 5.176, 5.131, 5.072, 5.007,
2907 4.941, 4.865, 4.785, 4.704, 4.617, 4.529, 4.439,
2908 4.348, 4.251, 4.153, 4.047, 3.942, 3.826, 3.697,
2909 3.562, 3.403, 3.239, 3.069, 2.915, 2.731, 2.531,
2910 2.341, 2.183, 2.069, 1.908, 1.781, 1.717, 1.691,
2911 1.629, 1.601, 1.635, 1.693, 1.756, 1.826, 1.951,
2912 2.048, 2.126, 2.238, 2.359, 2.474, 2.578, 2.696,
2913 2.803, 2.875, 2.968, 3.056, 3.12, 3.174, 3.258,
2914 3.342, 3.398, 3.466, 3.531, 3.623, 3.712, 3.772,
2915 3.806, 3.811, 3.796, 3.777, 3.757, 3.752, 3.707,
2916 3.672, 3.627, 3.572, 3.506, 3.398, 3.316, 3.227,
2917 3.12, 3.033, 3.028, 3.04, 3.092, 3.143, 3.177,
2918 3.227, 3.242, 3.265, 3.267, 3.243, 3.215, 3.21,
2919 3.215, 3.226, 3.236, 3.258, 3.289, 3.279, 3.268,
2920 3.242, 3.147, 3.11, 3.044, 2.985, 2.903, 2.832,
2921 2.808, 2.782, 2.797, 2.832, 2.903, 2.979, 3.061,
2922 3.163, 3.247, 3.331, 3.383, 3.419, 3.46, 3.496,
2923 3.518, 3.557, 3.623, 3.679, 3.725, 3.762, 3.821,
2924 3.864, 3.899, 3.892, 3.829, 3.752, 3.661, 3.565,
2925 3.44, 3.331, 3.231, 3.13, 3.018, 2.99, 3.044,
2926 3.098, 3.194, 3.294, 3.382, 3.44, 3.485, 3.522,
2927 3.55, 3.568, 3.623, 3.668, 3.715, 3.774, 3.841,
2928 3.903, 3.952, 3.981, 4.009, 4.044, 4.062, 4.099,
2929 4.142, 4.207, 4.286, 4.378, 4.483, 4.578, 4.679,
2930 4.771, 4.857, 4.934, 5.007, 5.086, 5.154, 5.224,
2931 5.295, 5.358, 5.427, 5.489, 5.55, 5.612, 5.671,
2932 5.729, 5.782, 5.836, 5.885, 5.933, 5.978, 6.023,
2933 6.065, 6.102, 6.136, 6.169, 6.197, 6.228, 6.253,
2934 6.275, 6.292, 6.309, 6.323, 6.334, 6.341, 6.349,
2935 6.356, 6.359, 6.359, 6.359, 6.359, 6.356, 6.352,
2936 6.349, 6.342, 6.335, 6.331, 6.324, 6.317, 6.309,
2937 6.306, 6.299, 6.295, 6.288, 6.284, 6.281, 6.281,
2938 6.278, 6.277, 6.278, 6.277, 6.282, 6.283, 6.289,
2939 6.297, 6.3, 6.305, 6.317, 6.325, 6.337, 6.345,
2940 6.36, 6.37, 6.384, 6.398, 6.416, 6.43, 6.448,
2941 6.465, 6.483, 6.502, 6.52, 6.541, 6.562, 6.583,
2942 6.605, 6.628, 6.649, 6.672, 6.697, 6.72, 6.743,
2943 6.768, 6.791, 6.818, 6.841, 6.867, 6.891, 6.916,
2944 6.943, 6.97, 6.996, 7.022, 7.052, 7.077, 7.103,
2945 7.132, 7.158, 7.185, 7.215, 7.241, 7.269, 7.298,
2946 7.326, 7.354, 7.382, 7.41, 7.438, 7.469, 7.497,
2947 7.528, 7.555, 7.585, 7.613, 7.643, 7.669, 7.698,
2948 7.729, 7.759, 7.787, 7.819, 7.849, 7.878, 7.909,
2949 7.936, 7.968, 7.998, 8.03, 8.055, 8.088, 8.115,
2950 8.146, 8.18, 8.205, 8.235, 8.269, 8.297, 8.328,
2951 8.36, 8.393, 8.421, 8.452, 8.484, 8.513, 8.547,
2952 8.576, 8.607, 8.64, 8.671, 8.699, 8.733, 8.762,
2953 8.794, 8.827, 8.855, 8.891, 8.922, 8.954, 8.984,
2954 9.015, 9.049, 9.08, 9.114, 9.143, 9.175, 9.209,
2955 9.241, 9.271, 9.306, 9.338, 9.369, 9.403, 9.435,
2956 9.466, 9.5, 9.532, 9.562, 9.594, 9.63, 9.661,
2957 9.695, 9.726, 9.761, 9.792, 9.825, 9.859, 9.891,
2958 9.924, 9.954, 9.987, 10.02, 10.06, 10.09, 10.12,
2959 10.16, 10.19, 10.22, 10.26, 10.29, 10.32
2960 };
2961
2962 /* Get MT_CKD 4.1 H2O continuum absorption... */
2963 const double xw = nu / 10 + 1;
2964 if (xw >= 1 && xw < 2001) {
2965 const int iw = (int) xw;
2966 const double dw = xw - iw;
2967 const double ew = 1 - dw;
2968 const double cwslf = ew * h2oslf[iw - 1] + dw * h2oslf[iw];
2969 const double cwfrn = ew * h2ofrn[iw - 1] + dw * h2ofrn[iw];
2970 const double tcoslf = ew * tcoslf_table[iw - 1]
2971 + dw * tcoslf_table[iw];
2972 const double ctwslf = cwslf * pow(296 / t, tcoslf);
2973 const double a1 = nu * u * tanh(.7193876 / t * nu);
2974 const double a2 = 296 / t;
2975 const double a3 = p / 1013 * (q * ctwslf + (1 - q) * cwfrn);
2976 return a1 * a2 * a3;
2977 } else
2978 return 0;
2979}

◆ ctmn2()

double ctmn2 ( const double  nu,
const double  p,
const double  t 
)

Compute N₂ collision-induced absorption coefficient.

Calculates the nitrogen (N₂) absorption coefficient due to collision-induced absorption (CIA) near the 4.3 µm CO₂ band using tabulated laboratory data for the absorption strength (B) and temperature exponent (β).

The function linearly interpolates B and β as a function of wavenumber, then applies a temperature- and pressure-dependent scaling relation to compute the absorption coefficient.

Parameters
[in]nuWavenumber [cm⁻¹].
[in]pPressure [hPa].
[in]tTemperature [K].
Returns
N₂ absorption coefficient [km⁻¹].
Note
The coefficients cover 2120–2605 cm^-1. The end points at 2120 and 2605 cm^-1 were added with zero absorption to taper the tabulation smoothly to zero. The implementation assumes a fixed N2 volume mixing ratio of 0.78084 and the remaining gas to have the RFM O2 foreign-broadening efficiency.
See also
locate_reg, LIN, P0, N2
Reference
Lafferty et al., Appl. Opt., 35, 5911–5917 (1996).
Author
Lars Hoffmann

Definition at line 2983 of file jurassic.c.

2986 {
2987
2988 static const double ba[98] =
2989 { 0., 4.45e-8, 5.22e-8, 6.46e-8, 7.75e-8, 9.03e-8,
2990 1.06e-7, 1.21e-7, 1.37e-7, 1.57e-7, 1.75e-7, 2.01e-7, 2.3e-7,
2991 2.59e-7, 2.95e-7, 3.26e-7, 3.66e-7, 4.05e-7, 4.47e-7, 4.92e-7,
2992 5.34e-7, 5.84e-7, 6.24e-7, 6.67e-7, 7.14e-7, 7.26e-7, 7.54e-7,
2993 7.84e-7, 8.09e-7, 8.42e-7, 8.62e-7, 8.87e-7, 9.11e-7, 9.36e-7,
2994 9.76e-7, 1.03e-6, 1.11e-6, 1.23e-6, 1.39e-6, 1.61e-6, 1.76e-6,
2995 1.94e-6, 1.97e-6, 1.87e-6, 1.75e-6, 1.56e-6, 1.42e-6, 1.35e-6,
2996 1.32e-6, 1.29e-6, 1.29e-6, 1.29e-6, 1.3e-6, 1.32e-6, 1.33e-6,
2997 1.34e-6, 1.35e-6, 1.33e-6, 1.31e-6, 1.29e-6, 1.24e-6, 1.2e-6,
2998 1.16e-6, 1.1e-6, 1.04e-6, 9.96e-7, 9.38e-7, 8.63e-7, 7.98e-7,
2999 7.26e-7, 6.55e-7, 5.94e-7, 5.35e-7, 4.74e-7, 4.24e-7, 3.77e-7,
3000 3.33e-7, 2.96e-7, 2.63e-7, 2.34e-7, 2.08e-7, 1.85e-7, 1.67e-7,
3001 1.47e-7, 1.32e-7, 1.2e-7, 1.09e-7, 9.85e-8, 9.08e-8, 8.18e-8,
3002 7.56e-8, 6.85e-8, 6.14e-8, 5.83e-8, 5.77e-8, 5e-8, 4.32e-8, 0.
3003 };
3004
3005 static const double betaa[98] =
3006 { 802., 802., 761., 722., 679., 646., 609., 562.,
3007 511., 472., 436., 406., 377., 355., 338., 319., 299., 278., 255.,
3008 233., 208., 184., 149., 107., 66., 25., -13., -49., -82., -104.,
3009 -119., -130., -139., -144., -146., -146., -147., -148., -150.,
3010 -153., -160., -169., -181., -189., -195., -200., -205., -209.,
3011 -211., -210., -210., -209., -205., -199., -190., -180., -168.,
3012 -157., -143., -126., -108., -89., -63., -32., 1., 35., 65., 95.,
3013 121., 141., 152., 161., 164., 164., 161., 155., 148., 143., 137.,
3014 133., 131., 133., 139., 150., 165., 187., 213., 248., 284., 321.,
3015 372., 449., 514., 569., 609., 642., 673., 673.
3016 };
3017
3018 static const double nua[98] =
3019 { 2120., 2125., 2130., 2135., 2140., 2145., 2150.,
3020 2155., 2160., 2165., 2170., 2175., 2180., 2185., 2190., 2195.,
3021 2200., 2205., 2210., 2215., 2220., 2225., 2230., 2235., 2240.,
3022 2245., 2250., 2255., 2260., 2265., 2270., 2275., 2280., 2285.,
3023 2290., 2295., 2300., 2305., 2310., 2315., 2320., 2325., 2330.,
3024 2335., 2340., 2345., 2350., 2355., 2360., 2365., 2370., 2375.,
3025 2380., 2385., 2390., 2395., 2400., 2405., 2410., 2415., 2420.,
3026 2425., 2430., 2435., 2440., 2445., 2450., 2455., 2460., 2465.,
3027 2470., 2475., 2480., 2485., 2490., 2495., 2500., 2505., 2510.,
3028 2515., 2520., 2525., 2530., 2535., 2540., 2545., 2550., 2555.,
3029 2560., 2565., 2570., 2575., 2580., 2585., 2590., 2595., 2600., 2605.
3030 };
3031
3032 const double t0 = 273.0, tr = 296.0;
3033
3034 /* Check wavenumber range... */
3035 if (nu < nua[0] || nu > nua[97])
3036 return 0;
3037
3038 /* Interpolate B and beta... */
3039 const int idx = locate_reg(nua, 98, nu);
3040 const double b =
3041 1e6 * LIN(nua[idx], ba[idx], nua[idx + 1], ba[idx + 1], nu);
3042 const double beta =
3043 LIN(nua[idx], betaa[idx], nua[idx + 1], betaa[idx + 1], nu);
3044
3045 /* Compute absorption coefficient... */
3046 return 0.1 * POW2(p / P0 * t0 / t) * exp(beta * (1 / tr - 1 / t))
3047 * N2 * b * (N2 + (1 - N2) * (1.294 - 0.4545 * t / tr));
3048}
Here is the call graph for this function:

◆ ctmo2()

double ctmo2 ( const double  nu,
const double  p,
const double  t 
)

Compute O₂ collision-induced absorption coefficient.

Calculates the molecular oxygen (O₂) absorption coefficient due to collision-induced absorption (CIA) using tabulated laboratory data for the absorption strength (B) and temperature exponent (β).

The function linearly interpolates B and β as a function of wavenumber and applies a pressure- and temperature-dependent scaling relation to compute the absorption coefficient.

Parameters
[in]nuWavenumber [cm⁻¹].
[in]pPressure [hPa].
[in]tTemperature [K].
Returns
O₂ absorption coefficient [km⁻¹].
Note
The coefficients cover 1360–1805 cm^-1. The end points at 1360 and 1805 cm^-1 were added with zero absorption to taper the tabulation smoothly to zero. The implementation assumes a fixed O2 volume mixing ratio of 0.20946.
See also
locate_reg, LIN, P0, O2
Reference
Thibault et al., Appl. Opt., 36, 563–567 (1997).
Author
Lars Hoffmann

Definition at line 3052 of file jurassic.c.

3055 {
3056
3057 static const double ba[90] =
3058 { 0., .061, .074, .084, .096, .12, .162, .208, .246,
3059 .285, .314, .38, .444, .5, .571, .673, .768, .853, .966, 1.097,
3060 1.214, 1.333, 1.466, 1.591, 1.693, 1.796, 1.922, 2.037, 2.154,
3061 2.264, 2.375, 2.508, 2.671, 2.847, 3.066, 3.417, 3.828, 4.204,
3062 4.453, 4.599, 4.528, 4.284, 3.955, 3.678, 3.477, 3.346, 3.29,
3063 3.251, 3.231, 3.226, 3.212, 3.192, 3.108, 3.033, 2.911, 2.798,
3064 2.646, 2.508, 2.322, 2.13, 1.928, 1.757, 1.588, 1.417, 1.253,
3065 1.109, .99, .888, .791, .678, .587, .524, .464, .403, .357, .32,
3066 .29, .267, .242, .215, .182, .16, .146, .128, .103, .087, .081,
3067 .071, .064, 0.
3068 };
3069
3070 static const double betaa[90] =
3071 { 467., 467., 400., 315., 379., 368., 475., 521.,
3072 531., 512., 442., 444., 430., 381., 335., 324., 296., 248., 215.,
3073 193., 158., 127., 101., 71., 31., -6., -26., -47., -63., -79.,
3074 -88., -88., -87., -90., -98., -99., -109., -134., -160., -167.,
3075 -164., -158., -153., -151., -156., -166., -168., -173., -170.,
3076 -161., -145., -126., -108., -84., -59., -29., 4., 41., 73., 97.,
3077 123., 159., 198., 220., 242., 256., 281., 311., 334., 319., 313.,
3078 321., 323., 310., 315., 320., 335., 361., 378., 373., 338., 319.,
3079 346., 322., 291., 290., 350., 371., 504., 504.
3080 };
3081
3082 static const double nua[90] =
3083 { 1360., 1365., 1370., 1375., 1380., 1385., 1390.,
3084 1395., 1400., 1405., 1410., 1415., 1420., 1425., 1430., 1435.,
3085 1440., 1445., 1450., 1455., 1460., 1465., 1470., 1475., 1480.,
3086 1485., 1490., 1495., 1500., 1505., 1510., 1515., 1520., 1525.,
3087 1530., 1535., 1540., 1545., 1550., 1555., 1560., 1565., 1570.,
3088 1575., 1580., 1585., 1590., 1595., 1600., 1605., 1610., 1615.,
3089 1620., 1625., 1630., 1635., 1640., 1645., 1650., 1655., 1660.,
3090 1665., 1670., 1675., 1680., 1685., 1690., 1695., 1700., 1705.,
3091 1710., 1715., 1720., 1725., 1730., 1735., 1740., 1745., 1750.,
3092 1755., 1760., 1765., 1770., 1775., 1780., 1785., 1790., 1795.,
3093 1800., 1805.
3094 };
3095
3096 const double t0 = 273, tr = 296;
3097
3098 /* Check wavenumber range... */
3099 if (nu < nua[0] || nu > nua[89])
3100 return 0;
3101
3102 /* Interpolate B and beta... */
3103 const int idx = locate_reg(nua, 90, nu);
3104 const double b = LIN(nua[idx], ba[idx], nua[idx + 1], ba[idx + 1], nu);
3105 const double beta =
3106 LIN(nua[idx], betaa[idx], nua[idx + 1], betaa[idx + 1], nu);
3107
3108 /* Compute absorption coefficient... */
3109 return 0.1 * POW2(p / P0 * t0 / t) * exp(beta * (1 / tr - 1 / t)) * O2 * b;
3110}
Here is the call graph for this function:

◆ copy_atm()

void copy_atm ( const ctl_t *  ctl,
atm_t *  atm_dest,
const atm_t *  atm_src,
const int  init 
)

Copy or initialize atmospheric profile data.

Copies all fields from one atmospheric structure (atm_src) to another (atm_dest), including geolocation, thermodynamic, gas, extinction, cloud, and surface parameters. If init is nonzero, the destination fields are instead initialized to default values (zeros for most fields, unity for surface emissivity).

Parameters
[in]ctlControl structure defining array dimensions.
[out]atm_destDestination atmospheric structure.
[in]atm_srcSource atmospheric structure.
[in]initInitialization flag:
  • 0 → copy data from atm_src
  • 1 → initialize atm_dest to default values
Note
The number of vertical levels (atm_src->np) determines the amount of data copied. The function performs shallow copies using memcpy for efficiency.
See also
atm_t, ctl_t
Author
Lars Hoffmann

Definition at line 3114 of file jurassic.c.

3118 {
3119
3120 /* Data size... */
3121 const size_t s = (size_t) atm_src->np * sizeof(double);
3122
3123 /* Copy data... */
3124 atm_dest->np = atm_src->np;
3125 memcpy(atm_dest->time, atm_src->time, s);
3126 memcpy(atm_dest->z, atm_src->z, s);
3127 memcpy(atm_dest->lon, atm_src->lon, s);
3128 memcpy(atm_dest->lat, atm_src->lat, s);
3129 memcpy(atm_dest->p, atm_src->p, s);
3130 memcpy(atm_dest->t, atm_src->t, s);
3131 for (int ig = 0; ig < ctl->ng; ig++)
3132 memcpy(atm_dest->q[ig], atm_src->q[ig], s);
3133 for (int iw = 0; iw < ctl->nw; iw++)
3134 memcpy(atm_dest->k[iw], atm_src->k[iw], s);
3135 atm_dest->clz = atm_src->clz;
3136 atm_dest->cldz = atm_src->cldz;
3137 for (int icl = 0; icl < ctl->ncl; icl++)
3138 atm_dest->clk[icl] = atm_src->clk[icl];
3139 atm_dest->sft = atm_src->sft;
3140 for (int isf = 0; isf < ctl->nsf; isf++)
3141 atm_dest->sfeps[isf] = atm_src->sfeps[isf];
3142
3143 /* Initialize... */
3144 if (init)
3145 for (int ip = 0; ip < atm_dest->np; ip++) {
3146 atm_dest->p[ip] = 0;
3147 atm_dest->t[ip] = 0;
3148 for (int ig = 0; ig < ctl->ng; ig++)
3149 atm_dest->q[ig][ip] = 0;
3150 for (int iw = 0; iw < ctl->nw; iw++)
3151 atm_dest->k[iw][ip] = 0;
3152 atm_dest->clz = 0;
3153 atm_dest->cldz = 0;
3154 for (int icl = 0; icl < ctl->ncl; icl++)
3155 atm_dest->clk[icl] = 0;
3156 atm_dest->sft = 0;
3157 for (int isf = 0; isf < ctl->nsf; isf++)
3158 atm_dest->sfeps[isf] = 1;
3159 }
3160}
double lat[NP]
Latitude [deg].
Definition: jurassic.h:1421
double lon[NP]
Longitude [deg].
Definition: jurassic.h:1418

◆ copy_obs()

void copy_obs ( const ctl_t *  ctl,
obs_t *  obs_dest,
const obs_t *  obs_src,
const int  init 
)

Copy or initialize observation geometry and radiance data.

Copies all observation fields from a source structure (obs_src) to a destination structure (obs_dest), including observer, view, and tangent point geometry, as well as radiance and transmittance data. If init is nonzero, radiance and transmittance values are reset to zero wherever finite values are found.

Parameters
[in]ctlControl structure defining the number of channels (ctl_t::nd) and other dimensions.
[out]obs_destDestination observation structure.
[in]obs_srcSource observation structure.
[in]initInitialization flag:
  • 0 → copy data from obs_src
  • 1 → initialize obs_dest (set rad and tau to zero)
Note
The number of ray paths (obs_src->nr) defines the copied data size. Shallow copies are performed via memcpy for efficiency.
See also
obs_t, ctl_t
Author
Lars Hoffmann

Definition at line 3164 of file jurassic.c.

3168 {
3169
3170 /* Data size... */
3171 const size_t s = (size_t) obs_src->nr * sizeof(double);
3172
3173 /* Copy data... */
3174 obs_dest->nr = obs_src->nr;
3175 memcpy(obs_dest->time, obs_src->time, s);
3176 memcpy(obs_dest->obsz, obs_src->obsz, s);
3177 memcpy(obs_dest->obslon, obs_src->obslon, s);
3178 memcpy(obs_dest->obslat, obs_src->obslat, s);
3179 memcpy(obs_dest->vpz, obs_src->vpz, s);
3180 memcpy(obs_dest->vplon, obs_src->vplon, s);
3181 memcpy(obs_dest->vplat, obs_src->vplat, s);
3182 memcpy(obs_dest->tpz, obs_src->tpz, s);
3183 memcpy(obs_dest->tplon, obs_src->tplon, s);
3184 memcpy(obs_dest->tplat, obs_src->tplat, s);
3185 for (int id = 0; id < ctl->nd; id++)
3186 memcpy(obs_dest->rad[id], obs_src->rad[id], s);
3187 for (int id = 0; id < ctl->nd; id++)
3188 memcpy(obs_dest->tau[id], obs_src->tau[id], s);
3189
3190 /* Initialize... */
3191 if (init)
3192 for (int id = 0; id < ctl->nd; id++)
3193 for (int ir = 0; ir < obs_dest->nr; ir++)
3194 if (isfinite(obs_dest->rad[id][ir])) {
3195 obs_dest->rad[id][ir] = 0;
3196 obs_dest->tau[id][ir] = 0;
3197 }
3198}
int nd
Number of radiance channels.
Definition: jurassic.h:1480
double tau[ND][NR]
Transmittance of ray path.
Definition: jurassic.h:1724
double rad[ND][NR]
Radiance [W/(m^2 sr cm^-1)].
Definition: jurassic.h:1727
double tplon[NR]
Tangent point longitude [deg].
Definition: jurassic.h:1718
double vpz[NR]
View point altitude [km].
Definition: jurassic.h:1706
double vplat[NR]
View point latitude [deg].
Definition: jurassic.h:1712
double obslon[NR]
Observer longitude [deg].
Definition: jurassic.h:1700
double obslat[NR]
Observer latitude [deg].
Definition: jurassic.h:1703
double obsz[NR]
Observer altitude [km].
Definition: jurassic.h:1697
double tplat[NR]
Tangent point latitude [deg].
Definition: jurassic.h:1721
double vplon[NR]
View point longitude [deg].
Definition: jurassic.h:1709
double time[NR]
Time (seconds since 2000-01-01T00:00Z).
Definition: jurassic.h:1694
double tpz[NR]
Tangent point altitude [km].
Definition: jurassic.h:1715
int nr
Number of ray paths.
Definition: jurassic.h:1691

◆ day2doy()

void day2doy ( int  year,
int  mon,
int  day,
int *  doy 
)

Convert a calendar date to day-of-year.

This function computes the day-of-year (1–365 or 1–366 for leap years) corresponding to a given Gregorian date specified by year, month, and day.

Leap years are determined using the standard Gregorian rules:

  • Every year divisible by 4 is a leap year,
  • except years divisible by 100, unless also divisible by 400.
Parameters
yearThe full year (e.g., 2025).
monThe month of the year (1–12).
dayThe day of the month (1–31).
[out]doyPointer to an integer where the resulting day-of-year will be stored (1–365 or 1–366).
Note
The caller must ensure that the input date is valid.
Author
Lars Hoffmann

Definition at line 3202 of file jurassic.c.

3206 {
3207
3208 const int d0[12] =
3209 { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
3210 const int d0l[12] =
3211 { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
3212
3213 /* Get day of year... */
3214 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
3215 *doy = d0l[mon - 1] + day - 1;
3216 else
3217 *doy = d0[mon - 1] + day - 1;
3218}

◆ doy2day()

void doy2day ( int  year,
int  doy,
int *  mon,
int *  day 
)

Convert a day-of-year value to a calendar date.

This function computes the month and day corresponding to a given day-of-year (1–365 or 1–366 for leap years) in the Gregorian calendar.

Leap years are determined using the standard Gregorian rules:

  • Every year divisible by 4 is a leap year,
  • except years divisible by 100, unless also divisible by 400.
Parameters
yearThe full year (e.g., 2025).
doyThe day-of-year (1–365 or 1–366).
[out]monPointer to an integer where the calculated month (1–12) will be stored.
[out]dayPointer to an integer where the calculated day-of-month will be stored.
Note
The caller must ensure that doy is within the valid range for the specified year.
Author
Lars Hoffmann

Definition at line 3222 of file jurassic.c.

3226 {
3227
3228 const int d0[12] =
3229 { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
3230 const int d0l[12] =
3231 { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
3232 int i;
3233
3234 /* Get month and day... */
3235 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
3236 for (i = 11; i >= 0; i--)
3237 if (d0l[i] <= doy)
3238 break;
3239 *mon = i + 1;
3240 *day = doy - d0l[i] + 1;
3241 } else {
3242 for (i = 11; i >= 0; i--)
3243 if (d0[i] <= doy)
3244 break;
3245 *mon = i + 1;
3246 *day = doy - d0[i] + 1;
3247 }
3248}

◆ find_emitter()

int find_emitter ( const ctl_t *  ctl,
const char *  emitter 
)

Find gas species index by name.

Searches the list of emitter (gas) names defined in the control structure for a case-insensitive match to the given string. Returns the corresponding gas index if found, or -1 otherwise.

Parameters
[in]ctlControl structure containing the list of gas emitters.
[in]emitterName of the gas species to search for (e.g. "H2O", "CO2").
Returns
Index of the matching emitter (0 ≤ index < ctl->ng), or -1 if no match is found.
Note
Comparison is case-insensitive using strcasecmp().
See also
ctl_t
Author
Lars Hoffmann

Definition at line 3252 of file jurassic.c.

3254 {
3255
3256 for (int ig = 0; ig < ctl->ng; ig++)
3257 if (strcasecmp(ctl->emitter[ig], emitter) == 0)
3258 return ig;
3259
3260 return -1;
3261}

◆ formod()

int formod ( const ctl_t *  ctl,
const tbl_t *  tbl,
atm_t *  atm,
obs_t *  obs,
los_t *  los_scratch,
obs_t *  obs_scratch 
)

Execute one complete forward-model calculation.

Computes synthetic radiances or brightness temperatures for the given atmospheric state and observation geometry using the selected forward-model method (CGA, EGA, or RFM). The function also applies hydrostatic adjustment, field-of-view convolution, and optional brightness-temperature conversion. Independent cases can be evaluated with formod_batch.

Parameters
[in]ctlControl structure defining model settings and options.
[in]tblEmissivity and source-function lookup tables.
[in,out]atmAtmospheric profile; may be adjusted for hydrostatic balance.
[in,out]obsObservation geometry and radiance data; populated with model output.
[out]los_scratchCaller-provided scratch line-of-sight buffer (one element; must not be shared between concurrent calls).
[out]obs_scratchCaller-provided scratch observation buffer used by the field-of-view convolution (one element; must not be shared between concurrent calls).
Returns
Forward-model status code, e.g. FORMOD_STATUS_OK.
Note
The model type is selected via ctl_t::formod:
The function preserves obs->rad elements marked as invalid (NaN) by applying an internal observation mask stored in obs->mask.
No memory is allocated inside this function.
See also
ctl_t, atm_t, obs_t, tbl_t, formod_pencil, formod_rfm, formod_fov, hydrostatic
Author
Lars Hoffmann

Definition at line 3265 of file jurassic.c.

3271 {
3272
3273 /* Save observation mask... */
3274 for (int id = 0; id < ctl->nd; id++)
3275 for (int ir = 0; ir < obs->nr; ir++)
3276 obs->mask[id][ir] = !isfinite(obs->rad[id][ir]);
3277
3278 /* Hydrostatic equilibrium... */
3279 hydrostatic(ctl, atm);
3280
3281 /* CGA or EGA forward model... */
3282 if (ctl->formod == 0 || ctl->formod == 1) {
3283 for (int ir = 0; ir < obs->nr; ir++) {
3284 const int status = formod_pencil(ctl, tbl, atm, obs, ir, los_scratch);
3285 if (status != FORMOD_STATUS_OK)
3286 return status;
3287 }
3288 }
3289
3290 /* Call RFM... */
3291 else if (ctl->formod == 2)
3292 formod_rfm(ctl, tbl, atm, obs);
3293
3294 /* Apply field-of-view convolution... */
3295 const int fov_status = formod_fov(ctl, obs, obs_scratch);
3296 if (fov_status != FORMOD_STATUS_OK)
3297 return fov_status;
3298
3299 /* Convert radiance to brightness temperature... */
3300 if (ctl->write_bbt)
3301 for (int id = 0; id < ctl->nd; id++)
3302 for (int ir = 0; ir < obs->nr; ir++)
3303 obs->rad[id][ir] = BRIGHT(obs->rad[id][ir], ctl->nu[id]);
3304
3305 /* Apply observation mask... */
3306 for (int id = 0; id < ctl->nd; id++)
3307 for (int ir = 0; ir < obs->nr; ir++)
3308 if (obs->mask[id][ir])
3309 obs->rad[id][ir] = NAN;
3310
3311 return FORMOD_STATUS_OK;
3312}
void formod_rfm(const ctl_t *ctl, const tbl_t *tbl, const atm_t *atm, obs_t *obs)
Forward-model radiance and transmittance with the Reference Forward Model (RFM).
Definition: jurassic.c:3642
int formod_pencil(const ctl_t *ctl, const tbl_t *tbl, const atm_t *atm, obs_t *obs, const int ir, los_t *los)
Compute line-of-sight radiances using the pencil-beam forward model.
Definition: jurassic.c:3458
int formod_fov(const ctl_t *ctl, obs_t *obs, obs_t *obs_scratch)
Apply field-of-view (FOV) convolution to modeled radiances.
Definition: jurassic.c:3396
void hydrostatic(const ctl_t *ctl, atm_t *atm)
Adjust pressure profile using the hydrostatic equation.
Definition: jurassic.c:3877
#define BRIGHT(rad, nu)
Compute brightness temperature from radiance.
Definition: jurassic.h:456
double nu[ND]
Centroid wavenumber of each channel [cm^-1].
Definition: jurassic.h:1483
int formod
Forward model (0=CGA, 1=EGA, 2=RFM).
Definition: jurassic.h:1606
int write_bbt
Use brightness temperature instead of radiance (0=no, 1=yes).
Definition: jurassic.h:1600
int mask[ND][NR]
Internal observation mask used by the forward model.
Definition: jurassic.h:1730
Here is the call graph for this function:

◆ formod_batch()

void formod_batch ( const ctl_t *  ctl,
const tbl_t *  tbl,
atm_t *  atm,
obs_t *  obs,
const int  nbatch,
int *  status,
los_t *  los_scratch,
obs_t *  obs_scratch 
)

Execute the forward model for a batch of independent cases.

Runs one complete formod calculation for each independent pair of atmospheric and observation states. Cases are evaluated in parallel with OpenMP where applicable (serially for the RFM model).

Parameters
[in]ctlControl structure.
[in]tblLookup tables.
[in,out]atmArray of nbatch atmospheres.
[in,out]obsArray of nbatch observation sets.
[in]nbatchNumber of batch elements.
[out]statusOptional array of nbatch status codes; if NULL, any failure aborts with an error message.
[out]los_scratchArray of nbatch scratch line-of-sight buffers.
[out]obs_scratchArray of nbatch scratch observation buffers.
Author
Lars Hoffmann

Definition at line 3316 of file jurassic.c.

3324 {
3325
3326 if (nbatch <= 0)
3327 return;
3328
3329 if (los_scratch == NULL || obs_scratch == NULL)
3330 ERRMSG("formod_batch requires scratch arrays for los and obs_scratch!");
3331
3332 /* The RFM interface uses fixed temporary filenames and is therefore
3333 not thread-safe... */
3334 if (ctl->formod == 2) {
3335 for (int ib = 0; ib < nbatch; ib++) {
3336 const int ib_status = formod(ctl, tbl, &atm[ib], &obs[ib],
3337 &los_scratch[ib], &obs_scratch[ib]);
3338 if (status)
3339 status[ib] = ib_status;
3340 else if (ib_status != FORMOD_STATUS_OK)
3341 ERRMSG("Forward model failed with status code %d!", ib_status);
3342 }
3343 return;
3344 }
3345
3346 /* Run independent cases in parallel... */
3347#pragma omp parallel for schedule(static) default(none) shared(ctl,tbl,atm,obs,nbatch,status,los_scratch,obs_scratch)
3348 for (int ib = 0; ib < nbatch; ib++) {
3349 const int ib_status = formod(ctl, tbl, &atm[ib], &obs[ib],
3350 &los_scratch[ib], &obs_scratch[ib]);
3351 if (status)
3352 status[ib] = ib_status;
3353 else if (ib_status != FORMOD_STATUS_OK)
3354 ERRMSG("Forward model failed with status code %d!", ib_status);
3355 }
3356}
int formod(const ctl_t *ctl, const tbl_t *tbl, atm_t *atm, obs_t *obs, los_t *los_scratch, obs_t *obs_scratch)
Execute one complete forward-model calculation.
Definition: jurassic.c:3265
Here is the call graph for this function:

◆ formod_continua()

void formod_continua ( const ctl_t *  ctl,
const los_t *  los,
const int  ip,
double *  beta 
)

Compute total extinction including gaseous continua.

Calculates the total extinction coefficient for a given line-of-sight point by summing spectrally dependent extinction and optional gaseous continuum contributions (CO₂, H₂O, N₂, O₂).

The function updates the extinction array beta for each spectral channel based on line-by-line extinction and enabled continua flags specified in ctl.

Parameters
[in]ctlControl structure defining model setup and continuum options.
[in]losLine-of-sight data containing pressure, temperature, gas concentrations, and extinction coefficients.
[in]ipIndex of the line-of-sight point to process.
[out]betaArray of total extinction coefficients [km⁻¹] per channel.
Note
Each continuum component is added only if its corresponding control flag (e.g., ctl_t::ctm_co2, ctl_t::ctm_h2o) is enabled and the gas index is valid.
See also
ctl_t, los_t, ctmco2, ctmh2o, ctmn2, ctmo2
Author
Lars Hoffmann

Definition at line 3360 of file jurassic.c.

3364 {
3365
3366 /* Extinction... */
3367 for (int id = 0; id < ctl->nd; id++)
3368 beta[id] = los->k[ip][id];
3369
3370 /* CO2 continuum... */
3371 if (ctl->ctm_co2 && ctl->ig_co2 >= 0)
3372 for (int id = 0; id < ctl->nd; id++)
3373 beta[id] += ctmco2(ctl->nu[id], los->p[ip], los->t[ip],
3374 los->u[ip][ctl->ig_co2]) / los->ds[ip];
3375
3376 /* H2O continuum... */
3377 if (ctl->ctm_h2o && ctl->ig_h2o >= 0)
3378 for (int id = 0; id < ctl->nd; id++)
3379 beta[id] += ctmh2o(ctl->nu[id], los->p[ip], los->t[ip],
3380 los->q[ip][ctl->ig_h2o], los->u[ip][ctl->ig_h2o])
3381 / los->ds[ip];
3382
3383 /* N2 continuum... */
3384 if (ctl->ctm_n2)
3385 for (int id = 0; id < ctl->nd; id++)
3386 beta[id] += ctmn2(ctl->nu[id], los->p[ip], los->t[ip]);
3387
3388 /* O2 continuum... */
3389 if (ctl->ctm_o2)
3390 for (int id = 0; id < ctl->nd; id++)
3391 beta[id] += ctmo2(ctl->nu[id], los->p[ip], los->t[ip]);
3392}
double ctmo2(const double nu, const double p, const double t)
Compute O₂ collision-induced absorption coefficient.
Definition: jurassic.c:3052
double ctmh2o(const double nu, const double p, const double t, const double q, const double u)
Compute the MT_CKD 4.1 water vapor continuum (optical depth).
Definition: jurassic.c:2087
double ctmco2(const double nu, const double p, const double t, const double u)
Compute carbon dioxide continuum optical depth.
Definition: jurassic.c:1224
double ctmn2(const double nu, const double p, const double t)
Compute N₂ collision-induced absorption coefficient.
Definition: jurassic.c:2983
int ctm_co2
Compute CO2 continuum (0=no, 1=yes).
Definition: jurassic.h:1528
int ctm_n2
Compute N2 continuum (0=no, 1=yes).
Definition: jurassic.h:1534
int ctm_h2o
Compute H2O continuum (0=no, 1=yes).
Definition: jurassic.h:1531
int ctm_o2
Compute O2 continuum (0=no, 1=yes).
Definition: jurassic.h:1537
int ig_h2o
Emitter index of H2O.
Definition: jurassic.h:1471
double q[NLOS][NG]
Volume mixing ratio [ppv].
Definition: jurassic.h:1647
double ds[NLOS]
Segment length [km].
Definition: jurassic.h:1659
double u[NLOS][NG]
Column density [molecules/cm^2].
Definition: jurassic.h:1662
double k[NLOS][ND]
Extinction [km^-1].
Definition: jurassic.h:1650
double t[NLOS]
Temperature [K].
Definition: jurassic.h:1644
double p[NLOS]
Pressure [hPa].
Definition: jurassic.h:1641
Here is the call graph for this function:

◆ formod_fov()

int formod_fov ( const ctl_t *  ctl,
obs_t *  obs,
obs_t *  obs_scratch 
)

Apply field-of-view (FOV) convolution to modeled radiances.

Convolves pencil-beam radiances and transmittances along each ray path with the instrument field-of-view weighting function defined in the control structure. This simulates finite FOV effects on measured radiances and transmittances.

Parameters
[in]ctlControl structure containing FOV parameters (offsets ctl_t::fov_dz and weights ctl_t::fov_w).
[in,out]obsObservation structure; input pencil-beam data are replaced with FOV-convolved radiances and transmittances.
[out]obs_scratchScratch observation buffer (overwritten).
Returns
FORMOD_STATUS_OK, or FORMOD_STATUS_FOV_DATA_MISSING if fewer than two altitude samples exist for a time step.
Note
The convolution is skipped if ctl_t::fov starts with '-' (indicating no FOV correction). Requires at least two valid altitude samples per time step.
Author
Lars Hoffmann

Definition at line 3396 of file jurassic.c.

3399 {
3400
3401 int rays[2 * NFOV + 1];
3402 double z[2 * NFOV + 1];
3403
3404 /* Do not take into account FOV... */
3405 if (ctl->fov[0] == '-')
3406 return FORMOD_STATUS_OK;
3407
3408 /* Copy observation data... */
3409 copy_obs(ctl, obs_scratch, obs, 0);
3410
3411 /* Loop over ray paths... */
3412 for (int ir = 0; ir < obs->nr; ir++) {
3413
3414 /* Collect neighbouring ray paths for the same time step... */
3415 int nz = 0;
3416 for (int ir2 = MAX(ir - NFOV, 0);
3417 ir2 < MIN(ir + 1 + NFOV, obs->nr); ir2++)
3418 if (obs->time[ir2] == obs->time[ir]) {
3419 rays[nz] = ir2;
3420 z[nz] = obs_scratch->vpz[ir2];
3421 nz++;
3422 }
3423 if (nz < 2)
3425
3426 /* Convolute profiles with FOV... */
3427 double wsum = 0;
3428 for (int id = 0; id < ctl->nd; id++) {
3429 obs->rad[id][ir] = 0;
3430 obs->tau[id][ir] = 0;
3431 }
3432 for (int i = 0; i < ctl->fov_n; i++) {
3433 const double zfov = obs->vpz[ir] + ctl->fov_dz[i];
3434 const int idx = locate_irr(z, nz, zfov);
3435 const int ir0 = rays[idx];
3436 const int ir1 = rays[idx + 1];
3437 for (int id = 0; id < ctl->nd; id++) {
3438 obs->rad[id][ir] += ctl->fov_w[i]
3439 * LIN(z[idx], obs_scratch->rad[id][ir0],
3440 z[idx + 1], obs_scratch->rad[id][ir1], zfov);
3441 obs->tau[id][ir] += ctl->fov_w[i]
3442 * LIN(z[idx], obs_scratch->tau[id][ir0],
3443 z[idx + 1], obs_scratch->tau[id][ir1], zfov);
3444 }
3445 wsum += ctl->fov_w[i];
3446 }
3447 for (int id = 0; id < ctl->nd; id++) {
3448 obs->rad[id][ir] /= wsum;
3449 obs->tau[id][ir] /= wsum;
3450 }
3451 }
3452
3453 return FORMOD_STATUS_OK;
3454}
int locate_irr(const double *xx, const int n, const double x)
Locate index for interpolation on an irregular grid.
Definition: jurassic.c:4489
void copy_obs(const ctl_t *ctl, obs_t *obs_dest, const obs_t *obs_src, const int init)
Copy or initialize observation geometry and radiance data.
Definition: jurassic.c:3164
#define NFOV
Number of ray paths used for FOV calculations.
Definition: jurassic.h:301
#define MIN(a, b)
Determine the minimum of two values.
Definition: jurassic.h:692
#define MAX(a, b)
Determine the maximum of two values.
Definition: jurassic.h:674
char fov[LEN]
Field-of-view data file.
Definition: jurassic.h:1549
int fov_n
Field-of-view number of data points.
Definition: jurassic.h:1558
double fov_dz[NSHAPE]
Field-of-view vertical distance [km].
Definition: jurassic.h:1552
double fov_w[NSHAPE]
Field-of-view weighting factor.
Definition: jurassic.h:1555
Here is the call graph for this function:

◆ formod_pencil()

int formod_pencil ( const ctl_t *  ctl,
const tbl_t *  tbl,
const atm_t *  atm,
obs_t *  obs,
const int  ir,
los_t *  los 
)

Compute line-of-sight radiances using the pencil-beam forward model.

Simulates monochromatic radiances and transmittances along a single line of sight using a layer-by-layer pencil-beam approximation. The model includes gaseous absorption, continuum extinction, surface emission, reflection, and optional solar illumination.

Parameters
[in]ctlControl structure defining model configuration, gas setup, surface type, and spectral parameters.
[in]tblEmissivity and source-function lookup tables.
[in]atmAtmospheric state containing pressure, temperature, and gas profiles.
[in,out]obsObservation data; updated with modeled radiances and transmittances for the specified ray path.
[in]irIndex of the current ray path in obs.
[out]losScratch line-of-sight buffer (zeroed and overwritten).
Returns
FORMOD_STATUS_OK, or the error status returned by raytrace.
Note
Depending on ctl_t::formod, this function calls either intpol_tbl_cga() (CGA) or intpol_tbl_ega() (EGA) for gas absorption interpolation.
Surface effects include emission, reflection, and—if enabled— solar illumination based on the solar zenith angle.
See also
ctl_t, atm_t, obs_t, tbl_t, los_t, raytrace, formod_continua, formod_srcfunc, intpol_tbl_cga, intpol_tbl_ega, PLANCK
Author
Lars Hoffmann

Definition at line 3458 of file jurassic.c.

3464 {
3465
3466 double rad[ND], tau[ND], tau_path[ND][NG];
3467
3468 /* Reset scratch LOS data (raytrace relies on zero-initialized fields)... */
3469 memset(los, 0, sizeof(*los));
3470
3471 /* Initialize... */
3472 for (int id = 0; id < ctl->nd; id++) {
3473 rad[id] = 0;
3474 tau[id] = 1;
3475 for (int ig = 0; ig < ctl->ng; ig++)
3476 tau_path[id][ig] = 1;
3477 }
3478
3479 /* Raytracing... */
3480 {
3481 const int status = raytrace(ctl, atm, obs, los, ir);
3482 if (status != FORMOD_STATUS_OK)
3483 return status;
3484 }
3485
3486 /* Loop over LOS points... */
3487 for (int ip = 0; ip < los->np; ip++) {
3488
3489 /* Get trace gas transmittance... */
3490 double tau_gas[ND];
3491 if (ctl->formod == 0)
3492 intpol_tbl_cga(ctl, tbl, los, ip, tau_path, tau_gas);
3493 else
3494 intpol_tbl_ega(ctl, tbl, los, ip, tau_path, tau_gas);
3495
3496 /* Get continuum absorption... */
3497 double beta_ctm[ND];
3498 formod_continua(ctl, los, ip, beta_ctm);
3499
3500 /* Compute Planck function... */
3501 formod_srcfunc(ctl, tbl, los->t[ip], los->src[ip]);
3502
3503 /* Loop over channels... */
3504 for (int id = 0; id < ctl->nd; id++)
3505 if (tau_gas[id] >= 0) {
3506
3507 /* Get segment emissivity. An exactly zero transmittance represents
3508 a fully opaque segment and must contribute with emissivity one. */
3509 los->eps[ip][id] = 1 - tau_gas[id] * exp(-beta_ctm[id] * los->ds[ip]);
3510
3511 /* Compute radiance... */
3512 rad[id] += los->src[ip][id] * los->eps[ip][id] * tau[id];
3513
3514 /* Compute path transmittance... */
3515 tau[id] *= (1 - los->eps[ip][id]);
3516 }
3517 }
3518
3519 /* Check whether LOS hit the ground... */
3520 if (ctl->sftype >= 1 && los->sft > 0) {
3521
3522 /* Add surface emissions... */
3523 double src_sf[ND];
3524 formod_srcfunc(ctl, tbl, los->sft, src_sf);
3525 for (int id = 0; id < ctl->nd; id++)
3526 rad[id] += los->sfeps[id] * src_sf[id] * tau[id];
3527
3528 /* Check reflectivity... */
3529 int refl = 0;
3530 if (ctl->sftype >= 2)
3531 for (int id = 0; id < ctl->nd; id++)
3532 if (los->sfeps[id] < 1) {
3533 refl = 1;
3534 break;
3535 }
3536
3537 /* Calculate reflection... */
3538 if (refl) {
3539
3540 /* Initialize... */
3541 double tau_refl[ND];
3542 for (int id = 0; id < ctl->nd; id++)
3543 tau_refl[id] = 1;
3544
3545 /* Add down-welling radiance... */
3546 for (int ip = los->np - 1; ip >= 0; ip--)
3547 for (int id = 0; id < ctl->nd; id++) {
3548 rad[id] += los->src[ip][id] * los->eps[ip][id] * tau_refl[id]
3549 * tau[id] * (1 - los->sfeps[id]);
3550 tau_refl[id] *= (1 - los->eps[ip][id]);
3551 }
3552
3553 /* Add solar term... */
3554 if (ctl->sftype >= 3) {
3555
3556 /* Get cosine of solar zenith angle... */
3557 double cos_sza_val;
3558 if (ctl->sfsza < 0)
3559 cos_sza_val = cos_sza(obs->time[ir],
3560 los->lon[los->np - 1], los->lat[los->np - 1]);
3561 else
3562 cos_sza_val = cos(DEG2RAD(ctl->sfsza));
3563
3564 /* Check validity (avoid division by zero)... */
3565 if (cos_sza_val > 1e-6) {
3566
3567 /* Compute incidence direction cosine... */
3568 double x0[3], x1[3];
3569 geo2cart(los->z[los->np - 1], los->lon[los->np - 1],
3570 los->lat[los->np - 1], x0);
3571 geo2cart(los->z[0], los->lon[0], los->lat[0], x1);
3572 for (int i = 0; i < 3; i++)
3573 x1[i] -= x0[i];
3574 const double cosa = DOTP(x0, x1) / NORM(x0) / NORM(x1);
3575
3576 /* Ratio of incident direction to solar zenith direction... */
3577 const double rcos = cosa / cos_sza_val;
3578
3579 /* Add solar radiance contribution... */
3580 for (int id = 0; id < ctl->nd; id++)
3581 rad[id] += 6.764e-5 / (2. * M_PI) * PLANCK(TSUN, ctl->nu[id])
3582 * tau_refl[id] * (1 - los->sfeps[id]) * tau[id] * rcos;
3583 }
3584 }
3585 }
3586 }
3587
3588 /* Copy results... */
3589 for (int id = 0; id < ctl->nd; id++) {
3590 obs->rad[id][ir] = rad[id];
3591 obs->tau[id][ir] = tau[id];
3592 }
3593
3594 return FORMOD_STATUS_OK;
3595}
double cos_sza(const double sec, const double lon, const double lat)
Calculates the cosine of the solar zenith angle.
Definition: jurassic.c:1152
int raytrace(const ctl_t *ctl, const atm_t *atm, obs_t *obs, los_t *los, const int ir)
Perform line-of-sight (LOS) ray tracing through the atmosphere.
Definition: jurassic.c:4986
void intpol_tbl_ega(const ctl_t *ctl, const tbl_t *tbl, const los_t *los, const int ip, double tau_path[ND][NG], double tau_seg[ND])
Interpolate emissivities and transmittances using the Emissivity Growth Approximation (EGA).
Definition: jurassic.c:4141
void formod_continua(const ctl_t *ctl, const los_t *los, const int ip, double *beta)
Compute total extinction including gaseous continua.
Definition: jurassic.c:3360
void intpol_tbl_cga(const ctl_t *ctl, const tbl_t *tbl, const los_t *los, const int ip, double tau_path[ND][NG], double tau_seg[ND])
Interpolate emissivities and transmittances using the Curtis–Godson approximation (CGA).
Definition: jurassic.c:4048
void formod_srcfunc(const ctl_t *ctl, const tbl_t *tbl, const double t, double *src)
Interpolate the source function (Planck radiance) at a given temperature.
Definition: jurassic.c:3842
void geo2cart(const double z, const double lon, const double lat, double *x)
Converts geographic coordinates (longitude, latitude, altitude) to Cartesian coordinates.
Definition: jurassic.c:3859
#define DOTP(a, b)
Compute dot product of two 3D vectors.
Definition: jurassic.h:566
#define ND
Maximum number of radiance channels.
Definition: jurassic.h:296
#define TSUN
Effective temperature of the sun [K].
Definition: jurassic.h:257
#define PLANCK(T, nu)
Compute spectral radiance using Planck’s law.
Definition: jurassic.h:1035
double sfsza
Solar zenith angle at the surface [deg] (-999=auto).
Definition: jurassic.h:1507
int sftype
Surface treatment (0=none, 1=emissions, 2=downward, 3=solar).
Definition: jurassic.h:1504
double z[NLOS]
Altitude [km].
Definition: jurassic.h:1632
double eps[NLOS][ND]
Segment emissivity.
Definition: jurassic.h:1674
double sft
Surface temperature [K].
Definition: jurassic.h:1653
double lon[NLOS]
Longitude [deg].
Definition: jurassic.h:1635
int np
Number of LOS points.
Definition: jurassic.h:1629
double lat[NLOS]
Latitude [deg].
Definition: jurassic.h:1638
double src[NLOS][ND]
Segment source function [W/(m^2 sr cm^-1)].
Definition: jurassic.h:1677
double sfeps[ND]
Surface emissivity.
Definition: jurassic.h:1656
Here is the call graph for this function:

◆ formod_rfm()

void formod_rfm ( const ctl_t *  ctl,
const tbl_t *  tbl,
const atm_t *  atm,
obs_t *  obs 
)

Forward-model radiance and transmittance with the Reference Forward Model (RFM).

This routine provides the JURASSIC interface to the external RFM executable. It writes an RFM atmospheric profile file and a per-channel RFM driver file, runs RFM, and reads back the resulting radiance and transmittance spectra. The spectra are then convolved with the instrument channel filter functions and stored in the observation structure.

Filter functions are taken exclusively from the lookup-table container tbl (i.e., tbl->filt_n, tbl->filt_nu, tbl->filt_f). This makes the behavior independent of the lookup-table format (ASCII, binary, or netCDF) and avoids reliance on external per-channel ASCII filter files.

Viewing geometry is classified as one of:

  • limb: uses tangent altitude
  • nadir: path intersects the surface (secant/air-mass-factor geometry)
  • zenith: upward-looking path exits the atmosphere at the top boundary

Mixed geometries (e.g., limb and nadir simultaneously) are not allowed and will trigger an error.

Limitations:

  • Requires identical observer positions for all rays.
  • Does not support extinction input data (atm->k must be zero everywhere).
  • Uses temporary files in the current working directory (e.g., rfm.atm, rfm.drv, rad_*.asc, tra_*.asc) and removes them on completion.
Parameters
[in]ctlControl and configuration parameters (RFM binary path, HITRAN/XSC settings, channel definitions, flags such as refraction and continua).
[in]tblLookup-table container providing per-channel filter functions.
[in]atmAtmospheric state (altitude grid, temperature, and gas profiles).
[out]obsObservation geometry and output arrays; on return, obs->rad[id][ir] and obs->tau[id][ir] are filled for all channels and rays.
Precondition
tbl contains valid filter functions for all channels used (tbl->filt_n[id] > 0).
All rays share identical observer position (obsz/obslon/obslat).
No extinction data is present (atm->k == 0 for all wavelengths/levels).
Postcondition
obs->rad and obs->tau are updated with channel-integrated radiance and transmittance computed by RFM.
Note
The surface temperature is taken as the temperature at the lowest altitude level of the atmospheric grid.
Warning
This function executes external commands via system(), and creates/removes files in the current working directory.
Reference
Dudhia, A., "The Reference Forward Model (RFM)", JQSRT 186, 243–253 (2017)
Author
Lars Hoffmann

Definition at line 3642 of file jurassic.c.

3646 {
3647
3648 los_t *los;
3649
3650 char cmd[2 * LEN], filename[LEN], rfmflg[LEN] = { "RAD TRA MIX LIN SFC" };
3651
3652 double lower[ND], upper[ND], nu0, nu1, obsz = -999, *nurfm, *spec, tsurf,
3653 xd[3], xo[3], xv[3], z[NR], zmin, zmax;
3654
3655 int nadir = 0, npts, order[ND], zenith = 0;
3656
3657 /* Allocate... */
3658 ALLOC(los, los_t, 1);
3659 ALLOC(nurfm, double, RFMNPTS);
3660 ALLOC(spec, double, RFMNPTS);
3661
3662 /* Check observer positions... */
3663 for (int ir = 1; ir < obs->nr; ir++)
3664 if (obs->obsz[ir] != obs->obsz[0]
3665 || obs->obslon[ir] != obs->obslon[0]
3666 || obs->obslat[ir] != obs->obslat[0])
3667 ERRMSG("RFM interface requires identical observer positions!");
3668
3669 /* Check extinction data... */
3670 for (int iw = 0; iw < ctl->nw; iw++)
3671 for (int ip = 0; ip < atm->np; ip++)
3672 if (atm->k[iw][ip] != 0)
3673 ERRMSG("RFM interface cannot handle extinction data!");
3674
3675 /* Get altitude range of atmospheric data... */
3676 gsl_stats_minmax(&zmin, &zmax, atm->z, 1, (size_t) atm->np);
3677
3678 /* Observer within atmosphere? */
3679 if (obs->obsz[0] >= zmin && obs->obsz[0] <= zmax) {
3680 obsz = obs->obsz[0];
3681 strcat(rfmflg, " OBS");
3682 }
3683
3684 /* Determine tangent altitude or air mass factor... */
3685 for (int ir = 0; ir < obs->nr; ir++) {
3686
3687 /* Raytracing... */
3688 if (raytrace(ctl, atm, obs, los, ir) != FORMOD_STATUS_OK)
3689 ERRMSG("Ray tracing failed!");
3690
3691 /* Nadir or zenith? (air mass factor / secant of zenith angle) */
3692 if (obs->tpz[ir] <= zmin) {
3693
3694 /* Nadir: path intersects the surface. */
3695 geo2cart(obs->obsz[ir], obs->obslon[ir], obs->obslat[ir], xo);
3696 geo2cart(obs->vpz[ir], obs->vplon[ir], obs->vplat[ir], xv);
3697 for (int i = 0; i < 3; i++)
3698 xd[i] = xo[i] - xv[i];
3699 z[ir] = NORM(xo) * NORM(xd) / DOTP(xo, xd);
3700 nadir++;
3701
3702 } else if (obs->tpz[ir] >= zmax - 1e-3 && obs->vpz[ir] > obs->obsz[ir]) {
3703
3704 /* Zenith: upward-looking path leaves the atmosphere at the top boundary. */
3705 geo2cart(obs->obsz[ir], obs->obslon[ir], obs->obslat[ir], xo);
3706 geo2cart(obs->vpz[ir], obs->vplon[ir], obs->vplat[ir], xv);
3707 for (int i = 0; i < 3; i++)
3708 xd[i] = xv[i] - xo[i];
3709 z[ir] = NORM(xo) * NORM(xd) / DOTP(xo, xd);
3710 zenith++;
3711
3712 } else
3713 /* Limb: use tangent altitude. */
3714 z[ir] = obs->tpz[ir];
3715 }
3716 if ((nadir > 0 && nadir < obs->nr)
3717 || (zenith > 0 && zenith < obs->nr)
3718 || (nadir > 0 && zenith > 0))
3719 ERRMSG("Limb, nadir, and zenith not simultaneously possible!");
3720
3721 /* Viewing geometry... */
3722 if (nadir)
3723 strcat(rfmflg, " NAD");
3724 if (zenith)
3725 strcat(rfmflg, " ZEN");
3726
3727 /* Get surface temperature... */
3728 tsurf = atm->t[gsl_stats_min_index(atm->z, 1, (size_t) atm->np)];
3729
3730 /* Refraction? */
3731 if (!nadir && !zenith && !ctl->refrac)
3732 strcat(rfmflg, " GEO");
3733
3734 /* Continua? */
3735 if (ctl->ctm_co2 || ctl->ctm_h2o || ctl->ctm_n2 || ctl->ctm_o2)
3736 strcat(rfmflg, " CTM");
3737
3738 /* Write atmospheric data file... */
3739 write_atm_rfm("rfm.atm", ctl, atm);
3740
3741 /* Check filter functions and initialize channel order... */
3742 for (int id = 0; id < ctl->nd; id++) {
3743 const int n = tbl->filt_n[id];
3744 if (n < 2 || n > NSHAPE)
3745 ERRMSG("Missing or invalid filter function in lookup table!");
3746 for (int i = 1; i < n; i++)
3747 if (tbl->filt_nu[id][i] <= tbl->filt_nu[id][i - 1])
3748 ERRMSG("Filter wavenumbers must be strictly increasing!");
3749 lower[id] = tbl->filt_nu[id][0];
3750 upper[id] = tbl->filt_nu[id][n - 1];
3751 order[id] = id;
3752 }
3753
3754 /* Sort channels by lower filter bound... */
3755 for (int i = 1; i < ctl->nd; i++) {
3756 const int id = order[i];
3757 int j = i;
3758 while (j > 0 && lower[order[j - 1]] > lower[id]) {
3759 order[j] = order[j - 1];
3760 j--;
3761 }
3762 order[j] = id;
3763 }
3764
3765 /* Loop over overlapping spectral blocks... */
3766 for (int ib = 0; ib < ctl->nd;) {
3767 int ie = ib + 1;
3768 nu0 = lower[order[ib]];
3769 nu1 = upper[order[ib]];
3770 while (ie < ctl->nd && lower[order[ie]] <= nu1) {
3771 nu1 = MAX(nu1, upper[order[ie]]);
3772 ie++;
3773 }
3774
3775 /* Create RFM driver file... */
3776 FILE *out;
3777 if (!(out = fopen("rfm.drv", "w")))
3778 ERRMSG("Cannot create file!");
3779 fprintf(out, "*HDR\nRFM call by JURASSIC.\n");
3780 fprintf(out, "*FLG\n%s\n", rfmflg);
3781 fprintf(out, "*SPC\n%.4f %.4f 0.0005\n", nu0, nu1);
3782 fprintf(out, "*GAS\n");
3783 for (int ig = 0; ig < ctl->ng; ig++)
3784 fprintf(out, "%s\n", ctl->emitter[ig]);
3785 fprintf(out, "*ATM\nrfm.atm\n");
3786 fprintf(out, "*TAN\n");
3787 for (int ir = 0; ir < obs->nr; ir++)
3788 fprintf(out, "%g\n", z[ir]);
3789 fprintf(out, "*SFC\n%g 1.0\n", tsurf);
3790 if (obsz >= 0)
3791 fprintf(out, "*OBS\n%g\n", obsz);
3792 fprintf(out, "*HIT\n%s\n", ctl->rfmhit);
3793 fprintf(out, "*XSC\n");
3794 for (int ig = 0; ig < ctl->ng; ig++)
3795 if (ctl->rfmxsc[ig][0] != '-')
3796 fprintf(out, "%s\n", ctl->rfmxsc[ig]);
3797 fprintf(out, "*END\n");
3798 fclose(out);
3799
3800 /* Remove temporary files... */
3801 if (system("rm -f rfm.runlog rad_*.asc tra_*.asc"))
3802 ERRMSG("Cannot remove temporary files!");
3803
3804 /* Call RFM... */
3805 sprintf(cmd, "echo | %s", ctl->rfmbin);
3806 if (system(cmd))
3807 ERRMSG("Error while calling RFM!");
3808
3809 /* Read and convolute each spectrum once... */
3810 for (int ir = 0; ir < obs->nr; ir++) {
3811 find_rfm_file(filename, "rad", z[ir]);
3812 read_rfm_spec(filename, nurfm, spec, &npts);
3813 for (int i = ib; i < ie; i++) {
3814 const int id = order[i];
3815 obs->rad[id][ir] = convolve_rfm(nurfm, spec, npts,
3816 tbl->filt_nu[id], tbl->filt_f[id], tbl->filt_n[id]) * 1e-5;
3817 }
3818
3819 find_rfm_file(filename, "tra", z[ir]);
3820 read_rfm_spec(filename, nurfm, spec, &npts);
3821 for (int i = ib; i < ie; i++) {
3822 const int id = order[i];
3823 obs->tau[id][ir] = convolve_rfm(nurfm, spec, npts,
3824 tbl->filt_nu[id], tbl->filt_f[id], tbl->filt_n[id]);
3825 }
3826 }
3827 ib = ie;
3828 }
3829
3830 /* Remove temporary files... */
3831 if (system("rm -f rfm.drv rfm.atm rfm.runlog rad_*.asc tra_*.asc"))
3832 ERRMSG("Error while removing temporary files!");
3833
3834 /* Free... */
3835 free(los);
3836 free(nurfm);
3837 free(spec);
3838}
void read_rfm_spec(const char *filename, double *nu, double *rad, int *npts)
Read a Reference Forward Model (RFM) ASCII spectrum.
Definition: jurassic.c:6232
void write_atm_rfm(const char *filename, const ctl_t *ctl, const atm_t *atm)
Write atmospheric profile in RFM-compatible format.
Definition: jurassic.c:7717
#define RFMNPTS
Maximum number of RFM spectral grid points.
Definition: jurassic.h:351
#define NSHAPE
Maximum number of shape function grid points.
Definition: jurassic.h:336
#define NR
Maximum number of ray paths.
Definition: jurassic.h:326
char rfmhit[LEN]
HITRAN file for RFM.
Definition: jurassic.h:1612
char rfmbin[LEN]
Path to RFM binary.
Definition: jurassic.h:1609
char rfmxsc[NG][LEN]
Emitter cross-section files for RFM.
Definition: jurassic.h:1615
int refrac
Take into account refractivity (0=no, 1=yes).
Definition: jurassic.h:1540
Line-of-sight data.
Definition: jurassic.h:1626
int filt_n[ND]
Filter function number of spectral grid points.
Definition: jurassic.h:1903
double filt_f[ND][NSHAPE]
Filter function values.
Definition: jurassic.h:1909
double filt_nu[ND][NSHAPE]
Filter function spectral grid points [cm^-1].
Definition: jurassic.h:1906
Here is the call graph for this function:

◆ formod_srcfunc()

void formod_srcfunc ( const ctl_t *  ctl,
const tbl_t *  tbl,
const double  t,
double *  src 
)

Interpolate the source function (Planck radiance) at a given temperature.

Computes source function values by linearly interpolating between precomputed Planck radiances in the lookup table. The resulting radiance spectrum corresponds to the input temperature and is stored in src for all spectral channels.

Parameters
[in]ctlControl structure defining the number of spectral channels.
[in]tblEmissivity and source-function lookup table containing Planck radiances (tbl_t::sr) and corresponding temperatures (tbl_t::st).
[in]tTemperature [K] for which the source function is evaluated.
[out]srcOutput array of interpolated source-function values [W·m⁻²·sr⁻¹·cm⁻¹] per spectral channel.
Note
Linear interpolation is used between the two nearest temperature grid points. The function does not extrapolate beyond the tabulated temperature range.
See also
ctl_t, tbl_t, LIN, locate_reg
Author
Lars Hoffmann

Definition at line 3842 of file jurassic.c.

3846 {
3847
3848 /* Determine index in temperature array... */
3849 const int it = locate_reg(tbl->st, TBLNS, t);
3850
3851 /* Interpolate Planck function value... */
3852 for (int id = 0; id < ctl->nd; id++)
3853 src[id] = LIN(tbl->st[it], tbl->sr[it][id],
3854 tbl->st[it + 1], tbl->sr[it + 1][id], t);
3855}
#define TBLNS
Maximum number of source function temperature levels.
Definition: jurassic.h:361
double sr[TBLNS][ND]
Source function radiance [W/(m^2 sr cm^-1)].
Definition: jurassic.h:1915
double st[TBLNS]
Source function temperature [K].
Definition: jurassic.h:1912
Here is the call graph for this function:

◆ geo2cart()

void geo2cart ( const double  z,
const double  lon,
const double  lat,
double *  x 
)

Converts geographic coordinates (longitude, latitude, altitude) to Cartesian coordinates.

This function converts geographic coordinates specified by longitude, latitude, and altitude into Cartesian coordinates. The Earth is approximated as a sphere with radius defined by the constant RE.

Parameters
zThe altitude above the Earth's surface in kilometers.
lonThe longitude in degrees.
latThe latitude in degrees.
xPointer to an array of three doubles where the computed Cartesian coordinates (x, y, z) will be stored.

The function computes the Cartesian coordinates using the given altitude, longitude, and latitude. It assumes the Earth is a perfect sphere and uses the following formulas:

  • \( x = (\textrm{radius}) \cos(\textrm{lat in radians}) \cos(\textrm{lon in radians}) \)
  • \( y = (\textrm{radius}) \cos(\textrm{lat in radians}) \sin(\textrm{lon in radians}) \)
  • \( z = (\textrm{radius}) \sin(\textrm{lat in radians}) \)
Note
The constant RE is defined as the Earth's radius in kilometers.
Longitude and latitude should be in degrees.
See also
https://en.wikipedia.org/wiki/Geographic_coordinate_conversion
Author
Lars Hoffmann

Definition at line 3859 of file jurassic.c.

3863 {
3864
3865 const double radius = z + RE;
3866 const double latrad = lat / 180. * M_PI;
3867 const double lonrad = lon / 180. * M_PI;
3868 const double coslat = cos(latrad);
3869
3870 x[0] = radius * coslat * cos(lonrad);
3871 x[1] = radius * coslat * sin(lonrad);
3872 x[2] = radius * sin(latrad);
3873}

◆ hydrostatic()

void hydrostatic ( const ctl_t *  ctl,
atm_t *  atm 
)

Adjust pressure profile using the hydrostatic equation.

Recomputes the atmospheric pressure field to ensure hydrostatic equilibrium with respect to altitude and temperature. Starting from a reference altitude (ctl_t::hydz), the routine integrates the hydrostatic balance equation both upward and downward through the profile using small interpolation steps.

The air density is corrected for humidity using the mean molecular mass of dry air and water vapor.

Parameters
[in]ctlControl structure providing model constants and reference altitude (ctl_t::hydz) and H₂O index (ctl_t::ig_h2o).
[in,out]atmAtmospheric state; input temperatures, heights, and humidities are used to update pressure [hPa].
Note
The integration is performed in log-pressure space assuming hydrostatic balance: \( \frac{dp}{dz} = -\rho g \),
using 20 linear substeps between adjacent levels.
See also
ctl_t, atm_t, LIN, G0, RI
Author
Lars Hoffmann

Definition at line 3877 of file jurassic.c.

3879 {
3880
3881 const double mmair = 28.96456e-3, mmh2o = 18.0153e-3;
3882
3883 const int ipts = 20;
3884
3885 double dzmin = 1e99, e = 0;
3886
3887 int ipref = 0;
3888
3889 /* Check reference height... */
3890 if (ctl->hydz < 0)
3891 return;
3892
3893 /* Find air parcel next to reference height... */
3894 for (int ip = 0; ip < atm->np; ip++)
3895 if (fabs(atm->z[ip] - ctl->hydz) < dzmin) {
3896 dzmin = fabs(atm->z[ip] - ctl->hydz);
3897 ipref = ip;
3898 }
3899
3900 /* Upper part of profile... */
3901 for (int ip = ipref + 1; ip < atm->np; ip++) {
3902 double mean = 0;
3903 for (int i = 0; i < ipts; i++) {
3904 if (ctl->ig_h2o >= 0)
3905 e = LIN(0.0, atm->q[ctl->ig_h2o][ip - 1],
3906 ipts - 1.0, atm->q[ctl->ig_h2o][ip], (double) i);
3907 mean += (e * mmh2o + (1 - e) * mmair)
3908 * G0 / RI
3909 / LIN(0.0, atm->t[ip - 1], ipts - 1.0, atm->t[ip], (double) i) / ipts;
3910 }
3911
3912 /* Compute p(z,T)... */
3913 atm->p[ip] =
3914 exp(log(atm->p[ip - 1]) - mean * 1000 * (atm->z[ip] - atm->z[ip - 1]));
3915 }
3916
3917 /* Lower part of profile... */
3918 for (int ip = ipref - 1; ip >= 0; ip--) {
3919 double mean = 0;
3920 for (int i = 0; i < ipts; i++) {
3921 if (ctl->ig_h2o >= 0)
3922 e = LIN(0.0, atm->q[ctl->ig_h2o][ip + 1],
3923 ipts - 1.0, atm->q[ctl->ig_h2o][ip], (double) i);
3924 mean += (e * mmh2o + (1 - e) * mmair)
3925 * G0 / RI
3926 / LIN(0.0, atm->t[ip + 1], ipts - 1.0, atm->t[ip], (double) i) / ipts;
3927 }
3928
3929 /* Compute p(z,T)... */
3930 atm->p[ip] =
3931 exp(log(atm->p[ip + 1]) - mean * 1000 * (atm->z[ip] - atm->z[ip + 1]));
3932 }
3933}
#define G0
Standard gravity [m/s^2].
Definition: jurassic.h:192
#define RI
Ideal gas constant [J/(mol K)].
Definition: jurassic.h:237
double hydz
Reference height for hydrostatic pressure profile (-999 to skip) [km].
Definition: jurassic.h:1525

◆ idx2name()

void idx2name ( const ctl_t *  ctl,
const int  idx,
char *  quantity 
)

Convert a quantity index to a descriptive name string.

Translates a model quantity index (e.g., pressure, temperature, gas mixing ratio, extinction, or surface parameter) into a human-readable name. The function uses the index mapping defined in the control structure to assign appropriate labels.

Parameters
[in]ctlControl structure containing gas, window, cloud, and surface setup information.
[in]idxQuantity index (see IDXP, IDXT, IDXQ, IDXK, etc.).
[out]quantityCharacter buffer to receive the descriptive quantity name (e.g., "PRESSURE", "H2O", "CLOUD_HEIGHT", "SURFACE_EMISSIVITY_1000.0").
Note
The function writes directly to quantity using sprintf(). The caller must ensure sufficient buffer size (≥ LEN).
See also
ctl_t, IDXP, IDXT, IDXQ, IDXK, IDXCLZ, IDXCLDZ, IDXCLK, IDXSFT, IDXSFEPS
Author
Lars Hoffmann

Definition at line 3937 of file jurassic.c.

3940 {
3941
3942 if (idx == IDXP)
3943 sprintf(quantity, "PRESSURE");
3944
3945 if (idx == IDXT)
3946 sprintf(quantity, "TEMPERATURE");
3947
3948 for (int ig = 0; ig < ctl->ng; ig++)
3949 if (idx == IDXQ(ig))
3950 sprintf(quantity, "%s", ctl->emitter[ig]);
3951
3952 for (int iw = 0; iw < ctl->nw; iw++)
3953 if (idx == IDXK(iw))
3954 sprintf(quantity, "EXTINCT_WINDOW_%d", iw);
3955
3956 if (idx == IDXCLZ)
3957 sprintf(quantity, "CLOUD_HEIGHT");
3958
3959 if (idx == IDXCLDZ)
3960 sprintf(quantity, "CLOUD_DEPTH");
3961
3962 for (int icl = 0; icl < ctl->ncl; icl++)
3963 if (idx == IDXCLK(icl))
3964 sprintf(quantity, "CLOUD_EXTINCT_%.4f", ctl->clnu[icl]);
3965
3966 if (idx == IDXSFT)
3967 sprintf(quantity, "SURFACE_TEMPERATURE");
3968
3969 for (int isf = 0; isf < ctl->nsf; isf++)
3970 if (idx == IDXSFEPS(isf))
3971 sprintf(quantity, "SURFACE_EMISSIVITY_%.4f", ctl->sfnu[isf]);
3972}
double sfnu[NSF]
Surface layer wavenumber [cm^-1].
Definition: jurassic.h:1501
double clnu[NCL]
Cloud layer wavenumber [cm^-1].
Definition: jurassic.h:1495

◆ init_srcfunc()

void init_srcfunc ( const ctl_t *  ctl,
tbl_t *  tbl 
)

Initialize source function lookup tables from emissivity data.

This function computes channel-dependent source function lookup tables based on the spectral filter functions and the Planck function. For each spectral channel, the Planck radiance is integrated over the corresponding filter function and stored as a function of temperature.

The resulting source function table represents the band-integrated thermal emission associated with the emissivity lookup tables and is later used in radiative transfer calculations.

The temperature grid is uniformly sampled between TMIN and TMAX with TBLNS points. The spectral integration is performed on the finest frequency spacing present in the filter function.

Parameters
[in]ctlPointer to the control structure defining the number of channels and their central wavenumbers.
[in,out]tblPointer to the lookup-table structure in which the source function tables and temperature grid are stored.
Note
The computation is parallelized over temperature grid points using OpenMP.
The source function is normalized by the integral of the filter function to yield a band-averaged Planck radiance.
Author
Lars Hoffmann

Definition at line 3976 of file jurassic.c.

3978 {
3979
3980 /* Write info... */
3981 LOG(1, "Initialize source function table...");
3982 LOG(2, "Number of data points: %d", TBLNS);
3983
3984 /* Loop over channels... */
3985 for (int id = 0; id < ctl->nd; id++) {
3986
3987 /* Get minimum grid spacing... */
3988 double dnu = 1.0;
3989 for (int i = 1; i < tbl->filt_n[id]; i++)
3990 dnu = MIN(dnu, tbl->filt_nu[id][i] - tbl->filt_nu[id][i - 1]);
3991
3992 /* Compute source function table... */
3993#pragma omp parallel for default(none) shared(ctl,tbl,id,dnu)
3994 for (int it = 0; it < TBLNS; it++) {
3995
3996 /* Set temperature... */
3997 tbl->st[it] = LIN(0.0, TMIN, TBLNS - 1.0, TMAX, (double) it);
3998
3999 /* Integrate Planck function... */
4000 double fsum = tbl->sr[it][id] = 0;
4001 for (double fnu = tbl->filt_nu[id][0];
4002 fnu <= tbl->filt_nu[id][tbl->filt_n[id] - 1]; fnu += dnu) {
4003 const int i = locate_irr(tbl->filt_nu[id], tbl->filt_n[id], fnu);
4004 const double ff = LIN(tbl->filt_nu[id][i], tbl->filt_f[id][i],
4005 tbl->filt_nu[id][i + 1], tbl->filt_f[id][i + 1],
4006 fnu);
4007 fsum += ff;
4008 tbl->sr[it][id] += ff * PLANCK(tbl->st[it], fnu);
4009 }
4010 tbl->sr[it][id] /= fsum;
4011 }
4012
4013 /* Write info... */
4014 LOG(2,
4015 "channel= %.4f cm^-1 | T= %g ... %g K | B= %g ... %g W/(m^2 sr cm^-1)",
4016 ctl->nu[id], tbl->st[0], tbl->st[TBLNS - 1], tbl->sr[0][id],
4017 tbl->sr[TBLNS - 1][id]);
4018 }
4019}
#define TMAX
Maximum temperature for source function [K].
Definition: jurassic.h:247
#define TMIN
Minimum temperature for source function [K].
Definition: jurassic.h:252
Here is the call graph for this function:

◆ intpol_atm()

void intpol_atm ( const ctl_t *  ctl,
const atm_t *  atm,
const double  z,
double *  p,
double *  t,
double *  q,
double *  k 
)

Interpolate atmospheric state variables at a given altitude.

Computes pressure, temperature, volume mixing ratios, and extinction coefficients at the specified altitude by interpolating between adjacent model levels in the atmospheric profile.

Parameters
[in]ctlControl structure defining the number of gases (ctl_t::ng) and spectral windows (ctl_t::nw).
[in]atmAtmospheric profile providing altitude, pressure, temperature, gas mixing ratios, and extinction data.
[in]zTarget altitude [km].
[out]pInterpolated pressure [hPa].
[out]tInterpolated temperature [K].
[out]qInterpolated gas volume mixing ratios [ppv], length ctl_t::ng.
[out]kInterpolated extinction coefficients [km⁻¹], length ctl_t::nw.
Note
Pressure is interpolated logarithmically using LOGY, while other quantities use linear interpolation (LIN).
See also
ctl_t, atm_t, locate_irr, LIN, LOGY
Author
Lars Hoffmann

Definition at line 4023 of file jurassic.c.

4030 {
4031
4032 /* Get array index... */
4033 const int ip = locate_irr(atm->z, atm->np, z);
4034
4035 /* Interpolate... */
4036 *p = LOGY(atm->z[ip], atm->p[ip], atm->z[ip + 1], atm->p[ip + 1], z);
4037 *t = LIN(atm->z[ip], atm->t[ip], atm->z[ip + 1], atm->t[ip + 1], z);
4038 for (int ig = 0; ig < ctl->ng; ig++)
4039 q[ig] =
4040 LIN(atm->z[ip], atm->q[ig][ip], atm->z[ip + 1], atm->q[ig][ip + 1], z);
4041 for (int iw = 0; iw < ctl->nw; iw++)
4042 k[iw] =
4043 LIN(atm->z[ip], atm->k[iw][ip], atm->z[ip + 1], atm->k[iw][ip + 1], z);
4044}
Here is the call graph for this function:

◆ intpol_tbl_cga()

void intpol_tbl_cga ( const ctl_t *  ctl,
const tbl_t *  tbl,
const los_t *  los,
const int  ip,
double  tau_path[ND][NG],
double  tau_seg[ND] 
)

Interpolate emissivities and transmittances using the Curtis–Godson approximation (CGA).

Computes gas transmittance along a line-of-sight segment by interpolating precomputed emissivity values from lookup tables. The interpolation is performed in pressure, temperature, and column density space using bilinear (in p, T) and logarithmic (in p) interpolation.

Parameters
[in]ctlControl structure defining number of gases (ctl_t::ng) and channels (ctl_t::nd).
[in]tblEmissivity lookup tables (tbl_t) containing tabulated pressure, temperature, and column density grids.
[in]losLine-of-sight structure providing Curtis–Godson mean parameters and column densities.
[in]ipIndex of the current LOS point.
[in,out]tau_pathPath transmittance array [nd][ng]; updated cumulatively for each gas.
[out]tau_segTotal segment transmittance per channel [nd].
  • Uses pretabulated emissivity data (tbl->eps) for each gas and channel.
  • Applies logarithmic interpolation in pressure and linear interpolation in temperature (LIN).
  • Enforces emissivity limits in the range [0, 1].
  • Returns unity transmittance if data are missing or column density ≤ 0.
See also
ctl_t, tbl_t, los_t, intpol_tbl_eps, LIN, locate_irr, locate_reg
Author
Lars Hoffmann

Definition at line 4048 of file jurassic.c.

4054 {
4055
4056 double eps, lnp[NG];
4057
4058 /* Precompute log-pressure... */
4059 for (int ig = 0; ig < ctl->ng; ig++)
4060 lnp[ig] = log(los->cgp[ip][ig]);
4061
4062 /* Loop over channels... */
4063 for (int id = 0; id < ctl->nd; id++) {
4064
4065 /* Initialize... */
4066 tau_seg[id] = 1;
4067
4068 /* Loop over emitters.... */
4069 for (int ig = 0; ig < ctl->ng; ig++) {
4070
4071 /* Check size of table (pressure) and column density... */
4072 if (tbl->np[id][ig] < 30 || los->cgu[ip][ig] <= 0)
4073 eps = 0;
4074
4075 /* Check transmittance... */
4076 else if (tau_path[id][ig] < 1e-9)
4077 eps = 1;
4078
4079 /* Interpolate... */
4080 else {
4081
4082 /* Determine pressure and temperature indices... */
4083 const int ipr =
4084 locate_irr(tbl->p[id][ig], tbl->np[id][ig], los->cgp[ip][ig]);
4085 const int it0 = locate_reg(tbl->t[id][ig][ipr], tbl->nt[id][ig][ipr],
4086 los->cgt[ip][ig]);
4087 const int it1 =
4088 locate_reg(tbl->t[id][ig][ipr + 1], tbl->nt[id][ig][ipr + 1],
4089 los->cgt[ip][ig]);
4090
4091 /* Check size of table (temperature and column density)... */
4092 if (tbl->nt[id][ig][ipr] < 2 || tbl->nt[id][ig][ipr + 1] < 2
4093 || tbl->nu[id][ig][ipr][it0] < 2
4094 || tbl->nu[id][ig][ipr][it0 + 1] < 2
4095 || tbl->nu[id][ig][ipr + 1][it1] < 2
4096 || tbl->nu[id][ig][ipr + 1][it1 + 1] < 2)
4097 eps = 0;
4098
4099 else {
4100
4101 /* Get emissivities of extended path... */
4102 const double logu = log(los->cgu[ip][ig]);
4103 double eps00 = intpol_tbl_eps(tbl, ig, id, ipr, it0, logu);
4104 double eps01 = intpol_tbl_eps(tbl, ig, id, ipr, it0 + 1, logu);
4105 double eps10 = intpol_tbl_eps(tbl, ig, id, ipr + 1, it1, logu);
4106 double eps11 = intpol_tbl_eps(tbl, ig, id, ipr + 1, it1 + 1, logu);
4107
4108 /* Interpolate with respect to temperature... */
4109 eps00 = LIN(tbl->t[id][ig][ipr][it0], eps00,
4110 tbl->t[id][ig][ipr][it0 + 1], eps01, los->cgt[ip][ig]);
4111 eps11 = LIN(tbl->t[id][ig][ipr + 1][it1], eps10,
4112 tbl->t[id][ig][ipr + 1][it1 + 1],
4113 eps11, los->cgt[ip][ig]);
4114
4115 /* Interpolate with respect to log-pressure... */
4116 eps00 = LIN(tbl->lnp[id][ig][ipr], eps00,
4117 tbl->lnp[id][ig][ipr + 1], eps11, lnp[ig]);
4118
4119 /* Check emissivity range... */
4120 eps00 = CLAMP(eps00, 0, 1);
4121
4122 /* Determine segment emissivity... */
4123 eps = 1 - (1 - eps00) / tau_path[id][ig];
4124
4125 /* Check emissivity range... */
4126 eps = CLAMP(eps, 0, 1);
4127 }
4128 }
4129
4130 /* Get transmittance of extended path... */
4131 tau_path[id][ig] *= (1 - eps);
4132
4133 /* Get segment transmittance... */
4134 tau_seg[id] *= (1 - eps);
4135 }
4136 }
4137}
double intpol_tbl_eps(const tbl_t *tbl, const int ig, const int id, const int ip, const int it, const double logu)
Interpolate gas emissivity as a function of column amount.
Definition: jurassic.c:4243
#define CLAMP(v, lo, hi)
Clamp a value to a specified range.
Definition: jurassic.h:478
double cgu[NLOS][NG]
Curtis-Godson column density [molecules/cm^2].
Definition: jurassic.h:1671
double cgt[NLOS][NG]
Curtis-Godson temperature [K].
Definition: jurassic.h:1668
double cgp[NLOS][NG]
Curtis-Godson pressure [hPa].
Definition: jurassic.h:1665
double p[ND][NG][TBLNP]
Pressure [hPa].
Definition: jurassic.h:1888
int nu[ND][NG][TBLNP][TBLNT]
Number of column densities.
Definition: jurassic.h:1885
int nt[ND][NG][TBLNP]
Number of temperatures.
Definition: jurassic.h:1882
double t[ND][NG][TBLNP][TBLNT]
Temperature [K].
Definition: jurassic.h:1894
double lnp[ND][NG][TBLNP]
Log-pressure [hPa].
Definition: jurassic.h:1891
int np[ND][NG]
Number of pressure levels.
Definition: jurassic.h:1879
Here is the call graph for this function:

◆ intpol_tbl_ega()

void intpol_tbl_ega ( const ctl_t *  ctl,
const tbl_t *  tbl,
const los_t *  los,
const int  ip,
double  tau_path[ND][NG],
double  tau_seg[ND] 
)

Interpolate emissivities and transmittances using the Emissivity Growth Approximation (EGA).

Computes gas transmittance along a line-of-sight segment by interpolating emissivity values from lookup tables based on the Emissivity Growth Approximation (EGA). The interpolation is performed in pressure, temperature, and effective column density space derived from the local LOS properties.

Parameters
[in]ctlControl structure defining number of gases (ctl_t::ng) and channels (ctl_t::nd).
[in]tblEmissivity lookup tables (tbl_t) containing tabulated pressure, temperature, and column density grids.
[in]losLine-of-sight structure providing local pressure, temperature, and column density data.
[in]ipIndex of the current LOS point.
[in,out]tau_pathPath transmittance array [nd][ng]; updated cumulatively for each gas.
[out]tau_segTotal segment transmittance per channel [nd].
  • Uses pretabulated emissivity data (tbl->eps) and performs bilinear interpolation in pressure and temperature.
  • Column density interpolation is handled by intpol_tbl_u according to the emissivity growth relation.
  • Enforces emissivity limits within [0, 1].
  • Returns unity transmittance if lookup data are invalid or column density ≤ 0.
See also
ctl_t, tbl_t, los_t, intpol_tbl_u, intpol_tbl_eps, LIN, locate_irr, locate_reg
Note
Implements the EGA variant of the forward model, selected when ctl_t::formod = 1.
Author
Lars Hoffmann

Definition at line 4141 of file jurassic.c.

4147 {
4148
4149 const double lnp = log(los->p[ip]);
4150
4151 double eps, u;
4152
4153 /* Loop over channels... */
4154 for (int id = 0; id < ctl->nd; id++) {
4155
4156 /* Initialize... */
4157 tau_seg[id] = 1;
4158
4159 /* Loop over emitters.... */
4160 for (int ig = 0; ig < ctl->ng; ig++) {
4161
4162 /* Check size of table (pressure) and column density... */
4163 if (tbl->np[id][ig] < 30 || los->cgu[ip][ig] <= 0)
4164 eps = 0;
4165
4166 /* Check transmittance... */
4167 else if (tau_path[id][ig] < 1e-9)
4168 eps = 1;
4169
4170 /* Interpolate... */
4171 else {
4172
4173 /* Determine pressure and temperature indices... */
4174 const int ipr =
4175 locate_irr(tbl->p[id][ig], tbl->np[id][ig], los->p[ip]);
4176 const int it0 =
4177 locate_reg(tbl->t[id][ig][ipr], tbl->nt[id][ig][ipr], los->t[ip]);
4178 const int it1 =
4179 locate_reg(tbl->t[id][ig][ipr + 1], tbl->nt[id][ig][ipr + 1],
4180 los->t[ip]);
4181
4182 /* Check size of table (temperature and column density)... */
4183 if (tbl->nt[id][ig][ipr] < 2 || tbl->nt[id][ig][ipr + 1] < 2
4184 || tbl->nu[id][ig][ipr][it0] < 2
4185 || tbl->nu[id][ig][ipr][it0 + 1] < 2
4186 || tbl->nu[id][ig][ipr + 1][it1] < 2
4187 || tbl->nu[id][ig][ipr + 1][it1 + 1] < 2)
4188 eps = 0;
4189
4190 else {
4191
4192 /* Get emissivities of extended path... */
4193 const double logeps = log(1.0 - tau_path[id][ig]);
4194
4195 u = intpol_tbl_u(tbl, ig, id, ipr, it0, logeps);
4196 double eps00
4197 = intpol_tbl_eps(tbl, ig, id, ipr, it0, log(u + los->u[ip][ig]));
4198
4199 u = intpol_tbl_u(tbl, ig, id, ipr, it0 + 1, logeps);
4200 double eps01 = intpol_tbl_eps(tbl, ig, id, ipr, it0 + 1,
4201 log(u + los->u[ip][ig]));
4202
4203 u = intpol_tbl_u(tbl, ig, id, ipr + 1, it1, logeps);
4204 double eps10 = intpol_tbl_eps(tbl, ig, id, ipr + 1, it1,
4205 log(u + los->u[ip][ig]));
4206
4207 u = intpol_tbl_u(tbl, ig, id, ipr + 1, it1 + 1, logeps);
4208 double eps11 = intpol_tbl_eps(tbl, ig, id, ipr + 1, it1 + 1,
4209 log(u + los->u[ip][ig]));
4210
4211 /* Interpolate with respect to temperature... */
4212 eps00 = LIN(tbl->t[id][ig][ipr][it0], eps00,
4213 tbl->t[id][ig][ipr][it0 + 1], eps01, los->t[ip]);
4214 eps11 = LIN(tbl->t[id][ig][ipr + 1][it1], eps10,
4215 tbl->t[id][ig][ipr + 1][it1 + 1], eps11, los->t[ip]);
4216
4217 /* Interpolate with respect to log-pressure... */
4218 eps00 = LIN(tbl->lnp[id][ig][ipr], eps00,
4219 tbl->lnp[id][ig][ipr + 1], eps11, lnp);
4220
4221 /* Check emissivity range... */
4222 eps00 = CLAMP(eps00, 0, 1);
4223
4224 /* Determine segment emissivity... */
4225 eps = 1 - (1 - eps00) / tau_path[id][ig];
4226
4227 /* Check emissivity range... */
4228 eps = CLAMP(eps, 0, 1);
4229 }
4230 }
4231
4232 /* Get transmittance of extended path... */
4233 tau_path[id][ig] *= (1 - eps);
4234
4235 /* Get segment transmittance... */
4236 tau_seg[id] *= (1 - eps);
4237 }
4238 }
4239}
double intpol_tbl_u(const tbl_t *tbl, const int ig, const int id, const int ip, const int it, const double logeps)
Interpolate column amount as a function of emissivity.
Definition: jurassic.c:4288
Here is the call graph for this function:

◆ intpol_tbl_eps()

double intpol_tbl_eps ( const tbl_t *  tbl,
const int  ig,
const int  id,
const int  ip,
const int  it,
const double  logu 
)
inline

Interpolate gas emissivity as a function of column amount.

Computes emissivity \(\varepsilon(u)\) from tabulated data using linear interpolation in \(\log u\)– \(\log\varepsilon\) space. The input column amount must be provided as \(\log(u)\).

Behavior:

  • For \(u < u_{\min}\), emissivity scales linearly with column amount.
  • For \(u > u_{\max}\), emissivity asymptotically approaches unity using an exponential tail matched at \((u_{\max}, \varepsilon_{\max})\).

The implementation uses log1p/expm1 for numerical stability and minimizes conversions between linear and logarithmic space.

Parameters
tblLookup table structure.
igGas index.
idSpectral/channel index.
ipPressure index.
itTemperature index.
loguNatural logarithm of the column amount [molecules/cm²].
Returns
Emissivity in the range \([0,1]\).
Author
Lars Hoffmann

Definition at line 4243 of file jurassic.c.

4249 {
4250
4251 const int nu = tbl->nu[id][ig][ip][it];
4252 const float *logu_arr = tbl->logu[id][ig][ip][it];
4253 const float *logeps_arr = tbl->logeps[id][ig][ip][it];
4254
4255 /* Work in log-space and only convert back when needed... */
4256 const double logu_min = (double) logu_arr[0];
4257 const double logu_max = (double) logu_arr[nu - 1];
4258
4259 /* Lower boundary extrapolation (u < u_min)...
4260 eps ~ eps_min * u/u_min => log(eps) = logeps_min + log(u) - log(u_min) */
4261 if (logu < logu_min) {
4262 const double logeps_min = (double) logeps_arr[0];
4263 return exp(logeps_min + logu - logu_min);
4264 }
4265
4266 /* Upper boundary extrapolation (u > u_max)...
4267 * Assume eps(u) approaches 1 exponentially:
4268 * eps(u) = 1 - exp(a * u), a < 0
4269 * Continuity at (u_max, eps_max) gives
4270 * a = log(1 - eps_max) / u_max.
4271 * Use log1p/expm1 and u/u_max = exp(log(u) - log(u_max)) for stability.
4272 */
4273 if (logu > logu_max) {
4274 const double eps_max = exp((double) logeps_arr[nu - 1]);
4275 const double l1m_eps_max = log1p(-eps_max);
4276 const double r = exp(logu - logu_max);
4277 return -expm1(l1m_eps_max * r);
4278 }
4279
4280 /* Interpolation (log-log using precomputed logs)... */
4281 const int idx = locate_tbl(logu_arr, nu, logu);
4282 return exp(LIN(logu_arr[idx], logeps_arr[idx],
4283 logu_arr[idx + 1], logeps_arr[idx + 1], logu));
4284}
int locate_tbl(const float *xx, const int n, const double x)
Locate index for interpolation within emissivity table grids.
Definition: jurassic.c:4538
float * logu[ND][NG][TBLNP][TBLNT]
Logarithm of column density [molecules/cm^2].
Definition: jurassic.h:1897
float * logeps[ND][NG][TBLNP][TBLNT]
Logarithm of emissivity.
Definition: jurassic.h:1900
Here is the call graph for this function:

◆ intpol_tbl_u()

double intpol_tbl_u ( const tbl_t *  tbl,
const int  ig,
const int  id,
const int  ip,
const int  it,
const double  logeps 
)
inline

Interpolate column amount as a function of emissivity.

Computes the column amount \(u(\varepsilon)\) from tabulated data using linear interpolation in \(\log\varepsilon\)– \(\log u\) space. The emissivity must be provided as \(\log(\varepsilon)\) together with \(\log(1-\varepsilon)\).

Behavior:

  • For \(\varepsilon < \varepsilon_{\min}\), column amount scales linearly with emissivity.
  • For \(\varepsilon > \varepsilon_{\max}\), the exponential tail used in intpol_tbl_eps() is analytically inverted.

The implementation operates primarily in log-space and uses log1p for numerical stability near \(\varepsilon \rightarrow 1\).

Parameters
tblLookup table structure.
igGas index.
idSpectral/channel index.
ipPressure index.
itTemperature index.
logepsNatural logarithm of emissivity ( \(\log\varepsilon\)).
Returns
Column amount \(u\).
See also
intpol_tbl_eps
Author
Lars Hoffmann

Definition at line 4288 of file jurassic.c.

4294 {
4295
4296 const int nu = tbl->nu[id][ig][ip][it];
4297 const float *logeps_arr = tbl->logeps[id][ig][ip][it];
4298 const float *logu_arr = tbl->logu[id][ig][ip][it];
4299
4300 /* Work in log-space and only convert back when needed.... */
4301 const double logeps_min = (double) logeps_arr[0];
4302 const double logeps_max = (double) logeps_arr[nu - 1];
4303
4304 /* Lower boundary extrapolation (eps < eps_min)...
4305 u ~ u_min * eps/eps_min => log(u) = log(u_min) + log(eps) - log(eps_min) */
4306 if (logeps < logeps_min) {
4307 const double logu_min = (double) logu_arr[0];
4308 return exp(logu_min + logeps - logeps_min);
4309 }
4310
4311 /* Upper boundary extrapolation (eps > eps_max):
4312 * Invert the exponential tail used for eps(u):
4313 * u = log(1 - eps) / a,
4314 * with a = log(1 - eps_max) / u_max.
4315 * Rewritten as
4316 * u = u_max * log(tau) / log(1 - eps_max)
4317 * for numerical stability (log1p).
4318 */
4319 if (logeps > logeps_max) {
4320 const double u_max = exp((double) logu_arr[nu - 1]);
4321 const double l1m_eps_max = log1p(-exp(logeps_max));
4322 const double logtau = log1p(-exp(logeps));
4323 return u_max * (logtau / l1m_eps_max);
4324 }
4325
4326 /* Interpolation (log-log using precomputed logs)... */
4327 const int idx = locate_tbl(logeps_arr, nu, logeps);
4328 return exp(LIN(logeps_arr[idx], logu_arr[idx],
4329 logeps_arr[idx + 1], logu_arr[idx + 1], logeps));
4330}
Here is the call graph for this function:

◆ jsec2time()

void jsec2time ( const double  jsec,
int *  year,
int *  mon,
int *  day,
int *  hour,
int *  min,
int *  sec,
double *  remain 
)

Converts Julian seconds to calendar date and time components.

This function converts Julian seconds to calendar date and time components, including year, month, day, hour, minute, and second. It also calculates the fractional part of the seconds.

Parameters
jsecJulian seconds to convert.
yearPointer to store the year.
monPointer to store the month.
dayPointer to store the day.
hourPointer to store the hour.
minPointer to store the minute.
secPointer to store the second.
remainPointer to store the fractional part of seconds.

The function initializes a time structure t0 with a fixed starting date and time. It then converts the Julian seconds to a time_t type by adding the seconds to the epoch time. Next, it converts the time_t value to a UTC time structure t1. Finally, it extracts the year, month, day, hour, minute, and second components from t1 and calculates the fractional part of seconds, which is stored in remain.

Author
Lars Hoffmann

Definition at line 4334 of file jurassic.c.

4342 {
4343
4344 struct tm t0, *t1;
4345
4346 t0.tm_year = 100;
4347 t0.tm_mon = 0;
4348 t0.tm_mday = 1;
4349 t0.tm_hour = 0;
4350 t0.tm_min = 0;
4351 t0.tm_sec = 0;
4352
4353 const time_t jsec0 = (time_t) jsec + timegm(&t0);
4354 t1 = gmtime(&jsec0);
4355
4356 *year = t1->tm_year + 1900;
4357 *mon = t1->tm_mon + 1;
4358 *day = t1->tm_mday;
4359 *hour = t1->tm_hour;
4360 *min = t1->tm_min;
4361 *sec = t1->tm_sec;
4362 *remain = jsec - floor(jsec);
4363}

◆ kernel()

void kernel ( const ctl_t *  ctl,
const tbl_t *  tbl,
atm_t *  atm,
obs_t *  obs,
gsl_matrix *  k 
)

Compute the Jacobian (kernel) matrix by finite differences.

Evaluates the sensitivity of the simulated radiances to each element of the atmospheric state vector by perturbing one parameter at a time and re-running the forward model. Independent perturbed states are prepared in batches and evaluated through formod_batch. The resulting Jacobian matrix is \( K = \partial y / \partial x \), where y is the measurement vector and x is the state vector.

Parameters
[in]ctlControl structure defining retrieval configuration and model setup.
[in]tblEmissivity lookup tables used by the forward model.
[in,out]atmAtmospheric state and profile data; may be adjusted for hydrostatic balance.
[in,out]obsObservation geometry and radiance data; populated with the undisturbed forward-model result.
[out]kJacobian matrix [m×n], where m is the number of measurements and n the number of state variables.
  • The undisturbed forward model is first computed to obtain the reference measurement vector.
  • Each state vector element is perturbed by an adaptive step h depending on its physical type (pressure, temperature, VMR, etc.).
  • For each perturbation, the forward model is re-evaluated, and the corresponding column of K is estimated using finite differences.
  • Independent perturbed forward-model calculations are parallelized with OpenMP.
Note
Typical perturbation sizes:
  • Pressure: 1 % or ≥ 1e–7 hPa
  • Temperature: 1 K
  • VMR: 1 % or ≥ 1e–15
  • Extinction: 1e–4 km⁻¹
  • Cloud and surface parameters: 1 K or 1e–2 as appropriate.
See also
ctl_t, tbl_t, atm_t, obs_t, formod, formod_batch, x2atm, atm2x, obs2y, copy_atm, copy_obs
Warning
Computationally intensive; requires one forward model evaluation per state vector element.
Author
Lars Hoffmann

Definition at line 4367 of file jurassic.c.

4372 {
4373
4374 /* Get sizes... */
4375 const size_t m = k->size1;
4376 const size_t n = k->size2;
4377 const size_t batch_size = MIN(n, (size_t) MAX(1, omp_get_max_threads()));
4378
4379 /* Allocate... */
4380 gsl_vector *x0 = gsl_vector_alloc(n);
4381 gsl_vector *yy0 = gsl_vector_alloc(m);
4382 gsl_vector *x1 = gsl_vector_alloc(n);
4383 gsl_vector *yy1 = gsl_vector_alloc(m);
4384 int *iqa;
4385 ALLOC(iqa, int,
4386 N);
4387 double *h_batch;
4388 int *status;
4389 ALLOC(h_batch, double,
4390 batch_size);
4391 ALLOC(status, int,
4392 batch_size);
4393 los_t *los0, *los1;
4394 atm_t *atm1;
4395 obs_t *obs_scratch0, *obs1, *obs_scratch1;
4396 ALLOC(los0, los_t, 1);
4397 ALLOC(obs_scratch0, obs_t, 1);
4398 ALLOC(atm1, atm_t, batch_size);
4399 ALLOC(obs1, obs_t, batch_size);
4400 ALLOC(los1, los_t, batch_size);
4401 ALLOC(obs_scratch1, obs_t, batch_size);
4402
4403 /* Compute radiance for undisturbed atmospheric data... */
4404 if (formod(ctl, tbl, atm, obs, los0, obs_scratch0) != FORMOD_STATUS_OK)
4405 ERRMSG("Forward model failed!");
4406 free(los0);
4407 free(obs_scratch0);
4408
4409 /* Compose vectors... */
4410 atm2x(ctl, atm, x0, iqa, NULL);
4411 obs2y(ctl, obs, yy0, NULL, NULL);
4412
4413 /* Initialize kernel matrix... */
4414 gsl_matrix_set_zero(k);
4415
4416 /* Loop over state vector elements in batches... */
4417 for (size_t j0 = 0; j0 < n; j0 += batch_size) {
4418 const size_t nbatch = MIN(batch_size, n - j0);
4419
4420 /* Prepare disturbed states... */
4421 for (size_t jb = 0; jb < nbatch; jb++) {
4422 const size_t j = j0 + jb;
4423
4424 /* Set perturbation size... */
4425 double h;
4426 if (iqa[j] == IDXP)
4427 h = MAX(fabs(0.01 * gsl_vector_get(x0, j)), 1e-7);
4428 else if (iqa[j] == IDXT)
4429 h = 1.0;
4430 else if (iqa[j] >= IDXQ(0) && iqa[j] < IDXQ(ctl->ng))
4431 h = MAX(fabs(0.01 * gsl_vector_get(x0, j)), 1e-15);
4432 else if (iqa[j] >= IDXK(0) && iqa[j] < IDXK(ctl->nw))
4433 h = 1e-4;
4434 else if (iqa[j] == IDXCLZ || iqa[j] == IDXCLDZ)
4435 h = 1.0;
4436 else if (iqa[j] >= IDXCLK(0) && iqa[j] < IDXCLK(ctl->ncl))
4437 h = 1e-4;
4438 else if (iqa[j] == IDXSFT)
4439 h = 1.0;
4440 else if (iqa[j] >= IDXSFEPS(0) && iqa[j] < IDXSFEPS(ctl->nsf))
4441 h = 1e-2;
4442 else
4443 ERRMSG("Cannot set perturbation size!");
4444
4445 /* Disturb state vector element... */
4446 gsl_vector_memcpy(x1, x0);
4447 gsl_vector_set(x1, j, gsl_vector_get(x1, j) + h);
4448 copy_atm(ctl, &atm1[jb], atm, 0);
4449 copy_obs(ctl, &obs1[jb], obs, 0);
4450 x2atm(ctl, x1, &atm1[jb]);
4451 h_batch[jb] = h;
4452 }
4453
4454 /* Compute radiance for disturbed atmospheric data... */
4455 formod_batch(ctl, tbl, atm1, obs1, (int) nbatch, status, los1,
4456 obs_scratch1);
4457
4458 /* Compose measurement vectors and derivatives... */
4459 for (size_t jb = 0; jb < nbatch; jb++) {
4460 const size_t j = j0 + jb;
4461 if (status[jb] != FORMOD_STATUS_OK)
4462 ERRMSG("Forward model failed!");
4463 obs2y(ctl, &obs1[jb], yy1, NULL, NULL);
4464
4465 /* Compute derivatives... */
4466 for (size_t i = 0; i < m; i++)
4467 gsl_matrix_set(k, i, j,
4468 (gsl_vector_get(yy1, i) - gsl_vector_get(yy0, i))
4469 / h_batch[jb]);
4470 }
4471 }
4472
4473 /* Free... */
4474 gsl_vector_free(x0);
4475 gsl_vector_free(yy0);
4476 gsl_vector_free(x1);
4477 gsl_vector_free(yy1);
4478 free(atm1);
4479 free(obs1);
4480 free(obs_scratch1);
4481 free(los1);
4482 free(status);
4483 free(h_batch);
4484 free(iqa);
4485}
void x2atm(const ctl_t *ctl, const gsl_vector *x, atm_t *atm)
Map retrieval state vector back to atmospheric structure.
Definition: jurassic.c:8915
void formod_batch(const ctl_t *ctl, const tbl_t *tbl, atm_t *atm, obs_t *obs, const int nbatch, int *status, los_t *los_scratch, obs_t *obs_scratch)
Execute the forward model for a batch of independent cases.
Definition: jurassic.c:3316
size_t obs2y(const ctl_t *ctl, const obs_t *obs, gsl_vector *y, int *ida, int *ira)
Convert observation radiances into a measurement vector.
Definition: jurassic.c:4635
size_t atm2x(const ctl_t *ctl, const atm_t *atm, gsl_vector *x, int *iqa, int *ipa)
Convert atmospheric data to state vector elements.
Definition: jurassic.c:125
Observation geometry and radiance data.
Definition: jurassic.h:1688
Here is the call graph for this function:

◆ locate_irr()

int locate_irr ( const double *  xx,
const int  n,
const double  x 
)

Locate index for interpolation on an irregular grid.

Finds the lower index ilo such that \( xx[ilo] \le x < xx[ilo+1] \) for monotonically increasing or decreasing grids.
Used in interpolation routines for altitude, pressure, temperature, or wavenumber profiles that are not evenly spaced.

Parameters
[in]xxArray of monotonic grid values (increasing or decreasing).
[in]nNumber of grid points.
[in]xTarget value to locate within the grid range.
Returns
Index ilo of the lower grid point surrounding x.
  • Uses a binary search algorithm with \( O(\log n) \) complexity.
  • Handles both increasing and decreasing grids automatically.
  • Returns the index of the lower neighbor suitable for use in interpolation routines such as LIN or LOGY.
See also
LIN, LOGY, locate_reg, locate_tbl
Warning
Assumes x lies within the range of xx; no bounds checking beyond the first and last grid points is performed.
Author
Lars Hoffmann

Definition at line 4489 of file jurassic.c.

4492 {
4493
4494 int ilo = 0;
4495 int ihi = n - 1;
4496 int i = (ihi + ilo) >> 1;
4497
4498 if (xx[i] < xx[i + 1])
4499 while (ihi > ilo + 1) {
4500 i = (ihi + ilo) >> 1;
4501 if (xx[i] > x)
4502 ihi = i;
4503 else
4504 ilo = i;
4505 } else
4506 while (ihi > ilo + 1) {
4507 i = (ihi + ilo) >> 1;
4508 if (xx[i] <= x)
4509 ihi = i;
4510 else
4511 ilo = i;
4512 }
4513
4514 return ilo;
4515}

◆ locate_reg()

int locate_reg ( const double *  xx,
const int  n,
const double  x 
)

Locate index for interpolation on a regular (uniform) grid.

Computes the lower index i such that \( xx[i] \le x < xx[i+1] \) for evenly spaced grid points. Used for quick index lookup when the grid spacing is constant.

Parameters
[in]xxArray of regularly spaced grid values.
[in]nNumber of grid points.
[in]xTarget value to locate within the grid range.
Returns
Index i of the lower grid point surrounding x.
  • Computes the index directly from the grid spacing using \( i = (x - xx_0) / (xx_1 - xx_0) \).
  • Clamps the result to [0, n - 2] to avoid out-of-bounds indices.
  • Suitable for use with uniform grids such as pressure, temperature, or wavelength tables.
See also
locate_irr, locate_tbl, LIN, LOGY
Warning
Assumes uniform grid spacing; results are invalid for irregularly spaced arrays.
Author
Lars Hoffmann

Definition at line 4519 of file jurassic.c.

4522 {
4523
4524 /* Calculate index... */
4525 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
4526
4527 /* Check range... */
4528 if (i < 0)
4529 return 0;
4530 else if (i > n - 2)
4531 return n - 2;
4532 else
4533 return i;
4534}

◆ locate_tbl()

int locate_tbl ( const float *  xx,
const int  n,
const double  x 
)
inline

Locate index for interpolation within emissivity table grids.

Finds the lower index ilo such that \( xx[ilo] \le x < xx[ilo+1] \) in a monotonically increasing single-precision grid.
Used for emissivity and column density interpolation in table-based routines such as intpol_tbl_eps and intpol_tbl_u.

Parameters
[in]xxMonotonic (increasing) single-precision grid array.
[in]nNumber of grid points.
[in]xTarget value to locate within the grid range.
Returns
Index ilo of the lower grid point surrounding x.
  • Implements a binary search with \( O(\log n) \) complexity.
  • Optimized for lookup tables stored in float to minimize memory use.
  • Returns an index suitable for linear interpolation with LIN.
See also
intpol_tbl_eps, intpol_tbl_u, LIN, locate_irr, locate_reg
Warning
Assumes monotonic grid input (increasing order) and that x lies within the table range.
Author
Lars Hoffmann

Definition at line 4538 of file jurassic.c.

4541 {
4542
4543 int ilo = 0;
4544 int ihi = n - 1;
4545 int i = (ihi + ilo) >> 1;
4546
4547 while (ihi > ilo + 1) {
4548 i = (ihi + ilo) >> 1;
4549 if (xx[i] > x)
4550 ihi = i;
4551 else
4552 ilo = i;
4553 }
4554
4555 return ilo;
4556}

◆ matrix_invert()

void matrix_invert ( gsl_matrix *  a)

Invert a square matrix, optimized for diagonal or symmetric positive-definite matrices.

Performs in-place inversion of the matrix \(\mathbf{A}\) using either:

  • Fast diagonal inversion, if the matrix is strictly diagonal.
  • Cholesky decomposition, if the matrix is full and symmetric positive-definite.
Parameters
[in,out]aSquare matrix (gsl_matrix) to be inverted in place.

The function first checks whether the input matrix is diagonal by testing all off-diagonal elements. If diagonal, each diagonal element \(a_{ii}\) is replaced by its reciprocal \(1/a_{ii}\).

For non-diagonal matrices, a Cholesky decomposition is performed:

\[ \mathbf{A} = \mathbf{L}\mathbf{L}^T \]

followed by inversion using the Cholesky factors, yielding \(\mathbf{A}^{-1}\).

This approach assumes \(\mathbf{A}\) is symmetric and positive-definite.

See also
gsl_linalg_cholesky_decomp, gsl_linalg_cholesky_invert
Note
  • The inversion is performed in place; the input matrix is overwritten.
  • No explicit symmetry or definiteness checks are performed — invalid input may result in numerical instability or GSL errors.
  • Diagonal detection assumes exact zeros for off-diagonal elements.
Warning
For ill-conditioned matrices, consider using singular value decomposition (SVD) or regularization methods instead of direct inversion.
Author
Lars Hoffmann

Definition at line 4560 of file jurassic.c.

4561 {
4562
4563 size_t diag = 1;
4564
4565 /* Get size... */
4566 const size_t n = a->size1;
4567
4568 /* Check if matrix is diagonal... */
4569 for (size_t i = 0; i < n && diag; i++)
4570 for (size_t j = i + 1; j < n; j++)
4571 if (gsl_matrix_get(a, i, j) != 0) {
4572 diag = 0;
4573 break;
4574 }
4575
4576 /* Quick inversion of diagonal matrix... */
4577 if (diag)
4578 for (size_t i = 0; i < n; i++)
4579 gsl_matrix_set(a, i, i, 1 / gsl_matrix_get(a, i, i));
4580
4581 /* Matrix inversion by means of Cholesky decomposition... */
4582 else {
4583 gsl_linalg_cholesky_decomp(a);
4584 gsl_linalg_cholesky_invert(a);
4585 }
4586}

◆ matrix_product()

void matrix_product ( const gsl_matrix *  a,
const gsl_vector *  b,
const int  transpose,
gsl_matrix *  c 
)

Compute structured matrix products of the form \(A^T B A\) or \(A B A^T\).

Evaluates matrix products commonly used in covariance propagation and optimal estimation, depending on the specified transpose mode:

  • transpose = 1 → computes \(\mathbf{A}^T \mathbf{B} \mathbf{A}\)
  • transpose = 2 → computes \(\mathbf{A} \mathbf{B} \mathbf{A}^T\)

The vector \(\mathbf{b}\) represents the diagonal elements of \(\mathbf{B}\), i.e. a diagonal weighting or covariance matrix.

Parameters
[in]aInput matrix \(\mathbf{A}\) (size m×n).
[in]bVector representing the diagonal of \(\mathbf{B}\) (length m or n).
[in]transposeOperation selector:
  • 1 → compute \(A^T B A\)
  • 2 → compute \(A B A^T\)
[out]cOutput matrix to store the resulting product.
  • The function internally forms the scaled matrix \((B^{1/2} A)\) or \((A B^{1/2})\), then multiplies it using BLAS dgemm routines for efficiency:

    \[ A^T B A = (B^{1/2}A)^T (B^{1/2}A), \quad A B A^T = (A B^{1/2}) (A B^{1/2})^T \]

  • The input matrix \(\mathbf{A}\) is not modified.
  • This operation is typically used in computing gain matrices, propagated covariances, or sensitivity matrices in retrieval algorithms.
See also
gsl_blas_dgemm, matrix_invert
Note
  • Assumes \(\mathbf{B}\) is diagonal (provided as a vector of its diagonal elements).
  • The output matrix \(\mathbf{C}\) must be pre-allocated to the correct size.
  • No symmetry enforcement or normalization is applied.
Warning
  • If transpose is not 1 or 2, the function performs no operation.
  • Numerical stability depends on the conditioning of A and the scaling of B.
Author
Lars Hoffmann

Definition at line 4590 of file jurassic.c.

4594 {
4595
4596 /* Set sizes... */
4597 const size_t m = a->size1;
4598 const size_t n = a->size2;
4599
4600 /* Allocate... */
4601 gsl_matrix *aux = gsl_matrix_alloc(m, n);
4602
4603 /* Compute A^T B A... */
4604 if (transpose == 1) {
4605
4606 /* Compute B^1/2 A... */
4607 for (size_t i = 0; i < m; i++)
4608 for (size_t j = 0; j < n; j++)
4609 gsl_matrix_set(aux, i, j,
4610 gsl_vector_get(b, i) * gsl_matrix_get(a, i, j));
4611
4612 /* Compute A^T B A = (B^1/2 A)^T (B^1/2 A)... */
4613 gsl_blas_dgemm(CblasTrans, CblasNoTrans, 1.0, aux, aux, 0.0, c);
4614 }
4615
4616 /* Compute A B A^T... */
4617 else if (transpose == 2) {
4618
4619 /* Compute A B^1/2... */
4620 for (size_t i = 0; i < m; i++)
4621 for (size_t j = 0; j < n; j++)
4622 gsl_matrix_set(aux, i, j,
4623 gsl_matrix_get(a, i, j) * gsl_vector_get(b, j));
4624
4625 /* Compute A B A^T = (A B^1/2) (A B^1/2)^T... */
4626 gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0, aux, aux, 0.0, c);
4627 }
4628
4629 /* Free... */
4630 gsl_matrix_free(aux);
4631}

◆ obs2y()

size_t obs2y ( const ctl_t *  ctl,
const obs_t *  obs,
gsl_vector *  y,
int *  ida,
int *  ira 
)

Convert observation radiances into a measurement vector.

Extracts all finite radiance values from the observation structure and stores them sequentially in a GSL vector.
Optionally records detector (id) and ray path (ir) indices for each measurement element.

Parameters
[in]ctlControl structure containing observation setup (e.g. number of detectors).
[in]obsObservation data structure containing radiances.
[out]yMeasurement vector to store radiances (may be NULL).
[out]idaOptional array to store detector indices (may be NULL).
[out]iraOptional array to store ray path indices (may be NULL).
Returns
Number of valid (finite) radiance values added to the vector.
  • Loops over all detector channels (nd) and ray paths (nr).
  • Skips non-finite (NaN or Inf) radiance values.
  • Produces a compact measurement vector for use in retrievals and Jacobian computations.
See also
atm2x, x2atm, kernel, formod
Warning
Arrays ida and ira must be preallocated with sufficient size to hold all finite radiances if provided.
Author
Lars Hoffmann

Definition at line 4635 of file jurassic.c.

4640 {
4641
4642 size_t m = 0;
4643
4644 /* Determine measurement vector... */
4645 for (int ir = 0; ir < obs->nr; ir++)
4646 for (int id = 0; id < ctl->nd; id++)
4647 if (isfinite(obs->rad[id][ir])) {
4648 if (y != NULL)
4649 gsl_vector_set(y, m, obs->rad[id][ir]);
4650 if (ida != NULL)
4651 ida[m] = id;
4652 if (ira != NULL)
4653 ira[m] = ir;
4654 m++;
4655 }
4656
4657 return m;
4658}

◆ optimal_estimation()

void optimal_estimation ( ret_t *  ret,
ctl_t *  ctl,
tbl_t *  tbl,
obs_t *  obs_meas,
obs_t *  obs_i,
atm_t *  atm_apr,
atm_t *  atm_i,
double *  chisq 
)

Perform optimal estimation retrieval using Levenberg–Marquardt minimization.

This function performs an optimal estimation of atmospheric state variables based on measured observations, a priori information, and forward radiative transfer modeling. The estimation follows the Rodgers (2000) formalism and uses a Levenberg–Marquardt algorithm to iteratively minimize the cost function:

χ² = (x - x_a)^T S_a⁻¹ (x - x_a) + (y - F(x))^T S_ε⁻¹ (y - F(x)),

where x is the atmospheric state vector, x_a is its a priori estimate, S_a is the a priori covariance matrix, y is the measurement vector, F(x) is the forward model, and S_ε is the measurement error covariance.

The routine updates the atmospheric state until convergence criteria are met or the maximum number of iterations is reached. Optionally, the full retrieval error budget and averaging kernel analysis are computed.

Parameters
[out]retRetrieval configuration and output container. Determines convergence, kernel recomputation frequency, and error analysis options.
[in]ctlControl parameters describing problem setup (grids, species, etc.).
[in]tblLookup tables required by the forward model.
[in]obs_measMeasured observations used as input.
[out]obs_iIntermediate and final modeled observations corresponding to the retrieved state.
[in]atm_aprA priori atmospheric state used as reference.
[out]atm_iAtmospheric state vector to be iteratively retrieved and updated.
[out]chisqFinal value of the cost function (χ²) upon convergence.
Note
  • Aborts early if the problem dimension is zero (no observations or unknowns).
  • State updates are constrained to physically meaningful bounds (pressure, temperature, etc.).
  • Matrix computations are performed using GSL (GNU Scientific Library).
  • If retrieval error analysis is enabled (ret->err_ana), the function produces:
    • Retrieval covariance matrix
    • Error decomposition (noise, forward model)
    • Gain matrix
    • Averaging kernel matrix and diagnostic analysis
Warning
Input structures must be properly initialized. The function allocates several GSL matrices and vectors, all of which are freed before returning. The caller is responsible only for memory outside this function.
See also
formod(), cost_function(), analyze_avk(), set_cov_apr(), set_cov_meas()
Reference
Rodgers, C. D. (2000). Inverse Methods for Atmospheric Sounding: Theory and Practice.
Author
Lars Hoffmann

Definition at line 4662 of file jurassic.c.

4670 {
4671
4672 double disq = 0, lmpar = 0.001;
4673
4674 /* ------------------------------------------------------------
4675 Initialize...
4676 ------------------------------------------------------------ */
4677
4678 /* Allocate... */
4679 int *ipa, *iqa;
4680 ALLOC(ipa, int,
4681 N);
4682 ALLOC(iqa, int,
4683 N);
4684
4685 /* Get sizes... */
4686 const size_t m = obs2y(ctl, obs_meas, NULL, NULL, NULL);
4687 const size_t n = atm2x(ctl, atm_apr, NULL, iqa, ipa);
4688 if (m == 0 || n == 0) {
4689 WARN("Check problem definition (m = 0 or n = 0)!");
4690 *chisq = GSL_NAN;
4691 return;
4692 }
4693
4694 /* Allocate... */
4695 gsl_matrix *a = gsl_matrix_alloc(n, n);
4696 gsl_matrix *cov = gsl_matrix_alloc(n, n);
4697 gsl_matrix *k_i = gsl_matrix_alloc(m, n);
4698 gsl_matrix *s_a_inv = gsl_matrix_alloc(n, n);
4699
4700 gsl_vector *b = gsl_vector_alloc(n);
4701 gsl_vector *dx = gsl_vector_alloc(n);
4702 gsl_vector *dy = gsl_vector_alloc(m);
4703 gsl_vector *sig_eps_inv = gsl_vector_alloc(m);
4704 gsl_vector *sig_formod = gsl_vector_alloc(m);
4705 gsl_vector *sig_noise = gsl_vector_alloc(m);
4706 gsl_vector *x_a = gsl_vector_alloc(n);
4707 gsl_vector *x_i = gsl_vector_alloc(n);
4708 gsl_vector *x_step = gsl_vector_alloc(n);
4709 gsl_vector *y_aux = gsl_vector_alloc(m);
4710 gsl_vector *y_i = gsl_vector_alloc(m);
4711 gsl_vector *y_m = gsl_vector_alloc(m);
4712
4713 los_t *los_scratch;
4714 obs_t *obs_scratch;
4715 ALLOC(los_scratch, los_t, 1);
4716 ALLOC(obs_scratch, obs_t, 1);
4717
4718 /* Set timer... */
4719 SELECT_TIMER("RET_SETUP", "RETRIEVAL");
4720
4721 /* Set initial state... */
4722 copy_atm(ctl, atm_i, atm_apr, 0);
4723 copy_obs(ctl, obs_i, obs_meas, 0);
4724 if (formod(ctl, tbl, atm_i, obs_i, los_scratch, obs_scratch)
4726 ERRMSG("Forward model failed!");
4727
4728 /* Set state vectors and observation vectors... */
4729 atm2x(ctl, atm_apr, x_a, NULL, NULL);
4730 atm2x(ctl, atm_i, x_i, NULL, NULL);
4731 obs2y(ctl, obs_meas, y_m, NULL, NULL);
4732 obs2y(ctl, obs_i, y_i, NULL, NULL);
4733
4734 /* Set inverse a priori covariance S_a^-1... */
4735 set_cov_apr(ret, ctl, atm_apr, iqa, ipa, s_a_inv);
4736 int lockfd = shared_io_lock(ret);
4737 const char *dirname;
4738 int profile;
4739 const char *filename =
4741 "matrix_cov_apr.tab", &dirname, &profile);
4742 write_matrix(dirname, filename, ctl, s_a_inv,
4743 atm_i, obs_i, "x", "x", "r", profile);
4744 shared_io_unlock(lockfd);
4745 matrix_invert(s_a_inv);
4746
4747 /* Get measurement errors... */
4748 set_cov_meas(ret, ctl, obs_meas, sig_noise, sig_formod, sig_eps_inv);
4749
4750 /* Determine dx = x_i - x_a and dy = y - F(x_i) ... */
4751 gsl_vector_memcpy(dx, x_i);
4752 gsl_vector_sub(dx, x_a);
4753 gsl_vector_memcpy(dy, y_m);
4754 gsl_vector_sub(dy, y_i);
4755
4756 /* Compute cost function... */
4757 *chisq = cost_function(dx, dy, s_a_inv, sig_eps_inv);
4758
4759 /* Write info... */
4760 LOG(2, "it= %d / chi^2/m= %g", 0, *chisq);
4761
4762 /* Compute initial kernel... */
4763 SELECT_TIMER("RET_KERNEL_INIT", "RETRIEVAL");
4764 kernel(ctl, tbl, atm_i, obs_i, k_i);
4765
4766 /* ------------------------------------------------------------
4767 Levenberg-Marquardt minimization...
4768 ------------------------------------------------------------ */
4769
4770 SELECT_TIMER("RET_ITERATE", "RETRIEVAL");
4771
4772 /* Outer loop... */
4773 for (int it = 1; it <= ret->conv_itmax; it++) {
4774
4775 /* Store current cost function value... */
4776 double chisq_old = *chisq;
4777
4778 /* Compute kernel matrix K_i... */
4779 if (it > 1 && it % ret->kernel_recomp == 0)
4780 kernel(ctl, tbl, atm_i, obs_i, k_i);
4781
4782 /* Compute K_i^T * S_eps^{-1} * K_i ... */
4783 if (it == 1 || it % ret->kernel_recomp == 0)
4784 matrix_product(k_i, sig_eps_inv, 1, cov);
4785
4786 /* Determine b = K_i^T * S_eps^{-1} * dy - S_a^{-1} * dx ... */
4787 for (size_t i = 0; i < m; i++)
4788 gsl_vector_set(y_aux, i, gsl_vector_get(dy, i)
4789 * POW2(gsl_vector_get(sig_eps_inv, i)));
4790 gsl_blas_dgemv(CblasTrans, 1.0, k_i, y_aux, 0.0, b);
4791 gsl_blas_dgemv(CblasNoTrans, -1.0, s_a_inv, dx, 1.0, b);
4792
4793 /* Inner loop... */
4794 for (int it2 = 0; it2 < 20; it2++) {
4795
4796 /* Compute A = (1 + lmpar) * S_a^{-1} + K_i^T * S_eps^{-1} * K_i ... */
4797 gsl_matrix_memcpy(a, s_a_inv);
4798 gsl_matrix_scale(a, 1 + lmpar);
4799 gsl_matrix_add(a, cov);
4800
4801 /* Solve A * x_step = b by means of Cholesky decomposition... */
4802 gsl_linalg_cholesky_decomp(a);
4803 gsl_linalg_cholesky_solve(a, b, x_step);
4804
4805 /* Update atmospheric state... */
4806 gsl_vector_add(x_i, x_step);
4807 copy_atm(ctl, atm_i, atm_apr, 0);
4808 copy_obs(ctl, obs_i, obs_meas, 0);
4809 x2atm(ctl, x_i, atm_i);
4810
4811 /* Check atmospheric state... */
4812 for (int ip = 0; ip < atm_i->np; ip++) {
4813 atm_i->p[ip] = CLAMP(atm_i->p[ip], 5e-7, 5e4);
4814 atm_i->t[ip] = CLAMP(atm_i->t[ip], 100, 400);
4815 for (int ig = 0; ig < ctl->ng; ig++)
4816 atm_i->q[ig][ip] = CLAMP(atm_i->q[ig][ip], 0, 1);
4817 for (int iw = 0; iw < ctl->nw; iw++)
4818 atm_i->k[iw][ip] = MAX(atm_i->k[iw][ip], 0);
4819 }
4820 atm_i->clz = MAX(atm_i->clz, 0);
4821 atm_i->cldz = MAX(atm_i->cldz, 0.1);
4822 for (int icl = 0; icl < ctl->ncl; icl++)
4823 atm_i->clk[icl] = MAX(atm_i->clk[icl], 0);
4824 atm_i->sft = CLAMP(atm_i->sft, 100, 400);
4825 for (int isf = 0; isf < ctl->nsf; isf++)
4826 atm_i->sfeps[isf] = CLAMP(atm_i->sfeps[isf], 0, 1);
4827
4828 /* Forward calculation... */
4829 if (formod(ctl, tbl, atm_i, obs_i, los_scratch, obs_scratch)
4831 ERRMSG("Forward model failed!");
4832 obs2y(ctl, obs_i, y_i, NULL, NULL);
4833
4834 /* Determine dx = x_i - x_a and dy = y - F(x_i) ... */
4835 gsl_vector_memcpy(dx, x_i);
4836 gsl_vector_sub(dx, x_a);
4837 gsl_vector_memcpy(dy, y_m);
4838 gsl_vector_sub(dy, y_i);
4839
4840 /* Compute cost function... */
4841 *chisq = cost_function(dx, dy, s_a_inv, sig_eps_inv);
4842
4843 /* Modify Levenberg-Marquardt parameter... */
4844 if (*chisq > chisq_old) {
4845 lmpar *= 10;
4846 gsl_vector_sub(x_i, x_step);
4847 } else {
4848 lmpar /= 10;
4849 break;
4850 }
4851 }
4852
4853 /* Write info... */
4854 LOG(2, "it= %d / chi^2/m= %g", it, *chisq);
4855
4856 /* Get normalized step size in state space... */
4857 gsl_blas_ddot(x_step, b, &disq);
4858 disq /= (double) n;
4859
4860 /* Convergence test... */
4861 if ((it == 1 || it % ret->kernel_recomp == 0) && disq < ret->conv_dmin)
4862 break;
4863 }
4864
4865 /* ------------------------------------------------------------
4866 Analysis of retrieval results...
4867 ------------------------------------------------------------ */
4868
4869 /* Check if error analysis is requested... */
4870 if (ret->err_ana) {
4871
4872 SELECT_TIMER("RET_DIAGNOSTICS", "OUTPUT");
4873
4874 /* Store results... */
4875 lockfd = shared_io_lock(ret);
4877 "atm_final.tab", &dirname, &profile);
4878 write_atm(dirname, filename, ctl, atm_i, profile);
4880 "obs_final.tab", &dirname, &profile);
4881 write_obs(dirname, filename, ctl, obs_i, profile);
4882 filename =
4884 "matrix_kernel.tab", &dirname, &profile);
4885 write_matrix(dirname, filename, ctl, k_i,
4886 atm_i, obs_i, "y", "x", "r", profile);
4887
4888 /* Allocate... */
4889 gsl_matrix *auxnm = gsl_matrix_alloc(n, m);
4890 gsl_matrix *corr = gsl_matrix_alloc(n, n);
4891 gsl_matrix *gain = gsl_matrix_alloc(n, m);
4892
4893 /* Compute inverse retrieval covariance...
4894 cov^{-1} = S_a^{-1} + K_i^T * S_eps^{-1} * K_i */
4895 matrix_product(k_i, sig_eps_inv, 1, cov);
4896 gsl_matrix_add(cov, s_a_inv);
4897
4898 /* Compute retrieval covariance... */
4899 matrix_invert(cov);
4900 filename =
4902 "matrix_cov_ret.tab", &dirname, &profile);
4903 write_matrix(dirname, filename, ctl, cov,
4904 atm_i, obs_i, "x", "x", "r", profile);
4905 write_stddev("total", ret, ctl, atm_i, cov);
4906
4907 /* Compute correlation matrix... */
4908 for (size_t i = 0; i < n; i++)
4909 for (size_t j = 0; j < n; j++)
4910 gsl_matrix_set(corr, i, j, gsl_matrix_get(cov, i, j)
4911 / sqrt(gsl_matrix_get(cov, i, i))
4912 / sqrt(gsl_matrix_get(cov, j, j)));
4914 "matrix_corr.tab", &dirname, &profile);
4915 write_matrix(dirname, filename, ctl, corr,
4916 atm_i, obs_i, "x", "x", "r", profile);
4917
4918 /* Compute gain matrix...
4919 G = cov * K^T * S_eps^{-1} */
4920 for (size_t i = 0; i < n; i++)
4921 for (size_t j = 0; j < m; j++)
4922 gsl_matrix_set(auxnm, i, j, gsl_matrix_get(k_i, j, i)
4923 * POW2(gsl_vector_get(sig_eps_inv, j)));
4924 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, cov, auxnm, 0.0, gain);
4926 "matrix_gain.tab", &dirname, &profile);
4927 write_matrix(dirname, filename, ctl, gain,
4928 atm_i, obs_i, "x", "y", "c", profile);
4929
4930 /* Compute retrieval error due to noise... */
4931 matrix_product(gain, sig_noise, 2, a);
4932 write_stddev("noise", ret, ctl, atm_i, a);
4933
4934 /* Compute retrieval error due to forward model errors... */
4935 matrix_product(gain, sig_formod, 2, a);
4936 write_stddev("formod", ret, ctl, atm_i, a);
4937
4938 /* Compute averaging kernel matrix
4939 A = G * K ... */
4940 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, gain, k_i, 0.0, a);
4942 "matrix_avk.tab", &dirname, &profile);
4943 write_matrix(dirname, filename, ctl, a,
4944 atm_i, obs_i, "x", "x", "r", profile);
4945
4946 /* Analyze averaging kernel matrix... */
4947 analyze_avk(ret, ctl, atm_i, iqa, ipa, a);
4948 shared_io_unlock(lockfd);
4949
4950 /* Free... */
4951 gsl_matrix_free(auxnm);
4952 gsl_matrix_free(corr);
4953 gsl_matrix_free(gain);
4954 }
4955
4956 /* ------------------------------------------------------------
4957 Finalize...
4958 ------------------------------------------------------------ */
4959
4960 gsl_matrix_free(a);
4961 gsl_matrix_free(cov);
4962 gsl_matrix_free(k_i);
4963 gsl_matrix_free(s_a_inv);
4964
4965 gsl_vector_free(b);
4966 gsl_vector_free(dx);
4967 gsl_vector_free(dy);
4968 gsl_vector_free(sig_eps_inv);
4969 gsl_vector_free(sig_formod);
4970 gsl_vector_free(sig_noise);
4971 gsl_vector_free(x_a);
4972 gsl_vector_free(x_i);
4973 gsl_vector_free(x_step);
4974 gsl_vector_free(y_aux);
4975 gsl_vector_free(y_i);
4976 gsl_vector_free(y_m);
4977 free(los_scratch);
4978 free(obs_scratch);
4979
4980 free(ipa);
4981 free(iqa);
4982}
void analyze_avk(const ret_t *ret, const ctl_t *ctl, const atm_t *atm, const int *iqa, const int *ipa, const gsl_matrix *avk)
Analyze averaging kernel (AVK) matrix for retrieval diagnostics.
Definition: jurassic.c:29
double cost_function(const gsl_vector *dx, const gsl_vector *dy, const gsl_matrix *s_a_inv, const gsl_vector *sig_eps_inv)
Compute the normalized quadratic cost function for optimal estimation.
Definition: jurassic.c:1193
int shared_io_lock(const ret_t *ret)
Acquire an exclusive lock for shared retrieval output files.
Definition: jurassic.c:6881
void matrix_product(const gsl_matrix *a, const gsl_vector *b, const int transpose, gsl_matrix *c)
Compute structured matrix products of the form or .
Definition: jurassic.c:4590
void write_matrix(const char *dirname, const char *filename, const ctl_t *ctl, const gsl_matrix *matrix, const atm_t *atm, const obs_t *obs, const char *rowspace, const char *colspace, const char *sort, int dataset)
Write a fully annotated matrix (e.g., Jacobian or gain matrix) to file.
Definition: jurassic.c:7754
void shared_io_unlock(int fd)
Release a shared retrieval output lock.
Definition: jurassic.c:6908
void set_cov_meas(const ret_t *ret, const ctl_t *ctl, const obs_t *obs, gsl_vector *sig_noise, gsl_vector *sig_formod, gsl_vector *sig_eps_inv)
Construct measurement error standard deviations and their inverse.
Definition: jurassic.c:6792
void write_obs(const char *dirname, const char *filename, const ctl_t *ctl, const obs_t *obs, int profile)
Write observation data to an output file in ASCII or binary format.
Definition: jurassic.c:8276
void kernel(const ctl_t *ctl, const tbl_t *tbl, atm_t *atm, obs_t *obs, gsl_matrix *k)
Compute the Jacobian (kernel) matrix by finite differences.
Definition: jurassic.c:4367
void matrix_invert(gsl_matrix *a)
Invert a square matrix, optimized for diagonal or symmetric positive-definite matrices.
Definition: jurassic.c:4560
void set_cov_apr(const ret_t *ret, const ctl_t *ctl, const atm_t *atm, const int *iqa, const int *ipa, gsl_matrix *s_a)
Construct the a priori covariance matrix for retrieval parameters.
Definition: jurassic.c:6681
void write_stddev(const char *quantity, const ret_t *ret, const ctl_t *ctl, const atm_t *atm, const gsl_matrix *s)
Write retrieval standard deviation profiles to disk.
Definition: jurassic.c:8680
#define SELECT_TIMER(id, group)
Switch to a named aggregated timer.
Definition: jurassic.h:1189
char shared_io_atm_final_file[LEN]
Optional shared retrieved-atmosphere output file.
Definition: jurassic.h:1830
int err_ana
Carry out error analysis (0=no, 1=yes).
Definition: jurassic.h:1758
char shared_io_matrix_cov_apr_file[LEN]
Optional shared a priori covariance output file.
Definition: jurassic.h:1836
double conv_dmin
Minimum normalized step size in state space.
Definition: jurassic.h:1755
char shared_io_matrix_gain_file[LEN]
Optional shared gain matrix output file.
Definition: jurassic.h:1848
char shared_io_matrix_cov_ret_file[LEN]
Optional shared retrieval covariance output file.
Definition: jurassic.h:1842
char shared_io_matrix_kernel_file[LEN]
Optional shared kernel matrix output file.
Definition: jurassic.h:1839
char shared_io_matrix_avk_file[LEN]
Optional shared averaging-kernel matrix output file.
Definition: jurassic.h:1851
int kernel_recomp
Re-computation of kernel matrix (number of iterations).
Definition: jurassic.h:1749
int conv_itmax
Maximum number of iterations.
Definition: jurassic.h:1752
char shared_io_matrix_corr_file[LEN]
Optional shared correlation matrix output file.
Definition: jurassic.h:1845
char shared_io_obs_final_file[LEN]
Optional shared retrieved-observation output file.
Definition: jurassic.h:1833
Here is the call graph for this function:

◆ raytrace()

int raytrace ( const ctl_t *  ctl,
const atm_t *  atm,
obs_t *  obs,
los_t *  los,
const int  ir 
)

Perform line-of-sight (LOS) ray tracing through the atmosphere.

Computes the geometric path of a viewing ray from the observer to the atmosphere (and possibly the surface), accounting for spherical geometry, optional refraction, and cloud or surface interactions.
Fills the LOS structure with pressure, temperature, gas concentrations, extinction, and path length at each step.

Parameters
[in]ctlControl structure containing model and numerical settings.
[in]atmAtmospheric state structure (profiles of p, T, q, k, etc.).
[in,out]obsObservation geometry and radiance data; updated tangent point.
[out]losLine-of-sight structure to be populated with sampled quantities.
[in]irIndex of the current ray path in the observation set.
Returns
FORMOD_STATUS_OK on success, FORMOD_STATUS_OBSERVER_BELOW_SURFACE if the observer lies below the surface, or FORMOD_STATUS_TOO_MANY_LOS_POINTS if the number of LOS points would exceed NLOS.
  • Integrates along the viewing ray starting at the observer position.
  • Performs stepwise propagation with step length ds determined by altitude and user-specified controls (rayds, raydz).
  • Interpolates atmospheric variables at each step using intpol_atm.
  • Detects surface intersection or top-of-atmosphere exit and terminates accordingly.
  • Optionally accounts for refraction via a dry-air refractive index n(p, T) based on an Edlen-type relation evaluated at a fixed reference wavelength of 10 um, consistent with the published RFM algorithm.
  • Accumulates column densities and Curtis–Godson means for each gas.
  • Supports cloud extinction and surface emissivity interpolation.
Note
The routine enforces that atmospheric grids include the surface (z = 0 km). Rays starting above the atmosphere are propagated downward until entry.
See also
intpol_atm, tangent_point, formod_pencil, hydrostatic
Warning
  • Returns an error status if the observer is below the surface or the number of LOS points exceeds NLOS.
  • Requires that the atmosphere includes z = 0.
  • Assumes monotonic altitude ordering in atmospheric data.
Author
Lars Hoffmann

Definition at line 4986 of file jurassic.c.

4991 {
4992
4993 const double h = 0.02, zrefrac = 60;
4994
4995 double ex0[3], ex1[3], k[NW], lat, lon, n, ng[3], norm, p, q[NG], t,
4996 x[3], xh[3], xobs[3], xvp[3], z = 1e99, zmax, zmin;
4997
4998 int stop = 0;
4999
5000 /* Initialize... */
5001 los->np = 0;
5002 los->sft = -999;
5003 obs->tpz[ir] = obs->vpz[ir];
5004 obs->tplon[ir] = obs->vplon[ir];
5005 obs->tplat[ir] = obs->vplat[ir];
5006
5007 /* Get altitude range of atmospheric data... */
5008 gsl_stats_minmax(&zmin, &zmax, atm->z, 1, (size_t) atm->np);
5009
5010 /* Check observer altitude... */
5011 if (obs->obsz[ir] < zmin)
5013
5014 /* Determine Cartesian coordinates for observer and view point... */
5015 geo2cart(obs->obsz[ir], obs->obslon[ir], obs->obslat[ir], xobs);
5016 geo2cart(obs->vpz[ir], obs->vplon[ir], obs->vplat[ir], xvp);
5017
5018 /* Determine initial tangent vector... */
5019 for (int i = 0; i < 3; i++)
5020 ex0[i] = xvp[i] - xobs[i];
5021 norm = NORM(ex0);
5022 for (int i = 0; i < 3; i++)
5023 ex0[i] /= norm;
5024
5025 /* Observer within atmosphere... */
5026 for (int i = 0; i < 3; i++)
5027 x[i] = xobs[i];
5028
5029 /* Observer above atmosphere (search entry point)... */
5030 if (obs->obsz[ir] > zmax) {
5031 double dmax = norm, dmin = 0;
5032 while (fabs(dmin - dmax) > 0.001) {
5033 const double d = (dmax + dmin) / 2;
5034 for (int i = 0; i < 3; i++)
5035 x[i] = xobs[i] + d * ex0[i];
5036 cart2geo(x, &z, &lon, &lat);
5037 if (z <= zmax && z > zmax - 0.001)
5038 break;
5039 if (z < zmax - 0.0005)
5040 dmax = d;
5041 else
5042 dmin = d;
5043 }
5044 }
5045
5046 /* Ray-tracing... */
5047 while (1) {
5048
5049 /* Set step length... */
5050 double ds = ctl->rayds;
5051 if (ctl->raydz > 0) {
5052 norm = NORM(x);
5053 for (int i = 0; i < 3; i++)
5054 xh[i] = x[i] / norm;
5055 const double cosa = fabs(DOTP(ex0, xh));
5056 if (cosa != 0)
5057 ds = MIN(ctl->rayds, ctl->raydz / cosa);
5058 }
5059
5060 /* Determine geolocation... */
5061 cart2geo(x, &z, &lon, &lat);
5062
5063 /* Check if LOS hits the ground or has left atmosphere... */
5064 if (z < zmin || z > zmax) {
5065 stop = (z < zmin ? 2 : 1);
5066 const double frac =
5067 ((z <
5068 zmin ? zmin : zmax) - los->z[los->np - 1]) / (z - los->z[los->np -
5069 1]);
5070 geo2cart(los->z[los->np - 1], los->lon[los->np - 1],
5071 los->lat[los->np - 1], xh);
5072 for (int i = 0; i < 3; i++)
5073 x[i] = xh[i] + frac * (x[i] - xh[i]);
5074 cart2geo(x, &z, &lon, &lat);
5075 los->ds[los->np - 1] = ds * frac;
5076 ds = 0;
5077 }
5078
5079 /* Interpolate atmospheric data... */
5080 intpol_atm(ctl, atm, z, &p, &t, q, k);
5081
5082 /* Abort before writing beyond the fixed LOS scratch buffers... */
5083 if (los->np >= NLOS)
5085
5086 /* Save data... */
5087 los->lon[los->np] = lon;
5088 los->lat[los->np] = lat;
5089 los->z[los->np] = z;
5090 los->p[los->np] = p;
5091 los->t[los->np] = t;
5092 for (int ig = 0; ig < ctl->ng; ig++)
5093 los->q[los->np][ig] = q[ig];
5094 for (int id = 0; id < ctl->nd; id++)
5095 los->k[los->np][id] = k[ctl->window[id]];
5096 los->ds[los->np] = ds;
5097
5098 /* Add cloud extinction... */
5099 if (ctl->ncl > 0 && atm->cldz > 0) {
5100 const double aux = exp(-0.5 * POW2((z - atm->clz) / atm->cldz));
5101 for (int id = 0; id < ctl->nd; id++) {
5102 const int icl = locate_irr(ctl->clnu, ctl->ncl, ctl->nu[id]);
5103 los->k[los->np][id]
5104 += aux * LIN(ctl->clnu[icl], atm->clk[icl],
5105 ctl->clnu[icl + 1], atm->clk[icl + 1], ctl->nu[id]);
5106 }
5107 }
5108
5109 /* Increment number of LOS points... */
5110 los->np++;
5111
5112 /* Check stop flag... */
5113 if (stop) {
5114
5115 /* Set surface temperature... */
5116 if (ctl->nsf > 0 && atm->sft > 0)
5117 t = atm->sft;
5118 los->sft = (stop == 2 ? t : -999);
5119
5120 /* Set surface emissivity... */
5121 for (int id = 0; id < ctl->nd; id++) {
5122 los->sfeps[id] = 1.0;
5123 if (ctl->nsf > 0) {
5124 const int isf = locate_irr(ctl->sfnu, ctl->nsf, ctl->nu[id]);
5125 los->sfeps[id] = LIN(ctl->sfnu[isf], atm->sfeps[isf],
5126 ctl->sfnu[isf + 1], atm->sfeps[isf + 1],
5127 ctl->nu[id]);
5128 }
5129 }
5130
5131 /* Leave raytracer... */
5132 break;
5133 }
5134
5135 /* Determine refractivity... */
5136 if (ctl->refrac && z <= zrefrac)
5137 n = 1 + REFRAC_EDLEN(p, t);
5138 else
5139 n = 1;
5140
5141 /* Construct new tangent vector (first term)... */
5142 for (int i = 0; i < 3; i++)
5143 ex1[i] = ex0[i] * n;
5144
5145 /* Compute gradient of refractivity... */
5146 if (ctl->refrac && z <= zrefrac) {
5147 for (int i = 0; i < 3; i++)
5148 xh[i] = x[i] + 0.5 * ds * ex0[i];
5149 cart2geo(xh, &z, &lon, &lat);
5150 intpol_atm(ctl, atm, z, &p, &t, q, k);
5151 n = REFRAC_EDLEN(p, t);
5152 for (int i = 0; i < 3; i++) {
5153 xh[i] += h;
5154 cart2geo(xh, &z, &lon, &lat);
5155 intpol_atm(ctl, atm, z, &p, &t, q, k);
5156 ng[i] = (REFRAC_EDLEN(p, t) - n) / h;
5157 xh[i] -= h;
5158 }
5159 } else
5160 for (int i = 0; i < 3; i++)
5161 ng[i] = 0;
5162
5163 /* Construct new tangent vector (second term)... */
5164 for (int i = 0; i < 3; i++)
5165 ex1[i] += ds * ng[i];
5166
5167 /* Normalize new tangent vector... */
5168 norm = NORM(ex1);
5169 for (int i = 0; i < 3; i++)
5170 ex1[i] /= norm;
5171
5172 /* Determine next point of LOS... */
5173 for (int i = 0; i < 3; i++)
5174 x[i] += 0.5 * ds * (ex0[i] + ex1[i]);
5175
5176 /* Copy tangent vector... */
5177 for (int i = 0; i < 3; i++)
5178 ex0[i] = ex1[i];
5179 }
5180
5181 /* Get tangent point (to be done before changing segment lengths!)... */
5182 tangent_point(los, &obs->tpz[ir], &obs->tplon[ir], &obs->tplat[ir]);
5183
5184 /* Change segment lengths according to trapezoid rule... */
5185 for (int ip = los->np - 1; ip >= 1; ip--)
5186 los->ds[ip] = 0.5 * (los->ds[ip - 1] + los->ds[ip]);
5187 los->ds[0] *= 0.5;
5188
5189 /* Compute column density... */
5190 for (int ip = 0; ip < los->np; ip++)
5191 for (int ig = 0; ig < ctl->ng; ig++)
5192 los->u[ip][ig] = 10 * los->q[ip][ig] * los->p[ip]
5193 / (KB * los->t[ip]) * los->ds[ip];
5194
5195 /* Compute Curtis-Godson means... */
5196 for (int ig = 0; ig < ctl->ng; ig++) {
5197 los->cgu[0][ig] = los->u[0][ig];
5198 los->cgp[0][ig] = los->u[0][ig] * los->p[0];
5199 los->cgt[0][ig] = los->u[0][ig] * los->t[0];
5200 }
5201 for (int ip = 1; ip < los->np; ip++)
5202 for (int ig = 0; ig < ctl->ng; ig++) {
5203 los->cgu[ip][ig] = los->cgu[ip - 1][ig] + los->u[ip][ig];
5204 los->cgp[ip][ig] = los->cgp[ip - 1][ig] + los->u[ip][ig] * los->p[ip];
5205 los->cgt[ip][ig] = los->cgt[ip - 1][ig] + los->u[ip][ig] * los->t[ip];
5206 }
5207 for (int ip = 0; ip < los->np; ip++)
5208 for (int ig = 0; ig < ctl->ng; ig++)
5209 if (los->cgu[ip][ig] != 0) {
5210 los->cgp[ip][ig] /= los->cgu[ip][ig];
5211 los->cgt[ip][ig] /= los->cgu[ip][ig];
5212 }
5213
5214 return FORMOD_STATUS_OK;
5215}
void intpol_atm(const ctl_t *ctl, const atm_t *atm, const double z, double *p, double *t, double *q, double *k)
Interpolate atmospheric state variables at a given altitude.
Definition: jurassic.c:4023
void tangent_point(const los_t *los, double *tpz, double *tplon, double *tplat)
Determine the tangent point along a line of sight (LOS).
Definition: jurassic.c:6960
void cart2geo(const double *x, double *z, double *lon, double *lat)
Converts Cartesian coordinates to geographic coordinates.
Definition: jurassic.c:200
#define KB
Boltzmann constant [kg m^2/(K s^2)].
Definition: jurassic.h:202
#define REFRAC_EDLEN(p, T)
Compute dry-air refractivity (n - 1) with an Edlen-type relation.
Definition: jurassic.h:1135
#define NLOS
Maximum number of LOS points.
Definition: jurassic.h:311
#define NW
Maximum number of spectral windows.
Definition: jurassic.h:346
int window[ND]
Window index of each channel.
Definition: jurassic.h:1489
double rayds
Maximum step length for raytracing [km].
Definition: jurassic.h:1543
double raydz
Vertical step length for raytracing [km].
Definition: jurassic.h:1546
Here is the call graph for this function:

◆ read_atm()

void read_atm ( const char *  dirname,
const char *  filename,
const ctl_t *  ctl,
atm_t *  atm,
int  profile 
)

Read atmospheric input data from a file.

This function reads atmospheric data from the file specified by filename, optionally prefixed by the directory dirname. The file format (ASCII or binary) is determined by the control structure ctl. The data are stored in the atmospheric structure atm.

Supported file formats are:

  • ASCII format (ctl->atmfmt == 1)
  • Binary format (ctl->atmfmt == 2)

The function initializes the atmospheric data container, opens the specified file, reads its contents according to the selected format, and performs sanity checks on the number of data points. It also logs basic statistical information about the loaded atmospheric fields (time, altitude, longitude, latitude, pressure, temperature, and species/emitter mixing ratios).

Parameters
dirnameOptional directory path where the atmospheric file resides. If NULL, only filename is used.
filenameName of the atmospheric data file to read.
ctlPointer to a control structure specifying input parameters, file format, number of emitters, spectral windows, and additional atmospheric configuration.
atmPointer to an atmospheric data structure that will be filled with the values read from the file. The structure must be allocated before calling this function.
profileZero-based profile index for netCDF input. Ignored for ASCII and binary formats.
Note
The function aborts execution using ERRMSG on critical errors, such as failure to open the file, unknown file format, or absence of readable data.
Warning
Ensure that the atm structure has been properly allocated, and that the control parameters in ctl are valid before calling this function.
Author
Lars Hoffmann

Definition at line 5219 of file jurassic.c.

5224 {
5225
5226 /* Init... */
5227 atm->np = 0;
5228
5229 /* Set filename... */
5230 char file[LEN];
5231 if (dirname != NULL)
5232 sprintf(file, "%s/%s", dirname, filename);
5233 else
5234 sprintf(file, "%s", filename);
5235
5236 /* Write info... */
5237 LOG(1, "Read atmospheric data: %s", file);
5238
5239 /* Read ASCII data... */
5240 if (ctl->atmfmt == 1)
5241 read_atm_asc(file, ctl, atm);
5242
5243 /* Read binary data... */
5244 else if (ctl->atmfmt == 2)
5245 read_atm_bin(file, ctl, atm);
5246
5247 /* Read netCDF data... */
5248 else if (ctl->atmfmt == 3)
5249 read_atm_nc(file, ctl, atm, profile);
5250
5251 /* Check number of points... */
5252 if (atm->np < 1)
5253 ERRMSG("Could not read any data!");
5254
5255 /* Write info... */
5256 double mini, maxi;
5257 LOG(2, "Number of data points: %d", atm->np);
5258 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
5259 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
5260 gsl_stats_minmax(&mini, &maxi, atm->z, 1, (size_t) atm->np);
5261 LOG(2, "Altitude range: %g ... %g km", mini, maxi);
5262 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
5263 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
5264 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
5265 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
5266 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
5267 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
5268 gsl_stats_minmax(&mini, &maxi, atm->t, 1, (size_t) atm->np);
5269 LOG(2, "Temperature range: %g ... %g K", mini, maxi);
5270 for (int ig = 0; ig < ctl->ng; ig++) {
5271 gsl_stats_minmax(&mini, &maxi, atm->q[ig], 1, (size_t) atm->np);
5272 LOG(2, "Emitter %s range: %g ... %g ppv", ctl->emitter[ig], mini, maxi);
5273 }
5274 for (int iw = 0; iw < ctl->nw; iw++) {
5275 gsl_stats_minmax(&mini, &maxi, atm->k[iw], 1, (size_t) atm->np);
5276 LOG(2, "Extinction range (window %d): %g ... %g km^-1", iw, mini, maxi);
5277 }
5278 if (ctl->ncl > 0) {
5279 LOG(2, "Cloud layer: z= %g km | dz= %g km | k= %g ... %g km^-1",
5280 atm->clz, atm->cldz, atm->clk[0], atm->clk[ctl->ncl - 1]);
5281 } else
5282 LOG(2, "Cloud layer: none");
5283 if (ctl->nsf > 0) {
5284 LOG(2,
5285 "Surface: T_s = %g K | eps= %g ... %g",
5286 atm->sft, atm->sfeps[0], atm->sfeps[ctl->nsf - 1]);
5287 } else
5288 LOG(2, "Surface: none");
5289}
void read_atm_bin(const char *filename, const ctl_t *ctl, atm_t *atm)
Read atmospheric data in binary format.
Definition: jurassic.c:5344
void read_atm_asc(const char *filename, const ctl_t *ctl, atm_t *atm)
Read atmospheric data in ASCII format.
Definition: jurassic.c:5293
void read_atm_nc(const char *filename, const ctl_t *ctl, atm_t *atm, int profile)
Read one atmospheric profile from a netCDF file.
Definition: jurassic.c:5438
int atmfmt
Atmospheric data file format (1=ASCII, 2=binary, 3=netCDF).
Definition: jurassic.h:1516
Here is the call graph for this function:

◆ read_atm_asc()

void read_atm_asc ( const char *  filename,
const ctl_t *  ctl,
atm_t *  atm 
)

Read atmospheric data in ASCII format.

This function reads and parses atmospheric input data from an ASCII file specified by its filename and stores the values in the atmospheric structure atm. The number and type of fields to read are determined by the control structure ctl. Each line of the ASCII file corresponds to a single atmospheric data point.

The expected order of fields in each line is:

  • Time
  • Altitude
  • Longitude
  • Latitude
  • Pressure
  • Temperature
  • Mixing ratios for each gas/emitter (ctl->ng values)
  • Extinction coefficients for each spectral window (ctl->nw values)

Additionally, if cloud or surface layer parameters are enabled in ctl, they are read once from the first line only:

  • Cloud layer: altitude, thickness, and extinction (ctl->ncl values)
  • Surface layer: temperature and emissivity (ctl->nsf values)
Parameters
filenamePath to the ASCII file containing atmospheric data.
ctlPointer to a control structure defining the number of gases, spectral windows, and whether cloud or surface layer information should be read.
atmPointer to an initialized atmospheric structure where the parsed data points will be stored. The function updates atm->np to reflect the number of successfully read data records.
Note
The function reads until end-of-file is reached. Each successfully parsed line increments the atmospheric data point counter.
Warning
The function terminates execution using ERRMSG if more than NP data points are encountered, or if the input format deviates from expectations.
Author
Lars Hoffmann

Definition at line 5293 of file jurassic.c.

5296 {
5297
5298 /* Init... */
5299 atm->np = 0;
5300
5301 /* Open file... */
5302 FILE *in;
5303 if (!(in = fopen(filename, "r")))
5304 ERRMSG("Cannot open file!");
5305
5306 /* Read line... */
5307 char line[LEN], *tok;
5308 while (fgets(line, LEN, in)) {
5309
5310 /* Read data... */
5311 TOK(line, tok, "%lg", atm->time[atm->np]);
5312 TOK(NULL, tok, "%lg", atm->z[atm->np]);
5313 TOK(NULL, tok, "%lg", atm->lon[atm->np]);
5314 TOK(NULL, tok, "%lg", atm->lat[atm->np]);
5315 TOK(NULL, tok, "%lg", atm->p[atm->np]);
5316 TOK(NULL, tok, "%lg", atm->t[atm->np]);
5317 for (int ig = 0; ig < ctl->ng; ig++)
5318 TOK(NULL, tok, "%lg", atm->q[ig][atm->np]);
5319 for (int iw = 0; iw < ctl->nw; iw++)
5320 TOK(NULL, tok, "%lg", atm->k[iw][atm->np]);
5321 if (ctl->ncl > 0 && atm->np == 0) {
5322 TOK(NULL, tok, "%lg", atm->clz);
5323 TOK(NULL, tok, "%lg", atm->cldz);
5324 for (int icl = 0; icl < ctl->ncl; icl++)
5325 TOK(NULL, tok, "%lg", atm->clk[icl]);
5326 }
5327 if (ctl->nsf > 0 && atm->np == 0) {
5328 TOK(NULL, tok, "%lg", atm->sft);
5329 for (int isf = 0; isf < ctl->nsf; isf++)
5330 TOK(NULL, tok, "%lg", atm->sfeps[isf]);
5331 }
5332
5333 /* Increment data point counter... */
5334 if ((++atm->np) > NP)
5335 ERRMSG("Too many data points!");
5336 }
5337
5338 /* Close file... */
5339 fclose(in);
5340}
#define TOK(line, tok, format, var)
Tokenize a string and parse a variable.
Definition: jurassic.h:1220
#define NP
Maximum number of atmospheric data points.
Definition: jurassic.h:316

◆ read_atm_bin()

void read_atm_bin ( const char *  filename,
const ctl_t *  ctl,
atm_t *  atm 
)

Read atmospheric data in binary format.

This function reads atmospheric input data from a binary file specified by its filename and stores the decoded values in the atmospheric structure atm. The expected binary format is predefined and must match the configuration provided in the control structure ctl. The function reads a header containing metadata describing the dataset, followed by the atmospheric fields and optional cloud and surface layer properties.

The binary file layout is expected to follow this structure:

  1. Magic identifier (4 bytes, ignored except for presence)
  2. Header integers:
    • Number of gas species (ng)
    • Number of spectral windows (nw)
    • Number of cloud layer extinction elements (ncl)
    • Number of surface emissivity elements (nsf) These must match the corresponding values in ctl.
  3. Data payload:
    • Number of points (np)
    • Arrays of size np for time, altitude, longitude, latitude, pressure, and temperature
    • For each gas species: mixing ratio array of length np
    • For each spectral window: extinction coefficient array of length np
  4. Optional layered parameters:
    • Cloud layer altitude, thickness, and extinction (ctl->ncl values)
    • Surface temperature and emissivity (ctl->nsf values)
Parameters
filenamePath to the binary file containing atmospheric data.
ctlPointer to a control structure specifying the expected dimensions of atmospheric fields and optional layers. Used for header validation.
atmPointer to an allocated atmospheric data structure that will be filled with the contents of the binary file. All arrays must be allocated prior to calling this function.
Note
This function does not allocate memory; it assumes storage for all atmospheric variables already exists and matches the expected sizes.
Warning
Execution is terminated via ERRMSG if:
  • The binary header does not match the control structure.
  • The binary file does not contain the expected amount of data.
Author
Lars Hoffmann

Definition at line 5344 of file jurassic.c.

5347 {
5348
5349 /* Open file... */
5350 FILE *in;
5351 if (!(in = fopen(filename, "r")))
5352 ERRMSG("Cannot open file!");
5353
5354 /* Read header... */
5355 char magic[4];
5356 FREAD(magic, char,
5357 4,
5358 in);
5359 if (memcmp(magic, "ATM1", 4) != 0)
5360 ERRMSG("Invalid magic string!");
5361
5362 int ng, nw, ncl, nsf;
5363 FREAD(&ng, int,
5364 1,
5365 in);
5366 FREAD(&nw, int,
5367 1,
5368 in);
5369 FREAD(&ncl, int,
5370 1,
5371 in);
5372 FREAD(&nsf, int,
5373 1,
5374 in);
5375 if (ng != ctl->ng || nw != ctl->nw || ncl != ctl->ncl || nsf != ctl->nsf)
5376 ERRMSG("Error reading file header!");
5377
5378 /* Read data... */
5379 size_t np;
5380 FREAD(&np, size_t,
5381 1,
5382 in);
5383 atm->np = (int) np;
5384 if (atm->np > NP)
5385 ERRMSG("Too many data points!");
5386 FREAD(atm->time, double,
5387 np,
5388 in);
5389 FREAD(atm->z, double,
5390 np,
5391 in);
5392 FREAD(atm->lon, double,
5393 np,
5394 in);
5395 FREAD(atm->lat, double,
5396 np,
5397 in);
5398 FREAD(atm->p, double,
5399 np,
5400 in);
5401 FREAD(atm->t, double,
5402 np,
5403 in);
5404 for (int ig = 0; ig < ctl->ng; ig++)
5405 FREAD(atm->q[ig], double,
5406 np,
5407 in);
5408 for (int iw = 0; iw < ctl->nw; iw++)
5409 FREAD(atm->k[iw], double,
5410 np,
5411 in);
5412 if (ctl->ncl > 0) {
5413 FREAD(&atm->clz, double,
5414 1,
5415 in);
5416 FREAD(&atm->cldz, double,
5417 1,
5418 in);
5419 FREAD(atm->clk, double,
5420 (size_t) ctl->ncl,
5421 in);
5422 }
5423 if (ctl->nsf) {
5424 FREAD(&atm->sft, double,
5425 1,
5426 in);
5427 FREAD(atm->sfeps, double,
5428 (size_t) ctl->nsf,
5429 in);
5430 }
5431
5432 /* Close file... */
5433 fclose(in);
5434}
#define FREAD(ptr, type, size, out)
Read binary data from a file.
Definition: jurassic.h:586

◆ read_atm_nc()

void read_atm_nc ( const char *  filename,
const ctl_t *  ctl,
atm_t *  atm,
int  profile 
)

Read one atmospheric profile from a netCDF file.

This routine reads a single profile (record) from a netCDF file into an atm_t structure. The file is expected to follow the JURASSIC netCDF layout produced by write_atm_nc(), using an unlimited profile dimension and a fixed level dimension.

The number of valid vertical levels for the requested profile is read from nlev(profile) and stored in atm->np. All 2-D profile variables are then read for the hyperslab (profile,0:atm->np-1).

File layout (expected)

Dimensions:

  • profile : unlimited (record dimension)
  • level : fixed (maximum number of vertical levels stored in the file)

Variables:

  • nlev(profile) : number of valid levels per profile (required)
  • Core state (2-D): time,z,lon,lat,p,t(profile,level)
  • Trace gases (2-D): one variable per species named ctl->emitter[ig] with dimensions (profile,level)
  • Extinction windows (2-D): ext_win_d(profile,level)
  • Clouds (1-D, optional if ctl->ncl>0): cld_z, cld_dz, cld_k_%.4f(profile)
  • Surface (1-D, optional if ctl->nsf>0): srf_t, srf_eps_%.4f(profile)
Parameters
filenameInput netCDF file name.
ctlControl structure (defines numbers/names of optional fields, e.g., ng, nw, ncl, nsf, and emitter[]).
atmAtmospheric profile structure to fill. On return, atm->np contains the number of valid levels for the requested profile.
profileRecord index along the unlimited profile dimension.
Note
This function assumes that arrays in atm have static capacity NP and checks that atm->np is within [1,NP]. Errors are handled via the NC(...) macro.
Author
Lars Hoffmann

Definition at line 5438 of file jurassic.c.

5442 {
5443
5444 int ncid, var_time, var_z, var_lon, var_lat, var_p, var_t, var_q[NG],
5445 var_k[NW], var_cz = -1, var_cdz = -1, var_ck[NCL], var_sft =
5446 -1, var_sfe[NSF], var_nlev = -1;
5447
5448 char varname[LEN];
5449
5450 /* Open file... */
5451 NC(nc_open(filename, NC_NOWRITE, &ncid));
5452
5453 /* Initialize hyperslab... */
5454 size_t start[2] = { (size_t) profile, 0 };
5455 size_t count[2] = { 1, 0 };
5456
5457 /* Determine atm->np... */
5458 NC(nc_inq_varid(ncid, "nlev", &var_nlev));
5459 NC(nc_get_vara_int(ncid, var_nlev, start, count, &atm->np));
5460 if (atm->np < 1 || atm->np > NP)
5461 ERRMSG("Number of level out of range!");
5462
5463 /* Update hyperslab... */
5464 count[1] = (size_t) atm->np;
5465
5466 /* Inquire core variables... */
5467 NC(nc_inq_varid(ncid, "time", &var_time));
5468 NC(nc_inq_varid(ncid, "z", &var_z));
5469 NC(nc_inq_varid(ncid, "lon", &var_lon));
5470 NC(nc_inq_varid(ncid, "lat", &var_lat));
5471 NC(nc_inq_varid(ncid, "p", &var_p));
5472 NC(nc_inq_varid(ncid, "t", &var_t));
5473
5474 /* Inquire emiters... */
5475 for (int ig = 0; ig < ctl->ng; ig++)
5476 NC(nc_inq_varid(ncid, ctl->emitter[ig], &var_q[ig]));
5477
5478 /* Inquire extinctions... */
5479 for (int iw = 0; iw < ctl->nw; iw++) {
5480 sprintf(varname, "ext_win_%d", iw);
5481 NC(nc_inq_varid(ncid, varname, &var_k[iw]));
5482 }
5483
5484 /* Inquire cloud variables... */
5485 if (ctl->ncl > 0) {
5486 NC(nc_inq_varid(ncid, "cld_z", &var_cz));
5487 NC(nc_inq_varid(ncid, "cld_dz", &var_cdz));
5488 for (int icl = 0; icl < ctl->ncl; icl++) {
5489 sprintf(varname, "cld_k_%.4f", ctl->clnu[icl]);
5490 NC(nc_inq_varid(ncid, varname, &var_ck[icl]));
5491 }
5492 }
5493
5494 /* Inquire surface variables... */
5495 if (ctl->nsf > 0) {
5496 NC(nc_inq_varid(ncid, "srf_t", &var_sft));
5497 for (int isf = 0; isf < ctl->nsf; isf++) {
5498 sprintf(varname, "srf_eps_%.4f", ctl->sfnu[isf]);
5499 NC(nc_inq_varid(ncid, varname, &var_sfe[isf]));
5500 }
5501 }
5502
5503 /* Read core variables... */
5504 NC(nc_get_vara_double(ncid, var_time, start, count, atm->time));
5505 NC(nc_get_vara_double(ncid, var_z, start, count, atm->z));
5506 NC(nc_get_vara_double(ncid, var_lon, start, count, atm->lon));
5507 NC(nc_get_vara_double(ncid, var_lat, start, count, atm->lat));
5508 NC(nc_get_vara_double(ncid, var_p, start, count, atm->p));
5509 NC(nc_get_vara_double(ncid, var_t, start, count, atm->t));
5510
5511 /* Read emitters... */
5512 for (int ig = 0; ig < ctl->ng; ig++)
5513 NC(nc_get_vara_double(ncid, var_q[ig], start, count, atm->q[ig]));
5514
5515 /* Read extinctions... */
5516 for (int iw = 0; iw < ctl->nw; iw++)
5517 NC(nc_get_vara_double(ncid, var_k[iw], start, count, atm->k[iw]));
5518
5519 /* Read cloud variables... */
5520 if (ctl->ncl > 0) {
5521 NC(nc_get_vara_double(ncid, var_cz, start, count, &atm->clz));
5522 NC(nc_get_vara_double(ncid, var_cdz, start, count, &atm->cldz));
5523 for (int icl = 0; icl < ctl->ncl; icl++)
5524 NC(nc_get_vara_double(ncid, var_ck[icl], start, count, &atm->clk[icl]));
5525 }
5526
5527 /* Read surface variables... */
5528 if (ctl->nsf > 0) {
5529 NC(nc_get_vara_double(ncid, var_sft, start, count, &atm->sft));
5530
5531 for (int isf = 0; isf < ctl->nsf; isf++)
5532 NC(nc_get_vara_double
5533 (ncid, var_sfe[isf], start, count, &atm->sfeps[isf]));
5534 }
5535
5536 /* Close file... */
5537 NC(nc_close(ncid));
5538}
#define NC(cmd)
Execute a NetCDF command and check for errors.
Definition: jurassic.h:705
#define NSF
Maximum number of surface layer spectral grid points.
Definition: jurassic.h:331
#define NCL
Maximum number of cloud layer spectral grid points.
Definition: jurassic.h:291

◆ read_ctl()

void read_ctl ( int  argc,
char *  argv[],
ctl_t *  ctl 
)

Read model control parameters from command-line and configuration input.

Parses all numerical and string parameters required to initialize a JURASSIC simulation, including atmospheric composition, radiative channels, cloud and surface options, continua, ray-tracing setup, retrieval parameters, and output settings.
Populates the ctl_t structure with all configuration values.

Parameters
[in]argcArgument count from the command line.
[in]argvArgument vector containing user-specified options.
[out]ctlControl structure to be filled with parsed settings.
  • Uses scan_ctl to extract key–value pairs from the command line or control file.
  • Initializes:
    • Emitters and gases (NG, EMITTER),
    • Spectral channels (ND, NU, WINDOW),
    • Cloud parameters (NCL, CLNU),
    • Surface parameters (NSF, SFNU, SFTYPE, SFSZA),
    • Hydrostatic reference height (HYDZ),
    • Continuum flags (CTM_CO2, CTM_H2O, CTM_N2, CTM_O2),
    • Ray-tracing options (REFRAC, RAYDS, RAYDZ),
    • Field-of-view (FOV),
    • Retrieval limits (RETP_ZMIN, RETQ_ZMAX, etc.),
    • Output flags (WRITE_BBT, WRITE_MATRIX),
    • External forward model paths (RFMBIN, RFMHIT, RFMXSC).
  • Validates array bounds and logical parameter ranges.
  • Automatically detects major gas species indices (e.g. CO₂, H₂O, N₂, O₂).
  • Logs the executable name, version, and compilation time at startup.
See also
ctl_t, scan_ctl, find_emitter, read_shape, formod
Warning
  • Aborts if mandatory keys are missing or exceed defined limits (e.g. NG > NG_MAX).
  • Requires consistent index ordering (e.g. NCL > 1, NSF > 1).
  • Undefined or invalid parameters trigger ERRMSG() aborts.
Author
Lars Hoffmann

Definition at line 5542 of file jurassic.c.

5545 {
5546
5547 /* Write info... */
5548 LOG(1, "\nJuelich Rapid Spectral Simulation Code (JURASSIC)\n"
5549 "(executable: %s | version: %s | compiled: %s, %s)\n",
5550 argv[0], VERSION, __DATE__, __TIME__);
5551
5552 /* Emitters... */
5553 ctl->ng = (int) scan_ctl(argc, argv, "NG", -1, "0", NULL);
5554 if (ctl->ng < 0 || ctl->ng > NG)
5555 ERRMSG("Set 0 <= NG <= MAX!");
5556 for (int ig = 0; ig < ctl->ng; ig++)
5557 scan_ctl(argc, argv, "EMITTER", ig, "", ctl->emitter[ig]);
5558 ctl->ig_co2 = find_emitter(ctl, "CO2");
5559 ctl->ig_h2o = find_emitter(ctl, "H2O");
5560 ctl->ig_n2 = find_emitter(ctl, "N2");
5561 ctl->ig_o2 = find_emitter(ctl, "O2");
5562
5563 /* Radiance channels... */
5564 ctl->nd = (int) scan_ctl(argc, argv, "ND", -1, "0", NULL);
5565 if (ctl->nd < 0 || ctl->nd > ND)
5566 ERRMSG("Set 0 <= ND <= MAX!");
5567 for (int id = 0; id < ctl->nd; id++)
5568 ctl->nu[id] = scan_ctl(argc, argv, "NU", id, "", NULL);
5569
5570 /* Spectral windows... */
5571 ctl->nw = (int) scan_ctl(argc, argv, "NW", -1, "1", NULL);
5572 if (ctl->nw < 0 || ctl->nw > NW)
5573 ERRMSG("Set 0 <= NW <= MAX!");
5574 for (int id = 0; id < ctl->nd; id++)
5575 ctl->window[id] = (int) scan_ctl(argc, argv, "WINDOW", id, "0", NULL);
5576
5577 /* Cloud data... */
5578 ctl->ncl = (int) scan_ctl(argc, argv, "NCL", -1, "0", NULL);
5579 if (ctl->ncl < 0 || ctl->ncl > NCL)
5580 ERRMSG("Set 0 <= NCL <= MAX!");
5581 if (ctl->ncl == 1)
5582 ERRMSG("Set NCL > 1!");
5583 for (int icl = 0; icl < ctl->ncl; icl++)
5584 ctl->clnu[icl] = scan_ctl(argc, argv, "CLNU", icl, "", NULL);
5585
5586 /* Surface data... */
5587 ctl->nsf = (int) scan_ctl(argc, argv, "NSF", -1, "0", NULL);
5588 if (ctl->nsf < 0 || ctl->nsf > NSF)
5589 ERRMSG("Set 0 <= NSF <= MAX!");
5590 if (ctl->nsf == 1)
5591 ERRMSG("Set NSF > 1!");
5592 for (int isf = 0; isf < ctl->nsf; isf++)
5593 ctl->sfnu[isf] = scan_ctl(argc, argv, "SFNU", isf, "", NULL);
5594 ctl->sftype = (int) scan_ctl(argc, argv, "SFTYPE", -1, "2", NULL);
5595 if (ctl->sftype < 0 || ctl->sftype > 3)
5596 ERRMSG("Set 0 <= SFTYPE <= 3!");
5597 ctl->sfsza = scan_ctl(argc, argv, "SFSZA", -1, "-999", NULL);
5598
5599 /* Emissivity look-up tables... */
5600 scan_ctl(argc, argv, "TBLBASE", -1, "-", ctl->tblbase);
5601 ctl->tblfmt = (int) scan_ctl(argc, argv, "TBLFMT", -1, "1", NULL);
5602 if (ctl->tblfmt < 1 || ctl->tblfmt > 3)
5603 ERRMSG("Unknown look-up table file format, set TBLFMT to 1, 2, or 3!");
5604
5605 /* File formats... */
5606 ctl->atmfmt = (int) scan_ctl(argc, argv, "ATMFMT", -1, "1", NULL);
5607 if (ctl->atmfmt < 1 || ctl->atmfmt > 3)
5608 ERRMSG("Unknown atmospheric file format, set ATMFMT to 1, 2, or 3!");
5609 ctl->obsfmt = (int) scan_ctl(argc, argv, "OBSFMT", -1, "1", NULL);
5610 if (ctl->obsfmt < 1 || ctl->obsfmt > 3)
5611 ERRMSG("Unknown observation file format, set OBSFMT to 1, 2, or 3!");
5612 ctl->matrixfmt = (int) scan_ctl(argc, argv, "MATRIXFMT", -1, "1", NULL);
5613 if (ctl->matrixfmt < 1 || ctl->matrixfmt > 3)
5614 ERRMSG("Unknown matrix file format, set MATRIXFMT to 1, 2, or 3!");
5615
5616 /* Hydrostatic equilibrium... */
5617 ctl->hydz = scan_ctl(argc, argv, "HYDZ", -1, "-999", NULL);
5618
5619 /* Continua... */
5620 ctl->ctm_co2 = (int) scan_ctl(argc, argv, "CTM_CO2", -1, "1", NULL);
5621 ctl->ctm_h2o = (int) scan_ctl(argc, argv, "CTM_H2O", -1, "1", NULL);
5622 ctl->ctm_n2 = (int) scan_ctl(argc, argv, "CTM_N2", -1, "1", NULL);
5623 ctl->ctm_o2 = (int) scan_ctl(argc, argv, "CTM_O2", -1, "1", NULL);
5624
5625 /* Ray-tracing... */
5626 ctl->refrac = (int) scan_ctl(argc, argv, "REFRAC", -1, "1", NULL);
5627 ctl->rayds = scan_ctl(argc, argv, "RAYDS", -1, "10", NULL);
5628 ctl->raydz = scan_ctl(argc, argv, "RAYDZ", -1, "0.1", NULL);
5629
5630 /* Field of view... */
5631 scan_ctl(argc, argv, "FOV", -1, "-", ctl->fov);
5632 if (ctl->fov[0] != '-')
5633 read_shape(ctl->fov, ctl->fov_dz, ctl->fov_w, &ctl->fov_n);
5634
5635 /* Retrieval interface... */
5636 ctl->retp_zmin = scan_ctl(argc, argv, "RETP_ZMIN", -1, "-999", NULL);
5637 ctl->retp_zmax = scan_ctl(argc, argv, "RETP_ZMAX", -1, "-999", NULL);
5638 ctl->rett_zmin = scan_ctl(argc, argv, "RETT_ZMIN", -1, "-999", NULL);
5639 ctl->rett_zmax = scan_ctl(argc, argv, "RETT_ZMAX", -1, "-999", NULL);
5640 for (int ig = 0; ig < ctl->ng; ig++) {
5641 ctl->retq_zmin[ig] = scan_ctl(argc, argv, "RETQ_ZMIN", ig, "-999", NULL);
5642 ctl->retq_zmax[ig] = scan_ctl(argc, argv, "RETQ_ZMAX", ig, "-999", NULL);
5643 }
5644 for (int iw = 0; iw < ctl->nw; iw++) {
5645 ctl->retk_zmin[iw] = scan_ctl(argc, argv, "RETK_ZMIN", iw, "-999", NULL);
5646 ctl->retk_zmax[iw] = scan_ctl(argc, argv, "RETK_ZMAX", iw, "-999", NULL);
5647 }
5648 ctl->ret_clz = (int) scan_ctl(argc, argv, "RET_CLZ", -1, "0", NULL);
5649 ctl->ret_cldz = (int) scan_ctl(argc, argv, "RET_CLDZ", -1, "0", NULL);
5650 ctl->ret_clk = (int) scan_ctl(argc, argv, "RET_CLK", -1, "0", NULL);
5651 ctl->ret_sft = (int) scan_ctl(argc, argv, "RET_SFT", -1, "0", NULL);
5652 ctl->ret_sfeps = (int) scan_ctl(argc, argv, "RET_SFEPS", -1, "0", NULL);
5653
5654 /* Output flags... */
5655 ctl->write_bbt = (int) scan_ctl(argc, argv, "WRITE_BBT", -1, "0", NULL);
5656 ctl->write_matrix =
5657 (int) scan_ctl(argc, argv, "WRITE_MATRIX", -1, "0", NULL);
5658
5659 /* External forward models... */
5660 ctl->formod = (int) scan_ctl(argc, argv, "FORMOD", -1, "1", NULL);
5661 scan_ctl(argc, argv, "RFMBIN", -1, "-", ctl->rfmbin);
5662 scan_ctl(argc, argv, "RFMHIT", -1, "-", ctl->rfmhit);
5663 for (int ig = 0; ig < ctl->ng; ig++)
5664 scan_ctl(argc, argv, "RFMXSC", ig, "-", ctl->rfmxsc[ig]);
5665}
int find_emitter(const ctl_t *ctl, const char *emitter)
Find gas species index by name.
Definition: jurassic.c:3252
double scan_ctl(int argc, char *argv[], const char *varname, const int arridx, const char *defvalue, char *value)
Scan control file or command-line arguments for a configuration variable.
Definition: jurassic.c:6613
void read_shape(const char *filename, double *x, double *y, int *n)
Read a two-column shape function from an ASCII file.
Definition: jurassic.c:6292
int write_matrix
Write matrix file (0=no, 1=yes).
Definition: jurassic.h:1603
char tblbase[LEN]
Basename for table files and filter function files.
Definition: jurassic.h:1510
int matrixfmt
Matrix data file format (1=ASCII, 2=binary, 3=netCDF).
Definition: jurassic.h:1522
int obsfmt
Observation data file format (1=ASCII, 2=binary, 3=netCDF).
Definition: jurassic.h:1519
int tblfmt
Look-up table file format (1=ASCII, 2=binary, 3=netCDF).
Definition: jurassic.h:1513
Here is the call graph for this function:

◆ read_matrix()

void read_matrix ( const char *  dirname,
const char *  filename,
const ctl_t *  ctl,
gsl_matrix *  matrix,
int  dataset 
)

Read a numerical matrix from a file.

Dispatches matrix input according to the configured matrix file format. Supported formats are ASCII (MATRIXFMT=1), binary (MATRIXFMT=2), and netCDF (MATRIXFMT=3).

Parameters
[in]dirnameDirectory path containing the matrix file (may be NULL).
[in]filenameName of the matrix file to read.
[in]ctlControl structure defining the matrix file format.
[out]matrixPointer to the GSL matrix to be filled with values.
[in]datasetZero-based dataset index for netCDF input. Ignored for ASCII and binary formats.
See also
read_matrix_asc(), read_matrix_bin(), read_matrix_nc()
Author
Lars Hoffmann

Definition at line 5669 of file jurassic.c.

5674 {
5675
5676 /* Read ASCII data... */
5677 if (ctl->matrixfmt == 1)
5678 read_matrix_asc(dirname, filename, matrix);
5679
5680 /* Read binary data... */
5681 else if (ctl->matrixfmt == 2)
5682 read_matrix_bin(dirname, filename, matrix);
5683
5684 /* Read netCDF data... */
5685 else if (ctl->matrixfmt == 3)
5686 read_matrix_nc(dirname, filename, matrix, dataset);
5687
5688 /* Error... */
5689 else
5690 ERRMSG("Unknown matrix file format, check MATRIXFMT!");
5691}
void read_matrix_nc(const char *dirname, const char *filename, gsl_matrix *matrix, int dataset)
Read a numerical matrix from a netCDF file.
Definition: jurassic.c:5787
void read_matrix_asc(const char *dirname, const char *filename, gsl_matrix *matrix)
Read a numerical matrix from an ASCII file.
Definition: jurassic.c:5695
void read_matrix_bin(const char *dirname, const char *filename, gsl_matrix *matrix)
Read a numerical matrix from a binary file.
Definition: jurassic.c:5734
Here is the call graph for this function:

◆ read_matrix_asc()

void read_matrix_asc ( const char *  dirname,
const char *  filename,
gsl_matrix *  matrix 
)

Read a numerical matrix from an ASCII file.

Loads values into a GSL matrix from a text file containing sparse or indexed entries in tabular format.
Each valid line is parsed for row and column indices and the corresponding value.

Parameters
[in]dirnameDirectory path containing the matrix file (may be NULL).
[in]filenameName of the matrix file to read.
[out]matrixPointer to the GSL matrix to be filled with values.
  • Opens the specified file and scans it line by line.
  • Initializes the matrix to zero before filling.
  • Each line is expected to contain at least 13 formatted fields, where:
    • The first integer gives the row index,
    • The seventh integer gives the column index,
    • The thirteenth floating-point number is the matrix element value.
  • All successfully parsed entries are written to the corresponding positions in the GSL matrix using gsl_matrix_set().
  • Non-matching lines are ignored.
See also
gsl_matrix, read_ctl, read_atm
Warning
  • Aborts if the file cannot be opened.
  • Expects 0-based integer indices consistent with matrix dimensions.
  • Lines not matching the expected 13-field format are skipped silently.
Author
Lars Hoffmann

Definition at line 5695 of file jurassic.c.

5698 {
5699
5700 char dum[LEN], file[LEN], line[LEN];
5701
5702 double value;
5703
5704 int i, j;
5705
5706 /* Set filename... */
5707 if (dirname != NULL)
5708 sprintf(file, "%s/%s", dirname, filename);
5709 else
5710 sprintf(file, "%s", filename);
5711
5712 /* Write info... */
5713 LOG(1, "Read matrix: %s", file);
5714
5715 /* Open file... */
5716 FILE *in;
5717 if (!(in = fopen(file, "r")))
5718 ERRMSG("Cannot open file!");
5719
5720 /* Read data... */
5721 gsl_matrix_set_zero(matrix);
5722 while (fgets(line, LEN, in))
5723 if (sscanf(line, "%d %s %s %s %s %s %d %s %s %s %s %s %lg",
5724 &i, dum, dum, dum, dum, dum,
5725 &j, dum, dum, dum, dum, dum, &value) == 13)
5726 gsl_matrix_set(matrix, (size_t) i, (size_t) j, value);
5727
5728 /* Close file... */
5729 fclose(in);
5730}

◆ read_matrix_bin()

void read_matrix_bin ( const char *  dirname,
const char *  filename,
gsl_matrix *  matrix 
)

Read a numerical matrix from a binary file.

Loads values into a GSL matrix from a compact binary file containing a magic identifier, matrix dimensions, and all matrix elements in row-major order.

Parameters
[in]dirnameDirectory path containing the matrix file (may be NULL).
[in]filenameName of the matrix file to read.
[out]matrixPointer to the preallocated GSL matrix to be filled.
Warning
  • Aborts if the file cannot be opened.
  • The stored matrix dimensions must match the size of matrix.
Author
Lars Hoffmann

Definition at line 5734 of file jurassic.c.

5737 {
5738
5739 char file[LEN], magic[4];
5740 size_t nr, nc;
5741
5742 /* Set filename... */
5743 if (dirname != NULL)
5744 sprintf(file, "%s/%s", dirname, filename);
5745 else
5746 sprintf(file, "%s", filename);
5747
5748 /* Write info... */
5749 LOG(1, "Read matrix: %s", file);
5750
5751 /* Open file... */
5752 FILE *in;
5753 if (!(in = fopen(file, "r")))
5754 ERRMSG("Cannot open file!");
5755
5756 /* Read header... */
5757 FREAD(magic, char,
5758 4,
5759 in);
5760 if (memcmp(magic, "MAT1", 4) != 0)
5761 ERRMSG("Invalid magic string!");
5762 FREAD(&nr, size_t,
5763 1,
5764 in);
5765 FREAD(&nc, size_t,
5766 1,
5767 in);
5768 if (nr != matrix->size1 || nc != matrix->size2)
5769 ERRMSG("Error reading file header!");
5770
5771 /* Read data... */
5772 for (size_t i = 0; i < nr; i++)
5773 for (size_t j = 0; j < nc; j++) {
5774 double value;
5775 FREAD(&value, double,
5776 1,
5777 in);
5778 gsl_matrix_set(matrix, i, j, value);
5779 }
5780
5781 /* Close file... */
5782 fclose(in);
5783}

◆ read_matrix_nc()

void read_matrix_nc ( const char *  dirname,
const char *  filename,
gsl_matrix *  matrix,
int  dataset 
)

Read a numerical matrix from a netCDF file.

Loads one matrix record into a GSL matrix from a netCDF file containing an unlimited dimension dataset, fixed dimensions row and col, and a variable matrix(dataset,row,col). The schema also stores per-dataset selectors rowspace, colspace, and sort, along with per-row and per-column metadata variables for channel wavenumber, time, position, and state quantity names.

Parameters
[in]dirnameDirectory path containing the matrix file (may be NULL).
[in]filenameName of the matrix file to read.
[out]matrixPointer to the preallocated GSL matrix to be filled.
[in]datasetZero-based index along the unlimited dataset dimension.
Warning
  • Aborts if the file cannot be opened.
  • The stored matrix dimensions must match the size of matrix.
Author
Lars Hoffmann

Definition at line 5787 of file jurassic.c.

5791 {
5792
5793 char file[LEN];
5794
5795 int ncid, dimid_row, dimid_col, varid;
5796
5797 size_t nr, nc;
5798
5799 /* Set filename... */
5800 if (dirname != NULL)
5801 sprintf(file, "%s/%s", dirname, filename);
5802 else
5803 sprintf(file, "%s", filename);
5804
5805 /* Write info... */
5806 LOG(1, "Read matrix: %s", file);
5807
5808 /* Open file... */
5809 NC(nc_open(file, NC_NOWRITE, &ncid));
5810
5811 /* Read dimensions... */
5812 NC(nc_inq_dimid(ncid, "row", &dimid_row));
5813 NC(nc_inq_dimid(ncid, "col", &dimid_col));
5814 NC(nc_inq_dimlen(ncid, dimid_row, &nr));
5815 NC(nc_inq_dimlen(ncid, dimid_col, &nc));
5816 if (nr != matrix->size1 || nc != matrix->size2)
5817 ERRMSG("Error reading file header!");
5818
5819 /* Read data... */
5820 NC(nc_inq_varid(ncid, "matrix", &varid));
5821 for (size_t i = 0; i < nr; i++)
5822 for (size_t j = 0; j < nc; j++) {
5823 double value;
5824 size_t start[3] = { (size_t) dataset, i, j };
5825 size_t count[3] = { 1, 1, 1 };
5826 NC(nc_get_vara_double(ncid, varid, start, count, &value));
5827 gsl_matrix_set(matrix, i, j, value);
5828 }
5829
5830 /* Close file... */
5831 NC(nc_close(ncid));
5832}

◆ read_obs()

void read_obs ( const char *  dirname,
const char *  filename,
const ctl_t *  ctl,
obs_t *  obs,
int  profile 
)

Read observation data from an input file.

This function reads atmospheric observation data from the specified file and stores the results in the provided obs_t structure. The file may be in ASCII or binary format, depending on the control settings passed via ctl_t. After reading the data, the routine performs basic validation (e.g., verifies that at least one observation entry was loaded) and logs diagnostic statistics such as ranges of times, observer coordinates, view point coordinates, tangent point coordinates, radiance or brightness temperature values, and transmittances.

The input file path is constructed from the provided directory and filename. If a directory name is given, the file is assumed to reside within it; otherwise, the filename is used as-is. Depending on the value of ctl->obsfmt, the function dispatches either to read_obs_asc() for ASCII files or read_obs_bin() for binary files.

Parameters
[in]dirnameDirectory containing the input file, or NULL to use only filename.
[in]filenameName of the observation file to read.
[in]ctlPointer to a control structure specifying file format and other options.
[out]obsPointer to an observation structure where the data will be stored.
[in]profileZero-based profile index for netCDF input. Ignored for ASCII and binary formats.
Note
The function terminates with an error message if the file cannot be opened, the observation format is unknown, or no valid data is read.
Warning
The obs structure must be properly allocated before calling this function. The function assumes its arrays are large enough to store all values contained in the input file.
See also
read_obs_asc(), read_obs_bin(), ctl_t, obs_t
Author
Lars Hoffmann

Definition at line 5836 of file jurassic.c.

5841 {
5842
5843 /* Set filename... */
5844 char file[LEN];
5845 if (dirname != NULL)
5846 sprintf(file, "%s/%s", dirname, filename);
5847 else
5848 sprintf(file, "%s", filename);
5849
5850 /* Write info... */
5851 LOG(1, "Read observation data: %s", file);
5852
5853 /* Read ASCII data... */
5854 if (ctl->obsfmt == 1)
5855 read_obs_asc(file, ctl, obs);
5856
5857 /* Read binary data... */
5858 else if (ctl->obsfmt == 2)
5859 read_obs_bin(file, ctl, obs);
5860
5861 /* Read netCDF data... */
5862 else if (ctl->obsfmt == 3)
5863 read_obs_nc(file, ctl, obs, profile);
5864
5865 /* Check number of points... */
5866 if (obs->nr < 1)
5867 ERRMSG("Could not read any data!");
5868
5869 /* Write info... */
5870 double mini, maxi;
5871 LOG(2, "Number of ray paths: %d", obs->nr);
5872 gsl_stats_minmax(&mini, &maxi, obs->time, 1, (size_t) obs->nr);
5873 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
5874 gsl_stats_minmax(&mini, &maxi, obs->obsz, 1, (size_t) obs->nr);
5875 LOG(2, "Observer altitude range: %g ... %g km", mini, maxi);
5876 gsl_stats_minmax(&mini, &maxi, obs->obslon, 1, (size_t) obs->nr);
5877 LOG(2, "Observer longitude range: %g ... %g deg", mini, maxi);
5878 gsl_stats_minmax(&mini, &maxi, obs->obslat, 1, (size_t) obs->nr);
5879 LOG(2, "Observer latitude range: %g ... %g deg", mini, maxi);
5880 gsl_stats_minmax(&mini, &maxi, obs->vpz, 1, (size_t) obs->nr);
5881 LOG(2, "View point altitude range: %g ... %g km", mini, maxi);
5882 gsl_stats_minmax(&mini, &maxi, obs->vplon, 1, (size_t) obs->nr);
5883 LOG(2, "View point longitude range: %g ... %g deg", mini, maxi);
5884 gsl_stats_minmax(&mini, &maxi, obs->vplat, 1, (size_t) obs->nr);
5885 LOG(2, "View point latitude range: %g ... %g deg", mini, maxi);
5886 gsl_stats_minmax(&mini, &maxi, obs->tpz, 1, (size_t) obs->nr);
5887 LOG(2, "Tangent point altitude range: %g ... %g km", mini, maxi);
5888 gsl_stats_minmax(&mini, &maxi, obs->tplon, 1, (size_t) obs->nr);
5889 LOG(2, "Tangent point longitude range: %g ... %g deg", mini, maxi);
5890 gsl_stats_minmax(&mini, &maxi, obs->tplat, 1, (size_t) obs->nr);
5891 LOG(2, "Tangent point latitude range: %g ... %g deg", mini, maxi);
5892 for (int id = 0; id < ctl->nd; id++) {
5893 gsl_stats_minmax(&mini, &maxi, obs->rad[id], 1, (size_t) obs->nr);
5894 if (ctl->write_bbt) {
5895 LOG(2, "Brightness temperature (%.4f cm^-1) range: %g ... %g K",
5896 ctl->nu[id], mini, maxi);
5897 } else {
5898 LOG(2, "Radiance (%.4f cm^-1) range: %g ... %g W/(m^2 sr cm^-1)",
5899 ctl->nu[id], mini, maxi);
5900 }
5901 }
5902 for (int id = 0; id < ctl->nd; id++) {
5903 gsl_stats_minmax(&mini, &maxi, obs->tau[id], 1, (size_t) obs->nr);
5904 LOG(2, "Transmittance (%.4f cm^-1) range: %g ... %g",
5905 ctl->nu[id], mini, maxi);
5906 }
5907}
void read_obs_bin(const char *filename, const ctl_t *ctl, obs_t *obs)
Read binary-formatted observation data from a file.
Definition: jurassic.c:5955
void read_obs_nc(const char *filename, const ctl_t *ctl, obs_t *obs, const int profile)
Read one observation profile from a NetCDF file.
Definition: jurassic.c:6033
void read_obs_asc(const char *filename, const ctl_t *ctl, obs_t *obs)
Read ASCII-formatted observation data from a file.
Definition: jurassic.c:5911
Here is the call graph for this function:

◆ read_obs_asc()

void read_obs_asc ( const char *  filename,
const ctl_t *  ctl,
obs_t *  obs 
)

Read ASCII-formatted observation data from a file.

This function reads atmospheric observation data from an ASCII text file specified by its filename and stores it in the provided obs_t structure. Each line in the input file is expected to contain numerical values representing a single observation record, including time, observer coordinates, view point coordinates, tangent point coordinates, spectral values stored as radiance or brightness temperature depending on ctl->write_bbt, and transmittances. The number of spectral-value and transmittance columns per record is determined by ctl->nd.

The function reads the file line by line, tokenizes the data fields, and fills the corresponding observation arrays. The number of successfully read observation entries is stored in obs->nr.

Parameters
filenamePath to the ASCII file containing the observation data.
ctlControl structure containing metadata such as the number of spectral channels (nd).
obsObservation structure where the parsed data will be stored.
Note
This is a C function and assumes that the obs structure has been preallocated with sufficient space for all records and spectral channels. No memory allocation is performed inside this routine.
Warning
The function terminates with an error message if the number of entries exceeds the predefined limit NR.
See also
read_obs(), read_obs_bin(), ctl_t, obs_t
Author
Lars Hoffmann

Definition at line 5911 of file jurassic.c.

5914 {
5915
5916 /* Init... */
5917 obs->nr = 0;
5918
5919 /* Open file... */
5920 FILE *in;
5921 if (!(in = fopen(filename, "r")))
5922 ERRMSG("Cannot open file!");
5923
5924 /* Read line... */
5925 char line[LEN], *tok;
5926 while (fgets(line, LEN, in)) {
5927
5928 /* Read data... */
5929 TOK(line, tok, "%lg", obs->time[obs->nr]);
5930 TOK(NULL, tok, "%lg", obs->obsz[obs->nr]);
5931 TOK(NULL, tok, "%lg", obs->obslon[obs->nr]);
5932 TOK(NULL, tok, "%lg", obs->obslat[obs->nr]);
5933 TOK(NULL, tok, "%lg", obs->vpz[obs->nr]);
5934 TOK(NULL, tok, "%lg", obs->vplon[obs->nr]);
5935 TOK(NULL, tok, "%lg", obs->vplat[obs->nr]);
5936 TOK(NULL, tok, "%lg", obs->tpz[obs->nr]);
5937 TOK(NULL, tok, "%lg", obs->tplon[obs->nr]);
5938 TOK(NULL, tok, "%lg", obs->tplat[obs->nr]);
5939 for (int id = 0; id < ctl->nd; id++)
5940 TOK(NULL, tok, "%lg", obs->rad[id][obs->nr]);
5941 for (int id = 0; id < ctl->nd; id++)
5942 TOK(NULL, tok, "%lg", obs->tau[id][obs->nr]);
5943
5944 /* Increment counter... */
5945 if ((++obs->nr) > NR)
5946 ERRMSG("Too many rays!");
5947 }
5948
5949 /* Close file... */
5950 fclose(in);
5951}

◆ read_obs_bin()

void read_obs_bin ( const char *  filename,
const ctl_t *  ctl,
obs_t *  obs 
)

Read binary-formatted observation data from a file.

This C function reads observation data stored in a compact binary format from a file specified by its filename and initializes the provided obs_t structure with the values retrieved. The binary format begins with a header that contains a magic identifier and the expected number of spectral channels. The number of channels in the file must match ctl->nd, otherwise the routine aborts with an error.

After verifying the header, the function reads the number of ray paths and then sequentially loads arrays corresponding to observation time, observer location, view point location, tangent point location, spectral values stored as radiance or brightness temperature depending on ctl->write_bbt, and transmittance data. The number of ray paths is assigned to obs->nr. All arrays must have been allocated prior to calling this function.

Parameters
filenamePath to the binary file containing the observation data.
ctlPointer to a control structure specifying the number of spectral channels (nd) and other configuration settings.
obsPointer to an observation structure where the decoded binary data will be stored.
Note
This function does not perform any memory allocation. The caller must ensure that all arrays in obs have sufficient capacity for the data being read.
Warning
The function terminates with an error message if the binary header does not match the expected channel count, if more data than allowed by NR is encountered, or if any read operation fails.
See also
read_obs(), read_obs_asc(), ctl_t, obs_t
Author
Lars Hoffmann

Definition at line 5955 of file jurassic.c.

5958 {
5959
5960 /* Open file... */
5961 FILE *in;
5962 if (!(in = fopen(filename, "r")))
5963 ERRMSG("Cannot open file!");
5964
5965 /* Read header... */
5966 char magic[4];
5967 FREAD(magic, char,
5968 4,
5969 in);
5970 if (memcmp(magic, "OBS1", 4) != 0)
5971 ERRMSG("Invalid magic string!");
5972
5973 int nd;
5974 FREAD(&nd, int,
5975 1,
5976 in);
5977 if (nd != ctl->nd)
5978 ERRMSG("Error reading file header!");
5979
5980 /* Read data... */
5981 size_t nr;
5982 FREAD(&nr, size_t,
5983 1,
5984 in);
5985 obs->nr = (int) nr;
5986 if (obs->nr > NR)
5987 ERRMSG("Too many ray paths!");
5988 FREAD(obs->time, double,
5989 nr,
5990 in);
5991 FREAD(obs->obsz, double,
5992 nr,
5993 in);
5994 FREAD(obs->obslon, double,
5995 nr,
5996 in);
5997 FREAD(obs->obslat, double,
5998 nr,
5999 in);
6000 FREAD(obs->vpz, double,
6001 nr,
6002 in);
6003 FREAD(obs->vplon, double,
6004 nr,
6005 in);
6006 FREAD(obs->vplat, double,
6007 nr,
6008 in);
6009 FREAD(obs->tpz, double,
6010 nr,
6011 in);
6012 FREAD(obs->tplon, double,
6013 nr,
6014 in);
6015 FREAD(obs->tplat, double,
6016 nr,
6017 in);
6018 for (int id = 0; id < ctl->nd; id++)
6019 FREAD(obs->rad[id], double,
6020 nr,
6021 in);
6022 for (int id = 0; id < ctl->nd; id++)
6023 FREAD(obs->tau[id], double,
6024 nr,
6025 in);
6026
6027 /* Close file... */
6028 fclose(in);
6029}

◆ read_obs_nc()

void read_obs_nc ( const char *  filename,
const ctl_t *  ctl,
obs_t *  obs,
const int  profile 
)

Read one observation profile from a NetCDF file.

This function reads all geometric and spectral observation data for a single profile from a NetCDF file using the variable-per-channel layout.

The NetCDF file is expected to contain:

  • A dimension profile (unlimited)
  • A dimension ray (number of ray paths)
  • A variable nray(profile) giving the number of rays for each profile
  • Geometry variables with dimensions (profile, ray):
    • time, obs_z, obs_lon, obs_lat
    • vp_z, vp_lon, vp_lat
    • tp_z, tp_lon, tp_lat
  • Spectral variables with dimensions (profile, ray), one per channel:
    • rad_%.4f (radiance, if ctl->write_bbt == 0)
    • bt_%.4f (brightness temperature, if ctl->write_bbt != 0)
    • tau_%.4f (transmittance) where the formatted frequency corresponds to ctl->nu[id].

All data for the selected profile are read into the supplied obs_t structure. The number of rays is read from nray(profile) and stored in obs->nr. If the number of rays exceeds NR or is less than one, an error is raised.

Parameters
filenamePath to the NetCDF observation file.
ctlPointer to the control structure defining spectral channels.
obsPointer to the observation structure to be filled.
profileZero-based index of the profile to read.
Author
Lars Hoffmann

Definition at line 6033 of file jurassic.c.

6037 {
6038
6039 int ncid, var_nray = -1, var_time = -1, var_obsz = -1, var_obslon =
6040 -1, var_obslat = -1, var_vpz = -1, var_vplon = -1, var_vplat =
6041 -1, var_tpz = -1, var_tplon = -1, var_tplat =
6042 -1, var_rad[ND], var_tau[ND];
6043 const char *spec_prefix = ctl->write_bbt ? "bt" : "rad";
6044
6045 /* Open file... */
6046 NC(nc_open(filename, NC_NOWRITE, &ncid));
6047
6048 /* Initialize hyperslab... */
6049 size_t start[2] = { (size_t) profile, 0 };
6050 size_t count[2] = { 1, 0 };
6051
6052 /* Read nray(profile) -> obs->nr */
6053 NC(nc_inq_varid(ncid, "nray", &var_nray));
6054 NC(nc_get_vara_int(ncid, var_nray, start, count, &obs->nr));
6055 if (obs->nr < 1 || obs->nr > NR)
6056 ERRMSG("Number of ray paths out of range!");
6057
6058 /* Update hyperslab... */
6059 count[1] = (size_t) obs->nr;
6060
6061 /* Inquire geometry variables... */
6062 NC(nc_inq_varid(ncid, "time", &var_time));
6063 NC(nc_inq_varid(ncid, "obs_z", &var_obsz));
6064 NC(nc_inq_varid(ncid, "obs_lon", &var_obslon));
6065 NC(nc_inq_varid(ncid, "obs_lat", &var_obslat));
6066
6067 NC(nc_inq_varid(ncid, "vp_z", &var_vpz));
6068 NC(nc_inq_varid(ncid, "vp_lon", &var_vplon));
6069 NC(nc_inq_varid(ncid, "vp_lat", &var_vplat));
6070
6071 NC(nc_inq_varid(ncid, "tp_z", &var_tpz));
6072 NC(nc_inq_varid(ncid, "tp_lon", &var_tplon));
6073 NC(nc_inq_varid(ncid, "tp_lat", &var_tplat));
6074
6075 /* Inquire spectral variables per channel... */
6076 for (int id = 0; id < ctl->nd; id++) {
6077 char varname[LEN];
6078
6079 sprintf(varname, "%s_%.4f", spec_prefix, ctl->nu[id]);
6080 NC(nc_inq_varid(ncid, varname, &var_rad[id]));
6081
6082 sprintf(varname, "tau_%.4f", ctl->nu[id]);
6083 NC(nc_inq_varid(ncid, varname, &var_tau[id]));
6084 }
6085
6086 /* Read geometry... */
6087 NC(nc_get_vara_double(ncid, var_time, start, count, obs->time));
6088 NC(nc_get_vara_double(ncid, var_obsz, start, count, obs->obsz));
6089 NC(nc_get_vara_double(ncid, var_obslon, start, count, obs->obslon));
6090 NC(nc_get_vara_double(ncid, var_obslat, start, count, obs->obslat));
6091
6092 NC(nc_get_vara_double(ncid, var_vpz, start, count, obs->vpz));
6093 NC(nc_get_vara_double(ncid, var_vplon, start, count, obs->vplon));
6094 NC(nc_get_vara_double(ncid, var_vplat, start, count, obs->vplat));
6095
6096 NC(nc_get_vara_double(ncid, var_tpz, start, count, obs->tpz));
6097 NC(nc_get_vara_double(ncid, var_tplon, start, count, obs->tplon));
6098 NC(nc_get_vara_double(ncid, var_tplat, start, count, obs->tplat));
6099
6100 /* Read radiance and transmittance... */
6101 for (int id = 0; id < ctl->nd; id++) {
6102 NC(nc_get_vara_double(ncid, var_rad[id], start, count, obs->rad[id]));
6103 NC(nc_get_vara_double(ncid, var_tau[id], start, count, obs->tau[id]));
6104 }
6105
6106 /* Close file... */
6107 NC(nc_close(ncid));
6108}

◆ read_obs_rfm()

double read_obs_rfm ( const char *  basename,
const double  z,
const double *  nu,
const double *  f,
const int  n 
)

Read and spectrally convolve an RFM output spectrum.

Opens the appropriate RFM ASCII spectrum file for a given tangent or observation altitude and convolves the high-resolution spectrum with a provided instrument filter function.
Returns the integrated (filtered) radiance value.

Parameters
[in]basenameBase filename of the RFM output (e.g. "rad" or "tra").
[in]zAltitude [km] used to select the corresponding RFM file.
[in]nuWavenumber grid [cm⁻¹] of the filter function.
[in]fFilter transmission values corresponding to nu.
[in]nNumber of points in nu and f arrays.
Returns
Filtered radiance value integrated over the instrument bandpass.
  • The routine looks for an RFM output file named basename_<altitude_in_meters>.asc (e.g. rad_04500.asc).
  • If not found, it retries with altitude+1 meter to tolerate rounding.
  • The file is read using read_rfm_spec() into arrays of wavenumbers (nurfm) and radiances (rad).
  • The input filter function \( f(\nu) \) is linearly interpolated onto the RFM wavenumber grid, and the spectrum is convolved as

    \[ R = \frac{\int f(\nu) \, I(\nu) \, d\nu}{\int f(\nu) \, d\nu} \]

  • Linear interpolation is used for both spectral alignment and filter sampling.
  • Returns the resulting band-averaged radiance in the same units as the input.
See also
read_rfm_spec, locate_irr, LIN, formod_rfm
Warning
  • Aborts if the corresponding RFM file cannot be found.
  • Assumes nu and f arrays are monotonic and have at least two points.
  • Files must contain RFM ASCII spectra in expected column format.
Author
Lars Hoffmann

Definition at line 6112 of file jurassic.c.

6117 {
6118
6119 double *nurfm, *spec;
6120
6121 int npts;
6122
6123 /* Allocate... */
6124 ALLOC(nurfm, double, RFMNPTS);
6125 ALLOC(spec, double, RFMNPTS);
6126
6127 /* Search and read RFM spectrum... */
6128 char filename[LEN];
6129 find_rfm_file(filename, basename, z);
6130 read_rfm_spec(filename, nurfm, spec, &npts);
6131
6132 /* Convolute... */
6133 const double result = convolve_rfm(nurfm, spec, npts, nu, f, n);
6134
6135 /* Free... */
6136 free(nurfm);
6137 free(spec);
6138
6139 return result;
6140}

◆ read_ret()

void read_ret ( int  argc,
char *  argv[],
const ctl_t *  ctl,
ret_t *  ret 
)

Read retrieval configuration and error parameters.

Initializes the retrieval control structure (ret_t) by reading all iteration and uncertainty parameters from the command line or an input control file using the scan_ctl() interface.

Parameters
[in]argcNumber of command-line arguments.
[in]argvCommand-line argument vector.
[in]ctlPointer to global control structure (ctl_t) defining the number of emitters, detectors, windows, clouds, etc.
[out]retPointer to retrieval configuration structure (ret_t) to be populated with iteration and error settings.

The function performs the following initialization steps:

  1. Iteration control parameters
    • KERNEL_RECOMP — number of iterations between kernel recomputations.
    • CONV_ITMAX — maximum number of retrieval iterations.
    • CONV_DMIN — minimum normalized step size for convergence.
  2. Optional shared-file retrieval I/O
    • SHARED_IO_PROFLIST — optional file containing profile indices for batch mode.
    • SHARED_IO_ATM_APR_FILE, SHARED_IO_OBS_MEAS_FILE — optional shared input files.
    • SHARED_IO_ATM_FINAL_FILE, SHARED_IO_OBS_FINAL_FILE — optional shared output files.
    • SHARED_IO_MATRIX_*_FILE, SHARED_IO_ATM_ERR_*_FILE, SHARED_IO_ATM_CONT_FILE, SHARED_IO_ATM_RES_FILE — optional shared diagnostic output files.
  3. Error analysis flag
    • ERR_ANA — enables or disables retrieval error analysis (0 = off, 1 = on).
  4. Instrument and forward model errors
    • ERR_FORMOD[id] — relative (%) forward model uncertainty per detector channel.
    • ERR_NOISE[id] — absolute instrument noise per detector channel
      [W/(m²·sr·cm⁻¹)] or [K] depending on write_bbt.
  5. Pressure and temperature retrieval uncertainties
    • ERR_PRESS, ERR_PRESS_CZ, ERR_PRESS_CH — pressure error [%] and correlation lengths [km].
    • ERR_TEMP, ERR_TEMP_CZ, ERR_TEMP_CH — temperature error [K] and correlation lengths [km].
  6. Volume mixing ratio (VMR) errors
    • ERR_Q[ig], ERR_Q_CZ[ig], ERR_Q_CH[ig] — per gas [%] and correlation lengths [km].
  7. Extinction errors
    • ERR_K[iw], ERR_K_CZ[iw], ERR_K_CH[iw] — per spectral window [km⁻¹] and correlation lengths [km].
  8. Cloud retrieval parameters
    • ERR_CLZ — cloud top height error [km].
    • ERR_CLDZ — cloud depth error [km].
    • ERR_CLK[icl] — cloud extinction error per frequency [km⁻¹].
  9. Surface retrieval parameters
    • ERR_SFT — surface temperature error [K].
    • ERR_SFEPS[isf] — surface emissivity errors (dimensionless).
See also
scan_ctl, set_cov_apr, set_cov_meas, ret_t, ctl_t
Note
  • Each parameter can be specified either in the control file or on the command line (the latter overrides file values).
  • Default values are used when a parameter is not explicitly defined.
  • Correlation lengths of -999 indicate uncorrelated (diagonal) treatment.
Warning
  • Input validation is minimal; ensure consistency between ctl and ret dimensions.
  • Missing mandatory parameters trigger runtime errors.
Author
Lars Hoffmann

Definition at line 6144 of file jurassic.c.

6148 {
6149
6150 /* Iteration control... */
6151 ret->kernel_recomp =
6152 (int) scan_ctl(argc, argv, "KERNEL_RECOMP", -1, "3", NULL);
6153 ret->conv_itmax = (int) scan_ctl(argc, argv, "CONV_ITMAX", -1, "30", NULL);
6154 ret->conv_dmin = scan_ctl(argc, argv, "CONV_DMIN", -1, "0.1", NULL);
6155
6156 /* Error analysis... */
6157 ret->err_ana = (int) scan_ctl(argc, argv, "ERR_ANA", -1, "0", NULL);
6158
6159 for (int id = 0; id < ctl->nd; id++)
6160 ret->err_formod[id] = scan_ctl(argc, argv, "ERR_FORMOD", id, "0", NULL);
6161
6162 for (int id = 0; id < ctl->nd; id++)
6163 ret->err_noise[id] = scan_ctl(argc, argv, "ERR_NOISE", id, "0", NULL);
6164
6165 ret->err_press = scan_ctl(argc, argv, "ERR_PRESS", -1, "0", NULL);
6166 ret->err_press_cz = scan_ctl(argc, argv, "ERR_PRESS_CZ", -1, "-999", NULL);
6167 ret->err_press_ch = scan_ctl(argc, argv, "ERR_PRESS_CH", -1, "-999", NULL);
6168
6169 ret->err_temp = scan_ctl(argc, argv, "ERR_TEMP", -1, "0", NULL);
6170 ret->err_temp_cz = scan_ctl(argc, argv, "ERR_TEMP_CZ", -1, "-999", NULL);
6171 ret->err_temp_ch = scan_ctl(argc, argv, "ERR_TEMP_CH", -1, "-999", NULL);
6172
6173 for (int ig = 0; ig < ctl->ng; ig++) {
6174 ret->err_q[ig] = scan_ctl(argc, argv, "ERR_Q", ig, "0", NULL);
6175 ret->err_q_cz[ig] = scan_ctl(argc, argv, "ERR_Q_CZ", ig, "-999", NULL);
6176 ret->err_q_ch[ig] = scan_ctl(argc, argv, "ERR_Q_CH", ig, "-999", NULL);
6177 }
6178
6179 for (int iw = 0; iw < ctl->nw; iw++) {
6180 ret->err_k[iw] = scan_ctl(argc, argv, "ERR_K", iw, "0", NULL);
6181 ret->err_k_cz[iw] = scan_ctl(argc, argv, "ERR_K_CZ", iw, "-999", NULL);
6182 ret->err_k_ch[iw] = scan_ctl(argc, argv, "ERR_K_CH", iw, "-999", NULL);
6183 }
6184
6185 ret->err_clz = scan_ctl(argc, argv, "ERR_CLZ", -1, "0", NULL);
6186 ret->err_cldz = scan_ctl(argc, argv, "ERR_CLDZ", -1, "0", NULL);
6187 for (int icl = 0; icl < ctl->ncl; icl++)
6188 ret->err_clk[icl] = scan_ctl(argc, argv, "ERR_CLK", icl, "0", NULL);
6189
6190 ret->err_sft = scan_ctl(argc, argv, "ERR_SFT", -1, "0", NULL);
6191 for (int isf = 0; isf < ctl->nsf; isf++)
6192 ret->err_sfeps[isf] = scan_ctl(argc, argv, "ERR_SFEPS", isf, "0", NULL);
6193
6194 /* Shared retrieval I/O... */
6195 ret->shared_io_profile = 0;
6196 scan_ctl(argc, argv, "SHARED_IO_PROFLIST", -1, "-",
6197 ret->shared_io_proflist);
6198 scan_ctl(argc, argv, "SHARED_IO_ATM_APR_FILE", -1, "-",
6200 scan_ctl(argc, argv, "SHARED_IO_OBS_MEAS_FILE", -1, "-",
6202 scan_ctl(argc, argv, "SHARED_IO_ATM_FINAL_FILE", -1, "-",
6204 scan_ctl(argc, argv, "SHARED_IO_OBS_FINAL_FILE", -1, "-",
6206 scan_ctl(argc, argv, "SHARED_IO_MATRIX_COV_APR_FILE", -1, "-",
6208 scan_ctl(argc, argv, "SHARED_IO_MATRIX_KERNEL_FILE", -1, "-",
6210 scan_ctl(argc, argv, "SHARED_IO_MATRIX_COV_RET_FILE", -1, "-",
6212 scan_ctl(argc, argv, "SHARED_IO_MATRIX_CORR_FILE", -1, "-",
6214 scan_ctl(argc, argv, "SHARED_IO_MATRIX_GAIN_FILE", -1, "-",
6216 scan_ctl(argc, argv, "SHARED_IO_MATRIX_AVK_FILE", -1, "-",
6218 scan_ctl(argc, argv, "SHARED_IO_ATM_ERR_TOTAL_FILE", -1, "-",
6220 scan_ctl(argc, argv, "SHARED_IO_ATM_ERR_NOISE_FILE", -1, "-",
6222 scan_ctl(argc, argv, "SHARED_IO_ATM_ERR_FORMOD_FILE", -1, "-",
6224 scan_ctl(argc, argv, "SHARED_IO_ATM_CONT_FILE", -1, "-",
6226 scan_ctl(argc, argv, "SHARED_IO_ATM_RES_FILE", -1, "-",
6228}
double err_press_cz
Vertical correlation length for pressure error [km].
Definition: jurassic.h:1770
double err_press
Pressure error [%].
Definition: jurassic.h:1767
double err_k_cz[NW]
Vertical correlation length for extinction error [km].
Definition: jurassic.h:1797
double err_k_ch[NW]
Horizontal correlation length for extinction error [km].
Definition: jurassic.h:1800
double err_temp_cz
Vertical correlation length for temperature error [km].
Definition: jurassic.h:1779
double err_formod[ND]
Forward model error [%].
Definition: jurassic.h:1761
double err_temp
Temperature error [K].
Definition: jurassic.h:1776
double err_q_cz[NG]
Vertical correlation length for volume mixing ratio error [km].
Definition: jurassic.h:1788
char shared_io_proflist[LEN]
Optional file containing retrieval profile indices.
Definition: jurassic.h:1821
double err_noise[ND]
Noise error [W/(m^2 sr cm^-1)].
Definition: jurassic.h:1764
double err_clz
Cloud height error [km].
Definition: jurassic.h:1803
double err_sft
Surface temperature error [K].
Definition: jurassic.h:1812
double err_clk[NCL]
Cloud extinction error [km^-1].
Definition: jurassic.h:1809
char shared_io_obs_meas_file[LEN]
Optional shared measured-observation input file.
Definition: jurassic.h:1827
char shared_io_atm_apr_file[LEN]
Optional shared atmospheric a priori input file.
Definition: jurassic.h:1824
double err_temp_ch
Horizontal correlation length for temperature error [km].
Definition: jurassic.h:1782
char shared_io_atm_err_formod_file[LEN]
Optional shared forward-model retrieval-error output file.
Definition: jurassic.h:1860
double err_cldz
Cloud depth error [km].
Definition: jurassic.h:1806
double err_press_ch
Horizontal correlation length for pressure error [km].
Definition: jurassic.h:1773
double err_q_ch[NG]
Horizontal correlation length for volume mixing ratio error [km].
Definition: jurassic.h:1791
char shared_io_atm_err_total_file[LEN]
Optional shared total retrieval-error output file.
Definition: jurassic.h:1854
double err_q[NG]
Volume mixing ratio error [%].
Definition: jurassic.h:1785
char shared_io_atm_err_noise_file[LEN]
Optional shared noise retrieval-error output file.
Definition: jurassic.h:1857
double err_sfeps[NSF]
Surface emissivity error.
Definition: jurassic.h:1815
int shared_io_profile
Profile index used for shared netCDF retrieval inputs and outputs.
Definition: jurassic.h:1818
double err_k[NW]
Extinction error [km^-1].
Definition: jurassic.h:1794
Here is the call graph for this function:

◆ read_rfm_spec()

void read_rfm_spec ( const char *  filename,
double *  nu,
double *  rad,
int *  npts 
)

Read a Reference Forward Model (RFM) ASCII spectrum.

Parses an RFM output file containing high-resolution spectral radiances and fills the provided arrays with wavenumber and radiance values.

Parameters
[in]filenameName of the RFM ASCII spectrum file (e.g. "rad_04500.asc").
[out]nuArray to receive the spectral wavenumber grid [cm⁻¹].
[out]radArray to receive the corresponding radiances.
[out]nptsPointer to integer receiving the number of spectral points.
  • Expects the RFM file to begin with a four-line header. The final header line must contain, in order:
    • the number of spectral points (npts),
    • starting wavenumber nu0 [cm⁻¹],
    • spectral increment dnu [cm⁻¹],
    • ending wavenumber nu1 [cm⁻¹].
  • Radiance data follow as a sequence of floating-point values, separated by spaces, tabs, or line breaks.
  • The wavenumber grid is reconstructed using linear interpolation between nu0 and nu1:

    \[ \nu_i = \nu_0 + i \, \frac{\nu_1 - \nu_0}{N - 1}, \quad i = 0,\dots,N-1 \]

  • Uses dynamic line buffering and token-based parsing for efficiency.
See also
read_obs_rfm, locate_irr, LIN, formod_rfm
Warning
  • Aborts if the file cannot be opened or has an invalid header format.
  • Aborts if the number of grid points exceeds RFMNPTS.
  • Assumes ASCII format consistent with standard RFM .asc output.
Note
This routine reads only the spectral intensity data — additional metadata (e.g., gas profiles, geometry) must be handled separately.
Author
Lars Hoffmann

Definition at line 6232 of file jurassic.c.

6236 {
6237
6238 char *line = NULL, *tok;
6239
6240 size_t line_buf_size = 0;
6241
6242 double dnu, nu0, nu1;
6243
6244 int ipts = 0;
6245
6246 /* Write info... */
6247 LOG(1, "Read RFM data: %s", filename);
6248
6249 /* Open file... */
6250 FILE *in;
6251 if (!(in = fopen(filename, "r")))
6252 ERRMSG("Cannot open file!");
6253
6254 /* Read header... */
6255 for (int i = 0; i < 4; i++)
6256 if (getline(&line, &line_buf_size, in) == -1)
6257 ERRMSG("Error while reading file header!");
6258 if (sscanf(line, "%d %lg %lg %lg", npts, &nu0, &dnu, &nu1) != 4)
6259 ERRMSG("Invalid spectrum header format!");
6260
6261 /* Check number of spectral grid points... */
6262 if (*npts > RFMNPTS)
6263 ERRMSG("Too many spectral grid points!");
6264
6265 /* Read radiance data... */
6266 while (getline(&line, &line_buf_size, in) != -1 && ipts < *npts) {
6267 tok = strtok(line, " \t\n");
6268 while (tok != NULL && ipts < *npts) {
6269 if (sscanf(tok, "%lg", &rad[ipts]) == 1)
6270 ipts++;
6271 tok = strtok(NULL, " \t\n");
6272 }
6273 }
6274
6275 /* Check number of spectral grid points... */
6276 if (ipts != *npts)
6277 ERRMSG("Error while reading RFM data!");
6278
6279 /* Compute wavenumbers... */
6280 for (ipts = 0; ipts < *npts; ipts++)
6281 nu[ipts] = LIN(0.0, nu0, (double) (*npts - 1), nu1, (double) ipts);
6282
6283 /* Close file... */
6284 fclose(in);
6285
6286 /* Free.. */
6287 free(line);
6288}

◆ read_shape()

void read_shape ( const char *  filename,
double *  x,
double *  y,
int *  n 
)

Read a two-column shape function from an ASCII file.

Loads tabulated x–y data pairs (e.g., filter transmission or field-of-view weighting function) into the provided arrays.

Parameters
[in]filenameName of the ASCII file containing the shape function.
[out]xArray to receive the abscissa values.
[out]yArray to receive the ordinate values.
[out]nPointer to integer receiving the number of data points read.
  • The input file must contain at least two whitespace-separated columns:
    • Column 1: abscissa (x), typically wavenumber [cm⁻¹] or angular offset [deg].
    • Column 2: ordinate (y), typically transmission or weighting value.
  • Comment lines or malformed entries are ignored.
  • The routine logs the number of data points and their value ranges.
  • Data are stored directly in the provided arrays for subsequent interpolation or convolution.
See also
gsl_stats_minmax, formod_fov, init_srcfunc, read_obs_rfm
Warning
  • Aborts if the file cannot be opened or if fewer than two valid points are read.
  • Aborts if the number of data points exceeds NSHAPE.
  • Assumes numeric ASCII format and monotonic ordering of x values.
Note
This generic shape reader is used for both spectral filter functions and angular field-of-view profiles.
Author
Lars Hoffmann

Definition at line 6292 of file jurassic.c.

6296 {
6297
6298 char line[LEN];
6299
6300 /* Write info... */
6301 LOG(1, "Read shape function: %s", filename);
6302
6303 /* Open file... */
6304 FILE *in;
6305 if (!(in = fopen(filename, "r")))
6306 ERRMSG("Cannot open file!");
6307
6308 /* Read data... */
6309 *n = 0;
6310 while (fgets(line, LEN, in))
6311 if (sscanf(line, "%lg %lg", &x[*n], &y[*n]) == 2)
6312 if ((++(*n)) > NSHAPE)
6313 ERRMSG("Too many data points!");
6314
6315 /* Close file... */
6316 fclose(in);
6317
6318 /* Check number of data points... */
6319 if (*n < 2)
6320 ERRMSG("Could not read any data!");
6321
6322 /* Write info... */
6323 double mini, maxi;
6324 LOG(2, "Number of data points: %d", *n);
6325 gsl_stats_minmax(&mini, &maxi, x, 1, (size_t) *n);
6326 LOG(2, "Range of x values: %.4f ... %.4f", mini, maxi);
6327 gsl_stats_minmax(&mini, &maxi, y, 1, (size_t) *n);
6328 LOG(2, "Range of y values: %g ... %g", mini, maxi);
6329}

◆ read_tbl()

tbl_t * read_tbl ( const ctl_t *  ctl)

Read emissivity lookup tables from disk.

Loads emissivity lookup tables for all detector/channel indices id and all emitter/gas indices ig according to the configured table format ctl->tblfmt:

  • ASCII (ctl->tblfmt == 1)
  • compact binary (ctl->tblfmt == 2)
  • netCDF (ctl->tblfmt == 3)

The function allocates and initializes a tbl_t structure, reads the corresponding lookup tables, and (depending on the table format) also loads filter functions.

Missing per-table files (ASCII/binary) or missing netCDF files/variables are not fatal: the reader emits a warning and the corresponding lookup table is treated as empty (i.e., tbl->np[id][ig] == 0).

Diagnostic information about loaded tables (pressure levels, temperature ranges, absorber amounts, emissivity ranges) may be written to the log.

Parameters
[in]ctlPointer to the control structure defining lookup table format, filenames, emitters, and detector/channel frequencies.
Returns
Pointer to an allocated and initialized tbl_t structure containing the loaded lookup tables.
Warning
If an unsupported lookup table format is specified via ctl->tblfmt, the function aborts with an error message.
Note
Memory for the returned structure is dynamically allocated and must be released by the caller.
Author
Lars Hoffmann

Definition at line 6333 of file jurassic.c.

6334 {
6335
6336 /* Allocate... */
6337 tbl_t *tbl;
6338 ALLOC(tbl, tbl_t, 1);
6339
6340 /* Initialize filter function sizes... */
6341 for (int id = 0; id < ctl->nd; id++)
6342 tbl->filt_n[id] = 0;
6343
6344 /* Loop over trace gases... */
6345 for (int ig = 0; ig < ctl->ng; ig++) {
6346
6347 /* Read ASCII look-up tables... */
6348 if (ctl->tblfmt == 1)
6349 for (int id = 0; id < ctl->nd; id++) {
6350 read_tbl_asc(ctl, tbl, id, ig);
6351 TBL_LOG(tbl, id, ig);
6352 }
6353
6354 /* Read binary look-up tables... */
6355 else if (ctl->tblfmt == 2)
6356 for (int id = 0; id < ctl->nd; id++) {
6357 read_tbl_bin(ctl, tbl, id, ig);
6358 TBL_LOG(tbl, id, ig);
6359 }
6360
6361 /* Read netCDF look-up tables... */
6362 else if (ctl->tblfmt == 3) {
6363
6364 /* Open file... */
6365 int ncid;
6366 char filename[2 * LEN];
6367 sprintf(filename, "%s_%s.nc", ctl->tblbase, ctl->emitter[ig]);
6368 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
6369 WARN("Missing emissivity table: %s", filename);
6370 continue;
6371 } else
6372 LOG(1, "Read emissivity table: %s", filename);
6373
6374 /* Read channels... */
6375 for (int id = 0; id < ctl->nd; id++) {
6376 read_tbl_nc_channel(ctl, tbl, id, ig, ncid);
6377 TBL_LOG(tbl, id, ig);
6378 }
6379
6380 /* Close file... */
6381 NC(nc_close(ncid));
6382 }
6383 }
6384
6385 /* Calculate log-pressure... */
6386 for (int id = 0; id < ctl->nd; id++)
6387 for (int ig = 0; ig < ctl->ng; ig++)
6388 for (int ip = 0; ip < tbl->np[id][ig]; ip++)
6389 tbl->lnp[id][ig][ip] = log(tbl->p[id][ig][ip]);
6390
6391 /* Read filter functions... */
6392 if (ctl->tblfmt == 1)
6393 for (int id = 0; id < ctl->nd; id++) {
6394 char filename[2 * LEN];
6395 sprintf(filename, "%s_%.4f.filt", ctl->tblbase, ctl->nu[id]);
6396 read_shape(filename, tbl->filt_nu[id], tbl->filt_f[id],
6397 &tbl->filt_n[id]);
6398 }
6399
6400 /* Initialize source function lookup tables... */
6401 init_srcfunc(ctl, tbl);
6402
6403 /* Return pointer... */
6404 return tbl;
6405}
void read_tbl_bin(const ctl_t *ctl, tbl_t *tbl, const int id, const int ig)
Read a single compact binary emissivity lookup table.
Definition: jurassic.c:6532
void init_srcfunc(const ctl_t *ctl, tbl_t *tbl)
Initialize source function lookup tables from emissivity data.
Definition: jurassic.c:3976
void read_tbl_asc(const ctl_t *ctl, tbl_t *tbl, const int id, const int ig)
Read a single ASCII emissivity lookup table.
Definition: jurassic.c:6409
void read_tbl_nc_channel(const ctl_t *ctl, tbl_t *tbl, int id, int ig, int ncid)
Read one packed emissivity lookup table from an open NetCDF file.
Definition: jurassic.c:6576
#define TBL_LOG(tbl, id, ig)
Log detailed statistics of an emissivity look-up table.
Definition: jurassic.h:1155
Emissivity look-up tables.
Definition: jurassic.h:1876
Here is the call graph for this function:

◆ read_tbl_asc()

void read_tbl_asc ( const ctl_t *  ctl,
tbl_t *  tbl,
const int  id,
const int  ig 
)

Read a single ASCII emissivity lookup table.

Reads one ASCII table for detector/channel index id and emitter/gas index ig from a file named:

<ctl->tblbase>_<ctl->nu[id]>_<ctl->emitter[ig]>.tab

The table file contains four columns:

  1. pressure [hPa]
  2. temperature [K]
  3. column density [molecules/cm^2]
  4. emissivity [-]

The routine infers the pressure/temperature/column-density indices from changes in the values read from the file. Values outside the supported ranges for column density or emissivity are skipped and counted.

If the file cannot be opened, a warning is issued and the table is treated as empty (i.e., tbl->np[id][ig] == 0).

Parameters
[in]ctlPointer to control structure specifying filenames and grids.
[in,out]tblPointer to the table structure to be filled.
[in]idDetector/channel index.
[in]igEmitter/gas index.
Warning
Aborts via ERRMSG() if table dimensions exceed TBLNP / TBLNT / TBLNU.
Note
Implementation detail: the ASCII reader may use an internal sentinel during parsing (historically np == -1 such that the first increment yields index 0). On return, tbl->np[id][ig] always represents the number of pressure levels (0 for an empty table).
Author
Lars Hoffmann

Definition at line 6409 of file jurassic.c.

6413 {
6414
6415 /* Initialize... */
6416 double eps, eps_old = -999, press, press_old = -999, temp,
6417 temp_old = -999, u, u_old = -999;
6418 int nrange = 0;
6419
6420 /* Set filename... */
6421 char filename[2 * LEN];
6422 sprintf(filename, "%s_%.4f_%s.tab", ctl->tblbase,
6423 ctl->nu[id], ctl->emitter[ig]);
6424
6425 /* Open file... */
6426 FILE *in;
6427 if (!(in = fopen(filename, "r"))) {
6428 WARN("Missing emissivity table: %s", filename);
6429 return;
6430 } else
6431 LOG(1, "Read emissivity table: %s", filename);
6432
6433 /* Init pressure level counter... */
6434 tbl->np[id][ig] = -1;
6435
6436 /* Read data... */
6437 char line[LEN];
6438 while (fgets(line, LEN, in)) {
6439
6440 /* Parse line... */
6441 if (sscanf(line, "%lg %lg %lg %lg", &press, &temp, &u, &eps) != 4)
6442 continue;
6443
6444 /* Check ranges... */
6445 if (u < UMIN || u > UMAX || eps < EPSMIN || eps > EPSMAX) {
6446 nrange++;
6447 continue;
6448 }
6449
6450 /* Determine pressure index... */
6451 if (press != press_old) {
6452 press_old = press;
6453 if ((++tbl->np[id][ig]) >= TBLNP)
6454 ERRMSG("Too many pressure levels!");
6455 tbl->nt[id][ig][tbl->np[id][ig]] = -1;
6456 }
6457
6458 /* Determine temperature index... */
6459 if (temp != temp_old) {
6460 temp_old = temp;
6461 if ((++tbl->nt[id][ig][tbl->np[id][ig]]) >= TBLNT)
6462 ERRMSG("Too many temperatures!");
6463 tbl->nu[id][ig][tbl->np[id][ig]]
6464 [tbl->nt[id][ig][tbl->np[id][ig]]] = -1;
6465
6466 /* Reset dynamic arrays for this (ip,it) node... */
6467 tbl->logu[id][ig][tbl->np[id][ig]]
6468 [tbl->nt[id][ig][tbl->np[id][ig]]] = NULL;
6469 tbl->logeps[id][ig][tbl->np[id][ig]]
6470 [tbl->nt[id][ig][tbl->np[id][ig]]] = NULL;
6471 }
6472
6473 /* Determine column density index... */
6474 if ((eps > eps_old && u > u_old) || tbl->nu[id][ig][tbl->np[id][ig]]
6475 [tbl->nt[id][ig][tbl->np[id][ig]]] < 0) {
6476 eps_old = eps;
6477 u_old = u;
6478 if ((++tbl->nu[id][ig][tbl->np[id][ig]]
6479 [tbl->nt[id][ig][tbl->np[id][ig]]]) >= TBLNU)
6480 ERRMSG("Too many column densities!");
6481
6482 /* Grow dynamic arrays (nu is used as an index during reading). */
6483 const int ip = tbl->np[id][ig];
6484 const int it = tbl->nt[id][ig][ip];
6485 const int iu = tbl->nu[id][ig][ip][it];
6486 const size_t nnew = (size_t) (iu + 1);
6487
6488 float *tmp = (float *) realloc(tbl->logu[id][ig][ip][it],
6489 nnew * sizeof(float));
6490 if (!tmp)
6491 ERRMSG("Out of memory!");
6492 tbl->logu[id][ig][ip][it] = tmp;
6493
6494 tmp =
6495 (float *) realloc(tbl->logeps[id][ig][ip][it], nnew * sizeof(float));
6496 if (!tmp)
6497 ERRMSG("Out of memory!");
6498 tbl->logeps[id][ig][ip][it] = tmp;
6499 }
6500
6501 /* Store data... */
6502 tbl->p[id][ig][tbl->np[id][ig]] = press;
6503 tbl->t[id][ig][tbl->np[id][ig]][tbl->nt[id][ig][tbl->np[id][ig]]]
6504 = temp;
6505 tbl->logu[id][ig][tbl->np[id][ig]][tbl->nt[id][ig][tbl->np[id][ig]]]
6506 [tbl->nu[id][ig][tbl->np[id][ig]]
6507 [tbl->nt[id][ig][tbl->np[id][ig]]]] = (float) log(u);
6508 tbl->logeps[id][ig][tbl->np[id][ig]][tbl->nt[id][ig][tbl->np[id][ig]]]
6509 [tbl->nu[id][ig][tbl->np[id][ig]]
6510 [tbl->nt[id][ig][tbl->np[id][ig]]]] = (float) log(eps);
6511 }
6512
6513 /* Increment counters... */
6514 tbl->np[id][ig]++;
6515 for (int ip = 0; ip < tbl->np[id][ig]; ip++) {
6516 tbl->nt[id][ig][ip]++;
6517 for (int it = 0; it < tbl->nt[id][ig][ip]; it++)
6518 tbl->nu[id][ig][ip][it]++;
6519 }
6520
6521 /* Check ranges... */
6522 if (nrange > 0)
6523 WARN("Column density or emissivity out of range (%d data points)!",
6524 nrange);
6525
6526 /* Close file... */
6527 fclose(in);
6528}
#define UMAX
Maximum column density [molecules/cm^2].
Definition: jurassic.h:267
#define TBLNU
Maximum number of column densities per emissivity curve.
Definition: jurassic.h:371
#define TBLNT
Maximum number of temperatures in emissivity tables.
Definition: jurassic.h:366
#define EPSMAX
Maximum emissivity.
Definition: jurassic.h:187
#define TBLNP
Maximum number of pressure levels in emissivity tables.
Definition: jurassic.h:356

◆ read_tbl_bin()

void read_tbl_bin ( const ctl_t *  ctl,
tbl_t *  tbl,
const int  id,
const int  ig 
)

Read a single compact binary emissivity lookup table.

Reads one binary table for detector/channel index id and emitter/gas index ig from a file named:

<ctl->tblbase>_<ctl->nu[id]>_<ctl->emitter[ig]>.bin

The file contains a length field followed by a packed byte blob created by tbl_pack():

  • size_t nbytes : number of bytes in the packed blob
  • uint8_t blob[] : packed lookup table data

The blob is unpacked into tbl using tbl_unpack().

If the file cannot be opened, a warning is issued and the table is treated as empty (i.e., tbl->np[id][ig] == 0).

Parameters
[in]ctlPointer to control structure specifying filenames and grids.
[in,out]tblPointer to the table structure to be filled.
[in]idDetector/channel index.
[in]igEmitter/gas index.
Warning
Aborts via ERRMSG() if the file is malformed or unpacking fails.
See also
write_tbl_bin()
tbl_pack()
tbl_unpack()
Author
Lars Hoffmann

Definition at line 6532 of file jurassic.c.

6536 {
6537
6538 /* Set filename... */
6539 char filename[2 * LEN];
6540 sprintf(filename, "%s_%.4f_%s.bin",
6541 ctl->tblbase, ctl->nu[id], ctl->emitter[ig]);
6542
6543 /* Open file... */
6544 FILE *in = fopen(filename, "rb");
6545 if (!in) {
6546 WARN("Missing emissivity table: %s", filename);
6547 return;
6548 } else
6549 LOG(1, "Read emissivity table: %s", filename);
6550
6551 /* Read length.. */
6552 size_t nbytes;
6553 FREAD(&nbytes, size_t,
6554 1,
6555 in);
6556 if (nbytes <= 0)
6557 ERRMSG("Invalid packed table size!");
6558
6559 /* Read packed blob... */
6560 uint8_t *work = NULL;
6561 ALLOC(work, uint8_t, nbytes);
6562 FREAD(work, uint8_t, nbytes, in);
6563
6564 /* Unpack... */
6565 tbl_unpack(tbl, id, ig, work);
6566
6567 /* Close file... */
6568 fclose(in);
6569
6570 /* Free... */
6571 free(work);
6572}
size_t tbl_unpack(tbl_t *tbl, int id, int ig, const uint8_t *buf)
Unpack a lookup table from a contiguous binary buffer.
Definition: jurassic.c:7130
Here is the call graph for this function:

◆ read_tbl_nc_channel()

void read_tbl_nc_channel ( const ctl_t *  ctl,
tbl_t *  tbl,
int  id,
int  ig,
int  ncid 
)

Read one packed emissivity lookup table from an open NetCDF file.

Loads a previously stored emissivity lookup table for detector/channel index id and emitter (trace gas) index ig from an already opened NetCDF file. The file is expected to have been created by write_tbl_nc().

The NetCDF variable name is derived from the detector/channel frequency:

tbl_XXXX

where XXXX is ctl->nu[id] formatted to four decimal places.

Each variable is stored as a one-dimensional NC_UBYTE array containing a packed lookup-table byte stream. The data are unpacked into tbl using tbl_unpack().

Missing variables are not fatal: a warning is issued and the corresponding table is left empty (i.e., tbl->np[id][ig] remains zero).

The NetCDF file handle ncid must refer to an open file and is not opened or closed by this function.

Parameters
[in]ctlControl structure defining emitters, detectors, and detector/channel frequencies.
[in,out]tblTable structure that receives the unpacked data.
[in]idDetector/channel index selecting ctl->nu[id].
[in]igEmitter (trace gas) index selecting ctl->emitter[ig].
[in]ncidNetCDF file identifier of an already opened file.
Note
A temporary buffer is allocated to hold the packed lookup-table data prior to unpacking.
Warning
Aborts via ERRMSG() if the NetCDF variable exists but cannot be read or unpacked (e.g., corrupted contents).
See also
write_tbl_nc()
tbl_unpack()
Author
Lars Hoffmann

Definition at line 6576 of file jurassic.c.

6581 {
6582
6583 char varname[LEN];
6584
6585 int varid, dimid;
6586
6587 size_t nbytes;
6588
6589 /* Inquire variable... */
6590 sprintf(varname, "tbl_%.4f", ctl->nu[id]);
6591 if (nc_inq_varid(ncid, varname, &varid) != NC_NOERR) {
6592 WARN("Missing emissivity table: %s", varname);
6593 return;
6594 } else
6595 LOG(1, "Read emissivity table: %s", varname);
6596 NC(nc_inq_vardimid(ncid, varid, &dimid));
6597 NC(nc_inq_dimlen(ncid, dimid, &nbytes));
6598
6599 /* Read variable... */
6600 uint8_t *work = NULL;
6601 ALLOC(work, uint8_t, nbytes);
6602 NC(nc_get_var_uchar(ncid, varid, (unsigned char *) work));
6603
6604 /* Unpack... */
6605 tbl_unpack(tbl, id, ig, work);
6606
6607 /* Free... */
6608 free(work);
6609}
Here is the call graph for this function:

◆ scan_ctl()

double scan_ctl ( int  argc,
char *  argv[],
const char *  varname,
const int  arridx,
const char *  defvalue,
char *  value 
)

Scan control file or command-line arguments for a configuration variable.

Searches for a named variable in the JURASSIC control file or command-line arguments, returning its value as a double. Optionally stores the value as a string and supports array-style parameters (e.g., EMITTER[0], NU[5]).

Parameters
[in]argcNumber of command-line arguments.
[in]argvCommand-line argument vector.
[in]varnameName of the control variable to read.
[in]arridxArray index (use -1 for scalar variables).
[in]defvalueDefault value if variable is not found (can be empty).
[out]valueOptional pointer to a string buffer receiving the value (may be NULL if only numeric output is required).
Returns
The variable value converted to double.
  • The routine first attempts to open the control file provided as the first command-line argument (argv[1]), unless it starts with '-'.
  • Variable names may appear as either:
    • VAR (scalar)
    • VAR[index] (explicit array index)
    • VAR[*] (wildcard entry applying to all indices)
  • The search order is:
    1. Control file lines of the form:
      VAR[index] = VALUE
      VAR[*] = VALUE
    2. Command-line arguments:
      ./jurassic ctlfile VAR[index] VALUE
  • If no match is found:
    • The default value defvalue is used (if non-empty).
    • Otherwise, the routine aborts with an error.
  • The variable value is printed to the log at verbosity level 1.
See also
read_ctl, LOG, ERRMSG
Warning
  • Aborts if the control file cannot be opened (unless skipped with '-').
  • Aborts if a required variable is missing and no default is provided.
  • Array bounds are not validated against internal limits; use ctl_t checks to ensure consistency.
Note
  • This utility simplifies control input parsing by supporting both command-line overrides and configuration files with the same syntax.
  • String comparisons are case-insensitive.
Author
Lars Hoffmann

Definition at line 6613 of file jurassic.c.

6619 {
6620
6621 char dummy[LEN], fullname1[LEN], fullname2[LEN], line[LEN],
6622 rvarname[LEN], rval[LEN];
6623
6624 int contain = 0;
6625
6626 /* Open file... */
6627 FILE *in = NULL;
6628 if (argv[1][0] != '-')
6629 if (!(in = fopen(argv[1], "r")))
6630 ERRMSG("Cannot open file!");
6631
6632 /* Set full variable name... */
6633 if (arridx >= 0) {
6634 sprintf(fullname1, "%s[%d]", varname, arridx);
6635 sprintf(fullname2, "%s[*]", varname);
6636 } else {
6637 sprintf(fullname1, "%s", varname);
6638 sprintf(fullname2, "%s", varname);
6639 }
6640
6641 /* Read data... */
6642 if (in != NULL)
6643 while (fgets(line, LEN, in))
6644 if (sscanf(line, "%s %s %s", rvarname, dummy, rval) == 3)
6645 if (strcasecmp(rvarname, fullname1) == 0 ||
6646 strcasecmp(rvarname, fullname2) == 0) {
6647 contain = 1;
6648 break;
6649 }
6650 for (int i = 1; i < argc - 1; i++)
6651 if (strcasecmp(argv[i], fullname1) == 0 ||
6652 strcasecmp(argv[i], fullname2) == 0) {
6653 sprintf(rval, "%s", argv[i + 1]);
6654 contain = 1;
6655 break;
6656 }
6657
6658 /* Close file... */
6659 if (in != NULL)
6660 fclose(in);
6661
6662 /* Check for missing variables... */
6663 if (!contain) {
6664 if (strlen(defvalue) > 0)
6665 sprintf(rval, "%s", defvalue);
6666 else
6667 ERRMSG("Missing variable %s!\n", fullname1);
6668 }
6669
6670 /* Write info... */
6671 LOG(1, "%s = %s", fullname1, rval);
6672
6673 /* Return values... */
6674 if (value != NULL)
6675 sprintf(value, "%s", rval);
6676 return atof(rval);
6677}

◆ set_cov_apr()

void set_cov_apr ( const ret_t *  ret,
const ctl_t *  ctl,
const atm_t *  atm,
const int *  iqa,
const int *  ipa,
gsl_matrix *  s_a 
)

Construct the a priori covariance matrix \(\mathbf{S_a}\) for retrieval parameters.

Builds the full a priori covariance matrix based on specified retrieval error assumptions and correlation lengths defined in the ret_t structure. Each diagonal element represents the variance of an individual state vector element, while off-diagonal terms encode spatial correlations between parameters of the same type.

Parameters
[in]retRetrieval configuration and error parameters (ret_t).
[in]ctlControl structure defining retrieval setup and state vector mapping (ctl_t).
[in]atmAtmospheric profile structure containing geolocation and altitude information (atm_t).
[in]iqaIndex array linking state vector elements to physical quantities (e.g. pressure, temperature, gas, extinction, etc.).
[in]ipaIndex array linking state vector elements to atmospheric grid points.
[out]s_aOutput a priori covariance matrix \(\mathbf{S_a}\) (gsl_matrix), dimension n×n.
  • The function first converts atmospheric quantities to a state vector (atm2x) and scales them according to their a priori uncertainties:
    • Pressure and trace gas errors are relative (% of nominal value).
    • Temperature, extinction, cloud, and surface errors are absolute.
  • The diagonal of \(\mathbf{S_a}\) is filled with the variances \(\sigma_i^2\) of each element.
  • Off-diagonal elements are populated according to an exponential correlation model:

    \[ \rho_{ij} = \exp\left(-\frac{d_{ij}}{L_h} - \frac{|z_i - z_j|}{L_v}\right) \]

    where:
    • \(d_{ij}\) is the great-circle (horizontal) distance between state vector locations,
    • \(L_h\) and \(L_v\) are horizontal and vertical correlation lengths for the parameter type.
See also
atm2x, geo2cart, DIST, ret_t, ctl_t
Note
  • Parameters with identical type indices (iqa[i] == iqa[j]) are assumed to share correlation properties.
  • Correlation lengths are taken from ret_t, differing by parameter type:
    • Pressure: err_press_cz, err_press_ch
    • Temperature: err_temp_cz, err_temp_ch
    • Volume mixing ratio: err_q_cz[], err_q_ch[]
    • Extinction: err_k_cz[], err_k_ch[]
  • Cloud and surface parameters are assumed uncorrelated (diagonal only).
Warning
  • A zero or negative variance triggers a runtime error.
  • The matrix is constructed in full (dense), which may be large for high-resolution retrieval grids.
Author
Lars Hoffmann

Definition at line 6681 of file jurassic.c.

6687 {
6688
6689 /* Get sizes... */
6690 const size_t n = s_a->size1;
6691
6692 /* Allocate... */
6693 gsl_vector *x_a = gsl_vector_alloc(n);
6694
6695 /* Get sigma vector... */
6696 atm2x(ctl, atm, x_a, NULL, NULL);
6697 for (size_t i = 0; i < n; i++) {
6698 if (iqa[i] == IDXP)
6699 gsl_vector_set(x_a, i, ret->err_press / 100 * gsl_vector_get(x_a, i));
6700 if (iqa[i] == IDXT)
6701 gsl_vector_set(x_a, i, ret->err_temp);
6702 for (int ig = 0; ig < ctl->ng; ig++)
6703 if (iqa[i] == IDXQ(ig))
6704 gsl_vector_set(x_a, i, ret->err_q[ig] / 100 * gsl_vector_get(x_a, i));
6705 for (int iw = 0; iw < ctl->nw; iw++)
6706 if (iqa[i] == IDXK(iw))
6707 gsl_vector_set(x_a, i, ret->err_k[iw]);
6708 if (iqa[i] == IDXCLZ)
6709 gsl_vector_set(x_a, i, ret->err_clz);
6710 if (iqa[i] == IDXCLDZ)
6711 gsl_vector_set(x_a, i, ret->err_cldz);
6712 for (int icl = 0; icl < ctl->ncl; icl++)
6713 if (iqa[i] == IDXCLK(icl))
6714 gsl_vector_set(x_a, i, ret->err_clk[icl]);
6715 if (iqa[i] == IDXSFT)
6716 gsl_vector_set(x_a, i, ret->err_sft);
6717 for (int isf = 0; isf < ctl->nsf; isf++)
6718 if (iqa[i] == IDXSFEPS(isf))
6719 gsl_vector_set(x_a, i, ret->err_sfeps[isf]);
6720 }
6721
6722 /* Check standard deviations... */
6723 for (size_t i = 0; i < n; i++)
6724 if (POW2(gsl_vector_get(x_a, i)) <= 0)
6725 ERRMSG("Check a priori data (zero standard deviation)!");
6726
6727 /* Initialize diagonal covariance... */
6728 gsl_matrix_set_zero(s_a);
6729 for (size_t i = 0; i < n; i++)
6730 gsl_matrix_set(s_a, i, i, POW2(gsl_vector_get(x_a, i)));
6731
6732 /* Loop over matrix elements... */
6733 for (size_t i = 0; i < n; i++)
6734 for (size_t j = 0; j < n; j++)
6735 if (i != j && iqa[i] == iqa[j]) {
6736
6737 /* Initialize... */
6738 double cz = 0;
6739 double ch = 0;
6740
6741 /* Set correlation lengths for pressure... */
6742 if (iqa[i] == IDXP) {
6743 cz = ret->err_press_cz;
6744 ch = ret->err_press_ch;
6745 }
6746
6747 /* Set correlation lengths for temperature... */
6748 if (iqa[i] == IDXT) {
6749 cz = ret->err_temp_cz;
6750 ch = ret->err_temp_ch;
6751 }
6752
6753 /* Set correlation lengths for volume mixing ratios... */
6754 for (int ig = 0; ig < ctl->ng; ig++)
6755 if (iqa[i] == IDXQ(ig)) {
6756 cz = ret->err_q_cz[ig];
6757 ch = ret->err_q_ch[ig];
6758 }
6759
6760 /* Set correlation lengths for extinction... */
6761 for (int iw = 0; iw < ctl->nw; iw++)
6762 if (iqa[i] == IDXK(iw)) {
6763 cz = ret->err_k_cz[iw];
6764 ch = ret->err_k_ch[iw];
6765 }
6766
6767 /* Compute correlations... */
6768 if (cz > 0 && ch > 0) {
6769
6770 /* Get Cartesian coordinates... */
6771 double x0[3], x1[3];
6772 geo2cart(0, atm->lon[ipa[i]], atm->lat[ipa[i]], x0);
6773 geo2cart(0, atm->lon[ipa[j]], atm->lat[ipa[j]], x1);
6774
6775 /* Compute correlations... */
6776 const double rho =
6777 exp(-DIST(x0, x1) / ch -
6778 fabs(atm->z[ipa[i]] - atm->z[ipa[j]]) / cz);
6779
6780 /* Set covariance... */
6781 gsl_matrix_set(s_a, i, j, gsl_vector_get(x_a, i)
6782 * gsl_vector_get(x_a, j) * rho);
6783 }
6784 }
6785
6786 /* Free... */
6787 gsl_vector_free(x_a);
6788}
#define DIST(a, b)
Compute Cartesian distance between two 3D vectors.
Definition: jurassic.h:531
Here is the call graph for this function:

◆ set_cov_meas()

void set_cov_meas ( const ret_t *  ret,
const ctl_t *  ctl,
const obs_t *  obs,
gsl_vector *  sig_noise,
gsl_vector *  sig_formod,
gsl_vector *  sig_eps_inv 
)

Construct measurement error standard deviations and their inverse.

Builds the total measurement uncertainty vector used in the optimal estimation retrieval, accounting for both instrument noise and forward model (systematic) errors.

Parameters
[in]retRetrieval configuration and error parameters (ret_t).
[in]ctlControl structure defining spectral channels and setup (ctl_t).
[in]obsObservation dataset (obs_t), containing measured radiances or brightness temperatures.
[out]sig_noiseVector of instrument noise standard deviations (gsl_vector), length m.
[out]sig_formodVector of forward model error standard deviations (gsl_vector), length m.
[out]sig_eps_invVector of inverse total standard deviations, \(\sigma_\epsilon^{-1}\), used for normalization.
  • The function computes the total measurement uncertainty for each observation element \(i\) as:

    \[ \sigma_{\epsilon,i}^2 = \sigma_{\text{noise},i}^2 + \sigma_{\text{formod},i}^2 \]

    and stores its reciprocal square root:

    \[ (\sigma_{\epsilon,i}^{-1}) = \frac{1}{\sqrt{\sigma_{\epsilon,i}^2}} \]

  • **Noise error (sig_noise)**
    Determined from the instrument noise level defined in ret->err_noise[id] for each spectral channel. The noise term is always included in the fit.
  • **Forward model error (sig_formod)**
    Computed as a fixed percentage (ret->err_formod[id]) of the measured radiance (or brightness temperature) per channel. This represents uncertainty due to imperfect forward modeling.
  • The inverse total standard deviation vector (sig_eps_inv) is used to normalize the measurement residuals \((y - F(x))\) in the cost function.
See also
obs2y, copy_obs, cost_function, set_cov_apr
Note
  • Only finite observation elements are considered; invalid values are set to NAN.
  • Units correspond to the observation quantity:
    • Radiance: [W/(m²·sr·cm⁻¹)]
    • Brightness temperature: [K]
  • The forward model error is always relative, expressed in percent (%).
Warning
  • A zero or negative uncertainty triggers a runtime error.
  • Assumes obs and ctl are consistent in dimension and indexing.
Author
Lars Hoffmann

Definition at line 6792 of file jurassic.c.

6798 {
6799
6800 /* Allocate... */
6801 obs_t *obs_err;
6802 ALLOC(obs_err, obs_t, 1);
6803
6804 /* Get size... */
6805 const size_t m = sig_eps_inv->size;
6806
6807 /* Noise error (always considered in retrieval fit)... */
6808 copy_obs(ctl, obs_err, obs, 1);
6809 for (int ir = 0; ir < obs_err->nr; ir++)
6810 for (int id = 0; id < ctl->nd; id++)
6811 obs_err->rad[id][ir]
6812 = (isfinite(obs->rad[id][ir]) ? ret->err_noise[id] : NAN);
6813 obs2y(ctl, obs_err, sig_noise, NULL, NULL);
6814
6815 /* Forward model error (always considered in retrieval fit)... */
6816 copy_obs(ctl, obs_err, obs, 1);
6817 for (int ir = 0; ir < obs_err->nr; ir++)
6818 for (int id = 0; id < ctl->nd; id++)
6819 obs_err->rad[id][ir]
6820 = fabs(ret->err_formod[id] / 100 * obs->rad[id][ir]);
6821 obs2y(ctl, obs_err, sig_formod, NULL, NULL);
6822
6823 /* Total error... */
6824 for (size_t i = 0; i < m; i++)
6825 gsl_vector_set(sig_eps_inv, i, 1 / sqrt(POW2(gsl_vector_get(sig_noise, i))
6826 +
6827 POW2(gsl_vector_get
6828 (sig_formod, i))));
6829
6830 /* Check standard deviations... */
6831 for (size_t i = 0; i < m; i++)
6832 if (gsl_vector_get(sig_eps_inv, i) <= 0)
6833 ERRMSG("Check measurement errors (zero standard deviation)!");
6834
6835 /* Free... */
6836 free(obs_err);
6837}
Here is the call graph for this function:

◆ shared_io_input_target()

const char * shared_io_input_target ( const ret_t *  ret,
const char *  shared_file,
const char *  legacy_file,
const char **  dirname,
int *  profile 
)

Resolve retrieval input target for legacy-directory and shared-file modes.

Chooses whether a retrieval input should be read from the legacy per-directory file layout or from a shared netCDF file selected through the retrieval control structure.

Parameters
[in]retRetrieval configuration structure (ret_t).
[in]shared_fileShared input file name from ret_t; ignored when set to "-".
[in]legacy_fileLegacy per-directory input file name.
[out]dirnameOutput directory pointer. Set to ret->dir for legacy input and to NULL for shared-file input.
[out]profileRecord index used by the generic I/O wrappers.
Returns
Pointer to the selected input file name.
  • In shared-file mode, the function returns shared_file, sets *dirname = NULL, and uses ret->shared_io_profile as the profile or dataset index.
  • In legacy mode, the function returns legacy_file, sets *dirname = ret->dir, and resets *profile = 0.
See also
shared_io_output_target, read_atm, read_obs
Author
Lars Hoffmann

Definition at line 6841 of file jurassic.c.

6846 {
6847
6848 if (shared_file[0] != '-') {
6849 *dirname = NULL;
6850 *profile = ret->shared_io_profile;
6851 return shared_file;
6852 }
6853
6854 *dirname = ret->dir;
6855 *profile = 0;
6856 return legacy_file;
6857}
char dir[LEN]
Working directory.
Definition: jurassic.h:1746

◆ shared_io_output_target()

const char * shared_io_output_target ( const ret_t *  ret,
const char *  shared_file,
const char *  legacy_file,
const char **  dirname,
int *  profile 
)

Resolve retrieval output target for legacy-directory and shared-file modes.

Chooses whether a retrieval product should be written into the legacy per-directory file layout or into a shared netCDF file selected through the retrieval control structure.

Parameters
[in]retRetrieval configuration structure (ret_t).
[in]shared_fileShared output file name from ret_t; ignored when set to "-".
[in]legacy_fileLegacy per-directory output file name.
[out]dirnameOutput directory pointer. Set to ret->dir for legacy output and to NULL for shared-file output.
[out]profileRecord index used by the generic I/O wrappers.
Returns
Pointer to the selected output file name.
  • In shared-file mode, the function returns shared_file, sets *dirname = NULL, and uses ret->shared_io_profile as the profile or dataset index.
  • In legacy mode, the function returns legacy_file, sets *dirname = ret->dir, and resets *profile = 0.
See also
shared_io_output_file, shared_io_lock, shared_io_unlock, write_atm, write_obs, write_matrix
Author
Lars Hoffmann

Definition at line 6861 of file jurassic.c.

6866 {
6867
6868 if (shared_file[0] != '-') {
6869 *dirname = NULL;
6870 *profile = ret->shared_io_profile;
6871 return shared_file;
6872 }
6873
6874 *dirname = ret->dir;
6875 *profile = 0;
6876 return legacy_file;
6877}

◆ shared_io_lock()

int shared_io_lock ( const ret_t *  ret)

Acquire an exclusive lock for shared retrieval output files.

Creates or opens a lock file derived from the configured shared retrieval output target and blocks until an exclusive file lock can be obtained.

Parameters
[in]retRetrieval configuration structure (ret_t).
Returns
File descriptor of the acquired lock, or -1 if no shared output file is configured.

The lock file name is formed as "<shared-output>.lock", where shared-output is determined by shared_io_output_file(). The lock is used to serialize writes when multiple retrieval processes or MPI ranks write into the same shared netCDF files.

See also
shared_io_output_file, shared_io_unlock
Author
Lars Hoffmann

Definition at line 6881 of file jurassic.c.

6882 {
6883
6884 const char *base = shared_io_output_file(ret);
6885 if (base == NULL)
6886 return -1;
6887
6888 char lockfile[LEN];
6889 if (snprintf(lockfile, LEN, "%s.lock", base) >= LEN)
6890 ERRMSG("Lock file name too long!");
6891 int fd = open(lockfile, O_CREAT | O_RDWR, 0666);
6892 if (fd < 0)
6893 ERRMSG("Cannot open lock file!");
6894
6895 struct flock fl;
6896 fl.l_type = F_WRLCK;
6897 fl.l_whence = SEEK_SET;
6898 fl.l_start = 0;
6899 fl.l_len = 0;
6900 if (fcntl(fd, F_SETLKW, &fl) < 0)
6901 ERRMSG("Cannot lock shared output file!");
6902
6903 return fd;
6904}
const char * shared_io_output_file(const ret_t *ret)
Return the primary shared retrieval output file configured for locking.
Definition: jurassic.c:6926
Here is the call graph for this function:

◆ shared_io_unlock()

void shared_io_unlock ( int  fd)

Release a shared retrieval output lock.

Unlocks and closes the file descriptor returned by shared_io_lock().

Parameters
[in]fdLock file descriptor returned by shared_io_lock().

Passing a negative descriptor is allowed and results in no action.

See also
shared_io_lock
Author
Lars Hoffmann

Definition at line 6908 of file jurassic.c.

6909 {
6910
6911 if (fd < 0)
6912 return;
6913
6914 struct flock fl;
6915 fl.l_type = F_UNLCK;
6916 fl.l_whence = SEEK_SET;
6917 fl.l_start = 0;
6918 fl.l_len = 0;
6919 if (fcntl(fd, F_SETLK, &fl) < 0)
6920 ERRMSG("Cannot unlock shared output file!");
6921 close(fd);
6922}

◆ shared_io_output_file()

const char * shared_io_output_file ( const ret_t *  ret)

Return the primary shared retrieval output file configured for locking.

Scans the shared retrieval output file fields in ret_t and returns the first configured file name. This file name is then used as the base for the shared lock file created by shared_io_lock().

Parameters
[in]retRetrieval configuration structure (ret_t).
Returns
Pointer to the first configured shared output file name, or NULL if shared-output mode is not active.
Note
This helper does not return shared input files. It is only used to locate a representative shared output target for lock-file naming.
See also
shared_io_lock, shared_io_output_target
Author
Lars Hoffmann

Definition at line 6926 of file jurassic.c.

6927 {
6928
6929 if (ret->shared_io_atm_final_file[0] != '-')
6930 return ret->shared_io_atm_final_file;
6931 if (ret->shared_io_obs_final_file[0] != '-')
6932 return ret->shared_io_obs_final_file;
6933 if (ret->shared_io_matrix_cov_apr_file[0] != '-')
6935 if (ret->shared_io_matrix_kernel_file[0] != '-')
6936 return ret->shared_io_matrix_kernel_file;
6937 if (ret->shared_io_matrix_cov_ret_file[0] != '-')
6939 if (ret->shared_io_matrix_corr_file[0] != '-')
6940 return ret->shared_io_matrix_corr_file;
6941 if (ret->shared_io_matrix_gain_file[0] != '-')
6942 return ret->shared_io_matrix_gain_file;
6943 if (ret->shared_io_matrix_avk_file[0] != '-')
6944 return ret->shared_io_matrix_avk_file;
6945 if (ret->shared_io_atm_err_total_file[0] != '-')
6946 return ret->shared_io_atm_err_total_file;
6947 if (ret->shared_io_atm_err_noise_file[0] != '-')
6948 return ret->shared_io_atm_err_noise_file;
6949 if (ret->shared_io_atm_err_formod_file[0] != '-')
6951 if (ret->shared_io_atm_cont_file[0] != '-')
6952 return ret->shared_io_atm_cont_file;
6953 if (ret->shared_io_atm_res_file[0] != '-')
6954 return ret->shared_io_atm_res_file;
6955 return NULL;
6956}

◆ tangent_point()

void tangent_point ( const los_t *  los,
double *  tpz,
double *  tplon,
double *  tplat 
)

Determine the tangent point along a line of sight (LOS).

Computes the location of the tangent point — the point of minimum altitude — along the current line of sight, based on the LOS geometry stored in los_t.

Parameters
[in]losPointer to the line-of-sight (LOS) structure containing altitude, longitude, latitude, and segment length data.
[out]tpzPointer to variable receiving tangent point altitude [km].
[out]tplonPointer to variable receiving tangent point longitude [deg].
[out]tplatPointer to variable receiving tangent point latitude [deg].
  • For limb or occultation geometry, the routine:
    1. Identifies the LOS grid point with minimum altitude.
    2. Fits a quadratic interpolation polynomial: \( z = a x^2 + b x + c \) through the altitudes of the three neighboring LOS points.
    3. Solves analytically for the vertex position \( x = -b / (2a) \), corresponding to the tangent point.
    4. Converts this interpolated position back to geographic coordinates.
  • For nadir or zenith viewing (minimum altitude at the LOS endpoint), the tangent point defaults to the last grid point.
See also
raytrace, geo2cart, cart2geo, los_t
Note
  • The LOS segment lengths (ds) must be consistent with the geometric spacing between altitude points for the interpolation to be accurate.
  • The quadratic interpolation provides sub-kilometer precision for smooth limb rays.
  • Longitude and latitude are returned in degrees.
Warning
  • If the LOS contains fewer than three valid points, or the geometry is strongly curved, the tangent point estimate may be unreliable.
Author
Lars Hoffmann

Definition at line 6960 of file jurassic.c.

6964 {
6965
6966 /* Find minimum altitude... */
6967 const size_t ip = gsl_stats_min_index(los->z, 1, (size_t) los->np);
6968
6969 /* Nadir or zenith... */
6970 if (ip <= 0 || ip >= (size_t) los->np - 1) {
6971 *tpz = los->z[los->np - 1];
6972 *tplon = los->lon[los->np - 1];
6973 *tplat = los->lat[los->np - 1];
6974 }
6975
6976 /* Limb... */
6977 else {
6978
6979 /* Determine interpolating polynomial y=a*x^2+b*x+c... */
6980 const double yy0 = los->z[ip - 1];
6981 const double yy1 = los->z[ip];
6982 const double yy2 = los->z[ip + 1];
6983 const double x1 = sqrt(POW2(los->ds[ip]) - POW2(yy1 - yy0));
6984 const double x2 = x1 + sqrt(POW2(los->ds[ip + 1]) - POW2(yy2 - yy1));
6985 const double a = 1 / (x1 - x2) * (-(yy0 - yy1) / x1 + (yy0 - yy2) / x2);
6986 const double b = -(yy0 - yy1) / x1 - a * x1;
6987 const double c = yy0;
6988
6989 /* Get tangent point location... */
6990 double dummy, v[3], v0[3], v2[3];
6991 const double x = -b / (2 * a);
6992 *tpz = a * x * x + b * x + c;
6993 geo2cart(los->z[ip - 1], los->lon[ip - 1], los->lat[ip - 1], v0);
6994 geo2cart(los->z[ip + 1], los->lon[ip + 1], los->lat[ip + 1], v2);
6995 for (int i = 0; i < 3; i++)
6996 v[i] = LIN(0.0, v0[i], x2, v2[i], x);
6997 cart2geo(v, &dummy, tplon, tplat);
6998 }
6999}
Here is the call graph for this function:

◆ tbl_free()

void tbl_free ( const ctl_t *  ctl,
tbl_t *  tbl 
)

Free lookup table and all internally allocated memory.

Frees all dynamically allocated memory owned by a tbl_t object, including the spectral lookup arrays (logu and logeps) for all detector/emitter/pressure/temperature combinations. The tbl_t structure itself is freed at the end.

The function is safe to call with a NULL pointer and will return immediately in that case. Partially initialized tables are handled safely.

Parameters
[in,out]tblPointer to the lookup table to be freed.
[in]ctlControl structure providing the number of detectors and emitters used for looping.
Note
This function must be used instead of free(tbl) since tbl_t contains nested dynamically allocated members.
Author
Lars Hoffmann

Definition at line 7003 of file jurassic.c.

7005 {
7006
7007 /* Check pointer... */
7008 if (!tbl)
7009 return;
7010
7011 /* Loop over channels and emitters... */
7012 for (int id = 0; id < ctl->nd; id++)
7013 for (int ig = 0; ig < ctl->ng; ig++) {
7014
7015 /* Check number of pressure levels... */
7016 const int np = tbl->np[id][ig];
7017 if (np < 0)
7018 continue;
7019
7020 /* Loop over pressure levels... */
7021 for (int ip = 0; ip < np; ip++) {
7022
7023 /* Loop over temperature levels... */
7024 const int nt = tbl->nt[id][ig][ip];
7025 for (int it = 0; it < nt; it++) {
7026
7027 /* Free... */
7028 free(tbl->logu[id][ig][ip][it]);
7029 free(tbl->logeps[id][ig][ip][it]);
7030 tbl->logu[id][ig][ip][it] = NULL;
7031 tbl->logeps[id][ig][ip][it] = NULL;
7032 }
7033 }
7034 }
7035
7036 /* Free... */
7037 free(tbl);
7038}

◆ tbl_pack()

void tbl_pack ( const tbl_t *  tbl,
int  id,
int  ig,
uint8_t *  buf,
size_t *  bytes_used 
)

Pack a lookup table into a contiguous binary buffer.

This function serializes the lookup table data for a given detector (id) and emitter (ig) into a compact, platform-native binary representation. The packed data can be written to disk (e.g., in a NetCDF variable) and later reconstructed using tbl_unpack().

The packed layout in buf is, in order:

  • int np : number of pressure grid points
  • double p[np] : pressure grid
  • for each pressure index ip:
    • int nt : number of temperature grid points
    • double t[nt] : temperature grid
    • for each temperature index it:
      • int nu : number of spectral grid points
      • float u[nu] : spectral values
      • float eps[nu] : associated epsilon values

No byte-order conversion or padding is applied; the data are written exactly as laid out in memory.

Parameters
[in]tblTable structure containing the lookup data.
[in]idDetector index.
[in]igEmitter index.
[out]bufDestination buffer that will receive the packed binary data.
[out]bytes_usedNumber of bytes written to buf.
Warning
The caller must ensure that buf is large enough to hold the packed data for the selected detector/emitter pair. The packed representation includes the detector filter function (mandatory for binary/netCDF formats). No bounds checking is performed inside this function.
See also
tbl_unpack()
Author
Lars Hoffmann

Definition at line 7042 of file jurassic.c.

7047 {
7048
7049 uint8_t *cur = buf;
7050
7051 /* Pack lookup table... */
7052 int np = tbl->np[id][ig];
7053 memcpy(cur, &np, sizeof(np));
7054 cur += sizeof(np);
7055
7056 memcpy(cur, tbl->p[id][ig], (size_t) np * sizeof(double));
7057 cur += ((size_t) np * sizeof(double));
7058
7059 for (int ip = 0; ip < np; ip++) {
7060 int nt = tbl->nt[id][ig][ip];
7061 memcpy(cur, &nt, sizeof(nt));
7062 cur += sizeof(nt);
7063
7064 memcpy(cur, tbl->t[id][ig][ip], (size_t) nt * sizeof(double));
7065 cur += ((size_t) nt * sizeof(double));
7066
7067 for (int it = 0; it < nt; it++) {
7068 int nu = tbl->nu[id][ig][ip][it];
7069 memcpy(cur, &nu, sizeof(nu));
7070 cur += sizeof(nu);
7071
7072 memcpy(cur, tbl->logu[id][ig][ip][it], (size_t) nu * sizeof(float));
7073 cur += ((size_t) nu * sizeof(float));
7074
7075 memcpy(cur, tbl->logeps[id][ig][ip][it], (size_t) nu * sizeof(float));
7076 cur += ((size_t) nu * sizeof(float));
7077 }
7078 }
7079
7080 /* Pack filter function... */
7081 const int n = tbl->filt_n[id];
7082 memcpy(cur, &n, sizeof(n));
7083 cur += sizeof(n);
7084
7085 memcpy(cur, tbl->filt_nu[id], (size_t) n * sizeof(double));
7086 cur += ((size_t) n * sizeof(double));
7087
7088 memcpy(cur, tbl->filt_f[id], (size_t) n * sizeof(double));
7089 cur += ((size_t) n * sizeof(double));
7090
7091 *bytes_used = (size_t) (cur - buf);
7092}

◆ tbl_packed_size()

size_t tbl_packed_size ( const tbl_t *  tbl,
int  id,
int  ig 
)

Compute required buffer size (in bytes) for tbl_pack().

Returns the exact number of bytes that tbl_pack() will write for the given detector/emitter pair (including the mandatory filter function).

See also
tbl_pack()
Author
Lars Hoffmann

Definition at line 7096 of file jurassic.c.

7099 {
7100
7101 size_t bytes = 0;
7102
7103 /* Size of lookup table... */
7104 const int np = tbl->np[id][ig];
7105 bytes += sizeof(int);
7106 bytes += ((size_t) np * sizeof(double));
7107
7108 for (int ip = 0; ip < np; ip++) {
7109 const int nt = tbl->nt[id][ig][ip];
7110 bytes += sizeof(int);
7111 bytes += ((size_t) nt * sizeof(double));
7112
7113 for (int it = 0; it < nt; it++) {
7114 const int nu = tbl->nu[id][ig][ip][it];
7115 bytes += sizeof(int);
7116 bytes += (2 * (size_t) nu * sizeof(float));
7117 }
7118 }
7119
7120 /* Size of filter function... */
7121 const int n = tbl->filt_n[id];
7122 bytes += sizeof(int);
7123 bytes += (2 * (size_t) n * sizeof(double));
7124
7125 return bytes;
7126}

◆ tbl_unpack()

size_t tbl_unpack ( tbl_t *  tbl,
int  id,
int  ig,
const uint8_t *  buf 
)

Unpack a lookup table from a contiguous binary buffer.

This function reconstructs the lookup table data for a given detector (id) and emitter (ig) from a binary buffer previously produced by tbl_pack(). The packed data are read sequentially and copied into the corresponding fields of the tbl structure.

The expected layout of buf is:

  • int np
  • double p[np]
  • for each pressure index ip:
    • int nt
    • double t[nt]
    • for each temperature index it:
      • int nu
      • float u[nu]
      • float eps[nu]

Range checks are applied to np, nt, and nu against the compile-time limits TBLNP, TBLNT, and TBLNU to prevent buffer overruns and invalid table sizes.

Parameters
[in,out]tblTable structure that will receive the unpacked data.
[in]idDetector index.
[in]igEmitter index.
[in]bufSource buffer containing the packed binary table.
Returns
The number of bytes consumed from buf.
Warning
The buffer must contain a valid packed table created by tbl_pack(). Supplying malformed or truncated data will result in undefined behavior or an error.
See also
tbl_pack()
Author
Lars Hoffmann

Definition at line 7130 of file jurassic.c.

7134 {
7135
7136 const uint8_t *cur = buf;
7137
7138 /* Unpack lookup table... */
7139 int np;
7140 memcpy(&np, cur, sizeof(np));
7141 cur += sizeof(np);
7142
7143 if (np < 0 || np > TBLNP)
7144 ERRMSG("np out of range!");
7145 tbl->np[id][ig] = np;
7146
7147 memcpy(tbl->p[id][ig], cur, (size_t) np * sizeof(double));
7148 cur += ((size_t) np * sizeof(double));
7149
7150 for (int ip = 0; ip < np; ip++) {
7151
7152 int nt;
7153 memcpy(&nt, cur, sizeof(nt));
7154 cur += sizeof(nt);
7155
7156 if (nt < 0 || nt > TBLNT)
7157 ERRMSG("nt out of range!");
7158 tbl->nt[id][ig][ip] = nt;
7159
7160 memcpy(tbl->t[id][ig][ip], cur, (size_t) nt * sizeof(double));
7161 cur += ((size_t) nt * sizeof(double));
7162
7163 for (int it = 0; it < nt; it++) {
7164
7165 int nu;
7166 memcpy(&nu, cur, sizeof(nu));
7167 cur += sizeof(nu);
7168
7169 if (nu < 0 || nu > TBLNU)
7170 ERRMSG("nu out of range!");
7171 tbl->nu[id][ig][ip][it] = nu;
7172
7173 ALLOC(tbl->logu[id][ig][ip][it], float,
7174 nu);
7175 ALLOC(tbl->logeps[id][ig][ip][it], float,
7176 nu);
7177
7178 memcpy(tbl->logu[id][ig][ip][it], cur, (size_t) nu * sizeof(float));
7179 cur += ((size_t) nu * sizeof(float));
7180
7181 memcpy(tbl->logeps[id][ig][ip][it], cur, (size_t) nu * sizeof(float));
7182 cur += ((size_t) nu * sizeof(float));
7183 }
7184 }
7185
7186 /* Unpack filter function... */
7187 int n;
7188 memcpy(&n, cur, sizeof(n));
7189 cur += sizeof(n);
7190
7191 if (n < 2 || n > NSHAPE)
7192 ERRMSG("Missing or invalid filter function (filt_n) in packed table!");
7193 tbl->filt_n[id] = n;
7194
7195 memcpy(tbl->filt_nu[id], cur, (size_t) n * sizeof(double));
7196 cur += ((size_t) n * sizeof(double));
7197
7198 memcpy(tbl->filt_f[id], cur, (size_t) n * sizeof(double));
7199 cur += ((size_t) n * sizeof(double));
7200
7201 return (size_t) (cur - buf);
7202}

◆ time2jsec()

void time2jsec ( const int  year,
const int  mon,
const int  day,
const int  hour,
const int  min,
const int  sec,
const double  remain,
double *  jsec 
)

Converts time components to seconds since January 1, 2000, 12:00:00 UTC.

This function calculates the number of seconds elapsed since January 1, 2000, 12:00:00 UTC, based on the provided year, month, day, hour, minute, and second. It also includes a fractional part to represent the remaining seconds.

Parameters
yearThe year.
monThe month (1-12).
dayThe day of the month (1-31).
hourThe hour of the day (0-23).
minThe minute (0-59).
secThe second (0-59).
remainThe fractional part of seconds.
jsecPointer to store the calculated number of seconds since January 1, 2000, 12:00:00 UTC.

The function calculates the time elapsed since January 1, 2000, 12:00:00 UTC, up to the specified time and includes any fractional seconds indicated by the "remain" parameter.

Note
The function uses the timegm function, which is similar to mktime but operates in UTC.
Author
Lars Hoffmann

Definition at line 7206 of file jurassic.c.

7214 {
7215
7216 struct tm t0, t1;
7217
7218 t0.tm_year = 100;
7219 t0.tm_mon = 0;
7220 t0.tm_mday = 1;
7221 t0.tm_hour = 0;
7222 t0.tm_min = 0;
7223 t0.tm_sec = 0;
7224
7225 t1.tm_year = year - 1900;
7226 t1.tm_mon = mon - 1;
7227 t1.tm_mday = day;
7228 t1.tm_hour = hour;
7229 t1.tm_min = min;
7230 t1.tm_sec = sec;
7231
7232 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
7233}

◆ timer_group()

void timer_group ( const char *  name,
const char *  group,
int  output 
)

Aggregate wall-clock timings for named code phases.

Tracks elapsed time for the currently active timer and accumulates it both per timer name and per timer group. Calling the function with output set to a non-zero value prints the current timing summary including total time, minimum, mean, standard deviation, maximum, and sample count for each timer.

Parameters
[in]nameName of the next timer to activate.
[in]groupGroup name of the next timer to activate.
[in]outputIf non-zero, print the accumulated timing summary.
Note
Intended for coarse profiling; this interface is not thread-safe.

Definition at line 7237 of file jurassic.c.

7240 {
7241
7242 static char names[NTIMER][100], groups[NTIMER][100];
7243 static double rt_name[NTIMER], rt_group[NTIMER], rt_min[NTIMER],
7244 rt_max[NTIMER], rt_sq[NTIMER], t0, t1;
7245 static int ct_name[NTIMER], iname = -1, igroup = -1, nname, ngroup;
7246
7247 /* Get time... */
7248 t1 = omp_get_wtime();
7249 const double dt = t1 - t0;
7250
7251 /* Accumulate runtime for current timer... */
7252 if (iname >= 0) {
7253 rt_name[iname] += dt;
7254 rt_sq[iname] += POW2(dt);
7255 rt_min[iname] = (ct_name[iname] <= 0 ? dt : MIN(rt_min[iname], dt));
7256 rt_max[iname] = (ct_name[iname] <= 0 ? dt : MAX(rt_max[iname], dt));
7257 ct_name[iname]++;
7258 }
7259 if (igroup >= 0)
7260 rt_group[igroup] += dt;
7261
7262 /* Write summary... */
7263 if (output) {
7264 for (int i = 0; i < nname; i++) {
7265 const double mean = rt_name[i] / ct_name[i];
7266 const double variance = MAX(0.0, rt_sq[i] / ct_name[i] - POW2(mean));
7267 LOG(1,
7268 "TIMER_%s = %.3f s (min= %g s, mean= %g s, stddev= %g s, max= %g s, n= %d)",
7269 names[i], rt_name[i], rt_min[i], mean, sqrt(variance), rt_max[i],
7270 ct_name[i]);
7271 }
7272 for (int i = 0; i < ngroup; i++)
7273 LOG(1, "TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
7274 double total = 0.0;
7275 for (int i = 0; i < nname; i++)
7276 total += rt_name[i];
7277 LOG(1, "TIMER_TOTAL = %.3f s", total);
7278 }
7279
7280 /* Identify next timer name... */
7281 for (iname = 0; iname < nname; iname++)
7282 if (strcasecmp(name, names[iname]) == 0)
7283 break;
7284 for (igroup = 0; igroup < ngroup; igroup++)
7285 if (strcasecmp(group, groups[igroup]) == 0)
7286 break;
7287
7288 /* Add new timer name if needed... */
7289 if (iname >= nname) {
7290 sprintf(names[iname], "%s", name);
7291 if ((++nname) >= NTIMER)
7292 ERRMSG("Too many timers!");
7293 }
7294
7295 /* Add new timer group if needed... */
7296 if (igroup >= ngroup) {
7297 sprintf(groups[igroup], "%s", group);
7298 if ((++ngroup) >= NTIMER)
7299 ERRMSG("Too many groups!");
7300 }
7301
7302 /* Save time stamp for next phase... */
7303 t0 = t1;
7304}
#define NTIMER
Maximum number of aggregated timers.
Definition: jurassic.h:341

◆ write_atm()

void write_atm ( const char *  dirname,
const char *  filename,
const ctl_t *  ctl,
const atm_t *  atm,
int  profile 
)

Write atmospheric data to a file.

This function writes the atmospheric dataset stored in atm to the file specified by filename, optionally prefixed by dirname. The output format (ASCII or binary) is selected based on the atmospheric format flag ctl->atmfmt. The function creates the output file, delegates the writing process to the appropriate format-specific routine, and logs summary statistics of the written atmospheric data.

Supported output formats:

The function writes:

  • Atmospheric profiles: time, altitude, longitude, latitude, pressure, temperature
  • Gas mixing ratios for each emitter (ctl->ng)
  • Extinction coefficients for each spectral window (ctl->nw)
  • Optional cloud layer or surface parameters if enabled in ctl

After writing, the function logs minimum and maximum values of the written fields for verification and diagnostic purposes.

Parameters
dirnameOptional directory in which the output file will be created. If NULL, only filename is used.
filenameName of the output file to be created and populated with atmospheric data.
ctlPointer to a control structure defining the output format and the sizes of gas, spectral, cloud, and surface parameter arrays.
atmPointer to the atmospheric data structure whose contents will be written. All required fields must be initialized and contain atm->np valid data points.
profileZero-based profile index for netCDF output. Ignored for ASCII and binary formats.
Note
The function aborts execution using ERRMSG if the file cannot be created or if an unsupported output format is requested.
Author
Lars Hoffmann

Definition at line 7308 of file jurassic.c.

7313 {
7314
7315 /* Set filename... */
7316 char file[LEN];
7317 if (dirname != NULL)
7318 sprintf(file, "%s/%s", dirname, filename);
7319 else
7320 sprintf(file, "%s", filename);
7321
7322 /* Write info... */
7323 LOG(1, "Write atmospheric data: %s", file);
7324
7325 /* Write ASCII data... */
7326 if (ctl->atmfmt == 1)
7327 write_atm_asc(file, ctl, atm);
7328
7329 /* Write binary data... */
7330 else if (ctl->atmfmt == 2)
7331 write_atm_bin(file, ctl, atm);
7332
7333 /* Write netCDF data... */
7334 else if (ctl->atmfmt == 3)
7335 write_atm_nc(file, ctl, atm, profile);
7336
7337 /* Error... */
7338 else
7339 ERRMSG("Unknown file format, check ATMFMT!");
7340
7341 /* Write info... */
7342 double mini, maxi;
7343 LOG(2, "Number of data points: %d", atm->np);
7344 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
7345 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
7346 gsl_stats_minmax(&mini, &maxi, atm->z, 1, (size_t) atm->np);
7347 LOG(2, "Altitude range: %g ... %g km", mini, maxi);
7348 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
7349 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
7350 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
7351 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
7352 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
7353 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
7354 gsl_stats_minmax(&mini, &maxi, atm->t, 1, (size_t) atm->np);
7355 LOG(2, "Temperature range: %g ... %g K", mini, maxi);
7356 for (int ig = 0; ig < ctl->ng; ig++) {
7357 gsl_stats_minmax(&mini, &maxi, atm->q[ig], 1, (size_t) atm->np);
7358 LOG(2, "Emitter %s range: %g ... %g ppv", ctl->emitter[ig], mini, maxi);
7359 }
7360 for (int iw = 0; iw < ctl->nw; iw++) {
7361 gsl_stats_minmax(&mini, &maxi, atm->k[iw], 1, (size_t) atm->np);
7362 LOG(2, "Extinction range (window %d): %g ... %g km^-1", iw, mini, maxi);
7363 }
7364 if (ctl->ncl > 0) {
7365 LOG(2, "Cloud layer: z= %g km | dz= %g km | k= %g ... %g km^-1",
7366 atm->clz, atm->cldz, atm->clk[0], atm->clk[ctl->ncl - 1]);
7367 } else
7368 LOG(2, "Cloud layer: none");
7369 if (ctl->nsf > 0) {
7370 LOG(2,
7371 "Surface: T_s = %g K | eps= %g ... %g",
7372 atm->sft, atm->sfeps[0], atm->sfeps[ctl->nsf - 1]);
7373 } else
7374 LOG(2, "Surface: none");
7375}
void write_atm_nc(const char *filename, const ctl_t *ctl, const atm_t *atm, int profile)
Write one atmospheric profile to a netCDF file.
Definition: jurassic.c:7530
void write_atm_asc(const char *filename, const ctl_t *ctl, const atm_t *atm)
Write atmospheric data to an ASCII file.
Definition: jurassic.c:7379
void write_atm_bin(const char *filename, const ctl_t *ctl, const atm_t *atm)
Write atmospheric data to a binary file.
Definition: jurassic.c:7446
Here is the call graph for this function:

◆ write_atm_asc()

void write_atm_asc ( const char *  filename,
const ctl_t *  ctl,
const atm_t *  atm 
)

Write atmospheric data to an ASCII file.

This function writes the contents of an atmospheric structure atm to an ASCII file specified by its filename. A descriptive column header is written first, documenting the meaning, units, and ordering of each data field. Atmospheric data points are then written line by line, with optional cloud and surface layer parameters appended if they are enabled in the control structure ctl.

The output columns include, in order:

  1. Time (seconds since 2000-01-01T00:00Z)
  2. Altitude [km]
  3. Longitude [deg]
  4. Latitude [deg]
  5. Pressure [hPa]
  6. Temperature [K]
  • Gas/emitter mixing ratios for each species (ctl->ng) [ppv]
  • Extinction values for each spectral window (ctl->nw) [km^-1]

If cloud layer properties are enabled (ctl->ncl > 0), the following are added:

  • Cloud layer height [km]
  • Cloud layer depth [km]
  • Cloud extinction values for each frequency (ctl->ncl) [km^-1]

If surface layer properties are enabled (ctl->nsf > 0), the following are added:

  • Surface layer height [km]
  • Surface layer pressure [hPa]
  • Surface layer temperature [K]
  • Surface emissivity values (ctl->nsf)
Parameters
filenamePath to the ASCII output file.
ctlPointer to a control structure defining the number of gases, spectral windows, and whether cloud or surface layer information should be included.
atmPointer to the atmospheric structure containing the data to be written. The function writes all atm->np data points.
Note
A blank line is inserted each time the time coordinate changes, grouping data points belonging to different timestamps.
Warning
The function assumes that all arrays in atm are properly allocated and populated. No validation of data ranges is performed here.
Author
Lars Hoffmann

Definition at line 7379 of file jurassic.c.

7382 {
7383
7384 int n = 6;
7385
7386 /* Create file... */
7387 FILE *out;
7388 if (!(out = fopen(filename, "w")))
7389 ERRMSG("Cannot create file!");
7390
7391 /* Write header... */
7392 fprintf(out,
7393 "# $1 = time (seconds since 2000-01-01T00:00Z)\n"
7394 "# $2 = altitude [km]\n"
7395 "# $3 = longitude [deg]\n"
7396 "# $4 = latitude [deg]\n"
7397 "# $5 = pressure [hPa]\n" "# $6 = temperature [K]\n");
7398 for (int ig = 0; ig < ctl->ng; ig++)
7399 fprintf(out, "# $%d = %s volume mixing ratio [ppv]\n",
7400 ++n, ctl->emitter[ig]);
7401 for (int iw = 0; iw < ctl->nw; iw++)
7402 fprintf(out, "# $%d = extinction (window %d) [km^-1]\n", ++n, iw);
7403 if (ctl->ncl > 0) {
7404 fprintf(out, "# $%d = cloud layer height [km]\n", ++n);
7405 fprintf(out, "# $%d = cloud layer depth [km]\n", ++n);
7406 for (int icl = 0; icl < ctl->ncl; icl++)
7407 fprintf(out, "# $%d = cloud layer extinction (%.4f cm^-1) [km^-1]\n",
7408 ++n, ctl->clnu[icl]);
7409 }
7410 if (ctl->nsf > 0) {
7411 fprintf(out, "# $%d = surface temperature [K]\n", ++n);
7412 for (int isf = 0; isf < ctl->nsf; isf++)
7413 fprintf(out, "# $%d = surface emissivity (%.4f cm^-1)\n",
7414 ++n, ctl->sfnu[isf]);
7415 }
7416
7417 /* Write data... */
7418 for (int ip = 0; ip < atm->np; ip++) {
7419 if (ip == 0 || atm->time[ip] != atm->time[ip - 1])
7420 fprintf(out, "\n");
7421 fprintf(out, "%.2f %g %g %g %g %g", atm->time[ip], atm->z[ip],
7422 atm->lon[ip], atm->lat[ip], atm->p[ip], atm->t[ip]);
7423 for (int ig = 0; ig < ctl->ng; ig++)
7424 fprintf(out, " %g", atm->q[ig][ip]);
7425 for (int iw = 0; iw < ctl->nw; iw++)
7426 fprintf(out, " %g", atm->k[iw][ip]);
7427 if (ctl->ncl > 0) {
7428 fprintf(out, " %g %g", atm->clz, atm->cldz);
7429 for (int icl = 0; icl < ctl->ncl; icl++)
7430 fprintf(out, " %g", atm->clk[icl]);
7431 }
7432 if (ctl->nsf > 0) {
7433 fprintf(out, " %g", atm->sft);
7434 for (int isf = 0; isf < ctl->nsf; isf++)
7435 fprintf(out, " %g", atm->sfeps[isf]);
7436 }
7437 fprintf(out, "\n");
7438 }
7439
7440 /* Close file... */
7441 fclose(out);
7442}

◆ write_atm_bin()

void write_atm_bin ( const char *  filename,
const ctl_t *  ctl,
const atm_t *  atm 
)

Write atmospheric data to a binary file.

This function writes the atmospheric dataset contained in atm to a binary file specified by its filename. The output format is compact and includes a file header followed by the serialized atmospheric fields. The format is compatible with read_atm_bin(), ensuring that files written by this function can be read back without loss of information.

The binary file structure written is as follows:

  1. Magic identifier "ATM1" (4 bytes)
  2. Header integers describing dataset layout:
    • Number of gas/emitter species (ctl->ng)
    • Number of spectral windows (ctl->nw)
    • Number of cloud extinction values (ctl->ncl)
    • Number of surface emissivity values (ctl->nsf)
  3. Data payload:
    • Number of atmospheric points np
    • Arrays of length np containing:
      • Time
      • Altitude
      • Longitude
      • Latitude
      • Pressure
      • Temperature
    • Gas mixing ratios for all emitters (ctl->ng × np)
    • Extinction coefficients for all spectral windows (ctl->nw × np)
  4. Optional parameters written only if enabled in ctl:
    • Cloud layer height, depth, and extinction values (ctl->ncl)
    • Surface temperature and emissivity values (ctl->nsf)
Parameters
filenamePath to the binary output file.
ctlPointer to a control structure specifying the number of gases, spectral windows, and whether cloud or surface layer parameters must be included.
atmPointer to the atmospheric data structure containing values to be written. All arrays must be populated and atm->np must contain the number of valid atmospheric records.
Note
This function performs no range checking or validation of the atm contents. It assumes that the memory layout matches expectations.
Warning
The binary structure must remain consistent with read_atm_bin(); modifying either implementation requires updating the other accordingly.
Author
Lars Hoffmann

Definition at line 7446 of file jurassic.c.

7449 {
7450
7451 /* Create file... */
7452 FILE *out;
7453 if (!(out = fopen(filename, "w")))
7454 ERRMSG("Cannot create file!");
7455
7456 /* Write header... */
7457 FWRITE("ATM1", char,
7458 4,
7459 out);
7460 FWRITE(&ctl->ng, int,
7461 1,
7462 out);
7463 FWRITE(&ctl->nw, int,
7464 1,
7465 out);
7466 FWRITE(&ctl->ncl, int,
7467 1,
7468 out);
7469 FWRITE(&ctl->nsf, int,
7470 1,
7471 out);
7472
7473 /* Write data... */
7474 size_t np = (size_t) atm->np;
7475 FWRITE(&np, size_t,
7476 1,
7477 out);
7478 FWRITE(atm->time, double,
7479 np,
7480 out);
7481 FWRITE(atm->z, double,
7482 np,
7483 out);
7484 FWRITE(atm->lon, double,
7485 np,
7486 out);
7487 FWRITE(atm->lat, double,
7488 np,
7489 out);
7490 FWRITE(atm->p, double,
7491 np,
7492 out);
7493 FWRITE(atm->t, double,
7494 np,
7495 out);
7496 for (int ig = 0; ig < ctl->ng; ig++)
7497 FWRITE(atm->q[ig], double,
7498 np,
7499 out);
7500 for (int iw = 0; iw < ctl->nw; iw++)
7501 FWRITE(atm->k[iw], double,
7502 np,
7503 out);
7504 if (ctl->ncl > 0) {
7505 FWRITE(&atm->clz, double,
7506 1,
7507 out);
7508 FWRITE(&atm->cldz, double,
7509 1,
7510 out);
7511 FWRITE(atm->clk, double,
7512 (size_t) ctl->ncl,
7513 out);
7514 }
7515 if (ctl->nsf > 0) {
7516 FWRITE(&atm->sft, double,
7517 1,
7518 out);
7519 FWRITE(atm->sfeps, double,
7520 (size_t) ctl->nsf,
7521 out);
7522 }
7523
7524 /* Close file... */
7525 fclose(out);
7526}
#define FWRITE(ptr, type, size, out)
Write binary data to a file.
Definition: jurassic.h:609

◆ write_atm_nc()

void write_atm_nc ( const char *  filename,
const ctl_t *  ctl,
const atm_t *  atm,
int  profile 
)

Write one atmospheric profile to a netCDF file.

This routine writes a single profile from an atm_t structure into a netCDF file using an unlimited record dimension. Multiple profiles can be stored in the same file by calling this function repeatedly with increasing profile indices, provided they fit the file's fixed level dimension.

The function creates the file if it does not exist (netCDF-4/HDF5) and defines missing dimensions/variables on the fly. Existing definitions are reused.

File layout

Dimensions:

  • profile : unlimited (record dimension)
  • level : fixed (maximum number of vertical levels stored in the file)

Variables:

  • nlev(profile) : number of valid levels for each profile (written as atm->np)
  • Core state (2-D): time,z,lon,lat,p,t(profile,level)
  • Trace gases (2-D): one variable per species named ctl->emitter[ig] with dimensions (profile,level)
  • Extinction windows (2-D): ext_win_d(profile,level)
  • Clouds (1-D, optional if ctl->ncl>0): cld_z, cld_dz, cld_k_%.4f(profile)
  • Surface (1-D, optional if ctl->nsf>0): srf_t, srf_eps_%.4f(profile)

Only the first atm->np elements along level are written for 2-D variables. The effective number of levels is stored in nlev(profile). The file uses one shared fixed level dimension for all profiles, so any later profile must satisfy atm->np <= level. (If a profile is overwritten with fewer levels than previously written, old values above nlev may remain unless explicitly filled by the caller.)

Parameters
filenameOutput netCDF file name.
ctlControl structure (defines numbers/names of optional fields, e.g., ng, nw, ncl, nsf, and emitter[]).
atmAtmospheric profile data to write (uses atm->np levels).
profileRecord index along the unlimited profile dimension.
Note
This function requires netCDF support (HAVE_NETCDF) and uses the netCDF C API. Errors are handled via the NC(...) macro.
Author
Lars Hoffmann

Definition at line 7530 of file jurassic.c.

7534 {
7535
7536 char longname[LEN], varname[LEN];
7537
7538 int ncid, varid, dim_profile, dim_level;
7539
7540 size_t level_max;
7541
7542 /* Check number of levels... */
7543 if (atm->np < 1 || atm->np > NP)
7544 ERRMSG("Number of levels out of range!");
7545
7546 /* Open or create file... */
7547 if (nc_open(filename, NC_WRITE, &ncid) != NC_NOERR)
7548 NC(nc_create(filename, NC_NETCDF4, &ncid));
7549
7550 /* Enter define mode... */
7551 int r = nc_redef(ncid);
7552 if (r != NC_NOERR && r != NC_EINDEFINE)
7553 NC(r);
7554
7555 /* Define profile dimension (unlimited)... */
7556 if (nc_inq_dimid(ncid, "profile", &dim_profile) != NC_NOERR)
7557 NC(nc_def_dim(ncid, "profile", NC_UNLIMITED, &dim_profile));
7558
7559 /* Define level dimension (fixed)... */
7560 if (nc_inq_dimid(ncid, "level", &dim_level) == NC_NOERR) {
7561 NC(nc_inq_dimlen(ncid, dim_level, &level_max));
7562 if (level_max < 1 || level_max > (size_t) NP)
7563 ERRMSG("netCDF dimension level is out of range!");
7564 if ((size_t) atm->np > level_max)
7565 ERRMSG("profile has too many levels!");
7566 } else {
7567 level_max = (size_t) atm->np;
7568 NC(nc_def_dim(ncid, "level", level_max, &dim_level));
7569 }
7570
7571 /* Set dimension IDs... */
7572 int dimids[2] = { dim_profile, dim_level };
7573
7574 /* Tunables for compression/quantization... */
7575 const int deflate_level = 0;
7576 const int quant_digits = 0;
7577
7578 /* Define nlev (1D)... */
7579 if (nc_inq_varid(ncid, "nlev", &varid) != NC_NOERR)
7580 NC_DEF_VAR("nlev", NC_INT, 1, dimids,
7581 "number of vertical levels", "1", 0, 0);
7582
7583 /* Define core variables (2D)... */
7584 if (nc_inq_varid(ncid, "time", &varid) != NC_NOERR)
7585 NC_DEF_VAR("time", NC_DOUBLE, 2, dimids,
7586 "time in seconds since 2000-01-01, 00:00 UTC", "s",
7587 deflate_level, 0);
7588
7589 if (nc_inq_varid(ncid, "z", &varid) != NC_NOERR)
7590 NC_DEF_VAR("z", NC_DOUBLE, 2, dimids, "altitude", "km", deflate_level, 0);
7591
7592 if (nc_inq_varid(ncid, "lon", &varid) != NC_NOERR)
7593 NC_DEF_VAR("lon", NC_DOUBLE, 2, dimids,
7594 "longitude", "degrees_east", deflate_level, 0);
7595
7596 if (nc_inq_varid(ncid, "lat", &varid) != NC_NOERR)
7597 NC_DEF_VAR("lat", NC_DOUBLE, 2, dimids,
7598 "latitude", "degrees_north", deflate_level, 0);
7599
7600 if (nc_inq_varid(ncid, "p", &varid) != NC_NOERR)
7601 NC_DEF_VAR("p", NC_DOUBLE, 2, dimids,
7602 "pressure", "hPa", deflate_level, quant_digits);
7603
7604 if (nc_inq_varid(ncid, "t", &varid) != NC_NOERR)
7605 NC_DEF_VAR("t", NC_DOUBLE, 2, dimids,
7606 "temperature", "K", deflate_level, quant_digits);
7607
7608 /* Write emitters (2D)... */
7609 for (int ig = 0; ig < ctl->ng; ig++)
7610 if (nc_inq_varid(ncid, ctl->emitter[ig], &varid) != NC_NOERR) {
7611 sprintf(longname, "%s volume mixing ratio", ctl->emitter[ig]);
7612 NC_DEF_VAR(ctl->emitter[ig], NC_DOUBLE, 2, dimids,
7613 longname, "ppv", deflate_level, quant_digits);
7614 }
7615
7616 /* Write extinction (2D)... */
7617 for (int iw = 0; iw < ctl->nw; iw++) {
7618 sprintf(varname, "ext_win_%d", iw);
7619 if (nc_inq_varid(ncid, varname, &varid) != NC_NOERR) {
7620 sprintf(longname, "extinction (window %d)", iw);
7621 NC_DEF_VAR(varname, NC_DOUBLE, 2, dimids,
7622 longname, "km**-1", deflate_level, quant_digits);
7623 }
7624 }
7625
7626 /* Write cloud variables (1D)... */
7627 if (ctl->ncl > 0) {
7628 if (nc_inq_varid(ncid, "cld_z", &varid) != NC_NOERR)
7629 NC_DEF_VAR("cld_z", NC_DOUBLE, 1, dimids,
7630 "cloud layer height", "km", deflate_level, quant_digits);
7631
7632 if (nc_inq_varid(ncid, "cld_dz", &varid) != NC_NOERR)
7633 NC_DEF_VAR("cld_dz", NC_DOUBLE, 1, dimids,
7634 "cloud layer depth", "km", deflate_level, quant_digits);
7635
7636 for (int icl = 0; icl < ctl->ncl; icl++) {
7637 sprintf(varname, "cld_k_%.4f", ctl->clnu[icl]);
7638 if (nc_inq_varid(ncid, varname, &varid) != NC_NOERR) {
7639 sprintf(longname, "cloud layer extinction (%.4f cm^-1)",
7640 ctl->clnu[icl]);
7641 NC_DEF_VAR(varname, NC_DOUBLE, 1, dimids, longname, "km**-1",
7642 deflate_level, quant_digits);
7643 }
7644 }
7645 }
7646
7647 /* Write surface variables (1D)... */
7648 if (ctl->nsf > 0) {
7649 if (nc_inq_varid(ncid, "srf_t", &varid) != NC_NOERR)
7650 NC_DEF_VAR("srf_t", NC_DOUBLE, 1, dimids,
7651 "surface temperature", "K", deflate_level, quant_digits);
7652
7653 for (int isf = 0; isf < ctl->nsf; isf++) {
7654 sprintf(varname, "srf_eps_%.4f", ctl->sfnu[isf]);
7655 if (nc_inq_varid(ncid, varname, &varid) != NC_NOERR) {
7656 sprintf(longname, "surface emissivity (%.4f cm^-1)", ctl->sfnu[isf]);
7657 NC_DEF_VAR(varname, NC_DOUBLE, 1, dimids, longname, "1",
7658 deflate_level, quant_digits);
7659 }
7660 }
7661 }
7662
7663 /* Leave define mode... */
7664 NC(nc_enddef(ncid));
7665
7666 /* Define hyperslabs... */
7667 size_t start[2] = { (size_t) profile, 0 };
7668 size_t count[2] = { 1, (size_t) atm->np };
7669
7670 /* Write nlev... */
7671 NC_PUT_INT("nlev", &atm->np, 1);
7672
7673 /* Write core variables... */
7674 NC_PUT_DOUBLE("time", atm->time, 1);
7675 NC_PUT_DOUBLE("z", atm->z, 1);
7676 NC_PUT_DOUBLE("lon", atm->lon, 1);
7677 NC_PUT_DOUBLE("lat", atm->lat, 1);
7678 NC_PUT_DOUBLE("p", atm->p, 1);
7679 NC_PUT_DOUBLE("t", atm->t, 1);
7680
7681 /* Write emitters... */
7682 for (int ig = 0; ig < ctl->ng; ig++)
7683 NC_PUT_DOUBLE(ctl->emitter[ig], atm->q[ig], 1);
7684
7685 /* Write extinction... */
7686 for (int iw = 0; iw < ctl->nw; iw++) {
7687 sprintf(varname, "ext_win_%d", iw);
7688 NC_PUT_DOUBLE(varname, atm->k[iw], 1);
7689 }
7690
7691 /* Write cloud variables... */
7692 if (ctl->ncl > 0) {
7693 NC_PUT_DOUBLE("cld_z", &atm->clz, 1);
7694 NC_PUT_DOUBLE("cld_dz", &atm->cldz, 1);
7695 for (int icl = 0; icl < ctl->ncl; icl++) {
7696 sprintf(varname, "cld_k_%.4f", ctl->clnu[icl]);
7697 NC_PUT_DOUBLE(varname, &atm->clk[icl], 1);
7698 }
7699 }
7700
7701 /* Write surface variables... */
7702 if (ctl->nsf > 0) {
7703 NC_PUT_DOUBLE("srf_t", &atm->sft, 1);
7704 for (int isf = 0; isf < ctl->nsf; isf++) {
7705 sprintf(varname, "srf_eps_%.4f", ctl->sfnu[isf]);
7706 NC_PUT_DOUBLE(varname, &atm->sfeps[isf], 1);
7707 }
7708 }
7709
7710 /* Close file... */
7711 NC(nc_sync(ncid));
7712 NC(nc_close(ncid));
7713}
#define NC_PUT_INT(varname, ptr, hyperslab)
Write integer data to a NetCDF variable.
Definition: jurassic.h:887
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units, level, quant)
Define a NetCDF variable with attributes.
Definition: jurassic.h:735
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
Write double precision data to a NetCDF variable.
Definition: jurassic.h:840

◆ write_atm_rfm()

void write_atm_rfm ( const char *  filename,
const ctl_t *  ctl,
const atm_t *  atm 
)

Write atmospheric profile in RFM-compatible format.

Exports the current atmospheric state to a file formatted for use with the Reference Forward Model (RFM). The file includes altitude, pressure, temperature, and volume mixing ratio profiles for each active emitter.

Parameters
[in]filenameOutput file name for the RFM atmosphere file.
[in]ctlPointer to the control structure defining active emitters.
[in]atmPointer to the atmospheric profile to export.
  • Produces a plain-text RFM atmosphere file with the following sections:
    NLAYERS
    *HGT [km]
    <altitude_1>
    ...
    *PRE [mb]
    <pressure_1>
    ...
    *TEM [K]
    <temperature_1>
    ...
    *<EMITTER> [ppmv]
    <mixing_ratio_1>
    ...
    *END
  • The first line specifies the number of vertical layers (atm->np).
  • Each subsequent block begins with a keyword (e.g., *HGT, *PRE, etc.) and lists one value per line.
  • Mixing ratios are converted from parts per volume (ppv) to parts per million (ppmv).
See also
read_atm, ctl_t, atm_t
Note
  • Compatible with the RFM “ATM” input file format.
  • Units:
    • Altitude in kilometers [km]
    • Pressure in millibars [mb]
    • Temperature in Kelvin [K]
    • Mixing ratios in parts per million by volume [ppmv]
Warning
  • Existing files with the same name will be overwritten.
  • The function assumes consistent vertical ordering (surface → top of atmosphere).
Author
Lars Hoffmann

Definition at line 7717 of file jurassic.c.

7720 {
7721
7722 /* Write info... */
7723 LOG(1, "Write RFM data: %s", filename);
7724
7725 /* Create file... */
7726 FILE *out;
7727 if (!(out = fopen(filename, "w")))
7728 ERRMSG("Cannot create file!");
7729
7730 /* Write data... */
7731 fprintf(out, "%d\n", atm->np);
7732 fprintf(out, "*HGT [km]\n");
7733 for (int ip = 0; ip < atm->np; ip++)
7734 fprintf(out, "%g\n", atm->z[ip]);
7735 fprintf(out, "*PRE [mb]\n");
7736 for (int ip = 0; ip < atm->np; ip++)
7737 fprintf(out, "%g\n", atm->p[ip]);
7738 fprintf(out, "*TEM [K]\n");
7739 for (int ip = 0; ip < atm->np; ip++)
7740 fprintf(out, "%g\n", atm->t[ip]);
7741 for (int ig = 0; ig < ctl->ng; ig++) {
7742 fprintf(out, "*%s [ppmv]\n", ctl->emitter[ig]);
7743 for (int ip = 0; ip < atm->np; ip++)
7744 fprintf(out, "%g\n", atm->q[ig][ip] * 1e6);
7745 }
7746 fprintf(out, "*END\n");
7747
7748 /* Close file... */
7749 fclose(out);
7750}

◆ write_matrix()

void write_matrix ( const char *  dirname,
const char *  filename,
const ctl_t *  ctl,
const gsl_matrix *  matrix,
const atm_t *  atm,
const obs_t *  obs,
const char *  rowspace,
const char *  colspace,
const char *  sort,
int  dataset 
)

Write a fully annotated matrix (e.g., Jacobian or gain matrix) to file.

Dispatches matrix output according to the configured matrix file format. Supported formats are ASCII (MATRIXFMT=1), binary (MATRIXFMT=2), and netCDF (MATRIXFMT=3).

Parameters
[in]dirnameOutput directory path. If NULL, only filename is used.
[in]filenameOutput matrix file name.
[in]ctlControl structure defining output format and metadata interpretation.
[in]matrixMatrix to be written.
[in]atmAtmospheric reference state used for state-space metadata.
[in]obsObservation reference state used for measurement-space metadata.
[in]rowspaceRow-space selector passed to the backend writer.
[in]colspaceColumn-space selector passed to the backend writer.
[in]sortSort-order selector passed to the backend writer.
[in]datasetZero-based dataset index for netCDF output. Ignored for ASCII and binary formats.
See also
write_matrix_asc(), write_matrix_bin(), write_matrix_nc()
Author
Lars Hoffmann

Definition at line 7754 of file jurassic.c.

7764 {
7765
7766 /* Check output flag... */
7767 if (!ctl->write_matrix)
7768 return;
7769
7770 /* Write ASCII data... */
7771 if (ctl->matrixfmt == 1)
7772 write_matrix_asc(dirname, filename, ctl, matrix, atm, obs,
7773 rowspace, colspace, sort);
7774
7775 /* Write binary data... */
7776 else if (ctl->matrixfmt == 2)
7777 write_matrix_bin(dirname, filename, matrix);
7778
7779 /* Write netCDF data... */
7780 else if (ctl->matrixfmt == 3)
7781 write_matrix_nc(dirname, filename, ctl, matrix, atm, obs,
7782 rowspace, colspace, sort, dataset);
7783
7784 /* Error... */
7785 else
7786 ERRMSG("Unknown matrix file format, check MATRIXFMT!");
7787}
void write_matrix_asc(const char *dirname, const char *filename, const ctl_t *ctl, const gsl_matrix *matrix, const atm_t *atm, const obs_t *obs, const char *rowspace, const char *colspace, const char *sort)
Write a fully annotated matrix (e.g., Jacobian or gain matrix) to an ASCII file.
Definition: jurassic.c:7791
void write_matrix_nc(const char *dirname, const char *filename, const ctl_t *ctl, const gsl_matrix *matrix, const atm_t *atm, const obs_t *obs, const char *rowspace, const char *colspace, const char *sort, int dataset)
Write a numerical matrix to a netCDF file.
Definition: jurassic.c:8013
void write_matrix_bin(const char *dirname, const char *filename, const gsl_matrix *matrix)
Write a numerical matrix to a binary file.
Definition: jurassic.c:7964
Here is the call graph for this function:

◆ write_matrix_asc()

void write_matrix_asc ( const char *  dirname,
const char *  filename,
const ctl_t *  ctl,
const gsl_matrix *  matrix,
const atm_t *  atm,
const obs_t *  obs,
const char *  rowspace,
const char *  colspace,
const char *  sort 
)

Write a fully annotated matrix (e.g., Jacobian or gain matrix) to an ASCII file.

Outputs a numerical matrix along with detailed metadata describing the row and column spaces. Depending on configuration, the rows and columns may correspond to measurement or state variables.

Parameters
[in]dirnameOutput directory path (may be NULL).
[in]filenameOutput file name.
[in]ctlPointer to control structure defining model setup and metadata.
[in]matrixPointer to GSL matrix to write (e.g., Jacobian, kernel, or covariance).
[in]atmPointer to atmospheric data structure (used when state-space indexing applies).
[in]obsPointer to observation data structure (used when measurement-space indexing applies).
[in]rowspaceSelects row labeling: "y" = measurement space, otherwise state space.
[in]colspaceSelects column labeling: "y" = measurement space, otherwise state space.
[in]sortDetermines writing order: "r" = row-major, otherwise column-major.
  • This routine writes one matrix element per line, including descriptive metadata:
    RowIndex RowMeta... ColIndex ColMeta... MatrixValue
  • The row and column metadata differ depending on space selection:
    • **Measurement space (‘'y’`)**:
      • Channel wavenumber [cm⁻¹]
      • Observation time [s since 2000-01-01T00:00Z]
      • View point altitude [km], longitude [°], latitude [°]
    • State space:
      • Quantity name (e.g., TEMPERATURE, H2O)
      • Time, altitude, longitude, latitude of the profile point
  • The header clearly documents all output columns for traceability.
See also
read_matrix, kernel, atm2x, obs2y, idx2name
Note
  • The function respects ctl->write_matrix — output is skipped if disabled.
  • Output is human-readable and can be post-processed using external tools (e.g., Python, MATLAB, GNU Octave).
  • Typically used for writing Jacobians, gain matrices, or averaging kernels.
  • Matrix orientation can be changed with sort to support row-major or column-major output.
Warning
  • Large matrices may produce very large output files.
  • Memory allocation is performed for temporary indexing arrays; ensure sufficient resources for large N, M.
  • The function overwrites existing files without confirmation.
Author
Lars Hoffmann

Definition at line 7791 of file jurassic.c.

7800 {
7801
7802 char file[LEN], quantity[LEN];
7803
7804 int *cida, *ciqa, *cipa, *cira, *rida, *riqa, *ripa, *rira;
7805
7806 size_t i, j, nc, nr;
7807
7808 /* Allocate... */
7809 ALLOC(cida, int,
7810 M);
7811 ALLOC(ciqa, int,
7812 N);
7813 ALLOC(cipa, int,
7814 N);
7815 ALLOC(cira, int,
7816 M);
7817 ALLOC(rida, int,
7818 M);
7819 ALLOC(riqa, int,
7820 N);
7821 ALLOC(ripa, int,
7822 N);
7823 ALLOC(rira, int,
7824 M);
7825
7826 /* Set filename... */
7827 if (dirname != NULL)
7828 sprintf(file, "%s/%s", dirname, filename);
7829 else
7830 sprintf(file, "%s", filename);
7831
7832 /* Write info... */
7833 LOG(1, "Write matrix: %s", file);
7834
7835 /* Create file... */
7836 FILE *out;
7837 if (!(out = fopen(file, "w")))
7838 ERRMSG("Cannot create file!");
7839
7840 /* Write header (row space)... */
7841 if (rowspace[0] == 'y') {
7842
7843 fprintf(out,
7844 "# $1 = Row: index (measurement space)\n"
7845 "# $2 = Row: channel wavenumber [cm^-1]\n"
7846 "# $3 = Row: time (seconds since 2000-01-01T00:00Z)\n"
7847 "# $4 = Row: view point altitude [km]\n"
7848 "# $5 = Row: view point longitude [deg]\n"
7849 "# $6 = Row: view point latitude [deg]\n");
7850
7851 /* Get number of rows... */
7852 nr = obs2y(ctl, obs, NULL, rida, rira);
7853
7854 } else {
7855
7856 fprintf(out,
7857 "# $1 = Row: index (state space)\n"
7858 "# $2 = Row: name of quantity\n"
7859 "# $3 = Row: time (seconds since 2000-01-01T00:00Z)\n"
7860 "# $4 = Row: altitude [km]\n"
7861 "# $5 = Row: longitude [deg]\n" "# $6 = Row: latitude [deg]\n");
7862
7863 /* Get number of rows... */
7864 nr = atm2x(ctl, atm, NULL, riqa, ripa);
7865 }
7866
7867 /* Write header (column space)... */
7868 if (colspace[0] == 'y') {
7869
7870 fprintf(out,
7871 "# $7 = Col: index (measurement space)\n"
7872 "# $8 = Col: channel wavenumber [cm^-1]\n"
7873 "# $9 = Col: time (seconds since 2000-01-01T00:00Z)\n"
7874 "# $10 = Col: view point altitude [km]\n"
7875 "# $11 = Col: view point longitude [deg]\n"
7876 "# $12 = Col: view point latitude [deg]\n");
7877
7878 /* Get number of columns... */
7879 nc = obs2y(ctl, obs, NULL, cida, cira);
7880
7881 } else {
7882
7883 fprintf(out,
7884 "# $7 = Col: index (state space)\n"
7885 "# $8 = Col: name of quantity\n"
7886 "# $9 = Col: time (seconds since 2000-01-01T00:00Z)\n"
7887 "# $10 = Col: altitude [km]\n"
7888 "# $11 = Col: longitude [deg]\n" "# $12 = Col: latitude [deg]\n");
7889
7890 /* Get number of columns... */
7891 nc = atm2x(ctl, atm, NULL, ciqa, cipa);
7892 }
7893
7894 /* Write header entry... */
7895 fprintf(out, "# $13 = Matrix element\n\n");
7896
7897 /* Write matrix data... */
7898 i = j = 0;
7899 while (i < nr && j < nc) {
7900
7901 /* Write info about the row... */
7902 if (rowspace[0] == 'y')
7903 fprintf(out, "%d %.4f %.2f %g %g %g",
7904 (int) i, ctl->nu[rida[i]],
7905 obs->time[rira[i]], obs->vpz[rira[i]],
7906 obs->vplon[rira[i]], obs->vplat[rira[i]]);
7907 else {
7908 idx2name(ctl, riqa[i], quantity);
7909 fprintf(out, "%d %s %.2f %g %g %g", (int) i, quantity,
7910 atm->time[ripa[i]], atm->z[ripa[i]],
7911 atm->lon[ripa[i]], atm->lat[ripa[i]]);
7912 }
7913
7914 /* Write info about the column... */
7915 if (colspace[0] == 'y')
7916 fprintf(out, " %d %.4f %.2f %g %g %g",
7917 (int) j, ctl->nu[cida[j]],
7918 obs->time[cira[j]], obs->vpz[cira[j]],
7919 obs->vplon[cira[j]], obs->vplat[cira[j]]);
7920 else {
7921 idx2name(ctl, ciqa[j], quantity);
7922 fprintf(out, " %d %s %.2f %g %g %g", (int) j, quantity,
7923 atm->time[cipa[j]], atm->z[cipa[j]],
7924 atm->lon[cipa[j]], atm->lat[cipa[j]]);
7925 }
7926
7927 /* Write matrix entry... */
7928 fprintf(out, " %g\n", gsl_matrix_get(matrix, i, j));
7929
7930 /* Set matrix indices... */
7931 if (sort[0] == 'r') {
7932 j++;
7933 if (j >= nc) {
7934 j = 0;
7935 i++;
7936 fprintf(out, "\n");
7937 }
7938 } else {
7939 i++;
7940 if (i >= nr) {
7941 i = 0;
7942 j++;
7943 fprintf(out, "\n");
7944 }
7945 }
7946 }
7947
7948 /* Close file... */
7949 fclose(out);
7950
7951 /* Free... */
7952 free(cida);
7953 free(ciqa);
7954 free(cipa);
7955 free(cira);
7956 free(rida);
7957 free(riqa);
7958 free(ripa);
7959 free(rira);
7960}
void idx2name(const ctl_t *ctl, const int idx, char *quantity)
Convert a quantity index to a descriptive name string.
Definition: jurassic.c:3937
#define M
Maximum size of measurement vector.
Definition: jurassic.h:281
Here is the call graph for this function:

◆ write_matrix_bin()

void write_matrix_bin ( const char *  dirname,
const char *  filename,
const gsl_matrix *  matrix 
)

Write a numerical matrix to a binary file.

Stores a compact binary representation consisting of a magic identifier, matrix dimensions, and all matrix elements in row-major order. Unlike the ASCII format, this binary format does not include annotated row/column metadata.

Parameters
[in]dirnameOutput directory path (may be NULL).
[in]filenameOutput file name.
[in]matrixPointer to GSL matrix to write.
Author
Lars Hoffmann

Definition at line 7964 of file jurassic.c.

7967 {
7968
7969 char file[LEN];
7970 const size_t nr = matrix->size1;
7971 const size_t nc = matrix->size2;
7972
7973 /* Set filename... */
7974 if (dirname != NULL)
7975 sprintf(file, "%s/%s", dirname, filename);
7976 else
7977 sprintf(file, "%s", filename);
7978
7979 /* Write info... */
7980 LOG(1, "Write matrix: %s", file);
7981
7982 /* Create file... */
7983 FILE *out;
7984 if (!(out = fopen(file, "w")))
7985 ERRMSG("Cannot create file!");
7986
7987 /* Write header... */
7988 FWRITE("MAT1", char,
7989 4,
7990 out);
7991 FWRITE(&nr, size_t,
7992 1,
7993 out);
7994 FWRITE(&nc, size_t,
7995 1,
7996 out);
7997
7998 /* Write data... */
7999 for (size_t i = 0; i < nr; i++)
8000 for (size_t j = 0; j < nc; j++) {
8001 double value = gsl_matrix_get(matrix, i, j);
8002 FWRITE(&value, double,
8003 1,
8004 out);
8005 }
8006
8007 /* Close file... */
8008 fclose(out);
8009}

◆ write_matrix_nc()

void write_matrix_nc ( const char *  dirname,
const char *  filename,
const ctl_t *  ctl,
const gsl_matrix *  matrix,
const atm_t *  atm,
const obs_t *  obs,
const char *  rowspace,
const char *  colspace,
const char *  sort,
int  dataset 
)

Write a numerical matrix to a netCDF file.

Stores one matrix record in a netCDF file using an unlimited dimension dataset, fixed dimensions row and col, and a variable matrix(dataset,row,col). The file also records the row space, column space, and sort order in per-dataset auxiliary variables. Per-row and per-column metadata are stored in auxiliary variables row_nu, row_time, row_z, row_lon, row_lat, row_quantity, col_nu, col_time, col_z, col_lon, col_lat, and col_quantity. Quantity-name strings use the fixed netCDF dimension name_strlen = 100.

Parameters
[in]dirnameOutput directory path (may be NULL).
[in]filenameOutput file name.
[in]ctlPointer to control structure.
[in]matrixPointer to GSL matrix to write.
[in]atmPointer to atmospheric data structure.
[in]obsPointer to observation data structure.
[in]rowspaceRow-space selector to store as metadata.
[in]colspaceColumn-space selector to store as metadata.
[in]sortSort-order selector to store as metadata.
[in]datasetZero-based index along the unlimited dataset dimension.
Author
Lars Hoffmann

Definition at line 8013 of file jurassic.c.

8023 {
8024
8025 char file[LEN];
8026 char quantity[LEN];
8027 const size_t name_strlen = 100;
8028
8029 int ncid, dimid_dataset, dimid_row, dimid_col, dimid_name, varid;
8030 int *cida, *ciqa, *cipa, *cira, *rida, *riqa, *ripa, *rira;
8031
8032 size_t nr = matrix->size1, nc = matrix->size2, naux;
8033
8034 /* Allocate metadata index arrays... */
8035 ALLOC(cida, int,
8036 M);
8037 ALLOC(ciqa, int,
8038 N);
8039 ALLOC(cipa, int,
8040 N);
8041 ALLOC(cira, int,
8042 M);
8043 ALLOC(rida, int,
8044 M);
8045 ALLOC(riqa, int,
8046 N);
8047 ALLOC(ripa, int,
8048 N);
8049 ALLOC(rira, int,
8050 M);
8051
8052 /* Set filename... */
8053 if (dirname != NULL)
8054 sprintf(file, "%s/%s", dirname, filename);
8055 else
8056 sprintf(file, "%s", filename);
8057
8058 /* Write info... */
8059 LOG(1, "Write matrix: %s", file);
8060
8061 /* Open or create file... */
8062 if (nc_open(file, NC_WRITE, &ncid) != NC_NOERR)
8063 NC(nc_create(file, NC_NETCDF4, &ncid));
8064
8065 /* Enter define mode... */
8066 int r = nc_redef(ncid);
8067 if (r != NC_NOERR && r != NC_EINDEFINE)
8068 NC(r);
8069
8070 /* Define dataset dimension (unlimited)... */
8071 if (nc_inq_dimid(ncid, "dataset", &dimid_dataset) != NC_NOERR)
8072 NC(nc_def_dim(ncid, "dataset", NC_UNLIMITED, &dimid_dataset));
8073
8074 /* Define row dimension (fixed)... */
8075 if (nc_inq_dimid(ncid, "row", &dimid_row) == NC_NOERR) {
8076 NC(nc_inq_dimlen(ncid, dimid_row, &naux));
8077 if (naux != nr)
8078 ERRMSG("matrix row dimension is incompatible!");
8079 } else
8080 NC(nc_def_dim(ncid, "row", nr, &dimid_row));
8081
8082 /* Define col dimension (fixed)... */
8083 if (nc_inq_dimid(ncid, "col", &dimid_col) == NC_NOERR) {
8084 NC(nc_inq_dimlen(ncid, dimid_col, &naux));
8085 if (naux != nc)
8086 ERRMSG("matrix col dimension is incompatible!");
8087 } else
8088 NC(nc_def_dim(ncid, "col", nc, &dimid_col));
8089
8090 /* Define fixed-length name dimension... */
8091 if (nc_inq_dimid(ncid, "name_strlen", &dimid_name) == NC_NOERR) {
8092 NC(nc_inq_dimlen(ncid, dimid_name, &naux));
8093 if (naux != name_strlen)
8094 ERRMSG("matrix name_strlen dimension is incompatible!");
8095 } else
8096 NC(nc_def_dim(ncid, "name_strlen", name_strlen, &dimid_name));
8097
8098 /* Define variables... */
8099 int dimids3[3] = { dimid_dataset, dimid_row, dimid_col };
8100 int dimids1[1] = { dimid_dataset };
8101 int dimids2_row[2] = { dimid_dataset, dimid_row };
8102 int dimids2_col[2] = { dimid_dataset, dimid_col };
8103 int dimids3_rowname[3] = { dimid_dataset, dimid_row, dimid_name };
8104 int dimids3_colname[3] = { dimid_dataset, dimid_col, dimid_name };
8105 if (nc_inq_varid(ncid, "matrix", &varid) != NC_NOERR) {
8106 NC(nc_def_var(ncid, "matrix", NC_DOUBLE, 3, dimids3, &varid));
8107 NC(nc_put_att_text(ncid, varid, "long_name", 14, "matrix element"));
8108 NC(nc_put_att_text(ncid, varid, "units", 1, "1"));
8109 }
8110 if (nc_inq_varid(ncid, "rowspace", &varid) != NC_NOERR)
8111 NC_DEF_VAR("rowspace", NC_CHAR, 1, dimids1,
8112 "row space selector", "1", 0, 0);
8113 if (nc_inq_varid(ncid, "colspace", &varid) != NC_NOERR)
8114 NC_DEF_VAR("colspace", NC_CHAR, 1, dimids1,
8115 "column space selector", "1", 0, 0);
8116 if (nc_inq_varid(ncid, "sort", &varid) != NC_NOERR)
8117 NC_DEF_VAR("sort", NC_CHAR, 1, dimids1,
8118 "matrix sort selector", "1", 0, 0);
8119 if (nc_inq_varid(ncid, "row_nu", &varid) != NC_NOERR)
8120 NC_DEF_VAR("row_nu", NC_DOUBLE, 2, dimids2_row,
8121 "row channel wavenumber", "cm^-1", 0, 0);
8122 if (nc_inq_varid(ncid, "row_time", &varid) != NC_NOERR)
8123 NC_DEF_VAR("row_time", NC_DOUBLE, 2, dimids2_row,
8124 "row time since 2000-01-01T00:00Z", "s", 0, 0);
8125 if (nc_inq_varid(ncid, "row_z", &varid) != NC_NOERR)
8126 NC_DEF_VAR("row_z", NC_DOUBLE, 2, dimids2_row,
8127 "row altitude", "km", 0, 0);
8128 if (nc_inq_varid(ncid, "row_lon", &varid) != NC_NOERR)
8129 NC_DEF_VAR("row_lon", NC_DOUBLE, 2, dimids2_row,
8130 "row longitude", "degrees_east", 0, 0);
8131 if (nc_inq_varid(ncid, "row_lat", &varid) != NC_NOERR)
8132 NC_DEF_VAR("row_lat", NC_DOUBLE, 2, dimids2_row,
8133 "row latitude", "degrees_north", 0, 0);
8134 if (nc_inq_varid(ncid, "row_quantity", &varid) != NC_NOERR)
8135 NC_DEF_VAR("row_quantity", NC_CHAR, 3, dimids3_rowname,
8136 "row state quantity name", "1", 0, 0);
8137 if (nc_inq_varid(ncid, "col_nu", &varid) != NC_NOERR)
8138 NC_DEF_VAR("col_nu", NC_DOUBLE, 2, dimids2_col,
8139 "column channel wavenumber", "cm^-1", 0, 0);
8140 if (nc_inq_varid(ncid, "col_time", &varid) != NC_NOERR)
8141 NC_DEF_VAR("col_time", NC_DOUBLE, 2, dimids2_col,
8142 "column time since 2000-01-01T00:00Z", "s", 0, 0);
8143 if (nc_inq_varid(ncid, "col_z", &varid) != NC_NOERR)
8144 NC_DEF_VAR("col_z", NC_DOUBLE, 2, dimids2_col,
8145 "column altitude", "km", 0, 0);
8146 if (nc_inq_varid(ncid, "col_lon", &varid) != NC_NOERR)
8147 NC_DEF_VAR("col_lon", NC_DOUBLE, 2, dimids2_col,
8148 "column longitude", "degrees_east", 0, 0);
8149 if (nc_inq_varid(ncid, "col_lat", &varid) != NC_NOERR)
8150 NC_DEF_VAR("col_lat", NC_DOUBLE, 2, dimids2_col,
8151 "column latitude", "degrees_north", 0, 0);
8152 if (nc_inq_varid(ncid, "col_quantity", &varid) != NC_NOERR)
8153 NC_DEF_VAR("col_quantity", NC_CHAR, 3, dimids3_colname,
8154 "column state quantity name", "1", 0, 0);
8155
8156 /* Leave define mode... */
8157 NC(nc_enddef(ncid));
8158
8159 /* Write metadata... */
8160 size_t start1[1] = { (size_t) dataset };
8161 size_t count1[1] = { 1 };
8162 NC(nc_inq_varid(ncid, "rowspace", &varid));
8163 NC(nc_put_vara_text(ncid, varid, start1, count1, rowspace));
8164 NC(nc_inq_varid(ncid, "colspace", &varid));
8165 NC(nc_put_vara_text(ncid, varid, start1, count1, colspace));
8166 NC(nc_inq_varid(ncid, "sort", &varid));
8167 NC(nc_put_vara_text(ncid, varid, start1, count1, sort));
8168
8169 /* Set row and column metadata indices... */
8170 if (rowspace[0] == 'y')
8171 nr = obs2y(ctl, obs, NULL, rida, rira);
8172 else
8173 nr = atm2x(ctl, atm, NULL, riqa, ripa);
8174 if (colspace[0] == 'y')
8175 nc = obs2y(ctl, obs, NULL, cida, cira);
8176 else
8177 nc = atm2x(ctl, atm, NULL, ciqa, cipa);
8178
8179 /* Write row metadata... */
8180 for (size_t i = 0; i < nr; i++) {
8181 const double nu = rowspace[0] == 'y' ? ctl->nu[rida[i]] : GSL_NAN;
8182 const double time =
8183 rowspace[0] == 'y' ? obs->time[rira[i]] : atm->time[ripa[i]];
8184 const double z = rowspace[0] == 'y' ? obs->vpz[rira[i]] : atm->z[ripa[i]];
8185 const double lon =
8186 rowspace[0] == 'y' ? obs->vplon[rira[i]] : atm->lon[ripa[i]];
8187 const double lat =
8188 rowspace[0] == 'y' ? obs->vplat[rira[i]] : atm->lat[ripa[i]];
8189 char qbuf[LEN] = { 0 };
8190 size_t start2[2] = { (size_t) dataset, i };
8191 size_t count2[2] = { 1, 1 };
8192 size_t start3n[3] = { (size_t) dataset, i, 0 };
8193 size_t count3n[3] = { 1, 1, name_strlen };
8194
8195 if (rowspace[0] != 'y') {
8196 idx2name(ctl, riqa[i], quantity);
8197 snprintf(qbuf, LEN, "%s", quantity);
8198 }
8199
8200 NC(nc_inq_varid(ncid, "row_nu", &varid));
8201 NC(nc_put_vara_double(ncid, varid, start2, count2, &nu));
8202 NC(nc_inq_varid(ncid, "row_time", &varid));
8203 NC(nc_put_vara_double(ncid, varid, start2, count2, &time));
8204 NC(nc_inq_varid(ncid, "row_z", &varid));
8205 NC(nc_put_vara_double(ncid, varid, start2, count2, &z));
8206 NC(nc_inq_varid(ncid, "row_lon", &varid));
8207 NC(nc_put_vara_double(ncid, varid, start2, count2, &lon));
8208 NC(nc_inq_varid(ncid, "row_lat", &varid));
8209 NC(nc_put_vara_double(ncid, varid, start2, count2, &lat));
8210 NC(nc_inq_varid(ncid, "row_quantity", &varid));
8211 NC(nc_put_vara_text(ncid, varid, start3n, count3n, qbuf));
8212 }
8213
8214 /* Write column metadata... */
8215 for (size_t j = 0; j < nc; j++) {
8216 const double nu = colspace[0] == 'y' ? ctl->nu[cida[j]] : GSL_NAN;
8217 const double time =
8218 colspace[0] == 'y' ? obs->time[cira[j]] : atm->time[cipa[j]];
8219 const double z = colspace[0] == 'y' ? obs->vpz[cira[j]] : atm->z[cipa[j]];
8220 const double lon =
8221 colspace[0] == 'y' ? obs->vplon[cira[j]] : atm->lon[cipa[j]];
8222 const double lat =
8223 colspace[0] == 'y' ? obs->vplat[cira[j]] : atm->lat[cipa[j]];
8224 char qbuf[LEN] = { 0 };
8225 size_t start2[2] = { (size_t) dataset, j };
8226 size_t count2[2] = { 1, 1 };
8227 size_t start3n[3] = { (size_t) dataset, j, 0 };
8228 size_t count3n[3] = { 1, 1, name_strlen };
8229
8230 if (colspace[0] != 'y') {
8231 idx2name(ctl, ciqa[j], quantity);
8232 snprintf(qbuf, LEN, "%s", quantity);
8233 }
8234
8235 NC(nc_inq_varid(ncid, "col_nu", &varid));
8236 NC(nc_put_vara_double(ncid, varid, start2, count2, &nu));
8237 NC(nc_inq_varid(ncid, "col_time", &varid));
8238 NC(nc_put_vara_double(ncid, varid, start2, count2, &time));
8239 NC(nc_inq_varid(ncid, "col_z", &varid));
8240 NC(nc_put_vara_double(ncid, varid, start2, count2, &z));
8241 NC(nc_inq_varid(ncid, "col_lon", &varid));
8242 NC(nc_put_vara_double(ncid, varid, start2, count2, &lon));
8243 NC(nc_inq_varid(ncid, "col_lat", &varid));
8244 NC(nc_put_vara_double(ncid, varid, start2, count2, &lat));
8245 NC(nc_inq_varid(ncid, "col_quantity", &varid));
8246 NC(nc_put_vara_text(ncid, varid, start3n, count3n, qbuf));
8247 }
8248
8249 /* Write matrix data... */
8250 NC(nc_inq_varid(ncid, "matrix", &varid));
8251 for (size_t i = 0; i < nr; i++)
8252 for (size_t j = 0; j < nc; j++) {
8253 const double value = gsl_matrix_get(matrix, i, j);
8254 size_t start3[3] = { (size_t) dataset, i, j };
8255 size_t count3[3] = { 1, 1, 1 };
8256 NC(nc_put_vara_double(ncid, varid, start3, count3, &value));
8257 }
8258
8259 /* Close file... */
8260 NC(nc_sync(ncid));
8261 NC(nc_close(ncid));
8262
8263 /* Free... */
8264 free(cida);
8265 free(ciqa);
8266 free(cipa);
8267 free(cira);
8268 free(rida);
8269 free(riqa);
8270 free(ripa);
8271 free(rira);
8272}
Here is the call graph for this function:

◆ write_obs()

void write_obs ( const char *  dirname,
const char *  filename,
const ctl_t *  ctl,
const obs_t *  obs,
int  profile 
)

Write observation data to an output file in ASCII or binary format.

This C function constructs the full output file path from the provided directory and filename, opens the file for writing, and exports the contents of the obs_t structure in either ASCII or binary format, depending on the observation format specified by ctl->obsfmt. The actual writing of formatted data is delegated to write_obs_asc() or write_obs_bin().

After writing, the function prints diagnostic information showing ranges of times, observer coordinates, view point coordinates, tangent point coordinates, and spectral values stored as radiance or brightness temperature depending on ctl->write_bbt, as well as transmittances. These diagnostics provide useful verification that the output data is valid and consistent.

Parameters
[in]dirnameOptional directory path. If NULL, only filename is used.
[in]filenameName of the output observation file.
[in]ctlControl structure specifying output format, spectral channel configuration, and brightness-temperature mode.
[in]obsObservation structure containing the data to be written.
[in]profileZero-based profile index for netCDF output. Ignored for ASCII and binary formats.
Note
This is a C function. The output file is always overwritten if it already exists.
Warning
The routine aborts with an error message if the output file cannot be created, or if ctl->obsfmt specifies an unsupported format.
See also
write_obs_asc(), write_obs_bin(), read_obs(), ctl_t, obs_t
Author
Lars Hoffmann

Definition at line 8276 of file jurassic.c.

8281 {
8282
8283 /* Set filename... */
8284 char file[LEN];
8285 if (dirname != NULL)
8286 sprintf(file, "%s/%s", dirname, filename);
8287 else
8288 sprintf(file, "%s", filename);
8289
8290 /* Write info... */
8291 LOG(1, "Write observation data: %s", file);
8292
8293 /* Write ASCII data... */
8294 if (ctl->obsfmt == 1)
8295 write_obs_asc(file, ctl, obs);
8296
8297 /* Write binary data... */
8298 else if (ctl->obsfmt == 2)
8299 write_obs_bin(file, ctl, obs);
8300
8301 /* Write netCDF data... */
8302 else if (ctl->obsfmt == 3)
8303 write_obs_nc(file, ctl, obs, profile);
8304
8305 /* Write info... */
8306 double mini, maxi;
8307 LOG(2, "Number of ray paths: %d", obs->nr);
8308 gsl_stats_minmax(&mini, &maxi, obs->time, 1, (size_t) obs->nr);
8309 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
8310 gsl_stats_minmax(&mini, &maxi, obs->obsz, 1, (size_t) obs->nr);
8311 LOG(2, "Observer altitude range: %g ... %g km", mini, maxi);
8312 gsl_stats_minmax(&mini, &maxi, obs->obslon, 1, (size_t) obs->nr);
8313 LOG(2, "Observer longitude range: %g ... %g deg", mini, maxi);
8314 gsl_stats_minmax(&mini, &maxi, obs->obslat, 1, (size_t) obs->nr);
8315 LOG(2, "Observer latitude range: %g ... %g deg", mini, maxi);
8316 gsl_stats_minmax(&mini, &maxi, obs->vpz, 1, (size_t) obs->nr);
8317 LOG(2, "View point altitude range: %g ... %g km", mini, maxi);
8318 gsl_stats_minmax(&mini, &maxi, obs->vplon, 1, (size_t) obs->nr);
8319 LOG(2, "View point longitude range: %g ... %g deg", mini, maxi);
8320 gsl_stats_minmax(&mini, &maxi, obs->vplat, 1, (size_t) obs->nr);
8321 LOG(2, "View point latitude range: %g ... %g deg", mini, maxi);
8322 gsl_stats_minmax(&mini, &maxi, obs->tpz, 1, (size_t) obs->nr);
8323 LOG(2, "Tangent point altitude range: %g ... %g km", mini, maxi);
8324 gsl_stats_minmax(&mini, &maxi, obs->tplon, 1, (size_t) obs->nr);
8325 LOG(2, "Tangent point longitude range: %g ... %g deg", mini, maxi);
8326 gsl_stats_minmax(&mini, &maxi, obs->tplat, 1, (size_t) obs->nr);
8327 LOG(2, "Tangent point latitude range: %g ... %g deg", mini, maxi);
8328 for (int id = 0; id < ctl->nd; id++) {
8329 gsl_stats_minmax(&mini, &maxi, obs->rad[id], 1, (size_t) obs->nr);
8330 if (ctl->write_bbt) {
8331 LOG(2, "Brightness temperature (%.4f cm^-1) range: %g ... %g K",
8332 ctl->nu[id], mini, maxi);
8333 } else {
8334 LOG(2, "Radiance (%.4f cm^-1) range: %g ... %g W/(m^2 sr cm^-1)",
8335 ctl->nu[id], mini, maxi);
8336 }
8337 }
8338 for (int id = 0; id < ctl->nd; id++) {
8339 gsl_stats_minmax(&mini, &maxi, obs->tau[id], 1, (size_t) obs->nr);
8340 LOG(2, "Transmittance (%.4f cm^-1) range: %g ... %g",
8341 ctl->nu[id], mini, maxi);
8342 }
8343}
void write_obs_asc(const char *filename, const ctl_t *ctl, const obs_t *obs)
Write observation data to an ASCII text file.
Definition: jurassic.c:8347
void write_obs_nc(const char *filename, const ctl_t *ctl, const obs_t *obs, const int profile)
Write one observation profile to a NetCDF file.
Definition: jurassic.c:8471
void write_obs_bin(const char *filename, const ctl_t *ctl, const obs_t *obs)
Write observation data in binary format to a file.
Definition: jurassic.c:8403
Here is the call graph for this function:

◆ write_obs_asc()

void write_obs_asc ( const char *  filename,
const ctl_t *  ctl,
const obs_t *  obs 
)

Write observation data to an ASCII text file.

This C function writes the contents of the obs_t observation structure as human-readable ASCII text to a file specified by its filename. It first prints a descriptive header that documents each column of the output format, including observation time, observer and view geometry, tangent point information, and spectral values. The number and meaning of spectral fields depend on ctl->nd and whether brightness temperature output is enabled via ctl->write_bbt.

The function then writes one line of data per ray path, including the base geometric information followed by spectral values labeled as radiance or brightness temperature according to ctl->write_bbt, and transmittances for each spectral channel. Blank lines are inserted whenever the time stamp changes, providing visual separation of distinct observation groups.

Parameters
filenamePath to the ASCII output file.
ctlControl structure specifying the number of spectral channels (nd), wavenumbers (nu), and output mode (write_bbt).
obsObservation structure containing the data to be written.
Note
This routine produces plain-text output intended for inspection, debugging, and compatibility with external processing tools.
Warning
The caller must ensure that the file specified by filename is writable. Existing files may be overwritten.
See also
write_obs(), write_obs_bin(), ctl_t, obs_t
Author
Lars Hoffmann

Definition at line 8347 of file jurassic.c.

8350 {
8351
8352 int n = 10;
8353
8354 /* Create file... */
8355 FILE *out;
8356 if (!(out = fopen(filename, "w")))
8357 ERRMSG("Cannot create file!");
8358
8359 /* Write header... */
8360 fprintf(out,
8361 "# $1 = time (seconds since 2000-01-01T00:00Z)\n"
8362 "# $2 = observer altitude [km]\n"
8363 "# $3 = observer longitude [deg]\n"
8364 "# $4 = observer latitude [deg]\n"
8365 "# $5 = view point altitude [km]\n"
8366 "# $6 = view point longitude [deg]\n"
8367 "# $7 = view point latitude [deg]\n"
8368 "# $8 = tangent point altitude [km]\n"
8369 "# $9 = tangent point longitude [deg]\n"
8370 "# $10 = tangent point latitude [deg]\n");
8371 for (int id = 0; id < ctl->nd; id++)
8372 if (ctl->write_bbt)
8373 fprintf(out, "# $%d = brightness temperature (%.4f cm^-1) [K]\n",
8374 ++n, ctl->nu[id]);
8375 else
8376 fprintf(out, "# $%d = radiance (%.4f cm^-1) [W/(m^2 sr cm^-1)]\n",
8377 ++n, ctl->nu[id]);
8378 for (int id = 0; id < ctl->nd; id++)
8379 fprintf(out, "# $%d = transmittance (%.4f cm^-1) [-]\n", ++n,
8380 ctl->nu[id]);
8381
8382 /* Write data... */
8383 for (int ir = 0; ir < obs->nr; ir++) {
8384 if (ir == 0 || obs->time[ir] != obs->time[ir - 1])
8385 fprintf(out, "\n");
8386 fprintf(out, "%.2f %g %g %g %g %g %g %g %g %g", obs->time[ir],
8387 obs->obsz[ir], obs->obslon[ir], obs->obslat[ir],
8388 obs->vpz[ir], obs->vplon[ir], obs->vplat[ir],
8389 obs->tpz[ir], obs->tplon[ir], obs->tplat[ir]);
8390 for (int id = 0; id < ctl->nd; id++)
8391 fprintf(out, " %g", obs->rad[id][ir]);
8392 for (int id = 0; id < ctl->nd; id++)
8393 fprintf(out, " %g", obs->tau[id][ir]);
8394 fprintf(out, "\n");
8395 }
8396
8397 /* Close file... */
8398 fclose(out);
8399}

◆ write_obs_bin()

void write_obs_bin ( const char *  filename,
const ctl_t *  ctl,
const obs_t *  obs 
)

Write observation data in binary format to a file.

This C function serializes the contents of the obs_t structure into a compact binary format and writes it to a file specified by its filename. The binary format begins with a header consisting of a magic identifier ("OBS1") and the number of spectral channels (ctl->nd). This header is used by read_obs_bin() to validate compatibility when reading.

Following the header, the function writes the number of ray paths and then sequentially outputs arrays of observation metadata, geometric parameters, spectral values stored as radiance or brightness temperature depending on ctl->write_bbt, and transmittances. All values are written in native binary representation using the FWRITE() macro, which performs buffered writes and error checking.

Parameters
filenamePath to the binary output file.
ctlControl structure specifying the number of spectral channels (nd) and corresponding configuration parameters.
obsObservation structure containing the data to be written.
Note
This routine does not perform any formatting or conversion. The resulting file is portable only to systems with compatible binary layouts (integer size, floating-point format, and endianness).
Warning
The caller must ensure that the file specified by filename is writable. Existing files may be overwritten.
See also
write_obs(), write_obs_asc(), read_obs_bin(), ctl_t, obs_t
Author
Lars Hoffmann

Definition at line 8403 of file jurassic.c.

8406 {
8407
8408 /* Create file... */
8409 FILE *out;
8410 if (!(out = fopen(filename, "w")))
8411 ERRMSG("Cannot create file!");
8412
8413 /* Write header... */
8414 FWRITE("OBS1", char,
8415 4,
8416 out);
8417 FWRITE(&ctl->nd, int,
8418 1,
8419 out);
8420
8421 /* Write data... */
8422 size_t nr = (size_t) obs->nr;
8423 FWRITE(&nr, size_t,
8424 1,
8425 out);
8426 FWRITE(obs->time, double,
8427 nr,
8428 out);
8429 FWRITE(obs->obsz, double,
8430 nr,
8431 out);
8432 FWRITE(obs->obslon, double,
8433 nr,
8434 out);
8435 FWRITE(obs->obslat, double,
8436 nr,
8437 out);
8438 FWRITE(obs->vpz, double,
8439 nr,
8440 out);
8441 FWRITE(obs->vplon, double,
8442 nr,
8443 out);
8444 FWRITE(obs->vplat, double,
8445 nr,
8446 out);
8447 FWRITE(obs->tpz, double,
8448 nr,
8449 out);
8450 FWRITE(obs->tplon, double,
8451 nr,
8452 out);
8453 FWRITE(obs->tplat, double,
8454 nr,
8455 out);
8456 for (int id = 0; id < ctl->nd; id++)
8457 FWRITE(obs->rad[id], double,
8458 nr,
8459 out);
8460 for (int id = 0; id < ctl->nd; id++)
8461 FWRITE(obs->tau[id], double,
8462 nr,
8463 out);
8464
8465 /* Close file... */
8466 fclose(out);
8467}

◆ write_obs_nc()

void write_obs_nc ( const char *  filename,
const ctl_t *  ctl,
const obs_t *  obs,
const int  profile 
)

Write one observation profile to a NetCDF file.

This function writes all geometric and spectral observation data for a single profile into a NetCDF file using a variable-per-channel layout. If the file does not exist it is created; if it already exists, the required dimensions and variables are created if missing and then extended by writing the specified profile.

The NetCDF file will contain:

  • A dimension profile (unlimited)
  • A dimension ray (fixed, number of ray paths)
  • A variable nray(profile) giving the number of rays for each profile
  • Geometry variables with dimensions (profile, ray):
    • time, obs_z, obs_lon, obs_lat
    • vp_z, vp_lon, vp_lat
    • tp_z, tp_lon, tp_lat
  • Spectral variables with dimensions (profile, ray), one per channel:
    • rad_%.4f (radiance, if ctl->write_bbt == 0)
    • bt_%.4f (brightness temperature, if ctl->write_bbt != 0)
    • tau_%.4f (transmittance) where the formatted frequency corresponds to ctl->nu[id].

Spectral data are written as physical radiance in rad_%.4f variables when ctl->write_bbt == 0, or as brightness temperature in bt_%.4f variables when ctl->write_bbt != 0. The ray dimension is fixed on first creation and all subsequently written profiles must not exceed this number of rays.

Parameters
filenamePath to the NetCDF observation file.
ctlPointer to the control structure defining spectral channels.
obsPointer to the observation structure containing the data to be written.
profileZero-based index of the profile to write.
Author
Lars Hoffmann

Definition at line 8471 of file jurassic.c.

8475 {
8476
8477 char longname[LEN], varname[LEN];
8478 const char *spec_prefix = ctl->write_bbt ? "bt" : "rad";
8479
8480 int ncid, varid, dim_profile, dim_ray;
8481
8482 size_t ray_max;
8483
8484 /* Check number of rays... */
8485 if (obs->nr < 1 || obs->nr > NR)
8486 ERRMSG("Number of ray paths out of range!");
8487
8488 /* Open or create file... */
8489 if (nc_open(filename, NC_WRITE, &ncid) != NC_NOERR)
8490 NC(nc_create(filename, NC_NETCDF4, &ncid));
8491
8492 /* Enter define mode... */
8493 int r = nc_redef(ncid);
8494 if (r != NC_NOERR && r != NC_EINDEFINE)
8495 NC(r);
8496
8497 /* Define profile dimension (unlimited)... */
8498 if (nc_inq_dimid(ncid, "profile", &dim_profile) != NC_NOERR)
8499 NC(nc_def_dim(ncid, "profile", NC_UNLIMITED, &dim_profile));
8500
8501 /* Define ray dimension (fixed)... */
8502 if (nc_inq_dimid(ncid, "ray", &dim_ray) == NC_NOERR) {
8503 NC(nc_inq_dimlen(ncid, dim_ray, &ray_max));
8504 if (ray_max < 1 || ray_max > (size_t) NR)
8505 ERRMSG("netCDF dimension ray is out of range!");
8506 if ((size_t) obs->nr > ray_max)
8507 ERRMSG("profile has too many rays!");
8508 } else {
8509 ray_max = (size_t) obs->nr;
8510 NC(nc_def_dim(ncid, "ray", ray_max, &dim_ray));
8511 }
8512
8513 /* Dimension ID array... */
8514 int dimids[2] = { dim_profile, dim_ray };
8515
8516 /* Tunables for compression/quantization... */
8517 const int deflate_level = 0;
8518 const int quant_digits = 0;
8519
8520 /* Define nray (1D over profile)... */
8521 if (nc_inq_varid(ncid, "nray", &varid) != NC_NOERR)
8522 NC_DEF_VAR("nray", NC_INT, 1, dimids, "number of ray paths", "1", 0, 0);
8523
8524 /* Define geometry variables (2D over profile, ray)... */
8525 if (nc_inq_varid(ncid, "time", &varid) != NC_NOERR)
8526 NC_DEF_VAR("time", NC_DOUBLE, 2, dimids,
8527 "time in seconds since 2000-01-01, 00:00 UTC", "s",
8528 deflate_level, 0);
8529
8530 if (nc_inq_varid(ncid, "obs_z", &varid) != NC_NOERR)
8531 NC_DEF_VAR("obs_z", NC_DOUBLE, 2, dimids,
8532 "observer altitude", "km", deflate_level, 0);
8533
8534 if (nc_inq_varid(ncid, "obs_lon", &varid) != NC_NOERR)
8535 NC_DEF_VAR("obs_lon", NC_DOUBLE, 2, dimids,
8536 "observer longitude", "degrees_east", deflate_level, 0);
8537
8538 if (nc_inq_varid(ncid, "obs_lat", &varid) != NC_NOERR)
8539 NC_DEF_VAR("obs_lat", NC_DOUBLE, 2, dimids,
8540 "observer latitude", "degrees_north", deflate_level, 0);
8541
8542 if (nc_inq_varid(ncid, "vp_z", &varid) != NC_NOERR)
8543 NC_DEF_VAR("vp_z", NC_DOUBLE, 2, dimids,
8544 "view point altitude", "km", deflate_level, 0);
8545
8546 if (nc_inq_varid(ncid, "vp_lon", &varid) != NC_NOERR)
8547 NC_DEF_VAR("vp_lon", NC_DOUBLE, 2, dimids,
8548 "view point longitude", "degrees_east", deflate_level, 0);
8549
8550 if (nc_inq_varid(ncid, "vp_lat", &varid) != NC_NOERR)
8551 NC_DEF_VAR("vp_lat", NC_DOUBLE, 2, dimids,
8552 "view point latitude", "degrees_north", deflate_level, 0);
8553
8554 if (nc_inq_varid(ncid, "tp_z", &varid) != NC_NOERR)
8555 NC_DEF_VAR("tp_z", NC_DOUBLE, 2, dimids,
8556 "tangent point altitude", "km", deflate_level, 0);
8557
8558 if (nc_inq_varid(ncid, "tp_lon", &varid) != NC_NOERR)
8559 NC_DEF_VAR("tp_lon", NC_DOUBLE, 2, dimids,
8560 "tangent point longitude", "degrees_east", deflate_level, 0);
8561
8562 if (nc_inq_varid(ncid, "tp_lat", &varid) != NC_NOERR)
8563 NC_DEF_VAR("tp_lat", NC_DOUBLE, 2, dimids,
8564 "tangent point latitude", "degrees_north", deflate_level, 0);
8565
8566 /* Define radiance/transmittance per channel (2D profile,ray)... */
8567 for (int id = 0; id < ctl->nd; id++) {
8568
8569 sprintf(varname, "%s_%.4f", spec_prefix, ctl->nu[id]);
8570 if (nc_inq_varid(ncid, varname, &varid) != NC_NOERR) {
8571 if (ctl->write_bbt) {
8572 sprintf(longname, "brightness temperature (%.4f cm^-1)", ctl->nu[id]);
8573 NC_DEF_VAR(varname, NC_DOUBLE, 2, dimids, longname, "K",
8574 deflate_level, quant_digits);
8575 } else {
8576 sprintf(longname, "radiance (%.4f cm^-1)", ctl->nu[id]);
8577 NC_DEF_VAR(varname, NC_DOUBLE, 2, dimids, longname,
8578 "W/(m^2 sr cm^-1)", deflate_level, quant_digits);
8579 }
8580 }
8581
8582 sprintf(varname, "tau_%.4f", ctl->nu[id]);
8583 if (nc_inq_varid(ncid, varname, &varid) != NC_NOERR) {
8584 sprintf(longname, "transmittance (%.4f cm^-1)", ctl->nu[id]);
8585 NC_DEF_VAR(varname, NC_DOUBLE, 2, dimids, longname, "1",
8586 deflate_level, quant_digits);
8587 }
8588 }
8589
8590 /* Leave define mode... */
8591 NC(nc_enddef(ncid));
8592
8593 /* Hyperslabs... */
8594 size_t start[2] = { (size_t) profile, 0 };
8595 size_t count[2] = { 1, (size_t) obs->nr };
8596
8597 /* Write nray(profile)... */
8598 int nr = obs->nr;
8599 NC(nc_inq_varid(ncid, "nray", &varid));
8600 NC(nc_put_vara_int(ncid, varid, start, count, &nr));
8601
8602 /* Write geometry... */
8603 NC(nc_inq_varid(ncid, "time", &varid));
8604 NC(nc_put_vara_double(ncid, varid, start, count, obs->time));
8605
8606 NC(nc_inq_varid(ncid, "obs_z", &varid));
8607 NC(nc_put_vara_double(ncid, varid, start, count, obs->obsz));
8608
8609 NC(nc_inq_varid(ncid, "obs_lon", &varid));
8610 NC(nc_put_vara_double(ncid, varid, start, count, obs->obslon));
8611
8612 NC(nc_inq_varid(ncid, "obs_lat", &varid));
8613 NC(nc_put_vara_double(ncid, varid, start, count, obs->obslat));
8614
8615 NC(nc_inq_varid(ncid, "vp_z", &varid));
8616 NC(nc_put_vara_double(ncid, varid, start, count, obs->vpz));
8617
8618 NC(nc_inq_varid(ncid, "vp_lon", &varid));
8619 NC(nc_put_vara_double(ncid, varid, start, count, obs->vplon));
8620
8621 NC(nc_inq_varid(ncid, "vp_lat", &varid));
8622 NC(nc_put_vara_double(ncid, varid, start, count, obs->vplat));
8623
8624 NC(nc_inq_varid(ncid, "tp_z", &varid));
8625 NC(nc_put_vara_double(ncid, varid, start, count, obs->tpz));
8626
8627 NC(nc_inq_varid(ncid, "tp_lon", &varid));
8628 NC(nc_put_vara_double(ncid, varid, start, count, obs->tplon));
8629
8630 NC(nc_inq_varid(ncid, "tp_lat", &varid));
8631 NC(nc_put_vara_double(ncid, varid, start, count, obs->tplat));
8632
8633 /* Write spectral variables per channel... */
8634 for (int id = 0; id < ctl->nd; id++) {
8635 sprintf(varname, "%s_%.4f", spec_prefix, ctl->nu[id]);
8636 NC(nc_inq_varid(ncid, varname, &varid));
8637 NC(nc_put_vara_double(ncid, varid, start, count, obs->rad[id]));
8638
8639 sprintf(varname, "tau_%.4f", ctl->nu[id]);
8640 NC(nc_inq_varid(ncid, varname, &varid));
8641 NC(nc_put_vara_double(ncid, varid, start, count, obs->tau[id]));
8642 }
8643
8644 /* Close file... */
8645 NC(nc_sync(ncid));
8646 NC(nc_close(ncid));
8647}

◆ write_shape()

void write_shape ( const char *  filename,
const double *  x,
const double *  y,
const int  n 
)

Write tabulated shape function data to a text file.

Exports a shape function (typically a weighting or field-of-view profile) defined by paired arrays of x and y values to an ASCII file.

Parameters
[in]filenameOutput file name.
[in]xPointer to array of x-values (independent variable).
[in]yPointer to array of y-values (dependent variable).
[in]nNumber of data points to write.
  • Writes a plain-text table with two columns:
    # $1 = shape function x-value [-]
    # $2 = shape function y-value [-]
  • Each line contains one (x, y) pair written with high precision.
  • Typically used to export field-of-view functions, apodization kernels, or any other normalized shape profiles used by the model.
See also
read_shape
Note
  • Units are dimensionless unless otherwise defined by the application.
  • The file is fully compatible with read_shape() for re-import.
  • Output precision is set to 10 significant digits for numerical stability.
Warning
  • Existing files with the same name will be overwritten.
  • The number of points n must be consistent with the size of x and y arrays.
Author
Lars Hoffmann

Definition at line 8651 of file jurassic.c.

8655 {
8656
8657 /* Write info... */
8658 LOG(1, "Write shape function: %s", filename);
8659
8660 /* Create file... */
8661 FILE *out;
8662 if (!(out = fopen(filename, "w")))
8663 ERRMSG("Cannot create file!");
8664
8665 /* Write header... */
8666 fprintf(out,
8667 "# $1 = shape function x-value [-]\n"
8668 "# $2 = shape function y-value [-]\n\n");
8669
8670 /* Write data... */
8671 for (int i = 0; i < n; i++)
8672 fprintf(out, "%.10g %.10g\n", x[i], y[i]);
8673
8674 /* Close file... */
8675 fclose(out);
8676}

◆ write_stddev()

void write_stddev ( const char *  quantity,
const ret_t *  ret,
const ctl_t *  ctl,
const atm_t *  atm,
const gsl_matrix *  s 
)

Write retrieval standard deviation profiles to disk.

Extracts the diagonal elements of a covariance matrix (a priori, posterior, or error covariance) to obtain the standard deviations of retrieved quantities and writes them as an atmospheric profile file.

Parameters
[in]quantityName of the retrieved quantity (e.g., "apr", "pos", "err"), used to label the output file.
[in]retRetrieval configuration structure (ret_t), providing the working directory for output files.
[in]ctlGlobal control structure (ctl_t) defining retrieval setup and quantities.
[in]atmReference atmospheric state (atm_t) for spatial/geometric metadata.
[in]sCovariance matrix (gsl_matrix, n×n) from which standard deviations are derived (typically posterior covariance \(\mathbf{S}\)).

This function performs the following operations:

  1. Extracts the standard deviation vector \(\sigma_i = \sqrt{S_{ii}}\) from the diagonal of the covariance matrix \(\mathbf{S}\).
  2. Copies the reference atmospheric structure (atm) into an auxiliary structure (atm_aux) to preserve coordinate and geometric metadata.
  3. Converts the standard deviation vector into the atmospheric representation using x2atm(), thereby mapping elements of the state vector to the corresponding atmospheric quantities.
  4. Writes the result to disk as a diagnostic file:

    \[ \texttt{<ret->dir>/atm\_err\_<quantity>.tab} \]

    using the standard JURASSIC atmospheric file format.
See also
x2atm, copy_atm, write_atm, set_cov_apr, set_cov_meas
Note
  • The file naming convention follows atm_err_<quantity>.tab (e.g., atm_err_apr.tab, atm_err_pos.tab).
  • The output profile includes all state quantities defined in ctl.
  • Only diagonal uncertainties are written; correlations are not stored.
Warning
  • The covariance matrix s must be symmetric and positive-definite.
  • The state vector mapping (x2atm) must correspond to the matrix ordering.
Author
Lars Hoffmann

Definition at line 8680 of file jurassic.c.

8685 {
8686
8687 /* Get sizes... */
8688 const size_t n = s->size1;
8689
8690 /* Allocate... */
8691 atm_t *atm_aux;
8692 ALLOC(atm_aux, atm_t, 1);
8693 gsl_vector *x_aux = gsl_vector_alloc(n);
8694
8695 /* Compute standard deviation... */
8696 for (size_t i = 0; i < n; i++)
8697 gsl_vector_set(x_aux, i, sqrt(gsl_matrix_get(s, i, i)));
8698
8699 /* Write to disk... */
8700 char filename[LEN];
8701 const char *dirname;
8702 int profile;
8703 const char *shared_file = "-";
8704 copy_atm(ctl, atm_aux, atm, 1);
8705 x2atm(ctl, x_aux, atm_aux);
8706 if (strcmp(quantity, "total") == 0)
8707 shared_file = ret->shared_io_atm_err_total_file;
8708 else if (strcmp(quantity, "noise") == 0)
8709 shared_file = ret->shared_io_atm_err_noise_file;
8710 else if (strcmp(quantity, "formod") == 0)
8711 shared_file = ret->shared_io_atm_err_formod_file;
8712 sprintf(filename, "atm_err_%s.tab", quantity);
8713 const char *target =
8714 shared_io_output_target(ret, shared_file, filename, &dirname, &profile);
8715 write_atm(dirname, target, ctl, atm_aux, profile);
8716
8717 /* Free... */
8718 gsl_vector_free(x_aux);
8719}
Here is the call graph for this function:

◆ write_tbl()

void write_tbl ( const ctl_t *  ctl,
const tbl_t *  tbl 
)

Write emissivity lookup tables to disk.

Writes emissivity lookup tables stored in tbl using the output format specified by ctl->tblfmt:

  • ASCII (ctl->tblfmt == 1)
  • compact binary (ctl->tblfmt == 2)
  • netCDF (ctl->tblfmt == 3)

The function iterates over all emitters (ig) and detectors/channels (id) and dispatches the corresponding per-table writer.

Lookup tables with no pressure levels (i.e. tbl->np[id][ig] <= 0) are skipped intentionally. In this case, a warning is issued and no output artifact (file or NetCDF variable) is written for the affected table. This allows trace gases or channels with negligible contribution to be omitted cleanly from the output.

After writing the lookup tables, the associated spectral filter functions are written to separate files (format-dependent).

Parameters
[in]ctlPointer to the control structure defining the lookup table output format, base filenames, emitters, and spectral channels.
[in]tblPointer to the lookup-table structure containing the emissivity data and filter functions to be written.
Warning
If an unsupported lookup table format is specified via ctl->tblfmt, the function aborts with an error message.
Note
Missing output artifacts caused by skipped tables are handled gracefully by the corresponding readers, which treat missing tables as empty.
Author
Lars Hoffmann

Definition at line 8723 of file jurassic.c.

8725 {
8726
8727 /* Loop over emitters and detectors... */
8728 for (int ig = 0; ig < ctl->ng; ig++)
8729 for (int id = 0; id < ctl->nd; id++) {
8730
8731 /* Skip empty tables... */
8732 if (tbl->np[id][ig] <= 0) {
8733 WARN("Skip writing empty emissivity table: emitter=%s, nu=%.4f",
8734 ctl->emitter[ig], ctl->nu[id]);
8735 continue;
8736 }
8737
8738 /* Write ASCII look-up tables... */
8739 if (ctl->tblfmt == 1)
8740 write_tbl_asc(ctl, tbl, id, ig);
8741
8742 /* Write binary look-up tables... */
8743 else if (ctl->tblfmt == 2)
8744 write_tbl_bin(ctl, tbl, id, ig);
8745
8746 /* Write netCDF look-up tables... */
8747 else if (ctl->tblfmt == 3)
8748 write_tbl_nc(ctl, tbl, id, ig);
8749
8750 /* Write info... */
8751 TBL_LOG(tbl, id, ig);
8752 }
8753
8754 /* Write filter functions... */
8755 if (ctl->tblfmt == 1)
8756 for (int id = 0; id < ctl->nd; id++) {
8757 char filename[2 * LEN];
8758 sprintf(filename, "%s_%.4f.filt", ctl->tblbase, ctl->nu[id]);
8759 write_shape(filename, tbl->filt_nu[id], tbl->filt_f[id],
8760 tbl->filt_n[id]);
8761 }
8762}
void write_tbl_asc(const ctl_t *ctl, const tbl_t *tbl, const int id, const int ig)
Write one emissivity lookup table in human-readable ASCII format.
Definition: jurassic.c:8766
void write_tbl_nc(const ctl_t *ctl, const tbl_t *tbl, const int id, const int ig)
Write one packed lookup table to a NetCDF file.
Definition: jurassic.c:8850
void write_tbl_bin(const ctl_t *ctl, const tbl_t *tbl, const int id, const int ig)
Write one emissivity lookup table in compact binary format.
Definition: jurassic.c:8808
void write_shape(const char *filename, const double *x, const double *y, const int n)
Write tabulated shape function data to a text file.
Definition: jurassic.c:8651
Here is the call graph for this function:

◆ write_tbl_asc()

void write_tbl_asc ( const ctl_t *  ctl,
const tbl_t *  tbl,
const int  id,
const int  ig 
)

Write one emissivity lookup table in human-readable ASCII format.

Writes the lookup table for detector/channel index id and emitter/gas index ig to a file named:

<ctl->tblbase>_<ctl->nu[id]>_<ctl->emitter[ig]>.tab

The ASCII file contains four columns:

  1. pressure [hPa]
  2. temperature [K]
  3. column density [molecules/cm^2]
  4. emissivity [-]

A header describing the columns is always written. If the table is empty (i.e. tbl->np[id][ig] == 0), the file will contain only the header.

Parameters
[in]ctlControl structure providing filename base, frequencies, and emitter names.
[in]tblLookup table data to be written.
[in]idDetector/channel index.
[in]igEmitter/gas index.
Author
Lars Hoffmann

Definition at line 8766 of file jurassic.c.

8770 {
8771
8772 /* Set filename... */
8773 char filename[2 * LEN];
8774 sprintf(filename, "%s_%.4f_%s.tab", ctl->tblbase,
8775 ctl->nu[id], ctl->emitter[ig]);
8776
8777 /* Create file... */
8778 FILE *out;
8779 if (!(out = fopen(filename, "w"))) {
8780 ERRMSG("Cannot create emissivity table: %s", filename);
8781 } else
8782 LOG(1, "Write emissivity table: %s", filename);
8783
8784 /* Write header... */
8785 fprintf(out,
8786 "# $1 = pressure [hPa]\n"
8787 "# $2 = temperature [K]\n"
8788 "# $3 = column density [molecules/cm^2]\n"
8789 "# $4 = emissivity [-]\n");
8790
8791 /* Save table file... */
8792 for (int ip = 0; ip < tbl->np[id][ig]; ip++)
8793 for (int it = 0; it < tbl->nt[id][ig][ip]; it++) {
8794 fprintf(out, "\n");
8795 for (int iu = 0; iu < tbl->nu[id][ig][ip][it]; iu++)
8796 fprintf(out, "%g %g %e %e\n",
8797 tbl->p[id][ig][ip], tbl->t[id][ig][ip][it],
8798 exp(tbl->logu[id][ig][ip][it][iu]),
8799 exp(tbl->logeps[id][ig][ip][it][iu]));
8800 }
8801
8802 /* Close file... */
8803 fclose(out);
8804}

◆ write_tbl_bin()

void write_tbl_bin ( const ctl_t *  ctl,
const tbl_t *  tbl,
const int  id,
const int  ig 
)

Write one emissivity lookup table in compact binary format.

Writes the lookup table for detector/channel index id and emitter/gas index ig to a file named:

<ctl->tblbase>_<ctl->nu[id]>_<ctl->emitter[ig]>.bin

The file contains a length field followed by a packed byte blob produced by tbl_pack():

  • size_t nbytes : number of bytes in the packed blob
  • uint8_t blob[] : packed lookup table data (see tbl_pack())

If the table is empty (tbl->np[id][ig] == 0), the packed blob still encodes this (it includes np = 0), so the file remains a valid representation of an empty table.

Parameters
[in]ctlControl structure providing filename base, frequencies, and emitter names.
[in]tblLookup table data to be packed and written.
[in]idDetector/channel index.
[in]igEmitter/gas index.
See also
tbl_pack()
Author
Lars Hoffmann

Definition at line 8808 of file jurassic.c.

8812 {
8813
8814 /* Set filename... */
8815 char filename[2 * LEN];
8816 sprintf(filename, "%s_%.4f_%s.bin",
8817 ctl->tblbase, ctl->nu[id], ctl->emitter[ig]);
8818
8819 /* Create file... */
8820 FILE *out;
8821 if (!(out = fopen(filename, "w"))) {
8822 ERRMSG("Cannot create emissivity table: %s", filename);
8823 } else
8824 LOG(1, "Write emissivity table: %s", filename);
8825
8826 /* Pack... */
8827 size_t used = 0;
8828 const size_t need = tbl_packed_size(tbl, id, ig);
8829 uint8_t *work = NULL;
8830 ALLOC(work, uint8_t, need);
8831 tbl_pack(tbl, id, ig, work, &used);
8832 if (used != need)
8833 ERRMSG("Internal error: packed size mismatch!");
8834
8835 /* Write length and packed blob... */
8836 FWRITE(&used, size_t,
8837 1,
8838 out);
8839 FWRITE(work, uint8_t, used, out);
8840
8841 /* Close file... */
8842 fclose(out);
8843
8844 /* Free... */
8845 free(work);
8846}
void tbl_pack(const tbl_t *tbl, int id, int ig, uint8_t *buf, size_t *bytes_used)
Pack a lookup table into a contiguous binary buffer.
Definition: jurassic.c:7042
size_t tbl_packed_size(const tbl_t *tbl, int id, int ig)
Compute required buffer size (in bytes) for tbl_pack().
Definition: jurassic.c:7096
Here is the call graph for this function:

◆ write_tbl_nc()

void write_tbl_nc ( const ctl_t *  ctl,
const tbl_t *  tbl,
const int  id,
const int  ig 
)

Write one packed lookup table to a NetCDF file.

Writes the lookup table for detector/channel index id and emitter/gas index ig to the NetCDF file:

<ctl->tblbase>_<ctl->emitter[ig]>.nc

The table is stored as a packed byte blob (produced by tbl_pack()) in a variable named tbl_XXXX with a corresponding dimension len_XXXX, where XXXX is the formatted frequency ctl->nu[id]. The variable type is NC_UBYTE.

If the NetCDF file does not exist, it is created and initialized with the global attributes:

  • format_version = "1"
  • emitter = ctl->emitter[ig]

To prevent accidental overwrites, the function terminates with an error if the target variable already exists in the file.

Parameters
[in]ctlControl structure defining emitter names, frequencies, and base filename.
[in]tblLookup table data structure containing the lookup table to be packed and written.
[in]idDetector/channel index.
[in]igEmitter/gas index.
See also
tbl_pack()
Author
Lars Hoffmann

Definition at line 8850 of file jurassic.c.

8854 {
8855
8856 /* Set filename... */
8857 char filename[2 * LEN];
8858 sprintf(filename, "%s_%s.nc", ctl->tblbase, ctl->emitter[ig]);
8859
8860 /* Open or create file... */
8861 int ncid;
8862 if (nc_open(filename, NC_WRITE, &ncid) != NC_NOERR) {
8863 if (nc_create(filename, NC_NETCDF4 | NC_CLOBBER, &ncid) != NC_NOERR)
8864 ERRMSG("Cannot open or create emissivity table: %s", filename);
8865 NC_PUT_ATT_GLOBAL("format_version", "1");
8866 NC_PUT_ATT_GLOBAL("emitter", ctl->emitter[ig]);
8867 NC(nc_enddef(ncid));
8868 }
8869
8870 /* Set variable and dimension name... */
8871 char varname[LEN], dimname[LEN];
8872 sprintf(varname, "tbl_%.4f", ctl->nu[id]);
8873 sprintf(dimname, "len_%.4f", ctl->nu[id]);
8874
8875 /* Write info... */
8876 LOG(1, "Write emissivity table: %s in %s", varname, filename);
8877
8878 /* Allocate work space... */
8879 size_t used = 0;
8880 const size_t need = tbl_packed_size(tbl, id, ig);
8881 uint8_t *work = NULL;
8882 ALLOC(work, uint8_t, need);
8883
8884 /* Pack table... */
8885 tbl_pack(tbl, id, ig, work, &used);
8886 if (used != need)
8887 ERRMSG("Internal error: packed size mismatch!");
8888
8889 /* Prevent overwrite... */
8890 int tmp;
8891 if (nc_inq_varid(ncid, varname, &tmp) == NC_NOERR)
8892 ERRMSG("Table already present!");
8893
8894 /* Add dimension and variable... */
8895 int dimid, varid;
8896 NC(nc_redef(ncid));
8897 NC(nc_def_dim(ncid, dimname, used, &dimid));
8898 int dimids[1] = { dimid };
8899 NC_DEF_VAR(varname, NC_UBYTE, 1, dimids,
8900 "Packed lookup table blob", "1", 0, 0);
8901 NC(nc_enddef(ncid));
8902
8903 /* Write data... */
8904 NC(nc_put_var_uchar(ncid, varid, (const unsigned char *) work));
8905
8906 /* Free... */
8907 free(work);
8908
8909 /* Close file... */
8910 NC(nc_close(ncid));
8911}
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
Definition: jurassic.h:926
Here is the call graph for this function:

◆ x2atm()

void x2atm ( const ctl_t *  ctl,
const gsl_vector *  x,
atm_t *  atm 
)

Map retrieval state vector back to atmospheric structure.

Updates the atmospheric data structure (atm_t) from the contents of a retrieval state vector (x). This function performs the inverse transformation of atm2x(), assigning retrieved quantities such as pressure, temperature, gas volume mixing ratios, extinction, and cloud/surface parameters to the corresponding atmospheric fields.

Parameters
[in]ctlPointer to control structure defining retrieval settings, vertical range limits, and active retrieval flags.
[in]xPointer to retrieval state vector containing the updated values.
[out]atmPointer to atmospheric data structure to be updated.
  • Each atmospheric quantity is updated only within its respective retrieval altitude range (ctl->ret*_zmin/ctl->ret*_zmax).
  • For each retrievable parameter, the helper routine x2atm_help() is called to sequentially read the next element from the state vector.
  • The order of assignments must match that in atm2x() to ensure one-to-one correspondence between state vector indices and atmospheric fields.

Quantities mapped:

  • Pressure (p[zmin:zmax])
  • Temperature (t[zmin:zmax])
  • Gas volume mixing ratios (q[ig][zmin:zmax])
  • Extinction coefficients (k[iw][zmin:zmax])
  • Cloud parameters (clz, cldz, clk)
  • Surface parameters (sft, sfeps)
See also
atm2x, x2atm_help, ctl_t, atm_t
Note
  • Only parameters marked as retrievable in ctl (e.g. ret_sft, ret_clk) are modified.
  • The state vector index (n) advances automatically as each element is read.
  • The helper function x2atm_help() abstracts sequential access to vector elements.
Warning
  • The atmospheric profile must be initialized before calling this function.
  • Retrieval ranges and flags in ctl must correspond exactly to those used in the forward-model configuration.
  • Mismatch between atm2x() and x2atm() ordering will cause incorrect mappings.
Author
Lars Hoffmann

Definition at line 8915 of file jurassic.c.

8918 {
8919
8920 size_t n = 0;
8921
8922 /* Get pressure... */
8923 for (int ip = 0; ip < atm->np; ip++)
8924 if (atm->z[ip] >= ctl->retp_zmin && atm->z[ip] <= ctl->retp_zmax)
8925 x2atm_help(&atm->p[ip], x, &n);
8926
8927 /* Get temperature... */
8928 for (int ip = 0; ip < atm->np; ip++)
8929 if (atm->z[ip] >= ctl->rett_zmin && atm->z[ip] <= ctl->rett_zmax)
8930 x2atm_help(&atm->t[ip], x, &n);
8931
8932 /* Get volume mixing ratio... */
8933 for (int ig = 0; ig < ctl->ng; ig++)
8934 for (int ip = 0; ip < atm->np; ip++)
8935 if (atm->z[ip] >= ctl->retq_zmin[ig]
8936 && atm->z[ip] <= ctl->retq_zmax[ig])
8937 x2atm_help(&atm->q[ig][ip], x, &n);
8938
8939 /* Get extinction... */
8940 for (int iw = 0; iw < ctl->nw; iw++)
8941 for (int ip = 0; ip < atm->np; ip++)
8942 if (atm->z[ip] >= ctl->retk_zmin[iw]
8943 && atm->z[ip] <= ctl->retk_zmax[iw])
8944 x2atm_help(&atm->k[iw][ip], x, &n);
8945
8946 /* Get cloud data... */
8947 if (ctl->ret_clz)
8948 x2atm_help(&atm->clz, x, &n);
8949 if (ctl->ret_cldz)
8950 x2atm_help(&atm->cldz, x, &n);
8951 if (ctl->ret_clk)
8952 for (int icl = 0; icl < ctl->ncl; icl++)
8953 x2atm_help(&atm->clk[icl], x, &n);
8954
8955 /* Get surface data... */
8956 if (ctl->ret_sft)
8957 x2atm_help(&atm->sft, x, &n);
8958 if (ctl->ret_sfeps)
8959 for (int isf = 0; isf < ctl->nsf; isf++)
8960 x2atm_help(&atm->sfeps[isf], x, &n);
8961}
void x2atm_help(double *value, const gsl_vector *x, size_t *n)
Helper function to extract a single value from the retrieval state vector.
Definition: jurassic.c:8965
Here is the call graph for this function:

◆ x2atm_help()

void x2atm_help ( double *  value,
const gsl_vector *  x,
size_t *  n 
)

Helper function to extract a single value from the retrieval state vector.

Retrieves the next element from the state vector x and assigns it to the provided scalar variable. This function is used by x2atm() to sequentially map the contents of the retrieval vector into the corresponding fields of the atmospheric structure.

Parameters
[out]valuePointer to the scalar variable to be updated.
[in]xPointer to the retrieval state vector (gsl_vector).
[in,out]nPointer to the current index in the state vector. The index is incremented after each extraction.
  • Acts as a lightweight iterator over the state vector elements.
  • Ensures consistent and sequential assignment order between atm2x() and x2atm().
  • Increments the index counter *n after reading a value, maintaining the correct position in the vector for subsequent calls.
See also
x2atm, atm2x
Note
  • The function performs no range checking; it assumes that the index is within valid bounds of the state vector length.
  • Typically used only internally by retrieval mapping routines.
Author
Lars Hoffmann

Definition at line 8965 of file jurassic.c.

8968 {
8969
8970 /* Get state vector element... */
8971 *value = gsl_vector_get(x, *n);
8972 (*n)++;
8973}

◆ y2obs()

void y2obs ( const ctl_t *  ctl,
const gsl_vector *  y,
obs_t *  obs 
)

Copy elements from the measurement vector y into the observation structure.

Decomposes the 1-D measurement vector y into its radiance components and writes them into the 2-D observation array obs->rad[id][ir], using the same ordering as produced by the corresponding forward model.

Only entries for which obs->rad[id][ir] is finite are updated. This allows missing or masked radiances to remain untouched in the observation structure.

Parameters
[in]ctlControl settings defining the number of detector channels (ctl->nd) and other retrieval configuration parameters.
[in]yMeasurement vector containing radiances in forward-model order.
[out]obsObservation structure whose radiance array (obs->rad) is to be filled with values from y.

The function loops over all ray paths (obs->nr) and detector channels (ctl->nd). For each pair (detector id, ray ir) where an existing value in obs->rad[id][ir] is finite, the next element from the measurement vector y is inserted. The counter m tracks progression through y.

This function is the inverse operation of the packing performed when constructing the measurement vector from an obs_t structure.

Note
The measurement vector y must contain as many finite elements as the number of finite entries in obs->rad, in the same scanning order.
See also
obs_t, ctl_t
Author
Lars Hoffmann

Definition at line 8977 of file jurassic.c.

8980 {
8981
8982 size_t m = 0;
8983
8984 /* Decompose measurement vector... */
8985 for (int ir = 0; ir < obs->nr; ir++)
8986 for (int id = 0; id < ctl->nd; id++)
8987 if (isfinite(obs->rad[id][ir])) {
8988 obs->rad[id][ir] = gsl_vector_get(y, m);
8989 m++;
8990 }
8991}