JURASSIC
Macros | Functions
jurassic.c File Reference

JURASSIC library definitions. More...

#include "jurassic.h"

Go to the source code of this file.

Macros

#define CLIM_TRANSITION   20.
 
#define CLIM_TOP_CONSTANT   1
 
#define CLIM_TOP_LOG   2
 

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, const clim_t *clim, atm_t *atm)
 Initializes atmospheric climatology profiles. More...
 
int read_clim_field (const char *filename, const char *varname, const int ncid, const int dim_month, const int dim_alt, const int dim_lat, const int nalt, const int nlat, double field[CT][CZ][CLAT], double *vmin, double *vmax)
 Reads and validates one JuMACS climatology field. More...
 
void climatology_external_interp (const clim_t *clim, const atm_t *atm, const double field[CT][CZ][CLAT], const int top_policy, double *out)
 Interpolates a JuMACS climatology field onto atmospheric profiles. More...
 
clim_t * read_clim (const ctl_t *ctl)
 Reads a JuMACS climatology file into an allocated climatology structure. More...
 
void climatology_external (const ctl_t *ctl, const clim_t *clim, atm_t *atm)
 Overwrites the built-in climatology with a JuMACS climatology. 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 definitions.

Definition in file jurassic.c.

Macro Definition Documentation

◆ CLIM_TRANSITION

#define CLIM_TRANSITION   20.

Definition at line 1228 of file jurassic.c.

◆ CLIM_TOP_CONSTANT

#define CLIM_TOP_CONSTANT   1

Definition at line 1235 of file jurassic.c.

◆ CLIM_TOP_LOG

#define CLIM_TOP_LOG   2

Definition at line 1236 of file jurassic.c.

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:8044
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:7597
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:3834
#define N
Maximum size of state vector.
Definition: jurassic.h:345
#define IDXCLZ
Index for cloud layer height.
Definition: jurassic.h:467
#define IDXCLDZ
Index for cloud layer depth.
Definition: jurassic.h:470
#define IDXK(iw)
Indices for extinction.
Definition: jurassic.h:464
#define NQ
Maximum number of quantities.
Definition: jurassic.h:397
#define IDXSFT
Index for surface layer temperature.
Definition: jurassic.h:476
#define IDXSFEPS(isf)
Indices for surface layer emissivity.
Definition: jurassic.h:479
#define IDXCLK(icl)
Indices for cloud layer extinction.
Definition: jurassic.h:473
#define IDXP
Index for pressure.
Definition: jurassic.h:455
#define ALLOC(ptr, type, n)
Allocate memory for an array.
Definition: jurassic.h:502
#define IDXQ(ig)
Indices for volume mixing ratios.
Definition: jurassic.h:461
#define IDXT
Index for temperature.
Definition: jurassic.h:458
Atmospheric profile data.
Definition: jurassic.h:1500
double sfeps[NSF]
Surface emissivity.
Definition: jurassic.h:1542
double k[NW][NP]
Extinction [km^-1].
Definition: jurassic.h:1527
double t[NP]
Temperature [K].
Definition: jurassic.h:1521
double clz
Cloud layer height [km].
Definition: jurassic.h:1530
double cldz
Cloud layer depth [km].
Definition: jurassic.h:1533
double sft
Surface temperature [K].
Definition: jurassic.h:1539
double clk[NCL]
Cloud layer extinction [km^-1].
Definition: jurassic.h:1536
double q[NG][NP]
Volume mixing ratio [ppv].
Definition: jurassic.h:1524
double p[NP]
Pressure [hPa].
Definition: jurassic.h:1518
int nw
Number of spectral windows.
Definition: jurassic.h:1619
int ng
Number of emitters.
Definition: jurassic.h:1595
int ncl
Number of cloud layer spectral grid points.
Definition: jurassic.h:1625
int nsf
Number of surface layer spectral grid points.
Definition: jurassic.h:1631
char shared_io_atm_res_file[LEN]
Optional shared averaging-kernel resolution output file.
Definition: jurassic.h:2002
char shared_io_atm_cont_file[LEN]
Optional shared averaging-kernel contribution output file.
Definition: jurassic.h:1999
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:1503
double z[NP]
Altitude [km].
Definition: jurassic.h:1509
double retp_zmin
Minimum altitude for pressure retrieval [km].
Definition: jurassic.h:1697
double retk_zmax[NW]
Maximum altitude for extinction retrieval [km].
Definition: jurassic.h:1718
double rett_zmax
Maximum altitude for temperature retrieval [km].
Definition: jurassic.h:1706
int ret_sfeps
Retrieve surface layer emissivity (0=no, 1=yes).
Definition: jurassic.h:1733
int ret_sft
Retrieve surface layer temperature (0=no, 1=yes).
Definition: jurassic.h:1730
int ret_clz
Retrieve cloud layer height (0=no, 1=yes).
Definition: jurassic.h:1721
double retq_zmax[NG]
Maximum altitude for volume mixing ratio retrieval [km].
Definition: jurassic.h:1712
double retq_zmin[NG]
Minimum altitude for volume mixing ratio retrieval [km].
Definition: jurassic.h:1709
double rett_zmin
Minimum altitude for temperature retrieval [km].
Definition: jurassic.h:1703
double retk_zmin[NW]
Minimum altitude for extinction retrieval [km].
Definition: jurassic.h:1715
int ret_clk
Retrieve cloud layer extinction (0=no, 1=yes).
Definition: jurassic.h:1727
int ret_cldz
Retrieve cloud layer depth (0=no, 1=yes).
Definition: jurassic.h:1724
double retp_zmax
Maximum altitude for pressure retrieval [km].
Definition: jurassic.h:1700
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:1098
#define RAD2DEG(rad)
Convert radians to degrees.
Definition: jurassic.h:1172

◆ climatology()

void climatology ( const ctl_t *  ctl,
const clim_t *  clim,
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.
[in]climPre-loaded JuMACS climatology to apply, or NULL to use only the built-in climatology. The structure is treated as read-only and remains owned by the caller.
[out]atmAtmospheric state structure to be populated with climatological data.
Author
Lars Hoffmann

Definition at line 215 of file jurassic.c.

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

◆ read_clim_field()

int read_clim_field ( const char *  filename,
const char *  varname,
const int  ncid,
const int  dim_month,
const int  dim_alt,
const int  dim_lat,
const int  nalt,
const int  nlat,
double  field[CT][CZ][CLAT],
double *  vmin,
double *  vmax 
)

Reads and validates one JuMACS climatology field.

Reads the NetCDF variable varname from an open JuMACS climatology file into a fixed-size field array. The variable must be three-dimensional with dimension order (month, altitude, lat). The complete field is read in a single nc_get_var_double() call into a compact temporary buffer and then copied into the used index range of the padded field array.

Parameters
[in]filenameName of the climatology file (for error messages).
[in]varnameName of the NetCDF variable to read.
[in]ncidNetCDF file ID of the open climatology file.
[in]dim_monthNetCDF ID of the month dimension.
[in]dim_altNetCDF ID of the altitude dimension.
[in]dim_latNetCDF ID of the lat dimension.
[in]naltNumber of altitude levels actually present.
[in]nlatNumber of latitude bands actually present.
[out]fieldFixed-size field array receiving the data.
[out]vminMinimum value over the actually read grid.
[out]vmaxMaximum value over the actually read grid.
Returns
1 if the variable was found and read, 0 if it is missing.
Note
Aborts with an error message if the variable exists but is malformed or contains non-finite values.
Author
Lars Hoffmann

Definition at line 1166 of file jurassic.c.

1177 {
1178
1179 int varid;
1180
1181 /* Skip missing variables... */
1182 if (nc_inq_varid(ncid, varname, &varid) != NC_NOERR)
1183 return 0;
1184
1185 /* Check dimensions... */
1186 int ndims = 0;
1187 int dims[3] = { -1, -1, -1 };
1188 NC(nc_inq_varndims(ncid, varid, &ndims));
1189 if (ndims != 3)
1190 ERRMSG("NetCDF variable %s in climatology file %s has wrong number of "
1191 "dimensions!", varname, filename);
1192 NC(nc_inq_vardimid(ncid, varid, dims));
1193 if (dims[0] != dim_month || dims[1] != dim_alt || dims[2] != dim_lat)
1194 ERRMSG("NetCDF variable %s in climatology file %s has wrong dimensions!",
1195 varname, filename);
1196
1197 /* Read the whole field in a single call into a compact temporary buffer
1198 and copy it into the padded target array, checking for non-finite
1199 values... */
1200 double *tmp;
1201 ALLOC(tmp, double, (size_t) CT * (size_t) nalt * (size_t) nlat);
1202 NC(nc_get_var_double(ncid, varid, tmp));
1203 double min = 1e100;
1204 double max = -1e100;
1205 for (int m = 0; m < CT; m++)
1206 for (int iz = 0; iz < nalt; iz++)
1207 for (int il = 0; il < nlat; il++) {
1208 const size_t idx = ((size_t) m * (size_t) nalt + (size_t) iz)
1209 * (size_t) nlat + (size_t) il;
1210 if (!isfinite(tmp[idx]))
1211 ERRMSG("Non-finite value in NetCDF variable %s of climatology "
1212 "file %s!", varname, filename);
1213 min = MIN(min, tmp[idx]);
1214 max = MAX(max, tmp[idx]);
1215 field[m][iz][il] = tmp[idx];
1216 }
1217 free(tmp);
1218
1219 *vmin = min;
1220 *vmax = max;
1221
1222 return 1;
1223}
#define NC(cmd)
Execute a NetCDF command and check for errors.
Definition: jurassic.h:799
#define ERRMSG(...)
Print an error message with contextual information and terminate the program.
Definition: jurassic.h:1450
#define CT
Maximum number of time steps for climatological data.
Definition: jurassic.h:370

◆ climatology_external_interp()

void climatology_external_interp ( const clim_t *  clim,
const atm_t *  atm,
const double  field[CT][CZ][CLAT],
const int  top_policy,
double *  out 
)

Interpolates a JuMACS climatology field onto atmospheric profiles.

Trilinearly interpolates a monthly zonal mean field from the JuMACS (altitude, lat) grid onto the altitude and latitude of each atmospheric profile point and overwrites the output array. In time, the field is interpolated linearly between the fixed climatological monthly center times on a 365.25-day year, with a cyclic wrap-around between December and January. Latitude is clamped at the outermost JuMACS band centers, altitude at the lowest JuMACS level. Profile points above the top of the JuMACS grid are either held at the top-level JuMACS value or blended smoothly towards the built-in climatology, according to the top-boundary policy.

Parameters
[in]climJuMACS climatology providing the altitude and latitude grids.
[in]atmAtmospheric state providing profile times, latitudes, and altitudes above the reference ellipsoid, in km.
[in]fieldClimatology field on the JuMACS grid.
[in]top_policyTop-boundary policy above the model top: 0 blends towards the built-in climatology, 1 keeps the JuMACS top-level value constant, 2 blends towards the built-in climatology in logarithmic space where both values are strictly positive.
[out]outOutput array of atm->np values to be overwritten.
Author
Lars Hoffmann

Definition at line 1258 of file jurassic.c.

1263 {
1264
1265 const double *alt = clim->alt;
1266 const double *latg = clim->lat;
1267 const int nalt = clim->nalt;
1268 const int nlat = clim->nlat;
1269
1270 /* JuMACS model top... */
1271 const double ztop = alt[nalt - 1];
1272
1273 /* Length of a climatological year [s]... */
1274 const double year = 365.25 * 86400.;
1275
1276 for (int ip = 0; ip < atm->np; ip++) {
1277
1278 /* Keep built-in climatology above the transition region, except for
1279 fields with constant extrapolation... */
1280 if (top_policy != CLIM_TOP_CONSTANT &&
1281 atm->z[ip] >= ztop + CLIM_TRANSITION)
1282 continue;
1283
1284 /* Position within the climatological year... */
1285 double sec = FMOD(atm->time[ip], year);
1286 while (sec < 0)
1287 sec += year;
1288
1289 /* Determine climatological time interval, cyclically interpolating
1290 between December and January across the turn of the year... */
1291 int it;
1292 double t0, t1;
1293 if (sec < clim->time[0]) {
1294 it = clim->ntime - 1;
1295 t0 = clim->time[it] - year;
1296 t1 = clim->time[0];
1297 } else if (sec >= clim->time[clim->ntime - 1]) {
1298 it = clim->ntime - 1;
1299 t0 = clim->time[it];
1300 t1 = clim->time[0] + year;
1301 } else {
1302 it = locate_irr(clim->time, clim->ntime, sec);
1303 t0 = clim->time[it];
1304 t1 = clim->time[it + 1];
1305 }
1306 const int it2 = (it + 1) % clim->ntime;
1307
1308 /* Latitude index (clamped at the polar band centers)... */
1309 double latq = atm->lat[ip];
1310 if (latq < latg[0])
1311 latq = latg[0];
1312 else if (latq > latg[nlat - 1])
1313 latq = latg[nlat - 1];
1314 const int il = locate_reg(latg, nlat, latq);
1315
1316 /* Altitude index (clamped at the JuMACS grid boundaries)... */
1317 double zq = atm->z[ip];
1318 if (zq < alt[0])
1319 zq = alt[0];
1320 else if (zq > ztop)
1321 zq = ztop;
1322 const int iz = locate_reg(alt, nalt, zq);
1323
1324 /* Trilinear interpolation (linear in all directions)... */
1325 const double v0 = LIN(alt[iz],
1326 LIN(latg[il], field[it][iz][il], latg[il + 1],
1327 field[it][iz][il + 1], latq),
1328 alt[iz + 1],
1329 LIN(latg[il], field[it][iz + 1][il], latg[il + 1],
1330 field[it][iz + 1][il + 1], latq), zq);
1331 const double v1 = LIN(alt[iz],
1332 LIN(latg[il], field[it2][iz][il], latg[il + 1],
1333 field[it2][iz][il + 1], latq),
1334 alt[iz + 1],
1335 LIN(latg[il], field[it2][iz + 1][il], latg[il + 1],
1336 field[it2][iz + 1][il + 1], latq), zq);
1337
1338 const double jumacs = LIN(t0, v0, t1, v1, sec);
1339
1340 /* Blend smoothly towards the built-in climatology above the model
1341 top, using a cosine taper over the transition region; before
1342 overwriting, out[] holds the built-in climatology. For gases with
1343 constant extrapolation, keep the top-level JuMACS value. For gases
1344 with logarithmic blending, taper the logarithms of the mixing
1345 ratios if both are strictly positive, falling back to the ordinary
1346 blend otherwise... */
1347 if (atm->z[ip] > ztop && top_policy != CLIM_TOP_CONSTANT) {
1348 const double x = (atm->z[ip] - ztop) / CLIM_TRANSITION;
1349 const double w = 0.5 * (1. + cos(M_PI * x));
1350 if (top_policy == CLIM_TOP_LOG && jumacs > 0. && out[ip] > 0.)
1351 out[ip] = exp(w * log(jumacs) + (1. - w) * log(out[ip]));
1352 else
1353 out[ip] = w * jumacs + (1. - w) * out[ip];
1354 } else
1355 out[ip] = jumacs;
1356 }
1357}
#define CLIM_TRANSITION
Definition: jurassic.c:1228
#define CLIM_TOP_CONSTANT
Definition: jurassic.c:1235
#define CLIM_TOP_LOG
Definition: jurassic.c:1236
int locate_irr(const double *xx, const int n, const double x)
Locate index for interpolation on an irregular grid.
Definition: jurassic.c:5218
#define FMOD(x, y)
Compute floating-point remainder.
Definition: jurassic.h:659
double lat[NP]
Latitude [deg].
Definition: jurassic.h:1515
double alt[CZ]
Altitude grid [km].
Definition: jurassic.h:1563
int ntime
Number of climatological time coordinates.
Definition: jurassic.h:1560
double time[CT]
Climatological time coordinates [s into year].
Definition: jurassic.h:1569
int nalt
Number of altitude levels.
Definition: jurassic.h:1554
double lat[CLAT]
Latitude grid [deg].
Definition: jurassic.h:1566
int nlat
Number of latitude bands.
Definition: jurassic.h:1557
Here is the call graph for this function:

◆ read_clim()

clim_t * read_clim ( const ctl_t *  ctl)

Reads a JuMACS climatology file into an allocated climatology structure.

Reads the JuMACS monthly zonal mean climatology from the file specified by the CLIM_FILE control parameter. The file is opened, validated, and closed within this routine. It must provide the dimensions month, altitude, and lat as well as coordinate variables of the same name. Fields are taken from NetCDF variables named after the quantity with a _mean suffix. A missing temperature field is an error, trace gas fields missing from the file are flagged by clim->has_q.

Parameters
[in]ctlControl parameters providing the climatology file name and the emitter list.
Returns
Pointer to an allocated and initialized clim_t structure, or NULL if the CLIM_FILE control parameter is set to "-", in which case only the built-in climatology is to be used.
Note
Aborts with an error message if the file cannot be opened or is not a valid JuMACS climatology file.
Memory for the returned structure is dynamically allocated and must be released by the caller.
Author
Lars Hoffmann

Definition at line 1361 of file jurassic.c.

1362 {
1363
1364 /* No JuMACS climatology requested... */
1365 if (strcmp(ctl->climfile, "-") == 0)
1366 return NULL;
1367
1368 /* Allocate... */
1369 clim_t *clim;
1370 ALLOC(clim, clim_t, 1);
1371
1372 /* Start with an empty climatology... */
1373 memset(clim, 0, sizeof(clim_t));
1374
1375 /* Set climatological time coordinates as seconds into a year of 365.25
1376 days, matching the centers of the twelve monthly fields... */
1377 static const double jumacs_time[CT] = { 1209600.0, 3888000.0, 6393600.0,
1378 9072000.0, 11664000.0, 14342400.0,
1379 16934400.0, 19612800.0, 22291200.0,
1380 24883200.0, 27561600.0, 30153600.0
1381 };
1382 clim->ntime = CT;
1383 memcpy(clim->time, jumacs_time, sizeof(clim->time));
1384
1385 LOG(1, "Read JuMACS climatology: %s", ctl->climfile);
1386
1387 /* Open climatology file... */
1388 int ncid;
1389 const int status = nc_open(ctl->climfile, NC_NOWRITE, &ncid);
1390 if (status != NC_NOERR)
1391 ERRMSG("Cannot open climatology file %s: %s",
1392 ctl->climfile, nc_strerror(status));
1393
1394 /* Check dimensions... */
1395 int dim_month, dim_alt, dim_lat;
1396 size_t len;
1397 if (nc_inq_dimid(ncid, "month", &dim_month) != NC_NOERR ||
1398 nc_inq_dimlen(ncid, dim_month, &len) != NC_NOERR || (int) len != 12)
1399 ERRMSG("Climatology file %s has no dimension 'month' of length 12 - "
1400 "not a JuMACS climatology file?", ctl->climfile);
1401 if (nc_inq_dimid(ncid, "altitude", &dim_alt) != NC_NOERR ||
1402 nc_inq_dimlen(ncid, dim_alt, &len) != NC_NOERR || (int) len < 2)
1403 ERRMSG("Climatology file %s has no dimension 'altitude' - "
1404 "not a JuMACS climatology file?", ctl->climfile);
1405 if ((int) len > CZ)
1406 ERRMSG("Climatology file %s has %d altitude levels, exceeding the "
1407 "maximum of %d supported by this version of JURASSIC!",
1408 ctl->climfile, (int) len, CZ);
1409 clim->nalt = (int) len;
1410 if (nc_inq_dimid(ncid, "lat", &dim_lat) != NC_NOERR ||
1411 nc_inq_dimlen(ncid, dim_lat, &len) != NC_NOERR || (int) len < 2)
1412 ERRMSG("Climatology file %s has no dimension 'lat' - "
1413 "not a JuMACS climatology file?", ctl->climfile);
1414 if ((int) len > CLAT)
1415 ERRMSG("Climatology file %s has %d latitude bands, exceeding the "
1416 "maximum of %d supported by this version of JURASSIC!",
1417 ctl->climfile, (int) len, CLAT);
1418 clim->nlat = (int) len;
1419
1420 /* Read and check coordinates... */
1421 int varid;
1422 int ndims;
1423 int dims[4];
1424 if (nc_inq_varid(ncid, "altitude", &varid) != NC_NOERR)
1425 ERRMSG("Cannot find coordinate 'altitude' in climatology file %s!",
1426 ctl->climfile);
1427 ndims = 0;
1428 NC(nc_inq_varndims(ncid, varid, &ndims));
1429 if (ndims != 1)
1430 ERRMSG("Coordinate 'altitude' in climatology file %s is not a "
1431 "one-dimensional variable!", ctl->climfile);
1432 NC(nc_inq_vardimid(ncid, varid, dims));
1433 if (dims[0] != dim_alt)
1434 ERRMSG("Coordinate 'altitude' in climatology file %s does not use the "
1435 "dimension 'altitude'!", ctl->climfile);
1436 NC(nc_get_var_double(ncid, varid, clim->alt));
1437 if (nc_inq_varid(ncid, "lat", &varid) != NC_NOERR)
1438 ERRMSG("Cannot find coordinate 'lat' in climatology file %s!",
1439 ctl->climfile);
1440 ndims = 0;
1441 NC(nc_inq_varndims(ncid, varid, &ndims));
1442 if (ndims != 1)
1443 ERRMSG("Coordinate 'lat' in climatology file %s is not a "
1444 "one-dimensional variable!", ctl->climfile);
1445 NC(nc_inq_vardimid(ncid, varid, dims));
1446 if (dims[0] != dim_lat)
1447 ERRMSG("Coordinate 'lat' in climatology file %s does not use the "
1448 "dimension 'lat'!", ctl->climfile);
1449 NC(nc_get_var_double(ncid, varid, clim->lat));
1450 for (int i = 0; i < clim->nalt; i++) {
1451 if (!isfinite(clim->alt[i]))
1452 ERRMSG("Non-finite coordinate 'altitude' in climatology file %s!",
1453 ctl->climfile);
1454 if (i > 0 && clim->alt[i] <= clim->alt[i - 1])
1455 ERRMSG("Coordinate 'altitude' not strictly increasing in climatology "
1456 "file %s!", ctl->climfile);
1457 }
1458 for (int i = 0; i < clim->nlat; i++) {
1459 if (!isfinite(clim->lat[i]))
1460 ERRMSG("Non-finite coordinate 'lat' in climatology file %s!",
1461 ctl->climfile);
1462 if (i > 0 && clim->lat[i] <= clim->lat[i - 1])
1463 ERRMSG("Coordinate 'lat' not strictly increasing in climatology file "
1464 "%s!", ctl->climfile);
1465 }
1466
1467 /* Check that the coordinates are equally spaced, since the interpolation
1468 locates grid cells by index arithmetic rather than by searching... */
1469 const double dz = clim->alt[1] - clim->alt[0];
1470 for (int i = 2; i < clim->nalt; i++)
1471 if (fabs(clim->alt[i] - clim->alt[i - 1] - dz) > 1e-6 * fabs(dz))
1472 ERRMSG("Coordinate 'altitude' not equally spaced in climatology "
1473 "file %s - interpolation requires a regular grid!",
1474 ctl->climfile);
1475 const double dy = clim->lat[1] - clim->lat[0];
1476 for (int i = 2; i < clim->nlat; i++)
1477 if (fabs(clim->lat[i] - clim->lat[i - 1] - dy) > 1e-6 * fabs(dy))
1478 ERRMSG("Coordinate 'lat' not equally spaced in climatology "
1479 "file %s - interpolation requires a regular grid!",
1480 ctl->climfile);
1481
1482 LOG(2, "Number of time steps: %d", clim->ntime);
1483 LOG(2, "Altitude grid: %d levels, %g ... %g km | dz = %g km",
1484 clim->nalt, clim->alt[0], clim->alt[clim->nalt - 1], dz);
1485 LOG(2, "Latitude grid: %d bands, %g ... %g deg | dy = %g deg",
1486 clim->nlat, clim->lat[0], clim->lat[clim->nlat - 1], dy);
1487
1488 /* Read and check temperature... */
1489 double vmin;
1490 double vmax;
1491 if (!read_clim_field(ctl->climfile, "temperature_mean", ncid,
1492 dim_month, dim_alt, dim_lat, clim->nalt,
1493 clim->nlat, clim->t, &vmin, &vmax))
1494 ERRMSG("Climatology file %s has no variable 'temperature_mean' - "
1495 "not a complete JuMACS climatology file?", ctl->climfile);
1496 clim->has_t = 1;
1497 LOG(2, "Temperature: JuMACS temperature_mean, %g ... %g K", vmin, vmax);
1498
1499 /* Read trace gases... */
1500 /* Mapping of JURASSIC emitter names to JuMACS climatology variable base
1501 names. Species without an entry keep their built-in climatological
1502 values. CO2, N2, and O2 are deliberately not mapped, since they are
1503 handled specially by the built-in climatology. */
1504 const struct {
1505 const char *emitter;
1506 const char *varname;
1507 } jumacs_map[] = {
1508 {"C2H2", "c2h2"},
1509 {"C2H6", "c2h6"},
1510 {"CCl4", "ccl4"},
1511 {"CH4", "ch4"},
1512 {"ClO", "clo"},
1513 {"ClONO2", "clono2"},
1514 {"CO", "co"},
1515 {"F11", "cfc_11"},
1516 {"F12", "cfc_12"},
1517 {"F22", "hcfc_22"},
1518 {"H2CO", "ch2o"},
1519 {"H2O", "h2o"},
1520 {"H2O2", "h2o2"},
1521 {"HCl", "hcl"},
1522 {"HNO3", "hno3"},
1523 {"HNO4", "hno4"},
1524 {"HOCl", "hocl"},
1525 {"N2O", "n2o"},
1526 {"N2O5", "n2o5"},
1527 {"NO", "no"},
1528 {"NO2", "no2"},
1529 {"O3", "o3"},
1530 {"OCS", "cos"},
1531 {"SO2", "so2"}
1532 };
1533
1534 char varname[LEN];
1535 for (int ig = 0; ig < ctl->ng; ig++) {
1536 const char *base = NULL;
1537 for (size_t i = 0; i < sizeof(jumacs_map) / sizeof(jumacs_map[0]); i++)
1538 if (strcasecmp(ctl->emitter[ig], jumacs_map[i].emitter) == 0) {
1539 base = jumacs_map[i].varname;
1540 break;
1541 }
1542 if (base == NULL) {
1543 if (ig == ctl->ig_co2) {
1544 LOG(2, "%s: built-in CO2 fit", ctl->emitter[ig]);
1545 } else if (ig == ctl->ig_n2 || ig == ctl->ig_o2) {
1546 LOG(2, "%s: constant", ctl->emitter[ig]);
1547 } else {
1548 LOG(2, "%s: built-in climatology", ctl->emitter[ig]);
1549 }
1550 continue;
1551 }
1552 sprintf(varname, "%s_mean", base);
1553 clim->has_q[ig] = read_clim_field(ctl->climfile, varname,
1554 ncid, dim_month, dim_alt,
1555 dim_lat, clim->nalt,
1556 clim->nlat, clim->q[ig],
1557 &vmin, &vmax);
1558 if (clim->has_q[ig]) {
1559 LOG(2, "%s: JuMACS %s, %g ... %g ppv", ctl->emitter[ig], varname,
1560 vmin, vmax);
1561 } else {
1562 LOG(2, "%s: built-in climatology (JuMACS variable %s not found)",
1563 ctl->emitter[ig], varname);
1564 }
1565 }
1566
1567 LOG(2, "Pressure: built-in climatology");
1568
1569 /* Close climatology file... */
1570 NC(nc_close(ncid));
1571
1572 /* Return pointer... */
1573 return clim;
1574}
int read_clim_field(const char *filename, const char *varname, const int ncid, const int dim_month, const int dim_alt, const int dim_lat, const int nalt, const int nlat, double field[CT][CZ][CLAT], double *vmin, double *vmax)
Reads and validates one JuMACS climatology field.
Definition: jurassic.c:1166
#define LEN
Maximum length of ASCII data lines.
Definition: jurassic.h:335
#define CLAT
Maximum number of latitudes for climatological data (JuMACS: 36 area-weighted 5-degree bands).
Definition: jurassic.h:382
#define CZ
Maximum number of altitudes for climatological data (JuMACS: 0...150 km at 1 km spacing).
Definition: jurassic.h:376
JuMACS climatology on a fixed grid.
Definition: jurassic.h:1552
int has_q[NG]
Set for each emitter with a field read.
Definition: jurassic.h:1581
double q[NG][CT][CZ][CLAT]
Volume mixing ratio [ppv].
Definition: jurassic.h:1575
int has_t
Set if a temperature field was read.
Definition: jurassic.h:1578
double t[CT][CZ][CLAT]
Temperature [K].
Definition: jurassic.h:1572
char climfile[LEN]
Climatological data file ("-" = built-in climatology).
Definition: jurassic.h:1649
Here is the call graph for this function:

◆ climatology_external()

void climatology_external ( const ctl_t *  ctl,
const clim_t *  clim,
atm_t *  atm 
)

Overwrites the built-in climatology with a JuMACS climatology.

Replaces the built-in climatological temperature and trace gas volume mixing ratios of all atmospheric profile points by the interpolated values of the given JuMACS climatology. Species not mapped to a JuMACS variable, and fields missing from the climatology, retain their built-in values. The climatological pressure is never overwritten.

Parameters
[in]ctlControl parameters providing the emitter list.
[in]climJuMACS climatology to interpolate from.
[out]atmAtmospheric state to be updated in place.
Author
Lars Hoffmann

Definition at line 1578 of file jurassic.c.

1581 {
1582
1583 /* Overwrite temperature... */
1584 if (clim->has_t)
1585 climatology_external_interp(clim, atm, clim->t, 0, atm->t);
1586
1587 /* Overwrite trace gases... */
1588 for (int ig = 0; ig < ctl->ng; ig++)
1589 if (clim->has_q[ig])
1590 climatology_external_interp(clim, atm, clim->q[ig],
1591 climatology_external_top_policy(
1592 ctl->emitter[ig]),
1593 atm->q[ig]);
1594}
void climatology_external_interp(const clim_t *clim, const atm_t *atm, const double field[CT][CZ][CLAT], const int top_policy, double *out)
Interpolates a JuMACS climatology field onto atmospheric profiles.
Definition: jurassic.c:1258
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 1598 of file jurassic.c.

1601 {
1602
1603 /* Number of days and fraction with respect to 2000-01-01T12:00Z... */
1604 const double D = sec / 86400 - 0.5;
1605
1606 /* Geocentric apparent ecliptic longitude [rad]... */
1607 const double g = DEG2RAD(357.529 + 0.98560028 * D);
1608 const double q = 280.459 + 0.98564736 * D;
1609 const double L = DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
1610
1611 /* Mean obliquity of the ecliptic [rad]... */
1612 const double e = DEG2RAD(23.439 - 0.00000036 * D);
1613
1614 /* Declination [rad]... */
1615 const double sindec = sin(e) * sin(L);
1616
1617 /* Right ascension [rad]... */
1618 const double ra = atan2(cos(e) * sin(L), cos(L));
1619
1620 /* Greenwich Mean Sidereal Time [h]... */
1621 const double GMST = 18.697374558 + 24.06570982441908 * D;
1622
1623 /* Local Sidereal Time [h]... */
1624 const double LST = GMST + lon / 15;
1625
1626 /* Hour angle [rad]... */
1627 const double h = LST / 12 * M_PI - ra;
1628
1629 /* Convert latitude... */
1630 const double lat_help = DEG2RAD(lat);
1631
1632 /* Return cosine of solar zenith angle... */
1633 return sin(lat_help) * sindec + cos(lat_help)
1634 * sqrt(1 - POW2(sindec)) * cos(h);
1635}
#define POW2(x)
Compute the square of a value.
Definition: jurassic.h:1143
#define DEG2RAD(deg)
Convert degrees to radians.
Definition: jurassic.h:589

◆ 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 1639 of file jurassic.c.

1643 {
1644
1645 double chisq_a, chisq_m = 0;
1646
1647 /* Get sizes... */
1648 const size_t m = dy->size;
1649 const size_t n = dx->size;
1650
1651 /* Allocate... */
1652 gsl_vector *x_aux = gsl_vector_alloc(n);
1653
1654 /* Determine normalized cost function...
1655 (chi^2 = 1/m * [dy^T * S_eps^{-1} * dy + dx^T * S_a^{-1} * dx]) */
1656 for (size_t i = 0; i < m; i++)
1657 chisq_m += POW2(gsl_vector_get(dy, i) * gsl_vector_get(sig_eps_inv, i));
1658 gsl_blas_dgemv(CblasNoTrans, 1.0, s_a_inv, dx, 0.0, x_aux);
1659 gsl_blas_ddot(dx, x_aux, &chisq_a);
1660
1661 /* Free... */
1662 gsl_vector_free(x_aux);
1663
1664 /* Return cost function value... */
1665 return (chisq_m + chisq_a) / (double) m;
1666}

◆ 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 1670 of file jurassic.c.

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

2538 {
2539
2540 /* MT_CKD 4.1 coefficients from RFM 5.21 (0 to 20000 cm^-1). */
2541 static const double h2oslf[2001] =
2542 { 2.877e-21, 2.855e-21, 2.731e-21, 2.49e-21, 2.178e-21, 1.863e-21,
2543 1.595e-21,
2544 1.381e-21, 1.221e-21, 1.095e-21, 9.882e-22, 8.926e-22, 8.041e-22,
2545 7.217e-22,
2546 6.45e-22, 5.74e-22, 5.088e-22, 4.492e-22, 3.952e-22, 3.466e-22, 3.031e-22,
2547 2.644e-22, 2.302e-22, 2.001e-22, 1.738e-22, 1.509e-22, 1.311e-22,
2548 1.139e-22,
2549 9.913e-23, 8.639e-23, 7.544e-23, 6.603e-23, 5.794e-23, 5.096e-23,
2550 4.495e-23,
2551 3.974e-23, 3.523e-23, 3.13e-23, 2.786e-23, 2.485e-23, 2.221e-23,
2552 1.987e-23,
2553 1.78e-23, 1.596e-23, 1.433e-23, 1.287e-23, 1.156e-23, 1.04e-23, 9.349e-24,
2554 8.41e-24, 7.568e-24, 6.81e-24, 6.13e-24, 5.517e-24, 4.967e-24, 4.471e-24,
2555 4.025e-24, 3.624e-24, 3.262e-24, 2.937e-24, 2.644e-24, 2.381e-24,
2556 2.143e-24,
2557 1.93e-24, 1.737e-24, 1.564e-24, 1.413e-24, 1.284e-24, 1.176e-24,
2558 1.087e-24,
2559 1.013e-24, 9.489e-25, 8.961e-25, 8.451e-25, 7.943e-25, 7.43e-25,
2560 6.912e-25,
2561 6.447e-25, 6.025e-25, 5.642e-25, 5.292e-25, 4.971e-25, 4.69e-25,
2562 4.444e-25,
2563 4.216e-25, 4.012e-25, 3.814e-25, 3.621e-25, 3.442e-25, 3.268e-25, 3.1e-25,
2564 2.957e-25, 2.78e-25, 2.617e-25, 2.445e-25, 2.305e-25, 2.187e-25, 2.08e-25,
2565 1.98e-25, 1.885e-25, 1.796e-25, 1.711e-25, 1.633e-25, 1.559e-25, 1.49e-25,
2566 1.426e-25, 1.367e-25, 1.312e-25, 1.263e-25, 1.218e-25, 1.178e-25,
2567 1.143e-25,
2568 1.112e-25, 1.088e-25, 1.07e-25, 1.057e-25, 1.05e-25, 1.051e-25, 1.059e-25,
2569 1.076e-25, 1.1e-25, 1.133e-25, 1.18e-25, 1.237e-25, 1.308e-25, 1.393e-25,
2570 1.483e-25, 1.614e-25, 1.758e-25, 1.93e-25, 2.123e-25, 2.346e-25,
2571 2.647e-25,
2572 2.93e-25, 3.279e-25, 3.745e-25, 4.152e-25, 4.813e-25, 5.477e-25,
2573 6.203e-25,
2574 7.331e-25, 8.056e-25, 9.882e-25, 1.05e-24, 1.21e-24, 1.341e-24, 1.572e-24,
2575 1.698e-24, 1.968e-24, 2.175e-24, 2.431e-24, 2.735e-24, 2.867e-24,
2576 3.19e-24,
2577 3.371e-24, 3.554e-24, 3.726e-24, 3.837e-24, 3.878e-24, 3.864e-24,
2578 3.858e-24,
2579 3.841e-24, 3.852e-24, 3.815e-24, 3.762e-24, 3.618e-24, 3.579e-24,
2580 3.45e-24,
2581 3.202e-24, 3.018e-24, 2.785e-24, 2.602e-24, 2.416e-24, 2.097e-24,
2582 1.939e-24,
2583 1.689e-24, 1.498e-24, 1.308e-24, 1.17e-24, 1.011e-24, 9.237e-25,
2584 7.909e-25,
2585 7.006e-25, 6.112e-25, 5.401e-25, 4.914e-25, 4.266e-25, 3.963e-25,
2586 3.316e-25,
2587 3.037e-25, 2.598e-25, 2.294e-25, 2.066e-25, 1.813e-25, 1.583e-25,
2588 1.423e-25,
2589 1.247e-25, 1.116e-25, 9.76e-26, 8.596e-26, 7.72e-26, 7.091e-26, 6.499e-26,
2590 5.801e-26, 5.15e-26, 4.5e-26, 4e-26, 3.509e-26, 3.1e-26, 2.714e-26,
2591 2.406e-26, 2.108e-26, 1.875e-26, 1.669e-26, 1.555e-26, 1.444e-26,
2592 1.345e-26,
2593 1.257e-26, 1.175e-26, 1.102e-26, 1.035e-26, 9.745e-27, 9.194e-27,
2594 8.685e-27,
2595 8.222e-27, 7.798e-27, 7.412e-27, 7.052e-27, 6.724e-27, 6.42e-27,
2596 6.143e-27,
2597 5.886e-27, 5.649e-27, 5.43e-27, 5.228e-27, 5.041e-27, 4.868e-27,
2598 4.708e-27,
2599 4.559e-27, 4.421e-27, 4.293e-27, 4.174e-27, 4.064e-27, 3.961e-27,
2600 3.865e-27,
2601 3.775e-27, 3.692e-27, 3.614e-27, 3.542e-27, 3.474e-27, 3.411e-27,
2602 3.353e-27,
2603 3.298e-27, 3.248e-27, 3.201e-27, 3.158e-27, 3.119e-27, 3.084e-27,
2604 3.053e-27,
2605 3.025e-27, 3.003e-27, 2.988e-27, 2.976e-27, 2.977e-27, 2.989e-27,
2606 3.015e-27,
2607 3.057e-27, 3.112e-27, 3.161e-27, 3.186e-27, 3.176e-27, 3.142e-27,
2608 3.099e-27,
2609 3.065e-27, 3.011e-27, 2.955e-27, 2.914e-27, 2.884e-27, 2.864e-27,
2610 2.858e-27,
2611 2.851e-27, 2.857e-27, 2.87e-27, 2.888e-27, 2.914e-27, 2.948e-27, 2.99e-27,
2612 3.042e-27, 3.105e-27, 3.185e-27, 3.276e-27, 3.385e-27, 3.511e-27,
2613 3.646e-27,
2614 3.858e-27, 4.081e-27, 4.335e-27, 4.643e-27, 5.011e-27, 5.494e-27,
2615 5.953e-27,
2616 6.354e-27, 7.116e-27, 7.498e-27, 8.613e-27, 9.35e-27, 1.002e-26, 1.09e-26,
2617 1.174e-26, 1.23e-26, 1.288e-26, 1.334e-26, 1.383e-26, 1.38e-26, 1.39e-26,
2618 1.373e-26, 1.354e-26, 1.335e-26, 1.343e-26, 1.323e-26, 1.349e-26,
2619 1.353e-26,
2620 1.362e-26, 1.344e-26, 1.329e-26, 1.336e-26, 1.327e-26, 1.325e-26,
2621 1.359e-26,
2622 1.374e-26, 1.415e-26, 1.462e-26, 1.526e-26, 1.619e-26, 1.735e-26,
2623 1.863e-26,
2624 2.034e-26, 2.265e-26, 2.482e-26, 2.756e-26, 3.103e-26, 3.466e-26,
2625 3.832e-26,
2626 4.378e-26, 4.913e-26, 5.651e-26, 6.311e-26, 7.169e-26, 8.057e-26,
2627 9.253e-26,
2628 1.047e-25, 1.212e-25, 1.36e-25, 1.569e-25, 1.776e-25, 2.02e-25, 2.281e-25,
2629 2.683e-25, 2.994e-25, 3.488e-25, 3.896e-25, 4.499e-25, 5.175e-25,
2630 6.035e-25,
2631 6.34e-25, 7.281e-25, 7.923e-25, 8.348e-25, 9.631e-25, 1.044e-24,
2632 1.102e-24,
2633 1.176e-24, 1.244e-24, 1.283e-24, 1.326e-24, 1.4e-24, 1.395e-24, 1.387e-24,
2634 1.363e-24, 1.314e-24, 1.241e-24, 1.228e-24, 1.148e-24, 1.086e-24,
2635 1.018e-24,
2636 8.89e-25, 8.316e-25, 7.292e-25, 6.452e-25, 5.625e-25, 5.045e-25, 4.38e-25,
2637 3.762e-25, 3.29e-25, 2.836e-25, 2.485e-25, 2.168e-25, 1.895e-25,
2638 1.659e-25,
2639 1.453e-25, 1.282e-25, 1.132e-25, 1.001e-25, 8.836e-26, 7.804e-26,
2640 6.922e-26,
2641 6.116e-26, 5.429e-26, 4.824e-26, 4.278e-26, 3.788e-26, 3.371e-26,
2642 2.985e-26,
2643 2.649e-26, 2.357e-26, 2.09e-26, 1.858e-26, 1.647e-26, 1.462e-26,
2644 1.299e-26,
2645 1.155e-26, 1.028e-26, 9.142e-27, 8.132e-27, 7.246e-27, 6.418e-27,
2646 5.726e-27,
2647 5.221e-27, 4.89e-27, 4.666e-27, 4.443e-27, 4.203e-27, 3.978e-27, 3.77e-27,
2648 3.575e-27, 3.395e-27, 3.227e-27, 3.07e-27, 2.924e-27, 2.788e-27,
2649 2.661e-27,
2650 2.543e-27, 2.433e-27, 2.329e-27, 2.233e-27, 2.143e-27, 2.058e-27,
2651 1.98e-27,
2652 1.906e-27, 1.837e-27, 1.773e-27, 1.713e-27, 1.657e-27, 1.605e-27,
2653 1.557e-27,
2654 1.514e-27, 1.472e-27, 1.435e-27, 1.404e-27, 1.377e-27, 1.354e-27,
2655 1.332e-27,
2656 1.308e-27, 1.282e-27, 1.256e-27, 1.227e-27, 1.192e-27, 1.159e-27,
2657 1.134e-27,
2658 1.114e-27, 1.098e-27, 1.081e-27, 1.066e-27, 1.055e-27, 1.045e-27,
2659 1.036e-27,
2660 1.03e-27, 1.026e-27, 1.025e-27, 1.025e-27, 1.028e-27, 1.033e-27,
2661 1.041e-27,
2662 1.049e-27, 1.06e-27, 1.075e-27, 1.093e-27, 1.114e-27, 1.139e-27,
2663 1.166e-27,
2664 1.199e-27, 1.239e-27, 1.282e-27, 1.316e-27, 1.355e-27, 1.436e-27,
2665 1.588e-27,
2666 1.807e-27, 2.06e-27, 2.337e-27, 2.645e-27, 2.996e-27, 3.393e-27,
2667 3.843e-27,
2668 4.363e-27, 4.935e-27, 5.607e-27, 6.363e-27, 7.242e-27, 8.23e-27,
2669 9.411e-27,
2670 1.071e-26, 1.232e-26, 1.402e-26, 1.6e-26, 1.82e-26, 2.128e-26, 2.386e-26,
2671 2.781e-26, 3.242e-26, 3.653e-26, 4.323e-26, 4.747e-26, 5.321e-26,
2672 5.919e-26,
2673 6.681e-26, 7.101e-26, 7.983e-26, 8.342e-26, 8.741e-26, 9.431e-26,
2674 9.952e-26,
2675 1.026e-25, 1.055e-25, 1.095e-25, 1.095e-25, 1.087e-25, 1.056e-25,
2676 1.026e-25,
2677 9.715e-26, 9.252e-26, 8.452e-26, 7.958e-26, 7.268e-26, 6.295e-26,
2678 6.003e-26,
2679 5e-26, 4.591e-26, 3.983e-26, 3.479e-26, 3.058e-26, 2.667e-26, 2.293e-26,
2680 1.995e-26, 1.747e-26, 1.517e-26, 1.335e-26, 1.165e-26, 1.028e-26,
2681 9.007e-27,
2682 7.956e-27, 7.015e-27, 6.192e-27, 5.491e-27, 4.859e-27, 4.297e-27,
2683 3.799e-27,
2684 3.38e-27, 3.002e-27, 2.659e-27, 2.366e-27, 2.103e-27, 1.861e-27,
2685 1.655e-27,
2686 1.469e-27, 1.309e-27, 1.162e-27, 1.032e-27, 9.198e-28, 8.181e-28,
2687 7.294e-28,
2688 6.516e-28, 5.787e-28, 5.163e-28, 4.612e-28, 4.096e-28, 3.654e-28,
2689 3.299e-28,
2690 3.052e-28, 2.856e-28, 2.683e-28, 2.507e-28, 2.346e-28, 2.194e-28,
2691 2.053e-28,
2692 1.921e-28, 1.799e-28, 1.686e-28, 1.58e-28, 1.481e-28, 1.389e-28,
2693 1.304e-28,
2694 1.226e-28, 1.151e-28, 1.083e-28, 1.02e-28, 9.618e-29, 9.08e-29, 8.575e-29,
2695 8.08e-29, 7.624e-29, 7.176e-29, 6.761e-29, 6.37e-29, 6.004e-29, 5.672e-29,
2696 5.371e-29, 5.097e-29, 4.845e-29, 4.608e-29, 4.39e-29, 4.192e-29,
2697 4.011e-29,
2698 3.846e-29, 3.698e-29, 3.568e-29, 3.45e-29, 3.351e-29, 3.268e-29,
2699 3.195e-29,
2700 3.131e-29, 3.091e-29, 3.06e-29, 3.039e-29, 3.034e-29, 3.045e-29,
2701 3.072e-29,
2702 3.116e-29, 3.176e-29, 3.253e-29, 3.347e-29, 3.467e-29, 3.605e-29,
2703 3.763e-29,
2704 3.946e-29, 4.162e-29, 4.399e-29, 4.677e-29, 4.983e-29, 5.336e-29,
2705 5.728e-29,
2706 6.168e-29, 6.684e-29, 7.214e-29, 7.861e-29, 8.62e-29, 9.481e-29,
2707 1.032e-28,
2708 1.135e-28, 1.264e-28, 1.396e-28, 1.567e-28, 1.74e-28, 1.977e-28, 2.2e-28,
2709 2.563e-28, 2.935e-28, 3.386e-28, 3.993e-28, 4.828e-28, 5.714e-28,
2710 6.877e-28,
2711 8.135e-28, 9.779e-28, 1.132e-27, 1.344e-27, 1.544e-27, 1.82e-27,
2712 2.207e-27,
2713 2.509e-27, 2.854e-27, 3.026e-27, 3.278e-27, 3.474e-27, 3.693e-27,
2714 3.93e-27,
2715 4.104e-27, 4.22e-27, 4.439e-27, 4.545e-27, 4.778e-27, 4.812e-27,
2716 5.018e-27,
2717 4.899e-27, 5.075e-27, 5.073e-27, 5.171e-27, 5.131e-27, 5.25e-27,
2718 5.617e-27,
2719 5.846e-27, 6.239e-27, 6.696e-27, 7.398e-27, 8.073e-27, 9.15e-27,
2720 1.009e-26,
2721 1.116e-26, 1.264e-26, 1.439e-26, 1.644e-26, 1.856e-26, 2.147e-26,
2722 2.317e-26,
2723 2.713e-26, 2.882e-26, 2.99e-26, 3.489e-26, 3.581e-26, 4.033e-26, 4.26e-26,
2724 4.543e-26, 4.84e-26, 4.826e-26, 5.013e-26, 5.252e-26, 5.277e-26,
2725 5.306e-26,
2726 5.234e-26, 5.111e-26, 5.134e-26, 4.748e-26, 4.434e-26, 4.109e-26,
2727 3.605e-26,
2728 3.252e-26, 2.731e-26, 2.369e-26, 1.922e-26, 1.558e-26, 1.321e-26,
2729 1.058e-26,
2730 8.515e-27, 6.811e-27, 5.431e-27, 4.348e-27, 3.51e-27, 2.853e-27,
2731 2.344e-27,
2732 1.949e-27, 1.649e-27, 1.409e-27, 1.232e-27, 1.098e-27, 9.866e-28,
2733 8.899e-28,
2734 8.135e-28, 7.409e-28, 6.809e-28, 6.237e-28, 5.728e-28, 5.267e-28,
2735 4.865e-28,
2736 4.482e-28, 4.169e-28, 3.841e-28, 3.573e-28, 3.304e-28, 3.065e-28,
2737 2.851e-28,
2738 2.634e-28, 2.448e-28, 2.275e-28, 2.114e-28, 1.965e-28, 1.83e-28,
2739 1.707e-28,
2740 1.591e-28, 1.484e-28, 1.386e-28, 1.294e-28, 1.209e-28, 1.131e-28,
2741 1.056e-28,
2742 9.901e-29, 9.263e-29, 8.68e-29, 8.137e-29, 7.627e-29, 7.158e-29,
2743 6.715e-29,
2744 6.305e-29, 5.927e-29, 5.568e-29, 5.242e-29, 4.935e-29, 4.648e-29,
2745 4.383e-29,
2746 4.137e-29, 3.909e-29, 3.697e-29, 3.5e-29, 3.321e-29, 3.156e-29, 3.006e-29,
2747 2.868e-29, 2.745e-29, 2.638e-29, 2.545e-29, 2.469e-29, 2.405e-29,
2748 2.369e-29,
2749 2.344e-29, 2.35e-29, 2.371e-29, 2.491e-29, 2.535e-29, 2.73e-29, 3.067e-29,
2750 3.322e-29, 3.63e-29, 4.045e-29, 4.524e-29, 4.981e-29, 5.613e-29,
2751 6.051e-29,
2752 6.538e-29, 6.892e-29, 7.601e-29, 8.194e-29, 8.806e-29, 9.45e-29,
2753 9.745e-29,
2754 1.009e-28, 1.017e-28, 1.039e-28, 1.061e-28, 1.076e-28, 1.086e-28,
2755 1.111e-28,
2756 1.142e-28, 1.16e-28, 1.174e-28, 1.18e-28, 1.187e-28, 1.194e-28, 1.192e-28,
2757 1.224e-28, 1.245e-28, 1.246e-28, 1.318e-28, 1.377e-28, 1.471e-28,
2758 1.582e-28,
2759 1.713e-28, 1.853e-28, 2.063e-28, 2.27e-28, 2.567e-28, 2.891e-28,
2760 3.264e-28,
2761 3.744e-28, 4.286e-28, 4.915e-28, 5.623e-28, 6.336e-28, 7.293e-28,
2762 8.309e-28,
2763 9.319e-28, 1.091e-27, 1.243e-27, 1.348e-27, 1.449e-27, 1.62e-27,
2764 1.846e-27,
2765 1.937e-27, 2.04e-27, 2.179e-27, 2.298e-27, 2.433e-27, 2.439e-27,
2766 2.464e-27,
2767 2.611e-27, 2.617e-27, 2.582e-27, 2.453e-27, 2.401e-27, 2.349e-27,
2768 2.203e-27,
2769 2.066e-27, 1.939e-27, 1.78e-27, 1.558e-27, 1.391e-27, 1.203e-27,
2770 1.048e-27,
2771 9.464e-28, 8.306e-28, 7.239e-28, 6.317e-28, 5.52e-28, 4.847e-28,
2772 4.282e-28,
2773 3.796e-28, 3.377e-28, 2.996e-28, 2.678e-28, 2.4e-28, 2.134e-28, 1.904e-28,
2774 1.705e-28, 1.523e-28, 1.35e-28, 1.204e-28, 1.07e-28, 9.408e-29, 8.476e-29,
2775 7.47e-29, 6.679e-29, 5.929e-29, 5.267e-29, 4.711e-29, 4.172e-29,
2776 3.761e-29,
2777 3.288e-29, 2.929e-29, 2.609e-29, 2.315e-29, 2.042e-29, 1.844e-29,
2778 1.64e-29,
2779 1.47e-29, 1.31e-29, 1.176e-29, 1.049e-29, 9.377e-30, 8.462e-30, 7.616e-30,
2780 6.818e-30, 6.119e-30, 5.558e-30, 5.152e-30, 4.832e-30, 4.546e-30,
2781 4.267e-30,
2782 4.009e-30, 3.77e-30, 3.546e-30, 3.34e-30, 3.149e-30, 2.971e-30, 2.805e-30,
2783 2.652e-30, 2.509e-30, 2.377e-30, 2.255e-30, 2.142e-30, 2.038e-30,
2784 1.943e-30,
2785 1.855e-30, 1.776e-30, 1.703e-30, 1.64e-30, 1.586e-30, 1.536e-30,
2786 1.494e-30,
2787 1.466e-30, 1.446e-30, 1.44e-30, 1.439e-30, 1.455e-30, 1.461e-30,
2788 1.479e-30,
2789 1.514e-30, 1.538e-30, 1.59e-30, 1.652e-30, 1.75e-30, 1.811e-30, 1.88e-30,
2790 1.933e-30, 2.027e-30, 2.078e-30, 2.17e-30, 2.249e-30, 2.323e-30,
2791 2.408e-30,
2792 2.461e-30, 2.536e-30, 2.581e-30, 2.615e-30, 2.721e-30, 2.782e-30,
2793 2.866e-30,
2794 2.938e-30, 2.958e-30, 3.011e-30, 3.155e-30, 3.237e-30, 3.589e-30,
2795 3.838e-30,
2796 4.083e-30, 4.354e-30, 4.745e-30, 5.148e-30, 5.648e-30, 6.194e-30,
2797 6.748e-30,
2798 7.566e-30, 8.421e-30, 9.427e-30, 1.042e-29, 1.165e-29, 1.341e-29,
2799 1.518e-29,
2800 1.686e-29, 2.036e-29, 2.362e-29, 2.811e-29, 3.296e-29, 4.07e-29,
2801 4.695e-29,
2802 6.152e-29, 7.572e-29, 9.557e-29, 1.135e-28, 1.279e-28, 1.364e-28,
2803 1.436e-28,
2804 1.54e-28, 1.672e-28, 1.793e-28, 1.906e-28, 2.036e-28, 2.144e-28,
2805 2.292e-28,
2806 2.371e-28, 2.493e-28, 2.606e-28, 2.706e-28, 2.866e-28, 3.036e-28,
2807 3.136e-28,
2808 3.405e-28, 3.665e-28, 3.837e-28, 4.229e-28, 4.748e-28, 5.32e-28,
2809 5.763e-28,
2810 6.677e-28, 7.216e-28, 7.716e-28, 8.958e-28, 9.419e-28, 1.036e-27,
2811 1.108e-27,
2812 1.189e-27, 1.246e-27, 1.348e-27, 1.31e-27, 1.361e-27, 1.364e-27,
2813 1.363e-27,
2814 1.343e-27, 1.293e-27, 1.254e-27, 1.235e-27, 1.158e-27, 1.107e-27,
2815 9.961e-28,
2816 9.011e-28, 7.91e-28, 6.916e-28, 6.338e-28, 5.564e-28, 4.827e-28,
2817 4.198e-28,
2818 3.695e-28, 3.276e-28, 2.929e-28, 2.633e-28, 2.391e-28, 2.192e-28,
2819 2.021e-28,
2820 1.89e-28, 1.772e-28, 1.667e-28, 1.603e-28, 1.547e-28, 1.537e-28,
2821 1.492e-28,
2822 1.515e-28, 1.479e-28, 1.45e-28, 1.513e-28, 1.495e-28, 1.529e-28,
2823 1.565e-28,
2824 1.564e-28, 1.553e-28, 1.569e-28, 1.584e-28, 1.57e-28, 1.538e-28,
2825 1.531e-28,
2826 1.346e-28, 1.199e-28, 1.044e-28, 8.892e-29, 7.076e-29, 5.884e-29,
2827 5.039e-29,
2828 4.129e-29, 3.663e-29, 2.993e-29, 2.622e-29, 2.232e-29, 1.884e-29,
2829 1.569e-29,
2830 1.348e-29, 1.144e-29, 1.009e-29, 8.833e-30, 7.907e-30, 7.079e-30,
2831 6.514e-30,
2832 5.823e-30, 5.312e-30, 4.883e-30, 4.458e-30, 4.094e-30, 3.734e-30,
2833 3.458e-30,
2834 3.205e-30, 2.962e-30, 2.733e-30, 2.532e-30, 2.351e-30, 2.187e-30,
2835 2.034e-30,
2836 1.889e-30, 1.764e-30, 1.648e-30, 1.541e-30, 1.443e-30, 1.355e-30,
2837 1.274e-30,
2838 1.198e-30, 1.133e-30, 1.071e-30, 1.015e-30, 9.648e-31, 9.195e-31,
2839 8.791e-31,
2840 8.435e-31, 8.125e-31, 7.859e-31, 7.621e-31, 7.481e-31, 7.351e-31,
2841 7.228e-31,
2842 7.295e-31, 7.339e-31, 7.588e-31, 7.701e-31, 7.886e-31, 8.511e-31,
2843 9.061e-31,
2844 9.926e-31, 1.083e-30, 1.241e-30, 1.469e-30, 1.736e-30, 1.966e-30,
2845 2.132e-30,
2846 2.28e-30, 2.473e-30, 2.718e-30, 2.922e-30, 3.128e-30, 3.361e-30,
2847 3.641e-30,
2848 3.91e-30, 4.196e-30, 4.501e-30, 4.932e-30, 5.258e-30, 5.755e-30,
2849 6.253e-30,
2850 6.664e-30, 7.344e-30, 7.985e-30, 8.877e-30, 1.005e-29, 1.118e-29,
2851 1.251e-29,
2852 1.428e-29, 1.61e-29, 1.888e-29, 2.077e-29, 2.331e-29, 2.751e-29,
2853 3.061e-29,
2854 3.522e-29, 3.805e-29, 4.181e-29, 4.575e-29, 5.167e-29, 5.634e-29,
2855 6.007e-29,
2856 6.501e-29, 6.829e-29, 7.211e-29, 7.262e-29, 7.696e-29, 7.832e-29,
2857 7.799e-29,
2858 7.651e-29, 7.304e-29, 7.15e-29, 6.977e-29, 6.603e-29, 6.209e-29, 5.69e-29,
2859 5.432e-29, 4.764e-29, 4.189e-29, 3.64e-29, 3.203e-29, 2.848e-29, 2.51e-29,
2860 2.194e-29, 1.946e-29, 1.75e-29, 1.567e-29, 1.426e-29, 1.302e-29,
2861 1.197e-29,
2862 1.109e-29, 1.035e-29, 9.719e-30, 9.207e-30, 8.957e-30, 8.578e-30,
2863 8.262e-30,
2864 8.117e-30, 7.987e-30, 7.875e-30, 7.741e-30, 7.762e-30, 7.537e-30,
2865 7.424e-30,
2866 7.474e-30, 7.294e-30, 7.216e-30, 7.233e-30, 7.14e-30, 7.085e-30,
2867 6.434e-30,
2868 5.585e-30, 5.015e-30, 3.956e-30, 3.337e-30, 2.545e-30, 2.141e-30,
2869 1.761e-30,
2870 1.685e-30, 1.507e-30, 1.241e-30, 1.081e-30, 9.675e-31, 7.964e-31,
2871 6.93e-31,
2872 5.79e-31, 5.069e-31, 4.452e-31, 3.97e-31, 3.551e-31, 3.228e-31, 2.939e-31,
2873 2.682e-31, 2.471e-31, 2.278e-31, 2.106e-31, 1.95e-31, 1.811e-31,
2874 1.682e-31,
2875 1.563e-31, 1.458e-31, 1.363e-31, 1.278e-31, 1.2e-31, 1.129e-31, 1.066e-31,
2876 1.007e-31, 9.545e-32, 9.075e-32, 8.656e-32, 8.285e-32, 7.958e-32,
2877 7.674e-32,
2878 7.431e-32, 7.227e-32, 7.061e-32, 6.934e-32, 6.843e-32, 6.79e-32,
2879 6.775e-32,
2880 6.798e-32, 6.859e-32, 6.96e-32, 7.102e-32, 7.287e-32, 7.517e-32,
2881 7.795e-32,
2882 8.123e-32, 8.504e-32, 8.945e-32, 9.45e-32, 1.003e-31, 1.07e-31, 1.148e-31,
2883 1.232e-31, 1.327e-31, 1.441e-31, 1.535e-31, 1.655e-31, 1.814e-31,
2884 2.02e-31,
2885 2.307e-31, 2.622e-31, 2.962e-31, 3.369e-31, 3.819e-31, 4.329e-31,
2886 4.932e-31,
2887 5.589e-31, 6.364e-31, 7.284e-31, 8.236e-31, 9.447e-31, 1.078e-30,
2888 1.229e-30,
2889 1.417e-30, 1.614e-30, 1.843e-30, 2.107e-30, 2.406e-30, 2.728e-30,
2890 3.195e-30,
2891 3.595e-30, 4.153e-30, 4.736e-30, 5.41e-30, 6.088e-30, 6.769e-30,
2892 7.691e-30,
2893 8.545e-30, 9.621e-30, 1.047e-29, 1.161e-29, 1.296e-29, 1.424e-29,
2894 1.576e-29,
2895 1.739e-29, 1.893e-29, 2.08e-29, 2.336e-29, 2.604e-29, 2.76e-29, 3.001e-29,
2896 3.365e-29, 3.55e-29, 3.895e-29, 4.183e-29, 4.614e-29, 4.846e-29,
2897 5.068e-29,
2898 5.427e-29, 5.541e-29, 5.864e-29, 5.997e-29, 5.997e-29, 6.061e-29,
2899 5.944e-29,
2900 5.855e-29, 5.661e-29, 5.523e-29, 5.374e-29, 4.94e-29, 4.688e-29, 4.17e-29,
2901 3.913e-29, 3.423e-29, 2.997e-29, 2.598e-29, 2.253e-29, 1.946e-29,
2902 1.71e-29,
2903 1.507e-29, 1.336e-29, 1.19e-29, 1.068e-29, 9.623e-30, 8.772e-30,
2904 8.007e-30,
2905 7.42e-30, 6.884e-30, 6.483e-30, 6.162e-30, 5.922e-30, 5.688e-30,
2906 5.654e-30,
2907 5.637e-30, 5.701e-30, 5.781e-30, 5.874e-30, 6.268e-30, 6.357e-30,
2908 6.525e-30,
2909 7.137e-30, 7.441e-30, 8.024e-30, 8.485e-30, 9.143e-30, 9.536e-30,
2910 9.717e-30,
2911 1.018e-29, 1.042e-29, 1.054e-29, 1.092e-29, 1.093e-29, 1.072e-29,
2912 1.046e-29,
2913 9.283e-30, 8.053e-30, 6.68e-30, 5.63e-30, 4.933e-30, 3.488e-30, 3.324e-30,
2914 2.826e-30, 2.429e-30, 2.051e-30, 1.679e-30, 1.411e-30, 1.24e-30,
2915 1.098e-30,
2916 9.668e-31, 8.529e-31, 7.848e-31, 7.098e-31, 6.117e-31, 5.246e-31,
2917 4.521e-31,
2918 4.059e-31, 3.783e-31, 3.502e-31, 3.271e-31, 2.956e-31, 2.636e-31,
2919 2.464e-31,
2920 2.19e-31, 1.986e-31, 1.791e-31, 1.638e-31, 1.491e-31, 1.383e-31,
2921 1.271e-31,
2922 1.166e-31, 1.082e-31, 1.002e-31, 9.317e-32, 8.697e-32, 8.157e-32,
2923 7.678e-32,
2924 7.252e-32, 6.874e-32, 6.539e-32, 6.243e-32, 5.985e-32, 5.763e-32,
2925 5.575e-32,
2926 5.421e-32, 5.3e-32, 5.212e-32, 5.157e-32, 5.138e-32, 5.156e-32, 5.214e-32,
2927 5.313e-32, 5.457e-32, 5.686e-32, 5.953e-32, 6.284e-32, 6.856e-32,
2928 7.351e-32,
2929 8.006e-32, 8.957e-32, 1.031e-31, 1.17e-31, 1.345e-31, 1.623e-31,
2930 1.999e-31,
2931 2.507e-31, 3.004e-31, 3.378e-31, 3.688e-31, 4.118e-31, 4.569e-31,
2932 5.025e-31,
2933 5.66e-31, 6.231e-31, 6.881e-31, 7.996e-31, 8.526e-31, 9.694e-31,
2934 1.106e-30,
2935 1.222e-30, 1.355e-30, 1.525e-30, 1.775e-30, 1.924e-30, 2.181e-30,
2936 2.379e-30,
2937 2.662e-30, 2.907e-30, 3.154e-30, 3.366e-30, 3.579e-30, 3.858e-30,
2938 4.046e-30,
2939 4.196e-30, 4.166e-30, 4.457e-30, 4.466e-30, 4.404e-30, 4.337e-30,
2940 4.15e-30,
2941 4.083e-30, 3.91e-30, 3.723e-30, 3.514e-30, 3.303e-30, 2.847e-30,
2942 2.546e-30,
2943 2.23e-30, 1.994e-30, 1.733e-30, 1.488e-30, 1.297e-30, 1.144e-30,
2944 1.004e-30,
2945 8.741e-31, 7.928e-31, 7.034e-31, 6.323e-31, 5.754e-31, 5.25e-31, 4.85e-31,
2946 4.502e-31, 4.286e-31, 4.028e-31, 3.899e-31, 3.824e-31, 3.761e-31,
2947 3.804e-31,
2948 3.839e-31, 3.845e-31, 4.244e-31, 4.382e-31, 4.582e-31, 4.847e-31,
2949 5.209e-31,
2950 5.384e-31, 5.887e-31, 6.371e-31, 6.737e-31, 7.168e-31, 7.415e-31,
2951 7.827e-31,
2952 8.037e-31, 8.12e-31, 8.154e-31, 7.981e-31, 7.783e-31, 6.9e-31, 6.03e-31,
2953 4.9e-31, 3.878e-31, 3.068e-31, 2.533e-31, 2.255e-31, 2.056e-31, 1.569e-31,
2954 1.398e-31, 1.149e-31, 9.249e-32, 7.706e-32, 6.436e-32, 5.514e-32,
2955 4.782e-32,
2956 4.202e-32, 3.721e-32, 3.336e-32, 3.015e-32, 2.744e-32, 2.512e-32,
2957 2.312e-32,
2958 2.138e-32, 1.987e-32, 1.855e-32, 1.741e-32, 1.642e-32, 1.557e-32,
2959 1.483e-32,
2960 1.422e-32, 1.37e-32, 1.329e-32, 1.297e-32, 1.274e-32, 1.259e-32,
2961 1.253e-32,
2962 1.255e-32, 1.266e-32, 1.284e-32, 1.312e-32, 1.348e-32, 1.393e-32,
2963 1.448e-32,
2964 1.512e-32, 1.587e-32, 1.672e-32, 1.77e-32, 1.88e-32, 1.99e-32, 2.11e-32,
2965 2.274e-32, 2.516e-32, 2.844e-32, 3.231e-32, 3.661e-32, 4.153e-32,
2966 4.717e-32,
2967 5.36e-32, 6.094e-32, 6.93e-32, 7.882e-32, 8.966e-32, 1.02e-31, 1.162e-31,
2968 1.324e-31, 1.51e-31, 1.72e-31, 1.965e-31, 2.237e-31, 2.56e-31, 2.927e-31,
2969 3.371e-31, 3.842e-31, 4.429e-31, 5.139e-31, 5.798e-31, 6.697e-31,
2970 7.626e-31,
2971 8.647e-31, 1.022e-30, 1.136e-30, 1.3e-30, 1.481e-30, 1.672e-30, 1.871e-30,
2972 2.126e-30, 2.357e-30, 2.583e-30, 2.997e-30, 3.289e-30, 3.702e-30,
2973 4.012e-30,
2974 4.319e-30, 4.527e-30, 5.001e-30, 5.448e-30, 5.611e-30, 5.76e-30,
2975 5.965e-30,
2976 6.079e-30, 6.207e-30, 6.276e-30, 6.222e-30, 6.137e-30, 6e-30, 5.814e-30,
2977 5.393e-30, 5.35e-30, 4.947e-30, 4.629e-30, 4.117e-30, 3.712e-30,
2978 3.372e-30,
2979 2.923e-30, 2.55e-30, 2.232e-30, 1.929e-30, 1.679e-30, 1.46e-30, 1.289e-30,
2980 1.13e-30, 9.953e-31, 8.763e-31, 7.76e-31, 6.9e-31, 6.16e-31, 5.525e-31,
2981 4.958e-31, 4.489e-31, 4.072e-31, 3.728e-31, 3.438e-31, 3.205e-31,
2982 3.006e-31,
2983 2.848e-31, 2.766e-31, 2.688e-31, 2.664e-31, 2.67e-31, 2.696e-31,
2984 2.786e-31,
2985 2.861e-31, 3.009e-31, 3.178e-31, 3.389e-31, 3.587e-31, 3.819e-31,
2986 4.054e-31,
2987 4.417e-31, 4.703e-31, 5.137e-31, 5.46e-31, 6.055e-31, 6.333e-31,
2988 6.773e-31,
2989 7.219e-31, 7.717e-31, 8.131e-31, 8.491e-31, 8.574e-31, 9.01e-31,
2990 9.017e-31,
2991 8.999e-31, 8.959e-31, 8.838e-31, 8.579e-31, 8.162e-31, 8.098e-31,
2992 7.472e-31,
2993 7.108e-31, 6.559e-31, 5.994e-31, 5.172e-31, 4.424e-31, 3.951e-31,
2994 3.34e-31,
2995 2.902e-31, 2.541e-31, 2.215e-31, 1.945e-31, 1.716e-31, 1.503e-31,
2996 1.339e-31,
2997 1.185e-31, 1.05e-31, 9.336e-32, 8.307e-32, 7.312e-32, 6.55e-32, 5.836e-32,
2998 5.178e-32, 4.6e-32, 4.086e-32, 3.639e-32, 3.247e-32, 2.904e-32, 2.604e-32,
2999 2.341e-32, 2.112e-32, 1.914e-32, 1.744e-32, 1.598e-32, 1.476e-32,
3000 1.374e-32,
3001 1.293e-32, 1.23e-32, 1.185e-32, 1.158e-32, 1.147e-32, 1.154e-32,
3002 1.177e-32,
3003 1.219e-32, 1.28e-32, 1.36e-32, 1.463e-32, 1.591e-32, 1.75e-32, 1.94e-32,
3004 2.156e-32, 2.43e-32, 2.748e-32, 3.052e-32, 3.533e-32, 3.967e-32,
3005 4.471e-32,
3006 5.041e-32, 5.86e-32, 6.664e-32, 7.522e-32, 8.342e-32, 9.412e-32,
3007 1.072e-31,
3008 1.213e-31, 1.343e-31, 1.496e-31, 1.664e-31, 1.822e-31, 2.029e-31,
3009 2.233e-31,
3010 2.457e-31, 2.709e-31, 2.928e-31, 3.115e-31, 3.356e-31, 3.592e-31,
3011 3.818e-31,
3012 3.936e-31, 4.061e-31, 4.149e-31, 4.299e-31, 4.223e-31, 4.251e-31,
3013 4.287e-31,
3014 4.177e-31, 4.094e-31, 3.942e-31, 3.772e-31, 3.614e-31, 3.394e-31,
3015 3.222e-31,
3016 2.791e-31, 2.665e-31, 2.309e-31, 2.032e-31, 1.74e-31, 1.535e-31,
3017 1.323e-31,
3018 1.151e-31, 9.803e-32, 8.65e-32, 7.54e-32, 6.619e-32, 5.832e-32, 5.113e-32,
3019 4.503e-32, 3.975e-32, 3.52e-32, 3.112e-32, 2.797e-32, 2.5e-32, 2.24e-32,
3020 2.013e-32, 1.819e-32, 1.653e-32, 1.513e-32, 1.395e-32, 1.299e-32,
3021 1.225e-32,
3022 1.168e-32, 1.124e-32, 1.148e-32, 1.107e-32, 1.128e-32, 1.169e-32,
3023 1.233e-32,
3024 1.307e-32, 1.359e-32, 1.543e-32, 1.686e-32, 1.794e-32, 2.028e-32,
3025 2.21e-32,
3026 2.441e-32, 2.653e-32, 2.828e-32, 3.093e-32, 3.28e-32, 3.551e-32,
3027 3.677e-32,
3028 3.803e-32, 3.844e-32, 4.068e-32, 4.093e-32, 4.002e-32, 3.904e-32,
3029 3.624e-32,
3030 3.633e-32, 3.622e-32, 3.443e-32, 3.184e-32, 2.934e-32, 2.476e-32,
3031 2.212e-32,
3032 1.867e-32, 1.594e-32, 1.37e-32, 1.192e-32, 1.045e-32, 9.211e-33, 8.17e-33,
3033 7.29e-33, 6.55e-33, 5.929e-33, 5.415e-33, 4.995e-33, 4.661e-33, 4.406e-33,
3034 4.225e-33, 4.116e-33, 4.075e-33, 4.102e-33, 4.198e-33, 4.365e-33,
3035 4.606e-33,
3036 4.925e-33, 5.326e-33, 5.818e-33, 6.407e-33, 7.104e-33, 7.92e-33,
3037 8.868e-33,
3038 9.964e-33, 1.123e-32, 1.268e-32, 1.434e-32, 1.626e-32, 1.848e-32,
3039 2.107e-32,
3040 2.422e-32, 2.772e-32, 3.145e-32, 3.704e-32, 4.27e-32, 4.721e-32,
3041 5.361e-32,
3042 6.083e-32, 7.095e-32, 7.968e-32, 9.228e-32, 1.048e-31, 1.187e-31,
3043 1.336e-31,
3044 1.577e-31, 1.772e-31, 2.017e-31, 2.25e-31, 2.63e-31, 2.911e-31, 3.356e-31,
3045 3.82e-31, 4.173e-31, 4.811e-31, 5.254e-31, 5.839e-31, 6.187e-31,
3046 6.805e-31,
3047 7.118e-31, 7.369e-31, 7.664e-31, 7.794e-31, 7.947e-31, 8.036e-31,
3048 7.954e-31,
3049 7.849e-31, 7.518e-31, 7.462e-31, 6.926e-31, 6.531e-31, 6.197e-31,
3050 5.421e-31,
3051 4.777e-31, 4.111e-31, 3.679e-31, 3.166e-31, 2.786e-31, 2.436e-31,
3052 2.144e-31,
3053 1.859e-31, 1.628e-31, 1.414e-31, 1.237e-31, 1.093e-31, 9.558e-32
3054 };
3055
3056 static const double h2ofrn[2001] =
3057 { 8.563e-23, 8.828e-23, 9.182e-23, 9.796e-23, 1.14e-22, 1.376e-22,
3058 1.545e-22,
3059 1.508e-22, 1.386e-22, 1.215e-22, 1.063e-22, 9.151e-23, 8.008e-23,
3060 6.97e-23,
3061 6.055e-23, 5.243e-23, 4.559e-23, 3.763e-23, 3.055e-23, 2.563e-23,
3062 2.197e-23,
3063 1.809e-23, 1.483e-23, 1.167e-23, 8.809e-24, 7.131e-24, 5.933e-24,
3064 5.172e-24,
3065 4.22e-24, 3.427e-24, 2.648e-24, 2.123e-24, 1.825e-24, 1.476e-24,
3066 1.101e-24,
3067 8.588e-25, 6.499e-25, 4.875e-25, 3.861e-25, 3.001e-25, 2.343e-25,
3068 2.087e-25,
3069 1.771e-25, 1.588e-25, 1.408e-25, 1.181e-25, 1.024e-25, 9.223e-26,
3070 7.916e-26,
3071 6.692e-26, 5.72e-26, 5.125e-26, 4.478e-26, 3.844e-26, 3.267e-26,
3072 2.851e-26,
3073 2.473e-26, 2.124e-26, 1.768e-26, 1.481e-26, 1.267e-26, 1.075e-26,
3074 9.212e-27,
3075 7.849e-27, 6.601e-27, 5.599e-27, 4.768e-27, 4.098e-27, 3.558e-27,
3076 3.089e-27,
3077 2.678e-27, 2.339e-27, 2.038e-27, 1.755e-27, 1.497e-27, 1.294e-27,
3078 1.129e-27,
3079 9.878e-28, 8.603e-28, 7.494e-28, 6.568e-28, 5.747e-28, 5.025e-28,
3080 4.345e-28,
3081 3.758e-28, 3.272e-28, 2.862e-28, 2.508e-28, 2.198e-28, 1.918e-28,
3082 1.68e-28,
3083 1.471e-28, 1.289e-28, 1.135e-28, 9.962e-29, 8.767e-29, 7.699e-29,
3084 6.798e-29,
3085 6.007e-29, 5.336e-29, 4.75e-29, 4.232e-29, 3.807e-29, 3.476e-29,
3086 3.237e-29,
3087 3.002e-29, 2.821e-29, 2.757e-29, 2.816e-29, 2.92e-29, 3.044e-29, 3.42e-29,
3088 3.745e-29, 4.197e-29, 4.816e-29, 5.987e-29, 7.098e-29, 8.082e-29,
3089 9.622e-29,
3090 1.211e-28, 1.502e-28, 1.766e-28, 2.223e-28, 2.901e-28, 3.951e-28,
3091 5.072e-28,
3092 6.232e-28, 7.904e-28, 1.034e-27, 1.438e-27, 1.89e-27, 2.59e-27, 3.592e-27,
3093 4.973e-27, 7.159e-27, 9.987e-27, 1.382e-26, 1.93e-26, 2.592e-26,
3094 3.454e-26,
3095 4.572e-26, 5.932e-26, 7.554e-26, 9.559e-26, 1.183e-25, 1.425e-25,
3096 1.681e-25,
3097 1.978e-25, 2.336e-25, 2.669e-25, 3.023e-25, 3.372e-25, 3.716e-25,
3098 3.968e-25,
3099 4.061e-25, 4.011e-25, 3.81e-25, 3.491e-25, 3.155e-25, 2.848e-25,
3100 2.678e-25,
3101 2.66e-25, 2.811e-25, 3.071e-25, 3.294e-25, 3.459e-25, 3.569e-25, 3.56e-25,
3102 3.434e-25, 3.186e-25, 2.916e-25, 2.622e-25, 2.275e-25, 1.918e-25,
3103 1.62e-25,
3104 1.373e-25, 1.182e-25, 1.006e-25, 8.556e-26, 7.26e-26, 6.11e-26, 5.04e-26,
3105 4.23e-26, 3.456e-26, 2.903e-26, 2.486e-26, 2.039e-26, 1.672e-26,
3106 1.285e-26,
3107 1.054e-26, 8.302e-27, 6.667e-27, 5.503e-27, 4.562e-27, 3.948e-27,
3108 3.198e-27,
3109 2.586e-27, 2.225e-27, 1.807e-27, 1.53e-27, 1.294e-27, 1.126e-27,
3110 9.604e-28,
3111 7.85e-28, 6.813e-28, 5.583e-28, 4.69e-28, 3.996e-28, 3.373e-28, 2.93e-28,
3112 2.417e-28, 2.061e-28, 1.743e-28, 1.475e-28, 1.273e-28, 1.084e-28,
3113 9.368e-29,
3114 7.985e-29, 6.785e-29, 5.804e-29, 4.975e-29, 4.311e-29, 3.738e-29,
3115 3.275e-29,
3116 2.847e-29, 2.469e-29, 2.149e-29, 1.884e-29, 1.631e-29, 1.393e-29,
3117 1.201e-29,
3118 1.027e-29, 8.807e-30, 7.521e-30, 6.436e-30, 5.509e-30, 4.729e-30,
3119 4.055e-30,
3120 3.49e-30, 3.006e-30, 2.599e-30, 2.246e-30, 1.942e-30, 1.685e-30,
3121 1.464e-30,
3122 1.273e-30, 1.115e-30, 9.794e-31, 8.729e-31, 7.893e-31, 7.313e-31,
3123 7.069e-31,
3124 7.19e-31, 7.828e-31, 9.295e-31, 1.174e-30, 1.578e-30, 2.184e-30,
3125 3.053e-30,
3126 4.212e-30, 5.733e-30, 7.497e-30, 9.487e-30, 1.153e-29, 1.343e-29,
3127 1.503e-29,
3128 1.623e-29, 1.696e-29, 1.746e-29, 1.789e-29, 1.852e-29, 1.862e-29,
3129 1.886e-29,
3130 1.912e-29, 1.942e-29, 1.938e-29, 1.914e-29, 1.898e-29, 1.864e-29,
3131 1.77e-29,
3132 1.635e-29, 1.464e-29, 1.279e-29, 1.099e-29, 9.528e-30, 8.433e-30,
3133 7.794e-30,
3134 7.793e-30, 8.241e-30, 9.417e-30, 1.179e-29, 1.616e-29, 2.144e-29,
3135 2.992e-29,
3136 4.344e-29, 6.415e-29, 9.242e-29, 1.31e-28, 1.847e-28, 2.567e-28, 3.39e-28,
3137 4.357e-28, 5.301e-28, 6.364e-28, 7.438e-28, 8.381e-28, 9.294e-28,
3138 1.013e-27,
3139 1.103e-27, 1.17e-27, 1.2e-27, 1.19e-27, 1.133e-27, 1.04e-27, 9.475e-28,
3140 8.601e-28, 8.074e-28, 8.023e-28, 8.473e-28, 9.256e-28, 9.989e-28,
3141 1.056e-27,
3142 1.079e-27, 1.079e-27, 1.049e-27, 1e-27, 9.35e-28, 8.662e-28, 7.88e-28,
3143 7.137e-28, 6.438e-28, 5.706e-28, 5.132e-28, 4.815e-28, 4.736e-28,
3144 4.709e-28,
3145 4.918e-28, 5.227e-28, 5.603e-28, 6.023e-28, 6.567e-28, 7.403e-28,
3146 8.695e-28,
3147 9.929e-28, 1.163e-27, 1.379e-27, 1.658e-27, 2.01e-27, 2.425e-27, 2.92e-27,
3148 3.562e-27, 4.274e-27, 5.173e-27, 6.285e-27, 7.787e-27, 9.563e-27,
3149 1.194e-26,
3150 1.517e-26, 1.934e-26, 2.511e-26, 3.197e-26, 4.024e-26, 4.981e-26,
3151 6.09e-26,
3152 7.229e-26, 8.439e-26, 9.367e-26, 1.016e-25, 1.057e-25, 1.088e-25,
3153 1.108e-25,
3154 1.129e-25, 1.159e-25, 1.19e-25, 1.21e-25, 1.21e-25, 1.2e-25, 1.19e-25,
3155 1.18e-25, 1.19e-25, 1.23e-25, 1.28e-25, 1.3e-25, 1.29e-25, 1.21e-25,
3156 1.09e-25, 9.44e-26, 7.79e-26, 6.22e-26, 4.64e-26, 3.4e-26, 2.47e-26,
3157 1.78e-26, 1.29e-26, 9.26e-27, 7e-27, 5.36e-27, 4.26e-27, 3.41e-27,
3158 2.79e-27, 2.36e-27, 2.01e-27, 1.75e-27, 1.52e-27, 1.33e-27, 1.16e-27,
3159 1.01e-27, 8.83e-28, 7.71e-28, 6.77e-28, 6.01e-28, 5.34e-28, 4.72e-28,
3160 4.2e-28, 3.69e-28, 3.27e-28, 2.92e-28, 2.57e-28, 2.27e-28, 2e-28,
3161 1.77e-28, 1.56e-28, 1.37e-28, 1.2e-28, 1.05e-28, 9.18e-29, 8e-29,
3162 6.98e-29, 6.08e-29, 5.27e-29, 4.56e-29, 3.94e-29, 3.4e-29, 2.93e-29,
3163 2.51e-29, 2.15e-29, 1.84e-29, 1.57e-29, 1.34e-29, 1.14e-29, 9.66e-30,
3164 8.19e-30, 6.93e-30, 5.86e-30, 4.95e-30, 4.19e-30, 3.56e-30, 3.06e-30,
3165 2.67e-30, 2.41e-30, 2.26e-30, 2.25e-30, 2.36e-30, 2.57e-30, 2.84e-30,
3166 3.18e-30, 3.49e-30, 3.71e-30, 3.81e-30, 3.84e-30, 3.8e-30, 3.59e-30,
3167 3.37e-30, 3.08e-30, 2.77e-30, 2.47e-30, 2.2e-30, 2.05e-30, 1.99e-30,
3168 2.03e-30, 2.13e-30, 2.25e-30, 2.34e-30, 2.41e-30, 2.47e-30, 2.48e-30,
3169 2.5e-30, 2.52e-30, 2.58e-30, 2.64e-30, 2.69e-30, 2.79e-30, 2.95e-30,
3170 3.13e-30, 3.34e-30, 3.57e-30, 3.84e-30, 4.2e-30, 4.66e-30, 5.21e-30,
3171 5.96e-30, 6.89e-30, 8.01e-30, 9.32e-30, 1.08e-29, 1.24e-29, 1.45e-29,
3172 1.71e-29, 2.01e-29, 2.36e-29, 2.82e-29, 3.38e-29, 4.01e-29, 4.79e-29,
3173 5.74e-29, 6.92e-29, 8.338e-29, 1.015e-28, 1.246e-28, 1.512e-28, 1.851e-28,
3174 2.32e-28, 2.988e-28, 3.989e-28, 5.351e-28, 7.256e-28, 1.011e-27,
3175 1.388e-27,
3176 1.914e-27, 2.512e-27, 3.257e-27, 4.075e-27, 4.991e-27, 5.914e-27,
3177 6.638e-27,
3178 7.16e-27, 7.45e-27, 7.59e-27, 7.54e-27, 7.47e-27, 7.53e-27, 7.94e-27,
3179 8.46e-27, 8.95e-27, 9.36e-27, 9.84e-27, 1.02e-26, 1.05e-26, 1.06e-26,
3180 1.07e-26, 1.07e-26, 1.04e-26, 9.79e-27, 8.8e-27, 7.66e-27, 6.38e-27,
3181 5.142e-27, 3.982e-27, 2.94e-27, 2.177e-27, 1.612e-27, 1.185e-27,
3182 8.966e-28,
3183 6.735e-28, 5.219e-28, 4.14e-28, 3.403e-28, 2.811e-28, 2.358e-28,
3184 1.969e-28,
3185 1.684e-28, 1.462e-28, 1.285e-28, 1.134e-28, 9.916e-29, 8.65e-29, 7.55e-29,
3186 6.62e-29, 5.83e-29, 5.14e-29, 4.51e-29, 3.98e-29, 3.53e-29, 3.12e-29,
3187 2.78e-29, 2.48e-29, 2.18e-29, 1.93e-29, 1.7e-29, 1.5e-29, 1.33e-29,
3188 1.16e-29, 1.03e-29, 9.01e-30, 7.86e-30, 6.88e-30, 6.02e-30, 5.25e-30,
3189 4.57e-30, 3.96e-30, 3.44e-30, 2.98e-30, 2.57e-30, 2.21e-30, 1.9e-30,
3190 1.63e-30, 1.4e-30, 1.21e-30, 1.04e-30, 9.09e-31, 7.96e-31, 7.05e-31,
3191 6.3e-31, 5.67e-31, 5.09e-31, 4.55e-31, 4.04e-31, 3.55e-31, 3.09e-31,
3192 2.64e-31, 2.26e-31, 1.9e-31, 1.6e-31, 1.34e-31, 1.14e-31, 1.01e-31,
3193 9.17e-32, 8.69e-32, 8.47e-32, 8.33e-32, 8.2e-32, 8.04e-32, 7.95e-32,
3194 7.98e-32, 8.25e-32, 8.47e-32, 8.74e-32, 8.87e-32, 8.92e-32, 8.71e-32,
3195 8.3e-32, 7.89e-32, 7.59e-32, 7.5e-32, 7.63e-32, 8.06e-32, 8.89e-32,
3196 1e-31, 1.14e-31, 1.28e-31, 1.45e-31, 1.64e-31, 1.87e-31, 2.12e-31,
3197 2.44e-31, 2.85e-31, 3.31e-31, 3.83e-31, 4.46e-31, 5.23e-31, 6.15e-31,
3198 7.35e-31, 8.84e-31, 1.07e-30, 1.29e-30, 1.59e-30, 1.99e-30, 2.49e-30,
3199 3.12e-30, 3.91e-30, 4.98e-30, 6.28e-30, 7.86e-30, 9.66e-30, 1.16e-29,
3200 1.41e-29, 1.7e-29, 2.06e-29, 2.54e-29, 3.17e-29, 4.08e-29, 5.24e-29,
3201 6.8e-29, 8.92e-29, 1.13e-28, 1.4e-28, 1.7e-28, 2.05e-28, 2.37e-28,
3202 2.61e-28, 2.77e-28, 2.85e-28, 2.86e-28, 2.78e-28, 2.72e-28, 2.74e-28,
3203 2.83e-28, 3.01e-28, 3.22e-28, 3.52e-28, 3.78e-28, 4.03e-28, 4.21e-28,
3204 4.33e-28, 4.39e-28, 4.34e-28, 4.25e-28, 4.07e-28, 3.88e-28, 3.67e-28,
3205 3.56e-28, 3.52e-28, 3.67e-28, 4.02e-28, 4.64e-28, 5.63e-28, 6.89e-28,
3206 8.82e-28, 1.11e-27, 1.41e-27, 1.73e-27, 2.12e-27, 2.57e-27, 2.99e-27,
3207 3.45e-27, 3.79e-27, 4.09e-27, 4.23e-27, 4.3e-27, 4.33e-27, 4.35e-27,
3208 4.44e-27, 4.54e-27, 4.62e-27, 4.67e-27, 4.71e-27, 4.77e-27, 4.93e-27,
3209 5.19e-27, 5.54e-27, 5.9e-27, 6.12e-27, 6.15e-27, 5.81e-27, 5.21e-27,
3210 4.51e-27, 3.69e-27, 2.89e-27, 2.14e-27, 1.55e-27, 1.11e-27, 7.78e-28,
3211 5.46e-28, 3.93e-28, 2.93e-28, 2.26e-28, 1.82e-28, 1.52e-28, 1.31e-28,
3212 1.15e-28, 1.02e-28, 9.01e-29, 7.95e-29, 7.04e-29, 6.2e-29, 5.49e-29,
3213 4.86e-29, 4.34e-29, 3.88e-29, 3.46e-29, 3.07e-29, 2.71e-29, 2.38e-29,
3214 2.09e-29, 1.82e-29, 1.59e-29, 1.38e-29, 1.2e-29, 1.04e-29, 9.08e-30,
3215 7.88e-30, 6.85e-30, 5.96e-30, 5.2e-30, 4.53e-30, 3.94e-30, 3.43e-30,
3216 2.97e-30, 2.58e-30, 2.23e-30, 1.92e-30, 1.66e-30, 1.43e-30, 1.24e-30,
3217 1.06e-30, 9.1e-31, 7.79e-31, 6.65e-31, 5.68e-31, 4.84e-31, 4.11e-31,
3218 3.51e-31, 2.99e-31, 2.54e-31, 2.17e-31, 1.86e-31, 1.59e-31, 1.37e-31,
3219 1.18e-31, 1.04e-31, 9.24e-32, 8.39e-32, 7.86e-32, 7.7e-32, 7.85e-32,
3220 8.41e-32, 9.62e-32, 1.16e-31, 1.47e-31, 1.94e-31, 2.58e-31, 3.51e-31,
3221 4.73e-31, 6.26e-31, 7.98e-31, 9.95e-31, 1.21e-30, 1.4e-30, 1.58e-30,
3222 1.77e-30, 1.98e-30, 2.22e-30, 2.47e-30, 2.79e-30, 3.14e-30, 3.55e-30,
3223 4e-30, 4.51e-30, 5.15e-30, 5.73e-30, 6.25e-30, 6.65e-30, 6.91e-30,
3224 6.98e-30, 6.83e-30, 6.67e-30, 6.57e-30, 6.6e-30, 6.84e-30, 7.39e-30,
3225 8.04e-30, 8.73e-30, 9.44e-30, 9.95e-30, 1.03e-29, 1.01e-29, 9.8e-30,
3226 9.32e-30, 8.67e-30, 7.99e-30, 7.29e-30, 6.67e-30, 6.14e-30, 5.78e-30,
3227 5.65e-30, 5.65e-30, 5.88e-30, 6.43e-30, 7.5e-30, 9.16e-30, 1.16e-29,
3228 1.51e-29, 1.99e-29, 2.7e-29, 3.66e-29, 4.95e-29, 6.41e-29, 8.16e-29,
3229 1.02e-28, 1.24e-28, 1.46e-28, 1.64e-28, 1.79e-28, 1.87e-28, 1.93e-28,
3230 1.93e-28, 1.93e-28, 1.95e-28, 2.07e-28, 2.23e-28, 2.34e-28, 2.44e-28,
3231 2.55e-28, 2.67e-28, 2.76e-28, 2.81e-28, 2.9e-28, 2.94e-28, 2.91e-28,
3232 2.77e-28, 2.52e-28, 2.21e-28, 1.84e-28, 1.49e-28, 1.15e-28, 8.64e-29,
3233 6.44e-29, 4.79e-29, 3.64e-29, 2.75e-29, 2.14e-29, 1.75e-29, 1.48e-29,
3234 1.3e-29, 1.16e-29, 1.05e-29, 9.46e-30, 8.55e-30, 7.66e-30, 6.79e-30,
3235 6.01e-30, 5.3e-30, 4.67e-30, 4.13e-30, 3.67e-30, 3.29e-30, 2.92e-30,
3236 2.57e-30, 2.27e-30, 1.96e-30, 1.7e-30, 1.47e-30, 1.27e-30, 1.1e-30,
3237 9.19e-31, 7.79e-31, 6.59e-31, 5.61e-31, 4.81e-31, 4.07e-31, 3.54e-31,
3238 3.04e-31, 2.62e-31, 2.3e-31, 1.97e-31, 1.71e-31, 1.48e-31, 1.28e-31,
3239 1.1e-31, 9.44e-32, 8.08e-32, 6.94e-32, 5.93e-32, 5.06e-32, 4.31e-32,
3240 3.66e-32, 3.12e-32, 2.67e-32, 2.28e-32, 1.95e-32, 1.67e-32, 1.43e-32,
3241 1.22e-32, 1.05e-32, 9.06e-33, 7.86e-33, 6.87e-33, 6.09e-33, 5.5e-33,
3242 5.07e-33, 4.78e-33, 4.66e-33, 4.77e-33, 5.21e-33, 5.94e-33, 7.44e-33,
3243 9.71e-33, 1.35e-32, 1.87e-32, 2.63e-32, 3.67e-32, 4.95e-32, 6.39e-32,
3244 8e-32, 9.88e-32, 1.15e-31, 1.28e-31, 1.37e-31, 1.43e-31, 1.47e-31,
3245 1.45e-31, 1.42e-31, 1.4e-31, 1.41e-31, 1.43e-31, 1.51e-31, 1.65e-31,
3246 1.83e-31, 2.07e-31, 2.25e-31, 2.38e-31, 2.42e-31, 2.38e-31, 2.27e-31,
3247 2.1e-31, 1.98e-31, 1.89e-31, 1.79e-31, 1.72e-31, 1.62e-31, 1.54e-31,
3248 1.43e-31, 1.35e-31, 1.35e-31, 1.42e-31, 1.57e-31, 1.77e-31, 2.06e-31,
3249 2.42e-31, 2.85e-31, 3.43e-31, 4.16e-31, 5.24e-31, 6.82e-31, 8.92e-31,
3250 1.2e-30, 1.6e-30, 2.15e-30, 2.89e-30, 3.77e-30, 4.8e-30, 5.93e-30,
3251 7.25e-30, 8.53e-30, 9.6e-30, 1.04e-29, 1.08e-29, 1.1e-29, 1.09e-29,
3252 1.07e-29, 1.07e-29, 1.12e-29, 1.21e-29, 1.33e-29, 1.48e-29, 1.64e-29,
3253 1.79e-29, 1.94e-29, 2.05e-29, 2.17e-29, 2.28e-29, 2.4e-29, 2.53e-29,
3254 2.74e-29, 3.03e-29, 3.42e-29, 3.87e-29, 4.47e-29, 5.19e-29, 5.91e-29,
3255 6.77e-29, 7.5e-29, 8.28e-29, 8.83e-29, 9.36e-29, 9.91e-29, 1.03e-28,
3256 1.09e-28, 1.14e-28, 1.17e-28, 1.18e-28, 1.18e-28, 1.18e-28, 1.21e-28,
3257 1.26e-28, 1.35e-28, 1.43e-28, 1.49e-28, 1.49e-28, 1.4e-28, 1.25e-28,
3258 1.07e-28, 8.61e-29, 6.57e-29, 4.8e-29, 3.47e-29, 2.47e-29, 1.78e-29,
3259 1.33e-29, 1.05e-29, 8.72e-30, 7.51e-30, 6.76e-30, 6.27e-30, 6e-30,
3260 5.99e-30, 6.26e-30, 6.86e-30, 7.58e-30, 8.49e-30, 9.53e-30, 1.05e-29,
3261 1.14e-29, 1.2e-29, 1.25e-29, 1.28e-29, 1.3e-29, 1.31e-29, 1.32e-29,
3262 1.33e-29, 1.33e-29, 1.31e-29, 1.27e-29, 1.23e-29, 1.19e-29, 1.2e-29,
3263 1.25e-29, 1.33e-29, 1.42e-29, 1.48e-29, 1.49e-29, 1.41e-29, 1.26e-29,
3264 1.08e-29, 8.8e-30, 6.78e-30, 4.95e-30, 3.58e-30, 2.54e-30, 1.78e-30,
3265 1.26e-30, 9.28e-31, 7.13e-31, 5.56e-31, 4.5e-31, 3.75e-31, 3.21e-31,
3266 2.76e-31, 2.41e-31, 2.09e-31, 1.82e-31, 1.59e-31, 1.36e-31, 1.18e-31,
3267 1.03e-31, 9.01e-32, 7.94e-32, 6.9e-32, 6.02e-32, 5.26e-32, 4.62e-32,
3268 4.06e-32, 3.55e-32, 3.13e-32, 2.76e-32, 2.43e-32, 2.15e-32, 1.9e-32,
3269 1.68e-32, 1.49e-32, 1.32e-32, 1.17e-32, 1.04e-32, 9.35e-33, 8.47e-33,
3270 7.79e-33, 7.3e-33, 6.96e-33, 6.88e-33, 7.11e-33, 7.6e-33, 8.67e-33,
3271 1.04e-32, 1.31e-32, 1.71e-32, 2.2e-32, 2.93e-32, 3.8e-32, 4.97e-32,
3272 6.22e-32, 7.63e-32, 9.29e-32, 1.1e-31, 1.24e-31, 1.34e-31, 1.41e-31,
3273 1.44e-31, 1.44e-31, 1.39e-31, 1.38e-31, 1.41e-31, 1.49e-31, 1.64e-31,
3274 1.86e-31, 2.11e-31, 2.38e-31, 2.65e-31, 2.89e-31, 3.04e-31, 3.14e-31,
3275 3.29e-31, 3.43e-31, 3.6e-31, 3.91e-31, 4.44e-31, 5.21e-31, 6.43e-31,
3276 8.18e-31, 1.06e-30, 1.4e-30, 1.78e-30, 2.24e-30, 2.77e-30, 3.35e-30,
3277 3.95e-30, 4.47e-30, 4.92e-30, 5.2e-30, 5.39e-30, 5.46e-30, 5.53e-30,
3278 5.66e-30, 6.02e-30, 6.43e-30, 6.68e-30, 6.91e-30, 7.12e-30, 7.42e-30,
3279 7.55e-30, 7.75e-30, 8.09e-30, 8.3e-30, 8.35e-30, 7.95e-30, 7.22e-30,
3280 6.3e-30, 5.23e-30, 4.2e-30, 3.19e-30, 2.39e-30, 1.79e-30, 1.36e-30,
3281 1.05e-30, 8.32e-31, 6.89e-31, 5.89e-31, 5.14e-31, 4.6e-31, 4.19e-31,
3282 3.94e-31, 3.9e-31, 4.07e-31, 4.39e-31, 4.82e-31, 5.29e-31, 5.75e-31,
3283 6.09e-31, 6.28e-31, 6.31e-31, 6.19e-31, 6.04e-31, 5.85e-31, 5.71e-31,
3284 5.68e-31, 5.68e-31, 5.64e-31, 5.58e-31, 5.51e-31, 5.48e-31, 5.45e-31,
3285 5.57e-31, 5.77e-31, 5.96e-31, 6.05e-31, 5.89e-31, 5.43e-31, 4.77e-31,
3286 4.02e-31, 3.25e-31, 2.5e-31, 1.82e-31, 1.31e-31, 9.32e-32, 6.58e-32,
3287 4.64e-32, 3.35e-32, 2.53e-32, 1.96e-32, 1.58e-32, 1.31e-32, 1.11e-32,
3288 9.58e-33, 8.32e-33, 7.31e-33, 6.43e-33, 5.62e-33, 4.89e-33, 4.27e-33,
3289 3.73e-33, 3.25e-33, 2.84e-33, 2.5e-33, 2.21e-33, 1.95e-33, 1.72e-33,
3290 1.52e-33, 1.34e-33, 1.18e-33, 1.05e-33, 9.26e-34, 8.21e-34, 7.29e-34,
3291 6.48e-34, 5.77e-34, 5.15e-34, 4.62e-34, 4.17e-34, 3.79e-34, 3.49e-34,
3292 3.26e-34, 3.09e-34, 3e-34, 2.98e-34, 3.04e-34, 3.2e-34, 3.49e-34,
3293 3.96e-34, 4.68e-34, 5.78e-34, 7.42e-34, 9.8e-34, 1.32e-33, 1.79e-33,
3294 2.23e-33, 2.65e-33, 3.02e-33, 3.38e-33, 3.74e-33, 4.05e-33, 4.42e-33,
3295 4.94e-33, 5.48e-33, 6.11e-33, 6.77e-33, 7.56e-33, 8.49e-33, 9.59e-33,
3296 1.09e-32, 1.27e-32, 1.48e-32, 1.73e-32, 2.08e-32, 2.48e-32, 3.03e-32,
3297 3.88e-32, 4.86e-32, 6.25e-32, 8.05e-32, 1.04e-31, 1.37e-31, 1.75e-31,
3298 2.2e-31, 2.75e-31, 3.35e-31, 4.08e-31, 4.79e-31, 5.44e-31, 5.99e-31,
3299 6.46e-31, 6.82e-31, 7.13e-31, 7.62e-31, 8.36e-31, 9.59e-31, 1.15e-30,
3300 1.38e-30, 1.67e-30, 1.99e-30, 2.35e-30, 2.74e-30, 3.11e-30, 3.51e-30,
3301 3.89e-30, 4.21e-30, 4.49e-30, 4.66e-30, 4.86e-30, 4.96e-30, 5.08e-30,
3302 5.2e-30, 5.29e-30, 5.3e-30, 5.22e-30, 5.16e-30, 5.18e-30, 5.35e-30,
3303 5.68e-30, 6.07e-30, 6.42e-30, 6.6e-30, 6.39e-30, 5.83e-30, 5.03e-30,
3304 4.11e-30, 3.2e-30, 2.35e-30, 1.7e-30, 1.2e-30, 8.54e-31, 6.31e-31,
3305 4.92e-31, 4.01e-31, 3.38e-31, 2.97e-31, 2.71e-31, 2.55e-31, 2.45e-31,
3306 2.42e-31, 2.43e-31, 2.49e-31, 2.6e-31, 2.73e-31, 2.91e-31, 3.16e-31,
3307 3.45e-31, 3.81e-31, 4.14e-31, 4.54e-31, 5.02e-31, 5.48e-31, 6.11e-31,
3308 6.72e-31, 7.37e-31, 7.99e-31, 8.5e-31, 9.01e-31, 9.3e-31, 9.52e-31,
3309 9.64e-31, 9.59e-31, 9.39e-31, 9.14e-31, 8.95e-31, 8.97e-31, 9.3e-31,
3310 9.91e-31, 1.06e-30, 1.12e-30, 1.14e-30, 1.1e-30, 1e-30, 8.68e-31,
3311 7.14e-31, 5.61e-31, 4.17e-31, 3.05e-31, 2.18e-31, 1.55e-31, 1.11e-31,
3312 8.29e-32, 6.38e-32, 5.07e-32, 4.2e-32, 3.64e-32, 3.28e-32, 3.03e-32,
3313 2.9e-32, 2.78e-32, 2.67e-32, 2.52e-32, 2.34e-32, 2.15e-32, 1.95e-32,
3314 1.75e-32, 1.54e-32, 1.32e-32, 1.13e-32, 9.55e-33, 7.9e-33, 6.44e-33,
3315 5.18e-33, 4.14e-33, 3.32e-33, 2.67e-33, 2.18e-33, 1.83e-33, 1.56e-33,
3316 1.35e-33, 1.18e-33, 1.05e-33, 9.31e-34, 8.35e-34, 7.55e-34, 6.89e-34,
3317 6.36e-34, 5.96e-34, 5.69e-34, 5.56e-34, 5.6e-34, 5.86e-34, 6.42e-34,
3318 7.33e-34, 8.85e-34, 1.14e-33, 1.49e-33, 1.97e-33, 2.69e-33, 3.61e-33,
3319 4.79e-33, 6.04e-33, 7.51e-33, 9.2e-33, 1.09e-32, 1.26e-32, 1.39e-32,
3320 1.53e-32, 1.64e-32, 1.71e-32, 1.77e-32, 1.88e-32, 2.08e-32, 2.37e-32,
3321 2.82e-32, 3.42e-32, 4.18e-32, 5.18e-32, 6.47e-32, 7.98e-32, 9.97e-32,
3322 1.22e-31, 1.47e-31, 1.75e-31, 2.05e-31, 2.38e-31, 2.66e-31, 2.91e-31,
3323 3.09e-31, 3.21e-31, 3.29e-31, 3.31e-31, 3.37e-31, 3.49e-31, 3.69e-31,
3324 3.82e-31, 3.92e-31, 4.05e-31, 4.17e-31, 4.3e-31, 4.42e-31, 4.61e-31,
3325 4.78e-31, 4.83e-31, 4.69e-31, 4.31e-31, 3.81e-31, 3.21e-31, 2.61e-31,
3326 2.04e-31, 1.56e-31, 1.2e-31, 9.2e-32, 7.1e-32, 5.65e-32, 4.63e-32,
3327 3.86e-32, 3.27e-32, 2.83e-32, 2.48e-32, 2.22e-32, 2.03e-32, 1.91e-32,
3328 1.84e-32, 1.82e-32, 1.82e-32, 1.86e-32, 1.94e-32, 2.11e-32, 2.36e-32,
3329 2.6e-32, 2.94e-32, 3.31e-32, 3.73e-32, 4.17e-32, 4.57e-32, 4.98e-32,
3330 5.26e-32, 5.54e-32, 5.79e-32, 6.05e-32, 6.38e-32, 6.71e-32, 6.93e-32,
3331 7.03e-32, 7.05e-32, 7.05e-32, 7.16e-32, 7.37e-32, 7.79e-32, 8.3e-32,
3332 8.65e-32, 8.76e-32, 8.32e-32, 7.51e-32, 6.48e-32, 5.31e-32, 4.18e-32,
3333 3.07e-32, 2.22e-32, 1.57e-32, 1.09e-32, 7.39e-33, 5.11e-33, 3.66e-33,
3334 2.68e-33, 2e-33, 1.56e-33, 1.27e-33, 1.06e-33, 9.05e-34, 7.85e-34,
3335 6.9e-34, 6.1e-34, 5.42e-34, 4.84e-34, 4.32e-34, 3.87e-34, 3.47e-34,
3336 3.12e-34, 2.8e-34, 2.52e-34, 2.27e-34, 2.05e-34, 1.86e-34, 1.69e-34,
3337 1.55e-34, 1.43e-34, 1.33e-34, 1.25e-34, 1.2e-34, 1.16e-34, 1.15e-34,
3338 1.16e-34, 1.19e-34, 1.25e-34, 1.34e-34, 1.45e-34, 1.6e-34, 1.78e-34,
3339 2.01e-34, 2.27e-34, 2.59e-34, 2.96e-34, 3.4e-34, 3.92e-34, 4.53e-34,
3340 5.24e-34, 6.08e-34, 7.09e-34, 8.31e-34, 9.81e-34, 1.17e-33, 1.42e-33,
3341 1.78e-33, 2.25e-33, 2.79e-33, 3.5e-33, 4.4e-33, 5.53e-33, 6.92e-33,
3342 8.92e-33, 1.15e-32, 1.48e-32, 1.92e-32, 2.54e-32, 3.37e-32, 4.37e-32,
3343 5.71e-32, 7.26e-32, 8.98e-32, 1.1e-31, 1.34e-31, 1.59e-31, 1.86e-31,
3344 2.14e-31, 2.4e-31, 2.69e-31, 2.98e-31, 3.33e-31, 3.77e-31, 4.25e-31,
3345 4.75e-31, 5.11e-31, 5.37e-31, 5.56e-31, 5.61e-31, 5.67e-31, 5.68e-31,
3346 5.78e-31, 5.86e-31, 5.91e-31, 5.93e-31, 5.91e-31, 5.92e-31, 5.93e-31,
3347 5.94e-31, 5.87e-31, 5.65e-31, 5.21e-31, 4.54e-31, 3.82e-31, 3.07e-31,
3348 2.37e-31, 1.78e-31, 1.32e-31, 9.82e-32, 7.34e-32, 5.59e-32, 4.33e-32,
3349 3.42e-32, 2.74e-32, 2.23e-32, 1.86e-32, 1.56e-32, 1.35e-32, 1.17e-32,
3350 1.05e-32, 9.54e-33, 8.83e-33, 8.34e-33, 8.1e-33, 8.11e-33, 8.2e-33,
3351 8.46e-33, 8.83e-33, 9.33e-33, 9.92e-33, 1.07e-32, 1.19e-32, 1.35e-32,
3352 1.58e-32, 1.86e-32, 2.17e-32, 2.52e-32, 2.92e-32, 3.36e-32, 3.83e-32,
3353 4.3e-32, 4.83e-32, 5.37e-32, 5.81e-32, 6.23e-32, 6.48e-32, 6.77e-32,
3354 6.99e-32, 7.17e-32, 7.47e-32, 7.66e-32, 7.77e-32, 7.77e-32, 7.72e-32,
3355 7.77e-32, 7.97e-32, 8.4e-32, 8.9e-32, 9.42e-32, 9.71e-32, 9.55e-32,
3356 8.85e-32, 7.68e-32, 6.39e-32, 5.02e-32, 3.74e-32, 2.68e-32, 1.87e-32,
3357 1.33e-32, 9.48e-33, 7e-33, 5.37e-33, 4.17e-33, 3.33e-33, 2.76e-33,
3358 2.35e-33, 2.04e-33, 1.78e-33, 1.59e-33, 1.42e-33, 1.23e-33, 1.06e-33,
3359 8.95e-34, 7.45e-34, 6.06e-34, 5.02e-34, 4.22e-34, 3.61e-34, 3.13e-34,
3360 2.75e-34, 2.45e-34, 2.19e-34, 1.97e-34, 1.79e-34, 1.63e-34, 1.49e-34,
3361 1.38e-34, 1.29e-34, 1.22e-34, 1.17e-34, 1.14e-34, 1.14e-34, 1.18e-34,
3362 1.26e-34, 1.41e-34, 1.65e-34, 2.04e-34, 2.65e-34, 3.59e-34, 4.87e-34,
3363 6.41e-34, 8.47e-34, 1.07e-33, 1.32e-33, 1.66e-33, 2.07e-33, 2.62e-33,
3364 3.21e-33, 3.94e-33, 4.84e-33, 5.81e-33, 6.84e-33, 7.73e-33, 8.67e-33,
3365 9.62e-33, 1.06e-32, 1.19e-32, 1.35e-32, 1.56e-32, 1.85e-32, 2.21e-32,
3366 2.66e-32, 3.14e-32, 3.6e-32, 3.99e-32, 4.22e-32, 4.36e-32, 4.35e-32,
3367 4.25e-32, 4.1e-32, 3.99e-32, 3.95e-32, 3.87e-32, 3.83e-32, 3.82e-32,
3368 3.89e-32, 3.98e-32, 4.06e-32, 4.19e-32, 4.22e-32, 4.17e-32, 3.9e-32,
3369 3.5e-32, 3.03e-32, 2.49e-32, 1.99e-32, 1.51e-32, 1.15e-32, 8.68e-33,
3370 6.53e-33, 4.89e-33, 3.78e-33, 2.92e-33, 2.25e-33, 1.74e-33, 1.35e-33,
3371 1.07e-33, 8.54e-34, 7.02e-34, 5.95e-34, 5.13e-34, 4.48e-34, 3.89e-34,
3372 3.34e-34, 2.94e-34, 2.63e-34, 2.42e-34, 2.3e-34, 2.27e-34, 2.37e-34,
3373 2.56e-34, 2.78e-34, 3.16e-34, 3.8e-34, 4.86e-34, 6.25e-34, 8.15e-34,
3374 1.01e-33, 1.24e-33, 1.49e-33, 1.73e-33, 1.99e-33, 2.22e-33, 2.44e-33,
3375 2.61e-33, 2.72e-33, 2.85e-33, 2.94e-33, 3.1e-33, 3.29e-33, 3.5e-33,
3376 3.62e-33, 3.66e-33, 3.7e-33, 3.72e-33, 3.83e-33, 4.01e-33, 4.26e-33,
3377 4.51e-33, 4.64e-33, 4.49e-33, 4.05e-33, 3.45e-33, 2.79e-33, 2.12e-33,
3378 1.46e-33, 9.67e-34, 6.18e-34, 3.98e-34, 2.63e-34, 1.81e-34, 1.32e-34,
3379 1.03e-34, 8.42e-35, 7.22e-35, 6.39e-35, 5.78e-35, 5.33e-35, 5e-35,
3380 4.76e-35, 4.61e-35, 4.54e-35, 4.55e-35, 4.64e-35, 4.81e-35, 5.06e-35,
3381 5.41e-35, 5.87e-35, 6.44e-35, 7.15e-35, 8.02e-35, 9.1e-35, 1.05e-34,
3382 1.22e-34, 1.46e-34, 1.8e-34, 2.28e-34, 2.98e-34, 4.02e-34, 5.53e-34,
3383 7.81e-34, 1.04e-33, 1.31e-33, 1.58e-33, 1.89e-33, 2.2e-33, 2.54e-33,
3384 3.01e-33, 3.67e-33, 4.43e-33, 5.42e-33, 6.85e-33, 8.44e-33, 1.04e-32,
3385 1.31e-32, 1.61e-32, 1.95e-32, 2.38e-32, 2.88e-32, 3.42e-32, 4.03e-32,
3386 4.65e-32, 5.24e-32, 5.7e-32, 6.09e-32, 6.39e-32, 6.48e-32, 6.58e-32,
3387 6.66e-32, 6.7e-32, 6.66e-32, 6.65e-32, 6.8e-32, 7.09e-32, 7.54e-32,
3388 8.06e-32, 8.62e-32, 8.89e-32, 8.68e-32, 8.04e-32, 7e-32, 5.83e-32,
3389 4.58e-32, 3.49e-32, 2.71e-32, 2.1e-32, 1.65e-32, 1.31e-32, 1.06e-32,
3390 8.35e-33, 6.45e-33, 5.02e-33, 3.94e-33, 3.09e-33, 2.46e-33
3391 };
3392
3393 static const double tcoslf_table[2001] =
3394 { 6.413, 6.414, 6.275, 6.049, 5.789, 5.557, 5.33,
3395 5.107, 4.893, 4.685, 4.481, 4.282, 4.09, 3.905,
3396 3.72, 3.548, 3.379, 3.215, 3.056, 2.903, 2.756,
3397 2.614, 2.475, 2.344, 2.219, 2.1, 1.983, 1.873,
3398 1.768, 1.67, 1.575, 1.486, 1.45, 1.432, 1.429,
3399 1.431, 1.428, 1.458, 1.517, 1.57, 1.628, 1.689,
3400 1.753, 1.819, 1.886, 1.976, 2.032, 2.106, 2.19,
3401 2.259, 2.33, 2.397, 2.466, 2.537, 2.613, 2.675,
3402 2.746, 2.819, 2.893, 2.97, 3.058, 3.168, 3.319,
3403 3.456, 3.601, 3.752, 3.9, 4.04, 4.183, 4.327,
3404 4.47, 4.602, 4.753, 4.897, 5.039, 5.214, 5.409,
3405 5.608, 5.782, 5.917, 5.983, 5.998, 6.016, 6.016,
3406 6.037, 6.026, 6.018, 6.021, 6.006, 6.005, 5.988,
3407 5.978, 5.956, 5.947, 5.898, 5.91, 5.88, 5.842,
3408 5.819, 5.772, 5.775, 5.74, 5.712, 5.685, 5.659,
3409 5.631, 5.601, 5.574, 5.541, 5.509, 5.474, 5.437,
3410 5.399, 5.359, 5.314, 5.261, 5.205, 5.146, 5.075,
3411 4.997, 4.909, 4.818, 4.709, 4.575, 4.411, 4.245,
3412 4.075, 3.889, 3.672, 3.387, 3.173, 2.907, 2.708,
3413 2.536, 2.35, 2.273, 2.196, 2.178, 2.201, 2.238,
3414 2.309, 2.382, 2.462, 2.579, 2.679, 2.737, 2.81,
3415 2.887, 2.964, 2.98, 3.011, 3.098, 3.157, 3.211,
3416 3.274, 3.388, 3.475, 3.527, 3.618, 3.772, 3.864,
3417 3.884, 3.889, 3.894, 3.884, 3.821, 3.758, 3.703,
3418 3.657, 3.567, 3.49, 3.435, 3.377, 3.29, 3.204,
3419 3.178, 3.146, 3.103, 3.088, 3.108, 3.116, 3.07,
3420 3.046, 3.029, 3.017, 3.001, 3.007, 2.984, 2.98,
3421 2.936, 2.908, 2.896, 2.875, 2.893, 2.888, 2.948,
3422 3.028, 3.064, 3.182, 3.228, 3.26, 3.335, 3.412,
3423 3.468, 3.523, 3.616, 3.659, 3.704, 3.81, 3.833,
3424 3.966, 4.026, 4.088, 4.141, 4.2, 4.269, 4.377,
3425 4.459, 4.566, 4.638, 4.709, 4.802, 4.878, 4.974,
3426 5.047, 5.147, 5.211, 5.315, 5.391, 5.483, 5.566,
3427 5.603, 5.643, 5.767, 5.807, 5.843, 5.904, 5.924,
3428 5.983, 5.993, 6.059, 6.095, 6.13, 6.153, 6.174,
3429 6.18, 6.201, 6.202, 6.21, 6.206, 6.209, 6.187,
3430 6.172, 6.138, 6.129, 6.085, 6.066, 6.043, 6.001,
3431 5.951, 5.93, 5.869, 5.822, 5.809, 5.777, 5.739,
3432 5.7, 5.68, 5.659, 5.598, 5.558, 5.519, 5.465,
3433 5.399, 5.358, 5.294, 5.225, 5.158, 5.094, 5.023,
3434 4.94, 4.846, 4.759, 4.662, 4.557, 4.435, 4.304,
3435 4.188, 4.042, 3.954, 3.803, 3.695, 3.619, 3.51,
3436 3.414, 3.366, 3.284, 3.217, 3.152, 3.044, 2.983,
3437 2.898, 2.784, 2.68, 2.627, 2.634, 2.704, 2.637,
3438 2.756, 2.79, 2.941, 3.091, 3.203, 3.308, 3.431,
3439 3.49, 3.57, 3.652, 3.683, 3.708, 3.722, 3.687,
3440 3.631, 3.584, 3.566, 3.536, 3.459, 3.401, 3.326,
3441 3.216, 3.103, 2.944, 2.828, 2.652, 2.597, 2.559,
3442 2.522, 2.468, 2.466, 2.43, 2.412, 2.383, 2.357,
3443 2.338, 2.312, 2.287, 2.25, 2.221, 2.174, 2.174,
3444 2.135, 2.109, 2.107, 2.106, 2.062, 2.075, 2.08,
3445 2.136, 2.219, 2.291, 2.415, 2.52, 2.663, 2.797,
3446 2.936, 3.112, 3.244, 3.347, 3.437, 3.501, 3.513,
3447 3.511, 3.515, 3.553, 3.553, 3.568, 3.621, 3.713,
3448 3.836, 3.888, 3.897, 3.874, 3.825, 3.743, 3.626,
3449 3.503, 3.365, 3.225, 3.077, 2.914, 2.764, 2.623,
3450 2.508, 2.433, 2.42, 2.41, 2.445, 2.49, 2.623,
3451 2.753, 2.871, 2.981, 3.069, 3.176, 3.27, 3.339,
3452 3.394, 3.45, 3.511, 3.572, 3.623, 3.668, 3.742,
3453 3.807, 3.893, 3.961, 4.019, 4.106, 4.194, 4.286,
3454 4.364, 4.447, 4.532, 4.629, 4.719, 4.815, 4.9,
3455 4.989, 5.067, 5.16, 5.245, 5.326, 5.406, 5.479,
3456 5.558, 5.632, 5.702, 5.772, 5.831, 5.893, 5.953,
3457 6.009, 6.056, 6.103, 6.143, 6.183, 6.21, 6.239,
3458 6.258, 6.264, 6.263, 6.247, 6.229, 6.201, 6.176,
3459 6.141, 6.11, 6.096, 6.085, 6.071, 6.05, 6.053,
3460 6.042, 6.035, 6.018, 6.005, 5.99, 5.955, 5.931,
3461 5.884, 5.833, 5.782, 5.724, 5.664, 5.594, 5.542,
3462 5.484, 5.422, 5.351, 5.284, 5.222, 5.143, 5.063,
3463 4.978, 4.896, 4.81, 4.723, 4.625, 4.525, 4.431,
3464 4.334, 4.231, 4.123, 4.022, 3.918, 3.831, 3.726,
3465 3.624, 3.537, 3.454, 3.367, 3.279, 3.211, 3.137,
3466 3.056, 2.968, 2.876, 2.764, 2.638, 2.486, 2.392,
3467 2.28, 2.193, 2.08, 2.056, 2.097, 2.155, 2.239,
3468 2.327, 2.461, 2.617, 2.759, 2.925, 3.082, 3.253,
3469 3.366, 3.491, 3.58, 3.67, 3.733, 3.756, 3.735,
3470 3.663, 3.612, 3.604, 3.655, 3.671, 3.68, 3.721,
3471 3.769, 3.769, 3.71, 3.605, 3.493, 3.383, 3.231,
3472 3.109, 2.936, 2.781, 2.645, 2.514, 2.397, 2.304,
3473 2.236, 2.212, 2.195, 2.204, 2.248, 2.337, 2.464,
3474 2.575, 2.714, 2.815, 2.941, 3.072, 3.173, 3.263,
3475 3.331, 3.398, 3.471, 3.531, 3.597, 3.657, 3.737,
3476 3.8, 3.844, 3.932, 3.997, 4.062, 4.135, 4.214,
3477 4.303, 4.378, 4.46, 4.563, 4.642, 4.72, 4.808,
3478 4.885, 4.978, 5.063, 5.142, 5.234, 5.318, 5.395,
3479 5.482, 5.553, 5.624, 5.684, 5.737, 5.792, 5.84,
3480 5.886, 5.925, 5.969, 6.01, 6.043, 6.078, 6.109,
3481 6.142, 6.159, 6.184, 6.201, 6.207, 6.211, 6.207,
3482 6.204, 6.187, 6.17, 6.151, 6.126, 6.099, 6.067,
3483 6.033, 5.992, 5.956, 5.919, 5.885, 5.847, 5.813,
3484 5.787, 5.755, 5.725, 5.687, 5.651, 5.607, 5.557,
3485 5.51, 5.458, 5.406, 5.35, 5.29, 5.225, 5.163,
3486 5.094, 5.013, 4.933, 4.852, 4.756, 4.661, 4.554,
3487 4.44, 4.326, 4.198, 4.078, 3.961, 3.823, 3.714,
3488 3.606, 3.527, 3.43, 3.345, 3.28, 3.216, 3.151,
3489 3.057, 2.985, 2.902, 2.786, 2.694, 2.64, 2.634,
3490 2.655, 2.667, 2.741, 2.824, 2.955, 3.069, 3.196,
3491 3.298, 3.408, 3.501, 3.577, 3.642, 3.673, 3.712,
3492 3.712, 3.688, 3.632, 3.598, 3.567, 3.536, 3.461,
3493 3.398, 3.331, 3.211, 3.099, 2.947, 2.825, 2.651,
3494 2.467, 2.338, 2.184, 2.098, 2.061, 2.037, 2.101,
3495 2.154, 2.279, 2.397, 2.514, 2.669, 2.799, 2.946,
3496 3.099, 3.232, 3.331, 3.404, 3.471, 3.481, 3.516,
3497 3.537, 3.587, 3.613, 3.637, 3.702, 3.772, 3.874,
3498 3.898, 3.883, 3.84, 3.771, 3.692, 3.566, 3.436,
3499 3.29, 3.133, 3.002, 2.833, 2.686, 2.565, 2.498,
3500 2.489, 2.51, 2.575, 2.69, 2.836, 2.967, 3.067,
3501 3.15, 3.215, 3.275, 3.333, 3.369, 3.416, 3.478,
3502 3.526, 3.563, 3.603, 3.649, 3.678, 3.694, 3.716,
3503 3.74, 3.761, 3.8, 3.831, 3.874, 3.942, 4.005,
3504 4.099, 4.193, 4.29, 4.387, 4.497, 4.617, 4.715,
3505 4.805, 4.894, 4.991, 5.084, 5.161, 5.236, 5.3,
3506 5.368, 5.454, 5.529, 5.589, 5.654, 5.714, 5.786,
3507 5.838, 5.886, 5.947, 5.987, 6.032, 6.071, 6.099,
3508 6.122, 6.136, 6.147, 6.151, 6.144, 6.129, 6.104,
3509 6.063, 6.008, 5.936, 5.835, 5.713, 5.572, 5.404,
3510 5.225, 5.042, 4.88, 4.718, 4.576, 4.46, 4.355,
3511 4.234, 4.111, 3.975, 3.888, 3.766, 3.683, 3.633,
3512 3.637, 3.669, 3.702, 3.739, 3.804, 3.87, 3.916,
3513 3.948, 3.943, 3.971, 3.98, 3.982, 3.967, 3.95,
3514 3.947, 3.92, 3.888, 3.819, 3.756, 3.689, 3.618,
3515 3.523, 3.405, 3.303, 3.206, 3.098, 2.963, 2.816,
3516 2.667, 2.521, 2.39, 2.261, 2.135, 2.031, 1.988,
3517 1.995, 2.044, 2.105, 2.189, 2.315, 2.445, 2.592,
3518 2.745, 2.907, 3.07, 3.231, 3.34, 3.45, 3.547,
3519 3.617, 3.682, 3.683, 3.653, 3.577, 3.558, 3.572,
3520 3.597, 3.648, 3.693, 3.772, 3.801, 3.772, 3.703,
3521 3.597, 3.459, 3.335, 3.189, 3.054, 2.901, 2.756,
3522 2.629, 2.519, 2.415, 2.379, 2.391, 2.433, 2.485,
3523 2.612, 2.787, 2.913, 3.033, 3.11, 3.185, 3.21,
3524 3.254, 3.286, 3.316, 3.334, 3.376, 3.422, 3.443,
3525 3.471, 3.492, 3.496, 3.491, 3.491, 3.481, 3.46,
3526 3.475, 3.466, 3.471, 3.485, 3.482, 3.548, 3.566,
3527 3.643, 3.748, 3.8, 3.956, 4.068, 4.223, 4.357,
3528 4.506, 4.634, 4.752, 4.839, 4.89, 4.95, 5.034,
3529 5.113, 5.176, 5.228, 5.383, 5.523, 5.62, 5.705,
3530 5.775, 5.823, 5.885, 5.931, 5.96, 5.985, 6.006,
3531 6.019, 6.021, 6.015, 5.997, 5.954, 5.901, 5.817,
3532 5.716, 5.554, 5.389, 5.18, 4.951, 4.772, 4.646,
3533 4.551, 4.424, 4.389, 4.41, 4.457, 4.471, 4.473,
3534 4.545, 4.605, 4.644, 4.652, 4.669, 4.666, 4.639,
3535 4.603, 4.531, 4.493, 4.449, 4.411, 4.361, 4.304,
3536 4.269, 4.212, 4.17, 4.152, 4.133, 4.119, 4.1,
3537 4.105, 4.096, 4.042, 3.964, 3.876, 3.779, 3.652,
3538 3.513, 3.359, 3.201, 3.075, 2.935, 2.775, 2.682,
3539 2.601, 2.613, 2.64, 2.663, 2.73, 2.82, 2.936,
3540 3.052, 3.149, 3.243, 3.322, 3.394, 3.441, 3.479,
3541 3.449, 3.423, 3.388, 3.331, 3.253, 3.153, 3.109,
3542 3.05, 2.952, 2.864, 2.808, 2.708, 2.657, 2.594,
3543 2.554, 2.543, 2.549, 2.623, 2.708, 2.798, 2.909,
3544 3.039, 3.161, 3.244, 3.293, 3.358, 3.389, 3.424,
3545 3.489, 3.559, 3.601, 3.641, 3.707, 3.791, 3.879,
3546 3.902, 3.873, 3.811, 3.726, 3.637, 3.519, 3.357,
3547 3.205, 3.055, 2.898, 2.737, 2.612, 2.543, 2.531,
3548 2.589, 2.697, 2.819, 2.914, 2.991, 3.045, 3.067,
3549 3.06, 3.082, 3.087, 3.11, 3.145, 3.183, 3.249,
3550 3.296, 3.346, 3.399, 3.409, 3.449, 3.472, 3.497,
3551 3.55, 3.593, 3.638, 3.674, 3.731, 3.795, 3.863,
3552 3.874, 3.845, 3.808, 3.739, 3.661, 3.556, 3.411,
3553 3.273, 3.139, 3.009, 2.865, 2.736, 2.675, 2.674,
3554 2.73, 2.845, 2.969, 3.148, 3.3, 3.429, 3.55,
3555 3.642, 3.721, 3.797, 3.866, 3.918, 3.992, 4.054,
3556 4.117, 4.18, 4.237, 4.318, 4.4, 4.482, 4.567,
3557 4.648, 4.735, 4.813, 4.886, 4.958, 5.022, 5.083,
3558 5.137, 5.186, 5.231, 5.266, 5.295, 5.317, 5.324,
3559 5.311, 5.287, 5.248, 5.178, 5.076, 4.954, 4.793,
3560 4.605, 4.349, 4.099, 3.939, 3.72, 3.578, 3.462,
3561 3.431, 3.463, 3.48, 3.528, 3.564, 3.631, 3.705,
3562 3.747, 3.782, 3.802, 3.825, 3.821, 3.787, 3.737,
3563 3.698, 3.642, 3.563, 3.445, 3.32, 3.2, 3.072,
3564 2.931, 2.722, 2.582, 2.409, 2.311, 2.237, 2.194,
3565 2.209, 2.256, 2.352, 2.45, 2.584, 2.72, 2.87,
3566 3.018, 3.184, 3.316, 3.408, 3.506, 3.577, 3.623,
3567 3.604, 3.565, 3.555, 3.562, 3.585, 3.603, 3.681,
3568 3.774, 3.838, 3.83, 3.779, 3.711, 3.592, 3.455,
3569 3.326, 3.157, 3.007, 2.847, 2.702, 2.583, 2.503,
3570 2.479, 2.513, 2.588, 2.656, 2.78, 2.894, 2.967,
3571 3.026, 3.076, 3.122, 3.164, 3.212, 3.282, 3.335,
3572 3.405, 3.468, 3.508, 3.546, 3.57, 3.591, 3.575,
3573 3.576, 3.611, 3.619, 3.649, 3.675, 3.764, 3.854,
3574 3.88, 3.873, 3.83, 3.767, 3.673, 3.556, 3.44,
3575 3.309, 3.188, 3.07, 2.969, 2.906, 2.871, 2.904,
3576 3.003, 3.162, 3.317, 3.469, 3.647, 3.774, 3.884,
3577 3.98, 4.066, 4.143, 4.225, 4.323, 4.419, 4.515,
3578 4.603, 4.707, 4.809, 4.893, 4.984, 5.071, 5.156,
3579 5.251, 5.329, 5.407, 5.478, 5.543, 5.594, 5.641,
3580 5.684, 5.708, 5.73, 5.741, 5.745, 5.738, 5.727,
3581 5.701, 5.676, 5.633, 5.591, 5.547, 5.489, 5.431,
3582 5.368, 5.299, 5.224, 5.154, 5.069, 4.99, 4.903,
3583 4.812, 4.717, 4.615, 4.513, 4.404, 4.29, 4.162,
3584 4.023, 3.904, 3.796, 3.683, 3.552, 3.424, 3.295,
3585 3.189, 3.034, 2.878, 2.751, 2.577, 2.47, 2.358,
3586 2.215, 2.154, 2.105, 2.104, 2.117, 2.129, 2.184,
3587 2.237, 2.298, 2.374, 2.462, 2.52, 2.606, 2.6,
3588 2.596, 2.619, 2.618, 2.572, 2.536, 2.573, 2.618,
3589 2.634, 2.646, 2.714, 2.787, 2.875, 2.963, 3.065,
3590 3.179, 3.253, 3.316, 3.352, 3.393, 3.404, 3.445,
3591 3.496, 3.547, 3.597, 3.632, 3.712, 3.787, 3.846,
3592 3.85, 3.806, 3.747, 3.662, 3.573, 3.424, 3.274,
3593 3.142, 3.017, 2.87, 2.765, 2.73, 2.781, 2.864,
3594 2.937, 3.002, 3.032, 3.044, 3.027, 3.007, 2.979,
3595 2.934, 2.897, 2.887, 2.875, 2.853, 2.848, 2.859,
3596 2.903, 2.925, 2.953, 3.006, 3.061, 3.12, 3.184,
3597 3.277, 3.343, 3.374, 3.422, 3.481, 3.521, 3.588,
3598 3.641, 3.695, 3.742, 3.776, 3.85, 3.899, 3.919,
3599 3.891, 3.84, 3.761, 3.662, 3.562, 3.395, 3.261,
3600 3.131, 3.018, 2.887, 2.802, 2.796, 2.87, 2.986,
3601 3.102, 3.247, 3.332, 3.4, 3.455, 3.511, 3.567,
3602 3.624, 3.671, 3.702, 3.734, 3.782, 3.823, 3.835,
3603 3.851, 3.883, 3.919, 3.949, 3.975, 4.014, 4.061,
3604 4.13, 4.218, 4.317, 4.422, 4.559, 4.68, 4.776,
3605 4.862, 4.932, 4.991, 5.033, 5.078, 5.106, 5.117,
3606 5.119, 5.095, 5.053, 4.988, 4.896, 4.785, 4.648,
3607 4.498, 4.352, 4.161, 4.005, 3.841, 3.673, 3.543,
3608 3.398, 3.323, 3.23, 3.17, 3.118, 3.049, 3,
3609 2.932, 2.83, 2.744, 2.617, 2.49, 2.368, 2.261,
3610 2.172, 2.135, 2.165, 2.189, 2.229, 2.313, 2.407,
3611 2.503, 2.601, 2.723, 2.853, 2.968, 3.109, 3.253,
3612 3.342, 3.43, 3.521, 3.572, 3.613, 3.582, 3.603,
3613 3.622, 3.633, 3.662, 3.702, 3.806, 3.86, 3.85,
3614 3.796, 3.722, 3.618, 3.481, 3.347, 3.2, 3.082,
3615 2.952, 2.846, 2.798, 2.783, 2.848, 2.912, 2.97,
3616 3.023, 3.085, 3.107, 3.104, 3.067, 3.034, 2.996,
3617 2.941, 2.914, 2.897, 2.887, 2.903, 2.915, 2.92,
3618 2.969, 3.023, 3.104, 3.174, 3.268, 3.393, 3.481,
3619 3.557, 3.633, 3.662, 3.664, 3.665, 3.712, 3.729,
3620 3.739, 3.774, 3.844, 3.971, 4.023, 4.02, 3.983,
3621 3.913, 3.853, 3.703, 3.511, 3.351, 3.168, 3.014,
3622 2.897, 2.844, 2.918, 3.074, 3.295, 3.464, 3.614,
3623 3.74, 3.858, 3.972, 4.079, 4.188, 4.286, 4.385,
3624 4.486, 4.581, 4.678, 4.767, 4.855, 4.937, 5.008,
3625 5.079, 5.137, 5.187, 5.225, 5.255, 5.271, 5.273,
3626 5.264, 5.247, 5.216, 5.176, 5.131, 5.072, 5.007,
3627 4.941, 4.865, 4.785, 4.704, 4.617, 4.529, 4.439,
3628 4.348, 4.251, 4.153, 4.047, 3.942, 3.826, 3.697,
3629 3.562, 3.403, 3.239, 3.069, 2.915, 2.731, 2.531,
3630 2.341, 2.183, 2.069, 1.908, 1.781, 1.717, 1.691,
3631 1.629, 1.601, 1.635, 1.693, 1.756, 1.826, 1.951,
3632 2.048, 2.126, 2.238, 2.359, 2.474, 2.578, 2.696,
3633 2.803, 2.875, 2.968, 3.056, 3.12, 3.174, 3.258,
3634 3.342, 3.398, 3.466, 3.531, 3.623, 3.712, 3.772,
3635 3.806, 3.811, 3.796, 3.777, 3.757, 3.752, 3.707,
3636 3.672, 3.627, 3.572, 3.506, 3.398, 3.316, 3.227,
3637 3.12, 3.033, 3.028, 3.04, 3.092, 3.143, 3.177,
3638 3.227, 3.242, 3.265, 3.267, 3.243, 3.215, 3.21,
3639 3.215, 3.226, 3.236, 3.258, 3.289, 3.279, 3.268,
3640 3.242, 3.147, 3.11, 3.044, 2.985, 2.903, 2.832,
3641 2.808, 2.782, 2.797, 2.832, 2.903, 2.979, 3.061,
3642 3.163, 3.247, 3.331, 3.383, 3.419, 3.46, 3.496,
3643 3.518, 3.557, 3.623, 3.679, 3.725, 3.762, 3.821,
3644 3.864, 3.899, 3.892, 3.829, 3.752, 3.661, 3.565,
3645 3.44, 3.331, 3.231, 3.13, 3.018, 2.99, 3.044,
3646 3.098, 3.194, 3.294, 3.382, 3.44, 3.485, 3.522,
3647 3.55, 3.568, 3.623, 3.668, 3.715, 3.774, 3.841,
3648 3.903, 3.952, 3.981, 4.009, 4.044, 4.062, 4.099,
3649 4.142, 4.207, 4.286, 4.378, 4.483, 4.578, 4.679,
3650 4.771, 4.857, 4.934, 5.007, 5.086, 5.154, 5.224,
3651 5.295, 5.358, 5.427, 5.489, 5.55, 5.612, 5.671,
3652 5.729, 5.782, 5.836, 5.885, 5.933, 5.978, 6.023,
3653 6.065, 6.102, 6.136, 6.169, 6.197, 6.228, 6.253,
3654 6.275, 6.292, 6.309, 6.323, 6.334, 6.341, 6.349,
3655 6.356, 6.359, 6.359, 6.359, 6.359, 6.356, 6.352,
3656 6.349, 6.342, 6.335, 6.331, 6.324, 6.317, 6.309,
3657 6.306, 6.299, 6.295, 6.288, 6.284, 6.281, 6.281,
3658 6.278, 6.277, 6.278, 6.277, 6.282, 6.283, 6.289,
3659 6.297, 6.3, 6.305, 6.317, 6.325, 6.337, 6.345,
3660 6.36, 6.37, 6.384, 6.398, 6.416, 6.43, 6.448,
3661 6.465, 6.483, 6.502, 6.52, 6.541, 6.562, 6.583,
3662 6.605, 6.628, 6.649, 6.672, 6.697, 6.72, 6.743,
3663 6.768, 6.791, 6.818, 6.841, 6.867, 6.891, 6.916,
3664 6.943, 6.97, 6.996, 7.022, 7.052, 7.077, 7.103,
3665 7.132, 7.158, 7.185, 7.215, 7.241, 7.269, 7.298,
3666 7.326, 7.354, 7.382, 7.41, 7.438, 7.469, 7.497,
3667 7.528, 7.555, 7.585, 7.613, 7.643, 7.669, 7.698,
3668 7.729, 7.759, 7.787, 7.819, 7.849, 7.878, 7.909,
3669 7.936, 7.968, 7.998, 8.03, 8.055, 8.088, 8.115,
3670 8.146, 8.18, 8.205, 8.235, 8.269, 8.297, 8.328,
3671 8.36, 8.393, 8.421, 8.452, 8.484, 8.513, 8.547,
3672 8.576, 8.607, 8.64, 8.671, 8.699, 8.733, 8.762,
3673 8.794, 8.827, 8.855, 8.891, 8.922, 8.954, 8.984,
3674 9.015, 9.049, 9.08, 9.114, 9.143, 9.175, 9.209,
3675 9.241, 9.271, 9.306, 9.338, 9.369, 9.403, 9.435,
3676 9.466, 9.5, 9.532, 9.562, 9.594, 9.63, 9.661,
3677 9.695, 9.726, 9.761, 9.792, 9.825, 9.859, 9.891,
3678 9.924, 9.954, 9.987, 10.02, 10.06, 10.09, 10.12,
3679 10.16, 10.19, 10.22, 10.26, 10.29, 10.32
3680 };
3681
3682 /* Get MT_CKD 4.1 H2O continuum absorption... */
3683 const double xw = nu / 10 + 1;
3684 if (xw >= 1 && xw < 2001) {
3685 const int iw = (int) xw;
3686 const double dw = xw - iw;
3687 const double ew = 1 - dw;
3688 const double cwslf = ew * h2oslf[iw - 1] + dw * h2oslf[iw];
3689 const double cwfrn = ew * h2ofrn[iw - 1] + dw * h2ofrn[iw];
3690 const double tcoslf = ew * tcoslf_table[iw - 1]
3691 + dw * tcoslf_table[iw];
3692 const double ctwslf = cwslf * pow(296 / t, tcoslf);
3693 const double a1 = nu * u * tanh(.7193876 / t * nu);
3694 const double a2 = 296 / t;
3695 const double a3 = p / 1013 * (q * ctwslf + (1 - q) * cwfrn);
3696 return a1 * a2 * a3;
3697 } else
3698 return 0;
3699}

◆ 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 3703 of file jurassic.c.

3706 {
3707
3708 static const double ba[98] =
3709 { 0., 4.45e-8, 5.22e-8, 6.46e-8, 7.75e-8, 9.03e-8,
3710 1.06e-7, 1.21e-7, 1.37e-7, 1.57e-7, 1.75e-7, 2.01e-7, 2.3e-7,
3711 2.59e-7, 2.95e-7, 3.26e-7, 3.66e-7, 4.05e-7, 4.47e-7, 4.92e-7,
3712 5.34e-7, 5.84e-7, 6.24e-7, 6.67e-7, 7.14e-7, 7.26e-7, 7.54e-7,
3713 7.84e-7, 8.09e-7, 8.42e-7, 8.62e-7, 8.87e-7, 9.11e-7, 9.36e-7,
3714 9.76e-7, 1.03e-6, 1.11e-6, 1.23e-6, 1.39e-6, 1.61e-6, 1.76e-6,
3715 1.94e-6, 1.97e-6, 1.87e-6, 1.75e-6, 1.56e-6, 1.42e-6, 1.35e-6,
3716 1.32e-6, 1.29e-6, 1.29e-6, 1.29e-6, 1.3e-6, 1.32e-6, 1.33e-6,
3717 1.34e-6, 1.35e-6, 1.33e-6, 1.31e-6, 1.29e-6, 1.24e-6, 1.2e-6,
3718 1.16e-6, 1.1e-6, 1.04e-6, 9.96e-7, 9.38e-7, 8.63e-7, 7.98e-7,
3719 7.26e-7, 6.55e-7, 5.94e-7, 5.35e-7, 4.74e-7, 4.24e-7, 3.77e-7,
3720 3.33e-7, 2.96e-7, 2.63e-7, 2.34e-7, 2.08e-7, 1.85e-7, 1.67e-7,
3721 1.47e-7, 1.32e-7, 1.2e-7, 1.09e-7, 9.85e-8, 9.08e-8, 8.18e-8,
3722 7.56e-8, 6.85e-8, 6.14e-8, 5.83e-8, 5.77e-8, 5e-8, 4.32e-8, 0.
3723 };
3724
3725 static const double betaa[98] =
3726 { 802., 802., 761., 722., 679., 646., 609., 562.,
3727 511., 472., 436., 406., 377., 355., 338., 319., 299., 278., 255.,
3728 233., 208., 184., 149., 107., 66., 25., -13., -49., -82., -104.,
3729 -119., -130., -139., -144., -146., -146., -147., -148., -150.,
3730 -153., -160., -169., -181., -189., -195., -200., -205., -209.,
3731 -211., -210., -210., -209., -205., -199., -190., -180., -168.,
3732 -157., -143., -126., -108., -89., -63., -32., 1., 35., 65., 95.,
3733 121., 141., 152., 161., 164., 164., 161., 155., 148., 143., 137.,
3734 133., 131., 133., 139., 150., 165., 187., 213., 248., 284., 321.,
3735 372., 449., 514., 569., 609., 642., 673., 673.
3736 };
3737
3738 static const double nua[98] =
3739 { 2120., 2125., 2130., 2135., 2140., 2145., 2150.,
3740 2155., 2160., 2165., 2170., 2175., 2180., 2185., 2190., 2195.,
3741 2200., 2205., 2210., 2215., 2220., 2225., 2230., 2235., 2240.,
3742 2245., 2250., 2255., 2260., 2265., 2270., 2275., 2280., 2285.,
3743 2290., 2295., 2300., 2305., 2310., 2315., 2320., 2325., 2330.,
3744 2335., 2340., 2345., 2350., 2355., 2360., 2365., 2370., 2375.,
3745 2380., 2385., 2390., 2395., 2400., 2405., 2410., 2415., 2420.,
3746 2425., 2430., 2435., 2440., 2445., 2450., 2455., 2460., 2465.,
3747 2470., 2475., 2480., 2485., 2490., 2495., 2500., 2505., 2510.,
3748 2515., 2520., 2525., 2530., 2535., 2540., 2545., 2550., 2555.,
3749 2560., 2565., 2570., 2575., 2580., 2585., 2590., 2595., 2600., 2605.
3750 };
3751
3752 const double t0 = 273.0, tr = 296.0;
3753
3754 /* Check wavenumber range... */
3755 if (nu < nua[0] || nu > nua[97])
3756 return 0;
3757
3758 /* Interpolate B and beta... */
3759 const int idx = locate_reg(nua, 98, nu);
3760 const double b =
3761 1e6 * LIN(nua[idx], ba[idx], nua[idx + 1], ba[idx + 1], nu);
3762 const double beta =
3763 LIN(nua[idx], betaa[idx], nua[idx + 1], betaa[idx + 1], nu);
3764
3765 /* Compute absorption coefficient... */
3766 return 0.1 * POW2(p / P0 * t0 / t) * exp(beta * (1 / tr - 1 / t))
3767 * N2 * b * (N2 + (1 - N2) * (1.294 - 0.4545 * t / tr));
3768}
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 3772 of file jurassic.c.

3775 {
3776
3777 static const double ba[90] =
3778 { 0., .061, .074, .084, .096, .12, .162, .208, .246,
3779 .285, .314, .38, .444, .5, .571, .673, .768, .853, .966, 1.097,
3780 1.214, 1.333, 1.466, 1.591, 1.693, 1.796, 1.922, 2.037, 2.154,
3781 2.264, 2.375, 2.508, 2.671, 2.847, 3.066, 3.417, 3.828, 4.204,
3782 4.453, 4.599, 4.528, 4.284, 3.955, 3.678, 3.477, 3.346, 3.29,
3783 3.251, 3.231, 3.226, 3.212, 3.192, 3.108, 3.033, 2.911, 2.798,
3784 2.646, 2.508, 2.322, 2.13, 1.928, 1.757, 1.588, 1.417, 1.253,
3785 1.109, .99, .888, .791, .678, .587, .524, .464, .403, .357, .32,
3786 .29, .267, .242, .215, .182, .16, .146, .128, .103, .087, .081,
3787 .071, .064, 0.
3788 };
3789
3790 static const double betaa[90] =
3791 { 467., 467., 400., 315., 379., 368., 475., 521.,
3792 531., 512., 442., 444., 430., 381., 335., 324., 296., 248., 215.,
3793 193., 158., 127., 101., 71., 31., -6., -26., -47., -63., -79.,
3794 -88., -88., -87., -90., -98., -99., -109., -134., -160., -167.,
3795 -164., -158., -153., -151., -156., -166., -168., -173., -170.,
3796 -161., -145., -126., -108., -84., -59., -29., 4., 41., 73., 97.,
3797 123., 159., 198., 220., 242., 256., 281., 311., 334., 319., 313.,
3798 321., 323., 310., 315., 320., 335., 361., 378., 373., 338., 319.,
3799 346., 322., 291., 290., 350., 371., 504., 504.
3800 };
3801
3802 static const double nua[90] =
3803 { 1360., 1365., 1370., 1375., 1380., 1385., 1390.,
3804 1395., 1400., 1405., 1410., 1415., 1420., 1425., 1430., 1435.,
3805 1440., 1445., 1450., 1455., 1460., 1465., 1470., 1475., 1480.,
3806 1485., 1490., 1495., 1500., 1505., 1510., 1515., 1520., 1525.,
3807 1530., 1535., 1540., 1545., 1550., 1555., 1560., 1565., 1570.,
3808 1575., 1580., 1585., 1590., 1595., 1600., 1605., 1610., 1615.,
3809 1620., 1625., 1630., 1635., 1640., 1645., 1650., 1655., 1660.,
3810 1665., 1670., 1675., 1680., 1685., 1690., 1695., 1700., 1705.,
3811 1710., 1715., 1720., 1725., 1730., 1735., 1740., 1745., 1750.,
3812 1755., 1760., 1765., 1770., 1775., 1780., 1785., 1790., 1795.,
3813 1800., 1805.
3814 };
3815
3816 const double t0 = 273, tr = 296;
3817
3818 /* Check wavenumber range... */
3819 if (nu < nua[0] || nu > nua[89])
3820 return 0;
3821
3822 /* Interpolate B and beta... */
3823 const int idx = locate_reg(nua, 90, nu);
3824 const double b = LIN(nua[idx], ba[idx], nua[idx + 1], ba[idx + 1], nu);
3825 const double beta =
3826 LIN(nua[idx], betaa[idx], nua[idx + 1], betaa[idx + 1], nu);
3827
3828 /* Compute absorption coefficient... */
3829 return 0.1 * POW2(p / P0 * t0 / t) * exp(beta * (1 / tr - 1 / t)) * O2 * b;
3830}
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 3834 of file jurassic.c.

3838 {
3839
3840 /* Data size... */
3841 const size_t s = (size_t) atm_src->np * sizeof(double);
3842
3843 /* Copy data... */
3844 atm_dest->np = atm_src->np;
3845 memcpy(atm_dest->time, atm_src->time, s);
3846 memcpy(atm_dest->z, atm_src->z, s);
3847 memcpy(atm_dest->lon, atm_src->lon, s);
3848 memcpy(atm_dest->lat, atm_src->lat, s);
3849 memcpy(atm_dest->p, atm_src->p, s);
3850 memcpy(atm_dest->t, atm_src->t, s);
3851 for (int ig = 0; ig < ctl->ng; ig++)
3852 memcpy(atm_dest->q[ig], atm_src->q[ig], s);
3853 for (int iw = 0; iw < ctl->nw; iw++)
3854 memcpy(atm_dest->k[iw], atm_src->k[iw], s);
3855 atm_dest->clz = atm_src->clz;
3856 atm_dest->cldz = atm_src->cldz;
3857 for (int icl = 0; icl < ctl->ncl; icl++)
3858 atm_dest->clk[icl] = atm_src->clk[icl];
3859 atm_dest->sft = atm_src->sft;
3860 for (int isf = 0; isf < ctl->nsf; isf++)
3861 atm_dest->sfeps[isf] = atm_src->sfeps[isf];
3862
3863 /* Initialize... */
3864 if (init)
3865 for (int ip = 0; ip < atm_dest->np; ip++) {
3866 atm_dest->p[ip] = 0;
3867 atm_dest->t[ip] = 0;
3868 for (int ig = 0; ig < ctl->ng; ig++)
3869 atm_dest->q[ig][ip] = 0;
3870 for (int iw = 0; iw < ctl->nw; iw++)
3871 atm_dest->k[iw][ip] = 0;
3872 atm_dest->clz = 0;
3873 atm_dest->cldz = 0;
3874 for (int icl = 0; icl < ctl->ncl; icl++)
3875 atm_dest->clk[icl] = 0;
3876 atm_dest->sft = 0;
3877 for (int isf = 0; isf < ctl->nsf; isf++)
3878 atm_dest->sfeps[isf] = 1;
3879 }
3880}
double lon[NP]
Longitude [deg].
Definition: jurassic.h:1512

◆ 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 3884 of file jurassic.c.

3888 {
3889
3890 /* Data size... */
3891 const size_t s = (size_t) obs_src->nr * sizeof(double);
3892
3893 /* Copy data... */
3894 obs_dest->nr = obs_src->nr;
3895 memcpy(obs_dest->time, obs_src->time, s);
3896 memcpy(obs_dest->obsz, obs_src->obsz, s);
3897 memcpy(obs_dest->obslon, obs_src->obslon, s);
3898 memcpy(obs_dest->obslat, obs_src->obslat, s);
3899 memcpy(obs_dest->vpz, obs_src->vpz, s);
3900 memcpy(obs_dest->vplon, obs_src->vplon, s);
3901 memcpy(obs_dest->vplat, obs_src->vplat, s);
3902 memcpy(obs_dest->tpz, obs_src->tpz, s);
3903 memcpy(obs_dest->tplon, obs_src->tplon, s);
3904 memcpy(obs_dest->tplat, obs_src->tplat, s);
3905 for (int id = 0; id < ctl->nd; id++)
3906 memcpy(obs_dest->rad[id], obs_src->rad[id], s);
3907 for (int id = 0; id < ctl->nd; id++)
3908 memcpy(obs_dest->tau[id], obs_src->tau[id], s);
3909
3910 /* Initialize... */
3911 if (init)
3912 for (int id = 0; id < ctl->nd; id++)
3913 for (int ir = 0; ir < obs_dest->nr; ir++)
3914 if (isfinite(obs_dest->rad[id][ir])) {
3915 obs_dest->rad[id][ir] = 0;
3916 obs_dest->tau[id][ir] = 0;
3917 }
3918}
int nd
Number of radiance channels.
Definition: jurassic.h:1613
double tau[ND][NR]
Transmittance of ray path.
Definition: jurassic.h:1860
double rad[ND][NR]
Radiance [W/(m^2 sr cm^-1)].
Definition: jurassic.h:1863
double tplon[NR]
Tangent point longitude [deg].
Definition: jurassic.h:1854
double vpz[NR]
View point altitude [km].
Definition: jurassic.h:1842
double vplat[NR]
View point latitude [deg].
Definition: jurassic.h:1848
double obslon[NR]
Observer longitude [deg].
Definition: jurassic.h:1836
double obslat[NR]
Observer latitude [deg].
Definition: jurassic.h:1839
double obsz[NR]
Observer altitude [km].
Definition: jurassic.h:1833
double tplat[NR]
Tangent point latitude [deg].
Definition: jurassic.h:1857
double vplon[NR]
View point longitude [deg].
Definition: jurassic.h:1845
double time[NR]
Time (seconds since 2000-01-01T00:00Z).
Definition: jurassic.h:1830
double tpz[NR]
Tangent point altitude [km].
Definition: jurassic.h:1851
int nr
Number of ray paths.
Definition: jurassic.h:1827

◆ 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 3922 of file jurassic.c.

3926 {
3927
3928 const int d0[12] =
3929 { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
3930 const int d0l[12] =
3931 { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
3932
3933 /* Get day of year... */
3934 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
3935 *doy = d0l[mon - 1] + day - 1;
3936 else
3937 *doy = d0[mon - 1] + day - 1;
3938}

◆ 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 3942 of file jurassic.c.

3946 {
3947
3948 const int d0[12] =
3949 { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
3950 const int d0l[12] =
3951 { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
3952 int i;
3953
3954 /* Get month and day... */
3955 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
3956 for (i = 11; i >= 0; i--)
3957 if (d0l[i] <= doy)
3958 break;
3959 *mon = i + 1;
3960 *day = doy - d0l[i] + 1;
3961 } else {
3962 for (i = 11; i >= 0; i--)
3963 if (d0[i] <= doy)
3964 break;
3965 *mon = i + 1;
3966 *day = doy - d0[i] + 1;
3967 }
3968}

◆ 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 3972 of file jurassic.c.

3974 {
3975
3976 for (int ig = 0; ig < ctl->ng; ig++)
3977 if (strcasecmp(ctl->emitter[ig], emitter) == 0)
3978 return ig;
3979
3980 return -1;
3981}

◆ 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 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 3985 of file jurassic.c.

3991 {
3992
3993 /* Save observation mask... */
3994 for (int id = 0; id < ctl->nd; id++)
3995 for (int ir = 0; ir < obs->nr; ir++)
3996 obs->mask[id][ir] = !isfinite(obs->rad[id][ir]);
3997
3998 /* Hydrostatic equilibrium... */
3999 hydrostatic(ctl, atm);
4000
4001 /* CGA or EGA forward model... */
4002 if (ctl->formod == 0 || ctl->formod == 1) {
4003 for (int ir = 0; ir < obs->nr; ir++) {
4004 const int status = formod_pencil(ctl, tbl, atm, obs, ir, los_scratch);
4005 if (status != FORMOD_STATUS_OK)
4006 return status;
4007 }
4008 }
4009
4010 /* Call RFM... */
4011 else if (ctl->formod == 2)
4012 formod_rfm(ctl, tbl, atm, obs);
4013
4014 /* Apply field-of-view convolution... */
4015 const int fov_status = formod_fov(ctl, obs, obs_scratch);
4016 if (fov_status != FORMOD_STATUS_OK)
4017 return fov_status;
4018
4019 /* Convert radiance to brightness temperature... */
4020 if (ctl->write_bbt)
4021 for (int id = 0; id < ctl->nd; id++)
4022 for (int ir = 0; ir < obs->nr; ir++)
4023 obs->rad[id][ir] = BRIGHT(obs->rad[id][ir], ctl->nu[id]);
4024
4025 /* Apply observation mask... */
4026 for (int id = 0; id < ctl->nd; id++)
4027 for (int ir = 0; ir < obs->nr; ir++)
4028 if (obs->mask[id][ir])
4029 obs->rad[id][ir] = NAN;
4030
4031 return FORMOD_STATUS_OK;
4032}
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:4362
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:4178
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:4116
void hydrostatic(const ctl_t *ctl, atm_t *atm)
Adjust pressure profile using the hydrostatic equation.
Definition: jurassic.c:4601
#define BRIGHT(rad, nu)
Compute brightness temperature from radiance.
Definition: jurassic.h:532
@ FORMOD_STATUS_OK
Definition: jurassic.h:159
double nu[ND]
Centroid wavenumber of each channel [cm^-1].
Definition: jurassic.h:1616
int formod
Forward model (0=CGA, 1=EGA, 2=RFM).
Definition: jurassic.h:1742
int write_bbt
Use brightness temperature instead of radiance (0=no, 1=yes).
Definition: jurassic.h:1736
int mask[ND][NR]
Internal observation mask used by the forward model.
Definition: jurassic.h:1866
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 4036 of file jurassic.c.

4044 {
4045
4046 if (nbatch <= 0)
4047 return;
4048
4049 if (los_scratch == NULL || obs_scratch == NULL)
4050 ERRMSG("formod_batch requires scratch arrays for los and obs_scratch!");
4051
4052 /* The RFM interface uses fixed temporary filenames and is therefore
4053 not thread-safe... */
4054 if (ctl->formod == 2) {
4055 for (int ib = 0; ib < nbatch; ib++) {
4056 const int ib_status = formod(ctl, tbl, &atm[ib], &obs[ib],
4057 &los_scratch[ib], &obs_scratch[ib]);
4058 if (status)
4059 status[ib] = ib_status;
4060 else if (ib_status != FORMOD_STATUS_OK)
4061 ERRMSG("Forward model failed with status code %d!", ib_status);
4062 }
4063 return;
4064 }
4065
4066 /* Run independent cases in parallel... */
4067#pragma omp parallel for schedule(static) default(none) shared(ctl,tbl,atm,obs,nbatch,status,los_scratch,obs_scratch)
4068 for (int ib = 0; ib < nbatch; ib++) {
4069 const int ib_status = formod(ctl, tbl, &atm[ib], &obs[ib],
4070 &los_scratch[ib], &obs_scratch[ib]);
4071 if (status)
4072 status[ib] = ib_status;
4073 else if (ib_status != FORMOD_STATUS_OK)
4074 ERRMSG("Forward model failed with status code %d!", ib_status);
4075 }
4076}
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:3985
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 4080 of file jurassic.c.

4084 {
4085
4086 /* Extinction... */
4087 for (int id = 0; id < ctl->nd; id++)
4088 beta[id] = los->k[ip][id];
4089
4090 /* CO2 continuum... */
4091 if (ctl->ctm_co2 && ctl->ig_co2 >= 0)
4092 for (int id = 0; id < ctl->nd; id++)
4093 beta[id] += ctmco2(ctl->nu[id], los->p[ip], los->t[ip],
4094 los->u[ip][ctl->ig_co2]) / los->ds[ip];
4095
4096 /* H2O continuum... */
4097 if (ctl->ctm_h2o && ctl->ig_h2o >= 0)
4098 for (int id = 0; id < ctl->nd; id++)
4099 beta[id] += ctmh2o(ctl->nu[id], los->p[ip], los->t[ip],
4100 los->q[ip][ctl->ig_h2o], los->u[ip][ctl->ig_h2o])
4101 / los->ds[ip];
4102
4103 /* N2 continuum... */
4104 if (ctl->ctm_n2)
4105 for (int id = 0; id < ctl->nd; id++)
4106 beta[id] += ctmn2(ctl->nu[id], los->p[ip], los->t[ip]);
4107
4108 /* O2 continuum... */
4109 if (ctl->ctm_o2)
4110 for (int id = 0; id < ctl->nd; id++)
4111 beta[id] += ctmo2(ctl->nu[id], los->p[ip], los->t[ip]);
4112}
double ctmo2(const double nu, const double p, const double t)
Compute O₂ collision-induced absorption coefficient.
Definition: jurassic.c:3772
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:2533
double ctmco2(const double nu, const double p, const double t, const double u)
Compute carbon dioxide continuum optical depth.
Definition: jurassic.c:1670
double ctmn2(const double nu, const double p, const double t)
Compute N₂ collision-induced absorption coefficient.
Definition: jurassic.c:3703
int ctm_co2
Compute CO2 continuum (0=no, 1=yes).
Definition: jurassic.h:1664
int ctm_n2
Compute N2 continuum (0=no, 1=yes).
Definition: jurassic.h:1670
int ctm_h2o
Compute H2O continuum (0=no, 1=yes).
Definition: jurassic.h:1667
int ctm_o2
Compute O2 continuum (0=no, 1=yes).
Definition: jurassic.h:1673
int ig_h2o
Emitter index of H2O.
Definition: jurassic.h:1604
double q[NLOS][NG]
Volume mixing ratio [ppv].
Definition: jurassic.h:1783
double ds[NLOS]
Segment length [km].
Definition: jurassic.h:1795
double u[NLOS][NG]
Column density [molecules/cm^2].
Definition: jurassic.h:1798
double k[NLOS][ND]
Extinction [km^-1].
Definition: jurassic.h:1786
double t[NLOS]
Temperature [K].
Definition: jurassic.h:1780
double p[NLOS]
Pressure [hPa].
Definition: jurassic.h:1777
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 4116 of file jurassic.c.

4119 {
4120
4121 int rays[2 * NFOV + 1];
4122 double z[2 * NFOV + 1];
4123
4124 /* Do not take into account FOV... */
4125 if (ctl->fov[0] == '-')
4126 return FORMOD_STATUS_OK;
4127
4128 /* Copy observation data... */
4129 copy_obs(ctl, obs_scratch, obs, 0);
4130
4131 /* Loop over ray paths... */
4132 for (int ir = 0; ir < obs->nr; ir++) {
4133
4134 /* Collect neighbouring ray paths for the same time step... */
4135 int nz = 0;
4136 for (int ir2 = MAX(ir - NFOV, 0);
4137 ir2 < MIN(ir + 1 + NFOV, obs->nr); ir2++)
4138 if (obs->time[ir2] == obs->time[ir]) {
4139 rays[nz] = ir2;
4140 z[nz] = obs_scratch->vpz[ir2];
4141 nz++;
4142 }
4143 if (nz < 2)
4145
4146 /* Convolute profiles with FOV... */
4147 double wsum = 0;
4148 for (int id = 0; id < ctl->nd; id++) {
4149 obs->rad[id][ir] = 0;
4150 obs->tau[id][ir] = 0;
4151 }
4152 for (int i = 0; i < ctl->fov_n; i++) {
4153 const double zfov = obs->vpz[ir] + ctl->fov_dz[i];
4154 const int idx = locate_irr(z, nz, zfov);
4155 const int ir0 = rays[idx];
4156 const int ir1 = rays[idx + 1];
4157 for (int id = 0; id < ctl->nd; id++) {
4158 obs->rad[id][ir] += ctl->fov_w[i]
4159 * LIN(z[idx], obs_scratch->rad[id][ir0],
4160 z[idx + 1], obs_scratch->rad[id][ir1], zfov);
4161 obs->tau[id][ir] += ctl->fov_w[i]
4162 * LIN(z[idx], obs_scratch->tau[id][ir0],
4163 z[idx + 1], obs_scratch->tau[id][ir1], zfov);
4164 }
4165 wsum += ctl->fov_w[i];
4166 }
4167 for (int id = 0; id < ctl->nd; id++) {
4168 obs->rad[id][ir] /= wsum;
4169 obs->tau[id][ir] /= wsum;
4170 }
4171 }
4172
4173 return FORMOD_STATUS_OK;
4174}
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:3884
@ FORMOD_STATUS_FOV_DATA_MISSING
Definition: jurassic.h:161
#define NFOV
Number of ray paths used for FOV calculations.
Definition: jurassic.h:360
char fov[LEN]
Field-of-view data file.
Definition: jurassic.h:1685
int fov_n
Field-of-view number of data points.
Definition: jurassic.h:1694
double fov_dz[NSHAPE]
Field-of-view vertical distance [km].
Definition: jurassic.h:1688
double fov_w[NSHAPE]
Field-of-view weighting factor.
Definition: jurassic.h:1691
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 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 4178 of file jurassic.c.

4184 {
4185
4186 double rad[ND], tau[ND], tau_path[ND][NG];
4187
4188 /* Reset scratch LOS data (raytrace relies on zero-initialized fields)... */
4189 memset(los, 0, sizeof(*los));
4190
4191 /* Initialize... */
4192 for (int id = 0; id < ctl->nd; id++) {
4193 rad[id] = 0;
4194 tau[id] = 1;
4195 for (int ig = 0; ig < ctl->ng; ig++)
4196 tau_path[id][ig] = 1;
4197 }
4198
4199 /* Raytracing... */
4200 {
4201 const int status = raytrace(ctl, atm, obs, los, ir);
4202 if (status != FORMOD_STATUS_OK)
4203 return status;
4204 }
4205
4206 /* Loop over LOS points... */
4207 for (int ip = 0; ip < los->np; ip++) {
4208
4209 /* Get trace gas transmittance... */
4210 double tau_gas[ND];
4211 if (ctl->formod == 0)
4212 intpol_tbl_cga(ctl, tbl, los, ip, tau_path, tau_gas);
4213 else
4214 intpol_tbl_ega(ctl, tbl, los, ip, tau_path, tau_gas);
4215
4216 /* Get continuum absorption... */
4217 double beta_ctm[ND];
4218 formod_continua(ctl, los, ip, beta_ctm);
4219
4220 /* Compute Planck function... */
4221 formod_srcfunc(ctl, tbl, los->t[ip], los->src[ip]);
4222
4223 /* Loop over channels... */
4224 for (int id = 0; id < ctl->nd; id++)
4225 if (tau_gas[id] >= 0) {
4226
4227 /* Get segment emissivity. An exactly zero transmittance represents
4228 a fully opaque segment and must contribute with emissivity one. */
4229 los->eps[ip][id] = 1 - tau_gas[id] * exp(-beta_ctm[id] * los->ds[ip]);
4230
4231 /* Compute radiance... */
4232 rad[id] += los->src[ip][id] * los->eps[ip][id] * tau[id];
4233
4234 /* Compute path transmittance... */
4235 tau[id] *= (1 - los->eps[ip][id]);
4236 }
4237 }
4238
4239 /* Check whether LOS hit the ground... */
4240 if (ctl->sftype >= 1 && los->sft > 0) {
4241
4242 /* Add surface emissions... */
4243 double src_sf[ND];
4244 formod_srcfunc(ctl, tbl, los->sft, src_sf);
4245 for (int id = 0; id < ctl->nd; id++)
4246 rad[id] += los->sfeps[id] * src_sf[id] * tau[id];
4247
4248 /* Check reflectivity... */
4249 int refl = 0;
4250 if (ctl->sftype >= 2)
4251 for (int id = 0; id < ctl->nd; id++)
4252 if (los->sfeps[id] < 1) {
4253 refl = 1;
4254 break;
4255 }
4256
4257 /* Calculate reflection... */
4258 if (refl) {
4259
4260 /* Initialize... */
4261 double tau_refl[ND];
4262 for (int id = 0; id < ctl->nd; id++)
4263 tau_refl[id] = 1;
4264
4265 /* Add down-welling radiance... */
4266 for (int ip = los->np - 1; ip >= 0; ip--)
4267 for (int id = 0; id < ctl->nd; id++) {
4268 rad[id] += los->src[ip][id] * los->eps[ip][id] * tau_refl[id]
4269 * tau[id] * (1 - los->sfeps[id]);
4270 tau_refl[id] *= (1 - los->eps[ip][id]);
4271 }
4272
4273 /* Add solar term... */
4274 if (ctl->sftype >= 3) {
4275
4276 /* Get cosine of solar zenith angle... */
4277 double cos_sza_val;
4278 if (ctl->sfsza < 0)
4279 cos_sza_val = cos_sza(obs->time[ir],
4280 los->lon[los->np - 1], los->lat[los->np - 1]);
4281 else
4282 cos_sza_val = cos(DEG2RAD(ctl->sfsza));
4283
4284 /* Check validity (avoid division by zero)... */
4285 if (cos_sza_val > 1e-6) {
4286
4287 /* Compute incidence direction cosine... */
4288 double x0[3], x1[3];
4289 geo2cart(los->z[los->np - 1], los->lon[los->np - 1],
4290 los->lat[los->np - 1], x0);
4291 geo2cart(los->z[0], los->lon[0], los->lat[0], x1);
4292 for (int i = 0; i < 3; i++)
4293 x1[i] -= x0[i];
4294 const double cosa = DOTP(x0, x1) / NORM(x0) / NORM(x1);
4295
4296 /* Ratio of incident direction to solar zenith direction... */
4297 const double rcos = cosa / cos_sza_val;
4298
4299 /* Add solar radiance contribution... */
4300 for (int id = 0; id < ctl->nd; id++)
4301 rad[id] += 6.764e-5 / (2. * M_PI) * PLANCK(TSUN, ctl->nu[id])
4302 * tau_refl[id] * (1 - los->sfeps[id]) * tau[id] * rcos;
4303 }
4304 }
4305 }
4306 }
4307
4308 /* Copy results... */
4309 for (int id = 0; id < ctl->nd; id++) {
4310 obs->rad[id][ir] = rad[id];
4311 obs->tau[id][ir] = tau[id];
4312 }
4313
4314 return FORMOD_STATUS_OK;
4315}
double cos_sza(const double sec, const double lon, const double lat)
Calculates the cosine of the solar zenith angle.
Definition: jurassic.c:1598
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:5715
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:4865
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:4080
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:4772
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:4566
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:4583
#define DOTP(a, b)
Compute dot product of two 3D vectors.
Definition: jurassic.h:642
#define ND
Maximum number of radiance channels.
Definition: jurassic.h:355
#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:1129
double sfsza
Solar zenith angle at the surface [deg] (-999=auto).
Definition: jurassic.h:1640
int sftype
Surface treatment (0=none, 1=emissions, 2=downward, 3=solar).
Definition: jurassic.h:1637
double z[NLOS]
Altitude [km].
Definition: jurassic.h:1768
double eps[NLOS][ND]
Segment emissivity.
Definition: jurassic.h:1810
double sft
Surface temperature [K].
Definition: jurassic.h:1789
double lon[NLOS]
Longitude [deg].
Definition: jurassic.h:1771
int np
Number of LOS points.
Definition: jurassic.h:1765
double lat[NLOS]
Latitude [deg].
Definition: jurassic.h:1774
double src[NLOS][ND]
Segment source function [W/(m^2 sr cm^-1)].
Definition: jurassic.h:1813
double sfeps[ND]
Surface emissivity.
Definition: jurassic.h:1792
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 4362 of file jurassic.c.

4366 {
4367
4368 los_t *los;
4369
4370 char cmd[2 * LEN], filename[LEN], rfmflg[LEN] = { "RAD TRA MIX LIN SFC" };
4371
4372 double lower[ND], upper[ND], nu0, nu1, obsz = -999, *nurfm, *spec, tsurf,
4373 xd[3], xo[3], xv[3], z[NR], zmin, zmax;
4374
4375 int nadir = 0, npts, order[ND], zenith = 0;
4376
4377 /* Allocate... */
4378 ALLOC(los, los_t, 1);
4379 ALLOC(nurfm, double,
4380 RFMNPTS);
4381 ALLOC(spec, double,
4382 RFMNPTS);
4383
4384 /* Check observer positions... */
4385 for (int ir = 1; ir < obs->nr; ir++)
4386 if (obs->obsz[ir] != obs->obsz[0]
4387 || obs->obslon[ir] != obs->obslon[0]
4388 || obs->obslat[ir] != obs->obslat[0])
4389 ERRMSG("RFM interface requires identical observer positions!");
4390
4391 /* Check extinction data... */
4392 for (int iw = 0; iw < ctl->nw; iw++)
4393 for (int ip = 0; ip < atm->np; ip++)
4394 if (atm->k[iw][ip] != 0)
4395 ERRMSG("RFM interface cannot handle extinction data!");
4396
4397 /* Get altitude range of atmospheric data... */
4398 gsl_stats_minmax(&zmin, &zmax, atm->z, 1, (size_t) atm->np);
4399
4400 /* Observer within atmosphere? */
4401 if (obs->obsz[0] >= zmin && obs->obsz[0] <= zmax) {
4402 obsz = obs->obsz[0];
4403 strcat(rfmflg, " OBS");
4404 }
4405
4406 /* Determine tangent altitude or air mass factor... */
4407 for (int ir = 0; ir < obs->nr; ir++) {
4408
4409 /* Raytracing... */
4410 if (raytrace(ctl, atm, obs, los, ir) != FORMOD_STATUS_OK)
4411 ERRMSG("Ray tracing failed!");
4412
4413 /* Nadir or zenith? (air mass factor / secant of zenith angle) */
4414 if (obs->tpz[ir] <= zmin) {
4415
4416 /* Nadir: path intersects the surface. */
4417 geo2cart(obs->obsz[ir], obs->obslon[ir], obs->obslat[ir], xo);
4418 geo2cart(obs->vpz[ir], obs->vplon[ir], obs->vplat[ir], xv);
4419 for (int i = 0; i < 3; i++)
4420 xd[i] = xo[i] - xv[i];
4421 z[ir] = NORM(xo) * NORM(xd) / DOTP(xo, xd);
4422 nadir++;
4423
4424 } else if (obs->tpz[ir] >= zmax - 1e-3 && obs->vpz[ir] > obs->obsz[ir]) {
4425
4426 /* Zenith: upward-looking path leaves the atmosphere at the top boundary. */
4427 geo2cart(obs->obsz[ir], obs->obslon[ir], obs->obslat[ir], xo);
4428 geo2cart(obs->vpz[ir], obs->vplon[ir], obs->vplat[ir], xv);
4429 for (int i = 0; i < 3; i++)
4430 xd[i] = xv[i] - xo[i];
4431 z[ir] = NORM(xo) * NORM(xd) / DOTP(xo, xd);
4432 zenith++;
4433
4434 } else
4435 /* Limb: use tangent altitude. */
4436 z[ir] = obs->tpz[ir];
4437 }
4438 if ((nadir > 0 && nadir < obs->nr)
4439 || (zenith > 0 && zenith < obs->nr)
4440 || (nadir > 0 && zenith > 0))
4441 ERRMSG("Limb, nadir, and zenith not simultaneously possible!");
4442
4443 /* Viewing geometry... */
4444 if (nadir)
4445 strcat(rfmflg, " NAD");
4446 if (zenith)
4447 strcat(rfmflg, " ZEN");
4448
4449 /* Get surface temperature... */
4450 tsurf = atm->t[gsl_stats_min_index(atm->z, 1, (size_t) atm->np)];
4451
4452 /* Refraction? */
4453 if (!nadir && !zenith && !ctl->refrac)
4454 strcat(rfmflg, " GEO");
4455
4456 /* Continua? */
4457 if (ctl->ctm_co2 || ctl->ctm_h2o || ctl->ctm_n2 || ctl->ctm_o2)
4458 strcat(rfmflg, " CTM");
4459
4460 /* Write atmospheric data file... */
4461 write_atm_rfm("rfm.atm", ctl, atm);
4462
4463 /* Check filter functions and initialize channel order... */
4464 for (int id = 0; id < ctl->nd; id++) {
4465 const int n = tbl->filt_n[id];
4466 if (n < 2 || n > NSHAPE)
4467 ERRMSG("Missing or invalid filter function in lookup table!");
4468 for (int i = 1; i < n; i++)
4469 if (tbl->filt_nu[id][i] <= tbl->filt_nu[id][i - 1])
4470 ERRMSG("Filter wavenumbers must be strictly increasing!");
4471 lower[id] = tbl->filt_nu[id][0];
4472 upper[id] = tbl->filt_nu[id][n - 1];
4473 order[id] = id;
4474 }
4475
4476 /* Sort channels by lower filter bound... */
4477 for (int i = 1; i < ctl->nd; i++) {
4478 const int id = order[i];
4479 int j = i;
4480 while (j > 0 && lower[order[j - 1]] > lower[id]) {
4481 order[j] = order[j - 1];
4482 j--;
4483 }
4484 order[j] = id;
4485 }
4486
4487 /* Loop over overlapping spectral blocks... */
4488 for (int ib = 0; ib < ctl->nd;) {
4489 int ie = ib + 1;
4490 nu0 = lower[order[ib]];
4491 nu1 = upper[order[ib]];
4492 while (ie < ctl->nd && lower[order[ie]] <= nu1) {
4493 nu1 = MAX(nu1, upper[order[ie]]);
4494 ie++;
4495 }
4496
4497 /* Create RFM driver file... */
4498 FILE *out;
4499 if (!(out = fopen("rfm.drv", "w")))
4500 ERRMSG("Cannot create file!");
4501 fprintf(out, "*HDR\nRFM call by JURASSIC.\n");
4502 fprintf(out, "*FLG\n%s\n", rfmflg);
4503 fprintf(out, "*SPC\n%.4f %.4f 0.0005\n", nu0, nu1);
4504 fprintf(out, "*GAS\n");
4505 for (int ig = 0; ig < ctl->ng; ig++)
4506 fprintf(out, "%s\n", ctl->emitter[ig]);
4507 fprintf(out, "*ATM\nrfm.atm\n");
4508 fprintf(out, "*TAN\n");
4509 for (int ir = 0; ir < obs->nr; ir++)
4510 fprintf(out, "%g\n", z[ir]);
4511 fprintf(out, "*SFC\n%g 1.0\n", tsurf);
4512 if (obsz >= 0)
4513 fprintf(out, "*OBS\n%g\n", obsz);
4514 fprintf(out, "*HIT\n%s\n", ctl->rfmhit);
4515 fprintf(out, "*XSC\n");
4516 for (int ig = 0; ig < ctl->ng; ig++)
4517 if (ctl->rfmxsc[ig][0] != '-')
4518 fprintf(out, "%s\n", ctl->rfmxsc[ig]);
4519 fprintf(out, "*END\n");
4520 fclose(out);
4521
4522 /* Remove temporary files... */
4523 if (system("rm -f rfm.runlog rad_*.asc tra_*.asc"))
4524 ERRMSG("Cannot remove temporary files!");
4525
4526 /* Call RFM... */
4527 sprintf(cmd, "echo | %s", ctl->rfmbin);
4528 if (system(cmd))
4529 ERRMSG("Error while calling RFM!");
4530
4531 /* Read and convolute each spectrum once... */
4532 for (int ir = 0; ir < obs->nr; ir++) {
4533 find_rfm_file(filename, "rad", z[ir]);
4534 read_rfm_spec(filename, nurfm, spec, &npts);
4535 for (int i = ib; i < ie; i++) {
4536 const int id = order[i];
4537 obs->rad[id][ir] = convolve_rfm(nurfm, spec, npts,
4538 tbl->filt_nu[id], tbl->filt_f[id],
4539 tbl->filt_n[id]) * 1e-5;
4540 }
4541
4542 find_rfm_file(filename, "tra", z[ir]);
4543 read_rfm_spec(filename, nurfm, spec, &npts);
4544 for (int i = ib; i < ie; i++) {
4545 const int id = order[i];
4546 obs->tau[id][ir] = convolve_rfm(nurfm, spec, npts,
4547 tbl->filt_nu[id], tbl->filt_f[id],
4548 tbl->filt_n[id]);
4549 }
4550 }
4551 ib = ie;
4552 }
4553
4554 /* Remove temporary files... */
4555 if (system("rm -f rfm.drv rfm.atm rfm.runlog rad_*.asc tra_*.asc"))
4556 ERRMSG("Error while removing temporary files!");
4557
4558 /* Free... */
4559 free(los);
4560 free(nurfm);
4561 free(spec);
4562}
void read_rfm_spec(const char *filename, double *nu, double *rad, int *npts)
Read a Reference Forward Model (RFM) ASCII spectrum.
Definition: jurassic.c:6966
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:8453
#define RFMNPTS
Maximum number of RFM spectral grid points.
Definition: jurassic.h:427
#define NSHAPE
Maximum number of shape function grid points.
Definition: jurassic.h:412
#define NR
Maximum number of ray paths.
Definition: jurassic.h:402
char rfmhit[LEN]
HITRAN file for RFM.
Definition: jurassic.h:1748
char rfmbin[LEN]
Path to RFM binary.
Definition: jurassic.h:1745
char rfmxsc[NG][LEN]
Emitter cross-section files for RFM.
Definition: jurassic.h:1751
int refrac
Take into account refractivity (0=no, 1=yes).
Definition: jurassic.h:1676
Line-of-sight data.
Definition: jurassic.h:1762
int filt_n[ND]
Filter function number of spectral grid points.
Definition: jurassic.h:2039
double filt_f[ND][NSHAPE]
Filter function values.
Definition: jurassic.h:2045
double filt_nu[ND][NSHAPE]
Filter function spectral grid points [cm^-1].
Definition: jurassic.h:2042
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 4566 of file jurassic.c.

4570 {
4571
4572 /* Determine index in temperature array... */
4573 const int it = locate_reg(tbl->st, TBLNS, t);
4574
4575 /* Interpolate Planck function value... */
4576 for (int id = 0; id < ctl->nd; id++)
4577 src[id] = LIN(tbl->st[it], tbl->sr[it][id],
4578 tbl->st[it + 1], tbl->sr[it + 1][id], t);
4579}
#define TBLNS
Maximum number of source function temperature levels.
Definition: jurassic.h:437
double sr[TBLNS][ND]
Source function radiance [W/(m^2 sr cm^-1)].
Definition: jurassic.h:2051
double st[TBLNS]
Source function temperature [K].
Definition: jurassic.h:2048
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 4583 of file jurassic.c.

4587 {
4588
4589 const double radius = z + RE;
4590 const double latrad = lat / 180. * M_PI;
4591 const double lonrad = lon / 180. * M_PI;
4592 const double coslat = cos(latrad);
4593
4594 x[0] = radius * coslat * cos(lonrad);
4595 x[1] = radius * coslat * sin(lonrad);
4596 x[2] = radius * sin(latrad);
4597}

◆ 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 4601 of file jurassic.c.

4603 {
4604
4605 const double mmair = 28.96456e-3, mmh2o = 18.0153e-3;
4606
4607 const int ipts = 20;
4608
4609 double dzmin = 1e99, e = 0;
4610
4611 int ipref = 0;
4612
4613 /* Check reference height... */
4614 if (ctl->hydz < 0)
4615 return;
4616
4617 /* Find air parcel next to reference height... */
4618 for (int ip = 0; ip < atm->np; ip++)
4619 if (fabs(atm->z[ip] - ctl->hydz) < dzmin) {
4620 dzmin = fabs(atm->z[ip] - ctl->hydz);
4621 ipref = ip;
4622 }
4623
4624 /* Upper part of profile... */
4625 for (int ip = ipref + 1; ip < atm->np; ip++) {
4626 double mean = 0;
4627 for (int i = 0; i < ipts; i++) {
4628 if (ctl->ig_h2o >= 0)
4629 e = LIN(0.0, atm->q[ctl->ig_h2o][ip - 1],
4630 ipts - 1.0, atm->q[ctl->ig_h2o][ip], (double) i);
4631 mean += (e * mmh2o + (1 - e) * mmair)
4632 * G0 / RI
4633 / LIN(0.0, atm->t[ip - 1], ipts - 1.0, atm->t[ip], (double) i) / ipts;
4634 }
4635
4636 /* Compute p(z,T)... */
4637 atm->p[ip] =
4638 exp(log(atm->p[ip - 1]) - mean * 1000 * (atm->z[ip] - atm->z[ip - 1]));
4639 }
4640
4641 /* Lower part of profile... */
4642 for (int ip = ipref - 1; ip >= 0; ip--) {
4643 double mean = 0;
4644 for (int i = 0; i < ipts; i++) {
4645 if (ctl->ig_h2o >= 0)
4646 e = LIN(0.0, atm->q[ctl->ig_h2o][ip + 1],
4647 ipts - 1.0, atm->q[ctl->ig_h2o][ip], (double) i);
4648 mean += (e * mmh2o + (1 - e) * mmair)
4649 * G0 / RI
4650 / LIN(0.0, atm->t[ip + 1], ipts - 1.0, atm->t[ip], (double) i) / ipts;
4651 }
4652
4653 /* Compute p(z,T)... */
4654 atm->p[ip] =
4655 exp(log(atm->p[ip + 1]) - mean * 1000 * (atm->z[ip] - atm->z[ip + 1]));
4656 }
4657}
#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:1661

◆ 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 4661 of file jurassic.c.

4664 {
4665
4666 if (idx == IDXP)
4667 sprintf(quantity, "PRESSURE");
4668
4669 if (idx == IDXT)
4670 sprintf(quantity, "TEMPERATURE");
4671
4672 for (int ig = 0; ig < ctl->ng; ig++)
4673 if (idx == IDXQ(ig))
4674 sprintf(quantity, "%s", ctl->emitter[ig]);
4675
4676 for (int iw = 0; iw < ctl->nw; iw++)
4677 if (idx == IDXK(iw))
4678 sprintf(quantity, "EXTINCT_WINDOW_%d", iw);
4679
4680 if (idx == IDXCLZ)
4681 sprintf(quantity, "CLOUD_HEIGHT");
4682
4683 if (idx == IDXCLDZ)
4684 sprintf(quantity, "CLOUD_DEPTH");
4685
4686 for (int icl = 0; icl < ctl->ncl; icl++)
4687 if (idx == IDXCLK(icl))
4688 sprintf(quantity, "CLOUD_EXTINCT_%.4f", ctl->clnu[icl]);
4689
4690 if (idx == IDXSFT)
4691 sprintf(quantity, "SURFACE_TEMPERATURE");
4692
4693 for (int isf = 0; isf < ctl->nsf; isf++)
4694 if (idx == IDXSFEPS(isf))
4695 sprintf(quantity, "SURFACE_EMISSIVITY_%.4f", ctl->sfnu[isf]);
4696}
double sfnu[NSF]
Surface layer wavenumber [cm^-1].
Definition: jurassic.h:1634
double clnu[NCL]
Cloud layer wavenumber [cm^-1].
Definition: jurassic.h:1628

◆ 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 4700 of file jurassic.c.

4702 {
4703
4704 /* Write info... */
4705 LOG(1, "Initialize source function table...");
4706 LOG(2, "Number of data points: %d", TBLNS);
4707
4708 /* Loop over channels... */
4709 for (int id = 0; id < ctl->nd; id++) {
4710
4711 /* Get minimum grid spacing... */
4712 double dnu = 1.0;
4713 for (int i = 1; i < tbl->filt_n[id]; i++)
4714 dnu = MIN(dnu, tbl->filt_nu[id][i] - tbl->filt_nu[id][i - 1]);
4715
4716 /* Compute source function table... */
4717#pragma omp parallel for default(none) shared(ctl,tbl,id,dnu)
4718 for (int it = 0; it < TBLNS; it++) {
4719
4720 /* Set temperature... */
4721 tbl->st[it] = LIN(0.0, TMIN, TBLNS - 1.0, TMAX, (double) it);
4722
4723 /* Integrate Planck function... */
4724 double fsum = tbl->sr[it][id] = 0;
4725 for (double fnu = tbl->filt_nu[id][0];
4726 fnu <= tbl->filt_nu[id][tbl->filt_n[id] - 1]; fnu += dnu) {
4727 const int i = locate_irr(tbl->filt_nu[id], tbl->filt_n[id], fnu);
4728 const double ff = LIN(tbl->filt_nu[id][i], tbl->filt_f[id][i],
4729 tbl->filt_nu[id][i + 1], tbl->filt_f[id][i + 1],
4730 fnu);
4731 fsum += ff;
4732 tbl->sr[it][id] += ff * PLANCK(tbl->st[it], fnu);
4733 }
4734 tbl->sr[it][id] /= fsum;
4735 }
4736
4737 /* Write info... */
4738 LOG(2,
4739 "channel= %.4f cm^-1 | T= %g ... %g K | B= %g ... %g W/(m^2 sr cm^-1)",
4740 ctl->nu[id], tbl->st[0], tbl->st[TBLNS - 1], tbl->sr[0][id],
4741 tbl->sr[TBLNS - 1][id]);
4742 }
4743}
#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 4747 of file jurassic.c.

4754 {
4755
4756 /* Get array index... */
4757 const int ip = locate_irr(atm->z, atm->np, z);
4758
4759 /* Interpolate... */
4760 *p = LOGY(atm->z[ip], atm->p[ip], atm->z[ip + 1], atm->p[ip + 1], z);
4761 *t = LIN(atm->z[ip], atm->t[ip], atm->z[ip + 1], atm->t[ip + 1], z);
4762 for (int ig = 0; ig < ctl->ng; ig++)
4763 q[ig] =
4764 LIN(atm->z[ip], atm->q[ig][ip], atm->z[ip + 1], atm->q[ig][ip + 1], z);
4765 for (int iw = 0; iw < ctl->nw; iw++)
4766 k[iw] =
4767 LIN(atm->z[ip], atm->k[iw][ip], atm->z[ip + 1], atm->k[iw][ip + 1], z);
4768}
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 4772 of file jurassic.c.

4778 {
4779
4780 double eps, lnp[NG];
4781
4782 /* Precompute log-pressure... */
4783 for (int ig = 0; ig < ctl->ng; ig++)
4784 lnp[ig] = log(los->cgp[ip][ig]);
4785
4786 /* Loop over channels... */
4787 for (int id = 0; id < ctl->nd; id++) {
4788
4789 /* Initialize... */
4790 tau_seg[id] = 1;
4791
4792 /* Loop over emitters.... */
4793 for (int ig = 0; ig < ctl->ng; ig++) {
4794
4795 /* Check size of table (pressure) and column density... */
4796 if (tbl->np[id][ig] < 30 || los->cgu[ip][ig] <= 0)
4797 eps = 0;
4798
4799 /* Check transmittance... */
4800 else if (tau_path[id][ig] < 1e-9)
4801 eps = 1;
4802
4803 /* Interpolate... */
4804 else {
4805
4806 /* Determine pressure and temperature indices... */
4807 const int ipr =
4808 locate_irr(tbl->p[id][ig], tbl->np[id][ig], los->cgp[ip][ig]);
4809 const int it0 = locate_reg(tbl->t[id][ig][ipr], tbl->nt[id][ig][ipr],
4810 los->cgt[ip][ig]);
4811 const int it1 =
4812 locate_reg(tbl->t[id][ig][ipr + 1], tbl->nt[id][ig][ipr + 1],
4813 los->cgt[ip][ig]);
4814
4815 /* Check size of table (temperature and column density)... */
4816 if (tbl->nt[id][ig][ipr] < 2 || tbl->nt[id][ig][ipr + 1] < 2
4817 || tbl->nu[id][ig][ipr][it0] < 2
4818 || tbl->nu[id][ig][ipr][it0 + 1] < 2
4819 || tbl->nu[id][ig][ipr + 1][it1] < 2
4820 || tbl->nu[id][ig][ipr + 1][it1 + 1] < 2)
4821 eps = 0;
4822
4823 else {
4824
4825 /* Get emissivities of extended path... */
4826 const double logu = log(los->cgu[ip][ig]);
4827 double eps00 = intpol_tbl_eps(tbl, ig, id, ipr, it0, logu);
4828 double eps01 = intpol_tbl_eps(tbl, ig, id, ipr, it0 + 1, logu);
4829 double eps10 = intpol_tbl_eps(tbl, ig, id, ipr + 1, it1, logu);
4830 double eps11 = intpol_tbl_eps(tbl, ig, id, ipr + 1, it1 + 1, logu);
4831
4832 /* Interpolate with respect to temperature... */
4833 eps00 = LIN(tbl->t[id][ig][ipr][it0], eps00,
4834 tbl->t[id][ig][ipr][it0 + 1], eps01, los->cgt[ip][ig]);
4835 eps11 = LIN(tbl->t[id][ig][ipr + 1][it1], eps10,
4836 tbl->t[id][ig][ipr + 1][it1 + 1],
4837 eps11, los->cgt[ip][ig]);
4838
4839 /* Interpolate with respect to log-pressure... */
4840 eps00 = LIN(tbl->lnp[id][ig][ipr], eps00,
4841 tbl->lnp[id][ig][ipr + 1], eps11, lnp[ig]);
4842
4843 /* Check emissivity range... */
4844 eps00 = CLAMP(eps00, 0.0, 1.0);
4845
4846 /* Determine segment emissivity... */
4847 eps = 1 - (1 - eps00) / tau_path[id][ig];
4848
4849 /* Check emissivity range... */
4850 eps = CLAMP(eps, 0.0, 1.0);
4851 }
4852 }
4853
4854 /* Get transmittance of extended path... */
4855 tau_path[id][ig] *= (1 - eps);
4856
4857 /* Get segment transmittance... */
4858 tau_seg[id] *= (1 - eps);
4859 }
4860 }
4861}
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:4967
#define CLAMP(v, lo, hi)
Clamp a value to a specified range.
Definition: jurassic.h:554
double cgu[NLOS][NG]
Curtis-Godson column density [molecules/cm^2].
Definition: jurassic.h:1807
double cgt[NLOS][NG]
Curtis-Godson temperature [K].
Definition: jurassic.h:1804
double cgp[NLOS][NG]
Curtis-Godson pressure [hPa].
Definition: jurassic.h:1801
double p[ND][NG][TBLNP]
Pressure [hPa].
Definition: jurassic.h:2024
int nu[ND][NG][TBLNP][TBLNT]
Number of column densities.
Definition: jurassic.h:2021
int nt[ND][NG][TBLNP]
Number of temperatures.
Definition: jurassic.h:2018
double t[ND][NG][TBLNP][TBLNT]
Temperature [K].
Definition: jurassic.h:2030
double lnp[ND][NG][TBLNP]
Log-pressure [hPa].
Definition: jurassic.h:2027
int np[ND][NG]
Number of pressure levels.
Definition: jurassic.h:2015
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 FORMOD = 1.
Author
Lars Hoffmann

Definition at line 4865 of file jurassic.c.

4871 {
4872
4873 const double lnp = log(los->p[ip]);
4874
4875 double eps, u;
4876
4877 /* Loop over channels... */
4878 for (int id = 0; id < ctl->nd; id++) {
4879
4880 /* Initialize... */
4881 tau_seg[id] = 1;
4882
4883 /* Loop over emitters.... */
4884 for (int ig = 0; ig < ctl->ng; ig++) {
4885
4886 /* Check size of table (pressure) and column density... */
4887 if (tbl->np[id][ig] < 30 || los->cgu[ip][ig] <= 0)
4888 eps = 0;
4889
4890 /* Check transmittance... */
4891 else if (tau_path[id][ig] < 1e-9)
4892 eps = 1;
4893
4894 /* Interpolate... */
4895 else {
4896
4897 /* Determine pressure and temperature indices... */
4898 const int ipr =
4899 locate_irr(tbl->p[id][ig], tbl->np[id][ig], los->p[ip]);
4900 const int it0 =
4901 locate_reg(tbl->t[id][ig][ipr], tbl->nt[id][ig][ipr], los->t[ip]);
4902 const int it1 =
4903 locate_reg(tbl->t[id][ig][ipr + 1], tbl->nt[id][ig][ipr + 1],
4904 los->t[ip]);
4905
4906 /* Check size of table (temperature and column density)... */
4907 if (tbl->nt[id][ig][ipr] < 2 || tbl->nt[id][ig][ipr + 1] < 2
4908 || tbl->nu[id][ig][ipr][it0] < 2
4909 || tbl->nu[id][ig][ipr][it0 + 1] < 2
4910 || tbl->nu[id][ig][ipr + 1][it1] < 2
4911 || tbl->nu[id][ig][ipr + 1][it1 + 1] < 2)
4912 eps = 0;
4913
4914 else {
4915
4916 /* Get emissivities of extended path... */
4917 const double logeps = log(1.0 - tau_path[id][ig]);
4918
4919 u = intpol_tbl_u(tbl, ig, id, ipr, it0, logeps);
4920 double eps00
4921 = intpol_tbl_eps(tbl, ig, id, ipr, it0, log(u + los->u[ip][ig]));
4922
4923 u = intpol_tbl_u(tbl, ig, id, ipr, it0 + 1, logeps);
4924 double eps01 = intpol_tbl_eps(tbl, ig, id, ipr, it0 + 1,
4925 log(u + los->u[ip][ig]));
4926
4927 u = intpol_tbl_u(tbl, ig, id, ipr + 1, it1, logeps);
4928 double eps10 = intpol_tbl_eps(tbl, ig, id, ipr + 1, it1,
4929 log(u + los->u[ip][ig]));
4930
4931 u = intpol_tbl_u(tbl, ig, id, ipr + 1, it1 + 1, logeps);
4932 double eps11 = intpol_tbl_eps(tbl, ig, id, ipr + 1, it1 + 1,
4933 log(u + los->u[ip][ig]));
4934
4935 /* Interpolate with respect to temperature... */
4936 eps00 = LIN(tbl->t[id][ig][ipr][it0], eps00,
4937 tbl->t[id][ig][ipr][it0 + 1], eps01, los->t[ip]);
4938 eps11 = LIN(tbl->t[id][ig][ipr + 1][it1], eps10,
4939 tbl->t[id][ig][ipr + 1][it1 + 1], eps11, los->t[ip]);
4940
4941 /* Interpolate with respect to log-pressure... */
4942 eps00 = LIN(tbl->lnp[id][ig][ipr], eps00,
4943 tbl->lnp[id][ig][ipr + 1], eps11, lnp);
4944
4945 /* Check emissivity range... */
4946 eps00 = CLAMP(eps00, 0.0, 1.0);
4947
4948 /* Determine segment emissivity... */
4949 eps = 1 - (1 - eps00) / tau_path[id][ig];
4950
4951 /* Check emissivity range... */
4952 eps = CLAMP(eps, 0.0, 1.0);
4953 }
4954 }
4955
4956 /* Get transmittance of extended path... */
4957 tau_path[id][ig] *= (1 - eps);
4958
4959 /* Get segment transmittance... */
4960 tau_seg[id] *= (1 - eps);
4961 }
4962 }
4963}
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:5012
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 4967 of file jurassic.c.

4973 {
4974
4975 const int nu = tbl->nu[id][ig][ip][it];
4976 const float *logu_arr = tbl->logu[id][ig][ip][it];
4977 const float *logeps_arr = tbl->logeps[id][ig][ip][it];
4978
4979 /* Work in log-space and only convert back when needed... */
4980 const double logu_min = (double) logu_arr[0];
4981 const double logu_max = (double) logu_arr[nu - 1];
4982
4983 /* Lower boundary extrapolation (u < u_min)...
4984 eps ~ eps_min * u/u_min => log(eps) = logeps_min + log(u) - log(u_min) */
4985 if (logu < logu_min) {
4986 const double logeps_min = (double) logeps_arr[0];
4987 return exp(logeps_min + logu - logu_min);
4988 }
4989
4990 /* Upper boundary extrapolation (u > u_max)...
4991 * Assume eps(u) approaches 1 exponentially:
4992 * eps(u) = 1 - exp(a * u), a < 0
4993 * Continuity at (u_max, eps_max) gives
4994 * a = log(1 - eps_max) / u_max.
4995 * Use log1p/expm1 and u/u_max = exp(log(u) - log(u_max)) for stability.
4996 */
4997 if (logu > logu_max) {
4998 const double eps_max = exp((double) logeps_arr[nu - 1]);
4999 const double l1m_eps_max = log1p(-eps_max);
5000 const double r = exp(logu - logu_max);
5001 return -expm1(l1m_eps_max * r);
5002 }
5003
5004 /* Interpolation (log-log using precomputed logs)... */
5005 const int idx = locate_tbl(logu_arr, nu, logu);
5006 return exp(LIN(logu_arr[idx], logeps_arr[idx],
5007 logu_arr[idx + 1], logeps_arr[idx + 1], logu));
5008}
int locate_tbl(const float *xx, const int n, const double x)
Locate index for interpolation within emissivity table grids.
Definition: jurassic.c:5267
float * logu[ND][NG][TBLNP][TBLNT]
Logarithm of column density [molecules/cm^2].
Definition: jurassic.h:2033
float * logeps[ND][NG][TBLNP][TBLNT]
Logarithm of emissivity.
Definition: jurassic.h:2036
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 5012 of file jurassic.c.

5018 {
5019
5020 const int nu = tbl->nu[id][ig][ip][it];
5021 const float *logeps_arr = tbl->logeps[id][ig][ip][it];
5022 const float *logu_arr = tbl->logu[id][ig][ip][it];
5023
5024 /* Work in log-space and only convert back when needed.... */
5025 const double logeps_min = (double) logeps_arr[0];
5026 const double logeps_max = (double) logeps_arr[nu - 1];
5027
5028 /* Lower boundary extrapolation (eps < eps_min)...
5029 u ~ u_min * eps/eps_min => log(u) = log(u_min) + log(eps) - log(eps_min) */
5030 if (logeps < logeps_min) {
5031 const double logu_min = (double) logu_arr[0];
5032 return exp(logu_min + logeps - logeps_min);
5033 }
5034
5035 /* Upper boundary extrapolation (eps > eps_max):
5036 * Invert the exponential tail used for eps(u):
5037 * u = log(1 - eps) / a,
5038 * with a = log(1 - eps_max) / u_max.
5039 * Rewritten as
5040 * u = u_max * log(tau) / log(1 - eps_max)
5041 * for numerical stability (log1p).
5042 */
5043 if (logeps > logeps_max) {
5044 const double u_max = exp((double) logu_arr[nu - 1]);
5045 const double l1m_eps_max = log1p(-exp(logeps_max));
5046 const double logtau = log1p(-exp(logeps));
5047 return u_max * (logtau / l1m_eps_max);
5048 }
5049
5050 /* Interpolation (log-log using precomputed logs)... */
5051 const int idx = locate_tbl(logeps_arr, nu, logeps);
5052 return exp(LIN(logeps_arr[idx], logu_arr[idx],
5053 logeps_arr[idx + 1], logu_arr[idx + 1], logeps));
5054}
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 5058 of file jurassic.c.

5066 {
5067
5068 struct tm t0, *t1;
5069
5070 t0.tm_year = 100;
5071 t0.tm_mon = 0;
5072 t0.tm_mday = 1;
5073 t0.tm_hour = 0;
5074 t0.tm_min = 0;
5075 t0.tm_sec = 0;
5076
5077 const time_t jsec0 = (time_t) jsec + timegm(&t0);
5078 t1 = gmtime(&jsec0);
5079
5080 *year = t1->tm_year + 1900;
5081 *mon = t1->tm_mon + 1;
5082 *day = t1->tm_mday;
5083 *hour = t1->tm_hour;
5084 *min = t1->tm_min;
5085 *sec = t1->tm_sec;
5086 *remain = jsec - floor(jsec);
5087}

◆ 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 5091 of file jurassic.c.

5096 {
5097
5098 /* Get sizes... */
5099 const size_t m = k->size1;
5100 const size_t n = k->size2;
5101 const size_t nthreads = (size_t) MAX(1, omp_get_max_threads());
5102 const size_t batch_size = n < nthreads ? n : nthreads;
5103
5104 /* Allocate... */
5105 gsl_vector *x0 = gsl_vector_alloc(n);
5106 gsl_vector *yy0 = gsl_vector_alloc(m);
5107 gsl_vector *x1 = gsl_vector_alloc(n);
5108 gsl_vector *yy1 = gsl_vector_alloc(m);
5109 int *iqa;
5110 ALLOC(iqa, int,
5111 N);
5112 double *h_batch;
5113 int *status;
5114 ALLOC(h_batch, double,
5115 batch_size);
5116 ALLOC(status, int,
5117 batch_size);
5118 los_t *los0, *los1;
5119 atm_t *atm1;
5120 obs_t *obs_scratch0, *obs1, *obs_scratch1;
5121 ALLOC(los0, los_t, 1);
5122 ALLOC(obs_scratch0, obs_t, 1);
5123 ALLOC(atm1, atm_t, batch_size);
5124 ALLOC(obs1, obs_t, batch_size);
5125 ALLOC(los1, los_t, batch_size);
5126 ALLOC(obs_scratch1, obs_t, batch_size);
5127
5128 /* Compute radiance for undisturbed atmospheric data... */
5129 if (formod(ctl, tbl, atm, obs, los0, obs_scratch0) != FORMOD_STATUS_OK)
5130 ERRMSG("Forward model failed!");
5131 free(los0);
5132 free(obs_scratch0);
5133
5134 /* Compose vectors... */
5135 atm2x(ctl, atm, x0, iqa, NULL);
5136 obs2y(ctl, obs, yy0, NULL, NULL);
5137
5138 /* Initialize kernel matrix... */
5139 gsl_matrix_set_zero(k);
5140
5141 /* Loop over state vector elements in batches... */
5142 for (size_t j0 = 0; j0 < n; j0 += batch_size) {
5143 const size_t nbatch = MIN(batch_size, n - j0);
5144
5145 /* Prepare disturbed states... */
5146 for (size_t jb = 0; jb < nbatch; jb++) {
5147 const size_t j = j0 + jb;
5148
5149 /* Set perturbation size... */
5150 double h;
5151 if (iqa[j] == IDXP)
5152 h = MAX(fabs(KERNEL_P_REL * gsl_vector_get(x0, j)),
5153 KERNEL_P_MIN);
5154 else if (iqa[j] == IDXT)
5155 h = KERNEL_T_ABS;
5156 else if (iqa[j] >= IDXQ(0) && iqa[j] < IDXQ(ctl->ng))
5157 h = MAX(fabs(KERNEL_Q_REL * gsl_vector_get(x0, j)),
5158 KERNEL_Q_MIN);
5159 else if (iqa[j] >= IDXK(0) && iqa[j] < IDXK(ctl->nw))
5160 h = KERNEL_K_ABS;
5161 else if (iqa[j] == IDXCLZ)
5162 h = KERNEL_CLZ_ABS;
5163 else if (iqa[j] == IDXCLDZ)
5164 h = KERNEL_CLDZ_ABS;
5165 else if (iqa[j] >= IDXCLK(0) && iqa[j] < IDXCLK(ctl->ncl))
5166 h = KERNEL_CLK_ABS;
5167 else if (iqa[j] == IDXSFT)
5168 h = KERNEL_SFT_ABS;
5169 else if (iqa[j] >= IDXSFEPS(0) && iqa[j] < IDXSFEPS(ctl->nsf))
5170 h = KERNEL_SFEPS_ABS;
5171 else
5172 ERRMSG("Cannot set perturbation size!");
5173
5174 /* Disturb state vector element... */
5175 gsl_vector_memcpy(x1, x0);
5176 gsl_vector_set(x1, j, gsl_vector_get(x1, j) + h);
5177 copy_atm(ctl, &atm1[jb], atm, 0);
5178 copy_obs(ctl, &obs1[jb], obs, 0);
5179 x2atm(ctl, x1, &atm1[jb]);
5180 h_batch[jb] = h;
5181 }
5182
5183 /* Compute radiance for disturbed atmospheric data... */
5184 formod_batch(ctl, tbl, atm1, obs1, (int) nbatch, status, los1,
5185 obs_scratch1);
5186
5187 /* Compose measurement vectors and derivatives... */
5188 for (size_t jb = 0; jb < nbatch; jb++) {
5189 const size_t j = j0 + jb;
5190 if (status[jb] != FORMOD_STATUS_OK)
5191 ERRMSG("Forward model failed!");
5192 obs2y(ctl, &obs1[jb], yy1, NULL, NULL);
5193
5194 /* Compute derivatives... */
5195 for (size_t i = 0; i < m; i++)
5196 gsl_matrix_set(k, i, j,
5197 (gsl_vector_get(yy1, i) - gsl_vector_get(yy0, i))
5198 / h_batch[jb]);
5199 }
5200 }
5201
5202 /* Free... */
5203 gsl_vector_free(x0);
5204 gsl_vector_free(yy0);
5205 gsl_vector_free(x1);
5206 gsl_vector_free(yy1);
5207 free(atm1);
5208 free(obs1);
5209 free(obs_scratch1);
5210 free(los1);
5211 free(status);
5212 free(h_batch);
5213 free(iqa);
5214}
void x2atm(const ctl_t *ctl, const gsl_vector *x, atm_t *atm)
Map retrieval state vector back to atmospheric structure.
Definition: jurassic.c:9651
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:4036
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:5364
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
#define KERNEL_T_ABS
Absolute temperature step [K].
Definition: jurassic.h:286
#define KERNEL_CLZ_ABS
Absolute cloud center altitude step [km].
Definition: jurassic.h:306
#define KERNEL_P_MIN
Minimum absolute pressure step [hPa].
Definition: jurassic.h:281
#define KERNEL_P_REL
Relative pressure step (fraction of pressure).
Definition: jurassic.h:276
#define KERNEL_SFT_ABS
Absolute surface temperature step [K].
Definition: jurassic.h:321
#define KERNEL_K_ABS
Absolute atmospheric extinction step [km^-1].
Definition: jurassic.h:301
#define KERNEL_Q_REL
Relative gas VMR step (fraction of VMR).
Definition: jurassic.h:291
#define KERNEL_CLK_ABS
Absolute cloud extinction step [km^-1].
Definition: jurassic.h:316
#define KERNEL_CLDZ_ABS
Absolute cloud width step [km].
Definition: jurassic.h:311
#define KERNEL_SFEPS_ABS
Absolute surface emissivity step (dimensionless).
Definition: jurassic.h:326
#define KERNEL_Q_MIN
Minimum absolute gas VMR step (dimensionless).
Definition: jurassic.h:296
Observation geometry and radiance data.
Definition: jurassic.h:1824
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 5218 of file jurassic.c.

5221 {
5222
5223 int ilo = 0;
5224 int ihi = n - 1;
5225 int i = (ihi + ilo) >> 1;
5226
5227 if (xx[i] < xx[i + 1])
5228 while (ihi > ilo + 1) {
5229 i = (ihi + ilo) >> 1;
5230 if (xx[i] > x)
5231 ihi = i;
5232 else
5233 ilo = i;
5234 } else
5235 while (ihi > ilo + 1) {
5236 i = (ihi + ilo) >> 1;
5237 if (xx[i] <= x)
5238 ihi = i;
5239 else
5240 ilo = i;
5241 }
5242
5243 return ilo;
5244}

◆ 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 5248 of file jurassic.c.

5251 {
5252
5253 /* Calculate index... */
5254 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
5255
5256 /* Check range... */
5257 if (i < 0)
5258 return 0;
5259 else if (i > n - 2)
5260 return n - 2;
5261 else
5262 return i;
5263}

◆ 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 5267 of file jurassic.c.

5270 {
5271
5272 int ilo = 0;
5273 int ihi = n - 1;
5274 int i = (ihi + ilo) >> 1;
5275
5276 while (ihi > ilo + 1) {
5277 i = (ihi + ilo) >> 1;
5278 if (xx[i] > x)
5279 ihi = i;
5280 else
5281 ilo = i;
5282 }
5283
5284 return ilo;
5285}

◆ 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 5289 of file jurassic.c.

5290 {
5291
5292 size_t diag = 1;
5293
5294 /* Get size... */
5295 const size_t n = a->size1;
5296
5297 /* Check if matrix is diagonal... */
5298 for (size_t i = 0; i < n && diag; i++)
5299 for (size_t j = i + 1; j < n; j++)
5300 if (gsl_matrix_get(a, i, j) != 0) {
5301 diag = 0;
5302 break;
5303 }
5304
5305 /* Quick inversion of diagonal matrix... */
5306 if (diag)
5307 for (size_t i = 0; i < n; i++)
5308 gsl_matrix_set(a, i, i, 1 / gsl_matrix_get(a, i, i));
5309
5310 /* Matrix inversion by means of Cholesky decomposition... */
5311 else {
5312 gsl_linalg_cholesky_decomp(a);
5313 gsl_linalg_cholesky_invert(a);
5314 }
5315}

◆ 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 5319 of file jurassic.c.

5323 {
5324
5325 /* Set sizes... */
5326 const size_t m = a->size1;
5327 const size_t n = a->size2;
5328
5329 /* Allocate... */
5330 gsl_matrix *aux = gsl_matrix_alloc(m, n);
5331
5332 /* Compute A^T B A... */
5333 if (transpose == 1) {
5334
5335 /* Compute B^1/2 A... */
5336 for (size_t i = 0; i < m; i++)
5337 for (size_t j = 0; j < n; j++)
5338 gsl_matrix_set(aux, i, j,
5339 gsl_vector_get(b, i) * gsl_matrix_get(a, i, j));
5340
5341 /* Compute A^T B A = (B^1/2 A)^T (B^1/2 A)... */
5342 gsl_blas_dgemm(CblasTrans, CblasNoTrans, 1.0, aux, aux, 0.0, c);
5343 }
5344
5345 /* Compute A B A^T... */
5346 else if (transpose == 2) {
5347
5348 /* Compute A B^1/2... */
5349 for (size_t i = 0; i < m; i++)
5350 for (size_t j = 0; j < n; j++)
5351 gsl_matrix_set(aux, i, j,
5352 gsl_matrix_get(a, i, j) * gsl_vector_get(b, j));
5353
5354 /* Compute A B A^T = (A B^1/2) (A B^1/2)^T... */
5355 gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0, aux, aux, 0.0, c);
5356 }
5357
5358 /* Free... */
5359 gsl_matrix_free(aux);
5360}

◆ 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 5364 of file jurassic.c.

5369 {
5370
5371 size_t m = 0;
5372
5373 /* Determine measurement vector... */
5374 for (int ir = 0; ir < obs->nr; ir++)
5375 for (int id = 0; id < ctl->nd; id++)
5376 if (isfinite(obs->rad[id][ir])) {
5377 if (y != NULL)
5378 gsl_vector_set(y, m, obs->rad[id][ir]);
5379 if (ida != NULL)
5380 ida[m] = id;
5381 if (ira != NULL)
5382 ira[m] = ir;
5383 m++;
5384 }
5385
5386 return m;
5387}

◆ 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 5391 of file jurassic.c.

5399 {
5400
5401 double disq = 0, lmpar = 0.001;
5402
5403 /* ------------------------------------------------------------
5404 Initialize...
5405 ------------------------------------------------------------ */
5406
5407 /* Allocate... */
5408 int *ipa, *iqa;
5409 ALLOC(ipa, int,
5410 N);
5411 ALLOC(iqa, int,
5412 N);
5413
5414 /* Get sizes... */
5415 const size_t m = obs2y(ctl, obs_meas, NULL, NULL, NULL);
5416 const size_t n = atm2x(ctl, atm_apr, NULL, iqa, ipa);
5417 if (m == 0 || n == 0) {
5418 WARN("Check problem definition (m = 0 or n = 0)!");
5419 *chisq = GSL_NAN;
5420 return;
5421 }
5422
5423 /* Allocate... */
5424 gsl_matrix *a = gsl_matrix_alloc(n, n);
5425 gsl_matrix *cov = gsl_matrix_alloc(n, n);
5426 gsl_matrix *k_i = gsl_matrix_alloc(m, n);
5427 gsl_matrix *s_a_inv = gsl_matrix_alloc(n, n);
5428
5429 gsl_vector *b = gsl_vector_alloc(n);
5430 gsl_vector *dx = gsl_vector_alloc(n);
5431 gsl_vector *dy = gsl_vector_alloc(m);
5432 gsl_vector *sig_eps_inv = gsl_vector_alloc(m);
5433 gsl_vector *sig_formod = gsl_vector_alloc(m);
5434 gsl_vector *sig_noise = gsl_vector_alloc(m);
5435 gsl_vector *x_a = gsl_vector_alloc(n);
5436 gsl_vector *x_i = gsl_vector_alloc(n);
5437 gsl_vector *x_step = gsl_vector_alloc(n);
5438 gsl_vector *y_aux = gsl_vector_alloc(m);
5439 gsl_vector *y_i = gsl_vector_alloc(m);
5440 gsl_vector *y_m = gsl_vector_alloc(m);
5441
5442 los_t *los_scratch;
5443 obs_t *obs_scratch;
5444 ALLOC(los_scratch, los_t, 1);
5445 ALLOC(obs_scratch, obs_t, 1);
5446
5447 /* Set timer... */
5448 SELECT_TIMER("RET_SETUP", "RETRIEVAL");
5449
5450 /* Set initial state... */
5451 copy_atm(ctl, atm_i, atm_apr, 0);
5452 copy_obs(ctl, obs_i, obs_meas, 0);
5453 if (formod(ctl, tbl, atm_i, obs_i, los_scratch, obs_scratch)
5455 ERRMSG("Forward model failed!");
5456
5457 /* Set state vectors and observation vectors... */
5458 atm2x(ctl, atm_apr, x_a, NULL, NULL);
5459 atm2x(ctl, atm_i, x_i, NULL, NULL);
5460 obs2y(ctl, obs_meas, y_m, NULL, NULL);
5461 obs2y(ctl, obs_i, y_i, NULL, NULL);
5462
5463 /* Set inverse a priori covariance S_a^-1... */
5464 set_cov_apr(ret, ctl, atm_apr, iqa, ipa, s_a_inv);
5465 int lockfd = shared_io_lock(ret);
5466 const char *dirname;
5467 int profile;
5468 const char *filename =
5470 "matrix_cov_apr.tab", &dirname, &profile);
5471 write_matrix(dirname, filename, ctl, s_a_inv,
5472 atm_i, obs_i, "x", "x", "r", profile);
5473 shared_io_unlock(lockfd);
5474 matrix_invert(s_a_inv);
5475
5476 /* Get measurement errors... */
5477 set_cov_meas(ret, ctl, obs_meas, sig_noise, sig_formod, sig_eps_inv);
5478
5479 /* Determine dx = x_i - x_a and dy = y - F(x_i) ... */
5480 gsl_vector_memcpy(dx, x_i);
5481 gsl_vector_sub(dx, x_a);
5482 gsl_vector_memcpy(dy, y_m);
5483 gsl_vector_sub(dy, y_i);
5484
5485 /* Compute cost function... */
5486 *chisq = cost_function(dx, dy, s_a_inv, sig_eps_inv);
5487
5488 /* Write info... */
5489 LOG(2, "it= %d / chi^2/m= %g", 0, *chisq);
5490
5491 /* Compute initial kernel... */
5492 SELECT_TIMER("RET_KERNEL_INIT", "RETRIEVAL");
5493 kernel(ctl, tbl, atm_i, obs_i, k_i);
5494
5495 /* ------------------------------------------------------------
5496 Levenberg-Marquardt minimization...
5497 ------------------------------------------------------------ */
5498
5499 SELECT_TIMER("RET_ITERATE", "RETRIEVAL");
5500
5501 /* Outer loop... */
5502 for (int it = 1; it <= ret->conv_itmax; it++) {
5503
5504 /* Store current cost function value... */
5505 double chisq_old = *chisq;
5506
5507 /* Compute kernel matrix K_i... */
5508 if (it > 1 && it % ret->kernel_recomp == 0)
5509 kernel(ctl, tbl, atm_i, obs_i, k_i);
5510
5511 /* Compute K_i^T * S_eps^{-1} * K_i ... */
5512 if (it == 1 || it % ret->kernel_recomp == 0)
5513 matrix_product(k_i, sig_eps_inv, 1, cov);
5514
5515 /* Determine b = K_i^T * S_eps^{-1} * dy - S_a^{-1} * dx ... */
5516 for (size_t i = 0; i < m; i++)
5517 gsl_vector_set(y_aux, i, gsl_vector_get(dy, i)
5518 * POW2(gsl_vector_get(sig_eps_inv, i)));
5519 gsl_blas_dgemv(CblasTrans, 1.0, k_i, y_aux, 0.0, b);
5520 gsl_blas_dgemv(CblasNoTrans, -1.0, s_a_inv, dx, 1.0, b);
5521
5522 /* Inner loop... */
5523 for (int it2 = 0; it2 < 20; it2++) {
5524
5525 /* Compute A = (1 + lmpar) * S_a^{-1} + K_i^T * S_eps^{-1} * K_i ... */
5526 gsl_matrix_memcpy(a, s_a_inv);
5527 gsl_matrix_scale(a, 1 + lmpar);
5528 gsl_matrix_add(a, cov);
5529
5530 /* Solve A * x_step = b by means of Cholesky decomposition... */
5531 gsl_linalg_cholesky_decomp(a);
5532 gsl_linalg_cholesky_solve(a, b, x_step);
5533
5534 /* Update atmospheric state... */
5535 gsl_vector_add(x_i, x_step);
5536 copy_atm(ctl, atm_i, atm_apr, 0);
5537 copy_obs(ctl, obs_i, obs_meas, 0);
5538 x2atm(ctl, x_i, atm_i);
5539
5540 /* Check atmospheric state... */
5541 for (int ip = 0; ip < atm_i->np; ip++) {
5542 atm_i->p[ip] = CLAMP(atm_i->p[ip], 5e-7, 5e4);
5543 atm_i->t[ip] = CLAMP(atm_i->t[ip], 100.0, 400.0);
5544 for (int ig = 0; ig < ctl->ng; ig++)
5545 atm_i->q[ig][ip] = CLAMP(atm_i->q[ig][ip], 0.0, 1.0);
5546 for (int iw = 0; iw < ctl->nw; iw++)
5547 atm_i->k[iw][ip] = MAX(atm_i->k[iw][ip], 0.0);
5548 }
5549 atm_i->clz = MAX(atm_i->clz, 0.0);
5550 atm_i->cldz = MAX(atm_i->cldz, 0.1);
5551 for (int icl = 0; icl < ctl->ncl; icl++)
5552 atm_i->clk[icl] = MAX(atm_i->clk[icl], 0.0);
5553 atm_i->sft = CLAMP(atm_i->sft, 100.0, 400.0);
5554 for (int isf = 0; isf < ctl->nsf; isf++)
5555 atm_i->sfeps[isf] = CLAMP(atm_i->sfeps[isf], 0.0, 1.0);
5556
5557 /* Forward calculation... */
5558 if (formod(ctl, tbl, atm_i, obs_i, los_scratch, obs_scratch)
5560 ERRMSG("Forward model failed!");
5561 obs2y(ctl, obs_i, y_i, NULL, NULL);
5562
5563 /* Determine dx = x_i - x_a and dy = y - F(x_i) ... */
5564 gsl_vector_memcpy(dx, x_i);
5565 gsl_vector_sub(dx, x_a);
5566 gsl_vector_memcpy(dy, y_m);
5567 gsl_vector_sub(dy, y_i);
5568
5569 /* Compute cost function... */
5570 *chisq = cost_function(dx, dy, s_a_inv, sig_eps_inv);
5571
5572 /* Modify Levenberg-Marquardt parameter... */
5573 if (*chisq > chisq_old) {
5574 lmpar *= 10;
5575 gsl_vector_sub(x_i, x_step);
5576 } else {
5577 lmpar /= 10;
5578 break;
5579 }
5580 }
5581
5582 /* Write info... */
5583 LOG(2, "it= %d / chi^2/m= %g", it, *chisq);
5584
5585 /* Get normalized step size in state space... */
5586 gsl_blas_ddot(x_step, b, &disq);
5587 disq /= (double) n;
5588
5589 /* Convergence test... */
5590 if ((it == 1 || it % ret->kernel_recomp == 0) && disq < ret->conv_dmin)
5591 break;
5592 }
5593
5594 /* ------------------------------------------------------------
5595 Analysis of retrieval results...
5596 ------------------------------------------------------------ */
5597
5598 /* Check if error analysis is requested... */
5599 if (ret->err_ana) {
5600
5601 SELECT_TIMER("RET_DIAGNOSTICS", "OUTPUT");
5602
5603 /* Store results... */
5604 lockfd = shared_io_lock(ret);
5606 "atm_final.tab", &dirname, &profile);
5607 write_atm(dirname, filename, ctl, atm_i, profile);
5609 "obs_final.tab", &dirname, &profile);
5610 write_obs(dirname, filename, ctl, obs_i, profile);
5611 filename =
5613 "matrix_kernel.tab", &dirname, &profile);
5614 write_matrix(dirname, filename, ctl, k_i,
5615 atm_i, obs_i, "y", "x", "r", profile);
5616
5617 /* Allocate... */
5618 gsl_matrix *auxnm = gsl_matrix_alloc(n, m);
5619 gsl_matrix *corr = gsl_matrix_alloc(n, n);
5620 gsl_matrix *gain = gsl_matrix_alloc(n, m);
5621
5622 /* Compute inverse retrieval covariance...
5623 cov^{-1} = S_a^{-1} + K_i^T * S_eps^{-1} * K_i */
5624 matrix_product(k_i, sig_eps_inv, 1, cov);
5625 gsl_matrix_add(cov, s_a_inv);
5626
5627 /* Compute retrieval covariance... */
5628 matrix_invert(cov);
5629 filename =
5631 "matrix_cov_ret.tab", &dirname, &profile);
5632 write_matrix(dirname, filename, ctl, cov,
5633 atm_i, obs_i, "x", "x", "r", profile);
5634 write_stddev("total", ret, ctl, atm_i, cov);
5635
5636 /* Compute correlation matrix... */
5637 for (size_t i = 0; i < n; i++)
5638 for (size_t j = 0; j < n; j++)
5639 gsl_matrix_set(corr, i, j, gsl_matrix_get(cov, i, j)
5640 / sqrt(gsl_matrix_get(cov, i, i))
5641 / sqrt(gsl_matrix_get(cov, j, j)));
5643 "matrix_corr.tab", &dirname, &profile);
5644 write_matrix(dirname, filename, ctl, corr,
5645 atm_i, obs_i, "x", "x", "r", profile);
5646
5647 /* Compute gain matrix...
5648 G = cov * K^T * S_eps^{-1} */
5649 for (size_t i = 0; i < n; i++)
5650 for (size_t j = 0; j < m; j++)
5651 gsl_matrix_set(auxnm, i, j, gsl_matrix_get(k_i, j, i)
5652 * POW2(gsl_vector_get(sig_eps_inv, j)));
5653 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, cov, auxnm, 0.0, gain);
5655 "matrix_gain.tab", &dirname, &profile);
5656 write_matrix(dirname, filename, ctl, gain,
5657 atm_i, obs_i, "x", "y", "c", profile);
5658
5659 /* Compute retrieval error due to noise... */
5660 matrix_product(gain, sig_noise, 2, a);
5661 write_stddev("noise", ret, ctl, atm_i, a);
5662
5663 /* Compute retrieval error due to forward model errors... */
5664 matrix_product(gain, sig_formod, 2, a);
5665 write_stddev("formod", ret, ctl, atm_i, a);
5666
5667 /* Compute averaging kernel matrix
5668 A = G * K ... */
5669 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, gain, k_i, 0.0, a);
5671 "matrix_avk.tab", &dirname, &profile);
5672 write_matrix(dirname, filename, ctl, a,
5673 atm_i, obs_i, "x", "x", "r", profile);
5674
5675 /* Analyze averaging kernel matrix... */
5676 analyze_avk(ret, ctl, atm_i, iqa, ipa, a);
5677 shared_io_unlock(lockfd);
5678
5679 /* Free... */
5680 gsl_matrix_free(auxnm);
5681 gsl_matrix_free(corr);
5682 gsl_matrix_free(gain);
5683 }
5684
5685 /* ------------------------------------------------------------
5686 Finalize...
5687 ------------------------------------------------------------ */
5688
5689 gsl_matrix_free(a);
5690 gsl_matrix_free(cov);
5691 gsl_matrix_free(k_i);
5692 gsl_matrix_free(s_a_inv);
5693
5694 gsl_vector_free(b);
5695 gsl_vector_free(dx);
5696 gsl_vector_free(dy);
5697 gsl_vector_free(sig_eps_inv);
5698 gsl_vector_free(sig_formod);
5699 gsl_vector_free(sig_noise);
5700 gsl_vector_free(x_a);
5701 gsl_vector_free(x_i);
5702 gsl_vector_free(x_step);
5703 gsl_vector_free(y_aux);
5704 gsl_vector_free(y_i);
5705 gsl_vector_free(y_m);
5706 free(los_scratch);
5707 free(obs_scratch);
5708
5709 free(ipa);
5710 free(iqa);
5711}
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:1639
int shared_io_lock(const ret_t *ret)
Acquire an exclusive lock for shared retrieval output files.
Definition: jurassic.c:7617
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:5319
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:8490
void shared_io_unlock(int fd)
Release a shared retrieval output lock.
Definition: jurassic.c:7644
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:7528
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:9012
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:5091
void matrix_invert(gsl_matrix *a)
Invert a square matrix, optimized for diagonal or symmetric positive-definite matrices.
Definition: jurassic.c:5289
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:7417
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:9416
#define SELECT_TIMER(id, group)
Switch to a named aggregated timer.
Definition: jurassic.h:1283
#define WARN(...)
Print a warning message with contextual information.
Definition: jurassic.h:1417
char shared_io_atm_final_file[LEN]
Optional shared retrieved-atmosphere output file.
Definition: jurassic.h:1966
int err_ana
Carry out error analysis (0=no, 1=yes).
Definition: jurassic.h:1894
char shared_io_matrix_cov_apr_file[LEN]
Optional shared a priori covariance output file.
Definition: jurassic.h:1972
double conv_dmin
Minimum normalized step size in state space.
Definition: jurassic.h:1891
char shared_io_matrix_gain_file[LEN]
Optional shared gain matrix output file.
Definition: jurassic.h:1984
char shared_io_matrix_cov_ret_file[LEN]
Optional shared retrieval covariance output file.
Definition: jurassic.h:1978
char shared_io_matrix_kernel_file[LEN]
Optional shared kernel matrix output file.
Definition: jurassic.h:1975
char shared_io_matrix_avk_file[LEN]
Optional shared averaging-kernel matrix output file.
Definition: jurassic.h:1987
int kernel_recomp
Re-computation of kernel matrix (number of iterations).
Definition: jurassic.h:1885
int conv_itmax
Maximum number of iterations.
Definition: jurassic.h:1888
char shared_io_matrix_corr_file[LEN]
Optional shared correlation matrix output file.
Definition: jurassic.h:1981
char shared_io_obs_final_file[LEN]
Optional shared retrieved-observation output file.
Definition: jurassic.h:1969
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 5715 of file jurassic.c.

5720 {
5721
5722 const double h = 0.02, zrefrac = 60;
5723
5724 double ex0[3], ex1[3], k[NW], lat, lon, n, ng[3], norm, p, q[NG], t,
5725 x[3], xh[3], xobs[3], xvp[3], z = 1e99, zmax, zmin;
5726
5727 int stop = 0;
5728
5729 /* Initialize... */
5730 los->np = 0;
5731 los->sft = -999;
5732 obs->tpz[ir] = obs->vpz[ir];
5733 obs->tplon[ir] = obs->vplon[ir];
5734 obs->tplat[ir] = obs->vplat[ir];
5735
5736 /* Get altitude range of atmospheric data... */
5737 gsl_stats_minmax(&zmin, &zmax, atm->z, 1, (size_t) atm->np);
5738
5739 /* Check observer altitude... */
5740 if (obs->obsz[ir] < zmin)
5742
5743 /* Determine Cartesian coordinates for observer and view point... */
5744 geo2cart(obs->obsz[ir], obs->obslon[ir], obs->obslat[ir], xobs);
5745 geo2cart(obs->vpz[ir], obs->vplon[ir], obs->vplat[ir], xvp);
5746
5747 /* Determine initial tangent vector... */
5748 for (int i = 0; i < 3; i++)
5749 ex0[i] = xvp[i] - xobs[i];
5750 norm = NORM(ex0);
5751 for (int i = 0; i < 3; i++)
5752 ex0[i] /= norm;
5753
5754 /* Observer within atmosphere... */
5755 for (int i = 0; i < 3; i++)
5756 x[i] = xobs[i];
5757
5758 /* Observer above atmosphere (search entry point)... */
5759 if (obs->obsz[ir] > zmax) {
5760 double dmax = norm, dmin = 0;
5761 while (fabs(dmin - dmax) > 0.001) {
5762 const double d = (dmax + dmin) / 2;
5763 for (int i = 0; i < 3; i++)
5764 x[i] = xobs[i] + d * ex0[i];
5765 cart2geo(x, &z, &lon, &lat);
5766 if (z <= zmax && z > zmax - 0.001)
5767 break;
5768 if (z < zmax - 0.0005)
5769 dmax = d;
5770 else
5771 dmin = d;
5772 }
5773 }
5774
5775 /* Ray-tracing... */
5776 while (1) {
5777
5778 /* Set step length... */
5779 double ds = ctl->rayds;
5780 if (ctl->raydz > 0) {
5781 norm = NORM(x);
5782 for (int i = 0; i < 3; i++)
5783 xh[i] = x[i] / norm;
5784 const double cosa = fabs(DOTP(ex0, xh));
5785 if (cosa != 0)
5786 ds = MIN(ctl->rayds, ctl->raydz / cosa);
5787 }
5788
5789 /* Determine geolocation... */
5790 cart2geo(x, &z, &lon, &lat);
5791
5792 /* Check if LOS hits the ground or has left atmosphere... */
5793 if (z < zmin || z > zmax) {
5794 stop = (z < zmin ? 2 : 1);
5795 const double frac =
5796 ((z <
5797 zmin ? zmin : zmax) - los->z[los->np - 1]) / (z - los->z[los->np -
5798 1]);
5799 geo2cart(los->z[los->np - 1], los->lon[los->np - 1],
5800 los->lat[los->np - 1], xh);
5801 for (int i = 0; i < 3; i++)
5802 x[i] = xh[i] + frac * (x[i] - xh[i]);
5803 cart2geo(x, &z, &lon, &lat);
5804 los->ds[los->np - 1] = ds * frac;
5805 ds = 0;
5806 }
5807
5808 /* Interpolate atmospheric data... */
5809 intpol_atm(ctl, atm, z, &p, &t, q, k);
5810
5811 /* Abort before writing beyond the fixed LOS scratch buffers... */
5812 if (los->np >= NLOS)
5814
5815 /* Save data... */
5816 los->lon[los->np] = lon;
5817 los->lat[los->np] = lat;
5818 los->z[los->np] = z;
5819 los->p[los->np] = p;
5820 los->t[los->np] = t;
5821 for (int ig = 0; ig < ctl->ng; ig++)
5822 los->q[los->np][ig] = q[ig];
5823 for (int id = 0; id < ctl->nd; id++)
5824 los->k[los->np][id] = k[ctl->window[id]];
5825 los->ds[los->np] = ds;
5826
5827 /* Add cloud extinction... */
5828 if (ctl->ncl > 0 && atm->cldz > 0) {
5829 const double aux = exp(-0.5 * POW2((z - atm->clz) / atm->cldz));
5830 for (int id = 0; id < ctl->nd; id++) {
5831 const int icl = locate_irr(ctl->clnu, ctl->ncl, ctl->nu[id]);
5832 los->k[los->np][id]
5833 += aux * LIN(ctl->clnu[icl], atm->clk[icl],
5834 ctl->clnu[icl + 1], atm->clk[icl + 1], ctl->nu[id]);
5835 }
5836 }
5837
5838 /* Increment number of LOS points... */
5839 los->np++;
5840
5841 /* Check stop flag... */
5842 if (stop) {
5843
5844 /* Set surface temperature... */
5845 if (ctl->nsf > 0 && atm->sft > 0)
5846 t = atm->sft;
5847 los->sft = (stop == 2 ? t : -999);
5848
5849 /* Set surface emissivity... */
5850 for (int id = 0; id < ctl->nd; id++) {
5851 los->sfeps[id] = 1.0;
5852 if (ctl->nsf > 0) {
5853 const int isf = locate_irr(ctl->sfnu, ctl->nsf, ctl->nu[id]);
5854 los->sfeps[id] = LIN(ctl->sfnu[isf], atm->sfeps[isf],
5855 ctl->sfnu[isf + 1], atm->sfeps[isf + 1],
5856 ctl->nu[id]);
5857 }
5858 }
5859
5860 /* Leave raytracer... */
5861 break;
5862 }
5863
5864 /* Determine refractivity... */
5865 if (ctl->refrac && z <= zrefrac)
5866 n = 1 + REFRAC_EDLEN(p, t);
5867 else
5868 n = 1;
5869
5870 /* Construct new tangent vector (first term)... */
5871 for (int i = 0; i < 3; i++)
5872 ex1[i] = ex0[i] * n;
5873
5874 /* Compute gradient of refractivity... */
5875 if (ctl->refrac && z <= zrefrac) {
5876 for (int i = 0; i < 3; i++)
5877 xh[i] = x[i] + 0.5 * ds * ex0[i];
5878 cart2geo(xh, &z, &lon, &lat);
5879 intpol_atm(ctl, atm, z, &p, &t, q, k);
5880 n = REFRAC_EDLEN(p, t);
5881 for (int i = 0; i < 3; i++) {
5882 xh[i] += h;
5883 cart2geo(xh, &z, &lon, &lat);
5884 intpol_atm(ctl, atm, z, &p, &t, q, k);
5885 ng[i] = (REFRAC_EDLEN(p, t) - n) / h;
5886 xh[i] -= h;
5887 }
5888 } else
5889 for (int i = 0; i < 3; i++)
5890 ng[i] = 0;
5891
5892 /* Construct new tangent vector (second term)... */
5893 for (int i = 0; i < 3; i++)
5894 ex1[i] += ds * ng[i];
5895
5896 /* Normalize new tangent vector... */
5897 norm = NORM(ex1);
5898 for (int i = 0; i < 3; i++)
5899 ex1[i] /= norm;
5900
5901 /* Determine next point of LOS... */
5902 for (int i = 0; i < 3; i++)
5903 x[i] += 0.5 * ds * (ex0[i] + ex1[i]);
5904
5905 /* Copy tangent vector... */
5906 for (int i = 0; i < 3; i++)
5907 ex0[i] = ex1[i];
5908 }
5909
5910 /* Get tangent point (to be done before changing segment lengths!)... */
5911 tangent_point(los, &obs->tpz[ir], &obs->tplon[ir], &obs->tplat[ir]);
5912
5913 /* Change segment lengths according to trapezoid rule... */
5914 for (int ip = los->np - 1; ip >= 1; ip--)
5915 los->ds[ip] = 0.5 * (los->ds[ip - 1] + los->ds[ip]);
5916 los->ds[0] *= 0.5;
5917
5918 /* Compute column density... */
5919 for (int ip = 0; ip < los->np; ip++)
5920 for (int ig = 0; ig < ctl->ng; ig++)
5921 los->u[ip][ig] = 10 * los->q[ip][ig] * los->p[ip]
5922 / (KB * los->t[ip]) * los->ds[ip];
5923
5924 /* Compute Curtis-Godson means... */
5925 for (int ig = 0; ig < ctl->ng; ig++) {
5926 los->cgu[0][ig] = los->u[0][ig];
5927 los->cgp[0][ig] = los->u[0][ig] * los->p[0];
5928 los->cgt[0][ig] = los->u[0][ig] * los->t[0];
5929 }
5930 for (int ip = 1; ip < los->np; ip++)
5931 for (int ig = 0; ig < ctl->ng; ig++) {
5932 los->cgu[ip][ig] = los->cgu[ip - 1][ig] + los->u[ip][ig];
5933 los->cgp[ip][ig] = los->cgp[ip - 1][ig] + los->u[ip][ig] * los->p[ip];
5934 los->cgt[ip][ig] = los->cgt[ip - 1][ig] + los->u[ip][ig] * los->t[ip];
5935 }
5936 for (int ip = 0; ip < los->np; ip++)
5937 for (int ig = 0; ig < ctl->ng; ig++)
5938 if (los->cgu[ip][ig] != 0) {
5939 los->cgp[ip][ig] /= los->cgu[ip][ig];
5940 los->cgt[ip][ig] /= los->cgu[ip][ig];
5941 }
5942
5943 return FORMOD_STATUS_OK;
5944}
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:4747
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:7696
void cart2geo(const double *x, double *z, double *lon, double *lat)
Converts Cartesian coordinates to geographic coordinates.
Definition: jurassic.c:200
@ FORMOD_STATUS_TOO_MANY_LOS_POINTS
Definition: jurassic.h:163
@ FORMOD_STATUS_OBSERVER_BELOW_SURFACE
Definition: jurassic.h:162
#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:1229
#define NLOS
Maximum number of LOS points.
Definition: jurassic.h:387
#define NW
Maximum number of spectral windows.
Definition: jurassic.h:422
int window[ND]
Window index of each channel.
Definition: jurassic.h:1622
double rayds
Maximum step length for raytracing [km].
Definition: jurassic.h:1679
double raydz
Vertical step length for raytracing [km].
Definition: jurassic.h:1682
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 5948 of file jurassic.c.

5953 {
5954
5955 /* Init... */
5956 atm->np = 0;
5957
5958 /* Set filename... */
5959 char file[LEN];
5960 if (dirname != NULL)
5961 sprintf(file, "%s/%s", dirname, filename);
5962 else
5963 sprintf(file, "%s", filename);
5964
5965 /* Write info... */
5966 LOG(1, "Read atmospheric data: %s", file);
5967
5968 /* Read ASCII data... */
5969 if (ctl->atmfmt == 1)
5970 read_atm_asc(file, ctl, atm);
5971
5972 /* Read binary data... */
5973 else if (ctl->atmfmt == 2)
5974 read_atm_bin(file, ctl, atm);
5975
5976 /* Read netCDF data... */
5977 else if (ctl->atmfmt == 3)
5978 read_atm_nc(file, ctl, atm, profile);
5979
5980 /* Check number of points... */
5981 if (atm->np < 1)
5982 ERRMSG("Could not read any data!");
5983
5984 /* Write info... */
5985 double mini, maxi;
5986 LOG(2, "Number of data points: %d", atm->np);
5987 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
5988 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
5989 gsl_stats_minmax(&mini, &maxi, atm->z, 1, (size_t) atm->np);
5990 LOG(2, "Altitude range: %g ... %g km", mini, maxi);
5991 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
5992 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
5993 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
5994 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
5995 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
5996 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
5997 gsl_stats_minmax(&mini, &maxi, atm->t, 1, (size_t) atm->np);
5998 LOG(2, "Temperature range: %g ... %g K", mini, maxi);
5999 for (int ig = 0; ig < ctl->ng; ig++) {
6000 gsl_stats_minmax(&mini, &maxi, atm->q[ig], 1, (size_t) atm->np);
6001 LOG(2, "Emitter %s range: %g ... %g ppv", ctl->emitter[ig], mini, maxi);
6002 }
6003 for (int iw = 0; iw < ctl->nw; iw++) {
6004 gsl_stats_minmax(&mini, &maxi, atm->k[iw], 1, (size_t) atm->np);
6005 LOG(2, "Extinction range (window %d): %g ... %g km^-1", iw, mini, maxi);
6006 }
6007 if (ctl->ncl > 0) {
6008 LOG(2, "Cloud layer: z= %g km | dz= %g km | k= %g ... %g km^-1",
6009 atm->clz, atm->cldz, atm->clk[0], atm->clk[ctl->ncl - 1]);
6010 } else
6011 LOG(2, "Cloud layer: none");
6012 if (ctl->nsf > 0) {
6013 LOG(2,
6014 "Surface: T_s = %g K | eps= %g ... %g",
6015 atm->sft, atm->sfeps[0], atm->sfeps[ctl->nsf - 1]);
6016 } else
6017 LOG(2, "Surface: none");
6018}
void read_atm_bin(const char *filename, const ctl_t *ctl, atm_t *atm)
Read atmospheric data in binary format.
Definition: jurassic.c:6073
void read_atm_asc(const char *filename, const ctl_t *ctl, atm_t *atm)
Read atmospheric data in ASCII format.
Definition: jurassic.c:6022
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:6167
int atmfmt
Atmospheric data file format (1=ASCII, 2=binary, 3=netCDF).
Definition: jurassic.h:1652
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 6022 of file jurassic.c.

6025 {
6026
6027 /* Init... */
6028 atm->np = 0;
6029
6030 /* Open file... */
6031 FILE *in;
6032 if (!(in = fopen(filename, "r")))
6033 ERRMSG("Cannot open file!");
6034
6035 /* Read line... */
6036 char line[LEN], *tok;
6037 while (fgets(line, LEN, in)) {
6038
6039 /* Read data... */
6040 TOK(line, tok, "%lg", atm->time[atm->np]);
6041 TOK(NULL, tok, "%lg", atm->z[atm->np]);
6042 TOK(NULL, tok, "%lg", atm->lon[atm->np]);
6043 TOK(NULL, tok, "%lg", atm->lat[atm->np]);
6044 TOK(NULL, tok, "%lg", atm->p[atm->np]);
6045 TOK(NULL, tok, "%lg", atm->t[atm->np]);
6046 for (int ig = 0; ig < ctl->ng; ig++)
6047 TOK(NULL, tok, "%lg", atm->q[ig][atm->np]);
6048 for (int iw = 0; iw < ctl->nw; iw++)
6049 TOK(NULL, tok, "%lg", atm->k[iw][atm->np]);
6050 if (ctl->ncl > 0 && atm->np == 0) {
6051 TOK(NULL, tok, "%lg", atm->clz);
6052 TOK(NULL, tok, "%lg", atm->cldz);
6053 for (int icl = 0; icl < ctl->ncl; icl++)
6054 TOK(NULL, tok, "%lg", atm->clk[icl]);
6055 }
6056 if (ctl->nsf > 0 && atm->np == 0) {
6057 TOK(NULL, tok, "%lg", atm->sft);
6058 for (int isf = 0; isf < ctl->nsf; isf++)
6059 TOK(NULL, tok, "%lg", atm->sfeps[isf]);
6060 }
6061
6062 /* Increment data point counter... */
6063 if ((++atm->np) > NP)
6064 ERRMSG("Too many data points!");
6065 }
6066
6067 /* Close file... */
6068 fclose(in);
6069}
#define TOK(line, tok, format, var)
Tokenize a string and parse a variable.
Definition: jurassic.h:1314
#define NP
Maximum number of atmospheric data points.
Definition: jurassic.h:392

◆ 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 6073 of file jurassic.c.

6076 {
6077
6078 /* Open file... */
6079 FILE *in;
6080 if (!(in = fopen(filename, "r")))
6081 ERRMSG("Cannot open file!");
6082
6083 /* Read header... */
6084 char magic[4];
6085 FREAD(magic, char,
6086 4,
6087 in);
6088 if (memcmp(magic, "ATM1", 4) != 0)
6089 ERRMSG("Invalid magic string!");
6090
6091 int ng, nw, ncl, nsf;
6092 FREAD(&ng, int,
6093 1,
6094 in);
6095 FREAD(&nw, int,
6096 1,
6097 in);
6098 FREAD(&ncl, int,
6099 1,
6100 in);
6101 FREAD(&nsf, int,
6102 1,
6103 in);
6104 if (ng != ctl->ng || nw != ctl->nw || ncl != ctl->ncl || nsf != ctl->nsf)
6105 ERRMSG("Error reading file header!");
6106
6107 /* Read data... */
6108 size_t np;
6109 FREAD(&np, size_t,
6110 1,
6111 in);
6112 atm->np = (int) np;
6113 if (atm->np > NP)
6114 ERRMSG("Too many data points!");
6115 FREAD(atm->time, double,
6116 np,
6117 in);
6118 FREAD(atm->z, double,
6119 np,
6120 in);
6121 FREAD(atm->lon, double,
6122 np,
6123 in);
6124 FREAD(atm->lat, double,
6125 np,
6126 in);
6127 FREAD(atm->p, double,
6128 np,
6129 in);
6130 FREAD(atm->t, double,
6131 np,
6132 in);
6133 for (int ig = 0; ig < ctl->ng; ig++)
6134 FREAD(atm->q[ig], double,
6135 np,
6136 in);
6137 for (int iw = 0; iw < ctl->nw; iw++)
6138 FREAD(atm->k[iw], double,
6139 np,
6140 in);
6141 if (ctl->ncl > 0) {
6142 FREAD(&atm->clz, double,
6143 1,
6144 in);
6145 FREAD(&atm->cldz, double,
6146 1,
6147 in);
6148 FREAD(atm->clk, double,
6149 (size_t) ctl->ncl,
6150 in);
6151 }
6152 if (ctl->nsf) {
6153 FREAD(&atm->sft, double,
6154 1,
6155 in);
6156 FREAD(atm->sfeps, double,
6157 (size_t) ctl->nsf,
6158 in);
6159 }
6160
6161 /* Close file... */
6162 fclose(in);
6163}
#define FREAD(ptr, type, size, out)
Read binary data from a file.
Definition: jurassic.h:680

◆ 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 6167 of file jurassic.c.

6171 {
6172
6173 int ncid, var_time, var_z, var_lon, var_lat, var_p, var_t, var_q[NG],
6174 var_k[NW], var_cz = -1, var_cdz = -1, var_ck[NCL], var_sft =
6175 -1, var_sfe[NSF], var_nlev = -1;
6176
6177 char varname[LEN];
6178
6179 /* Open file... */
6180 NC(nc_open(filename, NC_NOWRITE, &ncid));
6181
6182 /* Initialize hyperslab... */
6183 size_t start[2] = { (size_t) profile, 0 };
6184 size_t count[2] = { 1, 0 };
6185
6186 /* Determine atm->np... */
6187 NC(nc_inq_varid(ncid, "nlev", &var_nlev));
6188 NC(nc_get_vara_int(ncid, var_nlev, start, count, &atm->np));
6189 if (atm->np < 1 || atm->np > NP)
6190 ERRMSG("Number of level out of range!");
6191
6192 /* Update hyperslab... */
6193 count[1] = (size_t) atm->np;
6194
6195 /* Inquire core variables... */
6196 NC(nc_inq_varid(ncid, "time", &var_time));
6197 NC(nc_inq_varid(ncid, "z", &var_z));
6198 NC(nc_inq_varid(ncid, "lon", &var_lon));
6199 NC(nc_inq_varid(ncid, "lat", &var_lat));
6200 NC(nc_inq_varid(ncid, "p", &var_p));
6201 NC(nc_inq_varid(ncid, "t", &var_t));
6202
6203 /* Inquire emiters... */
6204 for (int ig = 0; ig < ctl->ng; ig++)
6205 NC(nc_inq_varid(ncid, ctl->emitter[ig], &var_q[ig]));
6206
6207 /* Inquire extinctions... */
6208 for (int iw = 0; iw < ctl->nw; iw++) {
6209 sprintf(varname, "ext_win_%d", iw);
6210 NC(nc_inq_varid(ncid, varname, &var_k[iw]));
6211 }
6212
6213 /* Inquire cloud variables... */
6214 if (ctl->ncl > 0) {
6215 NC(nc_inq_varid(ncid, "cld_z", &var_cz));
6216 NC(nc_inq_varid(ncid, "cld_dz", &var_cdz));
6217 for (int icl = 0; icl < ctl->ncl; icl++) {
6218 sprintf(varname, "cld_k_%.4f", ctl->clnu[icl]);
6219 NC(nc_inq_varid(ncid, varname, &var_ck[icl]));
6220 }
6221 }
6222
6223 /* Inquire surface variables... */
6224 if (ctl->nsf > 0) {
6225 NC(nc_inq_varid(ncid, "srf_t", &var_sft));
6226 for (int isf = 0; isf < ctl->nsf; isf++) {
6227 sprintf(varname, "srf_eps_%.4f", ctl->sfnu[isf]);
6228 NC(nc_inq_varid(ncid, varname, &var_sfe[isf]));
6229 }
6230 }
6231
6232 /* Read core variables... */
6233 NC(nc_get_vara_double(ncid, var_time, start, count, atm->time));
6234 NC(nc_get_vara_double(ncid, var_z, start, count, atm->z));
6235 NC(nc_get_vara_double(ncid, var_lon, start, count, atm->lon));
6236 NC(nc_get_vara_double(ncid, var_lat, start, count, atm->lat));
6237 NC(nc_get_vara_double(ncid, var_p, start, count, atm->p));
6238 NC(nc_get_vara_double(ncid, var_t, start, count, atm->t));
6239
6240 /* Read emitters... */
6241 for (int ig = 0; ig < ctl->ng; ig++)
6242 NC(nc_get_vara_double(ncid, var_q[ig], start, count, atm->q[ig]));
6243
6244 /* Read extinctions... */
6245 for (int iw = 0; iw < ctl->nw; iw++)
6246 NC(nc_get_vara_double(ncid, var_k[iw], start, count, atm->k[iw]));
6247
6248 /* Read cloud variables... */
6249 if (ctl->ncl > 0) {
6250 NC(nc_get_vara_double(ncid, var_cz, start, count, &atm->clz));
6251 NC(nc_get_vara_double(ncid, var_cdz, start, count, &atm->cldz));
6252 for (int icl = 0; icl < ctl->ncl; icl++)
6253 NC(nc_get_vara_double(ncid, var_ck[icl], start, count, &atm->clk[icl]));
6254 }
6255
6256 /* Read surface variables... */
6257 if (ctl->nsf > 0) {
6258 NC(nc_get_vara_double(ncid, var_sft, start, count, &atm->sft));
6259
6260 for (int isf = 0; isf < ctl->nsf; isf++)
6261 NC(nc_get_vara_double
6262 (ncid, var_sfe[isf], start, count, &atm->sfeps[isf]));
6263 }
6264
6265 /* Close file... */
6266 NC(nc_close(ncid));
6267}
#define NSF
Maximum number of surface layer spectral grid points.
Definition: jurassic.h:407
#define NCL
Maximum number of cloud layer spectral grid points.
Definition: jurassic.h:350

◆ 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 6271 of file jurassic.c.

6274 {
6275
6276 /* Write info... */
6277 LOG(1, "\nJuelich Rapid Spectral Simulation Code (JURASSIC)\n"
6278 "(executable: %s | version: %s | compiled: %s, %s)\n",
6279 argv[0], VERSION, __DATE__, __TIME__);
6280
6281 /* Emitters... */
6282 ctl->ng = (int) scan_ctl(argc, argv, "NG", -1, "0", NULL);
6283 if (ctl->ng < 0 || ctl->ng > NG)
6284 ERRMSG("Set 0 <= NG <= MAX!");
6285 for (int ig = 0; ig < ctl->ng; ig++)
6286 scan_ctl(argc, argv, "EMITTER", ig, "", ctl->emitter[ig]);
6287 ctl->ig_co2 = find_emitter(ctl, "CO2");
6288 ctl->ig_h2o = find_emitter(ctl, "H2O");
6289 ctl->ig_n2 = find_emitter(ctl, "N2");
6290 ctl->ig_o2 = find_emitter(ctl, "O2");
6291
6292 /* Radiance channels... */
6293 ctl->nd = (int) scan_ctl(argc, argv, "ND", -1, "0", NULL);
6294 if (ctl->nd < 0 || ctl->nd > ND)
6295 ERRMSG("Set 0 <= ND <= MAX!");
6296 for (int id = 0; id < ctl->nd; id++)
6297 ctl->nu[id] = scan_ctl(argc, argv, "NU", id, "", NULL);
6298
6299 /* Spectral windows... */
6300 ctl->nw = (int) scan_ctl(argc, argv, "NW", -1, "1", NULL);
6301 if (ctl->nw < 0 || ctl->nw > NW)
6302 ERRMSG("Set 0 <= NW <= MAX!");
6303 for (int id = 0; id < ctl->nd; id++)
6304 ctl->window[id] = (int) scan_ctl(argc, argv, "WINDOW", id, "0", NULL);
6305
6306 /* Cloud data... */
6307 ctl->ncl = (int) scan_ctl(argc, argv, "NCL", -1, "0", NULL);
6308 if (ctl->ncl < 0 || ctl->ncl > NCL)
6309 ERRMSG("Set 0 <= NCL <= MAX!");
6310 if (ctl->ncl == 1)
6311 ERRMSG("Set NCL > 1!");
6312 for (int icl = 0; icl < ctl->ncl; icl++)
6313 ctl->clnu[icl] = scan_ctl(argc, argv, "CLNU", icl, "", NULL);
6314
6315 /* Surface data... */
6316 ctl->nsf = (int) scan_ctl(argc, argv, "NSF", -1, "0", NULL);
6317 if (ctl->nsf < 0 || ctl->nsf > NSF)
6318 ERRMSG("Set 0 <= NSF <= MAX!");
6319 if (ctl->nsf == 1)
6320 ERRMSG("Set NSF > 1!");
6321 for (int isf = 0; isf < ctl->nsf; isf++)
6322 ctl->sfnu[isf] = scan_ctl(argc, argv, "SFNU", isf, "", NULL);
6323 ctl->sftype = (int) scan_ctl(argc, argv, "SFTYPE", -1, "2", NULL);
6324 if (ctl->sftype < 0 || ctl->sftype > 3)
6325 ERRMSG("Set 0 <= SFTYPE <= 3!");
6326 ctl->sfsza = scan_ctl(argc, argv, "SFSZA", -1, "-999", NULL);
6327
6328 /* Emissivity look-up tables... */
6329 scan_ctl(argc, argv, "TBLBASE", -1, "-", ctl->tblbase);
6330 ctl->tblfmt = (int) scan_ctl(argc, argv, "TBLFMT", -1, "1", NULL);
6331 if (ctl->tblfmt < 1 || ctl->tblfmt > 3)
6332 ERRMSG("Unknown look-up table file format, set TBLFMT to 1, 2, or 3!");
6333
6334 /* Climatological data file... */
6335 scan_ctl(argc, argv, "CLIM_FILE", -1, "-", ctl->climfile);
6336
6337 /* File formats... */
6338 ctl->atmfmt = (int) scan_ctl(argc, argv, "ATMFMT", -1, "1", NULL);
6339 if (ctl->atmfmt < 1 || ctl->atmfmt > 3)
6340 ERRMSG("Unknown atmospheric file format, set ATMFMT to 1, 2, or 3!");
6341 ctl->obsfmt = (int) scan_ctl(argc, argv, "OBSFMT", -1, "1", NULL);
6342 if (ctl->obsfmt < 1 || ctl->obsfmt > 3)
6343 ERRMSG("Unknown observation file format, set OBSFMT to 1, 2, or 3!");
6344 ctl->matrixfmt = (int) scan_ctl(argc, argv, "MATRIXFMT", -1, "1", NULL);
6345 if (ctl->matrixfmt < 1 || ctl->matrixfmt > 3)
6346 ERRMSG("Unknown matrix file format, set MATRIXFMT to 1, 2, or 3!");
6347
6348 /* Hydrostatic equilibrium... */
6349 ctl->hydz = scan_ctl(argc, argv, "HYDZ", -1, "-999", NULL);
6350
6351 /* Continua... */
6352 ctl->ctm_co2 = (int) scan_ctl(argc, argv, "CTM_CO2", -1, "1", NULL);
6353 ctl->ctm_h2o = (int) scan_ctl(argc, argv, "CTM_H2O", -1, "1", NULL);
6354 ctl->ctm_n2 = (int) scan_ctl(argc, argv, "CTM_N2", -1, "1", NULL);
6355 ctl->ctm_o2 = (int) scan_ctl(argc, argv, "CTM_O2", -1, "1", NULL);
6356
6357 /* Ray-tracing... */
6358 ctl->refrac = (int) scan_ctl(argc, argv, "REFRAC", -1, "1", NULL);
6359 ctl->rayds = scan_ctl(argc, argv, "RAYDS", -1, "10", NULL);
6360 ctl->raydz = scan_ctl(argc, argv, "RAYDZ", -1, "0.1", NULL);
6361
6362 /* Field of view... */
6363 scan_ctl(argc, argv, "FOV", -1, "-", ctl->fov);
6364 if (ctl->fov[0] != '-')
6365 read_shape(ctl->fov, ctl->fov_dz, ctl->fov_w, &ctl->fov_n);
6366
6367 /* Retrieval interface... */
6368 ctl->retp_zmin = scan_ctl(argc, argv, "RETP_ZMIN", -1, "-999", NULL);
6369 ctl->retp_zmax = scan_ctl(argc, argv, "RETP_ZMAX", -1, "-999", NULL);
6370 ctl->rett_zmin = scan_ctl(argc, argv, "RETT_ZMIN", -1, "-999", NULL);
6371 ctl->rett_zmax = scan_ctl(argc, argv, "RETT_ZMAX", -1, "-999", NULL);
6372 for (int ig = 0; ig < ctl->ng; ig++) {
6373 ctl->retq_zmin[ig] = scan_ctl(argc, argv, "RETQ_ZMIN", ig, "-999", NULL);
6374 ctl->retq_zmax[ig] = scan_ctl(argc, argv, "RETQ_ZMAX", ig, "-999", NULL);
6375 }
6376 for (int iw = 0; iw < ctl->nw; iw++) {
6377 ctl->retk_zmin[iw] = scan_ctl(argc, argv, "RETK_ZMIN", iw, "-999", NULL);
6378 ctl->retk_zmax[iw] = scan_ctl(argc, argv, "RETK_ZMAX", iw, "-999", NULL);
6379 }
6380 ctl->ret_clz = (int) scan_ctl(argc, argv, "RET_CLZ", -1, "0", NULL);
6381 ctl->ret_cldz = (int) scan_ctl(argc, argv, "RET_CLDZ", -1, "0", NULL);
6382 ctl->ret_clk = (int) scan_ctl(argc, argv, "RET_CLK", -1, "0", NULL);
6383 ctl->ret_sft = (int) scan_ctl(argc, argv, "RET_SFT", -1, "0", NULL);
6384 ctl->ret_sfeps = (int) scan_ctl(argc, argv, "RET_SFEPS", -1, "0", NULL);
6385
6386 /* Output flags... */
6387 ctl->write_bbt = (int) scan_ctl(argc, argv, "WRITE_BBT", -1, "0", NULL);
6388 ctl->write_matrix =
6389 (int) scan_ctl(argc, argv, "WRITE_MATRIX", -1, "0", NULL);
6390
6391 /* External forward models... */
6392 ctl->formod = (int) scan_ctl(argc, argv, "FORMOD", -1, "1", NULL);
6393 scan_ctl(argc, argv, "RFMBIN", -1, "-", ctl->rfmbin);
6394 scan_ctl(argc, argv, "RFMHIT", -1, "-", ctl->rfmhit);
6395 for (int ig = 0; ig < ctl->ng; ig++)
6396 scan_ctl(argc, argv, "RFMXSC", ig, "-", ctl->rfmxsc[ig]);
6397}
int find_emitter(const ctl_t *ctl, const char *emitter)
Find gas species index by name.
Definition: jurassic.c:3972
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:7349
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:7028
int write_matrix
Write matrix file (0=no, 1=yes).
Definition: jurassic.h:1739
char tblbase[LEN]
Basename for table files and filter function files.
Definition: jurassic.h:1643
int matrixfmt
Matrix data file format (1=ASCII, 2=binary, 3=netCDF).
Definition: jurassic.h:1658
int obsfmt
Observation data file format (1=ASCII, 2=binary, 3=netCDF).
Definition: jurassic.h:1655
int tblfmt
Look-up table file format (1=ASCII, 2=binary, 3=netCDF).
Definition: jurassic.h:1646
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 6401 of file jurassic.c.

6406 {
6407
6408 /* Read ASCII data... */
6409 if (ctl->matrixfmt == 1)
6410 read_matrix_asc(dirname, filename, matrix);
6411
6412 /* Read binary data... */
6413 else if (ctl->matrixfmt == 2)
6414 read_matrix_bin(dirname, filename, matrix);
6415
6416 /* Read netCDF data... */
6417 else if (ctl->matrixfmt == 3)
6418 read_matrix_nc(dirname, filename, matrix, dataset);
6419
6420 /* Error... */
6421 else
6422 ERRMSG("Unknown matrix file format, check MATRIXFMT!");
6423}
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:6519
void read_matrix_asc(const char *dirname, const char *filename, gsl_matrix *matrix)
Read a numerical matrix from an ASCII file.
Definition: jurassic.c:6427
void read_matrix_bin(const char *dirname, const char *filename, gsl_matrix *matrix)
Read a numerical matrix from a binary file.
Definition: jurassic.c:6466
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 6427 of file jurassic.c.

6430 {
6431
6432 char dum[LEN], file[LEN], line[LEN];
6433
6434 double value;
6435
6436 int i, j;
6437
6438 /* Set filename... */
6439 if (dirname != NULL)
6440 sprintf(file, "%s/%s", dirname, filename);
6441 else
6442 sprintf(file, "%s", filename);
6443
6444 /* Write info... */
6445 LOG(1, "Read matrix: %s", file);
6446
6447 /* Open file... */
6448 FILE *in;
6449 if (!(in = fopen(file, "r")))
6450 ERRMSG("Cannot open file!");
6451
6452 /* Read data... */
6453 gsl_matrix_set_zero(matrix);
6454 while (fgets(line, LEN, in))
6455 if (sscanf(line, "%d %s %s %s %s %s %d %s %s %s %s %s %lg",
6456 &i, dum, dum, dum, dum, dum,
6457 &j, dum, dum, dum, dum, dum, &value) == 13)
6458 gsl_matrix_set(matrix, (size_t) i, (size_t) j, value);
6459
6460 /* Close file... */
6461 fclose(in);
6462}

◆ 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 6466 of file jurassic.c.

6469 {
6470
6471 char file[LEN], magic[4];
6472 size_t nr, nc;
6473
6474 /* Set filename... */
6475 if (dirname != NULL)
6476 sprintf(file, "%s/%s", dirname, filename);
6477 else
6478 sprintf(file, "%s", filename);
6479
6480 /* Write info... */
6481 LOG(1, "Read matrix: %s", file);
6482
6483 /* Open file... */
6484 FILE *in;
6485 if (!(in = fopen(file, "r")))
6486 ERRMSG("Cannot open file!");
6487
6488 /* Read header... */
6489 FREAD(magic, char,
6490 4,
6491 in);
6492 if (memcmp(magic, "MAT1", 4) != 0)
6493 ERRMSG("Invalid magic string!");
6494 FREAD(&nr, size_t,
6495 1,
6496 in);
6497 FREAD(&nc, size_t,
6498 1,
6499 in);
6500 if (nr != matrix->size1 || nc != matrix->size2)
6501 ERRMSG("Error reading file header!");
6502
6503 /* Read data... */
6504 for (size_t i = 0; i < nr; i++)
6505 for (size_t j = 0; j < nc; j++) {
6506 double value;
6507 FREAD(&value, double,
6508 1,
6509 in);
6510 gsl_matrix_set(matrix, i, j, value);
6511 }
6512
6513 /* Close file... */
6514 fclose(in);
6515}

◆ 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 6519 of file jurassic.c.

6523 {
6524
6525 char file[LEN];
6526
6527 int ncid, dimid_row, dimid_col, varid;
6528
6529 size_t nr, nc;
6530
6531 /* Set filename... */
6532 if (dirname != NULL)
6533 sprintf(file, "%s/%s", dirname, filename);
6534 else
6535 sprintf(file, "%s", filename);
6536
6537 /* Write info... */
6538 LOG(1, "Read matrix: %s", file);
6539
6540 /* Open file... */
6541 NC(nc_open(file, NC_NOWRITE, &ncid));
6542
6543 /* Read dimensions... */
6544 NC(nc_inq_dimid(ncid, "row", &dimid_row));
6545 NC(nc_inq_dimid(ncid, "col", &dimid_col));
6546 NC(nc_inq_dimlen(ncid, dimid_row, &nr));
6547 NC(nc_inq_dimlen(ncid, dimid_col, &nc));
6548 if (nr != matrix->size1 || nc != matrix->size2)
6549 ERRMSG("Error reading file header!");
6550
6551 /* Read data... */
6552 NC(nc_inq_varid(ncid, "matrix", &varid));
6553 for (size_t i = 0; i < nr; i++)
6554 for (size_t j = 0; j < nc; j++) {
6555 double value;
6556 size_t start[3] = { (size_t) dataset, i, j };
6557 size_t count[3] = { 1, 1, 1 };
6558 NC(nc_get_vara_double(ncid, varid, start, count, &value));
6559 gsl_matrix_set(matrix, i, j, value);
6560 }
6561
6562 /* Close file... */
6563 NC(nc_close(ncid));
6564}

◆ 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 6568 of file jurassic.c.

6573 {
6574
6575 /* Set filename... */
6576 char file[LEN];
6577 if (dirname != NULL)
6578 sprintf(file, "%s/%s", dirname, filename);
6579 else
6580 sprintf(file, "%s", filename);
6581
6582 /* Write info... */
6583 LOG(1, "Read observation data: %s", file);
6584
6585 /* Read ASCII data... */
6586 if (ctl->obsfmt == 1)
6587 read_obs_asc(file, ctl, obs);
6588
6589 /* Read binary data... */
6590 else if (ctl->obsfmt == 2)
6591 read_obs_bin(file, ctl, obs);
6592
6593 /* Read netCDF data... */
6594 else if (ctl->obsfmt == 3)
6595 read_obs_nc(file, ctl, obs, profile);
6596
6597 /* Check number of points... */
6598 if (obs->nr < 1)
6599 ERRMSG("Could not read any data!");
6600
6601 /* Write info... */
6602 double mini, maxi;
6603 LOG(2, "Number of ray paths: %d", obs->nr);
6604 gsl_stats_minmax(&mini, &maxi, obs->time, 1, (size_t) obs->nr);
6605 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
6606 gsl_stats_minmax(&mini, &maxi, obs->obsz, 1, (size_t) obs->nr);
6607 LOG(2, "Observer altitude range: %g ... %g km", mini, maxi);
6608 gsl_stats_minmax(&mini, &maxi, obs->obslon, 1, (size_t) obs->nr);
6609 LOG(2, "Observer longitude range: %g ... %g deg", mini, maxi);
6610 gsl_stats_minmax(&mini, &maxi, obs->obslat, 1, (size_t) obs->nr);
6611 LOG(2, "Observer latitude range: %g ... %g deg", mini, maxi);
6612 gsl_stats_minmax(&mini, &maxi, obs->vpz, 1, (size_t) obs->nr);
6613 LOG(2, "View point altitude range: %g ... %g km", mini, maxi);
6614 gsl_stats_minmax(&mini, &maxi, obs->vplon, 1, (size_t) obs->nr);
6615 LOG(2, "View point longitude range: %g ... %g deg", mini, maxi);
6616 gsl_stats_minmax(&mini, &maxi, obs->vplat, 1, (size_t) obs->nr);
6617 LOG(2, "View point latitude range: %g ... %g deg", mini, maxi);
6618 gsl_stats_minmax(&mini, &maxi, obs->tpz, 1, (size_t) obs->nr);
6619 LOG(2, "Tangent point altitude range: %g ... %g km", mini, maxi);
6620 gsl_stats_minmax(&mini, &maxi, obs->tplon, 1, (size_t) obs->nr);
6621 LOG(2, "Tangent point longitude range: %g ... %g deg", mini, maxi);
6622 gsl_stats_minmax(&mini, &maxi, obs->tplat, 1, (size_t) obs->nr);
6623 LOG(2, "Tangent point latitude range: %g ... %g deg", mini, maxi);
6624 for (int id = 0; id < ctl->nd; id++) {
6625 gsl_stats_minmax(&mini, &maxi, obs->rad[id], 1, (size_t) obs->nr);
6626 if (ctl->write_bbt) {
6627 LOG(2, "Brightness temperature (%.4f cm^-1) range: %g ... %g K",
6628 ctl->nu[id], mini, maxi);
6629 } else {
6630 LOG(2, "Radiance (%.4f cm^-1) range: %g ... %g W/(m^2 sr cm^-1)",
6631 ctl->nu[id], mini, maxi);
6632 }
6633 }
6634 for (int id = 0; id < ctl->nd; id++) {
6635 gsl_stats_minmax(&mini, &maxi, obs->tau[id], 1, (size_t) obs->nr);
6636 LOG(2, "Transmittance (%.4f cm^-1) range: %g ... %g",
6637 ctl->nu[id], mini, maxi);
6638 }
6639}
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:6687
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:6765
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:6643
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 6643 of file jurassic.c.

6646 {
6647
6648 /* Init... */
6649 obs->nr = 0;
6650
6651 /* Open file... */
6652 FILE *in;
6653 if (!(in = fopen(filename, "r")))
6654 ERRMSG("Cannot open file!");
6655
6656 /* Read line... */
6657 char line[LEN], *tok;
6658 while (fgets(line, LEN, in)) {
6659
6660 /* Read data... */
6661 TOK(line, tok, "%lg", obs->time[obs->nr]);
6662 TOK(NULL, tok, "%lg", obs->obsz[obs->nr]);
6663 TOK(NULL, tok, "%lg", obs->obslon[obs->nr]);
6664 TOK(NULL, tok, "%lg", obs->obslat[obs->nr]);
6665 TOK(NULL, tok, "%lg", obs->vpz[obs->nr]);
6666 TOK(NULL, tok, "%lg", obs->vplon[obs->nr]);
6667 TOK(NULL, tok, "%lg", obs->vplat[obs->nr]);
6668 TOK(NULL, tok, "%lg", obs->tpz[obs->nr]);
6669 TOK(NULL, tok, "%lg", obs->tplon[obs->nr]);
6670 TOK(NULL, tok, "%lg", obs->tplat[obs->nr]);
6671 for (int id = 0; id < ctl->nd; id++)
6672 TOK(NULL, tok, "%lg", obs->rad[id][obs->nr]);
6673 for (int id = 0; id < ctl->nd; id++)
6674 TOK(NULL, tok, "%lg", obs->tau[id][obs->nr]);
6675
6676 /* Increment counter... */
6677 if ((++obs->nr) > NR)
6678 ERRMSG("Too many rays!");
6679 }
6680
6681 /* Close file... */
6682 fclose(in);
6683}

◆ 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 6687 of file jurassic.c.

6690 {
6691
6692 /* Open file... */
6693 FILE *in;
6694 if (!(in = fopen(filename, "r")))
6695 ERRMSG("Cannot open file!");
6696
6697 /* Read header... */
6698 char magic[4];
6699 FREAD(magic, char,
6700 4,
6701 in);
6702 if (memcmp(magic, "OBS1", 4) != 0)
6703 ERRMSG("Invalid magic string!");
6704
6705 int nd;
6706 FREAD(&nd, int,
6707 1,
6708 in);
6709 if (nd != ctl->nd)
6710 ERRMSG("Error reading file header!");
6711
6712 /* Read data... */
6713 size_t nr;
6714 FREAD(&nr, size_t,
6715 1,
6716 in);
6717 obs->nr = (int) nr;
6718 if (obs->nr > NR)
6719 ERRMSG("Too many ray paths!");
6720 FREAD(obs->time, double,
6721 nr,
6722 in);
6723 FREAD(obs->obsz, double,
6724 nr,
6725 in);
6726 FREAD(obs->obslon, double,
6727 nr,
6728 in);
6729 FREAD(obs->obslat, double,
6730 nr,
6731 in);
6732 FREAD(obs->vpz, double,
6733 nr,
6734 in);
6735 FREAD(obs->vplon, double,
6736 nr,
6737 in);
6738 FREAD(obs->vplat, double,
6739 nr,
6740 in);
6741 FREAD(obs->tpz, double,
6742 nr,
6743 in);
6744 FREAD(obs->tplon, double,
6745 nr,
6746 in);
6747 FREAD(obs->tplat, double,
6748 nr,
6749 in);
6750 for (int id = 0; id < ctl->nd; id++)
6751 FREAD(obs->rad[id], double,
6752 nr,
6753 in);
6754 for (int id = 0; id < ctl->nd; id++)
6755 FREAD(obs->tau[id], double,
6756 nr,
6757 in);
6758
6759 /* Close file... */
6760 fclose(in);
6761}

◆ 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 6765 of file jurassic.c.

6769 {
6770
6771 int ncid, var_nray = -1, var_time = -1, var_obsz = -1, var_obslon =
6772 -1, var_obslat = -1, var_vpz = -1, var_vplon = -1, var_vplat =
6773 -1, var_tpz = -1, var_tplon = -1, var_tplat =
6774 -1, var_rad[ND], var_tau[ND];
6775 const char *spec_prefix = ctl->write_bbt ? "bt" : "rad";
6776
6777 /* Open file... */
6778 NC(nc_open(filename, NC_NOWRITE, &ncid));
6779
6780 /* Initialize hyperslab... */
6781 size_t start[2] = { (size_t) profile, 0 };
6782 size_t count[2] = { 1, 0 };
6783
6784 /* Read nray(profile) -> obs->nr */
6785 NC(nc_inq_varid(ncid, "nray", &var_nray));
6786 NC(nc_get_vara_int(ncid, var_nray, start, count, &obs->nr));
6787 if (obs->nr < 1 || obs->nr > NR)
6788 ERRMSG("Number of ray paths out of range!");
6789
6790 /* Update hyperslab... */
6791 count[1] = (size_t) obs->nr;
6792
6793 /* Inquire geometry variables... */
6794 NC(nc_inq_varid(ncid, "time", &var_time));
6795 NC(nc_inq_varid(ncid, "obs_z", &var_obsz));
6796 NC(nc_inq_varid(ncid, "obs_lon", &var_obslon));
6797 NC(nc_inq_varid(ncid, "obs_lat", &var_obslat));
6798
6799 NC(nc_inq_varid(ncid, "vp_z", &var_vpz));
6800 NC(nc_inq_varid(ncid, "vp_lon", &var_vplon));
6801 NC(nc_inq_varid(ncid, "vp_lat", &var_vplat));
6802
6803 NC(nc_inq_varid(ncid, "tp_z", &var_tpz));
6804 NC(nc_inq_varid(ncid, "tp_lon", &var_tplon));
6805 NC(nc_inq_varid(ncid, "tp_lat", &var_tplat));
6806
6807 /* Inquire spectral variables per channel... */
6808 for (int id = 0; id < ctl->nd; id++) {
6809 char varname[LEN];
6810
6811 sprintf(varname, "%s_%.4f", spec_prefix, ctl->nu[id]);
6812 NC(nc_inq_varid(ncid, varname, &var_rad[id]));
6813
6814 sprintf(varname, "tau_%.4f", ctl->nu[id]);
6815 NC(nc_inq_varid(ncid, varname, &var_tau[id]));
6816 }
6817
6818 /* Read geometry... */
6819 NC(nc_get_vara_double(ncid, var_time, start, count, obs->time));
6820 NC(nc_get_vara_double(ncid, var_obsz, start, count, obs->obsz));
6821 NC(nc_get_vara_double(ncid, var_obslon, start, count, obs->obslon));
6822 NC(nc_get_vara_double(ncid, var_obslat, start, count, obs->obslat));
6823
6824 NC(nc_get_vara_double(ncid, var_vpz, start, count, obs->vpz));
6825 NC(nc_get_vara_double(ncid, var_vplon, start, count, obs->vplon));
6826 NC(nc_get_vara_double(ncid, var_vplat, start, count, obs->vplat));
6827
6828 NC(nc_get_vara_double(ncid, var_tpz, start, count, obs->tpz));
6829 NC(nc_get_vara_double(ncid, var_tplon, start, count, obs->tplon));
6830 NC(nc_get_vara_double(ncid, var_tplat, start, count, obs->tplat));
6831
6832 /* Read radiance and transmittance... */
6833 for (int id = 0; id < ctl->nd; id++) {
6834 NC(nc_get_vara_double(ncid, var_rad[id], start, count, obs->rad[id]));
6835 NC(nc_get_vara_double(ncid, var_tau[id], start, count, obs->tau[id]));
6836 }
6837
6838 /* Close file... */
6839 NC(nc_close(ncid));
6840}

◆ 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 6844 of file jurassic.c.

6849 {
6850
6851 double *nurfm, *spec;
6852
6853 int npts;
6854
6855 /* Allocate... */
6856 ALLOC(nurfm, double,
6857 RFMNPTS);
6858 ALLOC(spec, double,
6859 RFMNPTS);
6860
6861 /* Search and read RFM spectrum... */
6862 char filename[LEN];
6863 find_rfm_file(filename, basename, z);
6864 read_rfm_spec(filename, nurfm, spec, &npts);
6865
6866 /* Convolute... */
6867 const double result = convolve_rfm(nurfm, spec, npts, nu, f, n);
6868
6869 /* Free... */
6870 free(nurfm);
6871 free(spec);
6872
6873 return result;
6874}

◆ 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 6878 of file jurassic.c.

6882 {
6883
6884 /* Iteration control... */
6885 ret->kernel_recomp =
6886 (int) scan_ctl(argc, argv, "KERNEL_RECOMP", -1, "3", NULL);
6887 ret->conv_itmax = (int) scan_ctl(argc, argv, "CONV_ITMAX", -1, "30", NULL);
6888 ret->conv_dmin = scan_ctl(argc, argv, "CONV_DMIN", -1, "0.1", NULL);
6889
6890 /* Error analysis... */
6891 ret->err_ana = (int) scan_ctl(argc, argv, "ERR_ANA", -1, "0", NULL);
6892
6893 for (int id = 0; id < ctl->nd; id++)
6894 ret->err_formod[id] = scan_ctl(argc, argv, "ERR_FORMOD", id, "0", NULL);
6895
6896 for (int id = 0; id < ctl->nd; id++)
6897 ret->err_noise[id] = scan_ctl(argc, argv, "ERR_NOISE", id, "0", NULL);
6898
6899 ret->err_press = scan_ctl(argc, argv, "ERR_PRESS", -1, "0", NULL);
6900 ret->err_press_cz = scan_ctl(argc, argv, "ERR_PRESS_CZ", -1, "-999", NULL);
6901 ret->err_press_ch = scan_ctl(argc, argv, "ERR_PRESS_CH", -1, "-999", NULL);
6902
6903 ret->err_temp = scan_ctl(argc, argv, "ERR_TEMP", -1, "0", NULL);
6904 ret->err_temp_cz = scan_ctl(argc, argv, "ERR_TEMP_CZ", -1, "-999", NULL);
6905 ret->err_temp_ch = scan_ctl(argc, argv, "ERR_TEMP_CH", -1, "-999", NULL);
6906
6907 for (int ig = 0; ig < ctl->ng; ig++) {
6908 ret->err_q[ig] = scan_ctl(argc, argv, "ERR_Q", ig, "0", NULL);
6909 ret->err_q_cz[ig] = scan_ctl(argc, argv, "ERR_Q_CZ", ig, "-999", NULL);
6910 ret->err_q_ch[ig] = scan_ctl(argc, argv, "ERR_Q_CH", ig, "-999", NULL);
6911 }
6912
6913 for (int iw = 0; iw < ctl->nw; iw++) {
6914 ret->err_k[iw] = scan_ctl(argc, argv, "ERR_K", iw, "0", NULL);
6915 ret->err_k_cz[iw] = scan_ctl(argc, argv, "ERR_K_CZ", iw, "-999", NULL);
6916 ret->err_k_ch[iw] = scan_ctl(argc, argv, "ERR_K_CH", iw, "-999", NULL);
6917 }
6918
6919 ret->err_clz = scan_ctl(argc, argv, "ERR_CLZ", -1, "0", NULL);
6920 ret->err_cldz = scan_ctl(argc, argv, "ERR_CLDZ", -1, "0", NULL);
6921 for (int icl = 0; icl < ctl->ncl; icl++)
6922 ret->err_clk[icl] = scan_ctl(argc, argv, "ERR_CLK", icl, "0", NULL);
6923
6924 ret->err_sft = scan_ctl(argc, argv, "ERR_SFT", -1, "0", NULL);
6925 for (int isf = 0; isf < ctl->nsf; isf++)
6926 ret->err_sfeps[isf] = scan_ctl(argc, argv, "ERR_SFEPS", isf, "0", NULL);
6927
6928 /* Shared retrieval I/O... */
6929 ret->shared_io_profile = 0;
6930 scan_ctl(argc, argv, "SHARED_IO_PROFLIST", -1, "-",
6931 ret->shared_io_proflist);
6932 scan_ctl(argc, argv, "SHARED_IO_ATM_APR_FILE", -1, "-",
6934 scan_ctl(argc, argv, "SHARED_IO_OBS_MEAS_FILE", -1, "-",
6936 scan_ctl(argc, argv, "SHARED_IO_ATM_FINAL_FILE", -1, "-",
6938 scan_ctl(argc, argv, "SHARED_IO_OBS_FINAL_FILE", -1, "-",
6940 scan_ctl(argc, argv, "SHARED_IO_MATRIX_COV_APR_FILE", -1, "-",
6942 scan_ctl(argc, argv, "SHARED_IO_MATRIX_KERNEL_FILE", -1, "-",
6944 scan_ctl(argc, argv, "SHARED_IO_MATRIX_COV_RET_FILE", -1, "-",
6946 scan_ctl(argc, argv, "SHARED_IO_MATRIX_CORR_FILE", -1, "-",
6948 scan_ctl(argc, argv, "SHARED_IO_MATRIX_GAIN_FILE", -1, "-",
6950 scan_ctl(argc, argv, "SHARED_IO_MATRIX_AVK_FILE", -1, "-",
6952 scan_ctl(argc, argv, "SHARED_IO_ATM_ERR_TOTAL_FILE", -1, "-",
6954 scan_ctl(argc, argv, "SHARED_IO_ATM_ERR_NOISE_FILE", -1, "-",
6956 scan_ctl(argc, argv, "SHARED_IO_ATM_ERR_FORMOD_FILE", -1, "-",
6958 scan_ctl(argc, argv, "SHARED_IO_ATM_CONT_FILE", -1, "-",
6960 scan_ctl(argc, argv, "SHARED_IO_ATM_RES_FILE", -1, "-",
6962}
double err_press_cz
Vertical correlation length for pressure error [km].
Definition: jurassic.h:1906
double err_press
Pressure error [%].
Definition: jurassic.h:1903
double err_k_cz[NW]
Vertical correlation length for extinction error [km].
Definition: jurassic.h:1933
double err_k_ch[NW]
Horizontal correlation length for extinction error [km].
Definition: jurassic.h:1936
double err_temp_cz
Vertical correlation length for temperature error [km].
Definition: jurassic.h:1915
double err_formod[ND]
Forward model error [%].
Definition: jurassic.h:1897
double err_temp
Temperature error [K].
Definition: jurassic.h:1912
double err_q_cz[NG]
Vertical correlation length for volume mixing ratio error [km].
Definition: jurassic.h:1924
char shared_io_proflist[LEN]
Optional file containing retrieval profile indices.
Definition: jurassic.h:1957
double err_noise[ND]
Noise error [W/(m^2 sr cm^-1)].
Definition: jurassic.h:1900
double err_clz
Cloud height error [km].
Definition: jurassic.h:1939
double err_sft
Surface temperature error [K].
Definition: jurassic.h:1948
double err_clk[NCL]
Cloud extinction error [km^-1].
Definition: jurassic.h:1945
char shared_io_obs_meas_file[LEN]
Optional shared measured-observation input file.
Definition: jurassic.h:1963
char shared_io_atm_apr_file[LEN]
Optional shared atmospheric a priori input file.
Definition: jurassic.h:1960
double err_temp_ch
Horizontal correlation length for temperature error [km].
Definition: jurassic.h:1918
char shared_io_atm_err_formod_file[LEN]
Optional shared forward-model retrieval-error output file.
Definition: jurassic.h:1996
double err_cldz
Cloud depth error [km].
Definition: jurassic.h:1942
double err_press_ch
Horizontal correlation length for pressure error [km].
Definition: jurassic.h:1909
double err_q_ch[NG]
Horizontal correlation length for volume mixing ratio error [km].
Definition: jurassic.h:1927
char shared_io_atm_err_total_file[LEN]
Optional shared total retrieval-error output file.
Definition: jurassic.h:1990
double err_q[NG]
Volume mixing ratio error [%].
Definition: jurassic.h:1921
char shared_io_atm_err_noise_file[LEN]
Optional shared noise retrieval-error output file.
Definition: jurassic.h:1993
double err_sfeps[NSF]
Surface emissivity error.
Definition: jurassic.h:1951
int shared_io_profile
Profile index used for shared netCDF retrieval inputs and outputs.
Definition: jurassic.h:1954
double err_k[NW]
Extinction error [km^-1].
Definition: jurassic.h:1930
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.
  • Requires at least two spectral points.
  • 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 6966 of file jurassic.c.

6970 {
6971
6972 char *line = NULL, *tok;
6973
6974 size_t line_buf_size = 0;
6975
6976 double dnu, nu0, nu1;
6977
6978 int ipts = 0;
6979
6980 /* Write info... */
6981 LOG(1, "Read RFM data: %s", filename);
6982
6983 /* Open file... */
6984 FILE *in;
6985 if (!(in = fopen(filename, "r")))
6986 ERRMSG("Cannot open file!");
6987
6988 /* Read header... */
6989 for (int i = 0; i < 4; i++)
6990 if (getline(&line, &line_buf_size, in) == -1)
6991 ERRMSG("Error while reading file header!");
6992 if (sscanf(line, "%d %lg %lg %lg", npts, &nu0, &dnu, &nu1) != 4)
6993 ERRMSG("Invalid spectrum header format!");
6994
6995 /* Check number of spectral grid points... */
6996 if (*npts < 2)
6997 ERRMSG("RFM spectrum must contain at least two spectral points!");
6998 if (*npts > RFMNPTS)
6999 ERRMSG("Too many spectral grid points!");
7000
7001 /* Read radiance data... */
7002 while (getline(&line, &line_buf_size, in) != -1 && ipts < *npts) {
7003 tok = strtok(line, " \t\n");
7004 while (tok != NULL && ipts < *npts) {
7005 if (sscanf(tok, "%lg", &rad[ipts]) == 1)
7006 ipts++;
7007 tok = strtok(NULL, " \t\n");
7008 }
7009 }
7010
7011 /* Check number of spectral grid points... */
7012 if (ipts != *npts)
7013 ERRMSG("Error while reading RFM data!");
7014
7015 /* Compute wavenumbers... */
7016 for (ipts = 0; ipts < *npts; ipts++)
7017 nu[ipts] = LIN(0.0, nu0, (double) (*npts - 1), nu1, (double) ipts);
7018
7019 /* Close file... */
7020 fclose(in);
7021
7022 /* Free.. */
7023 free(line);
7024}

◆ 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 7028 of file jurassic.c.

7032 {
7033
7034 char line[LEN];
7035
7036 /* Write info... */
7037 LOG(1, "Read shape function: %s", filename);
7038
7039 /* Open file... */
7040 FILE *in;
7041 if (!(in = fopen(filename, "r")))
7042 ERRMSG("Cannot open file!");
7043
7044 /* Read data... */
7045 *n = 0;
7046 while (fgets(line, LEN, in))
7047 if (sscanf(line, "%lg %lg", &x[*n], &y[*n]) == 2)
7048 if ((++(*n)) > NSHAPE)
7049 ERRMSG("Too many data points!");
7050
7051 /* Close file... */
7052 fclose(in);
7053
7054 /* Check number of data points... */
7055 if (*n < 2)
7056 ERRMSG("Could not read any data!");
7057
7058 /* Write info... */
7059 double mini, maxi;
7060 LOG(2, "Number of data points: %d", *n);
7061 gsl_stats_minmax(&mini, &maxi, x, 1, (size_t) *n);
7062 LOG(2, "Range of x values: %.4f ... %.4f", mini, maxi);
7063 gsl_stats_minmax(&mini, &maxi, y, 1, (size_t) *n);
7064 LOG(2, "Range of y values: %g ... %g", mini, maxi);
7065}

◆ 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 7069 of file jurassic.c.

7070 {
7071
7072 /* Allocate... */
7073 tbl_t *tbl;
7074 ALLOC(tbl, tbl_t, 1);
7075
7076 /* Initialize filter function sizes... */
7077 for (int id = 0; id < ctl->nd; id++)
7078 tbl->filt_n[id] = 0;
7079
7080 /* Loop over trace gases... */
7081 for (int ig = 0; ig < ctl->ng; ig++) {
7082
7083 /* Read ASCII look-up tables... */
7084 if (ctl->tblfmt == 1)
7085 for (int id = 0; id < ctl->nd; id++) {
7086 read_tbl_asc(ctl, tbl, id, ig);
7087 TBL_LOG(tbl, id, ig);
7088 }
7089
7090 /* Read binary look-up tables... */
7091 else if (ctl->tblfmt == 2)
7092 for (int id = 0; id < ctl->nd; id++) {
7093 read_tbl_bin(ctl, tbl, id, ig);
7094 TBL_LOG(tbl, id, ig);
7095 }
7096
7097 /* Read netCDF look-up tables... */
7098 else if (ctl->tblfmt == 3) {
7099
7100 /* Open file... */
7101 int ncid;
7102 char filename[2 * LEN];
7103 sprintf(filename, "%s_%s.nc", ctl->tblbase, ctl->emitter[ig]);
7104 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7105 WARN("Missing emissivity table: %s", filename);
7106 continue;
7107 } else
7108 LOG(1, "Read emissivity table: %s", filename);
7109
7110 /* Read channels... */
7111 for (int id = 0; id < ctl->nd; id++) {
7112 read_tbl_nc_channel(ctl, tbl, id, ig, ncid);
7113 TBL_LOG(tbl, id, ig);
7114 }
7115
7116 /* Close file... */
7117 NC(nc_close(ncid));
7118 }
7119 }
7120
7121 /* Calculate log-pressure... */
7122 for (int id = 0; id < ctl->nd; id++)
7123 for (int ig = 0; ig < ctl->ng; ig++)
7124 for (int ip = 0; ip < tbl->np[id][ig]; ip++)
7125 tbl->lnp[id][ig][ip] = log(tbl->p[id][ig][ip]);
7126
7127 /* Read filter functions... */
7128 if (ctl->tblfmt == 1)
7129 for (int id = 0; id < ctl->nd; id++) {
7130 char filename[2 * LEN];
7131 sprintf(filename, "%s_%.4f.filt", ctl->tblbase, ctl->nu[id]);
7132 read_shape(filename, tbl->filt_nu[id], tbl->filt_f[id],
7133 &tbl->filt_n[id]);
7134 }
7135
7136 /* Initialize source function lookup tables... */
7137 init_srcfunc(ctl, tbl);
7138
7139 /* Return pointer... */
7140 return tbl;
7141}
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:7268
void init_srcfunc(const ctl_t *ctl, tbl_t *tbl)
Initialize source function lookup tables from emissivity data.
Definition: jurassic.c:4700
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:7145
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:7312
#define TBL_LOG(tbl, id, ig)
Log detailed statistics of an emissivity look-up table.
Definition: jurassic.h:1249
Emissivity look-up tables.
Definition: jurassic.h:2012
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 7145 of file jurassic.c.

7149 {
7150
7151 /* Initialize... */
7152 double eps, eps_old = -999, press, press_old = -999, temp,
7153 temp_old = -999, u, u_old = -999;
7154 int nrange = 0;
7155
7156 /* Set filename... */
7157 char filename[2 * LEN];
7158 sprintf(filename, "%s_%.4f_%s.tab", ctl->tblbase,
7159 ctl->nu[id], ctl->emitter[ig]);
7160
7161 /* Open file... */
7162 FILE *in;
7163 if (!(in = fopen(filename, "r"))) {
7164 WARN("Missing emissivity table: %s", filename);
7165 return;
7166 } else
7167 LOG(1, "Read emissivity table: %s", filename);
7168
7169 /* Init pressure level counter... */
7170 tbl->np[id][ig] = -1;
7171
7172 /* Read data... */
7173 char line[LEN];
7174 while (fgets(line, LEN, in)) {
7175
7176 /* Parse line... */
7177 if (sscanf(line, "%lg %lg %lg %lg", &press, &temp, &u, &eps) != 4)
7178 continue;
7179
7180 /* Check ranges... */
7181 if (u < UMIN || u > UMAX || eps < EPSMIN || eps > EPSMAX) {
7182 nrange++;
7183 continue;
7184 }
7185
7186 /* Determine pressure index... */
7187 if (press != press_old) {
7188 press_old = press;
7189 if ((++tbl->np[id][ig]) >= TBLNP)
7190 ERRMSG("Too many pressure levels!");
7191 tbl->nt[id][ig][tbl->np[id][ig]] = -1;
7192 }
7193
7194 /* Determine temperature index... */
7195 if (temp != temp_old) {
7196 temp_old = temp;
7197 if ((++tbl->nt[id][ig][tbl->np[id][ig]]) >= TBLNT)
7198 ERRMSG("Too many temperatures!");
7199 tbl->nu[id][ig][tbl->np[id][ig]]
7200 [tbl->nt[id][ig][tbl->np[id][ig]]] = -1;
7201
7202 /* Reset dynamic arrays for this (ip,it) node... */
7203 tbl->logu[id][ig][tbl->np[id][ig]]
7204 [tbl->nt[id][ig][tbl->np[id][ig]]] = NULL;
7205 tbl->logeps[id][ig][tbl->np[id][ig]]
7206 [tbl->nt[id][ig][tbl->np[id][ig]]] = NULL;
7207 }
7208
7209 /* Determine column density index... */
7210 if ((eps > eps_old && u > u_old) || tbl->nu[id][ig][tbl->np[id][ig]]
7211 [tbl->nt[id][ig][tbl->np[id][ig]]] < 0) {
7212 eps_old = eps;
7213 u_old = u;
7214 if ((++tbl->nu[id][ig][tbl->np[id][ig]]
7215 [tbl->nt[id][ig][tbl->np[id][ig]]]) >= TBLNU)
7216 ERRMSG("Too many column densities!");
7217
7218 /* Grow dynamic arrays (nu is used as an index during reading). */
7219 const int ip = tbl->np[id][ig];
7220 const int it = tbl->nt[id][ig][ip];
7221 const int iu = tbl->nu[id][ig][ip][it];
7222 const size_t nnew = (size_t) (iu + 1);
7223
7224 float *tmp = (float *) realloc(tbl->logu[id][ig][ip][it],
7225 nnew * sizeof(float));
7226 if (!tmp)
7227 ERRMSG("Out of memory!");
7228 tbl->logu[id][ig][ip][it] = tmp;
7229
7230 tmp =
7231 (float *) realloc(tbl->logeps[id][ig][ip][it], nnew * sizeof(float));
7232 if (!tmp)
7233 ERRMSG("Out of memory!");
7234 tbl->logeps[id][ig][ip][it] = tmp;
7235 }
7236
7237 /* Store data... */
7238 tbl->p[id][ig][tbl->np[id][ig]] = press;
7239 tbl->t[id][ig][tbl->np[id][ig]][tbl->nt[id][ig][tbl->np[id][ig]]]
7240 = temp;
7241 tbl->logu[id][ig][tbl->np[id][ig]][tbl->nt[id][ig][tbl->np[id][ig]]]
7242 [tbl->nu[id][ig][tbl->np[id][ig]]
7243 [tbl->nt[id][ig][tbl->np[id][ig]]]] = (float) log(u);
7244 tbl->logeps[id][ig][tbl->np[id][ig]][tbl->nt[id][ig][tbl->np[id][ig]]]
7245 [tbl->nu[id][ig][tbl->np[id][ig]]
7246 [tbl->nt[id][ig][tbl->np[id][ig]]]] = (float) log(eps);
7247 }
7248
7249 /* Increment counters... */
7250 tbl->np[id][ig]++;
7251 for (int ip = 0; ip < tbl->np[id][ig]; ip++) {
7252 tbl->nt[id][ig][ip]++;
7253 for (int it = 0; it < tbl->nt[id][ig][ip]; it++)
7254 tbl->nu[id][ig][ip][it]++;
7255 }
7256
7257 /* Check ranges... */
7258 if (nrange > 0)
7259 WARN("Column density or emissivity out of range (%d data points)!",
7260 nrange);
7261
7262 /* Close file... */
7263 fclose(in);
7264}
#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:447
#define TBLNT
Maximum number of temperatures in emissivity tables.
Definition: jurassic.h:442
#define EPSMAX
Maximum emissivity.
Definition: jurassic.h:187
#define TBLNP
Maximum number of pressure levels in emissivity tables.
Definition: jurassic.h:432

◆ 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 7268 of file jurassic.c.

7272 {
7273
7274 /* Set filename... */
7275 char filename[2 * LEN];
7276 sprintf(filename, "%s_%.4f_%s.bin",
7277 ctl->tblbase, ctl->nu[id], ctl->emitter[ig]);
7278
7279 /* Open file... */
7280 FILE *in = fopen(filename, "rb");
7281 if (!in) {
7282 WARN("Missing emissivity table: %s", filename);
7283 return;
7284 } else
7285 LOG(1, "Read emissivity table: %s", filename);
7286
7287 /* Read length.. */
7288 size_t nbytes;
7289 FREAD(&nbytes, size_t,
7290 1,
7291 in);
7292 if (nbytes <= 0)
7293 ERRMSG("Invalid packed table size!");
7294
7295 /* Read packed blob... */
7296 uint8_t *work = NULL;
7297 ALLOC(work, uint8_t, nbytes);
7298 FREAD(work, uint8_t, nbytes, in);
7299
7300 /* Unpack... */
7301 tbl_unpack(tbl, id, ig, work);
7302
7303 /* Close file... */
7304 fclose(in);
7305
7306 /* Free... */
7307 free(work);
7308}
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:7866
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 7312 of file jurassic.c.

7317 {
7318
7319 char varname[LEN];
7320
7321 int varid, dimid;
7322
7323 size_t nbytes;
7324
7325 /* Inquire variable... */
7326 sprintf(varname, "tbl_%.4f", ctl->nu[id]);
7327 if (nc_inq_varid(ncid, varname, &varid) != NC_NOERR) {
7328 WARN("Missing emissivity table: %s", varname);
7329 return;
7330 } else
7331 LOG(1, "Read emissivity table: %s", varname);
7332 NC(nc_inq_vardimid(ncid, varid, &dimid));
7333 NC(nc_inq_dimlen(ncid, dimid, &nbytes));
7334
7335 /* Read variable... */
7336 uint8_t *work = NULL;
7337 ALLOC(work, uint8_t, nbytes);
7338 NC(nc_get_var_uchar(ncid, varid, (unsigned char *) work));
7339
7340 /* Unpack... */
7341 tbl_unpack(tbl, id, ig, work);
7342
7343 /* Free... */
7344 free(work);
7345}
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 7349 of file jurassic.c.

7355 {
7356
7357 char dummy[LEN], fullname1[LEN], fullname2[LEN], line[LEN],
7358 rvarname[LEN], rval[LEN];
7359
7360 int contain = 0;
7361
7362 /* Open file... */
7363 FILE *in = NULL;
7364 if (argv[1][0] != '-')
7365 if (!(in = fopen(argv[1], "r")))
7366 ERRMSG("Cannot open file!");
7367
7368 /* Set full variable name... */
7369 if (arridx >= 0) {
7370 sprintf(fullname1, "%s[%d]", varname, arridx);
7371 sprintf(fullname2, "%s[*]", varname);
7372 } else {
7373 sprintf(fullname1, "%s", varname);
7374 sprintf(fullname2, "%s", varname);
7375 }
7376
7377 /* Read data... */
7378 if (in != NULL)
7379 while (fgets(line, LEN, in))
7380 if (sscanf(line, "%s %s %s", rvarname, dummy, rval) == 3)
7381 if (strcasecmp(rvarname, fullname1) == 0 ||
7382 strcasecmp(rvarname, fullname2) == 0) {
7383 contain = 1;
7384 break;
7385 }
7386 for (int i = 1; i < argc - 1; i++)
7387 if (strcasecmp(argv[i], fullname1) == 0 ||
7388 strcasecmp(argv[i], fullname2) == 0) {
7389 sprintf(rval, "%s", argv[i + 1]);
7390 contain = 1;
7391 break;
7392 }
7393
7394 /* Close file... */
7395 if (in != NULL)
7396 fclose(in);
7397
7398 /* Check for missing variables... */
7399 if (!contain) {
7400 if (strlen(defvalue) > 0)
7401 sprintf(rval, "%s", defvalue);
7402 else
7403 ERRMSG("Missing variable %s!\n", fullname1);
7404 }
7405
7406 /* Write info... */
7407 LOG(1, "%s = %s", fullname1, rval);
7408
7409 /* Return values... */
7410 if (value != NULL)
7411 sprintf(value, "%s", rval);
7412 return atof(rval);
7413}

◆ 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 7417 of file jurassic.c.

7423 {
7424
7425 /* Get sizes... */
7426 const size_t n = s_a->size1;
7427
7428 /* Allocate... */
7429 gsl_vector *x_a = gsl_vector_alloc(n);
7430
7431 /* Get sigma vector... */
7432 atm2x(ctl, atm, x_a, NULL, NULL);
7433 for (size_t i = 0; i < n; i++) {
7434 if (iqa[i] == IDXP)
7435 gsl_vector_set(x_a, i, ret->err_press / 100 * gsl_vector_get(x_a, i));
7436 if (iqa[i] == IDXT)
7437 gsl_vector_set(x_a, i, ret->err_temp);
7438 for (int ig = 0; ig < ctl->ng; ig++)
7439 if (iqa[i] == IDXQ(ig))
7440 gsl_vector_set(x_a, i, ret->err_q[ig] / 100 * gsl_vector_get(x_a, i));
7441 for (int iw = 0; iw < ctl->nw; iw++)
7442 if (iqa[i] == IDXK(iw))
7443 gsl_vector_set(x_a, i, ret->err_k[iw]);
7444 if (iqa[i] == IDXCLZ)
7445 gsl_vector_set(x_a, i, ret->err_clz);
7446 if (iqa[i] == IDXCLDZ)
7447 gsl_vector_set(x_a, i, ret->err_cldz);
7448 for (int icl = 0; icl < ctl->ncl; icl++)
7449 if (iqa[i] == IDXCLK(icl))
7450 gsl_vector_set(x_a, i, ret->err_clk[icl]);
7451 if (iqa[i] == IDXSFT)
7452 gsl_vector_set(x_a, i, ret->err_sft);
7453 for (int isf = 0; isf < ctl->nsf; isf++)
7454 if (iqa[i] == IDXSFEPS(isf))
7455 gsl_vector_set(x_a, i, ret->err_sfeps[isf]);
7456 }
7457
7458 /* Check standard deviations... */
7459 for (size_t i = 0; i < n; i++)
7460 if (POW2(gsl_vector_get(x_a, i)) <= 0)
7461 ERRMSG("Check a priori data (zero standard deviation)!");
7462
7463 /* Initialize diagonal covariance... */
7464 gsl_matrix_set_zero(s_a);
7465 for (size_t i = 0; i < n; i++)
7466 gsl_matrix_set(s_a, i, i, POW2(gsl_vector_get(x_a, i)));
7467
7468 /* Loop over matrix elements... */
7469 for (size_t i = 0; i < n; i++)
7470 for (size_t j = 0; j < n; j++)
7471 if (i != j && iqa[i] == iqa[j]) {
7472
7473 /* Initialize... */
7474 double cz = 0;
7475 double ch = 0;
7476
7477 /* Set correlation lengths for pressure... */
7478 if (iqa[i] == IDXP) {
7479 cz = ret->err_press_cz;
7480 ch = ret->err_press_ch;
7481 }
7482
7483 /* Set correlation lengths for temperature... */
7484 if (iqa[i] == IDXT) {
7485 cz = ret->err_temp_cz;
7486 ch = ret->err_temp_ch;
7487 }
7488
7489 /* Set correlation lengths for volume mixing ratios... */
7490 for (int ig = 0; ig < ctl->ng; ig++)
7491 if (iqa[i] == IDXQ(ig)) {
7492 cz = ret->err_q_cz[ig];
7493 ch = ret->err_q_ch[ig];
7494 }
7495
7496 /* Set correlation lengths for extinction... */
7497 for (int iw = 0; iw < ctl->nw; iw++)
7498 if (iqa[i] == IDXK(iw)) {
7499 cz = ret->err_k_cz[iw];
7500 ch = ret->err_k_ch[iw];
7501 }
7502
7503 /* Compute correlations... */
7504 if (cz > 0 && ch > 0) {
7505
7506 /* Get Cartesian coordinates... */
7507 double x0[3], x1[3];
7508 geo2cart(0, atm->lon[ipa[i]], atm->lat[ipa[i]], x0);
7509 geo2cart(0, atm->lon[ipa[j]], atm->lat[ipa[j]], x1);
7510
7511 /* Compute correlations... */
7512 const double rho =
7513 exp(-DIST(x0, x1) / ch -
7514 fabs(atm->z[ipa[i]] - atm->z[ipa[j]]) / cz);
7515
7516 /* Set covariance... */
7517 gsl_matrix_set(s_a, i, j, gsl_vector_get(x_a, i)
7518 * gsl_vector_get(x_a, j) * rho);
7519 }
7520 }
7521
7522 /* Free... */
7523 gsl_vector_free(x_a);
7524}
#define DIST(a, b)
Compute Cartesian distance between two 3D vectors.
Definition: jurassic.h:607
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 7528 of file jurassic.c.

7534 {
7535
7536 /* Allocate... */
7537 obs_t *obs_err;
7538 ALLOC(obs_err, obs_t, 1);
7539
7540 /* Get size... */
7541 const size_t m = sig_eps_inv->size;
7542
7543 /* Noise error (always considered in retrieval fit)... */
7544 copy_obs(ctl, obs_err, obs, 1);
7545 for (int ir = 0; ir < obs_err->nr; ir++)
7546 for (int id = 0; id < ctl->nd; id++)
7547 obs_err->rad[id][ir]
7548 = (isfinite(obs->rad[id][ir]) ? ret->err_noise[id] : NAN);
7549 obs2y(ctl, obs_err, sig_noise, NULL, NULL);
7550
7551 /* Forward model error (always considered in retrieval fit)... */
7552 copy_obs(ctl, obs_err, obs, 1);
7553 for (int ir = 0; ir < obs_err->nr; ir++)
7554 for (int id = 0; id < ctl->nd; id++)
7555 obs_err->rad[id][ir]
7556 = fabs(ret->err_formod[id] / 100 * obs->rad[id][ir]);
7557 obs2y(ctl, obs_err, sig_formod, NULL, NULL);
7558
7559 /* Total error... */
7560 for (size_t i = 0; i < m; i++)
7561 gsl_vector_set(sig_eps_inv, i, 1 / sqrt(POW2(gsl_vector_get(sig_noise, i))
7562 +
7563 POW2(gsl_vector_get
7564 (sig_formod, i))));
7565
7566 /* Check standard deviations... */
7567 for (size_t i = 0; i < m; i++)
7568 if (gsl_vector_get(sig_eps_inv, i) <= 0)
7569 ERRMSG("Check measurement errors (zero standard deviation)!");
7570
7571 /* Free... */
7572 free(obs_err);
7573}
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 7577 of file jurassic.c.

7582 {
7583
7584 if (shared_file[0] != '-') {
7585 *dirname = NULL;
7586 *profile = ret->shared_io_profile;
7587 return shared_file;
7588 }
7589
7590 *dirname = ret->dir;
7591 *profile = 0;
7592 return legacy_file;
7593}
char dir[LEN]
Working directory.
Definition: jurassic.h:1882

◆ 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 7597 of file jurassic.c.

7602 {
7603
7604 if (shared_file[0] != '-') {
7605 *dirname = NULL;
7606 *profile = ret->shared_io_profile;
7607 return shared_file;
7608 }
7609
7610 *dirname = ret->dir;
7611 *profile = 0;
7612 return legacy_file;
7613}

◆ 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 7617 of file jurassic.c.

7618 {
7619
7620 const char *base = shared_io_output_file(ret);
7621 if (base == NULL)
7622 return -1;
7623
7624 char lockfile[LEN];
7625 if (snprintf(lockfile, LEN, "%s.lock", base) >= LEN)
7626 ERRMSG("Lock file name too long!");
7627 int fd = open(lockfile, O_CREAT | O_RDWR, 0666);
7628 if (fd < 0)
7629 ERRMSG("Cannot open lock file!");
7630
7631 struct flock fl;
7632 fl.l_type = F_WRLCK;
7633 fl.l_whence = SEEK_SET;
7634 fl.l_start = 0;
7635 fl.l_len = 0;
7636 if (fcntl(fd, F_SETLKW, &fl) < 0)
7637 ERRMSG("Cannot lock shared output file!");
7638
7639 return fd;
7640}
const char * shared_io_output_file(const ret_t *ret)
Return the primary shared retrieval output file configured for locking.
Definition: jurassic.c:7662
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 7644 of file jurassic.c.

7645 {
7646
7647 if (fd < 0)
7648 return;
7649
7650 struct flock fl;
7651 fl.l_type = F_UNLCK;
7652 fl.l_whence = SEEK_SET;
7653 fl.l_start = 0;
7654 fl.l_len = 0;
7655 if (fcntl(fd, F_SETLK, &fl) < 0)
7656 ERRMSG("Cannot unlock shared output file!");
7657 close(fd);
7658}

◆ 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 7662 of file jurassic.c.

7663 {
7664
7665 if (ret->shared_io_atm_final_file[0] != '-')
7666 return ret->shared_io_atm_final_file;
7667 if (ret->shared_io_obs_final_file[0] != '-')
7668 return ret->shared_io_obs_final_file;
7669 if (ret->shared_io_matrix_cov_apr_file[0] != '-')
7671 if (ret->shared_io_matrix_kernel_file[0] != '-')
7672 return ret->shared_io_matrix_kernel_file;
7673 if (ret->shared_io_matrix_cov_ret_file[0] != '-')
7675 if (ret->shared_io_matrix_corr_file[0] != '-')
7676 return ret->shared_io_matrix_corr_file;
7677 if (ret->shared_io_matrix_gain_file[0] != '-')
7678 return ret->shared_io_matrix_gain_file;
7679 if (ret->shared_io_matrix_avk_file[0] != '-')
7680 return ret->shared_io_matrix_avk_file;
7681 if (ret->shared_io_atm_err_total_file[0] != '-')
7682 return ret->shared_io_atm_err_total_file;
7683 if (ret->shared_io_atm_err_noise_file[0] != '-')
7684 return ret->shared_io_atm_err_noise_file;
7685 if (ret->shared_io_atm_err_formod_file[0] != '-')
7687 if (ret->shared_io_atm_cont_file[0] != '-')
7688 return ret->shared_io_atm_cont_file;
7689 if (ret->shared_io_atm_res_file[0] != '-')
7690 return ret->shared_io_atm_res_file;
7691 return NULL;
7692}

◆ 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 7696 of file jurassic.c.

7700 {
7701
7702 /* Find minimum altitude... */
7703 const size_t ip = gsl_stats_min_index(los->z, 1, (size_t) los->np);
7704
7705 /* Nadir or zenith... */
7706 if (ip <= 0 || ip >= (size_t) los->np - 1) {
7707 *tpz = los->z[los->np - 1];
7708 *tplon = los->lon[los->np - 1];
7709 *tplat = los->lat[los->np - 1];
7710 }
7711
7712 /* Limb... */
7713 else {
7714
7715 /* Determine interpolating polynomial y=a*x^2+b*x+c... */
7716 const double yy0 = los->z[ip - 1];
7717 const double yy1 = los->z[ip];
7718 const double yy2 = los->z[ip + 1];
7719 const double x1 = sqrt(POW2(los->ds[ip]) - POW2(yy1 - yy0));
7720 const double x2 = x1 + sqrt(POW2(los->ds[ip + 1]) - POW2(yy2 - yy1));
7721 const double a = 1 / (x1 - x2) * (-(yy0 - yy1) / x1 + (yy0 - yy2) / x2);
7722 const double b = -(yy0 - yy1) / x1 - a * x1;
7723 const double c = yy0;
7724
7725 /* Get tangent point location... */
7726 double dummy, v[3], v0[3], v2[3];
7727 const double x = -b / (2 * a);
7728 *tpz = a * x * x + b * x + c;
7729 geo2cart(los->z[ip - 1], los->lon[ip - 1], los->lat[ip - 1], v0);
7730 geo2cart(los->z[ip + 1], los->lon[ip + 1], los->lat[ip + 1], v2);
7731 for (int i = 0; i < 3; i++)
7732 v[i] = LIN(0.0, v0[i], x2, v2[i], x);
7733 cart2geo(v, &dummy, tplon, tplat);
7734 }
7735}
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 7739 of file jurassic.c.

7741 {
7742
7743 /* Check pointer... */
7744 if (!tbl)
7745 return;
7746
7747 /* Loop over channels and emitters... */
7748 for (int id = 0; id < ctl->nd; id++)
7749 for (int ig = 0; ig < ctl->ng; ig++) {
7750
7751 /* Check number of pressure levels... */
7752 const int np = tbl->np[id][ig];
7753 if (np < 0)
7754 continue;
7755
7756 /* Loop over pressure levels... */
7757 for (int ip = 0; ip < np; ip++) {
7758
7759 /* Loop over temperature levels... */
7760 const int nt = tbl->nt[id][ig][ip];
7761 for (int it = 0; it < nt; it++) {
7762
7763 /* Free... */
7764 free(tbl->logu[id][ig][ip][it]);
7765 free(tbl->logeps[id][ig][ip][it]);
7766 tbl->logu[id][ig][ip][it] = NULL;
7767 tbl->logeps[id][ig][ip][it] = NULL;
7768 }
7769 }
7770 }
7771
7772 /* Free... */
7773 free(tbl);
7774}

◆ 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 7778 of file jurassic.c.

7783 {
7784
7785 uint8_t *cur = buf;
7786
7787 /* Pack lookup table... */
7788 int np = tbl->np[id][ig];
7789 memcpy(cur, &np, sizeof(np));
7790 cur += sizeof(np);
7791
7792 memcpy(cur, tbl->p[id][ig], (size_t) np * sizeof(double));
7793 cur += ((size_t) np * sizeof(double));
7794
7795 for (int ip = 0; ip < np; ip++) {
7796 int nt = tbl->nt[id][ig][ip];
7797 memcpy(cur, &nt, sizeof(nt));
7798 cur += sizeof(nt);
7799
7800 memcpy(cur, tbl->t[id][ig][ip], (size_t) nt * sizeof(double));
7801 cur += ((size_t) nt * sizeof(double));
7802
7803 for (int it = 0; it < nt; it++) {
7804 int nu = tbl->nu[id][ig][ip][it];
7805 memcpy(cur, &nu, sizeof(nu));
7806 cur += sizeof(nu);
7807
7808 memcpy(cur, tbl->logu[id][ig][ip][it], (size_t) nu * sizeof(float));
7809 cur += ((size_t) nu * sizeof(float));
7810
7811 memcpy(cur, tbl->logeps[id][ig][ip][it], (size_t) nu * sizeof(float));
7812 cur += ((size_t) nu * sizeof(float));
7813 }
7814 }
7815
7816 /* Pack filter function... */
7817 const int n = tbl->filt_n[id];
7818 memcpy(cur, &n, sizeof(n));
7819 cur += sizeof(n);
7820
7821 memcpy(cur, tbl->filt_nu[id], (size_t) n * sizeof(double));
7822 cur += ((size_t) n * sizeof(double));
7823
7824 memcpy(cur, tbl->filt_f[id], (size_t) n * sizeof(double));
7825 cur += ((size_t) n * sizeof(double));
7826
7827 *bytes_used = (size_t) (cur - buf);
7828}

◆ 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 7832 of file jurassic.c.

7835 {
7836
7837 size_t bytes = 0;
7838
7839 /* Size of lookup table... */
7840 const int np = tbl->np[id][ig];
7841 bytes += sizeof(int);
7842 bytes += ((size_t) np * sizeof(double));
7843
7844 for (int ip = 0; ip < np; ip++) {
7845 const int nt = tbl->nt[id][ig][ip];
7846 bytes += sizeof(int);
7847 bytes += ((size_t) nt * sizeof(double));
7848
7849 for (int it = 0; it < nt; it++) {
7850 const int nu = tbl->nu[id][ig][ip][it];
7851 bytes += sizeof(int);
7852 bytes += (2 * (size_t) nu * sizeof(float));
7853 }
7854 }
7855
7856 /* Size of filter function... */
7857 const int n = tbl->filt_n[id];
7858 bytes += sizeof(int);
7859 bytes += (2 * (size_t) n * sizeof(double));
7860
7861 return bytes;
7862}

◆ 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 7866 of file jurassic.c.

7870 {
7871
7872 const uint8_t *cur = buf;
7873
7874 /* Unpack lookup table... */
7875 int np;
7876 memcpy(&np, cur, sizeof(np));
7877 cur += sizeof(np);
7878
7879 if (np < 0 || np > TBLNP)
7880 ERRMSG("np out of range!");
7881 tbl->np[id][ig] = np;
7882
7883 memcpy(tbl->p[id][ig], cur, (size_t) np * sizeof(double));
7884 cur += ((size_t) np * sizeof(double));
7885
7886 for (int ip = 0; ip < np; ip++) {
7887
7888 int nt;
7889 memcpy(&nt, cur, sizeof(nt));
7890 cur += sizeof(nt);
7891
7892 if (nt < 0 || nt > TBLNT)
7893 ERRMSG("nt out of range!");
7894 tbl->nt[id][ig][ip] = nt;
7895
7896 memcpy(tbl->t[id][ig][ip], cur, (size_t) nt * sizeof(double));
7897 cur += ((size_t) nt * sizeof(double));
7898
7899 for (int it = 0; it < nt; it++) {
7900
7901 int nu;
7902 memcpy(&nu, cur, sizeof(nu));
7903 cur += sizeof(nu);
7904
7905 if (nu < 0 || nu > TBLNU)
7906 ERRMSG("nu out of range!");
7907 tbl->nu[id][ig][ip][it] = nu;
7908
7909 ALLOC(tbl->logu[id][ig][ip][it], float,
7910 nu);
7911 ALLOC(tbl->logeps[id][ig][ip][it], float,
7912 nu);
7913
7914 memcpy(tbl->logu[id][ig][ip][it], cur, (size_t) nu * sizeof(float));
7915 cur += ((size_t) nu * sizeof(float));
7916
7917 memcpy(tbl->logeps[id][ig][ip][it], cur, (size_t) nu * sizeof(float));
7918 cur += ((size_t) nu * sizeof(float));
7919 }
7920 }
7921
7922 /* Unpack filter function... */
7923 int n;
7924 memcpy(&n, cur, sizeof(n));
7925 cur += sizeof(n);
7926
7927 if (n < 2 || n > NSHAPE)
7928 ERRMSG("Missing or invalid filter function (filt_n) in packed table!");
7929 tbl->filt_n[id] = n;
7930
7931 memcpy(tbl->filt_nu[id], cur, (size_t) n * sizeof(double));
7932 cur += ((size_t) n * sizeof(double));
7933
7934 memcpy(tbl->filt_f[id], cur, (size_t) n * sizeof(double));
7935 cur += ((size_t) n * sizeof(double));
7936
7937 return (size_t) (cur - buf);
7938}

◆ 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 7942 of file jurassic.c.

7950 {
7951
7952 struct tm t0, t1;
7953
7954 t0.tm_year = 100;
7955 t0.tm_mon = 0;
7956 t0.tm_mday = 1;
7957 t0.tm_hour = 0;
7958 t0.tm_min = 0;
7959 t0.tm_sec = 0;
7960
7961 t1.tm_year = year - 1900;
7962 t1.tm_mon = mon - 1;
7963 t1.tm_mday = day;
7964 t1.tm_hour = hour;
7965 t1.tm_min = min;
7966 t1.tm_sec = sec;
7967
7968 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
7969}

◆ 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 7973 of file jurassic.c.

7976 {
7977
7978 static char names[NTIMER][100], groups[NTIMER][100];
7979 static double rt_name[NTIMER], rt_group[NTIMER], rt_min[NTIMER],
7980 rt_max[NTIMER], rt_sq[NTIMER], t0, t1;
7981 static int ct_name[NTIMER], iname = -1, igroup = -1, nname, ngroup;
7982
7983 /* Get time... */
7984 t1 = omp_get_wtime();
7985 const double dt = t1 - t0;
7986
7987 /* Accumulate runtime for current timer... */
7988 if (iname >= 0) {
7989 rt_name[iname] += dt;
7990 rt_sq[iname] += POW2(dt);
7991 rt_min[iname] = (ct_name[iname] <= 0 ? dt : MIN(rt_min[iname], dt));
7992 rt_max[iname] = (ct_name[iname] <= 0 ? dt : MAX(rt_max[iname], dt));
7993 ct_name[iname]++;
7994 }
7995 if (igroup >= 0)
7996 rt_group[igroup] += dt;
7997
7998 /* Write summary... */
7999 if (output) {
8000 for (int i = 0; i < nname; i++) {
8001 const double mean = rt_name[i] / ct_name[i];
8002 const double variance = MAX(0.0, rt_sq[i] / ct_name[i] - POW2(mean));
8003 LOG(1,
8004 "TIMER_%s = %.3f s (min= %g s, mean= %g s, stddev= %g s, max= %g s, n= %d)",
8005 names[i], rt_name[i], rt_min[i], mean, sqrt(variance), rt_max[i],
8006 ct_name[i]);
8007 }
8008 for (int i = 0; i < ngroup; i++)
8009 LOG(1, "TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
8010 double total = 0.0;
8011 for (int i = 0; i < nname; i++)
8012 total += rt_name[i];
8013 LOG(1, "TIMER_TOTAL = %.3f s", total);
8014 }
8015
8016 /* Identify next timer name... */
8017 for (iname = 0; iname < nname; iname++)
8018 if (strcasecmp(name, names[iname]) == 0)
8019 break;
8020 for (igroup = 0; igroup < ngroup; igroup++)
8021 if (strcasecmp(group, groups[igroup]) == 0)
8022 break;
8023
8024 /* Add new timer name if needed... */
8025 if (iname >= nname) {
8026 sprintf(names[iname], "%s", name);
8027 if ((++nname) >= NTIMER)
8028 ERRMSG("Too many timers!");
8029 }
8030
8031 /* Add new timer group if needed... */
8032 if (igroup >= ngroup) {
8033 sprintf(groups[igroup], "%s", group);
8034 if ((++ngroup) >= NTIMER)
8035 ERRMSG("Too many groups!");
8036 }
8037
8038 /* Save time stamp for next phase... */
8039 t0 = t1;
8040}
#define NTIMER
Maximum number of aggregated timers.
Definition: jurassic.h:417

◆ 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 8044 of file jurassic.c.

8049 {
8050
8051 /* Set filename... */
8052 char file[LEN];
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 atmospheric data: %s", file);
8060
8061 /* Write ASCII data... */
8062 if (ctl->atmfmt == 1)
8063 write_atm_asc(file, ctl, atm);
8064
8065 /* Write binary data... */
8066 else if (ctl->atmfmt == 2)
8067 write_atm_bin(file, ctl, atm);
8068
8069 /* Write netCDF data... */
8070 else if (ctl->atmfmt == 3)
8071 write_atm_nc(file, ctl, atm, profile);
8072
8073 /* Error... */
8074 else
8075 ERRMSG("Unknown file format, check ATMFMT!");
8076
8077 /* Write info... */
8078 double mini, maxi;
8079 LOG(2, "Number of data points: %d", atm->np);
8080 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
8081 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
8082 gsl_stats_minmax(&mini, &maxi, atm->z, 1, (size_t) atm->np);
8083 LOG(2, "Altitude range: %g ... %g km", mini, maxi);
8084 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
8085 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
8086 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
8087 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
8088 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
8089 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
8090 gsl_stats_minmax(&mini, &maxi, atm->t, 1, (size_t) atm->np);
8091 LOG(2, "Temperature range: %g ... %g K", mini, maxi);
8092 for (int ig = 0; ig < ctl->ng; ig++) {
8093 gsl_stats_minmax(&mini, &maxi, atm->q[ig], 1, (size_t) atm->np);
8094 LOG(2, "Emitter %s range: %g ... %g ppv", ctl->emitter[ig], mini, maxi);
8095 }
8096 for (int iw = 0; iw < ctl->nw; iw++) {
8097 gsl_stats_minmax(&mini, &maxi, atm->k[iw], 1, (size_t) atm->np);
8098 LOG(2, "Extinction range (window %d): %g ... %g km^-1", iw, mini, maxi);
8099 }
8100 if (ctl->ncl > 0) {
8101 LOG(2, "Cloud layer: z= %g km | dz= %g km | k= %g ... %g km^-1",
8102 atm->clz, atm->cldz, atm->clk[0], atm->clk[ctl->ncl - 1]);
8103 } else
8104 LOG(2, "Cloud layer: none");
8105 if (ctl->nsf > 0) {
8106 LOG(2,
8107 "Surface: T_s = %g K | eps= %g ... %g",
8108 atm->sft, atm->sfeps[0], atm->sfeps[ctl->nsf - 1]);
8109 } else
8110 LOG(2, "Surface: none");
8111}
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:8266
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:8115
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:8182
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 8115 of file jurassic.c.

8118 {
8119
8120 int n = 6;
8121
8122 /* Create file... */
8123 FILE *out;
8124 if (!(out = fopen(filename, "w")))
8125 ERRMSG("Cannot create file!");
8126
8127 /* Write header... */
8128 fprintf(out,
8129 "# $1 = time (seconds since 2000-01-01T00:00Z)\n"
8130 "# $2 = altitude [km]\n"
8131 "# $3 = longitude [deg]\n"
8132 "# $4 = latitude [deg]\n"
8133 "# $5 = pressure [hPa]\n" "# $6 = temperature [K]\n");
8134 for (int ig = 0; ig < ctl->ng; ig++)
8135 fprintf(out, "# $%d = %s volume mixing ratio [ppv]\n",
8136 ++n, ctl->emitter[ig]);
8137 for (int iw = 0; iw < ctl->nw; iw++)
8138 fprintf(out, "# $%d = extinction (window %d) [km^-1]\n", ++n, iw);
8139 if (ctl->ncl > 0) {
8140 fprintf(out, "# $%d = cloud layer height [km]\n", ++n);
8141 fprintf(out, "# $%d = cloud layer depth [km]\n", ++n);
8142 for (int icl = 0; icl < ctl->ncl; icl++)
8143 fprintf(out, "# $%d = cloud layer extinction (%.4f cm^-1) [km^-1]\n",
8144 ++n, ctl->clnu[icl]);
8145 }
8146 if (ctl->nsf > 0) {
8147 fprintf(out, "# $%d = surface temperature [K]\n", ++n);
8148 for (int isf = 0; isf < ctl->nsf; isf++)
8149 fprintf(out, "# $%d = surface emissivity (%.4f cm^-1)\n",
8150 ++n, ctl->sfnu[isf]);
8151 }
8152
8153 /* Write data... */
8154 for (int ip = 0; ip < atm->np; ip++) {
8155 if (ip == 0 || atm->time[ip] != atm->time[ip - 1])
8156 fprintf(out, "\n");
8157 fprintf(out, "%.2f %g %g %g %g %g", atm->time[ip], atm->z[ip],
8158 atm->lon[ip], atm->lat[ip], atm->p[ip], atm->t[ip]);
8159 for (int ig = 0; ig < ctl->ng; ig++)
8160 fprintf(out, " %g", atm->q[ig][ip]);
8161 for (int iw = 0; iw < ctl->nw; iw++)
8162 fprintf(out, " %g", atm->k[iw][ip]);
8163 if (ctl->ncl > 0) {
8164 fprintf(out, " %g %g", atm->clz, atm->cldz);
8165 for (int icl = 0; icl < ctl->ncl; icl++)
8166 fprintf(out, " %g", atm->clk[icl]);
8167 }
8168 if (ctl->nsf > 0) {
8169 fprintf(out, " %g", atm->sft);
8170 for (int isf = 0; isf < ctl->nsf; isf++)
8171 fprintf(out, " %g", atm->sfeps[isf]);
8172 }
8173 fprintf(out, "\n");
8174 }
8175
8176 /* Close file... */
8177 fclose(out);
8178}

◆ 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 8182 of file jurassic.c.

8185 {
8186
8187 /* Create file... */
8188 FILE *out;
8189 if (!(out = fopen(filename, "w")))
8190 ERRMSG("Cannot create file!");
8191
8192 /* Write header... */
8193 FWRITE("ATM1", char,
8194 4,
8195 out);
8196 FWRITE(&ctl->ng, int,
8197 1,
8198 out);
8199 FWRITE(&ctl->nw, int,
8200 1,
8201 out);
8202 FWRITE(&ctl->ncl, int,
8203 1,
8204 out);
8205 FWRITE(&ctl->nsf, int,
8206 1,
8207 out);
8208
8209 /* Write data... */
8210 size_t np = (size_t) atm->np;
8211 FWRITE(&np, size_t,
8212 1,
8213 out);
8214 FWRITE(atm->time, double,
8215 np,
8216 out);
8217 FWRITE(atm->z, double,
8218 np,
8219 out);
8220 FWRITE(atm->lon, double,
8221 np,
8222 out);
8223 FWRITE(atm->lat, double,
8224 np,
8225 out);
8226 FWRITE(atm->p, double,
8227 np,
8228 out);
8229 FWRITE(atm->t, double,
8230 np,
8231 out);
8232 for (int ig = 0; ig < ctl->ng; ig++)
8233 FWRITE(atm->q[ig], double,
8234 np,
8235 out);
8236 for (int iw = 0; iw < ctl->nw; iw++)
8237 FWRITE(atm->k[iw], double,
8238 np,
8239 out);
8240 if (ctl->ncl > 0) {
8241 FWRITE(&atm->clz, double,
8242 1,
8243 out);
8244 FWRITE(&atm->cldz, double,
8245 1,
8246 out);
8247 FWRITE(atm->clk, double,
8248 (size_t) ctl->ncl,
8249 out);
8250 }
8251 if (ctl->nsf > 0) {
8252 FWRITE(&atm->sft, double,
8253 1,
8254 out);
8255 FWRITE(atm->sfeps, double,
8256 (size_t) ctl->nsf,
8257 out);
8258 }
8259
8260 /* Close file... */
8261 fclose(out);
8262}
#define FWRITE(ptr, type, size, out)
Write binary data to a file.
Definition: jurassic.h:703

◆ 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 8266 of file jurassic.c.

8270 {
8271
8272 char longname[LEN], varname[LEN];
8273
8274 int ncid, varid, dim_profile, dim_level;
8275
8276 size_t level_max;
8277
8278 /* Check number of levels... */
8279 if (atm->np < 1 || atm->np > NP)
8280 ERRMSG("Number of levels out of range!");
8281
8282 /* Open or create file... */
8283 if (nc_open(filename, NC_WRITE, &ncid) != NC_NOERR)
8284 NC(nc_create(filename, NC_NETCDF4, &ncid));
8285
8286 /* Enter define mode... */
8287 int r = nc_redef(ncid);
8288 if (r != NC_NOERR && r != NC_EINDEFINE)
8289 NC(r);
8290
8291 /* Define profile dimension (unlimited)... */
8292 if (nc_inq_dimid(ncid, "profile", &dim_profile) != NC_NOERR)
8293 NC(nc_def_dim(ncid, "profile", NC_UNLIMITED, &dim_profile));
8294
8295 /* Define level dimension (fixed)... */
8296 if (nc_inq_dimid(ncid, "level", &dim_level) == NC_NOERR) {
8297 NC(nc_inq_dimlen(ncid, dim_level, &level_max));
8298 if (level_max < 1 || level_max > (size_t) NP)
8299 ERRMSG("netCDF dimension level is out of range!");
8300 if ((size_t) atm->np > level_max)
8301 ERRMSG("profile has too many levels!");
8302 } else {
8303 level_max = (size_t) atm->np;
8304 NC(nc_def_dim(ncid, "level", level_max, &dim_level));
8305 }
8306
8307 /* Set dimension IDs... */
8308 int dimids[2] = { dim_profile, dim_level };
8309
8310 /* Tunables for compression/quantization... */
8311 const int deflate_level = 0;
8312 const int quant_digits = 0;
8313
8314 /* Define nlev (1D)... */
8315 if (nc_inq_varid(ncid, "nlev", &varid) != NC_NOERR)
8316 NC_DEF_VAR("nlev", NC_INT, 1, dimids,
8317 "number of vertical levels", "1", 0, 0);
8318
8319 /* Define core variables (2D)... */
8320 if (nc_inq_varid(ncid, "time", &varid) != NC_NOERR)
8321 NC_DEF_VAR("time", NC_DOUBLE, 2, dimids,
8322 "time in seconds since 2000-01-01, 00:00 UTC", "s",
8323 deflate_level, 0);
8324
8325 if (nc_inq_varid(ncid, "z", &varid) != NC_NOERR)
8326 NC_DEF_VAR("z", NC_DOUBLE, 2, dimids, "altitude", "km", deflate_level, 0);
8327
8328 if (nc_inq_varid(ncid, "lon", &varid) != NC_NOERR)
8329 NC_DEF_VAR("lon", NC_DOUBLE, 2, dimids,
8330 "longitude", "degrees_east", deflate_level, 0);
8331
8332 if (nc_inq_varid(ncid, "lat", &varid) != NC_NOERR)
8333 NC_DEF_VAR("lat", NC_DOUBLE, 2, dimids,
8334 "latitude", "degrees_north", deflate_level, 0);
8335
8336 if (nc_inq_varid(ncid, "p", &varid) != NC_NOERR)
8337 NC_DEF_VAR("p", NC_DOUBLE, 2, dimids,
8338 "pressure", "hPa", deflate_level, quant_digits);
8339
8340 if (nc_inq_varid(ncid, "t", &varid) != NC_NOERR)
8341 NC_DEF_VAR("t", NC_DOUBLE, 2, dimids,
8342 "temperature", "K", deflate_level, quant_digits);
8343
8344 /* Write emitters (2D)... */
8345 for (int ig = 0; ig < ctl->ng; ig++)
8346 if (nc_inq_varid(ncid, ctl->emitter[ig], &varid) != NC_NOERR) {
8347 sprintf(longname, "%s volume mixing ratio", ctl->emitter[ig]);
8348 NC_DEF_VAR(ctl->emitter[ig], NC_DOUBLE, 2, dimids,
8349 longname, "ppv", deflate_level, quant_digits);
8350 }
8351
8352 /* Write extinction (2D)... */
8353 for (int iw = 0; iw < ctl->nw; iw++) {
8354 sprintf(varname, "ext_win_%d", iw);
8355 if (nc_inq_varid(ncid, varname, &varid) != NC_NOERR) {
8356 sprintf(longname, "extinction (window %d)", iw);
8357 NC_DEF_VAR(varname, NC_DOUBLE, 2, dimids,
8358 longname, "km**-1", deflate_level, quant_digits);
8359 }
8360 }
8361
8362 /* Write cloud variables (1D)... */
8363 if (ctl->ncl > 0) {
8364 if (nc_inq_varid(ncid, "cld_z", &varid) != NC_NOERR)
8365 NC_DEF_VAR("cld_z", NC_DOUBLE, 1, dimids,
8366 "cloud layer height", "km", deflate_level, quant_digits);
8367
8368 if (nc_inq_varid(ncid, "cld_dz", &varid) != NC_NOERR)
8369 NC_DEF_VAR("cld_dz", NC_DOUBLE, 1, dimids,
8370 "cloud layer depth", "km", deflate_level, quant_digits);
8371
8372 for (int icl = 0; icl < ctl->ncl; icl++) {
8373 sprintf(varname, "cld_k_%.4f", ctl->clnu[icl]);
8374 if (nc_inq_varid(ncid, varname, &varid) != NC_NOERR) {
8375 sprintf(longname, "cloud layer extinction (%.4f cm^-1)",
8376 ctl->clnu[icl]);
8377 NC_DEF_VAR(varname, NC_DOUBLE, 1, dimids, longname, "km**-1",
8378 deflate_level, quant_digits);
8379 }
8380 }
8381 }
8382
8383 /* Write surface variables (1D)... */
8384 if (ctl->nsf > 0) {
8385 if (nc_inq_varid(ncid, "srf_t", &varid) != NC_NOERR)
8386 NC_DEF_VAR("srf_t", NC_DOUBLE, 1, dimids,
8387 "surface temperature", "K", deflate_level, quant_digits);
8388
8389 for (int isf = 0; isf < ctl->nsf; isf++) {
8390 sprintf(varname, "srf_eps_%.4f", ctl->sfnu[isf]);
8391 if (nc_inq_varid(ncid, varname, &varid) != NC_NOERR) {
8392 sprintf(longname, "surface emissivity (%.4f cm^-1)", ctl->sfnu[isf]);
8393 NC_DEF_VAR(varname, NC_DOUBLE, 1, dimids, longname, "1",
8394 deflate_level, quant_digits);
8395 }
8396 }
8397 }
8398
8399 /* Leave define mode... */
8400 NC(nc_enddef(ncid));
8401
8402 /* Define hyperslabs... */
8403 size_t start[2] = { (size_t) profile, 0 };
8404 size_t count[2] = { 1, (size_t) atm->np };
8405
8406 /* Write nlev... */
8407 NC_PUT_INT("nlev", &atm->np, 1);
8408
8409 /* Write core variables... */
8410 NC_PUT_DOUBLE("time", atm->time, 1);
8411 NC_PUT_DOUBLE("z", atm->z, 1);
8412 NC_PUT_DOUBLE("lon", atm->lon, 1);
8413 NC_PUT_DOUBLE("lat", atm->lat, 1);
8414 NC_PUT_DOUBLE("p", atm->p, 1);
8415 NC_PUT_DOUBLE("t", atm->t, 1);
8416
8417 /* Write emitters... */
8418 for (int ig = 0; ig < ctl->ng; ig++)
8419 NC_PUT_DOUBLE(ctl->emitter[ig], atm->q[ig], 1);
8420
8421 /* Write extinction... */
8422 for (int iw = 0; iw < ctl->nw; iw++) {
8423 sprintf(varname, "ext_win_%d", iw);
8424 NC_PUT_DOUBLE(varname, atm->k[iw], 1);
8425 }
8426
8427 /* Write cloud variables... */
8428 if (ctl->ncl > 0) {
8429 NC_PUT_DOUBLE("cld_z", &atm->clz, 1);
8430 NC_PUT_DOUBLE("cld_dz", &atm->cldz, 1);
8431 for (int icl = 0; icl < ctl->ncl; icl++) {
8432 sprintf(varname, "cld_k_%.4f", ctl->clnu[icl]);
8433 NC_PUT_DOUBLE(varname, &atm->clk[icl], 1);
8434 }
8435 }
8436
8437 /* Write surface variables... */
8438 if (ctl->nsf > 0) {
8439 NC_PUT_DOUBLE("srf_t", &atm->sft, 1);
8440 for (int isf = 0; isf < ctl->nsf; isf++) {
8441 sprintf(varname, "srf_eps_%.4f", ctl->sfnu[isf]);
8442 NC_PUT_DOUBLE(varname, &atm->sfeps[isf], 1);
8443 }
8444 }
8445
8446 /* Close file... */
8447 NC(nc_sync(ncid));
8448 NC(nc_close(ncid));
8449}
#define NC_PUT_INT(varname, ptr, hyperslab)
Write integer data to a NetCDF variable.
Definition: jurassic.h:981
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units, level, quant)
Define a NetCDF variable with attributes.
Definition: jurassic.h:829
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
Write double precision data to a NetCDF variable.
Definition: jurassic.h:934

◆ 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 8453 of file jurassic.c.

8456 {
8457
8458 /* Write info... */
8459 LOG(1, "Write RFM data: %s", filename);
8460
8461 /* Create file... */
8462 FILE *out;
8463 if (!(out = fopen(filename, "w")))
8464 ERRMSG("Cannot create file!");
8465
8466 /* Write data... */
8467 fprintf(out, "%d\n", atm->np);
8468 fprintf(out, "*HGT [km]\n");
8469 for (int ip = 0; ip < atm->np; ip++)
8470 fprintf(out, "%g\n", atm->z[ip]);
8471 fprintf(out, "*PRE [mb]\n");
8472 for (int ip = 0; ip < atm->np; ip++)
8473 fprintf(out, "%g\n", atm->p[ip]);
8474 fprintf(out, "*TEM [K]\n");
8475 for (int ip = 0; ip < atm->np; ip++)
8476 fprintf(out, "%g\n", atm->t[ip]);
8477 for (int ig = 0; ig < ctl->ng; ig++) {
8478 fprintf(out, "*%s [ppmv]\n", ctl->emitter[ig]);
8479 for (int ip = 0; ip < atm->np; ip++)
8480 fprintf(out, "%g\n", atm->q[ig][ip] * 1e6);
8481 }
8482 fprintf(out, "*END\n");
8483
8484 /* Close file... */
8485 fclose(out);
8486}

◆ 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 8490 of file jurassic.c.

8500 {
8501
8502 /* Check output flag... */
8503 if (!ctl->write_matrix)
8504 return;
8505
8506 /* Write ASCII data... */
8507 if (ctl->matrixfmt == 1)
8508 write_matrix_asc(dirname, filename, ctl, matrix, atm, obs,
8509 rowspace, colspace, sort);
8510
8511 /* Write binary data... */
8512 else if (ctl->matrixfmt == 2)
8513 write_matrix_bin(dirname, filename, matrix);
8514
8515 /* Write netCDF data... */
8516 else if (ctl->matrixfmt == 3)
8517 write_matrix_nc(dirname, filename, ctl, matrix, atm, obs,
8518 rowspace, colspace, sort, dataset);
8519
8520 /* Error... */
8521 else
8522 ERRMSG("Unknown matrix file format, check MATRIXFMT!");
8523}
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:8527
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:8749
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:8700
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 8527 of file jurassic.c.

8536 {
8537
8538 char file[LEN], quantity[LEN];
8539
8540 int *cida, *ciqa, *cipa, *cira, *rida, *riqa, *ripa, *rira;
8541
8542 size_t i, j, nc, nr;
8543
8544 /* Allocate... */
8545 ALLOC(cida, int,
8546 M);
8547 ALLOC(ciqa, int,
8548 N);
8549 ALLOC(cipa, int,
8550 N);
8551 ALLOC(cira, int,
8552 M);
8553 ALLOC(rida, int,
8554 M);
8555 ALLOC(riqa, int,
8556 N);
8557 ALLOC(ripa, int,
8558 N);
8559 ALLOC(rira, int,
8560 M);
8561
8562 /* Set filename... */
8563 if (dirname != NULL)
8564 sprintf(file, "%s/%s", dirname, filename);
8565 else
8566 sprintf(file, "%s", filename);
8567
8568 /* Write info... */
8569 LOG(1, "Write matrix: %s", file);
8570
8571 /* Create file... */
8572 FILE *out;
8573 if (!(out = fopen(file, "w")))
8574 ERRMSG("Cannot create file!");
8575
8576 /* Write header (row space)... */
8577 if (rowspace[0] == 'y') {
8578
8579 fprintf(out,
8580 "# $1 = Row: index (measurement space)\n"
8581 "# $2 = Row: channel wavenumber [cm^-1]\n"
8582 "# $3 = Row: time (seconds since 2000-01-01T00:00Z)\n"
8583 "# $4 = Row: view point altitude [km]\n"
8584 "# $5 = Row: view point longitude [deg]\n"
8585 "# $6 = Row: view point latitude [deg]\n");
8586
8587 /* Get number of rows... */
8588 nr = obs2y(ctl, obs, NULL, rida, rira);
8589
8590 } else {
8591
8592 fprintf(out,
8593 "# $1 = Row: index (state space)\n"
8594 "# $2 = Row: name of quantity\n"
8595 "# $3 = Row: time (seconds since 2000-01-01T00:00Z)\n"
8596 "# $4 = Row: altitude [km]\n"
8597 "# $5 = Row: longitude [deg]\n" "# $6 = Row: latitude [deg]\n");
8598
8599 /* Get number of rows... */
8600 nr = atm2x(ctl, atm, NULL, riqa, ripa);
8601 }
8602
8603 /* Write header (column space)... */
8604 if (colspace[0] == 'y') {
8605
8606 fprintf(out,
8607 "# $7 = Col: index (measurement space)\n"
8608 "# $8 = Col: channel wavenumber [cm^-1]\n"
8609 "# $9 = Col: time (seconds since 2000-01-01T00:00Z)\n"
8610 "# $10 = Col: view point altitude [km]\n"
8611 "# $11 = Col: view point longitude [deg]\n"
8612 "# $12 = Col: view point latitude [deg]\n");
8613
8614 /* Get number of columns... */
8615 nc = obs2y(ctl, obs, NULL, cida, cira);
8616
8617 } else {
8618
8619 fprintf(out,
8620 "# $7 = Col: index (state space)\n"
8621 "# $8 = Col: name of quantity\n"
8622 "# $9 = Col: time (seconds since 2000-01-01T00:00Z)\n"
8623 "# $10 = Col: altitude [km]\n"
8624 "# $11 = Col: longitude [deg]\n" "# $12 = Col: latitude [deg]\n");
8625
8626 /* Get number of columns... */
8627 nc = atm2x(ctl, atm, NULL, ciqa, cipa);
8628 }
8629
8630 /* Write header entry... */
8631 fprintf(out, "# $13 = Matrix element\n\n");
8632
8633 /* Write matrix data... */
8634 i = j = 0;
8635 while (i < nr && j < nc) {
8636
8637 /* Write info about the row... */
8638 if (rowspace[0] == 'y')
8639 fprintf(out, "%d %.4f %.2f %g %g %g",
8640 (int) i, ctl->nu[rida[i]],
8641 obs->time[rira[i]], obs->vpz[rira[i]],
8642 obs->vplon[rira[i]], obs->vplat[rira[i]]);
8643 else {
8644 idx2name(ctl, riqa[i], quantity);
8645 fprintf(out, "%d %s %.2f %g %g %g", (int) i, quantity,
8646 atm->time[ripa[i]], atm->z[ripa[i]],
8647 atm->lon[ripa[i]], atm->lat[ripa[i]]);
8648 }
8649
8650 /* Write info about the column... */
8651 if (colspace[0] == 'y')
8652 fprintf(out, " %d %.4f %.2f %g %g %g",
8653 (int) j, ctl->nu[cida[j]],
8654 obs->time[cira[j]], obs->vpz[cira[j]],
8655 obs->vplon[cira[j]], obs->vplat[cira[j]]);
8656 else {
8657 idx2name(ctl, ciqa[j], quantity);
8658 fprintf(out, " %d %s %.2f %g %g %g", (int) j, quantity,
8659 atm->time[cipa[j]], atm->z[cipa[j]],
8660 atm->lon[cipa[j]], atm->lat[cipa[j]]);
8661 }
8662
8663 /* Write matrix entry... */
8664 fprintf(out, " %g\n", gsl_matrix_get(matrix, i, j));
8665
8666 /* Set matrix indices... */
8667 if (sort[0] == 'r') {
8668 j++;
8669 if (j >= nc) {
8670 j = 0;
8671 i++;
8672 fprintf(out, "\n");
8673 }
8674 } else {
8675 i++;
8676 if (i >= nr) {
8677 i = 0;
8678 j++;
8679 fprintf(out, "\n");
8680 }
8681 }
8682 }
8683
8684 /* Close file... */
8685 fclose(out);
8686
8687 /* Free... */
8688 free(cida);
8689 free(ciqa);
8690 free(cipa);
8691 free(cira);
8692 free(rida);
8693 free(riqa);
8694 free(ripa);
8695 free(rira);
8696}
void idx2name(const ctl_t *ctl, const int idx, char *quantity)
Convert a quantity index to a descriptive name string.
Definition: jurassic.c:4661
#define M
Maximum size of measurement vector.
Definition: jurassic.h:340
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 8700 of file jurassic.c.

8703 {
8704
8705 char file[LEN];
8706 const size_t nr = matrix->size1;
8707 const size_t nc = matrix->size2;
8708
8709 /* Set filename... */
8710 if (dirname != NULL)
8711 sprintf(file, "%s/%s", dirname, filename);
8712 else
8713 sprintf(file, "%s", filename);
8714
8715 /* Write info... */
8716 LOG(1, "Write matrix: %s", file);
8717
8718 /* Create file... */
8719 FILE *out;
8720 if (!(out = fopen(file, "w")))
8721 ERRMSG("Cannot create file!");
8722
8723 /* Write header... */
8724 FWRITE("MAT1", char,
8725 4,
8726 out);
8727 FWRITE(&nr, size_t,
8728 1,
8729 out);
8730 FWRITE(&nc, size_t,
8731 1,
8732 out);
8733
8734 /* Write data... */
8735 for (size_t i = 0; i < nr; i++)
8736 for (size_t j = 0; j < nc; j++) {
8737 double value = gsl_matrix_get(matrix, i, j);
8738 FWRITE(&value, double,
8739 1,
8740 out);
8741 }
8742
8743 /* Close file... */
8744 fclose(out);
8745}

◆ 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 8749 of file jurassic.c.

8759 {
8760
8761 char file[LEN];
8762 char quantity[LEN];
8763 const size_t name_strlen = 100;
8764
8765 int ncid, dimid_dataset, dimid_row, dimid_col, dimid_name, varid;
8766 int *cida, *ciqa, *cipa, *cira, *rida, *riqa, *ripa, *rira;
8767
8768 size_t nr = matrix->size1, nc = matrix->size2, naux;
8769
8770 /* Allocate metadata index arrays... */
8771 ALLOC(cida, int,
8772 M);
8773 ALLOC(ciqa, int,
8774 N);
8775 ALLOC(cipa, int,
8776 N);
8777 ALLOC(cira, int,
8778 M);
8779 ALLOC(rida, int,
8780 M);
8781 ALLOC(riqa, int,
8782 N);
8783 ALLOC(ripa, int,
8784 N);
8785 ALLOC(rira, int,
8786 M);
8787
8788 /* Set filename... */
8789 if (dirname != NULL)
8790 sprintf(file, "%s/%s", dirname, filename);
8791 else
8792 sprintf(file, "%s", filename);
8793
8794 /* Write info... */
8795 LOG(1, "Write matrix: %s", file);
8796
8797 /* Open or create file... */
8798 if (nc_open(file, NC_WRITE, &ncid) != NC_NOERR)
8799 NC(nc_create(file, NC_NETCDF4, &ncid));
8800
8801 /* Enter define mode... */
8802 int r = nc_redef(ncid);
8803 if (r != NC_NOERR && r != NC_EINDEFINE)
8804 NC(r);
8805
8806 /* Define dataset dimension (unlimited)... */
8807 if (nc_inq_dimid(ncid, "dataset", &dimid_dataset) != NC_NOERR)
8808 NC(nc_def_dim(ncid, "dataset", NC_UNLIMITED, &dimid_dataset));
8809
8810 /* Define row dimension (fixed)... */
8811 if (nc_inq_dimid(ncid, "row", &dimid_row) == NC_NOERR) {
8812 NC(nc_inq_dimlen(ncid, dimid_row, &naux));
8813 if (naux != nr)
8814 ERRMSG("matrix row dimension is incompatible!");
8815 } else
8816 NC(nc_def_dim(ncid, "row", nr, &dimid_row));
8817
8818 /* Define col dimension (fixed)... */
8819 if (nc_inq_dimid(ncid, "col", &dimid_col) == NC_NOERR) {
8820 NC(nc_inq_dimlen(ncid, dimid_col, &naux));
8821 if (naux != nc)
8822 ERRMSG("matrix col dimension is incompatible!");
8823 } else
8824 NC(nc_def_dim(ncid, "col", nc, &dimid_col));
8825
8826 /* Define fixed-length name dimension... */
8827 if (nc_inq_dimid(ncid, "name_strlen", &dimid_name) == NC_NOERR) {
8828 NC(nc_inq_dimlen(ncid, dimid_name, &naux));
8829 if (naux != name_strlen)
8830 ERRMSG("matrix name_strlen dimension is incompatible!");
8831 } else
8832 NC(nc_def_dim(ncid, "name_strlen", name_strlen, &dimid_name));
8833
8834 /* Define variables... */
8835 int dimids3[3] = { dimid_dataset, dimid_row, dimid_col };
8836 int dimids1[1] = { dimid_dataset };
8837 int dimids2_row[2] = { dimid_dataset, dimid_row };
8838 int dimids2_col[2] = { dimid_dataset, dimid_col };
8839 int dimids3_rowname[3] = { dimid_dataset, dimid_row, dimid_name };
8840 int dimids3_colname[3] = { dimid_dataset, dimid_col, dimid_name };
8841 if (nc_inq_varid(ncid, "matrix", &varid) != NC_NOERR) {
8842 NC(nc_def_var(ncid, "matrix", NC_DOUBLE, 3, dimids3, &varid));
8843 NC(nc_put_att_text(ncid, varid, "long_name", 14, "matrix element"));
8844 NC(nc_put_att_text(ncid, varid, "units", 1, "1"));
8845 }
8846 if (nc_inq_varid(ncid, "rowspace", &varid) != NC_NOERR)
8847 NC_DEF_VAR("rowspace", NC_CHAR, 1, dimids1,
8848 "row space selector", "1", 0, 0);
8849 if (nc_inq_varid(ncid, "colspace", &varid) != NC_NOERR)
8850 NC_DEF_VAR("colspace", NC_CHAR, 1, dimids1,
8851 "column space selector", "1", 0, 0);
8852 if (nc_inq_varid(ncid, "sort", &varid) != NC_NOERR)
8853 NC_DEF_VAR("sort", NC_CHAR, 1, dimids1,
8854 "matrix sort selector", "1", 0, 0);
8855 if (nc_inq_varid(ncid, "row_nu", &varid) != NC_NOERR)
8856 NC_DEF_VAR("row_nu", NC_DOUBLE, 2, dimids2_row,
8857 "row channel wavenumber", "cm^-1", 0, 0);
8858 if (nc_inq_varid(ncid, "row_time", &varid) != NC_NOERR)
8859 NC_DEF_VAR("row_time", NC_DOUBLE, 2, dimids2_row,
8860 "row time since 2000-01-01T00:00Z", "s", 0, 0);
8861 if (nc_inq_varid(ncid, "row_z", &varid) != NC_NOERR)
8862 NC_DEF_VAR("row_z", NC_DOUBLE, 2, dimids2_row,
8863 "row altitude", "km", 0, 0);
8864 if (nc_inq_varid(ncid, "row_lon", &varid) != NC_NOERR)
8865 NC_DEF_VAR("row_lon", NC_DOUBLE, 2, dimids2_row,
8866 "row longitude", "degrees_east", 0, 0);
8867 if (nc_inq_varid(ncid, "row_lat", &varid) != NC_NOERR)
8868 NC_DEF_VAR("row_lat", NC_DOUBLE, 2, dimids2_row,
8869 "row latitude", "degrees_north", 0, 0);
8870 if (nc_inq_varid(ncid, "row_quantity", &varid) != NC_NOERR)
8871 NC_DEF_VAR("row_quantity", NC_CHAR, 3, dimids3_rowname,
8872 "row state quantity name", "1", 0, 0);
8873 if (nc_inq_varid(ncid, "col_nu", &varid) != NC_NOERR)
8874 NC_DEF_VAR("col_nu", NC_DOUBLE, 2, dimids2_col,
8875 "column channel wavenumber", "cm^-1", 0, 0);
8876 if (nc_inq_varid(ncid, "col_time", &varid) != NC_NOERR)
8877 NC_DEF_VAR("col_time", NC_DOUBLE, 2, dimids2_col,
8878 "column time since 2000-01-01T00:00Z", "s", 0, 0);
8879 if (nc_inq_varid(ncid, "col_z", &varid) != NC_NOERR)
8880 NC_DEF_VAR("col_z", NC_DOUBLE, 2, dimids2_col,
8881 "column altitude", "km", 0, 0);
8882 if (nc_inq_varid(ncid, "col_lon", &varid) != NC_NOERR)
8883 NC_DEF_VAR("col_lon", NC_DOUBLE, 2, dimids2_col,
8884 "column longitude", "degrees_east", 0, 0);
8885 if (nc_inq_varid(ncid, "col_lat", &varid) != NC_NOERR)
8886 NC_DEF_VAR("col_lat", NC_DOUBLE, 2, dimids2_col,
8887 "column latitude", "degrees_north", 0, 0);
8888 if (nc_inq_varid(ncid, "col_quantity", &varid) != NC_NOERR)
8889 NC_DEF_VAR("col_quantity", NC_CHAR, 3, dimids3_colname,
8890 "column state quantity name", "1", 0, 0);
8891
8892 /* Leave define mode... */
8893 NC(nc_enddef(ncid));
8894
8895 /* Write metadata... */
8896 size_t start1[1] = { (size_t) dataset };
8897 size_t count1[1] = { 1 };
8898 NC(nc_inq_varid(ncid, "rowspace", &varid));
8899 NC(nc_put_vara_text(ncid, varid, start1, count1, rowspace));
8900 NC(nc_inq_varid(ncid, "colspace", &varid));
8901 NC(nc_put_vara_text(ncid, varid, start1, count1, colspace));
8902 NC(nc_inq_varid(ncid, "sort", &varid));
8903 NC(nc_put_vara_text(ncid, varid, start1, count1, sort));
8904
8905 /* Set row and column metadata indices... */
8906 if (rowspace[0] == 'y')
8907 nr = obs2y(ctl, obs, NULL, rida, rira);
8908 else
8909 nr = atm2x(ctl, atm, NULL, riqa, ripa);
8910 if (colspace[0] == 'y')
8911 nc = obs2y(ctl, obs, NULL, cida, cira);
8912 else
8913 nc = atm2x(ctl, atm, NULL, ciqa, cipa);
8914
8915 /* Write row metadata... */
8916 for (size_t i = 0; i < nr; i++) {
8917 const double nu = rowspace[0] == 'y' ? ctl->nu[rida[i]] : GSL_NAN;
8918 const double time =
8919 rowspace[0] == 'y' ? obs->time[rira[i]] : atm->time[ripa[i]];
8920 const double z = rowspace[0] == 'y' ? obs->vpz[rira[i]] : atm->z[ripa[i]];
8921 const double lon =
8922 rowspace[0] == 'y' ? obs->vplon[rira[i]] : atm->lon[ripa[i]];
8923 const double lat =
8924 rowspace[0] == 'y' ? obs->vplat[rira[i]] : atm->lat[ripa[i]];
8925 char qbuf[LEN] = { 0 };
8926 size_t start2[2] = { (size_t) dataset, i };
8927 size_t count2[2] = { 1, 1 };
8928 size_t start3n[3] = { (size_t) dataset, i, 0 };
8929 size_t count3n[3] = { 1, 1, name_strlen };
8930
8931 if (rowspace[0] != 'y') {
8932 idx2name(ctl, riqa[i], quantity);
8933 snprintf(qbuf, LEN, "%s", quantity);
8934 }
8935
8936 NC(nc_inq_varid(ncid, "row_nu", &varid));
8937 NC(nc_put_vara_double(ncid, varid, start2, count2, &nu));
8938 NC(nc_inq_varid(ncid, "row_time", &varid));
8939 NC(nc_put_vara_double(ncid, varid, start2, count2, &time));
8940 NC(nc_inq_varid(ncid, "row_z", &varid));
8941 NC(nc_put_vara_double(ncid, varid, start2, count2, &z));
8942 NC(nc_inq_varid(ncid, "row_lon", &varid));
8943 NC(nc_put_vara_double(ncid, varid, start2, count2, &lon));
8944 NC(nc_inq_varid(ncid, "row_lat", &varid));
8945 NC(nc_put_vara_double(ncid, varid, start2, count2, &lat));
8946 NC(nc_inq_varid(ncid, "row_quantity", &varid));
8947 NC(nc_put_vara_text(ncid, varid, start3n, count3n, qbuf));
8948 }
8949
8950 /* Write column metadata... */
8951 for (size_t j = 0; j < nc; j++) {
8952 const double nu = colspace[0] == 'y' ? ctl->nu[cida[j]] : GSL_NAN;
8953 const double time =
8954 colspace[0] == 'y' ? obs->time[cira[j]] : atm->time[cipa[j]];
8955 const double z = colspace[0] == 'y' ? obs->vpz[cira[j]] : atm->z[cipa[j]];
8956 const double lon =
8957 colspace[0] == 'y' ? obs->vplon[cira[j]] : atm->lon[cipa[j]];
8958 const double lat =
8959 colspace[0] == 'y' ? obs->vplat[cira[j]] : atm->lat[cipa[j]];
8960 char qbuf[LEN] = { 0 };
8961 size_t start2[2] = { (size_t) dataset, j };
8962 size_t count2[2] = { 1, 1 };
8963 size_t start3n[3] = { (size_t) dataset, j, 0 };
8964 size_t count3n[3] = { 1, 1, name_strlen };
8965
8966 if (colspace[0] != 'y') {
8967 idx2name(ctl, ciqa[j], quantity);
8968 snprintf(qbuf, LEN, "%s", quantity);
8969 }
8970
8971 NC(nc_inq_varid(ncid, "col_nu", &varid));
8972 NC(nc_put_vara_double(ncid, varid, start2, count2, &nu));
8973 NC(nc_inq_varid(ncid, "col_time", &varid));
8974 NC(nc_put_vara_double(ncid, varid, start2, count2, &time));
8975 NC(nc_inq_varid(ncid, "col_z", &varid));
8976 NC(nc_put_vara_double(ncid, varid, start2, count2, &z));
8977 NC(nc_inq_varid(ncid, "col_lon", &varid));
8978 NC(nc_put_vara_double(ncid, varid, start2, count2, &lon));
8979 NC(nc_inq_varid(ncid, "col_lat", &varid));
8980 NC(nc_put_vara_double(ncid, varid, start2, count2, &lat));
8981 NC(nc_inq_varid(ncid, "col_quantity", &varid));
8982 NC(nc_put_vara_text(ncid, varid, start3n, count3n, qbuf));
8983 }
8984
8985 /* Write matrix data... */
8986 NC(nc_inq_varid(ncid, "matrix", &varid));
8987 for (size_t i = 0; i < nr; i++)
8988 for (size_t j = 0; j < nc; j++) {
8989 const double value = gsl_matrix_get(matrix, i, j);
8990 size_t start3[3] = { (size_t) dataset, i, j };
8991 size_t count3[3] = { 1, 1, 1 };
8992 NC(nc_put_vara_double(ncid, varid, start3, count3, &value));
8993 }
8994
8995 /* Close file... */
8996 NC(nc_sync(ncid));
8997 NC(nc_close(ncid));
8998
8999 /* Free... */
9000 free(cida);
9001 free(ciqa);
9002 free(cipa);
9003 free(cira);
9004 free(rida);
9005 free(riqa);
9006 free(ripa);
9007 free(rira);
9008}
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 9012 of file jurassic.c.

9017 {
9018
9019 /* Set filename... */
9020 char file[LEN];
9021 if (dirname != NULL)
9022 sprintf(file, "%s/%s", dirname, filename);
9023 else
9024 sprintf(file, "%s", filename);
9025
9026 /* Write info... */
9027 LOG(1, "Write observation data: %s", file);
9028
9029 /* Write ASCII data... */
9030 if (ctl->obsfmt == 1)
9031 write_obs_asc(file, ctl, obs);
9032
9033 /* Write binary data... */
9034 else if (ctl->obsfmt == 2)
9035 write_obs_bin(file, ctl, obs);
9036
9037 /* Write netCDF data... */
9038 else if (ctl->obsfmt == 3)
9039 write_obs_nc(file, ctl, obs, profile);
9040
9041 /* Write info... */
9042 double mini, maxi;
9043 LOG(2, "Number of ray paths: %d", obs->nr);
9044 gsl_stats_minmax(&mini, &maxi, obs->time, 1, (size_t) obs->nr);
9045 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
9046 gsl_stats_minmax(&mini, &maxi, obs->obsz, 1, (size_t) obs->nr);
9047 LOG(2, "Observer altitude range: %g ... %g km", mini, maxi);
9048 gsl_stats_minmax(&mini, &maxi, obs->obslon, 1, (size_t) obs->nr);
9049 LOG(2, "Observer longitude range: %g ... %g deg", mini, maxi);
9050 gsl_stats_minmax(&mini, &maxi, obs->obslat, 1, (size_t) obs->nr);
9051 LOG(2, "Observer latitude range: %g ... %g deg", mini, maxi);
9052 gsl_stats_minmax(&mini, &maxi, obs->vpz, 1, (size_t) obs->nr);
9053 LOG(2, "View point altitude range: %g ... %g km", mini, maxi);
9054 gsl_stats_minmax(&mini, &maxi, obs->vplon, 1, (size_t) obs->nr);
9055 LOG(2, "View point longitude range: %g ... %g deg", mini, maxi);
9056 gsl_stats_minmax(&mini, &maxi, obs->vplat, 1, (size_t) obs->nr);
9057 LOG(2, "View point latitude range: %g ... %g deg", mini, maxi);
9058 gsl_stats_minmax(&mini, &maxi, obs->tpz, 1, (size_t) obs->nr);
9059 LOG(2, "Tangent point altitude range: %g ... %g km", mini, maxi);
9060 gsl_stats_minmax(&mini, &maxi, obs->tplon, 1, (size_t) obs->nr);
9061 LOG(2, "Tangent point longitude range: %g ... %g deg", mini, maxi);
9062 gsl_stats_minmax(&mini, &maxi, obs->tplat, 1, (size_t) obs->nr);
9063 LOG(2, "Tangent point latitude range: %g ... %g deg", mini, maxi);
9064 for (int id = 0; id < ctl->nd; id++) {
9065 gsl_stats_minmax(&mini, &maxi, obs->rad[id], 1, (size_t) obs->nr);
9066 if (ctl->write_bbt) {
9067 LOG(2, "Brightness temperature (%.4f cm^-1) range: %g ... %g K",
9068 ctl->nu[id], mini, maxi);
9069 } else {
9070 LOG(2, "Radiance (%.4f cm^-1) range: %g ... %g W/(m^2 sr cm^-1)",
9071 ctl->nu[id], mini, maxi);
9072 }
9073 }
9074 for (int id = 0; id < ctl->nd; id++) {
9075 gsl_stats_minmax(&mini, &maxi, obs->tau[id], 1, (size_t) obs->nr);
9076 LOG(2, "Transmittance (%.4f cm^-1) range: %g ... %g",
9077 ctl->nu[id], mini, maxi);
9078 }
9079}
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:9083
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:9207
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:9139
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 9083 of file jurassic.c.

9086 {
9087
9088 int n = 10;
9089
9090 /* Create file... */
9091 FILE *out;
9092 if (!(out = fopen(filename, "w")))
9093 ERRMSG("Cannot create file!");
9094
9095 /* Write header... */
9096 fprintf(out,
9097 "# $1 = time (seconds since 2000-01-01T00:00Z)\n"
9098 "# $2 = observer altitude [km]\n"
9099 "# $3 = observer longitude [deg]\n"
9100 "# $4 = observer latitude [deg]\n"
9101 "# $5 = view point altitude [km]\n"
9102 "# $6 = view point longitude [deg]\n"
9103 "# $7 = view point latitude [deg]\n"
9104 "# $8 = tangent point altitude [km]\n"
9105 "# $9 = tangent point longitude [deg]\n"
9106 "# $10 = tangent point latitude [deg]\n");
9107 for (int id = 0; id < ctl->nd; id++)
9108 if (ctl->write_bbt)
9109 fprintf(out, "# $%d = brightness temperature (%.4f cm^-1) [K]\n",
9110 ++n, ctl->nu[id]);
9111 else
9112 fprintf(out, "# $%d = radiance (%.4f cm^-1) [W/(m^2 sr cm^-1)]\n",
9113 ++n, ctl->nu[id]);
9114 for (int id = 0; id < ctl->nd; id++)
9115 fprintf(out, "# $%d = transmittance (%.4f cm^-1) [-]\n", ++n,
9116 ctl->nu[id]);
9117
9118 /* Write data... */
9119 for (int ir = 0; ir < obs->nr; ir++) {
9120 if (ir == 0 || obs->time[ir] != obs->time[ir - 1])
9121 fprintf(out, "\n");
9122 fprintf(out, "%.2f %g %g %g %g %g %g %g %g %g", obs->time[ir],
9123 obs->obsz[ir], obs->obslon[ir], obs->obslat[ir],
9124 obs->vpz[ir], obs->vplon[ir], obs->vplat[ir],
9125 obs->tpz[ir], obs->tplon[ir], obs->tplat[ir]);
9126 for (int id = 0; id < ctl->nd; id++)
9127 fprintf(out, " %g", obs->rad[id][ir]);
9128 for (int id = 0; id < ctl->nd; id++)
9129 fprintf(out, " %g", obs->tau[id][ir]);
9130 fprintf(out, "\n");
9131 }
9132
9133 /* Close file... */
9134 fclose(out);
9135}

◆ 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 9139 of file jurassic.c.

9142 {
9143
9144 /* Create file... */
9145 FILE *out;
9146 if (!(out = fopen(filename, "w")))
9147 ERRMSG("Cannot create file!");
9148
9149 /* Write header... */
9150 FWRITE("OBS1", char,
9151 4,
9152 out);
9153 FWRITE(&ctl->nd, int,
9154 1,
9155 out);
9156
9157 /* Write data... */
9158 size_t nr = (size_t) obs->nr;
9159 FWRITE(&nr, size_t,
9160 1,
9161 out);
9162 FWRITE(obs->time, double,
9163 nr,
9164 out);
9165 FWRITE(obs->obsz, double,
9166 nr,
9167 out);
9168 FWRITE(obs->obslon, double,
9169 nr,
9170 out);
9171 FWRITE(obs->obslat, double,
9172 nr,
9173 out);
9174 FWRITE(obs->vpz, double,
9175 nr,
9176 out);
9177 FWRITE(obs->vplon, double,
9178 nr,
9179 out);
9180 FWRITE(obs->vplat, double,
9181 nr,
9182 out);
9183 FWRITE(obs->tpz, double,
9184 nr,
9185 out);
9186 FWRITE(obs->tplon, double,
9187 nr,
9188 out);
9189 FWRITE(obs->tplat, double,
9190 nr,
9191 out);
9192 for (int id = 0; id < ctl->nd; id++)
9193 FWRITE(obs->rad[id], double,
9194 nr,
9195 out);
9196 for (int id = 0; id < ctl->nd; id++)
9197 FWRITE(obs->tau[id], double,
9198 nr,
9199 out);
9200
9201 /* Close file... */
9202 fclose(out);
9203}

◆ 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 9207 of file jurassic.c.

9211 {
9212
9213 char longname[LEN], varname[LEN];
9214 const char *spec_prefix = ctl->write_bbt ? "bt" : "rad";
9215
9216 int ncid, varid, dim_profile, dim_ray;
9217
9218 size_t ray_max;
9219
9220 /* Check number of rays... */
9221 if (obs->nr < 1 || obs->nr > NR)
9222 ERRMSG("Number of ray paths out of range!");
9223
9224 /* Open or create file... */
9225 if (nc_open(filename, NC_WRITE, &ncid) != NC_NOERR)
9226 NC(nc_create(filename, NC_NETCDF4, &ncid));
9227
9228 /* Enter define mode... */
9229 int r = nc_redef(ncid);
9230 if (r != NC_NOERR && r != NC_EINDEFINE)
9231 NC(r);
9232
9233 /* Define profile dimension (unlimited)... */
9234 if (nc_inq_dimid(ncid, "profile", &dim_profile) != NC_NOERR)
9235 NC(nc_def_dim(ncid, "profile", NC_UNLIMITED, &dim_profile));
9236
9237 /* Define ray dimension (fixed)... */
9238 if (nc_inq_dimid(ncid, "ray", &dim_ray) == NC_NOERR) {
9239 NC(nc_inq_dimlen(ncid, dim_ray, &ray_max));
9240 if (ray_max < 1 || ray_max > (size_t) NR)
9241 ERRMSG("netCDF dimension ray is out of range!");
9242 if ((size_t) obs->nr > ray_max)
9243 ERRMSG("profile has too many rays!");
9244 } else {
9245 ray_max = (size_t) obs->nr;
9246 NC(nc_def_dim(ncid, "ray", ray_max, &dim_ray));
9247 }
9248
9249 /* Dimension ID array... */
9250 int dimids[2] = { dim_profile, dim_ray };
9251
9252 /* Tunables for compression/quantization... */
9253 const int deflate_level = 0;
9254 const int quant_digits = 0;
9255
9256 /* Define nray (1D over profile)... */
9257 if (nc_inq_varid(ncid, "nray", &varid) != NC_NOERR)
9258 NC_DEF_VAR("nray", NC_INT, 1, dimids, "number of ray paths", "1", 0, 0);
9259
9260 /* Define geometry variables (2D over profile, ray)... */
9261 if (nc_inq_varid(ncid, "time", &varid) != NC_NOERR)
9262 NC_DEF_VAR("time", NC_DOUBLE, 2, dimids,
9263 "time in seconds since 2000-01-01, 00:00 UTC", "s",
9264 deflate_level, 0);
9265
9266 if (nc_inq_varid(ncid, "obs_z", &varid) != NC_NOERR)
9267 NC_DEF_VAR("obs_z", NC_DOUBLE, 2, dimids,
9268 "observer altitude", "km", deflate_level, 0);
9269
9270 if (nc_inq_varid(ncid, "obs_lon", &varid) != NC_NOERR)
9271 NC_DEF_VAR("obs_lon", NC_DOUBLE, 2, dimids,
9272 "observer longitude", "degrees_east", deflate_level, 0);
9273
9274 if (nc_inq_varid(ncid, "obs_lat", &varid) != NC_NOERR)
9275 NC_DEF_VAR("obs_lat", NC_DOUBLE, 2, dimids,
9276 "observer latitude", "degrees_north", deflate_level, 0);
9277
9278 if (nc_inq_varid(ncid, "vp_z", &varid) != NC_NOERR)
9279 NC_DEF_VAR("vp_z", NC_DOUBLE, 2, dimids,
9280 "view point altitude", "km", deflate_level, 0);
9281
9282 if (nc_inq_varid(ncid, "vp_lon", &varid) != NC_NOERR)
9283 NC_DEF_VAR("vp_lon", NC_DOUBLE, 2, dimids,
9284 "view point longitude", "degrees_east", deflate_level, 0);
9285
9286 if (nc_inq_varid(ncid, "vp_lat", &varid) != NC_NOERR)
9287 NC_DEF_VAR("vp_lat", NC_DOUBLE, 2, dimids,
9288 "view point latitude", "degrees_north", deflate_level, 0);
9289
9290 if (nc_inq_varid(ncid, "tp_z", &varid) != NC_NOERR)
9291 NC_DEF_VAR("tp_z", NC_DOUBLE, 2, dimids,
9292 "tangent point altitude", "km", deflate_level, 0);
9293
9294 if (nc_inq_varid(ncid, "tp_lon", &varid) != NC_NOERR)
9295 NC_DEF_VAR("tp_lon", NC_DOUBLE, 2, dimids,
9296 "tangent point longitude", "degrees_east", deflate_level, 0);
9297
9298 if (nc_inq_varid(ncid, "tp_lat", &varid) != NC_NOERR)
9299 NC_DEF_VAR("tp_lat", NC_DOUBLE, 2, dimids,
9300 "tangent point latitude", "degrees_north", deflate_level, 0);
9301
9302 /* Define radiance/transmittance per channel (2D profile,ray)... */
9303 for (int id = 0; id < ctl->nd; id++) {
9304
9305 sprintf(varname, "%s_%.4f", spec_prefix, ctl->nu[id]);
9306 if (nc_inq_varid(ncid, varname, &varid) != NC_NOERR) {
9307 if (ctl->write_bbt) {
9308 sprintf(longname, "brightness temperature (%.4f cm^-1)", ctl->nu[id]);
9309 NC_DEF_VAR(varname, NC_DOUBLE, 2, dimids, longname, "K",
9310 deflate_level, quant_digits);
9311 } else {
9312 sprintf(longname, "radiance (%.4f cm^-1)", ctl->nu[id]);
9313 NC_DEF_VAR(varname, NC_DOUBLE, 2, dimids, longname,
9314 "W/(m^2 sr cm^-1)", deflate_level, quant_digits);
9315 }
9316 }
9317
9318 sprintf(varname, "tau_%.4f", ctl->nu[id]);
9319 if (nc_inq_varid(ncid, varname, &varid) != NC_NOERR) {
9320 sprintf(longname, "transmittance (%.4f cm^-1)", ctl->nu[id]);
9321 NC_DEF_VAR(varname, NC_DOUBLE, 2, dimids, longname, "1",
9322 deflate_level, quant_digits);
9323 }
9324 }
9325
9326 /* Leave define mode... */
9327 NC(nc_enddef(ncid));
9328
9329 /* Hyperslabs... */
9330 size_t start[2] = { (size_t) profile, 0 };
9331 size_t count[2] = { 1, (size_t) obs->nr };
9332
9333 /* Write nray(profile)... */
9334 int nr = obs->nr;
9335 NC(nc_inq_varid(ncid, "nray", &varid));
9336 NC(nc_put_vara_int(ncid, varid, start, count, &nr));
9337
9338 /* Write geometry... */
9339 NC(nc_inq_varid(ncid, "time", &varid));
9340 NC(nc_put_vara_double(ncid, varid, start, count, obs->time));
9341
9342 NC(nc_inq_varid(ncid, "obs_z", &varid));
9343 NC(nc_put_vara_double(ncid, varid, start, count, obs->obsz));
9344
9345 NC(nc_inq_varid(ncid, "obs_lon", &varid));
9346 NC(nc_put_vara_double(ncid, varid, start, count, obs->obslon));
9347
9348 NC(nc_inq_varid(ncid, "obs_lat", &varid));
9349 NC(nc_put_vara_double(ncid, varid, start, count, obs->obslat));
9350
9351 NC(nc_inq_varid(ncid, "vp_z", &varid));
9352 NC(nc_put_vara_double(ncid, varid, start, count, obs->vpz));
9353
9354 NC(nc_inq_varid(ncid, "vp_lon", &varid));
9355 NC(nc_put_vara_double(ncid, varid, start, count, obs->vplon));
9356
9357 NC(nc_inq_varid(ncid, "vp_lat", &varid));
9358 NC(nc_put_vara_double(ncid, varid, start, count, obs->vplat));
9359
9360 NC(nc_inq_varid(ncid, "tp_z", &varid));
9361 NC(nc_put_vara_double(ncid, varid, start, count, obs->tpz));
9362
9363 NC(nc_inq_varid(ncid, "tp_lon", &varid));
9364 NC(nc_put_vara_double(ncid, varid, start, count, obs->tplon));
9365
9366 NC(nc_inq_varid(ncid, "tp_lat", &varid));
9367 NC(nc_put_vara_double(ncid, varid, start, count, obs->tplat));
9368
9369 /* Write spectral variables per channel... */
9370 for (int id = 0; id < ctl->nd; id++) {
9371 sprintf(varname, "%s_%.4f", spec_prefix, ctl->nu[id]);
9372 NC(nc_inq_varid(ncid, varname, &varid));
9373 NC(nc_put_vara_double(ncid, varid, start, count, obs->rad[id]));
9374
9375 sprintf(varname, "tau_%.4f", ctl->nu[id]);
9376 NC(nc_inq_varid(ncid, varname, &varid));
9377 NC(nc_put_vara_double(ncid, varid, start, count, obs->tau[id]));
9378 }
9379
9380 /* Close file... */
9381 NC(nc_sync(ncid));
9382 NC(nc_close(ncid));
9383}

◆ 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 9387 of file jurassic.c.

9391 {
9392
9393 /* Write info... */
9394 LOG(1, "Write shape function: %s", filename);
9395
9396 /* Create file... */
9397 FILE *out;
9398 if (!(out = fopen(filename, "w")))
9399 ERRMSG("Cannot create file!");
9400
9401 /* Write header... */
9402 fprintf(out,
9403 "# $1 = shape function x-value [-]\n"
9404 "# $2 = shape function y-value [-]\n\n");
9405
9406 /* Write data... */
9407 for (int i = 0; i < n; i++)
9408 fprintf(out, "%.10g %.10g\n", x[i], y[i]);
9409
9410 /* Close file... */
9411 fclose(out);
9412}

◆ 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 9416 of file jurassic.c.

9421 {
9422
9423 /* Get sizes... */
9424 const size_t n = s->size1;
9425
9426 /* Allocate... */
9427 atm_t *atm_aux;
9428 ALLOC(atm_aux, atm_t, 1);
9429 gsl_vector *x_aux = gsl_vector_alloc(n);
9430
9431 /* Compute standard deviation... */
9432 for (size_t i = 0; i < n; i++)
9433 gsl_vector_set(x_aux, i, sqrt(gsl_matrix_get(s, i, i)));
9434
9435 /* Write to disk... */
9436 char filename[LEN];
9437 const char *dirname;
9438 int profile;
9439 const char *shared_file = "-";
9440 copy_atm(ctl, atm_aux, atm, 1);
9441 x2atm(ctl, x_aux, atm_aux);
9442 if (strcmp(quantity, "total") == 0)
9443 shared_file = ret->shared_io_atm_err_total_file;
9444 else if (strcmp(quantity, "noise") == 0)
9445 shared_file = ret->shared_io_atm_err_noise_file;
9446 else if (strcmp(quantity, "formod") == 0)
9447 shared_file = ret->shared_io_atm_err_formod_file;
9448 sprintf(filename, "atm_err_%s.tab", quantity);
9449 const char *target =
9450 shared_io_output_target(ret, shared_file, filename, &dirname, &profile);
9451 write_atm(dirname, target, ctl, atm_aux, profile);
9452
9453 /* Free... */
9454 gsl_vector_free(x_aux);
9455}
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 9459 of file jurassic.c.

9461 {
9462
9463 /* Loop over emitters and detectors... */
9464 for (int ig = 0; ig < ctl->ng; ig++)
9465 for (int id = 0; id < ctl->nd; id++) {
9466
9467 /* Skip empty tables... */
9468 if (tbl->np[id][ig] <= 0) {
9469 WARN("Skip writing empty emissivity table: emitter=%s, nu=%.4f",
9470 ctl->emitter[ig], ctl->nu[id]);
9471 continue;
9472 }
9473
9474 /* Write ASCII look-up tables... */
9475 if (ctl->tblfmt == 1)
9476 write_tbl_asc(ctl, tbl, id, ig);
9477
9478 /* Write binary look-up tables... */
9479 else if (ctl->tblfmt == 2)
9480 write_tbl_bin(ctl, tbl, id, ig);
9481
9482 /* Write netCDF look-up tables... */
9483 else if (ctl->tblfmt == 3)
9484 write_tbl_nc(ctl, tbl, id, ig);
9485
9486 /* Write info... */
9487 TBL_LOG(tbl, id, ig);
9488 }
9489
9490 /* Write filter functions... */
9491 if (ctl->tblfmt == 1)
9492 for (int id = 0; id < ctl->nd; id++) {
9493 char filename[2 * LEN];
9494 sprintf(filename, "%s_%.4f.filt", ctl->tblbase, ctl->nu[id]);
9495 write_shape(filename, tbl->filt_nu[id], tbl->filt_f[id],
9496 tbl->filt_n[id]);
9497 }
9498}
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:9502
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:9586
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:9544
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:9387
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 9502 of file jurassic.c.

9506 {
9507
9508 /* Set filename... */
9509 char filename[2 * LEN];
9510 sprintf(filename, "%s_%.4f_%s.tab", ctl->tblbase,
9511 ctl->nu[id], ctl->emitter[ig]);
9512
9513 /* Create file... */
9514 FILE *out;
9515 if (!(out = fopen(filename, "w"))) {
9516 ERRMSG("Cannot create emissivity table: %s", filename);
9517 } else
9518 LOG(1, "Write emissivity table: %s", filename);
9519
9520 /* Write header... */
9521 fprintf(out,
9522 "# $1 = pressure [hPa]\n"
9523 "# $2 = temperature [K]\n"
9524 "# $3 = column density [molecules/cm^2]\n"
9525 "# $4 = emissivity [-]\n");
9526
9527 /* Save table file... */
9528 for (int ip = 0; ip < tbl->np[id][ig]; ip++)
9529 for (int it = 0; it < tbl->nt[id][ig][ip]; it++) {
9530 fprintf(out, "\n");
9531 for (int iu = 0; iu < tbl->nu[id][ig][ip][it]; iu++)
9532 fprintf(out, "%g %g %e %e\n",
9533 tbl->p[id][ig][ip], tbl->t[id][ig][ip][it],
9534 exp(tbl->logu[id][ig][ip][it][iu]),
9535 exp(tbl->logeps[id][ig][ip][it][iu]));
9536 }
9537
9538 /* Close file... */
9539 fclose(out);
9540}

◆ 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 9544 of file jurassic.c.

9548 {
9549
9550 /* Set filename... */
9551 char filename[2 * LEN];
9552 sprintf(filename, "%s_%.4f_%s.bin",
9553 ctl->tblbase, ctl->nu[id], ctl->emitter[ig]);
9554
9555 /* Create file... */
9556 FILE *out;
9557 if (!(out = fopen(filename, "w"))) {
9558 ERRMSG("Cannot create emissivity table: %s", filename);
9559 } else
9560 LOG(1, "Write emissivity table: %s", filename);
9561
9562 /* Pack... */
9563 size_t used = 0;
9564 const size_t need = tbl_packed_size(tbl, id, ig);
9565 uint8_t *work = NULL;
9566 ALLOC(work, uint8_t, need);
9567 tbl_pack(tbl, id, ig, work, &used);
9568 if (used != need)
9569 ERRMSG("Internal error: packed size mismatch!");
9570
9571 /* Write length and packed blob... */
9572 FWRITE(&used, size_t,
9573 1,
9574 out);
9575 FWRITE(work, uint8_t, used, out);
9576
9577 /* Close file... */
9578 fclose(out);
9579
9580 /* Free... */
9581 free(work);
9582}
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:7778
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:7832
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 9586 of file jurassic.c.

9590 {
9591
9592 /* Set filename... */
9593 char filename[2 * LEN];
9594 sprintf(filename, "%s_%s.nc", ctl->tblbase, ctl->emitter[ig]);
9595
9596 /* Open or create file... */
9597 int ncid;
9598 if (nc_open(filename, NC_WRITE, &ncid) != NC_NOERR) {
9599 if (nc_create(filename, NC_NETCDF4 | NC_CLOBBER, &ncid) != NC_NOERR)
9600 ERRMSG("Cannot open or create emissivity table: %s", filename);
9601 NC_PUT_ATT_GLOBAL("format_version", "1");
9602 NC_PUT_ATT_GLOBAL("emitter", ctl->emitter[ig]);
9603 NC(nc_enddef(ncid));
9604 }
9605
9606 /* Set variable and dimension name... */
9607 char varname[LEN], dimname[LEN];
9608 sprintf(varname, "tbl_%.4f", ctl->nu[id]);
9609 sprintf(dimname, "len_%.4f", ctl->nu[id]);
9610
9611 /* Write info... */
9612 LOG(1, "Write emissivity table: %s in %s", varname, filename);
9613
9614 /* Allocate work space... */
9615 size_t used = 0;
9616 const size_t need = tbl_packed_size(tbl, id, ig);
9617 uint8_t *work = NULL;
9618 ALLOC(work, uint8_t, need);
9619
9620 /* Pack table... */
9621 tbl_pack(tbl, id, ig, work, &used);
9622 if (used != need)
9623 ERRMSG("Internal error: packed size mismatch!");
9624
9625 /* Prevent overwrite... */
9626 int tmp;
9627 if (nc_inq_varid(ncid, varname, &tmp) == NC_NOERR)
9628 ERRMSG("Table already present!");
9629
9630 /* Add dimension and variable... */
9631 int dimid, varid;
9632 NC(nc_redef(ncid));
9633 NC(nc_def_dim(ncid, dimname, used, &dimid));
9634 int dimids[1] = { dimid };
9635 NC_DEF_VAR(varname, NC_UBYTE, 1, dimids,
9636 "Packed lookup table blob", "1", 0, 0);
9637 NC(nc_enddef(ncid));
9638
9639 /* Write data... */
9640 NC(nc_put_var_uchar(ncid, varid, (const unsigned char *) work));
9641
9642 /* Free... */
9643 free(work);
9644
9645 /* Close file... */
9646 NC(nc_close(ncid));
9647}
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
Definition: jurassic.h:1020
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 9651 of file jurassic.c.

9654 {
9655
9656 size_t n = 0;
9657
9658 /* Get pressure... */
9659 for (int ip = 0; ip < atm->np; ip++)
9660 if (atm->z[ip] >= ctl->retp_zmin && atm->z[ip] <= ctl->retp_zmax)
9661 x2atm_help(&atm->p[ip], x, &n);
9662
9663 /* Get temperature... */
9664 for (int ip = 0; ip < atm->np; ip++)
9665 if (atm->z[ip] >= ctl->rett_zmin && atm->z[ip] <= ctl->rett_zmax)
9666 x2atm_help(&atm->t[ip], x, &n);
9667
9668 /* Get volume mixing ratio... */
9669 for (int ig = 0; ig < ctl->ng; ig++)
9670 for (int ip = 0; ip < atm->np; ip++)
9671 if (atm->z[ip] >= ctl->retq_zmin[ig]
9672 && atm->z[ip] <= ctl->retq_zmax[ig])
9673 x2atm_help(&atm->q[ig][ip], x, &n);
9674
9675 /* Get extinction... */
9676 for (int iw = 0; iw < ctl->nw; iw++)
9677 for (int ip = 0; ip < atm->np; ip++)
9678 if (atm->z[ip] >= ctl->retk_zmin[iw]
9679 && atm->z[ip] <= ctl->retk_zmax[iw])
9680 x2atm_help(&atm->k[iw][ip], x, &n);
9681
9682 /* Get cloud data... */
9683 if (ctl->ret_clz)
9684 x2atm_help(&atm->clz, x, &n);
9685 if (ctl->ret_cldz)
9686 x2atm_help(&atm->cldz, x, &n);
9687 if (ctl->ret_clk)
9688 for (int icl = 0; icl < ctl->ncl; icl++)
9689 x2atm_help(&atm->clk[icl], x, &n);
9690
9691 /* Get surface data... */
9692 if (ctl->ret_sft)
9693 x2atm_help(&atm->sft, x, &n);
9694 if (ctl->ret_sfeps)
9695 for (int isf = 0; isf < ctl->nsf; isf++)
9696 x2atm_help(&atm->sfeps[isf], x, &n);
9697}
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:9701
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 9701 of file jurassic.c.

9704 {
9705
9706 /* Get state vector element... */
9707 *value = gsl_vector_get(x, *n);
9708 (*n)++;
9709}

◆ 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 9713 of file jurassic.c.

9716 {
9717
9718 size_t m = 0;
9719
9720 /* Decompose measurement vector... */
9721 for (int ir = 0; ir < obs->nr; ir++)
9722 for (int id = 0; id < ctl->nd; id++)
9723 if (isfinite(obs->rad[id][ir])) {
9724 obs->rad[id][ir] = gsl_vector_get(y, m);
9725 m++;
9726 }
9727}