MPTRAC
Data Structures | Macros | Functions
mptrac.h File Reference

MPTRAC library declarations. More...

#include <ctype.h>
#include <gsl/gsl_fft_complex.h>
#include <gsl/gsl_math.h>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_spline.h>
#include <gsl/gsl_statistics.h>
#include <math.h>
#include <netcdf.h>
#include <omp.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>

Go to the source code of this file.

Data Structures

struct  ctl_t
 Control parameters. More...
 
struct  atm_t
 Air parcel data. More...
 
struct  cache_t
 Cache data structure. More...
 
struct  clim_photo_t
 Climatological data in the form of photolysis rates. More...
 
struct  clim_ts_t
 Climatological data in the form of time series. More...
 
struct  clim_zm_t
 Climatological data in the form of zonal means. More...
 
struct  clim_t
 Climatological data. More...
 
struct  met_t
 Meteo data structure. More...
 

Macros

#define AVO   6.02214076e23
 Avogadro constant [1/mol]. More...
 
#define CPD   1003.5
 Specific heat of dry air at constant pressure [J/(kg K)]. More...
 
#define EPS   (MH2O / MA)
 Ratio of the specific gas constant of dry air and water vapor [1]. More...
 
#define G0   9.80665
 Standard gravity [m/s^2]. More...
 
#define H0   7.0
 Scale height [km]. More...
 
#define LV   2501000.
 Latent heat of vaporization of water [J/kg]. More...
 
#define KB   1.3806504e-23
 Boltzmann constant [kg m^2/(K s^2)]. More...
 
#define MA   28.9644
 Molar mass of dry air [g/mol]. More...
 
#define MH2O   18.01528
 Molar mass of water vapor [g/mol]. More...
 
#define MO3   48.00
 Molar mass of ozone [g/mol]. More...
 
#define P0   1013.25
 Standard pressure [hPa]. More...
 
#define RA   (1e3 * RI / MA)
 Specific gas constant of dry air [J/(kg K)]. More...
 
#define RE   6367.421
 Mean radius of Earth [km]. More...
 
#define RI   8.3144598
 Ideal gas constant [J/(mol K)]. More...
 
#define T0   273.15
 Standard temperature [K]. More...
 
#define LEN   5000
 Maximum length of ASCII data lines. More...
 
#define NP   10000000
 Maximum number of atmospheric data points. More...
 
#define NQ   15
 Maximum number of quantities per data point. More...
 
#define NCSI   1000000
 Maximum number of data points for CSI calculation. More...
 
#define EP   140
 Maximum number of pressure levels for meteo data. More...
 
#define EX   1202
 Maximum number of longitudes for meteo data. More...
 
#define EY   602
 Maximum number of latitudes for meteo data. More...
 
#define NENS   2000
 Maximum number of data points for ensemble analysis. More...
 
#define NOBS   10000000
 Maximum number of observation data points. More...
 
#define NTHREADS   512
 Maximum number of OpenMP threads. More...
 
#define CY   250
 Maximum number of latitudes for climatological data. More...
 
#define CO3   30
 Maximum number of total column ozone data for climatological data. More...
 
#define CP   70
 Maximum number of pressure levels for climatological data. More...
 
#define CSZA   50
 Maximum number of solar zenith angles for climatological data. More...
 
#define CT   12
 Maximum number of time steps for climatological data. More...
 
#define CTS   1000
 Maximum number of data points of climatological time series. More...
 
#define ALLOC(ptr, type, n)
 Allocate memory for a pointer with error handling. More...
 
#define ARRAY_2D(ix, iy, ny)    ((ix) * (ny) + (iy))
 Macro for computing the linear index of a 2D array element. More...
 
#define ARRAY_3D(ix, iy, ny, iz, nz)    (((ix)*(ny) + (iy)) * (nz) + (iz))
 Compute the linear index of a 3D array element. More...
 
#define ARRHENIUS(a, b, t)    ((a) * exp( -(b) / (t)))
 Calculate the Arrhenius rate constant. More...
 
#define DEG2DX(dlon, lat)    ((dlon) * M_PI * RE / 180. * cos((lat) / 180. * M_PI))
 Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude. More...
 
#define DEG2DY(dlat)    ((dlat) * M_PI * RE / 180.)
 Convert a latitude difference to a distance in the y-direction (north-south). More...
 
#define DP2DZ(dp, p)    (- (dp) * H0 / (p))
 Convert a pressure difference to a height difference in the vertical direction. More...
 
#define DX2DEG(dx, lat)
 Convert a distance in kilometers to degrees longitude at a given latitude. More...
 
#define DY2DEG(dy)    ((dy) * 180. / (M_PI * RE))
 Convert a distance in kilometers to degrees latitude. More...
 
#define DZ2DP(dz, p)    (-(dz) * (p) / H0)
 Convert a change in altitude to a change in pressure. More...
 
#define DIST(a, b)    sqrt(DIST2(a, b))
 Calculate the distance between two points in Cartesian coordinates. More...
 
#define DIST2(a, b)    ((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])+(a[2]-b[2])*(a[2]-b[2]))
 Calculate the squared Euclidean distance between two points in Cartesian coordinates. More...
 
#define DOTP(a, b)    (a[0]*b[0]+a[1]*b[1]+a[2]*b[2])
 Calculate the dot product of two vectors. More...
 
#define FMOD(x, y)    ((x) - (int) ((x) / (y)) * (y))
 Calculate the floating-point remainder of dividing x by y. More...
 
#define FREAD(ptr, type, size, in)
 Read data from a file stream and store it in memory. More...
 
#define FWRITE(ptr, type, size, out)
 Write data from memory to a file stream. More...
 
#define INTPOL_INIT    double cw[4] = {0.0, 0.0, 0.0, 0.0}; int ci[3] = {0, 0, 0};
 Initialize arrays for interpolation. More...
 
#define INTPOL_2D(var, init)
 Perform 2D interpolation for a meteorological variable. More...
 
#define INTPOL_3D(var, init)
 Perform 3D interpolation for a meteorological variable. More...
 
#define INTPOL_SPACE_ALL(p, lon, lat)
 Interpolate multiple meteorological variables in space. More...
 
#define INTPOL_TIME_ALL(time, p, lon, lat)
 Interpolate multiple meteorological variables in time. More...
 
#define LAPSE(p1, t1, p2, t2)
 Calculate lapse rate. More...
 
#define LIN(x0, y0, x1, y1, x)    ((y0)+((y1)-(y0))/((x1)-(x0))*((x)-(x0)))
 Linear interpolation. More...
 
#define MAX(a, b)    (((a)>(b))?(a):(b))
 Macro to determine the maximum of two values. More...
 
#define MET_HEADER
 Write header for meteorological data file. More...
 
#define MIN(a, b)    (((a)<(b))?(a):(b))
 Macro to determine the minimum of two values. More...
 
#define MOLEC_DENS(p, t)    (AVO * 1e-6 * ((p) * 100) / (RI * (t)))
 Calculate the density of a gas molecule. More...
 
#define NC(cmd)
 Execute a NetCDF command and check for errors. More...
 
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units)
 Define a NetCDF variable with attributes. More...
 
#define NC_GET_DOUBLE(varname, ptr, force)
 Retrieve a double-precision variable from a NetCDF file. More...
 
#define NC_INQ_DIM(dimname, ptr, min, max)
 Inquire the length of a dimension in a NetCDF file. More...
 
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
 Write double precision data to a NetCDF variable. More...
 
#define NC_PUT_FLOAT(varname, ptr, hyperslab)
 Write a float array to a NetCDF file. More...
 
#define NC_PUT_INT(varname, ptr, hyperslab)
 Write integer data to a NetCDF variable. More...
 
#define NC_PUT_ATT(varname, attname, text)
 Add a text attribute to a NetCDF variable. More...
 
#define NC_PUT_ATT_GLOBAL(attname, text)    NC(nc_put_att_text(ncid, NC_GLOBAL, attname, strnlen(text, LEN), text));
 Add a global text attribute to a NetCDF file. More...
 
#define NN(x0, y0, x1, y1, x)    (fabs((x) - (x0)) <= fabs((x) - (x1)) ? (y0) : (y1))
 Perform nearest-neighbor interpolation. More...
 
#define NORM(a)    sqrt(DOTP(a, a))
 Compute the norm (magnitude) of a vector. More...
 
#define PARTICLE_LOOP(ip0, ip1, check_dt, ...)
 Loop over particle indices with OpenACC acceleration. More...
 
#define P(z)    (P0 * exp(-(z) / H0))
 Compute pressure at given altitude. More...
 
#define PSAT(t)    (6.112 * exp(17.62 * ((t) - T0) / (243.12 + (t) - T0)))
 Compute saturation pressure over water. More...
 
#define PSICE(t)    (6.112 * exp(22.46 * ((t) - T0) / (272.62 + (t) - T0)))
 Compute saturation pressure over ice (WMO, 2018). More...
 
#define PW(p, h2o)    ((p) * MAX((h2o), 0.1e-6) / (1. + (1. - EPS) * MAX((h2o), 0.1e-6)))
 Calculate partial water vapor pressure. More...
 
#define RH(p, t, h2o)    (PW(p, h2o) / PSAT(t) * 100.)
 Compute relative humidity over water. More...
 
#define RHICE(p, t, h2o)    (PW(p, h2o) / PSICE(t) * 100.)
 Compute relative humidity over ice. More...
 
#define RHO(p, t)    (100. * (p) / (RA * (t)))
 Compute density of air. More...
 
#define ROETH_PHOTOL(a, b, c, sza)    ((c)*(sza) < M_PI/2. ? (a) * exp((b) * (1 - 1/cos((c) * (sza)))) : 0)
 Roeth approximation formula for photolysis reactions. More...
 
#define SET_ATM(qnt, val)
 Set atmospheric quantity value. More...
 
#define SET_QNT(qnt, name, longname, unit)
 Set atmospheric quantity index. More...
 
#define SH(h2o)    (EPS * MAX((h2o), 0.1e-6))
 Compute specific humidity from water vapor volume mixing ratio. More...
 
#define SQR(x)    ((x)*(x))
 Compute the square of a value. More...
 
#define SWAP(x, y, type)    do {type tmp = x; x = y; y = tmp;} while(0);
 Swap two values. More...
 
#define TDEW(p, h2o)
 Calculate dew point temperature. More...
 
#define TICE(p, h2o)
 Calculate frost point temperature (WMO, 2018). More...
 
#define THETA(p, t)    ((t) * pow(1000. / (p), 0.286))
 Compute potential temperature. More...
 
#define THETAVIRT(p, t, h2o)    (TVIRT(THETA((p), (t)), MAX((h2o), 0.1e-6)))
 Compute virtual potential temperature. More...
 
#define TOK(line, tok, format, var)
 Get string tokens. More...
 
#define TVIRT(t, h2o)    ((t) * (1. + (1. - EPS) * MAX((h2o), 0.1e-6)))
 Compute virtual temperature. More...
 
#define Z(p)    (H0 * log(P0 / (p)))
 Convert pressure to altitude. More...
 
#define ZDIFF(lnp0, t0, h2o0, lnp1, t1, h2o1)
 Calculate geopotential height difference. More...
 
#define ZETA(ps, p, t)
 Calculate potential vorticity using the Zeta approximation. More...
 
#define LOGLEV   2
 Level of log messages (0=none, 1=basic, 2=detailed, 3=debug). More...
 
#define LOG(level, ...)
 Print a log message with a specified logging level. More...
 
#define WARN(...)
 Print a warning message with contextual information. More...
 
#define ERRMSG(...)
 Print an error message with contextual information and terminate the program. More...
 
#define PRINT(format, var)
 Print the value of a variable with contextual information. More...
 
#define NTIMER   100
 Maximum number of timers. More...
 
#define PRINT_TIMERS    timer("END", "END", 1);
 Print the current state of all timers. More...
 
#define SELECT_TIMER(id, group, color)
 Select and start a timer with specific attributes. More...
 
#define START_TIMERS    NVTX_PUSH("START", NVTX_CPU);
 Starts a timer for tracking. More...
 
#define STOP_TIMERS    NVTX_POP;
 Stop the current timer. More...
 
#define NVTX_PUSH(range_title, range_color)   {}
 
#define NVTX_POP   {}
 

Functions

void thrustSortWrapper (double *__restrict__ c, int n, int *__restrict__ index)
 Wrapper to Thrust sorting function. More...
 
void broadcast_large_data (void *data, size_t N)
 Broadcasts large data across all processes in an MPI communicator. More...
 
void cart2geo (const double *x, double *z, double *lon, double *lat)
 Converts Cartesian coordinates to geographic coordinates. More...
 
double clim_oh (const ctl_t *ctl, const clim_t *clim, const double t, const double lon, const double lat, const double p)
 Calculates the hydroxyl radical (OH) concentration from climatology data, with an optional diurnal correction based on solar zenith angle. More...
 
void clim_oh_diurnal_correction (ctl_t *ctl, clim_t *clim)
 Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data. More...
 
double clim_photo (double rate[CP][CSZA][CO3], clim_photo_t *photo, double p, double sza, double o3c)
 Calculates the photolysis rate for a given set of atmospheric conditions. More...
 
double clim_tropo (const clim_t *clim, const double t, const double lat)
 Calculates the tropopause pressure based on climatological data. More...
 
void clim_tropo_init (clim_t *clim)
 Initializes the tropopause data in the climatology structure. More...
 
double clim_ts (const clim_ts_t *ts, const double t)
 Interpolates a time series of climatological variables. More...
 
double clim_zm (const clim_zm_t *zm, const double t, const double lat, const double p)
 Interpolates monthly mean zonal mean climatological variables. More...
 
void compress_cms (ctl_t *ctl, char *varname, float *array, size_t nx, size_t ny, size_t np, int decompress, FILE *inout)
 Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm. More...
 
void compress_pck (char *varname, float *array, size_t nxy, size_t nz, int decompress, FILE *inout)
 Compresses or decompresses a 3D array of floats. More...
 
void compress_zfp (char *varname, float *array, int nx, int ny, int nz, int precision, double tolerance, int decompress, FILE *inout)
 Compresses or decompresses a 3D array of floats using the ZFP library. More...
 
void compress_zstd (char *varname, float *array, size_t n, int decompress, FILE *inout)
 Compresses or decompresses an array of floats using the Zstandard (ZSTD) library. More...
 
void day2doy (const int year, const int mon, const int day, int *doy)
 Get day of year from date. More...
 
void doy2day (const int year, const int doy, int *mon, int *day)
 Converts a given day of the year (DOY) to a date (month and day). More...
 
void fft_help (double *fcReal, double *fcImag, int n)
 Computes the Fast Fourier Transform (FFT) of a complex sequence. 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 get_met (ctl_t *ctl, clim_t *clim, double t, met_t **met0, met_t **met1)
 Retrieves meteorological data for the specified time. More...
 
void get_met_help (ctl_t *ctl, double t, int direct, char *metbase, double dt_met, char *filename)
 Helper function to generate the filename for meteorological data. More...
 
void get_met_replace (char *orig, char *search, char *repl)
 Replaces occurrences of a substring in a string with another substring. More...
 
void get_tropo (int met_tropo, ctl_t *ctl, clim_t *clim, met_t *met, double *lons, int nx, double *lats, int ny, double *pt, double *zt, double *tt, double *qt, double *o3t, double *ps, double *zs)
 Calculate tropopause data. More...
 
void intpol_met_4d_coord (met_t *met0, float height0[EX][EY][EP], float array0[EX][EY][EP], met_t *met1, float height1[EX][EY][EP], float array1[EX][EY][EP], double ts, double height, double lon, double lat, double *var, int *ci, double *cw, int init)
 Interpolates meteorological variables to a given position and time. More...
 
void intpol_met_space_3d (met_t *met, float array[EX][EY][EP], double p, double lon, double lat, double *var, int *ci, double *cw, int init)
 Interpolates meteorological variables in 3D space. More...
 
void intpol_met_space_3d_ml (met_t *met, float array[EX][EY][EP], double p, double lon, double lat, double *var)
 Interpolates a meteorological variable in 3D space (longitude, latitude, pressure). More...
 
void intpol_met_space_2d (met_t *met, float array[EX][EY], double lon, double lat, double *var, int *ci, double *cw, int init)
 Interpolates meteorological variables in 2D space. More...
 
void intpol_met_time_3d (met_t *met0, float array0[EX][EY][EP], met_t *met1, float array1[EX][EY][EP], double ts, double p, double lon, double lat, double *var, int *ci, double *cw, int init)
 Interpolates meteorological data in 3D space and time. More...
 
void intpol_met_time_3d_ml (met_t *met0, float array0[EX][EY][EP], met_t *met1, float array1[EX][EY][EP], double ts, double p, double lon, double lat, double *var)
 Interpolates a meteorological variable in time and 3D space (longitude, latitude, pressure). More...
 
void intpol_met_time_2d (met_t *met0, float array0[EX][EY], met_t *met1, float array1[EX][EY], double ts, double lon, double lat, double *var, int *ci, double *cw, int init)
 Interpolates meteorological data in 2D space and time. More...
 
void intpol_tropo_3d (double time0, float array0[EX][EY], double time1, float array1[EX][EY], double lons[EX], double lats[EY], int nlon, int nlat, double time, double lon, double lat, int method, double *var, double *sigma)
 Interpolates tropopause data in 3D (latitude, longitude, and time). 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...
 
double kernel_weight (const double kz[EP], const double kw[EP], const int nk, const double p)
 Calculates the kernel weight based on altitude and given kernel data. More...
 
double lapse_rate (const double t, const double h2o)
 Calculates the moist adiabatic lapse rate in Kelvin per kilometer. More...
 
void level_definitions (ctl_t *ctl)
 Defines pressure levels for meteorological data. More...
 
int locate_irr (const double *xx, const int n, const double x)
 Locate the index of the interval containing a given value in a sorted array. More...
 
int locate_irr_float (const float *xx, const int n, const double x, const int ig)
 Locate the index of the interval containing a given value in an irregularly spaced array. More...
 
int locate_irr_3d (float profiles[EX][EY][EP], int np, int ind_lon, int ind_lat, double x)
 Locate the index of the interval containing a given value in a 3D irregular grid. More...
 
int locate_reg (const double *xx, const int n, const double x)
 Locate the index of the interval containing a given value in a regular grid. More...
 
void locate_vert (float profiles[EX][EY][EP], int np, int lon_ap_ind, int lat_ap_ind, double alt_ap, int *ind)
 Locate the four vertical indizes of a box for a given height value. More...
 
void module_advect (ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, double *dt)
 Performs the advection of atmospheric particles using meteorological data. More...
 
void module_advect_init (ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm)
 Initializes the advection module by setting up pressure fields. More...
 
void module_bound_cond (ctl_t *ctl, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm, double *dt)
 Apply boundary conditions to particles based on meteorological and climatological data. More...
 
void module_chemgrid (ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, double t)
 Calculate grid data for chemistry modules. More...
 
void module_chem_init (ctl_t *ctl, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Initializes the chemistry modules by setting atmospheric composition. More...
 
void module_convection (ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, double *dt, double *rs)
 Simulate convective processes for atmospheric particles. More...
 
void module_decay (ctl_t *ctl, clim_t *clim, atm_t *atm, double *dt)
 Simulate exponential decay processes for atmospheric particles. More...
 
void module_diffusion_meso (ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, cache_t *cache, double *dt, double *rs)
 Simulate mesoscale diffusion for atmospheric particles. More...
 
void module_diffusion_turb (ctl_t *ctl, clim_t *clim, atm_t *atm, double *dt, double *rs)
 Simulate turbulent diffusion for atmospheric particles. More...
 
void module_dry_deposition (ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, double *dt)
 Simulate dry deposition of atmospheric particles. More...
 
void module_h2o2_chem (ctl_t *ctl, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm, double *dt)
 Perform chemical reactions involving H2O2 within cloud particles. More...
 
void module_isosurf_init (ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, cache_t *cache)
 Initialize the isosurface module based on atmospheric data. More...
 
void module_isosurf (ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, cache_t *cache, double *dt)
 Apply the isosurface module to adjust atmospheric properties. More...
 
void module_kpp_chem (ctl_t *ctl, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm, double *dt)
 KPP chemistry module. More...
 
void module_meteo (ctl_t *ctl, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm, double *dt)
 Update atmospheric properties using meteorological data. More...
 
void module_mixing (ctl_t *ctl, clim_t *clim, atm_t *atm, double t)
 Update atmospheric properties through interparcel mixing. More...
 
void module_mixing_help (ctl_t *ctl, clim_t *clim, atm_t *atm, const int *ixs, const int *iys, const int *izs, int qnt_idx)
 Perform interparcel mixing for a specific quantity. More...
 
void module_oh_chem (ctl_t *ctl, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm, double *dt)
 Perform hydroxyl chemistry calculations for atmospheric particles. More...
 
void module_position (ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, double *dt)
 Update the positions and pressure levels of atmospheric particles. More...
 
void module_rng_init (int ntask)
 Initialize random number generators for parallel tasks. More...
 
void module_rng (ctl_t *ctl, double *rs, size_t n, int method)
 Generate random numbers using various methods and distributions. More...
 
void module_sedi (ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, double *dt)
 Simulate sedimentation of particles in the atmosphere. More...
 
void module_sort (ctl_t *ctl, met_t *met0, atm_t *atm)
 Sort particles according to box index. More...
 
void module_sort_help (double *a, const int *p, const int np)
 Reorder an array based on a given permutation. More...
 
void module_timesteps (ctl_t *ctl, met_t *met0, atm_t *atm, double *dt, double t)
 Calculate time steps for air parcels based on specified conditions. More...
 
void module_timesteps_init (ctl_t *ctl, atm_t *atm)
 Initialize start time and time interval for time-stepping. More...
 
void module_tracer_chem (ctl_t *ctl, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm, double *dt)
 Simulate chemical reactions involving long-lived atmospheric tracers. More...
 
void module_wet_deposition (ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, double *dt)
 Perform wet deposition calculations for air parcels. More...
 
double nat_temperature (const double p, const double h2o, const double hno3)
 Calculates the nitric acid trihydrate (NAT) temperature. More...
 
int read_atm (const char *filename, ctl_t *ctl, atm_t *atm)
 Reads air parcel data from a specified file into the given atmospheric structure. More...
 
int read_atm_asc (const char *filename, ctl_t *ctl, atm_t *atm)
 Reads air parcel data from an ASCII file and populates the given atmospheric structure. More...
 
int read_atm_bin (const char *filename, ctl_t *ctl, atm_t *atm)
 Reads air parcel data from a binary file and populates the given atmospheric structure. More...
 
int read_atm_clams (const char *filename, ctl_t *ctl, atm_t *atm)
 Reads air parcel data from a CLaMS netCDF file and populates the given atmospheric structure. More...
 
int read_atm_nc (const char *filename, ctl_t *ctl, atm_t *atm)
 Reads air parcel data from a generic netCDF file and populates the given atmospheric structure. More...
 
void read_clim (ctl_t *ctl, clim_t *clim)
 Reads various climatological data and populates the given climatology structure. More...
 
void read_clim_photo (const char *filename, clim_photo_t *photo)
 Reads photolysis rates from a NetCDF file and populates the given photolysis structure. More...
 
int read_clim_ts (const char *filename, clim_ts_t *ts)
 Reads a climatological time series from a file and populates the given time series structure. More...
 
void read_clim_zm (const char *filename, char *varname, clim_zm_t *zm)
 Reads zonally averaged climatological data from a netCDF file and populates the given structure. More...
 
void read_ctl (const char *filename, int argc, char *argv[], ctl_t *ctl)
 Reads control parameters from a configuration file and populates the given structure. More...
 
void read_kernel (const char *filename, double kz[EP], double kw[EP], int *nk)
 Reads kernel function data from a file and populates the provided arrays. More...
 
int read_met (const char *filename, ctl_t *ctl, clim_t *clim, met_t *met)
 Reads meteorological data from a file and populates the provided structures. More...
 
void read_met_bin_2d (FILE *in, met_t *met, float var[EX][EY], char *varname)
 Reads a 2-dimensional meteorological variable from a binary file and stores it in the provided array. More...
 
void read_met_bin_3d (FILE *in, ctl_t *ctl, met_t *met, float var[EX][EY][EP], char *varname, float bound_min, float bound_max)
 Reads 3D meteorological data from a binary file, potentially using different compression methods. More...
 
void read_met_cape (clim_t *clim, met_t *met)
 Calculates Convective Available Potential Energy (CAPE) for each grid point. More...
 
void read_met_cloud (met_t *met)
 Calculates cloud-related variables for each grid point. More...
 
void read_met_detrend (ctl_t *ctl, met_t *met)
 Detrends meteorological data. More...
 
void read_met_extrapolate (met_t *met)
 Extrapolates meteorological data. More...
 
void read_met_geopot (ctl_t *ctl, met_t *met)
 Calculates geopotential heights from meteorological data. More...
 
void read_met_grid (const char *filename, int ncid, ctl_t *ctl, met_t *met)
 Reads meteorological grid information from a NetCDF file. More...
 
void read_met_levels (int ncid, ctl_t *ctl, met_t *met)
 Reads meteorological variables at different vertical levels from a NetCDF file. More...
 
void read_met_ml2pl (ctl_t *ctl, met_t *met, float var[EX][EY][EP], char *varname)
 Interpolates meteorological data to specified pressure levels. More...
 
void read_met_monotonize (met_t *met)
 Makes zeta and pressure profiles monotone. More...
 
int read_met_nc_2d (int ncid, char *varname, char *varname2, char *varname3, char *varname4, ctl_t *ctl, met_t *met, float dest[EX][EY], float scl, int init)
 Reads a 2-dimensional meteorological variable from a NetCDF file. More...
 
int read_met_nc_3d (int ncid, char *varname, char *varname2, char *varname3, char *varname4, ctl_t *ctl, met_t *met, float dest[EX][EY][EP], float scl)
 Reads a 3-dimensional meteorological variable from a NetCDF file. More...
 
void read_met_pbl (met_t *met)
 Calculates the planetary boundary layer (PBL) height for each grid point. More...
 
void read_met_periodic (met_t *met)
 Applies periodic boundary conditions to meteorological data along longitudinal axis. More...
 
void read_met_polar_winds (met_t *met)
 Applies a fix for polar winds in meteorological data. More...
 
void read_met_pv (met_t *met)
 Calculates potential vorticity (PV) from meteorological data. More...
 
void read_met_ozone (met_t *met)
 Calculates the total column ozone from meteorological ozone data. More...
 
void read_met_sample (ctl_t *ctl, met_t *met)
 Downsamples meteorological data based on specified parameters. More...
 
void read_met_surface (int ncid, met_t *met, ctl_t *ctl)
 Reads surface meteorological data from a netCDF file and stores it in the meteorological data structure. More...
 
void read_met_tropo (ctl_t *ctl, clim_t *clim, met_t *met)
 Calculates the tropopause and related meteorological variables based on various methods and stores the results in the meteorological data structure. More...
 
void read_obs (const char *filename, ctl_t *ctl, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
 Reads observation data from a file and stores it in arrays. More...
 
void read_obs_asc (const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
 Reads observation data from an ASCII file. More...
 
void read_obs_nc (const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
 Reads observation data from a NetCDF file. More...
 
double scan_ctl (const char *filename, int argc, char *argv[], const char *varname, int arridx, const char *defvalue, char *value)
 Scans a control file or command-line arguments for a specified variable. More...
 
double sedi (const double p, const double T, const double rp, const double rhop)
 Calculates the sedimentation velocity of a particle in air. More...
 
void spline (const double *x, const double *y, const int n, const double *x2, double *y2, const int n2, const int method)
 Performs spline interpolation or linear interpolation. More...
 
float stddev (const float *data, const int n)
 Calculates the standard deviation of a set of data. More...
 
double sza_calc (const double sec, const double lon, const double lat)
 Calculates the solar zenith angle. 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 (const char *name, const char *group, int output)
 Measures and reports elapsed time for named and grouped timers. More...
 
double time_from_filename (const char *filename, int offset)
 Extracts and converts a timestamp from a filename to Julian seconds. More...
 
double tropo_weight (const clim_t *clim, const double t, const double lat, const double p)
 Computes the weighting factor for a given pressure with respect to the tropopause. More...
 
void write_atm (const char *filename, ctl_t *ctl, atm_t *atm, double t)
 Writes air parcel data to a file in various formats. More...
 
void write_atm_asc (const char *filename, ctl_t *ctl, atm_t *atm, double t)
 Writes air parcel data to an ASCII file or gnuplot. More...
 
void write_atm_bin (const char *filename, ctl_t *ctl, atm_t *atm)
 Writes air parcel data to a binary file. More...
 
void write_atm_clams (const char *filename, ctl_t *ctl, atm_t *atm)
 Writes air parcel data to a NetCDF file in the CLaMS format. More...
 
void write_atm_clams_traj (const char *dirname, ctl_t *ctl, atm_t *atm, double t)
 Writes CLaMS trajectory data to a NetCDF file. More...
 
void write_atm_nc (const char *filename, ctl_t *ctl, atm_t *atm)
 Writes air parcel data to a NetCDF file. More...
 
void write_csi (const char *filename, ctl_t *ctl, atm_t *atm, double t)
 Writes Critical Success Index (CSI) data to a file. More...
 
void write_ens (const char *filename, ctl_t *ctl, atm_t *atm, double t)
 Writes ensemble data to a file. More...
 
void write_grid (const char *filename, ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, double t)
 Writes grid data to a file in ASCII or netCDF format. More...
 
void write_grid_asc (const char *filename, ctl_t *ctl, double *cd, double *mean[NQ], double *sigma[NQ], double *vmr_impl, double t, double *z, double *lon, double *lat, double *area, double dz, int *np)
 Writes grid data to an ASCII file. More...
 
void write_grid_nc (const char *filename, ctl_t *ctl, double *cd, double *mean[NQ], double *sigma[NQ], double *vmr_impl, double t, double *z, double *lon, double *lat, double *area, double dz, int *np)
 Writes grid data to a NetCDF file. More...
 
int write_met (const char *filename, ctl_t *ctl, met_t *met)
 Writes meteorological data to a binary file. More...
 
void write_met_bin_2d (FILE *out, met_t *met, float var[EX][EY], char *varname)
 Writes a 2-dimensional meteorological variable to a binary file. More...
 
void write_met_bin_3d (FILE *out, ctl_t *ctl, met_t *met, float var[EX][EY][EP], char *varname, int precision, double tolerance)
 Writes a 3-dimensional meteorological variable to a binary file. More...
 
void write_output (const char *dirname, ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, double t)
 Writes various types of output data to files in a specified directory. More...
 
void write_prof (const char *filename, ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, double t)
 Writes profile data to a specified file. More...
 
void write_sample (const char *filename, ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, double t)
 Writes sample data to a specified file. More...
 
void write_station (const char *filename, ctl_t *ctl, atm_t *atm, double t)
 Writes station data to a specified file. More...
 
void write_vtk (const char *filename, ctl_t *ctl, atm_t *atm, double t)
 Writes VTK (Visualization Toolkit) data to a specified file. More...
 

Detailed Description

MPTRAC library declarations.

Definition in file mptrac.h.

Macro Definition Documentation

◆ AVO

#define AVO   6.02214076e23

Avogadro constant [1/mol].

Definition at line 157 of file mptrac.h.

◆ CPD

#define CPD   1003.5

Specific heat of dry air at constant pressure [J/(kg K)].

Definition at line 162 of file mptrac.h.

◆ EPS

#define EPS   (MH2O / MA)

Ratio of the specific gas constant of dry air and water vapor [1].

Definition at line 167 of file mptrac.h.

◆ G0

#define G0   9.80665

Standard gravity [m/s^2].

Definition at line 172 of file mptrac.h.

◆ H0

#define H0   7.0

Scale height [km].

Definition at line 177 of file mptrac.h.

◆ LV

#define LV   2501000.

Latent heat of vaporization of water [J/kg].

Definition at line 182 of file mptrac.h.

◆ KB

#define KB   1.3806504e-23

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

Definition at line 187 of file mptrac.h.

◆ MA

#define MA   28.9644

Molar mass of dry air [g/mol].

Definition at line 192 of file mptrac.h.

◆ MH2O

#define MH2O   18.01528

Molar mass of water vapor [g/mol].

Definition at line 197 of file mptrac.h.

◆ MO3

#define MO3   48.00

Molar mass of ozone [g/mol].

Definition at line 202 of file mptrac.h.

◆ P0

#define P0   1013.25

Standard pressure [hPa].

Definition at line 207 of file mptrac.h.

◆ RA

#define RA   (1e3 * RI / MA)

Specific gas constant of dry air [J/(kg K)].

Definition at line 212 of file mptrac.h.

◆ RE

#define RE   6367.421

Mean radius of Earth [km].

Definition at line 217 of file mptrac.h.

◆ RI

#define RI   8.3144598

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

Definition at line 222 of file mptrac.h.

◆ T0

#define T0   273.15

Standard temperature [K].

Definition at line 227 of file mptrac.h.

◆ LEN

#define LEN   5000

Maximum length of ASCII data lines.

Definition at line 236 of file mptrac.h.

◆ NP

#define NP   10000000

Maximum number of atmospheric data points.

Definition at line 241 of file mptrac.h.

◆ NQ

#define NQ   15

Maximum number of quantities per data point.

Definition at line 246 of file mptrac.h.

◆ NCSI

#define NCSI   1000000

Maximum number of data points for CSI calculation.

Definition at line 251 of file mptrac.h.

◆ EP

#define EP   140

Maximum number of pressure levels for meteo data.

Definition at line 256 of file mptrac.h.

◆ EX

#define EX   1202

Maximum number of longitudes for meteo data.

Definition at line 261 of file mptrac.h.

◆ EY

#define EY   602

Maximum number of latitudes for meteo data.

Definition at line 266 of file mptrac.h.

◆ NENS

#define NENS   2000

Maximum number of data points for ensemble analysis.

Definition at line 271 of file mptrac.h.

◆ NOBS

#define NOBS   10000000

Maximum number of observation data points.

Definition at line 276 of file mptrac.h.

◆ NTHREADS

#define NTHREADS   512

Maximum number of OpenMP threads.

Definition at line 281 of file mptrac.h.

◆ CY

#define CY   250

Maximum number of latitudes for climatological data.

Definition at line 286 of file mptrac.h.

◆ CO3

#define CO3   30

Maximum number of total column ozone data for climatological data.

Definition at line 291 of file mptrac.h.

◆ CP

#define CP   70

Maximum number of pressure levels for climatological data.

Definition at line 296 of file mptrac.h.

◆ CSZA

#define CSZA   50

Maximum number of solar zenith angles for climatological data.

Definition at line 301 of file mptrac.h.

◆ CT

#define CT   12

Maximum number of time steps for climatological data.

Definition at line 306 of file mptrac.h.

◆ CTS

#define CTS   1000

Maximum number of data points of climatological time series.

Definition at line 311 of file mptrac.h.

◆ ALLOC

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

Allocate memory for a pointer with error handling.

This macro allocates memory for a pointer of a given type and size using the calloc function. It includes error handling to check if memory allocation was successful. If the code is being compiled with OpenACC support (_OPENACC macro defined), it additionally checks if the code is running on a GPU device, and if not, it raises an error.

Parameters
ptrPointer variable to be allocated.
typeData type of the pointer.
nNumber of elements to allocate memory for.
Note
If the code is compiled without OpenACC support, the conditional check for GPU device is skipped.
Author
Lars Hoffmann

Definition at line 344 of file mptrac.h.

◆ ARRAY_2D

#define ARRAY_2D (   ix,
  iy,
  ny 
)     ((ix) * (ny) + (iy))

Macro for computing the linear index of a 2D array element.

The ARRAY_2D macro computes the linear index of a 2D array element based on the specified row index (ix), column index (iy), and number of columns (ny).

Parameters
ixInteger representing the row index of the 2D array element.
iyInteger representing the column index of the 2D array element.
nyInteger representing the number of columns in the 2D array.
Returns
The computed linear index of the 2D array element.

The macro computes the linear index using the formula: (ix) * (ny) + (iy). This formula assumes row-major storage, where elements of each row are stored sequentially in memory.

Author
Lars Hoffmann

Definition at line 367 of file mptrac.h.

◆ ARRAY_3D

#define ARRAY_3D (   ix,
  iy,
  ny,
  iz,
  nz 
)     (((ix)*(ny) + (iy)) * (nz) + (iz))

Compute the linear index of a 3D array element.

This macro computes the linear index of a 3D array element based on the specified row index (ix), column index (iy), depth index (iz), number of columns (ny), and number of depths (nz).

Parameters
ixRow index of the 3D array element.
iyColumn index of the 3D array element.
nyNumber of columns in the 3D array.
izDepth index of the 3D array element.
nzNumber of depths in the 3D array.
Returns
Linear index of the 3D array element.
Author
Lars Hoffmann

Definition at line 386 of file mptrac.h.

◆ ARRHENIUS

#define ARRHENIUS (   a,
  b,
 
)     ((a) * exp( -(b) / (t)))

Calculate the Arrhenius rate constant.

The Arrhenius equation is commonly used in chemical kinetics to describe the temperature dependence of reaction rates. This macro calculates the rate constant (k) based on the Arrhenius equation:

\[ k = a \times \exp( -b / T ), \]

where:

  • k is the rate constant.
  • a is the pre-exponential factor or frequency factor.
  • b is the activation energy.
  • T is the temperature in Kelvin.
Parameters
aPre-exponential factor or frequency factor.
bActivation energy.
tTemperature in Kelvin.
Returns
Calculated rate constant based on the Arrhenius equation.
Author
Mingzhao Liu

Definition at line 411 of file mptrac.h.

◆ DEG2DX

#define DEG2DX (   dlon,
  lat 
)     ((dlon) * M_PI * RE / 180. * cos((lat) / 180. * M_PI))

Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude.

This macro calculates the distance in the x-direction (east-west) corresponding to a given longitude difference at a specific latitude using the formula:

\[ dx = dlon \times \pi \times RE / 180 times \cos(lat), \]

where:

  • dx is the distance in the x-direction (east-west).
  • dlon is the difference in longitudes in degrees.
  • RE is the Earth's radius.
  • lat is the latitude in degrees.
Parameters
dlonDifference in longitudes in degrees.
latLatitude in degrees.
Returns
Distance in the x-direction (east-west) corresponding to the given longitude difference at the specified latitude.
Author
Lars Hoffmann

Definition at line 435 of file mptrac.h.

◆ DEG2DY

#define DEG2DY (   dlat)     ((dlat) * M_PI * RE / 180.)

Convert a latitude difference to a distance in the y-direction (north-south).

This macro calculates the distance in the y-direction (north-south) corresponding to a given latitude difference using the formula:

\[ dy = dlat \times \pi \times RE / 180, \]

where:

  • dy is the distance in the y-direction (north-south).
  • dlat is the difference in latitudes in degrees.
  • RE is the Earth's radius.
Parameters
dlatDifference in latitudes in degrees.
Returns
Distance in the y-direction (north-south) corresponding to the given latitude difference.
Author
Lars Hoffmann

Definition at line 456 of file mptrac.h.

◆ DP2DZ

#define DP2DZ (   dp,
 
)     (- (dp) * H0 / (p))

Convert a pressure difference to a height difference in the vertical direction.

This macro calculates the change in height (altitude) corresponding to a given pressure difference using the formula:

\[ dz = - (dp) \times H_0 / p \]

where:

  • dz is the change in height (altitude) in meters.
  • dp is the pressure difference in hPa.
  • H0 is a reference scale height in km.
  • p is the reference pressure in hPa.
Parameters
dpPressure difference in hPa.
pReference pressure in hPa.
Returns
Change in height (altitude) in kilometers corresponding to the given pressure difference.
Author
Lars Hoffmann

Definition at line 479 of file mptrac.h.

◆ DX2DEG

#define DX2DEG (   dx,
  lat 
)
Value:
(((lat) < -89.999 || (lat) > 89.999) ? 0 \
: (dx) * 180. / (M_PI * RE * cos((lat) / 180. * M_PI)))
#define RE
Mean radius of Earth [km].
Definition: mptrac.h:217

Convert a distance in kilometers to degrees longitude at a given latitude.

This macro calculates the change in longitude in degrees corresponding to a given distance in kilometers at a specified latitude on the Earth's surface. It uses the formula:

\[ dlon = \frac{dx \times 180}{\pi \times RE \times \cos(lat)} \]

Parameters
dxDistance in kilometers.
latLatitude in degrees.
Returns
Change in longitude in degrees.
Note
The latitude must be in the range [-89.999, 89.999] degrees. Otherwise, the macro return value will be zero. This avoids issues with the singularities at the poles.
Author
Lars Hoffmann

Definition at line 501 of file mptrac.h.

◆ DY2DEG

#define DY2DEG (   dy)     ((dy) * 180. / (M_PI * RE))

Convert a distance in kilometers to degrees latitude.

This macro calculates the change in latitude in degrees corresponding to a given distance in kilometers on the Earth's surface. It uses the formula:

\[ dlat = \frac{dy \times 180}{\pi \times RE} \]

Parameters
dyDistance in kilometers.
Returns
Change in latitude in degrees.
Author
Lars Hoffmann

Definition at line 519 of file mptrac.h.

◆ DZ2DP

#define DZ2DP (   dz,
 
)     (-(dz) * (p) / H0)

Convert a change in altitude to a change in pressure.

This macro calculates the change in pressure corresponding to a given change in altitude. It uses the hydrostatic equation:

\[ dp = -\left(dz \times \frac{p}{H_0}\right) \]

Parameters
dzChange in altitude in kilometers.
pCurrent pressure in hPa.
Returns
Change in pressure in hPa.
Author
Lars Hoffmann

Definition at line 536 of file mptrac.h.

◆ DIST

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

Calculate the distance between two points in Cartesian coordinates.

This macro calculates the Euclidean distance between two points in Cartesian coordinates. It uses the square root of the square of the distance obtained from the DIST2 macro.

Parameters
aCoordinates of the first point as an array of doubles.
bCoordinates of the second point as an array of doubles.
Returns
The distance between the two points.
Author
Lars Hoffmann

Definition at line 552 of file mptrac.h.

◆ DIST2

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

Calculate the squared Euclidean distance between two points in Cartesian coordinates.

This macro calculates the squared Euclidean distance between two points in Cartesian coordinates. It computes the sum of the squares of the differences of corresponding coordinates.

Parameters
aCoordinates of the first point as an array of doubles.
bCoordinates of the second point as an array of doubles.
Returns
The squared distance between the two points.
Author
Lars Hoffmann

Definition at line 568 of file mptrac.h.

◆ DOTP

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

Calculate the dot product of two vectors.

This macro computes the dot product of two vectors represented as arrays of doubles. It multiplies corresponding components of the vectors and sums the results.

Parameters
aThe first vector as an array of doubles.
bThe second vector as an array of doubles.
Returns
The dot product of the two vectors.
Author
Lars Hoffmann

Definition at line 584 of file mptrac.h.

◆ FMOD

#define FMOD (   x,
 
)     ((x) - (int) ((x) / (y)) * (y))

Calculate the floating-point remainder of dividing x by y.

This macro computes the floating-point remainder of dividing x by y. It calculates this remainder as x minus the integer part of (x / y) times y.

Parameters
xThe dividend.
yThe divisor.
Returns
The floating-point remainder of x divided by y.
Note
Macro has been added as a substitute when a GPU version of fmod() is missing.
Author
Lars Hoffmann

Definition at line 603 of file mptrac.h.

◆ FREAD

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

Read data from a file stream and store it in memory.

This macro reads data of a specified type from the given input file stream and stores it in the specified memory location. It ensures that the correct amount of data is read from the file stream, and if not, it raises an error.

Parameters
ptrPointer to the memory location where the data will be stored.
typeType of the data elements to be read.
sizeNumber of elements to read.
inFile stream from which to read the data.
Author
Lars Hoffmann

Definition at line 621 of file mptrac.h.

◆ FWRITE

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

Write data from memory to a file stream.

This macro writes data of a specified type from the specified memory location to the given output file stream. It ensures that the correct amount of data is written to the file stream, and if not, it raises an error.

Parameters
ptrPointer to the memory location containing the data to be written.
typeType of the data elements to be written.
sizeNumber of elements to write.
outFile stream to which the data will be written.
Author
Lars Hoffmann

Definition at line 641 of file mptrac.h.

◆ INTPOL_INIT

#define INTPOL_INIT    double cw[4] = {0.0, 0.0, 0.0, 0.0}; int ci[3] = {0, 0, 0};

Initialize arrays for interpolation.

This macro initializes arrays used for interpolation. It sets the weights cw and indices ci to zero. These arrays are used during interpolation to store the interpolation weights and indices.

Author
Lars Hoffmann

Definition at line 656 of file mptrac.h.

◆ INTPOL_2D

#define INTPOL_2D (   var,
  init 
)
Value:
intpol_met_time_2d(met0, met0->var, met1, met1->var, \
atm->time[ip], atm->lon[ip], atm->lat[ip], \
&var, ci, cw, init);
void intpol_met_time_2d(met_t *met0, float array0[EX][EY], met_t *met1, float array1[EX][EY], double ts, double lon, double lat, double *var, int *ci, double *cw, int init)
Interpolates meteorological data in 2D space and time.
Definition: mptrac.c:1609

Perform 2D interpolation for a meteorological variable.

This macro performs 2D interpolation for a given meteorological variable at a specific time and location.

Parameters
varThe variable to interpolate.
initA flag indicating whether to initialize the interpolation arrays (cw and ci). Set to 1 for initialization, 0 otherwise.
Returns
The interpolated value of the variable var.
Author
Lars Hoffmann

Definition at line 670 of file mptrac.h.

◆ INTPOL_3D

#define INTPOL_3D (   var,
  init 
)
Value:
intpol_met_time_3d(met0, met0->var, met1, met1->var, \
atm->time[ip], atm->p[ip], \
atm->lon[ip], atm->lat[ip], \
&var, ci, cw, init);
void intpol_met_time_3d(met_t *met0, float array0[EX][EY][EP], met_t *met1, float array1[EX][EY][EP], double ts, double p, double lon, double lat, double *var, int *ci, double *cw, int init)
Interpolates meteorological data in 3D space and time.
Definition: mptrac.c:1557

Perform 3D interpolation for a meteorological variable.

This macro performs 3D interpolation for a given meteorological variable at a specific time, pressure level, and location.

Parameters
varThe variable to interpolate.
initA flag indicating whether to initialize the interpolation arrays (cw and ci). Set to 1 for initialization, 0 otherwise.
Returns
The interpolated value of the variable var.
Author
Lars Hoffmann

Definition at line 687 of file mptrac.h.

◆ INTPOL_SPACE_ALL

#define INTPOL_SPACE_ALL (   p,
  lon,
  lat 
)

Interpolate multiple meteorological variables in space.

This macro performs spatial interpolation for multiple meteorological variables at a given pressure level, longitude, and latitude.

Parameters
pThe pressure level at which to interpolate the variables.
lonThe longitude at which to interpolate the variables.
latThe latitude at which to interpolate the variables.
Author
Lars Hofmann

Definition at line 706 of file mptrac.h.

◆ INTPOL_TIME_ALL

#define INTPOL_TIME_ALL (   time,
  p,
  lon,
  lat 
)

Interpolate multiple meteorological variables in time.

This macro performs temporal interpolation for multiple meteorological variables at a given time, pressure level, longitude, and latitude.

Parameters
timeThe time at which to interpolate the variables.
pThe pressure level at which to interpolate the variables.
lonThe longitude at which to interpolate the variables.
latThe latitude at which to interpolate the variables.
Author
Lars Hoffmann

Definition at line 757 of file mptrac.h.

◆ LAPSE

#define LAPSE (   p1,
  t1,
  p2,
  t2 
)
Value:
(1e3 * G0 / RA * ((t2) - (t1)) / ((t2) + (t1)) \
* ((p2) + (p1)) / ((p2) - (p1)))
#define RA
Specific gas constant of dry air [J/(kg K)].
Definition: mptrac.h:212
#define G0
Standard gravity [m/s^2].
Definition: mptrac.h:172

Calculate lapse rate.

This macro calculates the lapse rate between two pressure levels given their temperatures and pressures.

Parameters
p1Pressure at the first level (in hPa).
t1Temperature at the first level (in K).
p2Pressure at the second level (in hPa).
t2Temperature at the second level (in K).
Returns
The lapse rate (in K/km).
Author
Lars Hoffmann

Definition at line 808 of file mptrac.h.

◆ LIN

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

Linear interpolation.

This macro performs linear interpolation to estimate the value of y at a given x based on two points (x0, y0) and (x1, y1).

Parameters
x0X-coordinate of the first point.
y0Y-coordinate of the first point.
x1X-coordinate of the second point.
y1Y-coordinate of the second point.
xThe x-coordinate at which to estimate the y-value.
Returns
The estimated y-value at the given x-coordinate.
Author
Lars Hoffmann

Definition at line 827 of file mptrac.h.

◆ MAX

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

Macro to determine the maximum of two values.

This macro evaluates to the larger of its two arguments, a and b. It uses a ternary conditional operator to compare the values of a and b and returns a if a is greater than b; otherwise, it returns b.

Parameters
aThe first value to compare. Can be of any type that supports comparison.
bThe second value to compare. Can be of any type that supports comparison.
Returns
The larger of the two values, a or b.
Note
Both a and b are evaluated twice. If a or b have side effects (e.g., increment operators, function calls), the side effects will occur more than once. This can lead to unexpected behavior.
Warning
The macro does not perform type checking, so a and b should be of compatible types to avoid potential issues with comparison and return value.
Author
Lars Hoffmann

Definition at line 854 of file mptrac.h.

◆ MET_HEADER

#define MET_HEADER

Write header for meteorological data file.

This macro writes a header to a meteorological data file, providing information about the variables stored in the file and their corresponding columns.

Parameters
outPointer to the file stream where the header will be written.
Author
Lars Hoffmann

Definition at line 868 of file mptrac.h.

◆ MIN

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

Macro to determine the minimum of two values.

This macro evaluates to the smaller of its two arguments, a and b. It uses a ternary conditional operator to compare the values of a and b and returns a if a is less than b; otherwise, it returns b.

Parameters
aThe first value to compare. Can be of any type that supports comparison.
bThe second value to compare. Can be of any type that supports comparison.
Returns
The smaller of the two values, a or b.
Note
Both a and b are evaluated twice. If a or b have side effects (e.g., increment operators, function calls), the side effects will occur more than once. This can lead to unexpected behavior.
Warning
The macro does not perform type checking, so a and b should be of compatible types to avoid potential issues with comparison and return value.
Author
Lars Hoffmann

Definition at line 952 of file mptrac.h.

◆ MOLEC_DENS

#define MOLEC_DENS (   p,
 
)     (AVO * 1e-6 * ((p) * 100) / (RI * (t)))

Calculate the density of a gas molecule.

This macro calculates the density of a gas molecule using the provided pressure and temperature values.

Parameters
pPressure of the gas in Pascals.
tTemperature of the gas in Kelvin.
Returns
Density of the gas molecule in kg/m^3.
Author
Lars Hoffmann

Definition at line 967 of file mptrac.h.

◆ NC

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

Execute a NetCDF command and check for errors.

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

Parameters
cmdNetCDF command to execute.
Author
Lars Hoffmann

Definition at line 981 of file mptrac.h.

◆ NC_DEF_VAR

#define NC_DEF_VAR (   varname,
  type,
  ndims,
  dims,
  long_name,
  units 
)
Value:
{ \
NC(nc_def_var(ncid, varname, type, ndims, dims, &varid)); \
NC(nc_put_att_text(ncid, varid, "long_name", strnlen(long_name, LEN), long_name)); \
NC(nc_put_att_text(ncid, varid, "units", strnlen(units, LEN), units)); \
}
#define LEN
Maximum length of ASCII data lines.
Definition: mptrac.h:236

Define a NetCDF variable with attributes.

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

Parameters
varnameName of the variable.
typeData type of the variable.
ndimsNumber of dimensions for the variable.
dimsArray of dimension IDs.
long_nameLong name of the variable.
unitsUnits of the variable.
Author
Lars Hoffmann

Definition at line 1003 of file mptrac.h.

◆ NC_GET_DOUBLE

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

Retrieve a double-precision variable from a NetCDF file.

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

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

Definition at line 1026 of file mptrac.h.

◆ NC_INQ_DIM

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

Inquire the length of a dimension in a NetCDF file.

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

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

Definition at line 1054 of file mptrac.h.

◆ NC_PUT_DOUBLE

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

Write double precision data to a NetCDF variable.

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

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

Definition at line 1077 of file mptrac.h.

◆ NC_PUT_FLOAT

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

Write a float array to a NetCDF file.

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

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

Definition at line 1101 of file mptrac.h.

◆ NC_PUT_INT

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

Write integer data to a NetCDF variable.

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

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

Definition at line 1124 of file mptrac.h.

◆ NC_PUT_ATT

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

Add a text attribute to a NetCDF variable.

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

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

Definition at line 1146 of file mptrac.h.

◆ NC_PUT_ATT_GLOBAL

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

Add a global text attribute to a NetCDF file.

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

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

Definition at line 1163 of file mptrac.h.

◆ NN

#define NN (   x0,
  y0,
  x1,
  y1,
 
)     (fabs((x) - (x0)) <= fabs((x) - (x1)) ? (y0) : (y1))

Perform nearest-neighbor interpolation.

This macro returns the value of the nearest neighbor (y0 or y1) for a given x value. It compares the distances between x and x0, and between x and x1, and returns the y value corresponding to the closer x value.

Parameters
x0The x-coordinate of the first point.
y0The y-coordinate of the first point.
x1The x-coordinate of the second point.
y1The y-coordinate of the second point.
xThe x-coordinate for which the nearest neighbor is to be found.
Returns
The y-coordinate of the nearest neighbor (either y0 or y1).
Author
Lars Hoffmann

Definition at line 1183 of file mptrac.h.

◆ NORM

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

Compute the norm (magnitude) of a vector.

This macro computes the Euclidean norm (magnitude) of a vector a using the dot product of the vector with itself. The vector is assumed to have three components: a[0], a[1], and a[2].

Parameters
aThe vector for which the norm is to be computed.
Returns
The Euclidean norm of the vector.
Author
Lars Hoffmann

Definition at line 1198 of file mptrac.h.

◆ PARTICLE_LOOP

#define PARTICLE_LOOP (   ip0,
  ip1,
  check_dt,
  ... 
)
Value:
const int ip0_const = ip0; \
const int ip1_const = ip1; \
_Pragma("omp parallel for default(shared)") \
for (int ip = ip0_const; ip < ip1_const; ip++) \
if (!check_dt || dt[ip] != 0)

Loop over particle indices with OpenACC acceleration.

This macro defines a loop over particle indices from ip0 to ip1 with optional checking of dt. If _OPENACC is defined, the loop is accelerated using OpenACC directives. Otherwise, OpenMP parallelization is used.

Parameters
ip0The starting index of the loop (inclusive).
ip1The ending index of the loop (exclusive).
check_dtFlag indicating whether to check the array dt for non-zero values.
...Optional pragma directives to be applied.
Author
Lars Hoffmann

Definition at line 1225 of file mptrac.h.

◆ P

#define P (   z)     (P0 * exp(-(z) / H0))

Compute pressure at given altitude.

This macro calculates the pressure at a given altitude using the barometric formula.

Parameters
zThe altitude in kilometers.
Returns
The pressure in hPa at the given altitude.

The barometric formula used for this calculation is:

\[ P(z) = P_0 \times e^{-(z / H_0)}, \]

where:

  • \( P(z) \) is the pressure at altitude \( z \),
  • \( P_0 \) is the standard pressure,
  • \( H_0 \) is the scale height.

Note: The constants \( P_0 \) and \( H_0 \) must be defined before using this macro.

Author
Lars Hoffmann

Definition at line 1255 of file mptrac.h.

◆ PSAT

#define PSAT (   t)     (6.112 * exp(17.62 * ((t) - T0) / (243.12 + (t) - T0)))

Compute saturation pressure over water.

This macro calculates the saturation pressure over water based on the WMO (2018) formula.

Parameters
tThe temperature in degrees Celsius.
Returns
The saturation pressure over water at the given temperature.

The saturation pressure over water is calculated using the formula:

\[ P_{\textrm{sat}}(t) = 6.112 \times e^{17.62 \times \frac{(t - T_0)}{243.12 + (t - T_0)}}, \]

where:

  • \( P_{\textrm{sat}}(t) \) is the saturation pressure over water at temperature \( t \),
  • \( T_0 \) is the reference temperature (0°C).

Note: The constants \( T_0 \) must be defined before using this macro.

Author
Lars Hoffmann

Definition at line 1279 of file mptrac.h.

◆ PSICE

#define PSICE (   t)     (6.112 * exp(22.46 * ((t) - T0) / (272.62 + (t) - T0)))

Compute saturation pressure over ice (WMO, 2018).

This macro calculates the saturation pressure over ice based on the WMO (2018) formula.

Parameters
tThe temperature in K.
Returns
The saturation pressure over ice at the given temperature.

The saturation pressure over ice is calculated using the formula:

\[ P_{\textrm{ice}}(t) = 6.112 \times e^{22.46 \times \frac{(t - T_0)}{272.62 + (t - T_0)}}, \]

where:

  • \( P_{\textrm{ice}}(t) \) is the saturation pressure over ice at temperature \( t \),
  • \( T_0 \) is the reference temperature (0°C).

Note: The constant \( T_0 \) must be defined before using this macro.

Author
Lars Hoffmann

Definition at line 1303 of file mptrac.h.

◆ PW

#define PW (   p,
  h2o 
)     ((p) * MAX((h2o), 0.1e-6) / (1. + (1. - EPS) * MAX((h2o), 0.1e-6)))

Calculate partial water vapor pressure.

This macro calculates the partial water vapor pressure using the given total pressure and water vapor mixing ratio.

Parameters
pThe total pressure in hPa (hectopascals).
h2oThe water vapor mixing ratio in ppv (parts per volume).
Returns
The partial water vapor pressure.

The partial water vapor pressure is calculated using the formula:

\[ P_{\textrm{w}}(p, h_2o) = \frac{p \times \max(h_2o, 0.1 \times 10^{-6})}{1 + (1 - \epsilon) \times \max(h_2o, 0.1 \times 10^{-6})}, \]

where:

  • \( P_{\textrm{w}}(p, h_2o) \) is the partial water vapor pressure,
  • \( p \) is the total pressure in hPa,
  • \( h_2o \) is the water vapor mixing ratio in ppv,
  • \( \epsilon \) is the factor to account for saturation vapor pressure over water.

Note: The constant \( \epsilon \) must be defined before using this macro.

Author
Lars Hoffmann

Definition at line 1330 of file mptrac.h.

◆ RH

#define RH (   p,
  t,
  h2o 
)     (PW(p, h2o) / PSAT(t) * 100.)

Compute relative humidity over water.

This macro calculates the relative humidity over water using the given total pressure, temperature, and water vapor mixing ratio.

Parameters
pThe total pressure in hPa.
tThe temperature in K.
h2oThe water vapor mixing ratio in ppv (parts per volume).
Returns
The relative humidity over water in percentage.

The relative humidity over water is calculated using the formula:

\[ RH_{\textrm{w}}(p, t, h_2o) = \frac{P_{\textrm{w}}(p, h_2o)}{P_{\textrm{sat}}(t)} \times 100, \]

where:

  • \( RH_{\textrm{w}}(p, t, h_2o) \) is the relative humidity over water,
  • \( P_{\textrm{w}}(p, h_2o) \) is the partial water vapor pressure,
  • \( P_{\textrm{sat}}(t) \) is the saturation pressure over water at the given temperature,
  • \( p \) is the total pressure in hPa,
  • \( t \) is the temperature in Kelvin,
  • \( h_2o \) is the water vapor mixing ratio in ppv.

Note: The macros PW() and PSAT() must be defined before using this macro.

Author
Lars Hoffmann

Definition at line 1360 of file mptrac.h.

◆ RHICE

#define RHICE (   p,
  t,
  h2o 
)     (PW(p, h2o) / PSICE(t) * 100.)

Compute relative humidity over ice.

This macro calculates the relative humidity over ice using the given total pressure, temperature, and water vapor mixing ratio.

Parameters
pThe total pressure in hPa.
tThe temperature in K.
h2oThe water vapor mixing ratio in ppv (parts per volume).
Returns
The relative humidity over ice in percentage.

The relative humidity over ice is calculated using the formula:

\[ RH_{\textrm{ice}}(p, t, h_2o) = \frac{P_{\textrm{w}}(p, h_2o)}{P_{\textrm{ice}}(t)} \times 100, \]

where:

  • \( RH_{\textrm{ice}}(p, t, h_2o) \) is the relative humidity over ice,
  • \( P_{\textrm{w}}(p, h_2o) \) is the partial water vapor pressure,
  • \( P_{\textrm{ice}}(t) \) is the saturation pressure over ice at the given temperature,
  • \( p \) is the total pressure in hPa,
  • \( t \) is the temperature in Kelvin,
  • \( h_2o \) is the water vapor mixing ratio in ppv.

Note: The macros PW() and PSICE() must be defined before using this macro.

Author
Lars Hoffmann

Definition at line 1390 of file mptrac.h.

◆ RHO

#define RHO (   p,
 
)     (100. * (p) / (RA * (t)))

Compute density of air.

This macro calculates the density of air using the given total pressure and temperature.

Parameters
pThe total pressure in hPa.
tThe temperature in K.
Returns
The density of air in kg/m^3.

The density of air is calculated using the formula:

\[ \rho(p, t) = \frac{100 \times p}{R_a \times t}, \]

where:

  • \( \rho(p, t) \) is the density of air,
  • \( p \) is the total pressure in hPa,
  • \( t \) is the temperature in Kelvin,
  • \( R_a \) is the specific gas constant for dry air (287.05 J/(kg·K)).
Author
Lars Hoffmann

Definition at line 1415 of file mptrac.h.

◆ ROETH_PHOTOL

#define ROETH_PHOTOL (   a,
  b,
  c,
  sza 
)     ((c)*(sza) < M_PI/2. ? (a) * exp((b) * (1 - 1/cos((c) * (sza)))) : 0)

Roeth approximation formula for photolysis reactions.

This macro calculates the rate of a photolysis reaction using the Roeth approximation formula, which takes into account the solar zenith angle (SZA).

Parameters
aCoefficient 'a' in the Roeth formula.
bCoefficient 'b' in the Roeth formula.
cCoefficient 'c' in the Roeth formula.
szaThe solar zenith angle in radians.
Returns
The rate of the photolysis reaction.

The Roeth approximation formula for photolysis reactions is given by:

\[ ROETH\_PHOTOL(a, b, c, sza) = \begin{cases} a \times \exp\left(b \times \left(1 - \frac{1}{\cos(c \times sza)}\right)\right), \textrm{if } c \times sza < \frac{\pi}{2} \\ 0, \textrm{otherwise} \end{cases} \]

where:

  • 'a', 'b', and 'c' are coefficients specific to the photolysis reaction.
  • 'sza' is the solar zenith angle in radians.
Author
Mingzhao Liu

Definition at line 1446 of file mptrac.h.

◆ SET_ATM

#define SET_ATM (   qnt,
  val 
)
Value:
if (ctl->qnt >= 0) \
atm->q[ctl->qnt][ip] = val;

Set atmospheric quantity value.

This macro sets the value of a specific atmospheric quantity at a given index 'ip'. The macro first checks if the control index 'ctl->qnt' is non-negative before assigning the value, ensuring that the quantity index is valid.

Parameters
qntThe index representing the atmospheric quantity to set.
valThe value to set for the atmospheric quantity.
Note
The macro assumes the existence of structures 'ctl' and 'atm' containing the control indices and atmospheric data, respectively, and an index 'ip' representing the data point.
Author
Lars Hoffmann

Definition at line 1465 of file mptrac.h.

◆ SET_QNT

#define SET_QNT (   qnt,
  name,
  longname,
  unit 
)
Value:
if (strcasecmp(ctl->qnt_name[iq], name) == 0) { \
ctl->qnt = iq; \
sprintf(ctl->qnt_longname[iq], longname); \
sprintf(ctl->qnt_unit[iq], unit); \
} else

Set atmospheric quantity index.

This macro sets the index, long name, and unit of a specific atmospheric quantity based on its name. It compares the name parameter with the name of the atmospheric quantity stored in 'ctl->qnt_name'. If a match is found, it assigns the index to 'ctl->qnt', updates the long name, and updates the unit.

Parameters
qntThe index representing the atmospheric quantity.
nameThe name of the atmospheric quantity.
longnameThe long name of the atmospheric quantity.
unitThe unit of the atmospheric quantity.
Note
The macro assumes the existence of structures 'ctl' containing control information. It also assumes the presence of 'iq', representing the index of the atmospheric quantity.
Author
Lars Hoffmann

Definition at line 1488 of file mptrac.h.

◆ SH

#define SH (   h2o)     (EPS * MAX((h2o), 0.1e-6))

Compute specific humidity from water vapor volume mixing ratio.

This macro calculates the specific humidity from the water vapor volume mixing ratio. Specific humidity represents the ratio of the mass of water vapor to the total mass of air and is dimensionless.

Parameters
h2oThe water vapor volume mixing ratio.
Returns
The specific humidity.
Note
The macro assumes that 'EPS' is defined and represents the ratio of the molecular weight of water vapor to the molecular weight of dry air.
Author
Lars Hoffmann

Definition at line 1509 of file mptrac.h.

◆ SQR

#define SQR (   x)     ((x)*(x))

Compute the square of a value.

This macro computes the square of the input value.

Parameters
xThe input value.
Returns
The square of the input value.
Author
Lars Hoffmann

Definition at line 1522 of file mptrac.h.

◆ SWAP

#define SWAP (   x,
  y,
  type 
)     do {type tmp = x; x = y; y = tmp;} while(0);

Swap two values.

This macro swaps the values of two variables of the specified type.

Parameters
xThe first variable to be swapped.
yThe second variable to be swapped.
typeThe type of the variables.
Author
Lars Hoffmann

Definition at line 1536 of file mptrac.h.

◆ TDEW

#define TDEW (   p,
  h2o 
)
Value:
(T0 + 243.12 * log(PW((p), (h2o)) / 6.112) \
/ (17.62 - log(PW((p), (h2o)) / 6.112)))
#define PW(p, h2o)
Calculate partial water vapor pressure.
Definition: mptrac.h:1330
#define T0
Standard temperature [K].
Definition: mptrac.h:227

Calculate dew point temperature.

This macro computes the dew point temperature using the formula provided by the World Meteorological Organization (WMO, 2018).

Parameters
pThe atmospheric pressure in hPa.
h2oThe water vapor volume mixing ratio.
Returns
The dew point temperature in Kelvin.

Formula:

\[ T_{\textrm{dew}} = T_0 + \frac{243.12 \times \ln\left(\frac{{P_W(p, h_{2}O)}}{6.112}\right)}{17.62 - \ln\left(\frac{{P_W(p, h_{2}O)}}{6.112}\right)} \]

where:

  • \( T_{\textrm{dew}} \) is the dew point temperature.
  • \( T_0 \) is the reference temperature in Kelvin (typically 273.15 K).
  • \( P_W(p, h_{2}O) \) is the partial water vapor pressure.
Author
Lars Hoffmann

Definition at line 1560 of file mptrac.h.

◆ TICE

#define TICE (   p,
  h2o 
)
Value:
(T0 + 272.62 * log(PW((p), (h2o)) / 6.112) \
/ (22.46 - log(PW((p), (h2o)) / 6.112)))

Calculate frost point temperature (WMO, 2018).

This macro computes the frost point temperature using the formula provided by the World Meteorological Organization (WMO, 2018).

Parameters
pThe atmospheric pressure in hPa.
h2oThe water vapor volume mixing ratio.
Returns
The frost point temperature in Kelvin.

Formula:

\[ T_{\textrm{ice}} = T_0 + \frac{272.62 \times \ln\left(\frac{{P_W(p, h_{2}O)}}{6.112}\right)}{22.46 - \ln\left(\frac{{P_W(p, h_{2}O)}}{6.112}\right)} \]

where:

  • \( T_{\textrm{ice}} \) is the frost point temperature.
  • \( T_0 \) is the reference temperature in Kelvin (typically 273.15 K).
  • \( P_W(p, h_{2}O) \) is the partial water vapor pressure.
Author
Lars Hoffmann

Definition at line 1585 of file mptrac.h.

◆ THETA

#define THETA (   p,
 
)     ((t) * pow(1000. / (p), 0.286))

Compute potential temperature.

This macro calculates the potential temperature of the atmosphere.

Parameters
pThe atmospheric pressure in hPa.
tThe temperature in Kelvin.
Returns
The potential temperature in Kelvin.

Formula:

\[ \theta = T \left( \frac{1000}{P} \right)^{0.286} \]

where:

  • \( \theta \) is the potential temperature.
  • \( T \) is the temperature in Kelvin.
  • \( P \) is the atmospheric pressure in hPa.
Author
Lars Hoffmann

Definition at line 1609 of file mptrac.h.

◆ THETAVIRT

#define THETAVIRT (   p,
  t,
  h2o 
)     (TVIRT(THETA((p), (t)), MAX((h2o), 0.1e-6)))

Compute virtual potential temperature.

This macro calculates the virtual potential temperature of the atmosphere, which takes into account the effect of water vapor on the atmosphere's buoyancy.

Parameters
pThe atmospheric pressure in hPa.
tThe temperature in Kelvin.
h2oThe water vapor volume mixing ratio (ppv).
Returns
The virtual potential temperature in Kelvin.

Formula:

The virtual potential temperature ( \( \theta_v \)) is computed as

\[ \theta_v = \theta \left( 1 + \frac{0.61 \times q}{\epsilon} \right), \]

where:

  • \( \theta_v \) is the virtual potential temperature.
  • \( \theta \) is the potential temperature.
  • \( q \) is the specific humidity.
  • \( \epsilon \) is the ratio of the molecular weight of water vapor to dry air.
Author
Lars Hoffmann

Definition at line 1638 of file mptrac.h.

◆ TOK

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

Get string tokens.

This macro extracts tokens from a given string, typically used for parsing input lines.

Parameters
lineThe input string containing tokens.
tokA pointer to the token string.
formatThe format string specifying the expected format of the token.
varThe variable to store the parsed token value.

The macro tokenizes the input line using space and tab characters as delimiters. It then parses each token according to the specified format string and stores the parsed value in the provided variable.

Author
Lars Hoffmann

Definition at line 1659 of file mptrac.h.

◆ TVIRT

#define TVIRT (   t,
  h2o 
)     ((t) * (1. + (1. - EPS) * MAX((h2o), 0.1e-6)))

Compute virtual temperature.

This macro calculates the virtual temperature of air given its temperature and water vapor volume mixing ratio.

Parameters
tThe temperature of the air in Kelvin.
h2oThe water vapor volume mixing ratio.
Returns
The virtual temperature of the air.

The virtual temperature (T_v) is computed as the temperature (t) multiplied by (1 + (1 - EPS) * max(h2o, 0.1e-6)), where EPS is the ratio of the molar mass of water vapor to the molar mass of dry air.

Note
EPS is typically defined as 0.622.
Author
Lars Hoffmann

Definition at line 1684 of file mptrac.h.

◆ Z

#define Z (   p)     (H0 * log(P0 / (p)))

Convert pressure to altitude.

This macro calculates the altitude from the given pressure using the barometric formula.

Parameters
pThe pressure in hPa (hectopascal).
Returns
The altitude in kilometers (km).

Formula:

The altitude (z) is computed as H0 times the natural logarithm of the ratio of the reference pressure (P0) to the given pressure (p), where H0 is the scale height and P0 is the reference pressure at sea level.

Note
H0 and P0 are typically defined as constants specific to the atmosphere.
Author
Lars Hoffmann

Definition at line 1706 of file mptrac.h.

◆ ZDIFF

#define ZDIFF (   lnp0,
  t0,
  h2o0,
  lnp1,
  t1,
  h2o1 
)
Value:
(RI / MA / G0 * 0.5 * (TVIRT((t0), (h2o0)) + TVIRT((t1), (h2o1))) \
* ((lnp0) - (lnp1)))
#define TVIRT(t, h2o)
Compute virtual temperature.
Definition: mptrac.h:1684
#define MA
Molar mass of dry air [g/mol].
Definition: mptrac.h:192
#define RI
Ideal gas constant [J/(mol K)].
Definition: mptrac.h:222

Calculate geopotential height difference.

This macro calculates the geopotential height difference between two pressure levels using the hypsometric equation.

Parameters
lnp0The natural logarithm of the pressure at the first level.
t0The temperature at the first level in Kelvin (K).
h2o0The water vapor volume mixing ratio at the first level.
lnp1The natural logarithm of the pressure at the second level.
t1The temperature at the second level in Kelvin (K).
h2o1The water vapor volume mixing ratio at the second level.
Returns
The geopotential height difference in kilometers (km).

Formula: The geopotential height difference (dz) is computed as a function of the difference in natural logarithm of pressure (lnp) between the two levels, the average virtual temperature (ThetaVirt) of the two levels, the specific gas constant for dry air (RI), and the acceleration due to gravity at the surface of the Earth (G0).

Note
The specific gas constant for dry air (RI), the molar mass of dry air (MA), and the acceleration due to gravity at the surface of the Earth (G0) are typically defined as constants specific to the atmosphere.
Author
Lars Hoffmann

Definition at line 1737 of file mptrac.h.

◆ ZETA

#define ZETA (   ps,
  p,
 
)
Value:
(((p) / (ps) <= 0.3 ? 1. : \
sin(M_PI / 2. * (1. - (p) / (ps)) / (1. - 0.3))) \
* THETA((p), (t)))
#define THETA(p, t)
Compute potential temperature.
Definition: mptrac.h:1609

Calculate potential vorticity using the Zeta approximation.

This macro calculates the potential vorticity using the Zeta approximation, which is a function of pressure, surface pressure, and temperature.

Parameters
psSurface pressure in hPa.
pPressure at the given level in hPa.
tTemperature at the given level in Kelvin (K).
Returns
The potential vorticity.

Formula: The potential vorticity (Zeta) is computed based on the given pressure (p), surface pressure (ps), and temperature (t). It involves the potential temperature (Theta) at the given pressure level.

Note
The potential vorticity is approximated using the Zeta approximation, which includes conditions based on pressure ratio and a sinusoidal function. Adjust the constants if the approximation or conditions differ from the standard Zeta approximation formula.
Author
Lars Hoffmann

Definition at line 1768 of file mptrac.h.

◆ LOGLEV

#define LOGLEV   2

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

Definition at line 1779 of file mptrac.h.

◆ LOG

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

Print a log message with a specified logging level.

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

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

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

The macro expands to a block of code that:

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

Definition at line 1811 of file mptrac.h.

◆ WARN

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

Print a warning message with contextual information.

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

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

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

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

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

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

Definition at line 1848 of file mptrac.h.

◆ ERRMSG

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

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

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

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

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

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

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

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

Definition at line 1881 of file mptrac.h.

◆ PRINT

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

Print the value of a variable with contextual information.

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

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

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

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

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

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

Definition at line 1916 of file mptrac.h.

◆ NTIMER

#define NTIMER   100

Maximum number of timers.

Definition at line 1925 of file mptrac.h.

◆ PRINT_TIMERS

#define PRINT_TIMERS    timer("END", "END", 1);

Print the current state of all timers.

This macro calls the timer function with predefined arguments to signify the end of the timer logging process. It is used to print the results of all the timers that have been tracked.

Note
The timer function must be defined elsewhere in the codebase for this macro to function correctly.
Author
Lars Hoffmann

Definition at line 1940 of file mptrac.h.

◆ SELECT_TIMER

#define SELECT_TIMER (   id,
  group,
  color 
)
Value:
{ \
NVTX_POP; \
NVTX_PUSH(id, color); \
timer(id, group, 0); \
}

Select and start a timer with specific attributes.

This macro stops the current timer (if any) and starts a new timer with the specified ID, group, and color. It uses the NVTX_POP and NVTX_PUSH macros for managing timer events and the timer function to log the timer start event.

Parameters
idThe identifier for the timer.
groupThe group name associated with the timer.
colorThe color code associated with the timer for NVTX visualization.
Note
The NVTX_POP, NVTX_PUSH, and timer functions/macros must be defined elsewhere in the codebase for this macro to function correctly.
Author
Lars Hoffmann

Definition at line 1961 of file mptrac.h.

◆ START_TIMERS

#define START_TIMERS    NVTX_PUSH("START", NVTX_CPU);

Starts a timer for tracking.

This macro initializes the timer tracking process by pushing a start event onto the stack using the NVTX_PUSH macro with a predefined ID ("START") and color (NVTX_CPU).

Note
The NVTX_PUSH macro must be defined elsewhere in the codebase for this macro to function correctly.
Author
Lars Hoffmann

Definition at line 1980 of file mptrac.h.

◆ STOP_TIMERS

#define STOP_TIMERS    NVTX_POP;

Stop the current timer.

This macro stops the current timer by popping the top event from the stack using the NVTX_POP macro.

Note
The NVTX_POP macro must be defined elsewhere in the codebase for this macro to function correctly.
Author
Lars Hoffmann

Definition at line 1995 of file mptrac.h.

◆ NVTX_PUSH

#define NVTX_PUSH (   range_title,
  range_color 
)    {}

Definition at line 2087 of file mptrac.h.

◆ NVTX_POP

#define NVTX_POP   {}

Definition at line 2088 of file mptrac.h.

Function Documentation

◆ thrustSortWrapper()

void thrustSortWrapper ( double *__restrict__  c,
int  n,
int *__restrict__  index 
)

Wrapper to Thrust sorting function.

This function serves as a wrapper for a Thrust sorting operation, sorting the array c and maintaining the correspondence with the index array.

Parameters
cPointer to the array of double values to be sorted.
nThe number of elements in the array c.
indexPointer to the array of indices, which will be updated to reflect the sorted order.

The thrustSortWrapper function uses the Thrust library to sort the array c in ascending order. The index array is updated to reflect the new order of elements in c after sorting.

This function is particularly useful when the sorted order of elements needs to be tracked by indices.

Note
  • The c and index arrays must be of the same length n.
  • The function assumes that the Thrust library is properly included and configured in the project.
Author
Kaveh Haghighi Mood

◆ broadcast_large_data()

void broadcast_large_data ( void *  data,
size_t  N 
)

Broadcasts large data across all processes in an MPI communicator.

This function divides the data into manageable chunks and broadcasts each chunk sequentially. This approach is necessary because the data size may exceed the maximum allowable message size for a single MPI_Bcast operation.

Parameters
dataPointer to the data to be broadcasted.
NSize of the data in bytes.

The function first broadcasts the total size of the data to all processes. Then, it calculates the number of chunks needed to broadcast the entire data. Each chunk is broadcasted in sequence until the entire data has been sent.

The maximum chunk size is defined as CHUNK_SIZE (2147483647 bytes).

Note
The function assumes that the MPI environment has been initialized before calling this function and will be finalized afterward.
Author
Lars Hoffmann

◆ 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

Converts Cartesian coordinates to geographic coordinates.

Definition at line 74 of file mptrac.c.

78 {
79
80 double radius = NORM(x);
81 *lat = asin(x[2] / radius) * 180. / M_PI;
82 *lon = atan2(x[1], x[0]) * 180. / M_PI;
83 *z = radius - RE;
84}
#define NORM(a)
Compute the norm (magnitude) of a vector.
Definition: mptrac.h:1198

◆ clim_oh()

double clim_oh ( const ctl_t ctl,
const clim_t clim,
const double  t,
const double  lon,
const double  lat,
const double  p 
)

Calculates the hydroxyl radical (OH) concentration from climatology data, with an optional diurnal correction based on solar zenith angle.

This function retrieves OH data from a given climatology and applies a diurnal correction if the correction factor (oh_chem_beta) is greater than zero. The diurnal correction accounts for the variation in OH concentration due to changes in the solar zenith angle.

Parameters
ctlPointer to the control structure containing configuration parameters.
climPointer to the climatology structure containing OH data.
tTime at which the OH concentration is to be calculated.
lonLongitude at which the OH concentration is to be calculated.
latLatitude at which the OH concentration is to be calculated.
pPressure level at which the OH concentration is to be calculated.
Returns
The OH concentration at the specified time, location, and pressure, possibly adjusted by a diurnal correction.
Authors
Lars Hoffmann
Mingzhao Liu

Definition at line 88 of file mptrac.c.

94 {
95
96 /* Get OH data from climatology... */
97 double oh = clim_zm(&clim->oh, t, lat, p);
98
99 /* Apply diurnal correction... */
100 if (ctl->oh_chem_beta > 0) {
101 double sza = sza_calc(t, lon, lat);
102 if (sza <= M_PI / 2. * 85. / 90.)
103 return oh * exp(-ctl->oh_chem_beta / cos(sza));
104 else
105 return oh * exp(-ctl->oh_chem_beta / cos(M_PI / 2. * 85. / 90.));
106 } else
107 return oh;
108}
double clim_zm(const clim_zm_t *zm, const double t, const double lat, const double p)
Interpolates monthly mean zonal mean climatological variables.
Definition: mptrac.c:394
double sza_calc(const double sec, const double lon, const double lat)
Calculates the solar zenith angle.
Definition: mptrac.c:8082
clim_zm_t oh
OH zonal means.
Definition: mptrac.h:3252
double oh_chem_beta
Beta parameter for diurnal variablity of OH.
Definition: mptrac.h:2789
Here is the call graph for this function:

◆ clim_oh_diurnal_correction()

void clim_oh_diurnal_correction ( ctl_t ctl,
clim_t clim 
)

Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data.

This function iterates over the climatology data points for OH concentration and integrates the day/night correction factor over longitude. The correction factor is based on the solar zenith angle, and it adjusts the OH data to account for diurnal variations. The corrected OH data is scaled accordingly.

Parameters
ctlPointer to the control structure containing configuration parameters, including the correction factor (oh_chem_beta).
climPointer to the climatology structure containing OH data that will be corrected.
Authors
Lars Hoffmann
Mingzhao Liu

Definition at line 112 of file mptrac.c.

114 {
115
116 /* Loop over climatology data points... */
117 for (int it = 0; it < clim->oh.ntime; it++)
118 for (int iz = 0; iz < clim->oh.np; iz++)
119 for (int iy = 0; iy < clim->oh.nlat; iy++) {
120
121 /* Init... */
122 int n = 0;
123 double sum = 0;
124
125 /* Integrate day/night correction factor over longitude... */
126 for (double lon = -180; lon < 180; lon += 1.0) {
127 double sza = sza_calc(clim->oh.time[it], lon, clim->oh.lat[iy]);
128 if (sza <= M_PI / 2. * 85. / 90.)
129 sum += exp(-ctl->oh_chem_beta / cos(sza));
130 else
131 sum += exp(-ctl->oh_chem_beta / cos(M_PI / 2. * 85. / 90.));
132 n++;
133 }
134
135 /* Apply scaling factor to OH data... */
136 clim->oh.vmr[it][iz][iy] /= (sum / (double) n);
137 }
138}
double time[CT]
Time [s].
Definition: mptrac.h:3208
int np
Number of pressure levels.
Definition: mptrac.h:3205
double vmr[CT][CP][CY]
Volume mixing ratio [ppv].
Definition: mptrac.h:3217
int ntime
Number of timesteps.
Definition: mptrac.h:3199
int nlat
Number of latitudes.
Definition: mptrac.h:3202
double lat[CY]
Latitude [deg].
Definition: mptrac.h:3211
Here is the call graph for this function:

◆ clim_photo()

double clim_photo ( double  rate[CP][CSZA][CO3],
clim_photo_t photo,
double  p,
double  sza,
double  o3c 
)

Calculates the photolysis rate for a given set of atmospheric conditions.

This function computes the photolysis rate based on provided climatology data and input parameters such as pressure, solar zenith angle (SZA), and ozone column. It ensures that the input parameters are within the valid range of the climatology data and interpolates the photolysis rate accordingly.

Parameters
rate3D array containing the photolysis rates for different combinations of pressure, SZA, and ozone column.
photoPointer to the climatology data structure containing arrays of valid pressure levels, SZAs, and ozone columns.
pPressure at which the photolysis rate is to be calculated.
szaSolar zenith angle at which the photolysis rate is to be calculated.
o3cOzone column at which the photolysis rate is to be calculated.
Returns
The interpolated photolysis rate for the specified conditions. If the calculated rate is negative, it returns 0.0.

This function performs the following steps:

  1. Checks and adjusts the input parameters (pressure, SZA, and ozone column) to ensure they are within the valid range.
  2. Determines the appropriate indices in the climatology data for interpolation.
  3. Performs trilinear interpolation to calculate the photolysis rate based on the input parameters.
Authors
Lars Hoffmann
Mingzhao Liu

Definition at line 142 of file mptrac.c.

147 {
148
149 /* Check pressure range... */
150 double p_help = p;
151 if (p < photo->p[photo->np - 1])
152 p_help = photo->p[photo->np - 1];
153 else if (p > photo->p[0])
154 p_help = photo->p[0];
155
156 /* Check sza range... */
157 double sza_help = sza;
158 if (sza < photo->sza[0])
159 sza_help = photo->sza[0];
160 else if (sza > photo->sza[photo->nsza - 1])
161 sza_help = photo->sza[photo->nsza - 1];
162
163 /* Check ozone column range... */
164 double o3c_help = o3c;
165 if (o3c < photo->o3c[0])
166 o3c_help = photo->o3c[0];
167 else if (o3c > photo->o3c[photo->no3c - 1])
168 o3c_help = photo->o3c[photo->no3c - 1];
169
170 /* Get indices... */
171 int ip = locate_irr(photo->p, photo->np, p_help);
172 int isza = locate_reg(photo->sza, photo->nsza, sza_help);
173 int io3c = locate_reg(photo->o3c, photo->no3c, o3c_help);
174
175 /* Interpolate photolysis rate... */
176 double aux00 = LIN(photo->p[ip], rate[ip][isza][io3c],
177 photo->p[ip + 1], rate[ip + 1][isza][io3c], p_help);
178 double aux01 = LIN(photo->p[ip], rate[ip][isza][io3c + 1],
179 photo->p[ip + 1], rate[ip + 1][isza][io3c + 1], p_help);
180 double aux10 = LIN(photo->p[ip], rate[ip][isza + 1][io3c],
181 photo->p[ip + 1], rate[ip + 1][isza + 1][io3c], p_help);
182 double aux11 = LIN(photo->p[ip], rate[ip][isza + 1][io3c + 1],
183 photo->p[ip + 1], rate[ip + 1][isza + 1][io3c + 1],
184 p_help);
185 aux00 = LIN(photo->o3c[io3c], aux00, photo->o3c[io3c + 1], aux01, o3c_help);
186 aux11 = LIN(photo->o3c[io3c], aux10, photo->o3c[io3c + 1], aux11, o3c_help);
187 aux00 = LIN(photo->sza[isza], aux00, photo->sza[isza + 1], aux11, sza_help);
188 return MAX(aux00, 0.0);
189}
int locate_reg(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a regular grid.
Definition: mptrac.c:2117
int locate_irr(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a sorted array.
Definition: mptrac.c:2019
#define LIN(x0, y0, x1, y1, x)
Linear interpolation.
Definition: mptrac.h:827
#define MAX(a, b)
Macro to determine the maximum of two values.
Definition: mptrac.h:854
int nsza
Number of solar zenith angles.
Definition: mptrac.h:3126
double sza[CSZA]
Solar zenith angle [rad].
Definition: mptrac.h:3135
double p[CP]
Pressure [hPa].
Definition: mptrac.h:3132
double o3c[CO3]
Total column ozone [DU].
Definition: mptrac.h:3138
int np
Number of pressure levels.
Definition: mptrac.h:3123
int no3c
Number of total ozone columns.
Definition: mptrac.h:3129
Here is the call graph for this function:

◆ clim_tropo()

double clim_tropo ( const clim_t clim,
const double  t,
const double  lat 
)

Calculates the tropopause pressure based on climatological data.

This function computes the tropopause pressure using climatological data for different times and latitudes. It interpolates the tropopause pressure based on the input time and latitude parameters.

Parameters
climPointer to the climatology structure containing tropopause pressure data.
tTime for which the tropopause pressure is to be calculated, in seconds since the beginning of the year.
latLatitude at which the tropopause pressure is to be calculated.
Returns
The interpolated tropopause pressure for the specified time and latitude.

This function performs the following steps:

  1. Calculates the number of seconds since the beginning of the year.
  2. Determines the appropriate indices in the climatology data for interpolation based on time and latitude.
  3. Interpolates the tropopause pressure using linear interpolation based on latitude and time.
Author
Lars Hoffmann

Definition at line 193 of file mptrac.c.

196 {
197
198 /* Get seconds since begin of year... */
199 double sec = FMOD(t, 365.25 * 86400.);
200 while (sec < 0)
201 sec += 365.25 * 86400.;
202
203 /* Get indices... */
204 int isec = locate_irr(clim->tropo_time, clim->tropo_ntime, sec);
205 int ilat = locate_reg(clim->tropo_lat, clim->tropo_nlat, lat);
206
207 /* Interpolate tropopause pressure... */
208 double p0 = LIN(clim->tropo_lat[ilat],
209 clim->tropo[isec][ilat],
210 clim->tropo_lat[ilat + 1],
211 clim->tropo[isec][ilat + 1], lat);
212 double p1 = LIN(clim->tropo_lat[ilat],
213 clim->tropo[isec + 1][ilat],
214 clim->tropo_lat[ilat + 1],
215 clim->tropo[isec + 1][ilat + 1], lat);
216 return LIN(clim->tropo_time[isec], p0, clim->tropo_time[isec + 1], p1, sec);
217}
#define FMOD(x, y)
Calculate the floating-point remainder of dividing x by y.
Definition: mptrac.h:603
int tropo_ntime
Number of tropopause timesteps.
Definition: mptrac.h:3231
double tropo_lat[73]
Tropopause latitudes [deg].
Definition: mptrac.h:3240
int tropo_nlat
Number of tropopause latitudes.
Definition: mptrac.h:3234
double tropo[12][73]
Tropopause pressure values [hPa].
Definition: mptrac.h:3243
double tropo_time[12]
Tropopause time steps [s].
Definition: mptrac.h:3237
Here is the call graph for this function:

◆ clim_tropo_init()

void clim_tropo_init ( clim_t clim)

Initializes the tropopause data in the climatology structure.

This function initializes the tropopause data in the climatology structure. It sets the time steps, latitudes, and tropopause pressure values based on predefined arrays.

Parameters
climPointer to the climatology structure to be initialized.

This function performs the following steps:

  1. Sets the number of time steps and initializes the time array.
  2. Sets the number of latitudes and initializes the latitude array.
  3. Initializes the tropopause pressure values based on predefined arrays.
  4. Computes the range of tropopause pressure values.
  5. Logs information about the initialization process.
Author
Lars Hoffmann

Definition at line 221 of file mptrac.c.

222 {
223
224 /* Write info... */
225 LOG(1, "Initialize tropopause data...");
226
227 /* Set time [s]... */
228 clim->tropo_ntime = 12;
229 double tropo_time[12] = {
230 1209600.00, 3888000.00, 6393600.00,
231 9072000.00, 11664000.00, 14342400.00,
232 16934400.00, 19612800.00, 22291200.00,
233 24883200.00, 27561600.00, 30153600.00
234 };
235 memcpy(clim->tropo_time, tropo_time, sizeof(clim->tropo_time));
236
237 /* Set latitudes [deg]... */
238 clim->tropo_nlat = 73;
239 double tropo_lat[73] = {
240 -90, -87.5, -85, -82.5, -80, -77.5, -75, -72.5, -70, -67.5,
241 -65, -62.5, -60, -57.5, -55, -52.5, -50, -47.5, -45, -42.5,
242 -40, -37.5, -35, -32.5, -30, -27.5, -25, -22.5, -20, -17.5,
243 -15, -12.5, -10, -7.5, -5, -2.5, 0, 2.5, 5, 7.5, 10, 12.5,
244 15, 17.5, 20, 22.5, 25, 27.5, 30, 32.5, 35, 37.5, 40, 42.5,
245 45, 47.5, 50, 52.5, 55, 57.5, 60, 62.5, 65, 67.5, 70, 72.5,
246 75, 77.5, 80, 82.5, 85, 87.5, 90
247 };
248 memcpy(clim->tropo_lat, tropo_lat, sizeof(clim->tropo_lat));
249
250 /* Set tropopause pressure [hPa] (NCEP/NCAR Reanalysis 1)... */
251 double tropo[12][73] = {
252 {324.1, 325.6, 325, 324.3, 322.5, 319.7, 314, 307.2, 301.8, 299.6,
253 297.1, 292.2, 285.6, 276.1, 264, 248.9, 231.9, 213.5, 194.4,
254 175.3, 157, 140.4, 126.7, 116.3, 109.5, 105.4, 103, 101.4, 100.4,
255 99.69, 99.19, 98.84, 98.56, 98.39, 98.39, 98.42, 98.44, 98.54,
256 98.68, 98.81, 98.89, 98.96, 99.12, 99.65, 101.4, 105.4, 113.5, 128,
257 152.1, 184.7, 214, 234.1, 247.3, 255.8, 262.6, 267.7, 271.7, 275,
258 277.2, 279, 280.1, 280.4, 280.6, 280.1, 279.3, 278.3, 276.8, 275.8,
259 275.3, 275.6, 275.4, 274.1, 273.5},
260 {337.3, 338.7, 337.8, 336.4, 333, 328.8, 321.1, 312.6, 306.6, 303.7,
261 300.2, 293.8, 285.4, 273.8, 259.6, 242.7, 224.4, 205.2, 186, 167.5,
262 150.3, 135, 122.8, 113.9, 108.2, 104.7, 102.5, 101.1, 100.2, 99.42,
263 98.88, 98.52, 98.25, 98.09, 98.07, 98.1, 98.12, 98.2, 98.25, 98.27,
264 98.26, 98.27, 98.36, 98.79, 100.2, 104.2, 113.7, 131.2, 159.5, 193,
265 220.4, 238.1, 250.2, 258.1, 264.7, 269.7, 273.7, 277.3, 280.2, 282.8,
266 284.9, 286.5, 288.1, 288.8, 289, 288.5, 287.2, 286.3, 286.1, 287.2,
267 287.5, 286.2, 285.8},
268 {335, 336, 335.7, 335.1, 332.3, 328.1, 320.6, 311.8, 305.1, 301.9,
269 297.6, 290, 280.4, 268.3, 254.6, 239.6, 223.9, 207.9, 192.2, 176.9,
270 161.7, 146.4, 132.2, 120.6, 112.3, 107.2, 104.3, 102.4, 101.3,
271 100.4, 99.86, 99.47, 99.16, 98.97, 98.94, 98.97, 99, 99.09, 99.2,
272 99.31, 99.35, 99.41, 99.51, 99.86, 101.1, 104.9, 114.3, 131, 156.8,
273 186.3, 209.3, 224.6, 236.8, 246.3, 254.9, 262.3, 268.8, 274.8,
274 279.9, 284.6, 288.6, 291.6, 294.9, 297.5, 299.8, 301.8, 303.1,
275 304.3, 304.9, 306, 306.6, 306.2, 306},
276 {306.2, 306.7, 305.7, 307.1, 307.3, 306.4, 301.8, 296.2, 292.4,
277 290.3, 287.1, 280.9, 273.4, 264.3, 254.1, 242.8, 231, 219, 207.2,
278 195.5, 183.3, 169.7, 154.7, 138.7, 124.1, 113.6, 107.8, 104.7,
279 102.8, 101.7, 100.9, 100.4, 100, 99.79, 99.7, 99.66, 99.68, 99.79,
280 99.94, 100.2, 100.5, 100.9, 101.4, 102.1, 103.4, 107, 115.2, 129.1,
281 148.7, 171, 190.8, 205.6, 218.4, 229.4, 239.6, 248.6, 256.5,
282 263.7, 270.3, 276.6, 282.6, 288.1, 294.5, 300.4, 306.3, 311.4,
283 315.1, 318.3, 320.3, 322.2, 322.8, 321.5, 321.1},
284 {266.5, 264.9, 260.8, 261, 262, 263, 261.3, 259.7, 259.2, 259.8,
285 260.1, 258.6, 256.7, 253.6, 249.5, 243.9, 237.4, 230, 222.1, 213.9,
286 205, 194.4, 180.4, 161.8, 140.7, 122.9, 112.1, 106.7, 104.1, 102.7,
287 101.8, 101.4, 101.1, 101, 101, 101, 101.1, 101.2, 101.5, 101.9,
288 102.4, 103, 103.8, 104.9, 106.8, 110.1, 115.6, 124, 135.2, 148.9,
289 165.2, 181.3, 198, 211.8, 223.5, 233.8, 242.9, 251.5, 259, 266.2,
290 273.1, 279.2, 286.2, 292.8, 299.6, 306, 311.1, 315.5, 318.8, 322.6,
291 325.3, 325.8, 325.8},
292 {220.1, 218.1, 210.8, 207.2, 207.6, 210.5, 211.4, 213.5, 217.3,
293 222.4, 227.9, 232.8, 237.4, 240.8, 242.8, 243, 241.5, 238.6, 234.2,
294 228.5, 221, 210.7, 195.1, 172.9, 147.8, 127.6, 115.6, 109.9, 107.1,
295 105.7, 105, 104.8, 104.8, 104.9, 105, 105.1, 105.3, 105.5, 105.8,
296 106.4, 107, 107.6, 108.1, 108.8, 110, 111.8, 114.2, 117.4, 121.6,
297 127.9, 137.3, 151.2, 169.5, 189, 205.8, 218.9, 229.1, 237.8, 245,
298 251.5, 257.1, 262.3, 268.2, 274, 280.4, 286.7, 292.4, 297.9, 302.9,
299 308.5, 312.2, 313.1, 313.3},
300 {187.4, 184.5, 173.3, 166.1, 165.4, 167.8, 169.6, 173.6, 179.6,
301 187.9, 198.9, 210, 220.5, 229.2, 235.7, 239.9, 241.8, 241.6, 239.6,
302 235.8, 229.4, 218.6, 200.9, 175.9, 149.4, 129.4, 118.3, 113.1,
303 110.8, 109.7, 109.3, 109.4, 109.7, 110, 110.2, 110.4, 110.5, 110.7,
304 111, 111.4, 111.8, 112.1, 112.3, 112.7, 113.2, 113.9, 115, 116.4,
305 117.9, 120.4, 124.1, 130.9, 142.2, 159.6, 179.6, 198.5, 212.9,
306 224.2, 232.7, 239.1, 243.8, 247.7, 252.4, 257.3, 263.2, 269.5,
307 275.4, 281.1, 286.3, 292, 296.3, 298.2, 298.8},
308 {166, 166.4, 155.7, 148.3, 147.1, 149, 152.1, 157, 163.6, 172.4,
309 185.3, 199.2, 212.6, 224, 233.2, 239.6, 243.3, 244.6, 243.6, 240.3,
310 233.9, 222.6, 203.7, 177, 149.5, 129.7, 119, 114, 111.7, 110.7,
311 110.3, 110.3, 110.6, 110.9, 111.1, 111.3, 111.5, 111.6, 111.9,
312 112.2, 112.5, 112.6, 112.8, 113, 113.4, 114, 115.1, 116.5, 118.3,
313 120.9, 124.4, 130.2, 139.4, 154.6, 173.8, 193.1, 208.1, 220.4,
314 230.1, 238.2, 244.7, 249.5, 254.5, 259.3, 264.5, 269.4, 273.7,
315 278.2, 282.6, 287.4, 290.9, 292.5, 293},
316 {171.9, 172.8, 166.2, 162.3, 161.4, 162.5, 165.2, 169.6, 175.3,
317 183.1, 193.8, 205.9, 218.3, 229.6, 238.5, 244.3, 246.9, 246.7,
318 243.8, 238.4, 230.2, 217.9, 199.6, 174.9, 148.9, 129.8, 119.5,
319 114.8, 112.3, 110.9, 110.3, 110.1, 110.2, 110.3, 110.4, 110.5,
320 110.6, 110.8, 111, 111.4, 111.8, 112, 112.2, 112.4, 112.9, 113.6,
321 114.7, 116.3, 118.4, 121.9, 127.1, 136.1, 149.8, 168.4, 186.9,
322 203.3, 217, 229.1, 238.7, 247, 254, 259.3, 264.3, 268.3, 272.5,
323 276.6, 280.4, 284.4, 288.4, 293.3, 297.2, 298.7, 299.1},
324 {191.6, 192.2, 189, 188.1, 190.2, 193.7, 197.8, 202.9, 208.5,
325 215.6, 224.2, 233.1, 241.2, 247.3, 250.8, 251.3, 248.9, 244.2,
326 237.3, 228.4, 217.2, 202.9, 184.5, 162.5, 140.7, 124.8, 116.2,
327 111.8, 109.4, 107.9, 107, 106.7, 106.6, 106.6, 106.7, 106.7,
328 106.8, 107, 107.4, 108, 108.7, 109.3, 109.8, 110.4, 111.2,
329 112.4, 114.2, 116.9, 121.1, 127.9, 139.3, 155.2, 173.6, 190.7,
330 206.1, 220.1, 232.3, 243, 251.8, 259.2, 265.7, 270.6, 275.3,
331 279.3, 283.3, 286.9, 289.7, 292.8, 296.1, 300.5, 303.9, 304.8,
332 305.1},
333 {241.5, 239.6, 236.8, 237.4, 239.4, 242.3, 244.2, 246.4, 249.2,
334 253.6, 258.6, 262.7, 264.8, 264.2, 260.6, 254.1, 245.5, 235.3,
335 223.9, 211.7, 198.3, 183.1, 165.6, 147.1, 130.5, 118.7, 111.9,
336 108.1, 105.8, 104.3, 103.4, 102.8, 102.5, 102.4, 102.5, 102.5,
337 102.5, 102.7, 103.1, 103.8, 104.6, 105.4, 106.1, 107, 108.2,
338 109.9, 112.8, 117.5, 126, 140.4, 161, 181.9, 201.2, 216.8, 230.4,
339 241.8, 251.4, 259.9, 266.9, 272.8, 277.4, 280.4, 282.9, 284.6,
340 286.1, 287.4, 288.3, 289.5, 290.9, 294.2, 296.9, 297.5, 297.6},
341 {301.2, 300.3, 296.6, 295.4, 295, 294.3, 291.2, 287.4, 284.9, 284.7,
342 284.1, 281.5, 277.1, 270.4, 261.7, 250.6, 237.6, 223.1, 207.9, 192,
343 175.8, 158.8, 142.1, 127.6, 116.8, 109.9, 106, 103.6, 102.1, 101.1,
344 100.4, 99.96, 99.6, 99.37, 99.32, 99.32, 99.31, 99.46, 99.77, 100.2,
345 100.7, 101.3, 101.8, 102.7, 104.1, 106.8, 111.9, 121, 136.7, 160,
346 186.9, 209.9, 228.1, 241.2, 251.5, 259.5, 265.7, 270.9, 274.8, 278,
347 280.3, 281.8, 283, 283.3, 283.7, 283.8, 283, 282.2, 281.2, 281.4,
348 281.7, 281.1, 281.2}
349 };
350 memcpy(clim->tropo, tropo, sizeof(clim->tropo));
351
352 /* Get range... */
353 double tropomin = 1e99, tropomax = -1e99;
354 for (int it = 0; it < clim->tropo_ntime; it++)
355 for (int iy = 0; iy < clim->tropo_nlat; iy++) {
356 tropomin = MIN(tropomin, clim->tropo[it][iy]);
357 tropomax = MAX(tropomax, clim->tropo[it][iy]);
358 }
359
360 /* Write info... */
361 LOG(2, "Number of time steps: %d", clim->tropo_ntime);
362 LOG(2, "Time steps: %.2f, %.2f ... %.2f s",
363 clim->tropo_time[0], clim->tropo_time[1],
364 clim->tropo_time[clim->tropo_ntime - 1]);
365 LOG(2, "Number of latitudes: %d", clim->tropo_nlat);
366 LOG(2, "Latitudes: %g, %g ... %g deg",
367 clim->tropo_lat[0], clim->tropo_lat[1],
368 clim->tropo_lat[clim->tropo_nlat - 1]);
369 LOG(2, "Tropopause altitude range: %g ... %g hPa", Z(tropomax),
370 Z(tropomin));
371 LOG(2, "Tropopause pressure range: %g ... %g hPa", tropomin, tropomax);
372}
#define MIN(a, b)
Macro to determine the minimum of two values.
Definition: mptrac.h:952
#define Z(p)
Convert pressure to altitude.
Definition: mptrac.h:1706
#define LOG(level,...)
Print a log message with a specified logging level.
Definition: mptrac.h:1811

◆ clim_ts()

double clim_ts ( const clim_ts_t ts,
const double  t 
)

Interpolates a time series of climatological variables.

This function interpolates a time series of climatological variables based on the input time and the provided data points.

Parameters
tsPointer to the time series structure containing data points.
tTime at which to interpolate the climatological variable (in seconds).
Returns
Interpolated value of the climatological variable at the given time.

This function performs linear interpolation between the closest data points to the input time t. If t is outside the range of the provided time series, the value at the nearest boundary is returned.

Author
Lars Hoffmann

Definition at line 376 of file mptrac.c.

378 {
379
380 /* Interpolate... */
381 if (t <= ts->time[0])
382 return ts->vmr[0];
383 else if (t >= ts->time[ts->ntime - 1])
384 return ts->vmr[ts->ntime - 1];
385 else {
386 int idx = locate_irr(ts->time, ts->ntime, t);
387 return LIN(ts->time[idx], ts->vmr[idx],
388 ts->time[idx + 1], ts->vmr[idx + 1], t);
389 }
390}
double vmr[CTS]
Volume mixing ratio [ppv].
Definition: mptrac.h:3185
double time[CTS]
Time [s].
Definition: mptrac.h:3182
int ntime
Number of timesteps.
Definition: mptrac.h:3179
Here is the call graph for this function:

◆ clim_zm()

double clim_zm ( const clim_zm_t zm,
const double  t,
const double  lat,
const double  p 
)

Interpolates monthly mean zonal mean climatological variables.

This function interpolates climatological variables based on pressure, latitude, and time. The climatological data is provided in the form of monthly mean zonal mean values.

Parameters
zmPointer to the climatological zonal mean structure containing data points.
tTime at which to interpolate the climatological variable (in seconds since the beginning of the year).
latLatitude at which to interpolate the climatological variable (in degrees).
pPressure at which to interpolate the climatological variable (in hPa).
Returns
Interpolated value of the climatological variable at the given pressure, latitude, and time.

This function performs trilinear interpolation between the nearest data points to the input time t, latitude lat, and pressure or altitude p. If the input values are outside the range of the provided data, the function extrapolates by using the nearest boundary values.

Author
Lars Hoffmann

Definition at line 394 of file mptrac.c.

398 {
399
400 /* Get seconds since begin of year... */
401 double sec = FMOD(t, 365.25 * 86400.);
402 while (sec < 0)
403 sec += 365.25 * 86400.;
404
405 /* Check pressure range... */
406 double p_help = p;
407 if (p < zm->p[zm->np - 1])
408 p_help = zm->p[zm->np - 1];
409 else if (p > zm->p[0])
410 p_help = zm->p[0];
411
412 /* Check latitude range... */
413 double lat_help = lat;
414 if (lat < zm->lat[0])
415 lat_help = zm->lat[0];
416 else if (lat > zm->lat[zm->nlat - 1])
417 lat_help = zm->lat[zm->nlat - 1];
418
419 /* Get indices... */
420 int isec = locate_irr(zm->time, zm->ntime, sec);
421 int ilat = locate_reg(zm->lat, zm->nlat, lat_help);
422 int ip = locate_irr(zm->p, zm->np, p_help);
423
424 /* Interpolate climatology data... */
425 double aux00 = LIN(zm->p[ip], zm->vmr[isec][ip][ilat],
426 zm->p[ip + 1], zm->vmr[isec][ip + 1][ilat], p_help);
427 double aux01 = LIN(zm->p[ip], zm->vmr[isec][ip][ilat + 1],
428 zm->p[ip + 1], zm->vmr[isec][ip + 1][ilat + 1], p_help);
429 double aux10 = LIN(zm->p[ip], zm->vmr[isec + 1][ip][ilat],
430 zm->p[ip + 1], zm->vmr[isec + 1][ip + 1][ilat], p_help);
431 double aux11 = LIN(zm->p[ip], zm->vmr[isec + 1][ip][ilat + 1],
432 zm->p[ip + 1], zm->vmr[isec + 1][ip + 1][ilat + 1],
433 p_help);
434 aux00 = LIN(zm->lat[ilat], aux00, zm->lat[ilat + 1], aux01, lat_help);
435 aux11 = LIN(zm->lat[ilat], aux10, zm->lat[ilat + 1], aux11, lat_help);
436 aux00 = LIN(zm->time[isec], aux00, zm->time[isec + 1], aux11, sec);
437
438 return MAX(aux00, 0.0);
439}
double p[CP]
Pressure [hPa].
Definition: mptrac.h:3214
Here is the call graph for this function:

◆ compress_cms()

void compress_cms ( ctl_t ctl,
char *  varname,
float *  array,
size_t  nx,
size_t  ny,
size_t  np,
int  decompress,
FILE *  inout 
)

Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm.

This function either compresses or decompresses a 3D array of floats based on the value of the decompress parameter. The compression and decompression are performed using a custom multiscale module.

Parameters
varnameThe name of the variable being processed.
arrayPointer to the 3D array of floats to be compressed or decompressed.
nxThe number of elements in the x-dimension of the array.
nyThe number of elements in the y-dimension of the array.
npThe number of elements in the p-dimension of the array.
decompressIf non-zero, the function will decompress the data; otherwise, it will compress the data.
inoutFile pointer for input or output operations. It is used for reading compressed data during decompression and writing compressed data during compression.

The function performs the following steps:

  • Determines grid properties from the input data dimensions.
  • Initializes the multiscale module with the specified grid properties.
  • Sets up longitude and latitude grids for the data.
  • If decompressing:
    • Reads compressed data for each level and decompresses it.
    • Evaluates the decompressed data and stores it in the array.
  • If compressing:
    • Copies data for each level into a temporary array.
    • Compresses the data and writes the compressed data to the file.

The function logs the compression or decompression details and frees allocated resources before returning.

Note
Ensure that the input array is already allocated and can hold the decompressed data.
Warning
Ensure that the file pointer inout is correctly opened for reading or writing as required.
See also
get_2d_grid_from_meteo_data, init_multiscale, read_sol, save_sol, eval, coarsening, delete_solution, delete_multiscale
Author
Lars Hoffmann

◆ compress_pck()

void compress_pck ( char *  varname,
float *  array,
size_t  nxy,
size_t  nz,
int  decompress,
FILE *  inout 
)

Compresses or decompresses a 3D array of floats.

This function either compresses or decompresses a 3D array of floats based on the value of the decompress parameter. Compression reduces the storage size by converting float values (4 bytes) to unsigned short values (2 bytes) with scaling and offset. Decompression restores the original float values from the compressed unsigned short representation.

Parameters
varnameThe name of the variable being processed.
arrayPointer to the 3D array of floats to be compressed or decompressed.
nxyThe number of elements in the first two dimensions of the array.
nzThe number of elements in the third dimension of the array.
decompressIf non-zero, the function will decompress the data; otherwise, it will compress the data.
inoutFile pointer for input or output operations. It is used for reading compressed data during decompression and writing compressed data during compression.

The function performs the following steps:

  • If decompressing:
    • Reads scaling factors, offsets, and compressed data from the file.
    • Decompresses the data and stores it in the array.
  • If compressing:
    • Computes the minimum and maximum values for each slice in the third dimension.
    • Calculates scaling factors and offsets based on these values.
    • Compresses the data by converting floats to unsigned shorts using the scaling factors and offsets.
    • Writes the scaling factors, offsets, and compressed data to the file.

The function allocates memory for the compressed data array and frees it before returning.

Author
Lars Hoffmann

Definition at line 575 of file mptrac.c.

581 {
582
583 double min[EP], max[EP], off[EP], scl[EP];
584
585 unsigned short *sarray;
586
587 /* Allocate... */
588 ALLOC(sarray, unsigned short,
589 nxy * nz);
590
591 /* Read compressed stream and decompress array... */
592 if (decompress) {
593
594 /* Write info... */
595 LOG(2, "Read 3-D variable: %s (pck, RATIO= %g)",
596 varname, (double) sizeof(float) / (double) sizeof(unsigned short));
597
598 /* Read data... */
599 FREAD(&scl, double,
600 nz,
601 inout);
602 FREAD(&off, double,
603 nz,
604 inout);
605 FREAD(sarray, unsigned short,
606 nxy * nz,
607 inout);
608
609 /* Convert to float... */
610#pragma omp parallel for default(shared)
611 for (size_t ixy = 0; ixy < nxy; ixy++)
612 for (size_t iz = 0; iz < nz; iz++)
613 array[ixy * nz + iz]
614 = (float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
615 }
616
617 /* Compress array and output compressed stream... */
618 else {
619
620 /* Write info... */
621 LOG(2, "Write 3-D variable: %s (pck, RATIO= %g)",
622 varname, (double) sizeof(float) / (double) sizeof(unsigned short));
623
624 /* Get range... */
625 for (size_t iz = 0; iz < nz; iz++) {
626 min[iz] = array[iz];
627 max[iz] = array[iz];
628 }
629 for (size_t ixy = 1; ixy < nxy; ixy++)
630 for (size_t iz = 0; iz < nz; iz++) {
631 if (array[ixy * nz + iz] < min[iz])
632 min[iz] = array[ixy * nz + iz];
633 if (array[ixy * nz + iz] > max[iz])
634 max[iz] = array[ixy * nz + iz];
635 }
636
637 /* Get offset and scaling factor... */
638 for (size_t iz = 0; iz < nz; iz++) {
639 scl[iz] = (max[iz] - min[iz]) / 65533.;
640 off[iz] = min[iz];
641 }
642
643 /* Convert to short... */
644#pragma omp parallel for default(shared)
645 for (size_t ixy = 0; ixy < nxy; ixy++)
646 for (size_t iz = 0; iz < nz; iz++)
647 if (scl[iz] != 0)
648 sarray[ixy * nz + iz] = (unsigned short)
649 ((array[ixy * nz + iz] - off[iz]) / scl[iz] + .5);
650 else
651 sarray[ixy * nz + iz] = 0;
652
653 /* Write data... */
654 FWRITE(&scl, double,
655 nz,
656 inout);
657 FWRITE(&off, double,
658 nz,
659 inout);
660 FWRITE(sarray, unsigned short,
661 nxy * nz,
662 inout);
663 }
664
665 /* Free... */
666 free(sarray);
667}
#define FWRITE(ptr, type, size, out)
Write data from memory to a file stream.
Definition: mptrac.h:641
#define FREAD(ptr, type, size, in)
Read data from a file stream and store it in memory.
Definition: mptrac.h:621
#define ALLOC(ptr, type, n)
Allocate memory for a pointer with error handling.
Definition: mptrac.h:344
#define EP
Maximum number of pressure levels for meteo data.
Definition: mptrac.h:256

◆ compress_zfp()

void compress_zfp ( char *  varname,
float *  array,
int  nx,
int  ny,
int  nz,
int  precision,
double  tolerance,
int  decompress,
FILE *  inout 
)

Compresses or decompresses a 3D array of floats using the ZFP library.

This function either compresses or decompresses a 3D array of floats based on the value of the decompress parameter. Compression reduces the storage size using the ZFP compression algorithm, which supports fixed-precision or fixed-accuracy modes. Decompression restores the original float values from the compressed representation.

Parameters
varnameThe name of the variable being processed.
arrayPointer to the 3D array of floats to be compressed or decompressed.
nxThe number of elements in the x-dimension of the array.
nyThe number of elements in the y-dimension of the array.
nzThe number of elements in the z-dimension of the array.
precisionThe precision parameter for ZFP compression. If greater than 0, it sets the fixed precision mode.
toleranceThe tolerance parameter for ZFP compression. If greater than 0 and precision is 0, it sets the fixed accuracy mode.
decompressIf non-zero, the function will decompress the data; otherwise, it will compress the data.
inoutFile pointer for input or output operations. It is used for reading compressed data during decompression and writing compressed data during compression.

The function performs the following steps:

  • Allocates metadata for the 3D array and the ZFP compressed stream.
  • Sets the compression mode based on the precision or tolerance parameters.
  • Allocates a buffer for the compressed data.
  • Associates a bit stream with the allocated buffer and sets up the ZFP stream.
  • If decompressing:
    • Reads the size of the compressed data and the compressed data itself from the file.
    • Decompresses the data and stores it in the array.
  • If compressing:
    • Compresses the data and writes the compressed data size and the compressed data itself to the file.

The function logs the compression or decompression details and frees allocated resources before returning.

Note
Ensure that either the precision or tolerance parameter is set to a value greater than 0.
Author
Lars Hoffmann

◆ compress_zstd()

void compress_zstd ( char *  varname,
float *  array,
size_t  n,
int  decompress,
FILE *  inout 
)

Compresses or decompresses an array of floats using the Zstandard (ZSTD) library.

This function either compresses or decompresses an array of floats based on the value of the decompress parameter. Compression reduces the storage size using the ZSTD compression algorithm. Decompression restores the original float values from the compressed representation.

Parameters
varnameThe name of the variable being processed.
arrayPointer to the array of floats to be compressed or decompressed.
nThe number of elements in the array.
decompressIf non-zero, the function will decompress the data; otherwise, it will compress the data.
inoutFile pointer for input or output operations. It is used for reading compressed data during decompression and writing compressed data during compression.

The function performs the following steps:

  • Calculates the buffer sizes required for compression and decompression.
  • Allocates memory for the compressed data buffer.
  • If decompressing:
    • Reads the size of the compressed data and the compressed data itself from the file.
    • Decompresses the data and stores it in the array.
  • If compressing:
    • Compresses the data and writes the compressed data size and the compressed data itself to the file.

The function logs the compression or decompression details and frees allocated resources before returning.

Note
This function assumes that the input array is already allocated and can hold the decompressed data.
Warning
Ensure that the file pointer inout is correctly opened for reading or writing as required.
See also
ZSTD_compress, ZSTD_decompress, ZSTD_isError
Author
Lars Hoffmann

◆ day2doy()

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

Get day of year from date.

Converts a given date to the day of the year (DOY).

This function computes the day of the year (DOY) for a given date specified by the year, month, and day. It takes into account whether the given year is a leap year or not.

Parameters
yearThe year of the date.
monThe month of the date (1-12).
dayThe day of the month (1-31).
doyPointer to an integer where the computed day of the year will be stored.

The function uses two arrays, d0 and d0l, which contain the cumulative number of days at the start of each month for non-leap years and leap years respectively. It checks if the year is a leap year and calculates the day of the year accordingly.

Note
The function assumes that the input date is valid.
Author
Lars Hoffmann

Definition at line 816 of file mptrac.c.

820 {
821
822 const int
823 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
824 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
825
826 /* Get day of year... */
827 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
828 *doy = d0l[mon - 1] + day - 1;
829 else
830 *doy = d0[mon - 1] + day - 1;
831}

◆ doy2day()

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

Converts a given day of the year (DOY) to a date (month and day).

This function computes the month and day for a given day of the year (DOY) and year. It accounts for whether the given year is a leap year or not.

Parameters
yearThe year corresponding to the DOY.
doyThe day of the year (1-365 or 1-366).
monPointer to an integer where the computed month will be stored.
dayPointer to an integer where the computed day of the month will be stored.

The function uses two arrays, d0 and d0l, which contain the cumulative number of days at the start of each month for non-leap years and leap years respectively. It checks if the year is a leap year and calculates the month and day of the month accordingly.

Note
The function assumes that the input DOY is valid for the given year.
Author
Lars Hoffmann

Definition at line 835 of file mptrac.c.

839 {
840
841 const int
842 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
843 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
844
845 int i;
846
847 /* Get month and day... */
848 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
849 for (i = 11; i > 0; i--)
850 if (d0l[i] <= doy)
851 break;
852 *mon = i + 1;
853 *day = doy - d0l[i] + 1;
854 } else {
855 for (i = 11; i > 0; i--)
856 if (d0[i] <= doy)
857 break;
858 *mon = i + 1;
859 *day = doy - d0[i] + 1;
860 }
861}

◆ fft_help()

void fft_help ( double *  fcReal,
double *  fcImag,
int  n 
)

Computes the Fast Fourier Transform (FFT) of a complex sequence.

This function calculates the FFT of a complex sequence represented by separate arrays for the real and imaginary parts. The input arrays fcReal and fcImag are modified in place to contain the transformed data.

Parameters
fcRealPointer to an array of doubles representing the real part of the input sequence. The array should have at least n elements.
fcImagPointer to an array of doubles representing the imaginary part of the input sequence. The array should have at least n elements.
nThe number of complex data points in the input sequence. This value should not exceed PMAX.
Precondition
fcReal and fcImag must point to arrays of at least n elements.
n must be less than or equal to PMAX.
Postcondition
The arrays fcReal and fcImag will contain the real and imaginary parts of the FFT result, respectively.
Note
This function uses the GNU Scientific Library (GSL) for computing the FFT. Ensure that GSL is properly installed and linked in your project.
Warning
If n exceeds PMAX, the function will trigger an error message and terminate.
Author
Lars Hoffmann

Definition at line 865 of file mptrac.c.

868 {
869
870 gsl_fft_complex_wavetable *wavetable;
871 gsl_fft_complex_workspace *workspace;
872
873 double data[2 * EX];
874
875 /* Check size... */
876 if (n > EX)
877 ERRMSG("Too many data points!");
878
879 /* Allocate... */
880 wavetable = gsl_fft_complex_wavetable_alloc((size_t) n);
881 workspace = gsl_fft_complex_workspace_alloc((size_t) n);
882
883 /* Set data (real, complex)... */
884 for (int i = 0; i < n; i++) {
885 data[2 * i] = fcReal[i];
886 data[2 * i + 1] = fcImag[i];
887 }
888
889 /* Calculate FFT... */
890 gsl_fft_complex_forward(data, 1, (size_t) n, wavetable, workspace);
891
892 /* Copy data... */
893 for (int i = 0; i < n; i++) {
894 fcReal[i] = data[2 * i];
895 fcImag[i] = data[2 * i + 1];
896 }
897
898 /* Free... */
899 gsl_fft_complex_wavetable_free(wavetable);
900 gsl_fft_complex_workspace_free(workspace);
901}
#define EX
Maximum number of longitudes for meteo data.
Definition: mptrac.h:261

◆ 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 905 of file mptrac.c.

909 {
910
911 double radius = z + RE;
912 x[0] = radius * cos(lat / 180. * M_PI) * cos(lon / 180. * M_PI);
913 x[1] = radius * cos(lat / 180. * M_PI) * sin(lon / 180. * M_PI);
914 x[2] = radius * sin(lat / 180. * M_PI);
915}

◆ get_met()

void get_met ( ctl_t ctl,
clim_t clim,
double  t,
met_t **  met0,
met_t **  met1 
)

Retrieves meteorological data for the specified time.

This function retrieves meteorological data for the given time t and updates the provided pointers to the met0 and met1 structures accordingly. It handles both the initialization and subsequent updates of the meteorological data based on the direction of time integration.

Parameters
ctlPointer to the control structure containing configuration settings.
climPointer to the climate structure.
tThe current time for which meteorological data is to be retrieved.
met0Pointer to the pointer of the first meteorological data structure.
met1Pointer to the pointer of the second meteorological data structure.

The function performs the following steps:

  • Initializes meteorological data on the first call or when the simulation restarts.
  • Reads new meteorological data when advancing forward or backward in time.
  • Swaps pointers to manage double buffering of the meteorological data.
  • Performs caching to optimize subsequent data retrieval.
  • Ensures consistency of the meteorological grids.
Note
This function utilizes GPU acceleration with OpenACC directives if enabled.
Ensure that ctl, clim, met0, and met1 are properly initialized before calling this function.
See also
get_met_help
read_met
SELECT_TIMER
LOG
ERRMSG
WARN
Author
Lars Hoffmann

Definition at line 919 of file mptrac.c.

924 {
925
926 static int init;
927
928 met_t *mets;
929
930 char cachefile[LEN], cmd[2 * LEN], filename[LEN];
931
932 /* Set timer... */
933 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
934
935 /* Init... */
936 if (t == ctl->t_start || !init) {
937 init = 1;
938
939 /* Read meteo data... */
940 get_met_help(ctl, t + (ctl->direction == -1 ? -1 : 0), -1,
941 ctl->metbase, ctl->dt_met, filename);
942 if (!read_met(filename, ctl, clim, *met0))
943 ERRMSG("Cannot open file!");
944
945 get_met_help(ctl, t + (ctl->direction == 1 ? 1 : 0), 1,
946 ctl->metbase, ctl->dt_met, filename);
947 if (!read_met(filename, ctl, clim, *met1))
948 ERRMSG("Cannot open file!");
949
950 /* Update GPU... */
951#ifdef _OPENACC
952 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
953 met_t *met0up = *met0;
954 met_t *met1up = *met1;
955#ifdef ASYNCIO
956#pragma acc update device(met0up[:1],met1up[:1]) async(5)
957#else
958#pragma acc update device(met0up[:1],met1up[:1])
959#endif
960 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
961#endif
962
963 /* Caching... */
964 if (ctl->met_cache && t != ctl->t_stop) {
965 get_met_help(ctl, t + 1.1 * ctl->dt_met * ctl->direction,
966 ctl->direction, ctl->metbase, ctl->dt_met, cachefile);
967 sprintf(cmd, "cat %s > /dev/null &", cachefile);
968 LOG(1, "Caching: %s", cachefile);
969 if (system(cmd) != 0)
970 WARN("Caching command failed!");
971 }
972 }
973
974 /* Read new data for forward trajectories... */
975 if (t > (*met1)->time) {
976
977 /* Pointer swap... */
978 mets = *met1;
979 *met1 = *met0;
980 *met0 = mets;
981
982 /* Read new meteo data... */
983 get_met_help(ctl, t, 1, ctl->metbase, ctl->dt_met, filename);
984 if (!read_met(filename, ctl, clim, *met1))
985 ERRMSG("Cannot open file!");
986
987 /* Update GPU... */
988#ifdef _OPENACC
989 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
990 met_t *met1up = *met1;
991#ifdef ASYNCIO
992#pragma acc update device(met1up[:1]) async(5)
993#else
994#pragma acc update device(met1up[:1])
995#endif
996 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
997#endif
998
999 /* Caching... */
1000 if (ctl->met_cache && t != ctl->t_stop) {
1001 get_met_help(ctl, t + ctl->dt_met, 1, ctl->metbase, ctl->dt_met,
1002 cachefile);
1003 sprintf(cmd, "cat %s > /dev/null &", cachefile);
1004 LOG(1, "Caching: %s", cachefile);
1005 if (system(cmd) != 0)
1006 WARN("Caching command failed!");
1007 }
1008 }
1009
1010 /* Read new data for backward trajectories... */
1011 if (t < (*met0)->time) {
1012
1013 /* Pointer swap... */
1014 mets = *met1;
1015 *met1 = *met0;
1016 *met0 = mets;
1017
1018 /* Read new meteo data... */
1019 get_met_help(ctl, t, -1, ctl->metbase, ctl->dt_met, filename);
1020 if (!read_met(filename, ctl, clim, *met0))
1021 ERRMSG("Cannot open file!");
1022
1023 /* Update GPU... */
1024#ifdef _OPENACC
1025 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
1026 met_t *met0up = *met0;
1027#ifdef ASYNCIO
1028#pragma acc update device(met0up[:1]) async(5)
1029#else
1030#pragma acc update device(met0up[:1])
1031#endif
1032 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
1033#endif
1034
1035 /* Caching... */
1036 if (ctl->met_cache && t != ctl->t_stop) {
1037 get_met_help(ctl, t - ctl->dt_met, -1, ctl->metbase, ctl->dt_met,
1038 cachefile);
1039 sprintf(cmd, "cat %s > /dev/null &", cachefile);
1040 LOG(1, "Caching: %s", cachefile);
1041 if (system(cmd) != 0)
1042 WARN("Caching command failed!");
1043 }
1044 }
1045
1046 /* Check that grids are consistent... */
1047 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
1048 if ((*met0)->nx != (*met1)->nx
1049 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
1050 ERRMSG("Meteo grid dimensions do not match!");
1051 for (int ix = 0; ix < (*met0)->nx; ix++)
1052 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
1053 ERRMSG("Meteo grid longitudes do not match!");
1054 for (int iy = 0; iy < (*met0)->ny; iy++)
1055 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
1056 ERRMSG("Meteo grid latitudes do not match!");
1057 for (int ip = 0; ip < (*met0)->np; ip++)
1058 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
1059 ERRMSG("Meteo grid pressure levels do not match!");
1060 }
1061}
int read_met(const char *filename, ctl_t *ctl, clim_t *clim, met_t *met)
Reads meteorological data from a file and populates the provided structures.
Definition: mptrac.c:5575
void get_met_help(ctl_t *ctl, double t, int direct, char *metbase, double dt_met, char *filename)
Helper function to generate the filename for meteorological data.
Definition: mptrac.c:1065
#define SELECT_TIMER(id, group, color)
Select and start a timer with specific attributes.
Definition: mptrac.h:1961
int direction
Direction flag (1=forward calculation, -1=backward calculation).
Definition: mptrac.h:2439
double dt_met
Time step of meteo data [s].
Definition: mptrac.h:2458
double t_stop
Stop time of simulation [s].
Definition: mptrac.h:2445
int met_cache
Preload meteo data into disk cache (0=no, 1=yes).
Definition: mptrac.h:2574
char metbase[LEN]
Basename for meteo data.
Definition: mptrac.h:2455
double t_start
Start time of simulation [s].
Definition: mptrac.h:2442
Meteo data structure.
Definition: mptrac.h:3287
Here is the call graph for this function:

◆ get_met_help()

void get_met_help ( ctl_t ctl,
double  t,
int  direct,
char *  metbase,
double  dt_met,
char *  filename 
)

Helper function to generate the filename for meteorological data.

This function generates the appropriate filename for the meteorological data file based on the provided time t, direction direct, and the base filename metbase. The filename is formatted according to the specified meteorological data type.

Parameters
ctlPointer to the control structure containing configuration settings.
tThe time for which the meteorological data filename is to be generated.
directThe direction of time integration (-1 for backward, 1 for forward).
metbaseThe base string for the meteorological data filenames.
dt_metThe time interval between meteorological data files.
filenameThe generated filename for the meteorological data file.

The function performs the following steps:

  • Rounds the time to fixed intervals dt_met based on the direction.
  • Decodes the time into year, month, day, hour, minute, and second.
  • Constructs the filename based on the meteorological data type specified in ctl.
  • Replaces placeholders (YYYY, MM, DD, HH) in the base filename with actual date and time values.
Note
Ensure that ctl and filename are properly initialized before calling this function.
See also
jsec2time
get_met_replace
Author
Lars Hoffmann

Definition at line 1065 of file mptrac.c.

1071 {
1072
1073 char repl[LEN];
1074
1075 double t6, r;
1076
1077 int year, mon, day, hour, min, sec;
1078
1079 /* Round time to fixed intervals... */
1080 if (direct == -1)
1081 t6 = floor(t / dt_met) * dt_met;
1082 else
1083 t6 = ceil(t / dt_met) * dt_met;
1084
1085 /* Decode time... */
1086 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
1087
1088 /* Set filename of MPTRAC meteo files... */
1089 if (ctl->met_clams == 0) {
1090 if (ctl->met_type == 0)
1091 sprintf(filename, "%s_YYYY_MM_DD_HH.nc", metbase);
1092 else if (ctl->met_type == 1)
1093 sprintf(filename, "%s_YYYY_MM_DD_HH.bin", metbase);
1094 else if (ctl->met_type == 2)
1095 sprintf(filename, "%s_YYYY_MM_DD_HH.pck", metbase);
1096 else if (ctl->met_type == 3)
1097 sprintf(filename, "%s_YYYY_MM_DD_HH.zfp", metbase);
1098 else if (ctl->met_type == 4)
1099 sprintf(filename, "%s_YYYY_MM_DD_HH.zstd", metbase);
1100 else if (ctl->met_type == 5)
1101 sprintf(filename, "%s_YYYY_MM_DD_HH.cms", metbase);
1102 sprintf(repl, "%d", year);
1103 get_met_replace(filename, "YYYY", repl);
1104 sprintf(repl, "%02d", mon);
1105 get_met_replace(filename, "MM", repl);
1106 sprintf(repl, "%02d", day);
1107 get_met_replace(filename, "DD", repl);
1108 sprintf(repl, "%02d", hour);
1109 get_met_replace(filename, "HH", repl);
1110 }
1111
1112 /* Set filename of CLaMS meteo files... */
1113 else {
1114 sprintf(filename, "%s_YYMMDDHH.nc", metbase);
1115 sprintf(repl, "%d", year);
1116 get_met_replace(filename, "YYYY", repl);
1117 sprintf(repl, "%02d", year % 100);
1118 get_met_replace(filename, "YY", repl);
1119 sprintf(repl, "%02d", mon);
1120 get_met_replace(filename, "MM", repl);
1121 sprintf(repl, "%02d", day);
1122 get_met_replace(filename, "DD", repl);
1123 sprintf(repl, "%02d", hour);
1124 get_met_replace(filename, "HH", repl);
1125 }
1126}
void get_met_replace(char *orig, char *search, char *repl)
Replaces occurrences of a substring in a string with another substring.
Definition: mptrac.c:1130
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.
Definition: mptrac.c:1735
int met_clams
Read MPTRAC or CLaMS meteo data (0=MPTRAC, 1=CLaMS).
Definition: mptrac.h:2153
int met_type
Type of meteo data files (0=netCDF, 1=binary, 2=pck, 3=zfp, 4=zstd).
Definition: mptrac.h:2464
Here is the call graph for this function:

◆ get_met_replace()

void get_met_replace ( char *  orig,
char *  search,
char *  repl 
)

Replaces occurrences of a substring in a string with another substring.

This function replaces occurrences of the substring search in the string orig with the substring repl. The replacement is performed in-place.

Parameters
origThe original string where replacements are to be made.
searchThe substring to be replaced.
replThe substring to replace occurrences of search.

The function iterates over the original string orig and replaces each occurrence of the substring search with the substring repl. It performs the replacement operation up to three times to ensure multiple occurrences are replaced.

Note
We use this function to repace the strings YYYY, MM, and DD by year, month, and day in filenames.
Ensure that orig, search, and repl are properly initialized and have sufficient memory allocated before calling this function.
Author
Lars Hoffmann

Definition at line 1130 of file mptrac.c.

1133 {
1134
1135 char buffer[LEN];
1136
1137 /* Iterate... */
1138 for (int i = 0; i < 3; i++) {
1139
1140 /* Replace sub-string... */
1141 char *ch;
1142 if (!(ch = strstr(orig, search)))
1143 return;
1144 strncpy(buffer, orig, (size_t) (ch - orig));
1145 buffer[ch - orig] = 0;
1146 sprintf(buffer + (ch - orig), "%s%s", repl, ch + strlen(search));
1147 orig[0] = 0;
1148 strcpy(orig, buffer);
1149 }
1150}

◆ get_tropo()

void get_tropo ( int  met_tropo,
ctl_t ctl,
clim_t clim,
met_t met,
double *  lons,
int  nx,
double *  lats,
int  ny,
double *  pt,
double *  zt,
double *  tt,
double *  qt,
double *  o3t,
double *  ps,
double *  zs 
)

Calculate tropopause data.

This function reads and interpolates various meteorological parameters such as tropopause pressure, temperature, and ozone concentration at specified latitudes and longitudes. The interpolated data is stored in the provided arrays.

Parameters
met_tropoAn integer specifying the type of meteorological data to use.
ctlPointer to a ctl_t structure that controls the meteorological data processing.
climPointer to a clim_t structure containing climatological data.
metPointer to a met_t structure containing meteorological data.
lonsArray of longitudes at which to interpolate data. The array should have nx elements.
nxNumber of longitude points.
latsArray of latitudes at which to interpolate data. The array should have ny elements.
nyNumber of latitude points.
ptPointer to an array where the interpolated pressure values will be stored. The array should have nx * ny elements.
ztPointer to an array where the interpolated height values will be stored. The array should have nx * ny elements.
ttPointer to an array where the interpolated temperature values will be stored. The array should have nx * ny elements.
qtPointer to an array where the interpolated specific humidity values will be stored. The array should have nx * ny elements.
o3tPointer to an array where the interpolated ozone concentration values will be stored. The array should have nx * ny elements.
psPointer to an array where the interpolated surface pressure values will be stored. The array should have nx * ny elements.
zsPointer to an array where the interpolated surface height values will be stored. The array should have nx * ny elements.
Precondition
lons must have at least nx elements.
lats must have at least ny elements.
pt, zt, tt, qt, o3t, ps, and zs must have at least nx * ny elements.
Postcondition
The arrays pt, zt, tt, qt, o3t, ps, and zs will contain the interpolated meteorological data.
Note
The function utilizes OpenMP for parallel processing of the interpolation tasks.
The function uses the auxiliary functions read_met_tropo, intpol_met_space_2d, and intpol_met_space_3d for reading and interpolating the tropopause data.
Author
Lars Hoffmann

Definition at line 1154 of file mptrac.c.

1169 {
1170
1172
1173 ctl->met_tropo = met_tropo;
1174 read_met_tropo(ctl, clim, met);
1175#pragma omp parallel for default(shared) private(ci,cw)
1176 for (int ix = 0; ix < nx; ix++)
1177 for (int iy = 0; iy < ny; iy++) {
1178 intpol_met_space_2d(met, met->pt, lons[ix], lats[iy],
1179 &pt[iy * nx + ix], ci, cw, 1);
1180 intpol_met_space_2d(met, met->ps, lons[ix], lats[iy],
1181 &ps[iy * nx + ix], ci, cw, 0);
1182 intpol_met_space_2d(met, met->zs, lons[ix], lats[iy],
1183 &zs[iy * nx + ix], ci, cw, 0);
1184 intpol_met_space_3d(met, met->z, pt[iy * nx + ix], lons[ix],
1185 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
1186 intpol_met_space_3d(met, met->t, pt[iy * nx + ix], lons[ix],
1187 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
1188 intpol_met_space_3d(met, met->h2o, pt[iy * nx + ix], lons[ix],
1189 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
1190 intpol_met_space_3d(met, met->o3, pt[iy * nx + ix], lons[ix],
1191 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
1192 }
1193}
void read_met_tropo(ctl_t *ctl, clim_t *clim, met_t *met)
Calculates the tropopause and related meteorological variables based on various methods and stores th...
Definition: mptrac.c:7634
void intpol_met_space_3d(met_t *met, float array[EX][EY][EP], double p, double lon, double lat, double *var, int *ci, double *cw, int init)
Interpolates meteorological variables in 3D space.
Definition: mptrac.c:1373
void intpol_met_space_2d(met_t *met, float array[EX][EY], double lon, double lat, double *var, int *ci, double *cw, int init)
Interpolates meteorological variables in 2D space.
Definition: mptrac.c:1500
#define INTPOL_INIT
Initialize arrays for interpolation.
Definition: mptrac.h:656
int met_tropo
Tropopause definition (0=none, 1=clim, 2=cold point, 3=WMO_1st, 4=WMO_2nd, 5=dynamical).
Definition: mptrac.h:2559
float h2o[EX][EY][EP]
Water vapor volume mixing ratio [1].
Definition: mptrac.h:3398
float ps[EX][EY]
Surface pressure [hPa].
Definition: mptrac.h:3317
float zs[EX][EY]
Surface geopotential height [km].
Definition: mptrac.h:3323
float o3[EX][EY][EP]
Ozone volume mixing ratio [1].
Definition: mptrac.h:3401
float t[EX][EY][EP]
Temperature [K].
Definition: mptrac.h:3383
float pt[EX][EY]
Tropopause pressure [hPa].
Definition: mptrac.h:3341
float z[EX][EY][EP]
Geopotential height [km].
Definition: mptrac.h:3380
Here is the call graph for this function:

◆ intpol_met_4d_coord()

void intpol_met_4d_coord ( met_t met0,
float  height0[EX][EY][EP],
float  array0[EX][EY][EP],
met_t met1,
float  height1[EX][EY][EP],
float  array1[EX][EY][EP],
double  ts,
double  height,
double  lon,
double  lat,
double *  var,
int *  ci,
double *  cw,
int  init 
)

Interpolates meteorological variables to a given position and time.

This function interpolates meteorological variables to a specified position and time. It calculates the interpolated value based on the values provided at two time steps and performs interpolation in time, longitude, latitude, and altitude dimensions.

Parameters
met0Pointer to the meteorological data at the first time step.
height0Array containing heights at the first time step.
array0Array containing meteorological variable values at the first time step.
met1Pointer to the meteorological data at the second time step.
height1Array containing heights at the second time step.
array1Array containing meteorological variable values at the second time step.
tsInterpolation time (fractional time between met0 and met1).
heightAltitude at which to interpolate.
lonLongitude at which to interpolate.
latLatitude at which to interpolate.
varPointer to store the interpolated variable value.
ciArray to store the calculated indices.
cwArray to store the weighting factors.
initFlag indicating if it's the first call (1) or not (0).

The function first restricts the longitude within the range [0, 360) degrees. It then calculates the horizontal indices (ci[0] and ci[1]) based on the provided longitude and latitude. Next, it locates the vertical indices for each edge of the column based on the provided height.

The function then calculates the weighting factors for time, longitude, latitude, and altitude. It iterates over the interpolation process to determine the altitude weighting factor. After initializing the interpolation parameters, it calculates the interpolated variable value and stores it in the memory location pointed to by var.

Note
Ensure that all arrays (height0, array0, height1, array1, ci, cw) have sufficient memory allocated before calling this function.
Author
Jan Clemens

Definition at line 1197 of file mptrac.c.

1211 {
1212
1213 if (init) {
1214
1215 /* Restrict positions to coordinate range... */
1216 lon = FMOD(lon, 360.);
1217 if (met0->lon[met0->nx - 1] > 180 && lon < 0)
1218 lon += 360;
1219
1220 /* Get horizontal indizes... */
1221 ci[0] = locate_irr(met0->lon, met0->nx, lon);
1222 ci[1] = locate_irr(met0->lat, met0->ny, lat);
1223
1224 /* Locate the vertical indizes for each edge of the column... */
1225 int ind[2][4];
1226 locate_vert(heights0, met0->npl, ci[0], ci[1], height, ind[0]);
1227 locate_vert(heights1, met1->npl, ci[0], ci[1], height, ind[1]);
1228
1229 /* Find minimum and maximum indizes... */
1230 ci[2] = ind[0][0];
1231 int k_max = ind[0][0];
1232 for (int i = 0; i < 2; i++)
1233 for (int j = 0; j < 4; j++) {
1234 if (ci[2] > ind[i][j])
1235 ci[2] = ind[i][j];
1236 if (k_max < ind[i][j])
1237 k_max = ind[i][j];
1238 }
1239
1240 /* Get weighting factors for time, longitude and latitude... */
1241 cw[3] = (ts - met0->time) / (met1->time - met0->time);
1242 cw[0] = (lon - met0->lon[ci[0]]) /
1243 (met0->lon[ci[0] + 1] - met0->lon[ci[0]]);
1244 cw[1] = (lat - met0->lat[ci[1]]) /
1245 (met0->lat[ci[1] + 1] - met0->lat[ci[1]]);
1246
1247 /* Start determiniation of the altitude weighting factor... */
1248 double height_top, height_bot;
1249 double height00, height01, height10, height11, height0, height1;
1250
1251 /* Interpolate in time at the lowest level... */
1252 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
1253 - heights0[ci[0]][ci[1]][ci[2]])
1254 + heights0[ci[0]][ci[1]][ci[2]];
1255 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
1256 - heights0[ci[0]][ci[1] + 1][ci[2]])
1257 + heights0[ci[0]][ci[1] + 1][ci[2]];
1258 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
1259 - heights0[ci[0] + 1][ci[1]][ci[2]])
1260 + heights0[ci[0] + 1][ci[1]][ci[2]];
1261 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
1262 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
1263 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
1264
1265 /* Interpolate in latitude direction... */
1266 height0 = cw[1] * (height01 - height00) + height00;
1267 height1 = cw[1] * (height11 - height10) + height10;
1268
1269 /* Interpolate in longitude direction... */
1270 height_bot = cw[0] * (height1 - height0) + height0;
1271
1272 /* Interpolate in time at the upper level... */
1273 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
1274 - heights0[ci[0]][ci[1]][ci[2] + 1])
1275 + heights0[ci[0]][ci[1]][ci[2] + 1];
1276 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
1277 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
1278 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
1279 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
1280 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
1281 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
1282 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1283 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1284 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1285
1286 /* Interpolate in latitude direction... */
1287 height0 = cw[1] * (height01 - height00) + height00;
1288 height1 = cw[1] * (height11 - height10) + height10;
1289
1290 /* Interpolate in longitude direction... */
1291 height_top = cw[0] * (height1 - height0) + height0;
1292
1293 /* Search at higher levels if height is not in box... */
1294 while (((heights0[0][0][0] > heights0[0][0][1]) &&
1295 ((height_bot <= height) || (height_top > height))
1296 && (height_bot >= height) && (ci[2] < k_max))
1297 ||
1298 ((heights0[0][0][0] < heights0[0][0][1]) &&
1299 ((height_bot >= height) || (height_top < height))
1300 && (height_bot <= height) && (ci[2] < k_max))
1301 ) {
1302
1303 ci[2]++;
1304 height_bot = height_top;
1305
1306 /* Interpolate in time at the next level... */
1307 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
1308 - heights0[ci[0]][ci[1]][ci[2] + 1])
1309 + heights0[ci[0]][ci[1]][ci[2] + 1];
1310 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
1311 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
1312 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
1313 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
1314 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
1315 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
1316 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1317 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1318 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1319
1320 /* Interpolate in latitude direction... */
1321 height0 = cw[1] * (height01 - height00) + height00;
1322 height1 = cw[1] * (height11 - height10) + height10;
1323
1324 /* Interpolate in longitude direction... */
1325 height_top = cw[0] * (height1 - height0) + height0;
1326 }
1327
1328 /* Get vertical weighting factors... */
1329 cw[2] = (height - height_bot)
1330 / (height_top - height_bot);
1331 }
1332
1333 /* Calculate the needed array values... */
1334 double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
1335 - array0[ci[0]][ci[1]][ci[2]])
1336 + array0[ci[0]][ci[1]][ci[2]];
1337 double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
1338 - array0[ci[0] + 1][ci[1]][ci[2]])
1339 + array0[ci[0] + 1][ci[1]][ci[2]];
1340 double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
1341 - array0[ci[0]][ci[1] + 1][ci[2]])
1342 + array0[ci[0]][ci[1] + 1][ci[2]];
1343 double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
1344 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
1345 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
1346 double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
1347 - array0[ci[0]][ci[1]][ci[2] + 1])
1348 + array0[ci[0]][ci[1]][ci[2] + 1];
1349 double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
1350 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
1351 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
1352 double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
1353 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
1354 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
1355 double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1356 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1357 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1358
1359 double array00 = cw[0] * (array100 - array000) + array000;
1360 double array10 = cw[0] * (array110 - array010) + array010;
1361 double array01 = cw[0] * (array101 - array001) + array001;
1362 double array11 = cw[0] * (array111 - array011) + array011;
1363
1364 double aux0 = cw[1] * (array10 - array00) + array00;
1365 double aux1 = cw[1] * (array11 - array01) + array01;
1366
1367 /* Interpolate vertically... */
1368 *var = cw[2] * (aux1 - aux0) + aux0;
1369}
void locate_vert(float profiles[EX][EY][EP], int np, int lon_ap_ind, int lat_ap_ind, double height_ap, int *ind)
Locate the four vertical indizes of a box for a given height value.
Definition: mptrac.c:2136
int nx
Number of longitudes.
Definition: mptrac.h:3293
int ny
Number of latitudes.
Definition: mptrac.h:3296
double lon[EX]
Longitude [deg].
Definition: mptrac.h:3305
int npl
Number of model levels.
Definition: mptrac.h:3302
double time
Time [s].
Definition: mptrac.h:3290
double lat[EY]
Latitude [deg].
Definition: mptrac.h:3308
Here is the call graph for this function:

◆ intpol_met_space_3d()

void intpol_met_space_3d ( met_t met,
float  array[EX][EY][EP],
double  p,
double  lon,
double  lat,
double *  var,
int *  ci,
double *  cw,
int  init 
)

Interpolates meteorological variables in 3D space.

This function interpolates meteorological variables at a specified pressure level and geographic position. It calculates the interpolated value based on the values provided at neighboring grid points and performs interpolation in pressure, longitude, and latitude dimensions.

Parameters
metPointer to the meteorological data.
arrayArray containing meteorological variable values.
pPressure level at which to interpolate.
lonLongitude at which to interpolate.
latLatitude at which to interpolate.
varPointer to store the interpolated variable value.
ciArray to store the calculated indices.
cwArray to store the weighting factors.
initFlag indicating if it's the first call (1) or not (0).

The function first checks the longitude and adjusts it if necessary to ensure it falls within the valid range. It then calculates the interpolation indices based on the provided pressure level, longitude, and latitude. Next, it computes the interpolation weights for pressure, longitude, and latitude.

The function interpolates vertically first and then horizontally. The interpolated value is stored in the memory location pointed to by var.

Note
Ensure that the array, ci, and cw arrays have sufficient memory allocated before calling this function.
Author
Lars Hoffmann

Definition at line 1373 of file mptrac.c.

1382 {
1383
1384 /* Initialize interpolation... */
1385 if (init) {
1386
1387 /* Check longitude... */
1388 if (met->lon[met->nx - 1] > 180 && lon < 0)
1389 lon += 360;
1390
1391 /* Get interpolation indices... */
1392 ci[0] = locate_irr(met->p, met->np, p);
1393 ci[1] = locate_reg(met->lon, met->nx, lon);
1394 ci[2] = locate_reg(met->lat, met->ny, lat);
1395
1396 /* Get interpolation weights... */
1397 cw[0] = (met->p[ci[0] + 1] - p)
1398 / (met->p[ci[0] + 1] - met->p[ci[0]]);
1399 cw[1] = (met->lon[ci[1] + 1] - lon)
1400 / (met->lon[ci[1] + 1] - met->lon[ci[1]]);
1401 cw[2] = (met->lat[ci[2] + 1] - lat)
1402 / (met->lat[ci[2] + 1] - met->lat[ci[2]]);
1403 }
1404
1405 /* Interpolate vertically... */
1406 double aux00 =
1407 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
1408 + array[ci[1]][ci[2]][ci[0] + 1];
1409 double aux01 =
1410 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
1411 array[ci[1]][ci[2] + 1][ci[0] + 1])
1412 + array[ci[1]][ci[2] + 1][ci[0] + 1];
1413 double aux10 =
1414 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
1415 array[ci[1] + 1][ci[2]][ci[0] + 1])
1416 + array[ci[1] + 1][ci[2]][ci[0] + 1];
1417 double aux11 =
1418 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
1419 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
1420 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
1421
1422 /* Interpolate horizontally... */
1423 aux00 = cw[2] * (aux00 - aux01) + aux01;
1424 aux11 = cw[2] * (aux10 - aux11) + aux11;
1425 *var = cw[1] * (aux00 - aux11) + aux11;
1426}
int np
Number of pressure levels.
Definition: mptrac.h:3299
double p[EP]
Pressure levels [hPa].
Definition: mptrac.h:3311
Here is the call graph for this function:

◆ intpol_met_space_3d_ml()

void intpol_met_space_3d_ml ( met_t met,
float  array[EX][EY][EP],
double  p,
double  lon,
double  lat,
double *  var 
)

Interpolates a meteorological variable in 3D space (longitude, latitude, pressure).

This function performs trilinear interpolation of a meteorological variable based on the provided longitude, latitude, and pressure coordinates. The meteorological data is given in a 3D array, and the function calculates the interpolated value and stores it in the variable pointed to by var. The function operates on model level data.

Parameters
[in]metPointer to a met_t structure containing the meteorological data.
[in]array3D array of meteorological data with dimensions [EX][EY][EP].
[in]pPressure coordinate at which to interpolate.
[in]lonLongitude coordinate at which to interpolate.
[in]latLatitude coordinate at which to interpolate.
[out]varPointer to a double where the interpolated value will be stored.
Author
Lars Hoffmann

Definition at line 1430 of file mptrac.c.

1436 {
1437
1438 /* Check longitude... */
1439 if (met->lon[met->nx - 1] > 180 && lon < 0)
1440 lon += 360;
1441
1442 /* Get horizontal indices... */
1443 int ix = locate_reg(met->lon, met->nx, lon);
1444 int iy = locate_reg(met->lat, met->ny, lat);
1445
1446 /* Interpolate vertically... */
1447 int iz = locate_irr_float(met->pl[ix][iy], met->npl, p, 0);
1448 double aux00;
1449 if (p >= met->pl[ix][iy][iz + 1])
1450 aux00 = array[ix][iy][iz + 1];
1451 else if (p <= met->pl[ix][iy][iz])
1452 aux00 = array[ix][iy][iz];
1453 else
1454 aux00 = LIN(met->pl[ix][iy][iz],
1455 array[ix][iy][iz],
1456 met->pl[ix][iy][iz + 1], array[ix][iy][iz + 1], p);
1457
1458 iz = locate_irr_float(met->pl[ix][iy + 1], met->npl, p, iz);
1459 double aux01;
1460 if (p >= met->pl[ix][iy + 1][iz + 1])
1461 aux01 = array[ix][iy + 1][iz + 1];
1462 else if (p <= met->pl[ix][iy + 1][iz])
1463 aux01 = array[ix][iy + 1][iz];
1464 else
1465 aux01 = LIN(met->pl[ix][iy + 1][iz],
1466 array[ix][iy + 1][iz],
1467 met->pl[ix][iy + 1][iz + 1], array[ix][iy + 1][iz + 1], p);
1468
1469 iz = locate_irr_float(met->pl[ix + 1][iy], met->npl, p, iz);
1470 double aux10;
1471 if (p >= met->pl[ix + 1][iy][iz + 1])
1472 aux10 = array[ix + 1][iy][iz + 1];
1473 else if (p <= met->pl[ix + 1][iy][iz])
1474 aux10 = array[ix + 1][iy][iz];
1475 else
1476 aux10 = LIN(met->pl[ix + 1][iy][iz],
1477 array[ix + 1][iy][iz],
1478 met->pl[ix + 1][iy][iz + 1], array[ix + 1][iy][iz + 1], p);
1479
1480 iz = locate_irr_float(met->pl[ix + 1][iy + 1], met->npl, p, iz);
1481 double aux11;
1482 if (p >= met->pl[ix + 1][iy + 1][iz + 1])
1483 aux11 = array[ix + 1][iy + 1][iz + 1];
1484 else if (p <= met->pl[ix + 1][iy + 1][iz])
1485 aux11 = array[ix + 1][iy + 1][iz];
1486 else
1487 aux11 = LIN(met->pl[ix + 1][iy + 1][iz],
1488 array[ix + 1][iy + 1][iz],
1489 met->pl[ix + 1][iy + 1][iz + 1],
1490 array[ix + 1][iy + 1][iz + 1], p);
1491
1492 /* Interpolate horizontally... */
1493 double aux0 = LIN(met->lat[iy], aux00, met->lat[iy + 1], aux01, lat);
1494 double aux1 = LIN(met->lat[iy], aux10, met->lat[iy + 1], aux11, lat);
1495 *var = LIN(met->lon[ix], aux0, met->lon[ix + 1], aux1, lon);
1496}
int locate_irr_float(const float *xx, const int n, const double x, const int ig)
Locate the index of the interval containing a given value in an irregularly spaced array.
Definition: mptrac.c:2049
float pl[EX][EY][EP]
Pressure on model levels [hPa].
Definition: mptrac.h:3419
Here is the call graph for this function:

◆ intpol_met_space_2d()

void intpol_met_space_2d ( met_t met,
float  array[EX][EY],
double  lon,
double  lat,
double *  var,
int *  ci,
double *  cw,
int  init 
)

Interpolates meteorological variables in 2D space.

This function interpolates meteorological variables at a specified geographic position. It calculates the interpolated value based on the values provided at neighboring grid points and performs interpolation in longitude and latitude dimensions.

Parameters
metPointer to the meteorological data.
arrayArray containing meteorological variable values.
lonLongitude at which to interpolate.
latLatitude at which to interpolate.
varPointer to store the interpolated variable value.
ciArray to store the calculated indices.
cwArray to store the weighting factors.
initFlag indicating if it's the first call (1) or not (0).

The function first checks the longitude and adjusts it if necessary to ensure it falls within the valid range. It then calculates the interpolation indices based on the provided longitude and latitude. Next, it computes the interpolation weights for longitude and latitude.

The function interpolates horizontally and stores the interpolated value in the memory location pointed to by var. If any of the data values used in interpolation are not finite, the function handles this situation by choosing a valid value or performing a simple interpolation.

Note
Ensure that the array, ci, and cw arrays have sufficient memory allocated before calling this function.
Author
Lars Hoffmann

Definition at line 1500 of file mptrac.c.

1508 {
1509
1510 /* Initialize interpolation... */
1511 if (init) {
1512
1513 /* Check longitude... */
1514 if (met->lon[met->nx - 1] > 180 && lon < 0)
1515 lon += 360;
1516
1517 /* Get interpolation indices... */
1518 ci[1] = locate_reg(met->lon, met->nx, lon);
1519 ci[2] = locate_reg(met->lat, met->ny, lat);
1520
1521 /* Get interpolation weights... */
1522 cw[1] = (met->lon[ci[1] + 1] - lon)
1523 / (met->lon[ci[1] + 1] - met->lon[ci[1]]);
1524 cw[2] = (met->lat[ci[2] + 1] - lat)
1525 / (met->lat[ci[2] + 1] - met->lat[ci[2]]);
1526 }
1527
1528 /* Set variables... */
1529 double aux00 = array[ci[1]][ci[2]];
1530 double aux01 = array[ci[1]][ci[2] + 1];
1531 double aux10 = array[ci[1] + 1][ci[2]];
1532 double aux11 = array[ci[1] + 1][ci[2] + 1];
1533
1534 /* Interpolate horizontally... */
1535 if (isfinite(aux00) && isfinite(aux01)
1536 && isfinite(aux10) && isfinite(aux11)) {
1537 aux00 = cw[2] * (aux00 - aux01) + aux01;
1538 aux11 = cw[2] * (aux10 - aux11) + aux11;
1539 *var = cw[1] * (aux00 - aux11) + aux11;
1540 } else {
1541 if (cw[2] < 0.5) {
1542 if (cw[1] < 0.5)
1543 *var = aux11;
1544 else
1545 *var = aux01;
1546 } else {
1547 if (cw[1] < 0.5)
1548 *var = aux10;
1549 else
1550 *var = aux00;
1551 }
1552 }
1553}
Here is the call graph for this function:

◆ intpol_met_time_3d()

void intpol_met_time_3d ( met_t met0,
float  array0[EX][EY][EP],
met_t met1,
float  array1[EX][EY][EP],
double  ts,
double  p,
double  lon,
double  lat,
double *  var,
int *  ci,
double *  cw,
int  init 
)

Interpolates meteorological data in 3D space and time.

This function interpolates meteorological data in three dimensions (longitude, latitude, and pressure) and time. It calculates the interpolated value based on the values provided at neighboring grid points and performs interpolation both spatially and temporally.

Parameters
met0Pointer to the meteorological data at time t0.
array03D array of meteorological data at time t0.
met1Pointer to the meteorological data at time t1.
array13D array of meteorological data at time t1.
tsTime stamp at which to interpolate.
pPressure level at which to interpolate.
lonLongitude at which to interpolate.
latLatitude at which to interpolate.
varPointer to store the interpolated value.
ciArray to store the calculated indices.
cwArray to store the weighting factors.
initFlag indicating if it's the first call (1) or not (0).

The function first performs spatial interpolation for both time instances (t0 and t1) using the intpol_met_space_3d function. It then calculates the weighting factor wt based on the time stamp ts. Finally, it performs temporal interpolation using the interpolated values at t0 and t1 along with the weighting factor to compute the final interpolated value stored in var.

Note
Ensure that the ci and cw arrays have sufficient memory allocated before calling this function.
Author
Lars Hoffmann

Definition at line 1557 of file mptrac.c.

1569 {
1570
1571 double var0, var1, wt;
1572
1573 /* Spatial interpolation... */
1574 intpol_met_space_3d(met0, array0, p, lon, lat, &var0, ci, cw, init);
1575 intpol_met_space_3d(met1, array1, p, lon, lat, &var1, ci, cw, 0);
1576
1577 /* Get weighting factor... */
1578 wt = (met1->time - ts) / (met1->time - met0->time);
1579
1580 /* Interpolate... */
1581 *var = wt * (var0 - var1) + var1;
1582}
Here is the call graph for this function:

◆ intpol_met_time_3d_ml()

void intpol_met_time_3d_ml ( met_t met0,
float  array0[EX][EY][EP],
met_t met1,
float  array1[EX][EY][EP],
double  ts,
double  p,
double  lon,
double  lat,
double *  var 
)

Interpolates a meteorological variable in time and 3D space (longitude, latitude, pressure).

This function performs spatiotemporal interpolation of a meteorological variable based on the provided longitude, latitude, pressure, and timestamp. The meteorological data is given in two 3D arrays corresponding to two different time steps, and the function calculates the interpolated value and stores it in the variable pointed to by var. The function operates on model level data.

Parameters
[in]met0Pointer to a met_t structure containing the meteorological data for the first time step.
[in]array03D array of meteorological data for the first time step with dimensions [EX][EY][EP].
[in]met1Pointer to a met_t structure containing the meteorological data for the second time step.
[in]array13D array of meteorological data for the second time step with dimensions [EX][EY][EP].
[in]tsTimestamp at which to interpolate.
[in]pPressure coordinate at which to interpolate.
[in]lonLongitude coordinate at which to interpolate.
[in]latLatitude coordinate at which to interpolate.
[out]varPointer to a double where the interpolated value will be stored.
Author
Lars Hoffmann

Definition at line 1586 of file mptrac.c.

1595 {
1596
1597 double var0, var1;
1598
1599 /* Spatial interpolation... */
1600 intpol_met_space_3d_ml(met0, array0, p, lon, lat, &var0);
1601 intpol_met_space_3d_ml(met1, array1, p, lon, lat, &var1);
1602
1603 /* Interpolate... */
1604 *var = LIN(met0->time, var0, met1->time, var1, ts);
1605}
void intpol_met_space_3d_ml(met_t *met, float array[EX][EY][EP], double p, double lon, double lat, double *var)
Interpolates a meteorological variable in 3D space (longitude, latitude, pressure).
Definition: mptrac.c:1430
Here is the call graph for this function:

◆ intpol_met_time_2d()

void intpol_met_time_2d ( met_t met0,
float  array0[EX][EY],
met_t met1,
float  array1[EX][EY],
double  ts,
double  lon,
double  lat,
double *  var,
int *  ci,
double *  cw,
int  init 
)

Interpolates meteorological data in 2D space and time.

This function interpolates meteorological data in two dimensions (longitude and latitude) and time. It calculates the interpolated value based on the values provided at neighboring grid points and performs interpolation both spatially and temporally.

Parameters
met0Pointer to the meteorological data at time t0.
array02D array of meteorological data at time t0.
met1Pointer to the meteorological data at time t1.
array12D array of meteorological data at time t1.
tsTime stamp at which to interpolate.
lonLongitude at which to interpolate.
latLatitude at which to interpolate.
varPointer to store the interpolated value.
ciArray to store the calculated indices.
cwArray to store the weighting factors.
initFlag indicating if it's the first call (1) or not (0).

The function first performs spatial interpolation for both time instances (t0 and t1) using the intpol_met_space_2d function. It then calculates the weighting factor wt based on the time stamp ts. Finally, it performs temporal interpolation using the interpolated values at t0 and t1 along with the weighting factor to compute the final interpolated value stored in var. If one of the interpolated values is not finite, it selects the valid value based on the weighting factor wt.

Note
Ensure that the ci and cw arrays have sufficient memory allocated before calling this function.
Author
Lars Hoffmann

Definition at line 1609 of file mptrac.c.

1620 {
1621
1622 double var0, var1, wt;
1623
1624 /* Spatial interpolation... */
1625 intpol_met_space_2d(met0, array0, lon, lat, &var0, ci, cw, init);
1626 intpol_met_space_2d(met1, array1, lon, lat, &var1, ci, cw, 0);
1627
1628 /* Get weighting factor... */
1629 wt = (met1->time - ts) / (met1->time - met0->time);
1630
1631 /* Interpolate... */
1632 if (isfinite(var0) && isfinite(var1))
1633 *var = wt * (var0 - var1) + var1;
1634 else if (wt < 0.5)
1635 *var = var1;
1636 else
1637 *var = var0;
1638}
Here is the call graph for this function:

◆ intpol_tropo_3d()

void intpol_tropo_3d ( double  time0,
float  array0[EX][EY],
double  time1,
float  array1[EX][EY],
double  lons[EX],
double  lats[EY],
int  nlon,
int  nlat,
double  time,
double  lon,
double  lat,
int  method,
double *  var,
double *  sigma 
)

Interpolates tropopause data in 3D (latitude, longitude, and time).

This function performs interpolation of tropopause data at a given latitude, longitude, and time. The interpolation can be performed using either linear interpolation or nearest neighbor interpolation. The standard deviation of the data points used in the interpolation is also computed.

Parameters
time0Time corresponding to the first data array array0.
array0A 2D array of tropopause data at time0. The dimensions are EX by EY.
time1Time corresponding to the second data array array1.
array1A 2D array of tropopause data at time1. The dimensions are EX by EY.
lonsArray of longitudes with EX elements.
latsArray of latitudes with EY elements.
nlonNumber of longitudes.
nlatNumber of latitudes.
timeThe specific time at which to interpolate the data.
lonThe specific longitude at which to interpolate the data.
latThe specific latitude at which to interpolate the data.
methodInterpolation method: 1 for linear interpolation, otherwise nearest neighbor interpolation is used.
varPointer to the variable where the interpolated value will be stored.
sigmaPointer to the variable where the standard deviation of the data points will be stored.
Precondition
array0 and array1 must be 2D arrays of size EX by EY.
lons must have at least nlon elements and lats must have at least nlat elements.
Postcondition
var will contain the interpolated value.
sigma will contain the standard deviation of the data points used in the interpolation.
Note
The function adjusts the longitude to ensure it is within the range defined by lons.
This function uses the auxiliary functions locate_reg, LIN, and NN for locating indices and performing interpolation.
Warning
Ensure that EX and EY are defined appropriately to match the dimensions of array0 and array1.
Author
Lars Hoffmann

Definition at line 1642 of file mptrac.c.

1656 {
1657
1658 double aux0, aux1, aux00, aux01, aux10, aux11, mean = 0;
1659
1660 int n = 0;
1661
1662 /* Adjust longitude... */
1663 if (lon < lons[0])
1664 lon += 360;
1665 else if (lon > lons[nlon - 1])
1666 lon -= 360;
1667
1668 /* Get indices... */
1669 int ix = locate_reg(lons, (int) nlon, lon);
1670 int iy = locate_reg(lats, (int) nlat, lat);
1671
1672 /* Calculate standard deviation... */
1673 *sigma = 0;
1674 for (int dx = 0; dx < 2; dx++)
1675 for (int dy = 0; dy < 2; dy++) {
1676 if (isfinite(array0[ix + dx][iy + dy])) {
1677 mean += array0[ix + dx][iy + dy];
1678 *sigma += SQR(array0[ix + dx][iy + dy]);
1679 n++;
1680 }
1681 if (isfinite(array1[ix + dx][iy + dy])) {
1682 mean += array1[ix + dx][iy + dy];
1683 *sigma += SQR(array1[ix + dx][iy + dy]);
1684 n++;
1685 }
1686 }
1687 if (n > 0)
1688 *sigma = sqrt(MAX(*sigma / n - SQR(mean / n), 0.0));
1689
1690 /* Linear interpolation... */
1691 if (method == 1 && isfinite(array0[ix][iy])
1692 && isfinite(array0[ix][iy + 1])
1693 && isfinite(array0[ix + 1][iy])
1694 && isfinite(array0[ix + 1][iy + 1])
1695 && isfinite(array1[ix][iy])
1696 && isfinite(array1[ix][iy + 1])
1697 && isfinite(array1[ix + 1][iy])
1698 && isfinite(array1[ix + 1][iy + 1])) {
1699
1700 aux00 = LIN(lons[ix], array0[ix][iy],
1701 lons[ix + 1], array0[ix + 1][iy], lon);
1702 aux01 = LIN(lons[ix], array0[ix][iy + 1],
1703 lons[ix + 1], array0[ix + 1][iy + 1], lon);
1704 aux0 = LIN(lats[iy], aux00, lats[iy + 1], aux01, lat);
1705
1706 aux10 = LIN(lons[ix], array1[ix][iy],
1707 lons[ix + 1], array1[ix + 1][iy], lon);
1708 aux11 = LIN(lons[ix], array1[ix][iy + 1],
1709 lons[ix + 1], array1[ix + 1][iy + 1], lon);
1710 aux1 = LIN(lats[iy], aux10, lats[iy + 1], aux11, lat);
1711
1712 *var = LIN(time0, aux0, time1, aux1, time);
1713 }
1714
1715 /* Nearest neighbor interpolation... */
1716 else {
1717 aux00 = NN(lons[ix], array0[ix][iy],
1718 lons[ix + 1], array0[ix + 1][iy], lon);
1719 aux01 = NN(lons[ix], array0[ix][iy + 1],
1720 lons[ix + 1], array0[ix + 1][iy + 1], lon);
1721 aux0 = NN(lats[iy], aux00, lats[iy + 1], aux01, lat);
1722
1723 aux10 = NN(lons[ix], array1[ix][iy],
1724 lons[ix + 1], array1[ix + 1][iy], lon);
1725 aux11 = NN(lons[ix], array1[ix][iy + 1],
1726 lons[ix + 1], array1[ix + 1][iy + 1], lon);
1727 aux1 = NN(lats[iy], aux10, lats[iy + 1], aux11, lat);
1728
1729 *var = NN(time0, aux0, time1, aux1, time);
1730 }
1731}
#define NN(x0, y0, x1, y1, x)
Perform nearest-neighbor interpolation.
Definition: mptrac.h:1183
#define SQR(x)
Compute the square of a value.
Definition: mptrac.h:1522
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 1735 of file mptrac.c.

1743 {
1744
1745 struct tm t0, *t1;
1746
1747 t0.tm_year = 100;
1748 t0.tm_mon = 0;
1749 t0.tm_mday = 1;
1750 t0.tm_hour = 0;
1751 t0.tm_min = 0;
1752 t0.tm_sec = 0;
1753
1754 time_t jsec0 = (time_t) jsec + timegm(&t0);
1755 t1 = gmtime(&jsec0);
1756
1757 *year = t1->tm_year + 1900;
1758 *mon = t1->tm_mon + 1;
1759 *day = t1->tm_mday;
1760 *hour = t1->tm_hour;
1761 *min = t1->tm_min;
1762 *sec = t1->tm_sec;
1763 *remain = jsec - floor(jsec);
1764}

◆ kernel_weight()

double kernel_weight ( const double  kz[EP],
const double  kw[EP],
const int  nk,
const double  p 
)

Calculates the kernel weight based on altitude and given kernel data.

This function calculates the kernel weight based on altitude and given kernel data. It takes arrays of altitudes (kz) and corresponding weights (kw), the number of data points (nk), and the current altitude (p) as input.

Parameters
kzArray of altitudes.
kwArray of corresponding weights.
nkNumber of data points.
pCurrent altitude.
Returns
The calculated kernel weight.

If the number of data points is less than 2 (nk < 2), the function returns a default weight of 1.0.

The function first computes the altitude z based on the current altitude p. Then it checks whether z is outside the range of altitudes in the kernel data. If so, it returns the corresponding weight at the nearest altitude boundary. Otherwise, it interpolates linearly between the two closest altitudes in the kernel data to determine the weight at altitude z.

Author
Lars Hoffmann

Definition at line 1768 of file mptrac.c.

1772 {
1773
1774 /* Check number of data points... */
1775 if (nk < 2)
1776 return 1.0;
1777
1778 /* Get altitude... */
1779 double z = Z(p);
1780
1781 /* Get weighting factor... */
1782 if (z < kz[0])
1783 return kw[0];
1784 else if (z > kz[nk - 1])
1785 return kw[nk - 1];
1786 else {
1787 int idx = locate_irr(kz, nk, z);
1788 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
1789 }
1790}
Here is the call graph for this function:

◆ lapse_rate()

double lapse_rate ( const double  t,
const double  h2o 
)

Calculates the moist adiabatic lapse rate in Kelvin per kilometer.

This function calculates the moist adiabatic lapse rate in Kelvin per kilometer from the given temperature (t) in Kelvin and water vapor volume mixing ratio (h2o).

Parameters
tTemperature in Kelvin.
h2oWater vapor volume mixing ratio.
Returns
The moist adiabatic lapse rate in Kelvin per kilometer.

The moist adiabatic lapse rate is calculated using the formula:

\[ \Gamma = \frac{{1000 \times g \times \left(a + L_v \times r \times T\right)}} {{C_{pd} \times a + L_v^2 \times r \times \epsilon}} \]

where:

  • \( \Gamma \) is the lapse rate in Kelvin per kilometer.
  • \( g \) is the acceleration due to gravity (constant).
  • \( a = R_a \times T^2 \) is a term based on the gas constant for dry air and temperature squared.
  • \( R_a \) is the gas constant for dry air.
  • \( T \) is the temperature in Kelvin.
  • \( L_v \) is the latent heat of vaporization.
  • \( r = \frac{{S_h(h_2o)}}{{1 - S_h(h_2o)}} \) is a term based on the water vapor mixing ratio.
  • \( S_h(h_2o) \) is the saturation vapor pressure relative to the pressure at saturation.
  • \( C_{pd} \) is the specific heat of dry air at constant pressure.
  • \( \epsilon \) is the ratio of the gas constants for dry air and water vapor.

The constants used in the calculation are defined externally:

  • \( g \): Acceleration due to gravity (constant).
  • \( R_a \): Gas constant for dry air.
  • \( L_v \): Latent heat of vaporization.
  • \( C_{pd} \): Specific heat of dry air at constant pressure.
  • \( \epsilon \): Ratio of the gas constants for dry air and water vapor.
See also
Wikipedia - Lapse rate
Author
Lars Hoffmann

Definition at line 1794 of file mptrac.c.

1796 {
1797
1798 /*
1799 Calculate moist adiabatic lapse rate [K/km] from temperature [K]
1800 and water vapor volume mixing ratio [1].
1801
1802 Reference: https://en.wikipedia.org/wiki/Lapse_rate
1803 */
1804
1805 const double a = RA * SQR(t), r = SH(h2o) / (1. - SH(h2o));
1806
1807 return 1e3 * G0 * (a + LV * r * t) / (CPD * a + SQR(LV) * r * EPS);
1808}
#define SH(h2o)
Compute specific humidity from water vapor volume mixing ratio.
Definition: mptrac.h:1509
#define LV
Latent heat of vaporization of water [J/kg].
Definition: mptrac.h:182
#define EPS
Ratio of the specific gas constant of dry air and water vapor [1].
Definition: mptrac.h:167
#define CPD
Specific heat of dry air at constant pressure [J/(kg K)].
Definition: mptrac.h:162

◆ level_definitions()

void level_definitions ( ctl_t ctl)

Defines pressure levels for meteorological data.

This function defines pressure levels for meteorological data based on the given control structure (ctl). Pressure levels are defined differently based on the value of press_level_def in ctl.

Parameters
ctlControl structure containing information about pressure level definitions.

The function determines the number of pressure levels (met_np) and the corresponding pressure values (met_p) based on the value of press_level_def in the control structure ctl. It initializes the met_np and met_p fields accordingly.

Note
Valid values for press_level_def are:
  • 0: Define 138 pressure levels.
  • 1: Define 92 pressure levels.
  • 2: Define 60 pressure levels.
  • 3: Define 147 pressure levels.
  • 4: Define 101 pressure levels.
  • 5: Define 62 pressure levels.
  • 6: Define 137 pressure levels.
  • 7: Define 59 pressure levels. Any other value for press_level_def will result in an error message.
Author
Jan Clemens

Definition at line 1812 of file mptrac.c.

1813 {
1814
1815
1816 if (0 == ctl->met_press_level_def) {
1817
1818 ctl->met_np = 138;
1819
1820 const double press[138] = {
1821 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
1822 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
1823 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
1824 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
1825 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
1826 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
1827 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
1828 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
1829 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
1830 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
1831 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
1832 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
1833 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
1834 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
1835 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
1836 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
1837 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
1838 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
1839 1010.8487, 1013.2500, 1044.45
1840 };
1841
1842 for (int ip = 0; ip < ctl->met_np; ip++)
1843 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
1844
1845 } else if (1 == ctl->met_press_level_def) {
1846
1847 ctl->met_np = 92;
1848
1849 const double press[92] = {
1850 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
1851 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
1852 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
1853 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
1854 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
1855 113.6382,
1856 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
1857 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
1858 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
1859 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
1860 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
1861 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
1862 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
1863 1007.4431, 1010.8487, 1013.2500, 1044.45
1864 };
1865
1866 for (int ip = 0; ip < ctl->met_np; ip++)
1867 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
1868
1869 } else if (2 == ctl->met_press_level_def) {
1870
1871 ctl->met_np = 60;
1872
1873 const double press[60] = {
1874 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
1875 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
1876 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
1877 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
1878 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
1879 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
1880 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
1881 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1044.45
1882 };
1883
1884 for (int ip = 0; ip < ctl->met_np; ip++)
1885 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
1886
1887 } else if (3 == ctl->met_press_level_def) {
1888
1889 ctl->met_np = 147;
1890
1891 const double press[147] = {
1892 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
1893 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
1894 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
1895 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
1896 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
1897 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
1898 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
1899 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
1900 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
1901 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
1902 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
1903 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
1904 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
1905 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
1906 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
1907 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
1908 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
1909 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
1910 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73, 1028.85,
1911 1031.97,
1912 1035.09, 1038.21, 1041.33, 1044.45
1913 };
1914
1915 for (int ip = 0; ip < ctl->met_np; ip++)
1916 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
1917
1918 } else if (4 == ctl->met_press_level_def) {
1919
1920 ctl->met_np = 101;
1921
1922 const double press[101] = {
1923 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
1924 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
1925 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
1926 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
1927 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
1928 113.6382,
1929 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
1930 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
1931 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
1932 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
1933 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
1934 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
1935 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
1936 1007.4431, 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73,
1937 1028.85, 1031.97,
1938 1035.09, 1038.21, 1041.33, 1044.45
1939 };
1940
1941 for (int ip = 0; ip < ctl->met_np; ip++)
1942 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
1943
1944 } else if (5 == ctl->met_press_level_def) {
1945
1946 ctl->met_np = 62;
1947
1948 const double press[62] = {
1949 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
1950 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
1951 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
1952 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
1953 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
1954 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
1955 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
1956 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1034.86, 1039.65,
1957 1044.45
1958 };
1959
1960 for (int ip = 0; ip < ctl->met_np; ip++)
1961 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
1962
1963 } else if (6 == ctl->met_press_level_def) {
1964
1965 ctl->met_np = 137;
1966
1967 const double press[137] = {
1968 0.01, 0.02, 0.031, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861,
1969 0.2499, 0.3299, 0.4288, 0.5496, 0.6952, 0.869, 1.0742,
1970 1.3143, 1.5928, 1.9134, 2.2797, 2.6954, 3.1642, 3.6898,
1971 4.2759, 4.9262, 5.6441, 6.4334, 7.2974, 8.2397, 9.2634,
1972 10.372, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945, 18.9752,
1973 20.761, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
1974 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.199, 54.5299,
1975 57.9834, 61.5607, 65.2695, 69.1187, 73.1187, 77.281, 81.6182,
1976 86.145, 90.8774, 95.828, 101.005, 106.415, 112.068, 117.971,
1977 124.134, 130.564, 137.27, 144.262, 151.549, 159.14, 167.045,
1978 175.273, 183.834, 192.739, 201.997, 211.619, 221.615, 231.995,
1979 242.772, 253.955, 265.556, 277.585, 290.055, 302.976, 316.361,
1980 330.22, 344.566, 359.411, 374.767, 390.645, 407.058, 424.019,
1981 441.539, 459.632, 478.31, 497.584, 517.42, 537.72, 558.343,
1982 579.193, 600.167, 621.162, 642.076, 662.808, 683.262, 703.347,
1983 722.979, 742.086, 760.6, 778.466, 795.64, 812.085, 827.776,
1984 842.696, 856.838, 870.2, 882.791, 894.622, 905.712, 916.081,
1985 925.757, 934.767, 943.14, 950.908, 958.104, 965.299, 972.495,
1986 979.69, 986.886, 994.081, 1001.28, 1008.47, 1015.67, 1022.86,
1987 1030.06, 1037.25, 1044.45
1988 };
1989
1990 for (int ip = 0; ip < ctl->met_np; ip++)
1991 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
1992
1993 } else if (7 == ctl->met_press_level_def) {
1994
1995 ctl->met_np = 59;
1996
1997 const double press[59] = {
1998 0.1, 0.2, 0.3843, 0.6365, 0.9564, 1.3448, 1.8058, 2.3478,
1999 2.985, 3.7397, 4.6462, 5.7565, 7.1322, 8.8366, 10.9483,
2000 13.5647, 16.8064, 20.8227, 25.7989, 31.9642, 39.6029, 49.0671,
2001 60.1802, 73.0663, 87.7274, 104.229, 122.614, 142.902, 165.089,
2002 189.147, 215.025, 242.652, 272.059, 303.217, 336.044, 370.407,
2003 406.133, 443.009, 480.791, 519.209, 557.973, 596.777, 635.306,
2004 673.24, 710.263, 746.063, 780.346, 812.83, 843.263, 871.42,
2005 897.112, 920.189, 940.551, 958.148, 975.744, 993.341, 1010.94,
2006 1028.53, 1046.13
2007 };
2008
2009 for (int ip = 0; ip < ctl->met_np; ip++)
2010 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
2011
2012 } else {
2013 ERRMSG("Use 0 for l137, 1 for l91, 2 for l60 or values between 3 and 7.")
2014 }
2015}
int met_press_level_def
Use predefined pressure levels or not.
Definition: mptrac.h:2144
int met_np
Number of target pressure levels.
Definition: mptrac.h:2543
double met_p[EP]
Target pressure levels [hPa].
Definition: mptrac.h:2546

◆ locate_irr()

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

Locate the index of the interval containing a given value in a sorted array.

This function locates the index of the interval containing a given value in a sorted array. It uses a binary search algorithm to efficiently find the interval.

Parameters
xxPointer to the sorted array.
nSize of the array.
xValue to be located.
Returns
Index of the interval containing the value x.

The function assumes that the array xx is sorted in ascending order. It returns the index of the interval where the value x is located. If the value x is outside the range of the array, the function returns the index of the closest interval.

Author
Lars Hoffmann

Definition at line 2019 of file mptrac.c.

2022 {
2023
2024 int ilo = 0;
2025 int ihi = n - 1;
2026 int i = (ihi + ilo) >> 1;
2027
2028 if (xx[i] < xx[i + 1])
2029 while (ihi > ilo + 1) {
2030 i = (ihi + ilo) >> 1;
2031 if (xx[i] > x)
2032 ihi = i;
2033 else
2034 ilo = i;
2035 } else
2036 while (ihi > ilo + 1) {
2037 i = (ihi + ilo) >> 1;
2038 if (xx[i] <= x)
2039 ihi = i;
2040 else
2041 ilo = i;
2042 }
2043
2044 return ilo;
2045}

◆ locate_irr_float()

int locate_irr_float ( const float *  xx,
const int  n,
const double  x,
const int  ig 
)

Locate the index of the interval containing a given value in an irregularly spaced array.

This function performs a binary search to locate the interval in the array xx such that xx[ig] <= x < xx[ig + 1]. If the value x lies within the interval specified by the initial guess index ig, the function returns ig. Otherwise, it searches the array to find the correct interval.

Parameters
xxPointer to the array of floats representing the irregularly spaced intervals. The array must be of size n.
nThe number of elements in the array xx.
xThe value to locate within the intervals of the array xx.
igThe initial guess index. If the interval [xx[ig], xx[ig+1]) contains x, the function returns ig directly.
Returns
The index i such that xx[i] <= x < xx[i + 1]. If x is out of bounds, it returns the index of the closest interval.
Note
The function assumes that the array xx contains at least two elements.
The function can handle both increasing and decreasing sequences in the array xx.
Warning
The behavior is undefined if the array xx is not sorted in either increasing or decreasing order, or if it contains less than two elements.
Author
Lars Hoffmann

Definition at line 2049 of file mptrac.c.

2053 {
2054
2055 int ilo = 0;
2056 int ihi = n - 1;
2057 int i = (ihi + ilo) >> 1;
2058
2059 if (x >= xx[ig] && x < xx[ig + 1])
2060 return ig;
2061
2062 if (xx[i] < xx[i + 1])
2063 while (ihi > ilo + 1) {
2064 i = (ihi + ilo) >> 1;
2065 if (xx[i] > x)
2066 ihi = i;
2067 else
2068 ilo = i;
2069 } else
2070 while (ihi > ilo + 1) {
2071 i = (ihi + ilo) >> 1;
2072 if (xx[i] <= x)
2073 ihi = i;
2074 else
2075 ilo = i;
2076 }
2077
2078 return ilo;
2079}

◆ locate_irr_3d()

int locate_irr_3d ( float  profiles[EX][EY][EP],
int  np,
int  ind_lon,
int  ind_lat,
double  x 
)

Locate the index of the interval containing a given value in a 3D irregular grid.

This function locates the index of the interval containing a given value in a 3D irregular grid. It searches for the interval in the specified longitude and latitude indices of the grid.

Parameters
profiles3D array representing the irregular grid.
npSize of the profile (number of data points).
ind_lonIndex of the longitude.
ind_latIndex of the latitude.
xValue to be located.
Returns
Index of the interval containing the value x.

The function assumes that the array profiles represents a 3D irregular grid. It calculates the index of the interval where the value x is located based on the data in the specified longitude and latitude indices. If the value x is outside the range of the profile, the function returns the index of the closest interval.

Author
Jan Clemens

Definition at line 2083 of file mptrac.c.

2088 {
2089
2090 int ilo = 0;
2091 int ihi = np - 1;
2092 int i = (ihi + ilo) >> 1;
2093
2094 if (profiles[ind_lon][ind_lat][i] < profiles[ind_lon][ind_lat][i + 1])
2095 while (ihi > ilo + 1) {
2096 i = (ihi + ilo) >> 1;
2097 if (profiles[ind_lon][ind_lat][i] > x) {
2098 ihi = i;
2099 } else {
2100 ilo = i;
2101 }
2102 } else
2103 while (ihi > ilo + 1) {
2104 i = (ihi + ilo) >> 1;
2105 if (profiles[ind_lon][ind_lat][i] <= x) {
2106 ihi = i;
2107 } else {
2108 ilo = i;
2109 }
2110 }
2111
2112 return ilo;
2113}

◆ locate_reg()

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

Locate the index of the interval containing a given value in a regular grid.

This function locates the index of the interval containing a given value in a regular grid. It calculates the index based on the spacing between grid points and the value to be located.

Parameters
xxPointer to the array representing the regular grid.
nSize of the grid (number of grid points).
xValue to be located.
Returns
Index of the interval containing the value x.

The function assumes that the array xx represents a regular grid with equally spaced points. It calculates the index of the interval where the value x is located based on the spacing between grid points. If the value x is outside the range of the grid, the function returns the index of the closest interval.

Author
Lars Hoffmann

Definition at line 2117 of file mptrac.c.

2120 {
2121
2122 /* Calculate index... */
2123 int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2124
2125 /* Check range... */
2126 if (i < 0)
2127 return 0;
2128 else if (i > n - 2)
2129 return n - 2;
2130 else
2131 return i;
2132}

◆ locate_vert()

void locate_vert ( float  profiles[EX][EY][EP],
int  np,
int  lon_ap_ind,
int  lat_ap_ind,
double  alt_ap,
int *  ind 
)

Locate the four vertical indizes of a box for a given height value.

This function locates the vertical indices corresponding to a given height in a 3D irregular grid. It calculates the indices based on the specified longitude and latitude indices of the grid.

Parameters
profiles3D array representing the irregular grid.
npSize of the profile (number of data points).
lon_ap_indIndex of the longitude.
lat_ap_indIndex of the latitude.
alt_apHeight value.
indPointer to an array to store the resulting indices.

The function calculates the indices corresponding to the specified height in the 3D irregular grid. It stores the resulting indices in the array pointed to by ind. The indices are calculated based on the specified longitude and latitude indices of the grid.

Author
Lars Hoffmann

Definition at line 2136 of file mptrac.c.

2142 {
2143
2144 ind[0] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind],
2145 np, height_ap, 0);
2146 ind[1] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind],
2147 np, height_ap, ind[0]);
2148 ind[2] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind + 1],
2149 np, height_ap, ind[1]);
2150 ind[3] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind + 1],
2151 np, height_ap, ind[2]);
2152}
Here is the call graph for this function:

◆ module_advect()

void module_advect ( ctl_t ctl,
met_t met0,
met_t met1,
atm_t atm,
double *  dt 
)

Performs the advection of atmospheric particles using meteorological data.

This function advects particles in the atmosphere using meteorological data from two time steps, updating their positions and interpolating necessary data. It supports both pressure and zeta vertical coordinate systems.

Parameters
ctlPointer to the control structure containing configuration flags.
met0Pointer to the initial meteorological data structure.
met1Pointer to the final meteorological data structure.
atmPointer to the air parcel data structure.
dtArray of time step values for each particle.

The function performs the following operations:

  • Sets up a timer labeled "MODULE_ADVECTION" within the "PHYSICS" category for GPU profiling using NVTX.
  • Depending on the vertical coordinate system (pressure or zeta), it loops over each particle in the atmosphere (atm->np), initializing and updating their positions and velocities using meteorological data interpolation.

Pressure Coordinate System (ctl->vert_coord_ap == 0)

  • Initializes particle positions and velocities.
  • Performs integration over a specified number of nodes (ctl->advect) to update particle positions.
  • Interpolates meteorological data for velocity components (u, v, w).
  • Computes mean velocities and updates particle positions in longitude, latitude, and pressure.

Zeta Coordinate System (ctl->vert_coord_ap == 1)

  • Translates pressure into zeta coordinate if other modules have modified the pressure.
  • Initializes particle positions and velocities in zeta coordinates.
  • Performs integration over a specified number of nodes (ctl->advect) to update particle positions.
  • Interpolates meteorological data for velocity components (u, v) and zeta_dot.
  • Computes mean velocities and updates particle positions in longitude, latitude, and zeta.
  • Checks and corrects if zeta is below zero.
  • Translates updated zeta back into pressure coordinates.
Note
The function assumes that the atmospheric data structure (atm) contains arrays for time, longitude, latitude, and pressure for each point. The specific quantification of zeta is stored in atm->q[ctl.qnt_zeta].
Authors
Lars Hoffmann
Jan Clemens

Definition at line 2156 of file mptrac.c.

2161 {
2162
2163 /* Set timer... */
2164 SELECT_TIMER("MODULE_ADVECTION", "PHYSICS", NVTX_GPU);
2165
2166 /* Pressure coordinate... */
2167 if (ctl->advect_vert_coord == 0 || ctl->advect_vert_coord == 2) {
2168
2169 /* Loop over particles... */
2170 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,met0,met1,atm,dt)") {
2171
2172 /* Init... */
2174 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
2175 x[3] = { 0, 0, 0 };
2176
2177 /* Loop over integration nodes... */
2178 for (int i = 0; i < ctl->advect; i++) {
2179
2180 /* Set position... */
2181 if (i == 0) {
2182 dts = 0.0;
2183 x[0] = atm->lon[ip];
2184 x[1] = atm->lat[ip];
2185 x[2] = atm->p[ip];
2186 } else {
2187 dts = (i == 3 ? 1.0 : 0.5) * dt[ip];
2188 x[0] = atm->lon[ip] + DX2DEG(dts * u[i - 1] / 1000., atm->lat[ip]);
2189 x[1] = atm->lat[ip] + DY2DEG(dts * v[i - 1] / 1000.);
2190 x[2] = atm->p[ip] + dts * w[i - 1];
2191 }
2192 double tm = atm->time[ip] + dts;
2193
2194 /* Interpolate meteo data on pressure levels... */
2195 if (ctl->advect_vert_coord == 0) {
2196 intpol_met_time_3d(met0, met0->u, met1, met1->u,
2197 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2198 intpol_met_time_3d(met0, met0->v, met1, met1->v,
2199 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2200 intpol_met_time_3d(met0, met0->w, met1, met1->w,
2201 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
2202 }
2203
2204 /* Interpolate meteo data on model levels... */
2205 else {
2206 intpol_met_time_3d_ml(met0, met0->ul, met1, met1->ul, tm, x[2],
2207 x[0], x[1], &u[i]);
2208 intpol_met_time_3d_ml(met0, met0->vl, met1, met1->vl, tm, x[2],
2209 x[0], x[1], &v[i]);
2210 intpol_met_time_3d_ml(met0, met0->wl, met1, met1->wl, tm, x[2],
2211 x[0], x[1], &w[i]);
2212 }
2213
2214 /* Get mean wind... */
2215 double k = 1.0;
2216 if (ctl->advect == 2)
2217 k = (i == 0 ? 0.0 : 1.0);
2218 else if (ctl->advect == 4)
2219 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2220 um += k * u[i];
2221 vm += k * v[i];
2222 wm += k * w[i];
2223 }
2224
2225 /* Set new position... */
2226 atm->time[ip] += dt[ip];
2227 atm->lon[ip] += DX2DEG(dt[ip] * um / 1000.,
2228 (ctl->advect == 2 ? x[1] : atm->lat[ip]));
2229 atm->lat[ip] += DY2DEG(dt[ip] * vm / 1000.);
2230 atm->p[ip] += dt[ip] * wm;
2231 }
2232 }
2233
2234 /* Zeta coordinate... */
2235 else if (ctl->advect_vert_coord == 1) {
2236
2237 /* Loop over particles... */
2238 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,met0,met1,atm,dt)") {
2239
2240 /* If other modules have changed p translate it into a zeta... */
2241 if (ctl->advect_cpl_zeta_and_press_modules > 0) {
2243 intpol_met_4d_coord(met0, met0->pl, met0->zetal, met1,
2244 met1->pl, met1->zetal, atm->time[ip], atm->p[ip],
2245 atm->lon[ip], atm->lat[ip],
2246 &atm->q[ctl->qnt_zeta][ip], ci, cw, 1);
2247 }
2248
2249 /* Init... */
2250 double dts, u[4], um = 0, v[4], vm = 0, zeta_dot[4], zeta_dotm = 0,
2251 x[3] = { 0, 0, 0 };
2252
2253 /* Loop over integration nodes... */
2254 for (int i = 0; i < ctl->advect; i++) {
2255
2256 /* Set position... */
2257 if (i == 0) {
2258 dts = 0.0;
2259 x[0] = atm->lon[ip];
2260 x[1] = atm->lat[ip];
2261 x[2] = atm->q[ctl->qnt_zeta][ip];
2262 } else {
2263 dts = (i == 3 ? 1.0 : 0.5) * dt[ip];
2264 x[0] = atm->lon[ip] + DX2DEG(dts * u[i - 1] / 1000., atm->lat[ip]);
2265 x[1] = atm->lat[ip] + DY2DEG(dts * v[i - 1] / 1000.);
2266 x[2] = atm->q[ctl->qnt_zeta][ip] + dts * zeta_dot[i - 1];
2267 }
2268 double tm = atm->time[ip] + dts;
2269
2270 /* Interpolate meteo data... */
2272 intpol_met_4d_coord(met0, met0->zetal, met0->ul, met1, met1->zetal,
2273 met1->ul, tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2274 intpol_met_4d_coord(met0, met0->zetal, met0->vl, met1, met0->zetal,
2275 met1->vl, tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2276 intpol_met_4d_coord(met0, met0->zetal, met0->zeta_dotl, met1,
2277 met1->zetal, met1->zeta_dotl, tm, x[2], x[0],
2278 x[1], &zeta_dot[i], ci, cw, 0);
2279
2280 /* Get mean wind... */
2281 double k = 1.0;
2282 if (ctl->advect == 2)
2283 k = (i == 0 ? 0.0 : 1.0);
2284 else if (ctl->advect == 4)
2285 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2286 um += k * u[i];
2287 vm += k * v[i];
2288 zeta_dotm += k * zeta_dot[i];
2289 }
2290
2291 /* Set new position... */
2292 atm->time[ip] += dt[ip];
2293 atm->lon[ip] += DX2DEG(dt[ip] * um / 1000.,
2294 (ctl->advect == 2 ? x[1] : atm->lat[ip]));
2295 atm->lat[ip] += DY2DEG(dt[ip] * vm / 1000.);
2296 atm->q[ctl->qnt_zeta][ip] += dt[ip] * zeta_dotm;
2297
2298 /* Check if zeta is below zero... */
2299 if (atm->q[ctl->qnt_zeta][ip] < 0) {
2300 atm->q[ctl->qnt_zeta][ip] = 0;
2301 }
2302
2303 /* Set new position also in pressure coordinates... */
2305 intpol_met_4d_coord(met0, met0->zetal, met0->pl, met1, met1->zetal,
2306 met1->pl, atm->time[ip], atm->q[ctl->qnt_zeta][ip],
2307 atm->lon[ip], atm->lat[ip], &atm->p[ip], ci, cw, 1);
2308 }
2309 }
2310}
void intpol_met_time_3d(met_t *met0, float array0[EX][EY][EP], met_t *met1, float array1[EX][EY][EP], double ts, double p, double lon, double lat, double *var, int *ci, double *cw, int init)
Interpolates meteorological data in 3D space and time.
Definition: mptrac.c:1557
void intpol_met_4d_coord(met_t *met0, float heights0[EX][EY][EP], float array0[EX][EY][EP], met_t *met1, float heights1[EX][EY][EP], float array1[EX][EY][EP], double ts, double height, double lon, double lat, double *var, int *ci, double *cw, int init)
Interpolates meteorological variables to a given position and time.
Definition: mptrac.c:1197
void intpol_met_time_3d_ml(met_t *met0, float array0[EX][EY][EP], met_t *met1, float array1[EX][EY][EP], double ts, double p, double lon, double lat, double *var)
Interpolates a meteorological variable in time and 3D space (longitude, latitude, pressure).
Definition: mptrac.c:1586
#define PARTICLE_LOOP(ip0, ip1, check_dt,...)
Loop over particle indices with OpenACC acceleration.
Definition: mptrac.h:1225
#define DX2DEG(dx, lat)
Convert a distance in kilometers to degrees longitude at a given latitude.
Definition: mptrac.h:501
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
Definition: mptrac.h:519
double time[NP]
Time [s].
Definition: mptrac.h:3072
double lat[NP]
Latitude [deg].
Definition: mptrac.h:3081
double lon[NP]
Longitude [deg].
Definition: mptrac.h:3078
int np
Number of air parcels.
Definition: mptrac.h:3069
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
Definition: mptrac.h:3084
double p[NP]
Pressure [hPa].
Definition: mptrac.h:3075
int advect
Advection scheme (0=off, 1=Euler, 2=midpoint, 4=Runge-Kutta).
Definition: mptrac.h:2594
int qnt_zeta
Quantity array index for zeta vertical coordinate.
Definition: mptrac.h:2358
int advect_cpl_zeta_and_press_modules
Coupled use of pressure based modules and diabatic advection.
Definition: mptrac.h:2141
int advect_vert_coord
Vertical coordinate of air parcels (0=pressure, 1=zeta, 2=eta).
Definition: mptrac.h:2147
float zeta_dotl[EX][EY][EP]
Vertical velocity on model levels [K/s].
Definition: mptrac.h:3434
float w[EX][EY][EP]
Vertical velocity [hPa/s].
Definition: mptrac.h:3392
float wl[EX][EY][EP]
Vertical velocity on model levels [hPa/s].
Definition: mptrac.h:3428
float vl[EX][EY][EP]
Meridional wind on model levels [m/s].
Definition: mptrac.h:3425
float u[EX][EY][EP]
Zonal wind [m/s].
Definition: mptrac.h:3386
float ul[EX][EY][EP]
Zonal wind on model levels [m/s].
Definition: mptrac.h:3422
float v[EX][EY][EP]
Meridional wind [m/s].
Definition: mptrac.h:3389
float zetal[EX][EY][EP]
Zeta on model levels [K].
Definition: mptrac.h:3431
Here is the call graph for this function:

◆ module_advect_init()

void module_advect_init ( ctl_t ctl,
met_t met0,
met_t met1,
atm_t atm 
)

Initializes the advection module by setting up pressure fields.

This function initializes the advection module, setting up the air parcel pressure to be consistent with the given zeta vertical coordinate. It utilizes meteorological data from two time steps and interpolates the pressure values accordingly.

Parameters
ctlPointer to the control structure containing configuration flags.
met0Pointer to the initial meteorological data structure.
met1Pointer to the final meteorological data structure.
atmPointer to the air parcel data structure.

The function performs the following operations:

  • Sets up a timer labeled "MODULE_ADVECTION" within the "PHYSICS" category.
  • If the zeta vertical coordinate system is specified (ctl->vert_coord_ap == 1), it initializes the pressure fields to be consistent with the zeta coordinate using 4D interpolation.
Author
Jan Clemens

Definition at line 2314 of file mptrac.c.

2318 {
2319
2320 /* Initialize pressure consistent with zeta... */
2321 if (ctl->advect_vert_coord == 1) {
2322#pragma omp parallel for default(shared)
2323 for (int ip = 0; ip < atm->np; ip++) {
2325 intpol_met_4d_coord(met0, met0->zetal, met0->pl, met1, met1->zetal,
2326 met1->pl, atm->time[ip], atm->q[ctl->qnt_zeta][ip],
2327 atm->lon[ip], atm->lat[ip], &atm->p[ip], ci, cw, 1);
2328 }
2329 }
2330}
Here is the call graph for this function:

◆ module_bound_cond()

void module_bound_cond ( ctl_t ctl,
clim_t clim,
met_t met0,
met_t met1,
atm_t atm,
double *  dt 
)

Apply boundary conditions to particles based on meteorological and climatological data.

This function applies boundary conditions to particles based on specified criteria, including latitude, pressure, surface layer parameters, and climatological data. It loops over each particle and checks whether it satisfies the specified boundary conditions. If a particle satisfies the conditions, its properties such as mass, volume mixing ratio, and age of air are updated accordingly.

It checks for quantity flags to determine which properties need to be updated. If the latitude or pressure of a particle falls outside the specified ranges, it skips the particle. It also considers surface layer parameters such as surface pressure, height, zeta range, and planetary boundary layer. If a particle is within the specified surface layer boundaries, its properties are updated accordingly.

The function updates properties such as mass and volume mixing ratio if the corresponding flags are set. It retrieves volume mixing ratio values for various trace gases (e.g., CFC-10, CFC-11, N2O, SF6) from climatological time series data and updates the particle properties accordingly. Additionally, it updates the age of air for each particle based on the current simulation time.

Parameters
ctlPointer to the control structure containing simulation parameters.
climPointer to the climatological data structure containing time series data.
met0Pointer to the meteorological data structure at the initial time step.
met1Pointer to the meteorological data structure at the next time step.
atmPointer to the atmospheric data structure containing particle information.
dtPointer to the time step value.
Authors
Lars Hoffmann
Mingzhao Liu

Definition at line 2334 of file mptrac.c.

2340 {
2341
2342 /* Set timer... */
2343 SELECT_TIMER("MODULE_BOUNDCOND", "PHYSICS", NVTX_GPU);
2344
2345 /* Check quantity flags... */
2346 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0 && ctl->qnt_Cccl4
2347 && ctl->qnt_Cccl3f < 0 && ctl->qnt_Cccl2f2 < 0
2348 && ctl->qnt_Cn2o < 0 && ctl->qnt_Csf6 < 0 && ctl->qnt_aoa < 0)
2349 return;
2350
2351 /* Loop over particles... */
2352 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,clim,met0,met1,atm,dt)") {
2353
2354 /* Check latitude and pressure range... */
2355 if (atm->lat[ip] < ctl->bound_lat0 || atm->lat[ip] > ctl->bound_lat1
2356 || atm->p[ip] > ctl->bound_p0 || atm->p[ip] < ctl->bound_p1)
2357 continue;
2358
2359 /* Check surface layer... */
2360 if (ctl->bound_dps > 0 || ctl->bound_dzs > 0
2361 || ctl->bound_zetas > 0 || ctl->bound_pbl) {
2362
2363 /* Get surface pressure... */
2364 double ps;
2366 INTPOL_2D(ps, 1);
2367
2368 /* Check pressure... */
2369 if (ctl->bound_dps > 0 && atm->p[ip] < ps - ctl->bound_dps)
2370 continue;
2371
2372 /* Check height... */
2373 if (ctl->bound_dzs > 0 && Z(atm->p[ip]) > Z(ps) + ctl->bound_dzs)
2374 continue;
2375
2376 /* Check zeta range... */
2377 if (ctl->bound_zetas > 0) {
2378 double t;
2379 INTPOL_3D(t, 1);
2380 if (ZETA(ps, atm->p[ip], t) > ctl->bound_zetas)
2381 continue;
2382 }
2383
2384 /* Check planetary boundary layer... */
2385 if (ctl->bound_pbl) {
2386 double pbl;
2387 INTPOL_2D(pbl, 0);
2388 if (atm->p[ip] < pbl)
2389 continue;
2390 }
2391 }
2392
2393 /* Set mass and volume mixing ratio... */
2394 if (ctl->qnt_m >= 0 && ctl->bound_mass >= 0)
2395 atm->q[ctl->qnt_m][ip] =
2396 ctl->bound_mass + ctl->bound_mass_trend * atm->time[ip];
2397 if (ctl->qnt_vmr >= 0 && ctl->bound_vmr >= 0)
2398 atm->q[ctl->qnt_vmr][ip] =
2399 ctl->bound_vmr + ctl->bound_vmr_trend * atm->time[ip];
2400
2401 /* Set CFC-10 volume mixing ratio... */
2402 if (ctl->qnt_Cccl4 >= 0 && ctl->clim_ccl4_timeseries[0] != '-')
2403 atm->q[ctl->qnt_Cccl4][ip] = clim_ts(&clim->ccl4, atm->time[ip]);
2404
2405 /* Set CFC-11 volume mixing ratio... */
2406 if (ctl->qnt_Cccl3f >= 0 && ctl->clim_ccl3f_timeseries[0] != '-')
2407 atm->q[ctl->qnt_Cccl3f][ip] = clim_ts(&clim->ccl3f, atm->time[ip]);
2408
2409 /* Set CFC-12 volume mixing ratio... */
2410 if (ctl->qnt_Cccl2f2 >= 0 && ctl->clim_ccl2f2_timeseries[0] != '-')
2411 atm->q[ctl->qnt_Cccl2f2][ip] = clim_ts(&clim->ccl2f2, atm->time[ip]);
2412
2413 /* Set N2O volume mixing ratio... */
2414 if (ctl->qnt_Cn2o >= 0 && ctl->clim_n2o_timeseries[0] != '-')
2415 atm->q[ctl->qnt_Cn2o][ip] = clim_ts(&clim->n2o, atm->time[ip]);
2416
2417 /* Set SF6 volume mixing ratio... */
2418 if (ctl->qnt_Csf6 >= 0 && ctl->clim_sf6_timeseries[0] != '-')
2419 atm->q[ctl->qnt_Csf6][ip] = clim_ts(&clim->sf6, atm->time[ip]);
2420
2421 /* Set age of air... */
2422 if (ctl->qnt_aoa >= 0)
2423 atm->q[ctl->qnt_aoa][ip] = atm->time[ip];
2424 }
2425}
double clim_ts(const clim_ts_t *ts, const double t)
Interpolates a time series of climatological variables.
Definition: mptrac.c:376
#define INTPOL_3D(var, init)
Perform 3D interpolation for a meteorological variable.
Definition: mptrac.h:687
#define ZETA(ps, p, t)
Calculate potential vorticity using the Zeta approximation.
Definition: mptrac.h:1768
#define INTPOL_2D(var, init)
Perform 2D interpolation for a meteorological variable.
Definition: mptrac.h:670
clim_ts_t ccl2f2
CFC-12 time series.
Definition: mptrac.h:3270
clim_ts_t sf6
SF6 time series.
Definition: mptrac.h:3276
clim_ts_t ccl4
CFC-10 time series.
Definition: mptrac.h:3264
clim_ts_t ccl3f
CFC-11 time series.
Definition: mptrac.h:3267
clim_ts_t n2o
N2O time series.
Definition: mptrac.h:3273
int qnt_Cccl2f2
Quantity array index for CFC-12 volume mixing ratio (chemistry code).
Definition: mptrac.h:2427
int qnt_m
Quantity array index for mass.
Definition: mptrac.h:2184
int qnt_aoa
Quantity array index for age of air.
Definition: mptrac.h:2436
char clim_n2o_timeseries[LEN]
Filename of N2O time series.
Definition: mptrac.h:2714
double bound_dzs
Boundary conditions surface layer depth [km].
Definition: mptrac.h:2663
int qnt_Cccl4
Quantity array index for CFC-10 volume mixing ratio (chemistry code).
Definition: mptrac.h:2421
double bound_mass
Boundary conditions mass per particle [kg].
Definition: mptrac.h:2636
int qnt_vmr
Quantity array index for volume mixing ratio.
Definition: mptrac.h:2187
double bound_lat1
Boundary conditions maximum longitude [deg].
Definition: mptrac.h:2651
int bound_pbl
Boundary conditions planetary boundary layer (0=no, 1=yes).
Definition: mptrac.h:2669
double bound_p1
Boundary conditions top pressure [hPa].
Definition: mptrac.h:2657
double bound_vmr
Boundary conditions volume mixing ratio [ppv].
Definition: mptrac.h:2642
double bound_lat0
Boundary conditions minimum longitude [deg].
Definition: mptrac.h:2648
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
Definition: mptrac.h:2645
int qnt_Cn2o
Quantity array index for N2O volume mixing ratio (chemistry code).
Definition: mptrac.h:2430
int qnt_Cccl3f
Quantity array index for CFC-11 volume mixing ratio (chemistry code).
Definition: mptrac.h:2424
int qnt_Csf6
Quantity array index for SF6 volume mixing ratio (chemistry code).
Definition: mptrac.h:2433
double bound_dps
Boundary conditions surface layer depth [hPa].
Definition: mptrac.h:2660
double bound_mass_trend
Boundary conditions mass per particle trend [kg/s].
Definition: mptrac.h:2639
double bound_p0
Boundary conditions bottom pressure [hPa].
Definition: mptrac.h:2654
char clim_ccl4_timeseries[LEN]
Filename of CFC-10 time series.
Definition: mptrac.h:2705
char clim_sf6_timeseries[LEN]
Filename of SF6 time series.
Definition: mptrac.h:2717
char clim_ccl3f_timeseries[LEN]
Filename of CFC-11 time series.
Definition: mptrac.h:2708
char clim_ccl2f2_timeseries[LEN]
Filename of CFC-12 time series.
Definition: mptrac.h:2711
double bound_zetas
Boundary conditions surface layer zeta [K].
Definition: mptrac.h:2666
Here is the call graph for this function:

◆ module_chemgrid()

void module_chemgrid ( ctl_t ctl,
met_t met0,
met_t met1,
atm_t atm,
double  t 
)

Calculate grid data for chemistry modules.

This function initializes and updates chemical grid quantities based on atmospheric data and interpolation of meteorological variables.

Parameters
ctlPointer to the control structure containing simulation parameters.
climPointer to the climate data structure containing climatological data.
met0Pointer to the first meteorological data structure.
met1Pointer to the second meteorological data structure.
atmPointer to the atmospheric data structure containing particle information.
tTime for which chemical grid is updated.
Authors
Mingzhao Liu
Lars Hoffmann

Definition at line 2429 of file mptrac.c.

2434 {
2435
2436 /* Check quantities... */
2437 if (ctl->molmass <= 0)
2438 ERRMSG("Molar mass is not defined!");
2439 if (ctl->qnt_m < 0)
2440 ERRMSG("Module needs quantity mass!");
2441 if (ctl->qnt_Cx < 0)
2442 ERRMSG("Module needs quantity Cx!");
2443
2444 /* Set timer... */
2445 SELECT_TIMER("MODULE_CHEMGRID", "PHYSICS", NVTX_GPU);
2446
2447 /* Allocate... */
2448 const int np = atm->np;
2449 const int nz = ctl->chemgrid_nz;
2450 const int nx = ctl->chemgrid_nx;
2451 const int ny = ctl->chemgrid_ny;
2452 const int ngrid = nx * ny * nz;
2453
2454 double *restrict const z = (double *) malloc((size_t) nz * sizeof(double));
2455 double *restrict const press =
2456 (double *) malloc((size_t) nz * sizeof(double));
2457 double *restrict const mass =
2458 (double *) calloc((size_t) ngrid, sizeof(double));
2459 double *restrict const area =
2460 (double *) malloc((size_t) ny * sizeof(double));
2461 double *restrict const lon =
2462 (double *) malloc((size_t) nx * sizeof(double));
2463 double *restrict const lat =
2464 (double *) malloc((size_t) ny * sizeof(double));
2465
2466 int *restrict const ixs = (int *) malloc((size_t) np * sizeof(int));
2467 int *restrict const iys = (int *) malloc((size_t) np * sizeof(int));
2468 int *restrict const izs = (int *) malloc((size_t) np * sizeof(int));
2469
2470 /* Set grid box size... */
2471 const double dz = (ctl->chemgrid_z1 - ctl->chemgrid_z0) / nz;
2472 const double dlon = (ctl->chemgrid_lon1 - ctl->chemgrid_lon0) / nx;
2473 const double dlat = (ctl->chemgrid_lat1 - ctl->chemgrid_lat0) / ny;
2474
2475 /* Set vertical coordinates... */
2476#ifdef _OPENACC
2477#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np],z[0:nz],press[0:nz],mass[0:ngrid],area[0:ny],lon[0:nx],lat[0:ny])
2478#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
2479#pragma acc parallel loop independent gang vector
2480#else
2481#pragma omp parallel for default(shared)
2482#endif
2483 for (int iz = 0; iz < nz; iz++) {
2484 z[iz] = ctl->chemgrid_z0 + dz * (iz + 0.5);
2485 press[iz] = P(z[iz]);
2486 }
2487
2488 /* Set time interval for output... */
2489 const double t0 = tt - 0.5 * ctl->dt_mod;
2490 const double t1 = tt + 0.5 * ctl->dt_mod;
2491
2492 /* Get indices... */
2493#ifdef _OPENACC
2494#pragma acc parallel loop independent gang vector
2495#else
2496#pragma omp parallel for default(shared)
2497#endif
2498 for (int ip = 0; ip < np; ip++) {
2499 ixs[ip] = (int) ((atm->lon[ip] - ctl->chemgrid_lon0) / dlon);
2500 iys[ip] = (int) ((atm->lat[ip] - ctl->chemgrid_lat0) / dlat);
2501 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->chemgrid_z0) / dz);
2502 if (atm->time[ip] < t0 || atm->time[ip] > t1
2503 || ixs[ip] < 0 || ixs[ip] >= nx
2504 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
2505 izs[ip] = -1;
2506 }
2507
2508 /* Set horizontal coordinates... */
2509#ifdef _OPENACC
2510#pragma acc parallel loop independent gang vector
2511#else
2512#pragma omp parallel for default(shared)
2513#endif
2514 for (int ix = 0; ix < nx; ix++)
2515 lon[ix] = ctl->chemgrid_lon0 + dlon * (ix + 0.5);
2516#ifdef _OPENACC
2517#pragma acc parallel loop independent gang vector
2518#else
2519#pragma omp parallel for default(shared)
2520#endif
2521 for (int iy = 0; iy < ny; iy++) {
2522 lat[iy] = ctl->chemgrid_lat0 + dlat * (iy + 0.5);
2523 area[iy] =
2524 dlat * dlon * SQR(RE * M_PI / 180.) * cos(lat[iy] * M_PI / 180.);
2525 }
2526
2527 /* Get mass per grid box... */
2528#ifdef _OPENACC
2529#pragma acc parallel loop independent gang vector
2530#endif
2531 for (int ip = 0; ip < np; ip++)
2532 if (izs[ip] >= 0)
2533#ifdef _OPENACC
2534#pragma acc atomic update
2535#endif
2536 mass[ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz)]
2537 += atm->q[ctl->qnt_m][ip];
2538
2539 /* Assign grid data to air parcels ... */
2540#ifdef _OPENACC
2541#pragma acc parallel loop independent gang vector
2542#else
2543#pragma omp parallel for default(shared)
2544#endif
2545 for (int ip = 0; ip < np; ip++)
2546 if (izs[ip] >= 0) {
2547
2548 /* Interpolate temperature... */
2549 double temp;
2551 intpol_met_time_3d(met0, met0->t, met1, met1->t, tt, press[izs[ip]],
2552 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
2553
2554 /* Set mass... */
2555 double m = mass[ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz)];
2556
2557 /* Calculate volume mixing ratio... */
2558 atm->q[ctl->qnt_Cx][ip] = MA / ctl->molmass * m
2559 / (1e9 * RHO(press[izs[ip]], temp) * area[iys[ip]] * dz);
2560 }
2561#ifdef _OPENACC
2562#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
2563#endif
2564
2565 /* Free... */
2566 free(mass);
2567 free(lon);
2568 free(lat);
2569 free(area);
2570 free(z);
2571 free(press);
2572 free(ixs);
2573 free(iys);
2574 free(izs);
2575}
#define ARRAY_3D(ix, iy, ny, iz, nz)
Compute the linear index of a 3D array element.
Definition: mptrac.h:386
#define P(z)
Compute pressure at given altitude.
Definition: mptrac.h:1255
#define RHO(p, t)
Compute density of air.
Definition: mptrac.h:1415
double molmass
Molar mass [g/mol].
Definition: mptrac.h:2675
double chemgrid_z1
Upper altitude of chemistry grid [km].
Definition: mptrac.h:2762
double chemgrid_z0
Lower altitude of chemistry grid [km].
Definition: mptrac.h:2759
double chemgrid_lat0
Lower latitude of chemistry grid [deg].
Definition: mptrac.h:2777
double chemgrid_lat1
Upper latitude of chemistry grid [deg].
Definition: mptrac.h:2780
double chemgrid_lon0
Lower longitude of chemistry grid [deg].
Definition: mptrac.h:2768
double chemgrid_lon1
Upper longitude of chemistry grid [deg].
Definition: mptrac.h:2771
double dt_mod
Time step of simulation [s].
Definition: mptrac.h:2448
int chemgrid_nz
Number of altitudes of chemistry grid.
Definition: mptrac.h:2756
int chemgrid_nx
Number of longitudes of chemistry grid.
Definition: mptrac.h:2765
int chemgrid_ny
Number of latitudes of chemistry grid.
Definition: mptrac.h:2774
int qnt_Cx
Quantity array index for trace species x volume mixing ratio (chemistry code).
Definition: mptrac.h:2391
Here is the call graph for this function:

◆ module_chem_init()

void module_chem_init ( ctl_t ctl,
clim_t clim,
met_t met0,
met_t met1,
atm_t atm 
)

Initializes the chemistry modules by setting atmospheric composition.

This function initializes various chemical components of the atmosphere using meteorological data and climatological information. It interpolates and sets values for water vapor (H2O), ozone (O3), and several radical species such as OH, HO2, H2O2, and O1D for each air parcel.

Parameters
ctlPointer to the control structure containing quantity flags.
climPointer to the climatology structure containing climatological data.
met0Pointer to the initial meteorological data structure.
met1Pointer to the final meteorological data structure.
atmPointer to the air parcel data structure.

The function uses OpenMP for parallel processing, iterating over each point in the atmosphere (atm->np) to initialize chemical species concentrations. It performs the following steps:

  • Interpolates H2O and O3 data from meteorological input if the respective quantity flags (ctl->qnt_Ch2o and ctl->qnt_Co3) are set.
  • Sets the concentrations of OH, HO2, H2O2, and O1D using climatological data if the respective quantity flags are set.
Authors
Mingzhao Liu

Definition at line 2579 of file mptrac.c.

2584 {
2585
2586#pragma omp parallel for default(shared)
2587 for (int ip = 0; ip < atm->np; ip++) {
2588
2589 /* Set H2O and O3 using meteo data... */
2591 if (ctl->qnt_Ch2o >= 0) {
2592 double h2o;
2593 INTPOL_3D(h2o, 1);
2594 SET_ATM(qnt_Ch2o, h2o);
2595 }
2596 if (ctl->qnt_Co3 >= 0) {
2597 double o3;
2598 INTPOL_3D(o3, 1);
2599 SET_ATM(qnt_Co3, o3);
2600 }
2601
2602 /* Set radical species... */
2603 SET_ATM(qnt_Coh, clim_oh(ctl, clim, atm->time[ip],
2604 atm->lon[ip], atm->lat[ip], atm->p[ip]));
2605 SET_ATM(qnt_Cho2, clim_zm(&clim->ho2, atm->time[ip],
2606 atm->lat[ip], atm->p[ip]));
2607 SET_ATM(qnt_Ch2o2, clim_zm(&clim->h2o2, atm->time[ip],
2608 atm->lat[ip], atm->p[ip]));
2609 SET_ATM(qnt_Co1d, clim_zm(&clim->o1d, atm->time[ip],
2610 atm->lat[ip], atm->p[ip]));
2611 }
2612}
double clim_oh(const ctl_t *ctl, const clim_t *clim, const double t, const double lon, const double lat, const double p)
Calculates the hydroxyl radical (OH) concentration from climatology data, with an optional diurnal co...
Definition: mptrac.c:88
#define SET_ATM(qnt, val)
Set atmospheric quantity value.
Definition: mptrac.h:1465
clim_zm_t ho2
HO2 zonal means.
Definition: mptrac.h:3258
clim_zm_t o1d
O(1D) zonal means.
Definition: mptrac.h:3261
clim_zm_t h2o2
H2O2 zonal means.
Definition: mptrac.h:3255
int qnt_Ch2o
Quantity array index for H2O volume mixing ratio (chemistry code).
Definition: mptrac.h:2394
int qnt_Co3
Quantity array index for O3 volume mixing ratio (chemistry code).
Definition: mptrac.h:2397
Here is the call graph for this function:

◆ module_convection()

void module_convection ( ctl_t ctl,
met_t met0,
met_t met1,
atm_t atm,
double *  dt,
double *  rs 
)

Simulate convective processes for atmospheric particles.

This function simulates convective processes for atmospheric particles based on convective available potential energy (CAPE) and convective inhibition (CIN). It loops over each particle and checks whether the CAPE exceeds a specified threshold. If CAPE is above the threshold and meets the conditions, it performs convective mixing to update the particle's pressure based on random numbers generated for each particle.

The function interpolates CAPE and CIN from meteorological data and checks whether the particle is above the cloud top level. If the conditions are met, it determines the pressure range for vertical mixing and calculates the density range based on temperature at different pressure levels. It then calculates the new density based on random numbers and updates the particle's pressure accordingly.

Parameters
ctlPointer to the control structure containing simulation parameters.
met0Pointer to the meteorological data structure at the initial time step.
met1Pointer to the meteorological data structure at the next time step.
atmPointer to the atmospheric data structure containing particle information.
dtPointer to the time step value.
rsPointer to an array of random numbers generated for each particle.
Author
Lars Hoffmann

Definition at line 2616 of file mptrac.c.

2622 {
2623
2624 /* Set timer... */
2625 SELECT_TIMER("MODULE_CONVECTION", "PHYSICS", NVTX_GPU);
2626
2627 /* Create random numbers... */
2628 module_rng(ctl, rs, (size_t) atm->np, 0);
2629
2630 /* Loop over particles... */
2631 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,met0,met1,atm,dt,rs)") {
2632
2633 /* Interpolate CAPE... */
2634 double cape;
2636 INTPOL_2D(cape, 1);
2637
2638 /* Check threshold... */
2639 if (isfinite(cape) && cape >= ctl->conv_cape) {
2640
2641 /* Check CIN... */
2642 if (ctl->conv_cin > 0) {
2643 double cin;
2644 INTPOL_2D(cin, 0);
2645 if (isfinite(cin) && cin >= ctl->conv_cin)
2646 continue;
2647 }
2648
2649 /* Interpolate equilibrium level... */
2650 double pel;
2651 INTPOL_2D(pel, 0);
2652
2653 /* Check whether particle is above cloud top... */
2654 if (!isfinite(pel) || atm->p[ip] < pel)
2655 continue;
2656
2657 /* Set pressure range for vertical mixing... */
2658 double pbot = atm->p[ip];
2659 double ptop = atm->p[ip];
2660 if (ctl->conv_mix_bot == 1) {
2661 double ps;
2662 INTPOL_2D(ps, 0);
2663 pbot = ps;
2664 }
2665 if (ctl->conv_mix_top == 1)
2666 ptop = pel;
2667
2668 /* Get density range... */
2669 double tbot, ttop;
2670 intpol_met_time_3d(met0, met0->t, met1, met1->t, atm->time[ip],
2671 pbot, atm->lon[ip], atm->lat[ip], &tbot, ci, cw, 1);
2672 intpol_met_time_3d(met0, met0->t, met1, met1->t, atm->time[ip],
2673 ptop, atm->lon[ip], atm->lat[ip], &ttop, ci, cw, 1);
2674 double rhobot = pbot / tbot;
2675 double rhotop = ptop / ttop;
2676
2677 /* Get new density... */
2678 double rho = rhobot + (rhotop - rhobot) * rs[ip];
2679
2680 /* Get pressure... */
2681 atm->p[ip] = LIN(rhobot, pbot, rhotop, ptop, rho);
2682 }
2683 }
2684}
void module_rng(ctl_t *ctl, double *rs, size_t n, int method)
Generate random numbers using various methods and distributions.
Definition: mptrac.c:3623
double conv_cape
CAPE threshold for convection module [J/kg].
Definition: mptrac.h:2621
int conv_mix_bot
Lower level for mixing (0=particle pressure, 1=surface).
Definition: mptrac.h:2630
int conv_mix_top
Upper level for mixing (0=particle pressure, 1=EL).
Definition: mptrac.h:2633
double conv_cin
CIN threshold for convection module [J/kg].
Definition: mptrac.h:2624
Here is the call graph for this function:

◆ module_decay()

void module_decay ( ctl_t ctl,
clim_t clim,
atm_t atm,
double *  dt 
)

Simulate exponential decay processes for atmospheric particles.

This function simulates decay processes for atmospheric particles based on their mass or volume mixing ratio. It loops over each particle and calculates the decay rate using weighting factors for tropospheric and stratospheric lifetimes. Exponential decay is then calculated, and the mass or volume mixing ratio of particles is updated accordingly. Loss rates can also be calculated and updated based on the decay process.

The function checks for quantity flags to ensure that mass or volume mixing ratio data is available. It then calculates the weighting factor based on the particle's location in the atmosphere and sets the lifetime accordingly. Exponential decay is calculated using the time step and the lifetime, and the particle's mass or volume mixing ratio is updated. Loss rates can also be updated based on the decay process.

Parameters
ctlPointer to the control structure containing simulation parameters.
climPointer to the climate data structure containing atmospheric data.
atmPointer to the atmospheric data structure containing particle information.
dtPointer to the time step value.
Author
Lars Hoffmann

Definition at line 2688 of file mptrac.c.

2692 {
2693
2694 /* Set timer... */
2695 SELECT_TIMER("MODULE_DECAY", "PHYSICS", NVTX_GPU);
2696
2697 /* Check quantity flags... */
2698 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
2699 ERRMSG("Module needs quantity mass or volume mixing ratio!");
2700
2701 /* Loop over particles... */
2702 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,clim,atm,dt)") {
2703
2704 /* Get weighting factor... */
2705 double w = tropo_weight(clim, atm->time[ip], atm->lat[ip], atm->p[ip]);
2706
2707 /* Set lifetime... */
2708 double tdec = w * ctl->tdec_trop + (1 - w) * ctl->tdec_strat;
2709
2710 /* Calculate exponential decay... */
2711 double aux = exp(-dt[ip] / tdec);
2712 if (ctl->qnt_m >= 0) {
2713 if (ctl->qnt_mloss_decay >= 0)
2714 atm->q[ctl->qnt_mloss_decay][ip]
2715 += atm->q[ctl->qnt_m][ip] * (1 - aux);
2716 atm->q[ctl->qnt_m][ip] *= aux;
2717 if (ctl->qnt_loss_rate >= 0)
2718 atm->q[ctl->qnt_loss_rate][ip] += 1 / tdec;
2719 }
2720 if (ctl->qnt_vmr >= 0)
2721 atm->q[ctl->qnt_vmr][ip] *= aux;
2722 }
2723}
double tropo_weight(const clim_t *clim, const double t, const double lat, const double p)
Computes the weighting factor for a given pressure with respect to the tropopause.
Definition: mptrac.c:8257
int qnt_loss_rate
Quantity array index for total loss rate.
Definition: mptrac.h:2334
int qnt_mloss_decay
Quantity array index for total mass loss due to exponential decay.
Definition: mptrac.h:2331
double tdec_strat
Life time of particles in the stratosphere [s].
Definition: mptrac.h:2681
double tdec_trop
Life time of particles in the troposphere [s].
Definition: mptrac.h:2678
Here is the call graph for this function:

◆ module_diffusion_meso()

void module_diffusion_meso ( ctl_t ctl,
met_t met0,
met_t met1,
atm_t atm,
cache_t cache,
double *  dt,
double *  rs 
)

Simulate mesoscale diffusion for atmospheric particles.

This function simulates mesoscale diffusion for atmospheric particles, including horizontal and vertical wind fluctuations. It calculates standard deviations of local wind data and temporal correlations for mesoscale fluctuations. Mesoscale wind fluctuations are then calculated based on the provided random numbers and turbulence parameters. The particle positions are updated accordingly.

The function loops over each particle and calculates indices for interpolation of wind data. It then computes standard deviations of local wind data and temporal correlations for mesoscale fluctuations. Based on the turbulence parameters and provided random numbers, it calculates horizontal and vertical mesoscale wind fluctuations. Finally, it updates the particle positions based on the calculated wind fluctuations.

Parameters
ctlPointer to the control structure containing simulation parameters.
met0Pointer to the meteorological data structure at the current time step.
met1Pointer to the meteorological data structure at the next time step.
atmPointer to the atmospheric data structure containing particle information.
cachePointer to the cache structure for temporary storage.
dtPointer to the time step value.
rsPointer to the array of random numbers.
Author
Lars Hoffmann

Definition at line 2727 of file mptrac.c.

2734 {
2735
2736 /* Set timer... */
2737 SELECT_TIMER("MODULE_TURBMESO", "PHYSICS", NVTX_GPU);
2738
2739 /* Create random numbers... */
2740 module_rng(ctl, rs, 3 * (size_t) atm->np, 1);
2741
2742 /* Loop over particles... */
2743 PARTICLE_LOOP(0, atm->np, 1,
2744 "acc data present(ctl,met0,met1,atm,cache,dt,rs)") {
2745
2746 /* Get indices... */
2747 int ix = locate_reg(met0->lon, met0->nx, atm->lon[ip]);
2748 int iy = locate_reg(met0->lat, met0->ny, atm->lat[ip]);
2749 int iz = locate_irr(met0->p, met0->np, atm->p[ip]);
2750
2751 /* Get standard deviations of local wind data... */
2752 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
2753 for (int i = 0; i < 2; i++)
2754 for (int j = 0; j < 2; j++)
2755 for (int k = 0; k < 2; k++) {
2756 umean += met0->u[ix + i][iy + j][iz + k];
2757 usig += SQR(met0->u[ix + i][iy + j][iz + k]);
2758 vmean += met0->v[ix + i][iy + j][iz + k];
2759 vsig += SQR(met0->v[ix + i][iy + j][iz + k]);
2760 wmean += met0->w[ix + i][iy + j][iz + k];
2761 wsig += SQR(met0->w[ix + i][iy + j][iz + k]);
2762
2763 umean += met1->u[ix + i][iy + j][iz + k];
2764 usig += SQR(met1->u[ix + i][iy + j][iz + k]);
2765 vmean += met1->v[ix + i][iy + j][iz + k];
2766 vsig += SQR(met1->v[ix + i][iy + j][iz + k]);
2767 wmean += met1->w[ix + i][iy + j][iz + k];
2768 wsig += SQR(met1->w[ix + i][iy + j][iz + k]);
2769 }
2770 usig = usig / 16.f - SQR(umean / 16.f);
2771 usig = (usig > 0 ? sqrtf(usig) : 0);
2772 vsig = vsig / 16.f - SQR(vmean / 16.f);
2773 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
2774 wsig = wsig / 16.f - SQR(wmean / 16.f);
2775 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
2776
2777 /* Set temporal correlations for mesoscale fluctuations... */
2778 double r = 1 - 2 * fabs(dt[ip]) / ctl->dt_met;
2779 double r2 = sqrt(1 - r * r);
2780
2781 /* Calculate horizontal mesoscale wind fluctuations... */
2782 if (ctl->turb_mesox > 0) {
2783 cache->uvwp[ip][0] =
2784 (float) (r * cache->uvwp[ip][0] +
2785 r2 * rs[3 * ip] * ctl->turb_mesox * usig);
2786 atm->lon[ip] +=
2787 DX2DEG(cache->uvwp[ip][0] * dt[ip] / 1000., atm->lat[ip]);
2788
2789 cache->uvwp[ip][1] =
2790 (float) (r * cache->uvwp[ip][1] +
2791 r2 * rs[3 * ip + 1] * ctl->turb_mesox * vsig);
2792 atm->lat[ip] += DY2DEG(cache->uvwp[ip][1] * dt[ip] / 1000.);
2793 }
2794
2795 /* Calculate vertical mesoscale wind fluctuations... */
2796 if (ctl->turb_mesoz > 0) {
2797 cache->uvwp[ip][2] =
2798 (float) (r * cache->uvwp[ip][2] +
2799 r2 * rs[3 * ip + 2] * ctl->turb_mesoz * wsig);
2800 atm->p[ip] += cache->uvwp[ip][2] * dt[ip];
2801 }
2802 }
2803}
float uvwp[NP][3]
Wind perturbations [m/s].
Definition: mptrac.h:3109
double turb_mesoz
Vertical scaling factor for mesoscale wind fluctuations.
Definition: mptrac.h:2618
double turb_mesox
Horizontal scaling factor for mesoscale wind fluctuations.
Definition: mptrac.h:2615
Here is the call graph for this function:

◆ module_diffusion_turb()

void module_diffusion_turb ( ctl_t ctl,
clim_t clim,
atm_t atm,
double *  dt,
double *  rs 
)

Simulate turbulent diffusion for atmospheric particles.

This function simulates turbulent diffusion for atmospheric particles, including horizontal and vertical diffusion. It calculates diffusivity based on the provided weighting factor and turbulence parameters. The diffusion coefficients are then used to calculate horizontal and vertical displacements of particles based on the provided random numbers and time step.

The function loops over each particle and calculates the weighting factor based on the atmospheric properties. It then computes diffusivity for horizontal and vertical diffusion. Based on the diffusivity values and provided random numbers, it calculates horizontal and vertical displacements of particles and updates their positions accordingly.

Parameters
ctlPointer to the control structure containing simulation parameters.
climPointer to the climatological data structure containing atmospheric properties.
atmPointer to the atmospheric data structure containing particle information.
dtPointer to the time step value.
rsPointer to the array of random numbers.
Author
Lars Hoffmann

Definition at line 2807 of file mptrac.c.

2812 {
2813
2814 /* Set timer... */
2815 SELECT_TIMER("MODULE_TURBDIFF", "PHYSICS", NVTX_GPU);
2816
2817 /* Create random numbers... */
2818 module_rng(ctl, rs, 3 * (size_t) atm->np, 1);
2819
2820 /* Loop over particles... */
2821 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,clim,atm,dt,rs)") {
2822
2823 /* Get weighting factor... */
2824 double w = tropo_weight(clim, atm->time[ip], atm->lat[ip], atm->p[ip]);
2825
2826 /* Set diffusivity... */
2827 double dx = w * ctl->turb_dx_trop + (1 - w) * ctl->turb_dx_strat;
2828 double dz = w * ctl->turb_dz_trop + (1 - w) * ctl->turb_dz_strat;
2829
2830 /* Horizontal turbulent diffusion... */
2831 if (dx > 0) {
2832 double sigma = sqrt(2.0 * dx * fabs(dt[ip]));
2833 atm->lon[ip] += DX2DEG(rs[3 * ip] * sigma / 1000., atm->lat[ip]);
2834 atm->lat[ip] += DY2DEG(rs[3 * ip + 1] * sigma / 1000.);
2835 }
2836
2837 /* Vertical turbulent diffusion... */
2838 if (dz > 0) {
2839 double sigma = sqrt(2.0 * dz * fabs(dt[ip]));
2840 atm->p[ip] += DZ2DP(rs[3 * ip + 2] * sigma / 1000., atm->p[ip]);
2841 }
2842 }
2843}
#define DZ2DP(dz, p)
Convert a change in altitude to a change in pressure.
Definition: mptrac.h:536
double turb_dz_trop
Vertical turbulent diffusion coefficient (troposphere) [m^2/s].
Definition: mptrac.h:2609
double turb_dx_strat
Horizontal turbulent diffusion coefficient (stratosphere) [m^2/s].
Definition: mptrac.h:2606
double turb_dx_trop
Horizontal turbulent diffusion coefficient (troposphere) [m^2/s].
Definition: mptrac.h:2603
double turb_dz_strat
Vertical turbulent diffusion coefficient (stratosphere) [m^2/s].
Definition: mptrac.h:2612
Here is the call graph for this function:

◆ module_dry_deposition()

void module_dry_deposition ( ctl_t ctl,
met_t met0,
met_t met1,
atm_t atm,
double *  dt 
)

Simulate dry deposition of atmospheric particles.

This function simulates the dry deposition of atmospheric particles, including both particulate matter and gases. It calculates the sedimentation velocity for particles based on the atmospheric properties and applies it to determine the loss of mass or volume mixing ratio due to deposition. The function loops over each particle and calculates the loss of mass or volume mixing ratio based on the deposition velocity and time step.

Parameters
ctlPointer to the control structure containing simulation parameters.
met0Pointer to the meteorological data structure at the current time step.
met1Pointer to the meteorological data structure at the next time step.
atmPointer to the atmospheric data structure containing particle information.
dtPointer to the time step value.
Author
Lars Hoffmann

Definition at line 2847 of file mptrac.c.

2852 {
2853
2854 /* Set timer... */
2855 SELECT_TIMER("MODULE_DRYDEPO", "PHYSICS", NVTX_GPU);
2856
2857 /* Check quantity flags... */
2858 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
2859 ERRMSG("Module needs quantity mass or volume mixing ratio!");
2860
2861 /* Loop over particles... */
2862 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,met0,met1,atm,dt)") {
2863
2864 /* Get surface pressure... */
2865 double ps;
2867 INTPOL_2D(ps, 1);
2868
2869 /* Check whether particle is above the surface layer... */
2870 if (atm->p[ip] < ps - ctl->dry_depo_dp)
2871 continue;
2872
2873 /* Set depth of surface layer... */
2874 double dz = 1000. * (Z(ps - ctl->dry_depo_dp) - Z(ps));
2875
2876 /* Calculate sedimentation velocity for particles... */
2877 double v_dep;
2878 if (ctl->qnt_rp > 0 && ctl->qnt_rhop > 0) {
2879
2880 /* Get temperature... */
2881 double t;
2882 INTPOL_3D(t, 1);
2883
2884 /* Set deposition velocity... */
2885 v_dep = sedi(atm->p[ip], t, atm->q[ctl->qnt_rp][ip],
2886 atm->q[ctl->qnt_rhop][ip]);
2887 }
2888
2889 /* Use explicit sedimentation velocity for gases... */
2890 else
2891 v_dep = ctl->dry_depo_vdep;
2892
2893 /* Calculate loss of mass based on deposition velocity... */
2894 double aux = exp(-dt[ip] * v_dep / dz);
2895 if (ctl->qnt_m >= 0) {
2896 if (ctl->qnt_mloss_dry >= 0)
2897 atm->q[ctl->qnt_mloss_dry][ip]
2898 += atm->q[ctl->qnt_m][ip] * (1 - aux);
2899 atm->q[ctl->qnt_m][ip] *= aux;
2900 if (ctl->qnt_loss_rate >= 0)
2901 atm->q[ctl->qnt_loss_rate][ip] += v_dep / dz;
2902 }
2903 if (ctl->qnt_vmr >= 0)
2904 atm->q[ctl->qnt_vmr][ip] *= aux;
2905 }
2906}
double sedi(const double p, const double T, const double rp, const double rhop)
Calculates the sedimentation velocity of a particle in air.
Definition: mptrac.c:7979
int qnt_rhop
Quantity array index for particle density.
Definition: mptrac.h:2193
int qnt_rp
Quantity array index for particle radius.
Definition: mptrac.h:2190
double dry_depo_dp
Dry deposition surface layer [hPa].
Definition: mptrac.h:2831
int qnt_mloss_dry
Quantity array index for total mass loss due to dry deposition.
Definition: mptrac.h:2328
double dry_depo_vdep
Dry deposition velocity [m/s].
Definition: mptrac.h:2834
Here is the call graph for this function:

◆ module_h2o2_chem()

void module_h2o2_chem ( ctl_t ctl,
clim_t clim,
met_t met0,
met_t met1,
atm_t atm,
double *  dt 
)

Perform chemical reactions involving H2O2 within cloud particles.

This function simulates chemical reactions involving hydrogen peroxide (H2O2) within cloud particles. It calculates the change in H2O2 concentration over time due to chemical reactions. The reaction rates are determined based on temperature and cloud properties such as liquid water content.

Parameters
ctlPointer to the control structure containing simulation parameters.
climPointer to the climatological data structure.
met0Pointer to the first meteorological data structure.
met1Pointer to the second meteorological data structure.
atmPointer to the atmospheric data structure containing particle information.
dtPointer to an array containing the time step for each particle.
Note
The function assumes that the necessary control structure (ctl), climatological data structure (clim), meteorological data structures (met0, met1), and atmospheric data structure (atm) have been initialized and are accessible.
Chemical reactions involving H2O2 are simulated for particles within clouds, as indicated by a positive liquid water content (LWC).
The function calculates reaction rates based on temperature and cloud properties, including the liquid water content (LWC) and the concentration of SO2.
The exponential decay of H2O2 concentration due to chemical reactions is calculated using the reaction rate coefficient and the time step (dt) for each particle.
If the particle has a quantity flag for either mass (ctl->qnt_m) or volume mixing ratio (ctl->qnt_vmr), the function updates the quantity based on the exponential decay.
If the particle has a loss rate quantity flag (ctl->qnt_loss_rate), the function accumulates the reaction rate coefficient to quantify the loss rate.
Author
Mingzhao Liu

Definition at line 2910 of file mptrac.c.

2916 {
2917
2918 /* Set timer... */
2919 SELECT_TIMER("MODULE_H2O2CHEM", "PHYSICS", NVTX_GPU);
2920
2921 /* Check quantity flags... */
2922 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
2923 ERRMSG("Module needs quantity mass or volume mixing ratio!");
2924
2925 /* Parameter of SO2 correction... */
2926 const double a = 3.12541941e-06;
2927 const double b = -5.72532259e-01;
2928 const double low = pow(1 / a, 1 / b);
2929
2930 /* Loop over particles... */
2931 PARTICLE_LOOP(0, atm->np, 1, "acc data present(clim,ctl,met0,met1,atm,dt)") {
2932
2933 /* Check whether particle is inside cloud... */
2934 double lwc, rwc;
2936 INTPOL_3D(lwc, 1);
2937 INTPOL_3D(rwc, 0);
2938 if (!(lwc > 0 || rwc > 0))
2939 continue;
2940
2941 /* Get temperature... */
2942 double t;
2943 INTPOL_3D(t, 0);
2944
2945 /* Get molecular density... */
2946 double M = MOLEC_DENS(atm->p[ip], t);
2947
2948 /* Reaction rate (Berglen et al., 2004)... */
2949 double k = 9.1e7 * exp(-29700 / RI * (1. / t - 1. / 298.15)); /* (Maass, 1999), unit: M^(-2) */
2950
2951 /* Henry constant of SO2... */
2952 double H_SO2 = 1.3e-2 * exp(2900 * (1. / t - 1. / 298.15)) * RI * t;
2953 double K_1S = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15)); /* unit: mol/L */
2954
2955 /* Henry constant of H2O2... */
2956 double H_h2o2 = 8.3e2 * exp(7600 * (1 / t - 1 / 298.15)) * RI * t;
2957
2958 /* Correction factor for high SO2 concentration
2959 (if qnt_Cx is defined, the correction is switched on)... */
2960 double cor = 1;
2961 if (ctl->qnt_Cx >= 0)
2962 cor = atm->q[ctl->qnt_Cx][ip] >
2963 low ? a * pow(atm->q[ctl->qnt_Cx][ip], b) : 1;
2964
2965 double h2o2 = H_h2o2
2966 * clim_zm(&clim->h2o2, atm->time[ip], atm->lat[ip], atm->p[ip])
2967 * M * cor * 1000 / AVO; /* unit: mol/L */
2968
2969 /* Volume water content in cloud [m^3 m^(-3)]... */
2970 double rho_air = 100 * atm->p[ip] / (RI * t) * MA / 1000;
2971 double CWC = (lwc + rwc) * rho_air / 1000;
2972
2973 /* Calculate exponential decay (Rolph et al., 1992)... */
2974 double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
2975 double aux = exp(-dt[ip] * rate_coef);
2976 if (ctl->qnt_m >= 0) {
2977 if (ctl->qnt_mloss_h2o2 >= 0)
2978 atm->q[ctl->qnt_mloss_h2o2][ip] += atm->q[ctl->qnt_m][ip] * (1 - aux);
2979 atm->q[ctl->qnt_m][ip] *= aux;
2980 if (ctl->qnt_loss_rate >= 0)
2981 atm->q[ctl->qnt_loss_rate][ip] += rate_coef;
2982 }
2983 if (ctl->qnt_vmr >= 0)
2984 atm->q[ctl->qnt_vmr][ip] *= aux;
2985 }
2986}
#define AVO
Avogadro constant [1/mol].
Definition: mptrac.h:157
#define MOLEC_DENS(p, t)
Calculate the density of a gas molecule.
Definition: mptrac.h:967
int qnt_mloss_h2o2
Quantity array index for total mass loss due to H2O2 chemistry.
Definition: mptrac.h:2319
Here is the call graph for this function:

◆ module_isosurf_init()

void module_isosurf_init ( ctl_t ctl,
met_t met0,
met_t met1,
atm_t atm,
cache_t cache 
)

Initialize the isosurface module based on atmospheric data.

This function initializes the isosurface module based on the atmospheric data provided. It calculates the necessary variables required for generating the isosurface, such as pressure, density, or potential temperature. Additionally, it can read balloon pressure data from a file if specified in the control structure. The initialized data is stored in the cache for later use.

Parameters
ctlPointer to the control structure containing simulation parameters.
met0Pointer to the meteorological data structure at the current time step.
met1Pointer to the meteorological data structure at the next time step.
atmPointer to the atmospheric data structure containing particle information.
cachePointer to the cache structure for storing initialized data.
Author
Lars Hoffmann

Definition at line 2990 of file mptrac.c.

2995 {
2996
2997 double t;
2998
2999 /* Set timer... */
3000 SELECT_TIMER("MODULE_ISOSURF", "PHYSICS", NVTX_GPU);
3001
3002 /* Init... */
3004
3005 /* Save pressure... */
3006 if (ctl->isosurf == 1)
3007 for (int ip = 0; ip < atm->np; ip++)
3008 cache->iso_var[ip] = atm->p[ip];
3009
3010 /* Save density... */
3011 else if (ctl->isosurf == 2)
3012 for (int ip = 0; ip < atm->np; ip++) {
3013 INTPOL_3D(t, 1);
3014 cache->iso_var[ip] = atm->p[ip] / t;
3015 }
3016
3017 /* Save potential temperature... */
3018 else if (ctl->isosurf == 3)
3019 for (int ip = 0; ip < atm->np; ip++) {
3020 INTPOL_3D(t, 1);
3021 cache->iso_var[ip] = THETA(atm->p[ip], t);
3022 }
3023
3024 /* Read balloon pressure data... */
3025 else if (ctl->isosurf == 4) {
3026
3027 /* Write info... */
3028 LOG(1, "Read balloon pressure data: %s", ctl->balloon);
3029
3030 /* Open file... */
3031 FILE *in;
3032 if (!(in = fopen(ctl->balloon, "r")))
3033 ERRMSG("Cannot open file!");
3034
3035 /* Read pressure time series... */
3036 char line[LEN];
3037 while (fgets(line, LEN, in))
3038 if (sscanf(line, "%lg %lg", &(cache->iso_ts[cache->iso_n]),
3039 &(cache->iso_ps[cache->iso_n])) == 2)
3040 if ((++cache->iso_n) > NP)
3041 ERRMSG("Too many data points!");
3042
3043 /* Check number of points... */
3044 if (cache->iso_n < 1)
3045 ERRMSG("Could not read any data!");
3046
3047 /* Close file... */
3048 fclose(in);
3049 }
3050}
#define NP
Maximum number of atmospheric data points.
Definition: mptrac.h:241
double iso_ts[NP]
Isosurface balloon time [s].
Definition: mptrac.h:3103
int iso_n
Isosurface balloon number of data points.
Definition: mptrac.h:3106
double iso_ps[NP]
Isosurface balloon pressure [hPa].
Definition: mptrac.h:3100
double iso_var[NP]
Isosurface variables.
Definition: mptrac.h:3097
char balloon[LEN]
Balloon position filename.
Definition: mptrac.h:2591
int isosurf
Isosurface parameter (0=none, 1=pressure, 2=density, 3=theta, 4=balloon).
Definition: mptrac.h:2588

◆ module_isosurf()

void module_isosurf ( ctl_t ctl,
met_t met0,
met_t met1,
atm_t atm,
cache_t cache,
double *  dt 
)

Apply the isosurface module to adjust atmospheric properties.

This function applies the isosurface module to adjust atmospheric properties based on the initialized data stored in the cache. It interpolates and restores atmospheric pressure, density, or potential temperature according to the specified isosurface mode in the control structure.

Parameters
ctlPointer to the control structure containing simulation parameters.
met0Pointer to the meteorological data structure at the current time step.
met1Pointer to the meteorological data structure at the next time step.
atmPointer to the atmospheric data structure containing particle information.
cachePointer to the cache structure containing initialized data.
dtArray of time step values for each particle.
Author
Lars Hoffmann

Definition at line 3054 of file mptrac.c.

3060 {
3061
3062 /* Set timer... */
3063 SELECT_TIMER("MODULE_ISOSURF", "PHYSICS", NVTX_GPU);
3064
3065 /* Loop over particles... */
3066 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,met0,met1,atm,cache,dt)") {
3067
3068 /* Init... */
3069 double t;
3071
3072 /* Restore pressure... */
3073 if (ctl->isosurf == 1)
3074 atm->p[ip] = cache->iso_var[ip];
3075
3076 /* Restore density... */
3077 else if (ctl->isosurf == 2) {
3078 INTPOL_3D(t, 1);
3079 atm->p[ip] = cache->iso_var[ip] * t;
3080 }
3081
3082 /* Restore potential temperature... */
3083 else if (ctl->isosurf == 3) {
3084 INTPOL_3D(t, 1);
3085 atm->p[ip] = 1000. * pow(cache->iso_var[ip] / t, -1. / 0.286);
3086 }
3087
3088 /* Interpolate pressure... */
3089 else if (ctl->isosurf == 4) {
3090 if (atm->time[ip] <= cache->iso_ts[0])
3091 atm->p[ip] = cache->iso_ps[0];
3092 else if (atm->time[ip] >= cache->iso_ts[cache->iso_n - 1])
3093 atm->p[ip] = cache->iso_ps[cache->iso_n - 1];
3094 else {
3095 int idx = locate_irr(cache->iso_ts, cache->iso_n, atm->time[ip]);
3096 atm->p[ip] = LIN(cache->iso_ts[idx], cache->iso_ps[idx],
3097 cache->iso_ts[idx + 1], cache->iso_ps[idx + 1],
3098 atm->time[ip]);
3099 }
3100 }
3101 }
3102}
Here is the call graph for this function:

◆ module_kpp_chem()

void module_kpp_chem ( ctl_t ctl,
clim_t clim,
met_t met0,
met_t met1,
atm_t atm,
double *  dt 
)

KPP chemistry module.

Simulate chemical reactions using the Kinetic PreProcessor (KPP) integration scheme.

This function simulates chemical reactions using the Kinetic PreProcessor (KPP) integration scheme for atmospheric particles. It loops over each particle in the atmospheric data structure and integrates chemical reactions over a specified time step using the KPP algorithm.

Parameters
ctlPointer to the control structure containing simulation parameters.
climPointer to the climatological data structure.
met0Pointer to the first meteorological data structure.
met1Pointer to the second meteorological data structure.
atmPointer to the atmospheric data structure containing particle information.
dtPointer to an array containing the time step for each particle.
Note
The function initializes a timer to measure the execution time of the chemical simulation.
Chemical integration using KPP is performed for particles with a positive time step (dt > 0).
For each particle, the function allocates memory for variable (VAR) and fixed (FIX) arrays, sets the range of time steps (STEPMIN and STEPMAX), and defines relative and absolute tolerances.
The chemical system is initialized for each particle using the kpp_chem_initialize function.
Chemical integration is performed over a specified time step (ctl->dt_kpp) using the INTEGRATE macro, which is part of the KPP integration scheme.
The function outputs the integrated chemical concentrations back to the atmospheric data structure using the kpp_chem_output2atm function.
Memory allocated for the variable (VAR) and fixed (FIX) arrays is freed after the integration is completed for each particle.
Author
Mingzhao Liu

◆ module_meteo()

void module_meteo ( ctl_t ctl,
clim_t clim,
met_t met0,
met_t met1,
atm_t atm,
double *  dt 
)

Update atmospheric properties using meteorological data.

This function updates atmospheric properties based on meteorological data interpolated between two time steps. It calculates various atmospheric quantities such as pressure, temperature, wind speed, humidity, etc., and updates the corresponding fields in the atmospheric data structure.

Parameters
ctlPointer to the control structure containing simulation parameters.
climPointer to the climate data structure containing climatological data.
met0Pointer to the meteorological data structure at the current time step.
met1Pointer to the meteorological data structure at the next time step.
atmPointer to the atmospheric data structure containing particle information.
dtArray of time step values for each particle.
Author
Lars Hoffmann

Definition at line 3166 of file mptrac.c.

3172 {
3173
3174 /* Set timer... */
3175 SELECT_TIMER("MODULE_METEO", "PHYSICS", NVTX_GPU);
3176
3177 /* Check quantity flags... */
3178 if (ctl->qnt_tsts >= 0)
3179 if (ctl->qnt_tice < 0 || ctl->qnt_tnat < 0)
3180 ERRMSG("Need T_ice and T_NAT to calculate T_STS!");
3181
3182 /* Loop over particles... */
3183 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,clim,met0,met1,atm,dt)") {
3184
3185 double ps, ts, zs, us, vs, lsm, sst, pbl, pt, pct, pcb, cl, plcl, plfc,
3186 pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot, o3,
3187 lwc, rwc, iwc, swc, cc, z, zt;
3188
3189 /* Interpolate meteo data... */
3191 INTPOL_TIME_ALL(atm->time[ip], atm->p[ip], atm->lon[ip], atm->lat[ip]);
3192
3193 /* Set quantities... */
3194 SET_ATM(qnt_ps, ps);
3195 SET_ATM(qnt_ts, ts);
3196 SET_ATM(qnt_zs, zs);
3197 SET_ATM(qnt_us, us);
3198 SET_ATM(qnt_vs, vs);
3199 SET_ATM(qnt_lsm, lsm);
3200 SET_ATM(qnt_sst, sst);
3201 SET_ATM(qnt_pbl, pbl);
3202 SET_ATM(qnt_pt, pt);
3203 SET_ATM(qnt_tt, tt);
3204 SET_ATM(qnt_zt, zt);
3205 SET_ATM(qnt_h2ot, h2ot);
3206 SET_ATM(qnt_zg, z);
3207 SET_ATM(qnt_p, atm->p[ip]);
3208 SET_ATM(qnt_t, t);
3209 SET_ATM(qnt_rho, RHO(atm->p[ip], t));
3210 SET_ATM(qnt_u, u);
3211 SET_ATM(qnt_v, v);
3212 SET_ATM(qnt_w, w);
3213 SET_ATM(qnt_h2o, h2o);
3214 SET_ATM(qnt_o3, o3);
3215 SET_ATM(qnt_lwc, lwc);
3216 SET_ATM(qnt_rwc, rwc);
3217 SET_ATM(qnt_iwc, iwc);
3218 SET_ATM(qnt_swc, swc);
3219 SET_ATM(qnt_cc, cc);
3220 SET_ATM(qnt_pct, pct);
3221 SET_ATM(qnt_pcb, pcb);
3222 SET_ATM(qnt_cl, cl);
3223 SET_ATM(qnt_plcl, plcl);
3224 SET_ATM(qnt_plfc, plfc);
3225 SET_ATM(qnt_pel, pel);
3226 SET_ATM(qnt_cape, cape);
3227 SET_ATM(qnt_cin, cin);
3228 SET_ATM(qnt_o3c, o3c);
3229 SET_ATM(qnt_hno3,
3230 clim_zm(&clim->hno3, atm->time[ip], atm->lat[ip], atm->p[ip]));
3231 SET_ATM(qnt_oh, clim_oh(ctl, clim, atm->time[ip],
3232 atm->lon[ip], atm->lat[ip], atm->p[ip]));
3233 SET_ATM(qnt_h2o2, clim_zm(&clim->h2o2, atm->time[ip],
3234 atm->lat[ip], atm->p[ip]));
3235 SET_ATM(qnt_ho2, clim_zm(&clim->ho2, atm->time[ip],
3236 atm->lat[ip], atm->p[ip]));
3237 SET_ATM(qnt_o1d, clim_zm(&clim->o1d, atm->time[ip],
3238 atm->lat[ip], atm->p[ip]));
3239 SET_ATM(qnt_vh, sqrt(u * u + v * v));
3240 SET_ATM(qnt_vz, -1e3 * H0 / atm->p[ip] * w);
3241 SET_ATM(qnt_psat, PSAT(t));
3242 SET_ATM(qnt_psice, PSICE(t));
3243 SET_ATM(qnt_pw, PW(atm->p[ip], h2o));
3244 SET_ATM(qnt_sh, SH(h2o));
3245 SET_ATM(qnt_rh, RH(atm->p[ip], t, h2o));
3246 SET_ATM(qnt_rhice, RHICE(atm->p[ip], t, h2o));
3247 SET_ATM(qnt_theta, THETA(atm->p[ip], t));
3248 SET_ATM(qnt_zeta, atm->q[ctl->qnt_zeta][ip]);
3249 SET_ATM(qnt_zeta_d, ZETA(ps, atm->p[ip], t));
3250 SET_ATM(qnt_tvirt, TVIRT(t, h2o));
3251 SET_ATM(qnt_lapse, lapse_rate(t, h2o));
3252 SET_ATM(qnt_pv, pv);
3253 SET_ATM(qnt_tdew, TDEW(atm->p[ip], h2o));
3254 SET_ATM(qnt_tice, TICE(atm->p[ip], h2o));
3255 SET_ATM(qnt_tnat,
3256 nat_temperature(atm->p[ip], h2o,
3257 clim_zm(&clim->hno3, atm->time[ip],
3258 atm->lat[ip], atm->p[ip])));
3259 SET_ATM(qnt_tsts,
3260 0.5 * (atm->q[ctl->qnt_tice][ip] + atm->q[ctl->qnt_tnat][ip]));
3261 }
3262}
double nat_temperature(const double p, const double h2o, const double hno3)
Calculates the nitric acid trihydrate (NAT) temperature.
Definition: mptrac.c:4123
double lapse_rate(const double t, const double h2o)
Calculates the moist adiabatic lapse rate in Kelvin per kilometer.
Definition: mptrac.c:1794
#define H0
Scale height [km].
Definition: mptrac.h:177
#define PSICE(t)
Compute saturation pressure over ice (WMO, 2018).
Definition: mptrac.h:1303
#define TICE(p, h2o)
Calculate frost point temperature (WMO, 2018).
Definition: mptrac.h:1585
#define RHICE(p, t, h2o)
Compute relative humidity over ice.
Definition: mptrac.h:1390
#define INTPOL_TIME_ALL(time, p, lon, lat)
Interpolate multiple meteorological variables in time.
Definition: mptrac.h:757
#define RH(p, t, h2o)
Compute relative humidity over water.
Definition: mptrac.h:1360
#define TDEW(p, h2o)
Calculate dew point temperature.
Definition: mptrac.h:1560
#define PSAT(t)
Compute saturation pressure over water.
Definition: mptrac.h:1279
clim_zm_t hno3
HNO3 zonal means.
Definition: mptrac.h:3249
int qnt_tnat
Quantity array index for T_NAT.
Definition: mptrac.h:2388
int qnt_tice
Quantity array index for T_ice.
Definition: mptrac.h:2382
int qnt_tsts
Quantity array index for T_STS.
Definition: mptrac.h:2385
Here is the call graph for this function:

◆ module_mixing()

void module_mixing ( ctl_t ctl,
clim_t clim,
atm_t atm,
double  t 
)

Update atmospheric properties through interparcel mixing.

This function updates atmospheric properties by performing interparcel mixing based on the given meteorological and climatological data. It calculates the indices of grid boxes and performs mixing for various quantities such as mass, volume mixing ratio, and other chemical species concentrations.

Parameters
ctlPointer to the control structure containing simulation parameters.
climPointer to the climate data structure containing climatological data.
atmPointer to the atmospheric data structure containing particle information.
tTime at which mixing is performed.
Authors
Mingzhao Liu
Lars Hoffmann

Definition at line 3266 of file mptrac.c.

3270 {
3271
3272 /* Set timer... */
3273 SELECT_TIMER("MODULE_MIXING", "PHYSICS", NVTX_GPU);
3274
3275 /* Allocate... */
3276 const int np = atm->np;
3277 int *restrict const ixs = (int *) malloc((size_t) np * sizeof(int));
3278 int *restrict const iys = (int *) malloc((size_t) np * sizeof(int));
3279 int *restrict const izs = (int *) malloc((size_t) np * sizeof(int));
3280
3281 /* Set grid box size... */
3282 const double dz = (ctl->mixing_z1 - ctl->mixing_z0) / ctl->mixing_nz;
3283 const double dlon = (ctl->mixing_lon1 - ctl->mixing_lon0) / ctl->mixing_nx;
3284 const double dlat = (ctl->mixing_lat1 - ctl->mixing_lat0) / ctl->mixing_ny;
3285
3286 /* Set time interval... */
3287 const double t0 = t - 0.5 * ctl->dt_mod;
3288 const double t1 = t + 0.5 * ctl->dt_mod;
3289
3290 /* Get indices... */
3291#ifdef _OPENACC
3292#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
3293#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
3294#pragma acc parallel loop independent gang vector
3295#else
3296#pragma omp parallel for default(shared)
3297#endif
3298 for (int ip = 0; ip < np; ip++) {
3299 ixs[ip] = (int) ((atm->lon[ip] - ctl->mixing_lon0) / dlon);
3300 iys[ip] = (int) ((atm->lat[ip] - ctl->mixing_lat0) / dlat);
3301 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->mixing_z0) / dz);
3302 if (atm->time[ip] < t0 || atm->time[ip] > t1
3303 || ixs[ip] < 0 || ixs[ip] >= ctl->mixing_nx
3304 || iys[ip] < 0 || iys[ip] >= ctl->mixing_ny
3305 || izs[ip] < 0 || izs[ip] >= ctl->mixing_nz)
3306 izs[ip] = -1;
3307 }
3308
3309 /* Calculate interparcel mixing... */
3310 if (ctl->qnt_m >= 0)
3311 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_m);
3312 if (ctl->qnt_vmr >= 0)
3313 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_vmr);
3314 if (ctl->qnt_Ch2o >= 0)
3315 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Ch2o);
3316 if (ctl->qnt_Co3 >= 0)
3317 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Co3);
3318 if (ctl->qnt_Cco >= 0)
3319 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cco);
3320 if (ctl->qnt_Coh >= 0)
3321 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Coh);
3322 if (ctl->qnt_Ch >= 0)
3323 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Ch);
3324 if (ctl->qnt_Cho2 >= 0)
3325 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cho2);
3326 if (ctl->qnt_Ch2o2 >= 0)
3327 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Ch2o2);
3328 if (ctl->qnt_Co1d >= 0)
3329 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Co1d);
3330 if (ctl->qnt_Co3p >= 0)
3331 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Co3p);
3332 if (ctl->qnt_Cccl4 >= 0)
3333 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cccl4);
3334 if (ctl->qnt_Cccl3f >= 0)
3335 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cccl3f);
3336 if (ctl->qnt_Cccl2f2 >= 0)
3337 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cccl2f2);
3338 if (ctl->qnt_Cn2o >= 0)
3339 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cn2o);
3340 if (ctl->qnt_Csf6 >= 0)
3341 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Csf6);
3342 if (ctl->qnt_aoa >= 0)
3343 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_aoa);
3344
3345 /* Free... */
3346#ifdef _OPENACC
3347#pragma acc exit data delete(ixs,iys,izs)
3348#endif
3349 free(ixs);
3350 free(iys);
3351 free(izs);
3352}
void module_mixing_help(ctl_t *ctl, clim_t *clim, atm_t *atm, const int *ixs, const int *iys, const int *izs, int qnt_idx)
Perform interparcel mixing for a specific quantity.
Definition: mptrac.c:3356
int qnt_Coh
Quantity array index for OH volume mixing ratio (chemistry code).
Definition: mptrac.h:2403
int mixing_nx
Number of longitudes of mixing grid.
Definition: mptrac.h:2738
double mixing_z1
Upper altitude of mixing grid [km].
Definition: mptrac.h:2735
int qnt_Co1d
Quantity array index for O(1D) volume mixing ratio (chemistry code).
Definition: mptrac.h:2415
double mixing_z0
Lower altitude of mixing grid [km].
Definition: mptrac.h:2732
int qnt_Cco
Quantity array index for CO volume mixing ratio (chemistry code).
Definition: mptrac.h:2400
int mixing_ny
Number of latitudes of mixing grid.
Definition: mptrac.h:2747
int qnt_Ch
Quantity array index for H volume mixing ratio (chemistry code).
Definition: mptrac.h:2406
double mixing_lat0
Lower latitude of mixing grid [deg].
Definition: mptrac.h:2750
int qnt_Cho2
Quantity array index for HO2 volume mixing ratio (chemistry code).
Definition: mptrac.h:2409
int mixing_nz
Number of altitudes of mixing grid.
Definition: mptrac.h:2729
double mixing_lon0
Lower longitude of mixing grid [deg].
Definition: mptrac.h:2741
double mixing_lat1
Upper latitude of mixing grid [deg].
Definition: mptrac.h:2753
int qnt_Co3p
Quantity array index for O(3P) volume mixing ratio (chemistry code).
Definition: mptrac.h:2418
int qnt_Ch2o2
Quantity array index for H2O2 volume mixing ratio (chemistry code).
Definition: mptrac.h:2412
double mixing_lon1
Upper longitude of mixing grid [deg].
Definition: mptrac.h:2744
Here is the call graph for this function:

◆ module_mixing_help()

void module_mixing_help ( ctl_t ctl,
clim_t clim,
atm_t atm,
const int *  ixs,
const int *  iys,
const int *  izs,
int  qnt_idx 
)

Perform interparcel mixing for a specific quantity.

This function performs interparcel mixing for a specific quantity based on the given indices of grid boxes. It calculates the mean concentration within each grid box and adjusts the quantity for each particle accordingly.

Parameters
ctlPointer to the control structure containing simulation parameters.
climPointer to the climate data structure containing climatological data.
atmPointer to the atmospheric data structure containing particle information.
ixsPointer to the array of grid box indices along the longitude direction.
iysPointer to the array of grid box indices along the latitude direction.
izsPointer to the array of grid box indices along the vertical direction.
qnt_idxIndex of the quantity for which mixing is performed.
Authors
Mingzhao Liu
Lars Hoffmann

Definition at line 3356 of file mptrac.c.

3363 {
3364
3365 /* Allocate... */
3366 const int np = atm->np;
3367 const int ngrid = ctl->mixing_nx * ctl->mixing_ny * ctl->mixing_nz;
3368 double *restrict const cmean =
3369 (double *) malloc((size_t) ngrid * sizeof(double));
3370 int *restrict const count = (int *) malloc((size_t) ngrid * sizeof(int));
3371
3372 /* Init... */
3373#ifdef _OPENACC
3374#pragma acc enter data create(cmean[0:ngrid],count[0:ngrid])
3375#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
3376#pragma acc parallel loop independent gang vector
3377#else
3378#ifdef __NVCOMPILER
3379#pragma novector
3380#endif
3381#pragma omp parallel for
3382#endif
3383 for (int i = 0; i < ngrid; i++) {
3384 count[i] = 0;
3385 cmean[i] = 0;
3386 }
3387
3388 /* Loop over particles... */
3389#ifdef _OPENACC
3390#pragma acc parallel loop independent gang vector
3391#endif
3392 for (int ip = 0; ip < np; ip++)
3393 if (izs[ip] >= 0) {
3394 int idx = ARRAY_3D
3395 (ixs[ip], iys[ip], ctl->mixing_ny, izs[ip], ctl->mixing_nz);
3396#ifdef _OPENACC
3397#pragma acc atomic update
3398#endif
3399 cmean[idx] += atm->q[qnt_idx][ip];
3400#ifdef _OPENACC
3401#pragma acc atomic update
3402#endif
3403 count[idx]++;
3404 }
3405#ifdef _OPENACC
3406#pragma acc parallel loop independent gang vector
3407#else
3408#ifdef __NVCOMPILER
3409#pragma novector
3410#endif
3411#pragma omp parallel for
3412#endif
3413 for (int i = 0; i < ngrid; i++)
3414 if (count[i] > 0)
3415 cmean[i] /= count[i];
3416
3417 /* Calculate interparcel mixing... */
3418#ifdef _OPENACC
3419#pragma acc parallel loop independent gang vector
3420#else
3421#pragma omp parallel for
3422#endif
3423 for (int ip = 0; ip < np; ip++)
3424 if (izs[ip] >= 0) {
3425
3426 /* Set mixing parameter... */
3427 double mixparam = 1.0;
3428 if (ctl->mixing_trop < 1 || ctl->mixing_strat < 1) {
3429 double w =
3430 tropo_weight(clim, atm->time[ip], atm->lat[ip], atm->p[ip]);
3431 mixparam = w * ctl->mixing_trop + (1 - w) * ctl->mixing_strat;
3432 }
3433
3434 /* Adjust quantity... */
3435 atm->q[qnt_idx][ip] +=
3436 (cmean
3437 [ARRAY_3D(ixs[ip], iys[ip], ctl->mixing_ny, izs[ip], ctl->mixing_nz)]
3438 - atm->q[qnt_idx][ip]) * mixparam;
3439 }
3440
3441 /* Free... */
3442#ifdef _OPENACC
3443#pragma acc exit data delete(cmean,count)
3444#endif
3445 free(cmean);
3446 free(count);
3447}
double mixing_trop
Interparcel exchange parameter for mixing in the troposphere.
Definition: mptrac.h:2723
double mixing_strat
Interparcel exchange parameter for mixing in the stratosphere.
Definition: mptrac.h:2726
Here is the call graph for this function:

◆ module_oh_chem()

void module_oh_chem ( ctl_t ctl,
clim_t clim,
met_t met0,
met_t met1,
atm_t atm,
double *  dt 
)

Perform hydroxyl chemistry calculations for atmospheric particles.

This function calculates the OH chemistry for each atmospheric particle based on the specified reaction mechanism and updates the particle quantities accordingly. The OH chemistry includes bimolecular and termolecular reactions, and the reaction rates are calculated based on the provided climatological data and atmospheric conditions. The function supports both mass and volume mixing ratio quantities for the particles.

Parameters
ctlPointer to the control structure containing simulation parameters.
climPointer to the climate data structure containing climatological data.
met0Pointer to the first meteorological data structure.
met1Pointer to the second meteorological data structure.
atmPointer to the atmospheric data structure containing particle information.
dtArray of time steps for each particle.
Note
The function assumes that the necessary meteorological and climatological data structures have been initialized and are accessible via the pointers met0, met1, and clim, respectively.
The reaction rates are calculated based on the provided reaction mechanism and atmospheric conditions, including temperature, pressure, and the concentrations of relevant species.
The function updates the particle quantities based on the calculated reaction rates and the specified time steps. The update can include both mass and volume mixing ratio quantities, as determined by the control structure (ctl).
Authors
Lars Hoffmann
Mingzhao Liu

Definition at line 3451 of file mptrac.c.

3457 {
3458
3459 /* Set timer... */
3460 SELECT_TIMER("MODULE_OHCHEM", "PHYSICS", NVTX_GPU);
3461
3462 /* Check quantity flags... */
3463 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
3464 ERRMSG("Module needs quantity mass or volume mixing ratio!");
3465
3466 /* Parameter of SO2 correction... */
3467 const double a = 4.71572206e-08;
3468 const double b = -8.28782867e-01;
3469 const double low = pow(1 / a, 1 / b);
3470
3471 /* Loop over particles... */
3472 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,clim,met0,met1,atm,dt)") {
3473
3474 /* Get temperature... */
3475 double t;
3477 INTPOL_3D(t, 1);
3478
3479 /* Calculate molecular density... */
3480 double M = MOLEC_DENS(atm->p[ip], t);
3481
3482 /* Use constant reaction rate... */
3483 double k = NAN;
3484 if (ctl->oh_chem_reaction == 1)
3485 k = ctl->oh_chem[0];
3486
3487 /* Calculate bimolecular reaction rate... */
3488 else if (ctl->oh_chem_reaction == 2)
3489 k = ctl->oh_chem[0] * exp(-ctl->oh_chem[1] / t);
3490
3491 /* Calculate termolecular reaction rate... */
3492 if (ctl->oh_chem_reaction == 3) {
3493
3494 /* Calculate rate coefficient for X + OH + M -> XOH + M
3495 (JPL Publication 19-05) ... */
3496 double k0 =
3497 ctl->oh_chem[0] * (ctl->oh_chem[1] !=
3498 0 ? pow(298. / t, ctl->oh_chem[1]) : 1.);
3499 double ki =
3500 ctl->oh_chem[2] * (ctl->oh_chem[3] !=
3501 0 ? pow(298. / t, ctl->oh_chem[3]) : 1.);
3502 double c = log10(k0 * M / ki);
3503 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
3504 }
3505
3506 /* Correction factor for high SO2 concentration
3507 (if qnt_Cx is defined, the correction is switched on)... */
3508 double cor = 1;
3509 if (ctl->qnt_Cx >= 0)
3510 cor =
3511 atm->q[ctl->qnt_Cx][ip] >
3512 low ? a * pow(atm->q[ctl->qnt_Cx][ip], b) : 1;
3513
3514 /* Calculate exponential decay... */
3515 double rate_coef = k * clim_oh(ctl, clim, atm->time[ip], atm->lon[ip],
3516 atm->lat[ip], atm->p[ip]) * M * cor;
3517 double aux = exp(-dt[ip] * rate_coef);
3518 if (ctl->qnt_m >= 0) {
3519 if (ctl->qnt_mloss_oh >= 0)
3520 atm->q[ctl->qnt_mloss_oh][ip]
3521 += atm->q[ctl->qnt_m][ip] * (1 - aux);
3522 atm->q[ctl->qnt_m][ip] *= aux;
3523 if (ctl->qnt_loss_rate >= 0)
3524 atm->q[ctl->qnt_loss_rate][ip] += rate_coef;
3525 }
3526 if (ctl->qnt_vmr >= 0)
3527 atm->q[ctl->qnt_vmr][ip] *= aux;
3528 }
3529}
double oh_chem[4]
Coefficients for OH reaction rate (A, E/R or k0, n, kinf, m).
Definition: mptrac.h:2786
int oh_chem_reaction
Reaction type for OH chemistry (0=none, 2=bimolecular, 3=termolecular).
Definition: mptrac.h:2783
int qnt_mloss_oh
Quantity array index for total mass loss due to OH chemistry.
Definition: mptrac.h:2316
Here is the call graph for this function:

◆ module_position()

void module_position ( ctl_t ctl,
met_t met0,
met_t met1,
atm_t atm,
double *  dt 
)

Update the positions and pressure levels of atmospheric particles.

This function updates the positions and pressure levels of atmospheric particles based on the meteorological data and the specified time step. It loops over each particle in the atmospheric data structure and performs the following operations:

  • Initializes variables required for interpolation.
  • Calculates modulo for longitude and latitude to ensure they remain within valid ranges.
  • Adjusts latitude if it exceeds the range [-90, 90] degrees.
  • Adjusts longitude if it exceeds the range [-180, 180] degrees.
  • Checks and adjusts pressure levels:
    • Reflects pressure levels if they are below the minimum pressure in meteorological data.
    • Clamps pressure levels to the maximum pressure in meteorological data if they exceed a predefined threshold (300 hPa).
Parameters
ctlPointer to the control structure containing simulation parameters.
met0Pointer to the first meteorological data structure.
met1Pointer to the second meteorological data structure.
atmPointer to the atmospheric data structure containing particle information.
dtPointer to an array containing the time step for each particle.
Note
The function initializes a timer to measure the execution time of the position update process.
Position and pressure updates are performed for each particle using linear interpolation.
Longitude and latitude are adjusted to ensure they remain within valid ranges.
Pressure levels are adjusted based on meteorological data and a predefined threshold.
Author
Lars Hoffmann

Definition at line 3533 of file mptrac.c.

3538 {
3539
3540 /* Set timer... */
3541 SELECT_TIMER("MODULE_POSITION", "PHYSICS", NVTX_GPU);
3542
3543 /* Loop over particles... */
3544 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,met0,met1,atm,dt)") {
3545
3546 /* Init... */
3547 double ps;
3549
3550 /* Calculate modulo... */
3551 atm->lon[ip] = FMOD(atm->lon[ip], 360.);
3552 atm->lat[ip] = FMOD(atm->lat[ip], 360.);
3553
3554 /* Check latitude... */
3555 while (atm->lat[ip] < -90 || atm->lat[ip] > 90) {
3556 if (atm->lat[ip] > 90) {
3557 atm->lat[ip] = 180 - atm->lat[ip];
3558 atm->lon[ip] += 180;
3559 }
3560 if (atm->lat[ip] < -90) {
3561 atm->lat[ip] = -180 - atm->lat[ip];
3562 atm->lon[ip] += 180;
3563 }
3564 }
3565
3566 /* Check longitude... */
3567 while (atm->lon[ip] < -180)
3568 atm->lon[ip] += 360;
3569 while (atm->lon[ip] >= 180)
3570 atm->lon[ip] -= 360;
3571
3572 /* Check pressure... */
3573 if (atm->p[ip] < met0->p[met0->np - 1]) {
3574 if (ctl->reflect)
3575 atm->p[ip] = 2. * met0->p[met0->np - 1] - atm->p[ip];
3576 else
3577 atm->p[ip] = met0->p[met0->np - 1];
3578 } else if (atm->p[ip] > 300.) {
3579 INTPOL_2D(ps, 1);
3580 if (atm->p[ip] > ps) {
3581 if (ctl->reflect)
3582 atm->p[ip] = 2. * ps - atm->p[ip];
3583 else
3584 atm->p[ip] = ps;
3585 }
3586 }
3587 }
3588}
int reflect
Reflection of particles at top and bottom boundary (0=no, 1=yes).
Definition: mptrac.h:2597

◆ module_rng_init()

void module_rng_init ( int  ntask)

Initialize random number generators for parallel tasks.

This function initializes random number generators for parallel tasks using both GSL (GNU Scientific Library) and cuRAND (NVIDIA CUDA Random Number Generation Library) if available. It sets up GSL random number generators for each OpenMP thread and initializes them with unique seeds. For cuRAND, it creates a pseudo-random number generator and sets its seed. The initialization ensures that each task or thread has its own independent random number generator to prevent interference between parallel executions.

Parameters
ntaskThe number of tasks or parallel threads for which random number generators are initialized.
Note
This function must be called before using any random number generation functions to ensure proper initialization of random number generators.
GSL random number generators are initialized for each OpenMP thread, while cuRAND is initialized for the entire task set.
If cuRAND is not available (CURAND macro not defined), the cuRAND initialization section is skipped.
Random number generators are allocated and seeded uniquely for each task or thread to ensure independence and avoid interference between parallel executions.
Author
Lars Hoffmann

Definition at line 3592 of file mptrac.c.

3593 {
3594
3595 /* Initialize GSL random number generators... */
3596 gsl_rng_env_setup();
3597 if (omp_get_max_threads() > NTHREADS)
3598 ERRMSG("Too many threads!");
3599 for (int i = 0; i < NTHREADS; i++) {
3600 rng[i] = gsl_rng_alloc(gsl_rng_default);
3601 gsl_rng_set(rng[i], gsl_rng_default_seed
3602 + (long unsigned) (ntask * NTHREADS + i));
3603 }
3604
3605 /* Initialize cuRAND random number generators... */
3606#ifdef CURAND
3607 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
3608 CURAND_STATUS_SUCCESS)
3609 ERRMSG("Cannot create random number generator!");
3610 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
3611 CURAND_STATUS_SUCCESS)
3612 ERRMSG("Cannot set seed for random number generator!");
3613 if (curandSetStream
3614 (rng_curand,
3615 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
3616 CURAND_STATUS_SUCCESS)
3617 ERRMSG("Cannot set stream for random number generator!");
3618#endif
3619}
#define NTHREADS
Maximum number of OpenMP threads.
Definition: mptrac.h:281

◆ module_rng()

void module_rng ( ctl_t ctl,
double *  rs,
size_t  n,
int  method 
)

Generate random numbers using various methods and distributions.

This function generates random numbers using different methods and distributions based on the specified method and random number generator type. It supports uniform and normal distributions and can utilize GSL, Squares (Widynski, 2022), or cuRAND random number generators.

Parameters
ctlPointer to the control structure containing parameters and settings.
rsPointer to the array where the generated random numbers will be stored.
nThe number of random numbers to generate.
methodThe method for generating random numbers:
  • 0: Uniform distribution
  • 1: Normal distribution
Note
The function selects the appropriate random number generator based on the specified method and the random number generator type defined in the control structure (ctl->rng_type).
For uniform distribution, the generated random numbers are in the range [0, 1).
For normal distribution, the Box-Muller transform is used to generate pairs of random numbers and transform them into a normal distribution.
If cuRAND is not available (CURAND macro not defined), the function returns an error message.
Author
Lars Hoffmann

Definition at line 3623 of file mptrac.c.

3627 {
3628
3629 /* Use GSL random number generators... */
3630 if (ctl->rng_type == 0) {
3631
3632 /* Uniform distribution... */
3633 if (method == 0) {
3634#pragma omp parallel for default(shared)
3635 for (size_t i = 0; i < n; ++i)
3636 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
3637 }
3638
3639 /* Normal distribution... */
3640 else if (method == 1) {
3641#pragma omp parallel for default(shared)
3642 for (size_t i = 0; i < n; ++i)
3643 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
3644 }
3645
3646 /* Update of random numbers on device... */
3647#ifdef _OPENACC
3648#pragma acc update device(rs[:n])
3649#endif
3650 }
3651
3652 /* Use Squares random number generator (Widynski, 2022)... */
3653 else if (ctl->rng_type == 1) {
3654
3655 /* Set key (don't change this!)... */
3656 const uint64_t key = 0xc8e4fd154ce32f6d;
3657
3658 /* Uniform distribution... */
3659#ifdef _OPENACC
3660#pragma acc data present(rs)
3661#pragma acc parallel loop independent gang vector
3662#else
3663#pragma omp parallel for default(shared)
3664#endif
3665 for (size_t i = 0; i < n + 1; ++i) {
3666 uint64_t r, t, x, y, z;
3667 y = x = (rng_ctr + i) * key;
3668 z = y + key;
3669 x = x * x + y;
3670 x = (x >> 32) | (x << 32);
3671 x = x * x + z;
3672 x = (x >> 32) | (x << 32);
3673 x = x * x + y;
3674 x = (x >> 32) | (x << 32);
3675 t = x = x * x + z;
3676 x = (x >> 32) | (x << 32);
3677 r = t ^ ((x * x + y) >> 32);
3678 rs[i] = (double) r / (double) UINT64_MAX;
3679 }
3680 rng_ctr += n + 1;
3681
3682 /* Normal distribution... */
3683 if (method == 1) {
3684#ifdef _OPENACC
3685#pragma acc parallel loop independent gang vector
3686#else
3687#pragma omp parallel for default(shared)
3688#endif
3689 for (size_t i = 0; i < n; i += 2) {
3690 double r = sqrt(-2.0 * log(rs[i]));
3691 double phi = 2.0 * M_PI * rs[i + 1];
3692 rs[i] = r * cosf((float) phi);
3693 rs[i + 1] = r * sinf((float) phi);
3694 }
3695 }
3696 }
3697
3698 /* Use cuRAND random number generators... */
3699 else if (ctl->rng_type == 2) {
3700#ifdef CURAND
3701#pragma acc host_data use_device(rs)
3702 {
3703
3704 /* Uniform distribution... */
3705 if (method == 0) {
3706 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
3707 CURAND_STATUS_SUCCESS)
3708 ERRMSG("Cannot create random numbers!");
3709 }
3710
3711 /* Normal distribution... */
3712 else if (method == 1) {
3713 if (curandGenerateNormalDouble
3714 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
3715 1.0) != CURAND_STATUS_SUCCESS)
3716 ERRMSG("Cannot create random numbers!");
3717 }
3718 }
3719#else
3720 ERRMSG("MPTRAC was compiled without cuRAND!");
3721#endif
3722 }
3723}
int rng_type
Random number generator (0=GSL, 1=Squares, 2=cuRAND).
Definition: mptrac.h:2600

◆ module_sedi()

void module_sedi ( ctl_t ctl,
met_t met0,
met_t met1,
atm_t atm,
double *  dt 
)

Simulate sedimentation of particles in the atmosphere.

This function calculates the sedimentation velocity of particles based on atmospheric pressure, temperature, and particle properties such as radius and density. It then updates the pressure of each particle based on the sedimentation velocity and the specified time step.

Parameters
ctlPointer to the control structure containing parameters and settings.
met0Pointer to the meteorological data at the current time step.
met1Pointer to the meteorological data at the next time step.
atmPointer to the atmospheric data containing particle information.
dtPointer to the array of time steps for each particle.
Note
The sedimentation velocity is calculated using the sedi function, which takes atmospheric pressure, temperature, particle radius, and particle density as inputs.
The pressure change for each particle is calculated based on the sedimentation velocity and the specified time step using the DZ2DP function.
Author
Lars Hoffmann

Definition at line 3727 of file mptrac.c.

3732 {
3733
3734 /* Set timer... */
3735 SELECT_TIMER("MODULE_SEDI", "PHYSICS", NVTX_GPU);
3736
3737 /* Loop over particles... */
3738 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,met0,met1,atm,dt)") {
3739
3740 /* Get temperature... */
3741 double t;
3743 INTPOL_3D(t, 1);
3744
3745 /* Sedimentation velocity... */
3746 double v_s = sedi(atm->p[ip], t, atm->q[ctl->qnt_rp][ip],
3747 atm->q[ctl->qnt_rhop][ip]);
3748
3749 /* Calculate pressure change... */
3750 atm->p[ip] += DZ2DP(v_s * dt[ip] / 1000., atm->p[ip]);
3751 }
3752}
Here is the call graph for this function:

◆ module_sort()

void module_sort ( ctl_t ctl,
met_t met0,
atm_t atm 
)

Sort particles according to box index.

This function sorts particles within the atmosphere data structure based on their geographical coordinates (longitude and latitude) and pressure level. It allocates temporary arrays to store indices and auxiliary data for sorting, then performs the sorting operation. After sorting, it updates the order of particles in the atmosphere data structure.

Parameters
ctlPointer to the control structure containing parameters and settings.
met0Pointer to the meteorological data at the current time step.
atmPointer to the atmospheric data containing particle information.
Note
The function utilizes the locate_reg and locate_irr functions to determine the appropriate index for sorting particles based on their longitude, latitude, and pressure level.
Particle sorting is performed using either the Thrust library (if compiled with Thrust support) or a custom sorting algorithm. If compiled without Thrust support, an error message is displayed.
After sorting, the function updates the order of particle-related data arrays in the atmosphere data structure to maintain consistency.
Author
Lars Hoffmann

Definition at line 3756 of file mptrac.c.

3759 {
3760
3761 /* Set timer... */
3762 SELECT_TIMER("MODULE_SORT", "PHYSICS", NVTX_GPU);
3763
3764 /* Allocate... */
3765 const int np = atm->np;
3766 double *restrict const a = (double *) malloc((size_t) np * sizeof(double));
3767 int *restrict const p = (int *) malloc((size_t) np * sizeof(int));
3768
3769#ifdef _OPENACC
3770#pragma acc enter data create(a[0:np],p[0:np])
3771#pragma acc data present(ctl,met0,atm,a,p)
3772#endif
3773
3774 /* Get box index... */
3775#ifdef _OPENACC
3776#pragma acc parallel loop independent gang vector
3777#else
3778#pragma omp parallel for default(shared)
3779#endif
3780 for (int ip = 0; ip < np; ip++) {
3781 a[ip] =
3782 (double) ((locate_reg(met0->lon, met0->nx, atm->lon[ip]) * met0->ny +
3783 locate_reg(met0->lat, met0->ny, atm->lat[ip]))
3784 * met0->np + locate_irr(met0->p, met0->np, atm->p[ip]));
3785 p[ip] = ip;
3786 }
3787
3788 /* Sorting... */
3789#ifdef _OPENACC
3790#pragma acc host_data use_device(a, p)
3791#endif
3792#ifdef THRUST
3793 thrustSortWrapper(a, np, p);
3794#else
3795 ERRMSG("MPTRAC was compiled without Thrust library!");
3796#endif
3797
3798 /* Sort data... */
3799 module_sort_help(atm->time, p, np);
3800 module_sort_help(atm->p, p, np);
3801 module_sort_help(atm->lon, p, np);
3802 module_sort_help(atm->lat, p, np);
3803 for (int iq = 0; iq < ctl->nq; iq++)
3804 module_sort_help(atm->q[iq], p, np);
3805
3806 /* Free... */
3807#ifdef _OPENACC
3808#pragma acc exit data delete(a,p)
3809#endif
3810 free(a);
3811 free(p);
3812}
void module_sort_help(double *a, const int *p, const int np)
Reorder an array based on a given permutation.
Definition: mptrac.c:3816
void thrustSortWrapper(double *__restrict__ c, int n, int *__restrict__ index)
Wrapper to Thrust sorting function.
int nq
Number of quantities.
Definition: mptrac.h:2160
Here is the call graph for this function:

◆ module_sort_help()

void module_sort_help ( double *  a,
const int *  p,
const int  np 
)

Reorder an array based on a given permutation.

This function reorders the elements of a given array based on a specified permutation array. It allocates temporary memory to store the reordered elements, performs the reordering operation, and then updates the original array with the reordered elements.

Parameters
aPointer to the array to be reordered.
pPointer to the permutation array defining the order of elements.
npThe number of elements in the array.
Note
The function utilizes temporary memory to store the reordered elements before updating the original array to prevent data loss or corruption.
Reordering is performed based on the permutation array p, which defines the new order of elements in the array a.
Author
Lars Hoffmann

Definition at line 3816 of file mptrac.c.

3819 {
3820
3821 /* Allocate... */
3822 double *restrict const help =
3823 (double *) malloc((size_t) np * sizeof(double));
3824
3825 /* Reordering of array... */
3826#ifdef _OPENACC
3827#pragma acc enter data create(help[0:np])
3828#pragma acc data present(a,p,help)
3829#pragma acc parallel loop independent gang vector
3830#else
3831#pragma omp parallel for default(shared)
3832#endif
3833 for (int ip = 0; ip < np; ip++)
3834 help[ip] = a[p[ip]];
3835#ifdef _OPENACC
3836#pragma acc parallel loop independent gang vector
3837#else
3838#pragma omp parallel for default(shared)
3839#endif
3840 for (int ip = 0; ip < np; ip++)
3841 a[ip] = help[ip];
3842
3843 /* Free... */
3844#ifdef _OPENACC
3845#pragma acc exit data delete(help)
3846#endif
3847 free(help);
3848}

◆ module_timesteps()

void module_timesteps ( ctl_t ctl,
met_t met0,
atm_t atm,
double *  dt,
double  t 
)

Calculate time steps for air parcels based on specified conditions.

This function calculates the time steps for air parcels based on specified conditions, including the direction of simulation, start and stop times, and a given target time. It adjusts the time step for each air parcel accordingly and checks for horizontal boundary conditions of local meteorological data.

Parameters
ctlPointer to the control structure containing simulation parameters.
met0Pointer to the initial meteorological data structure.
atmPointer to the atmospheric data structure containing air parcel information.
dtPointer to the array storing the calculated time steps for air parcels.
tThe target time for which time steps are calculated.
Note
The function sets the time step for each air parcel based on its current time relative to the start and stop times of the simulation, as well as the specified target time t.
It also checks for horizontal boundaries of local meteorological data and adjusts the time step accordingly if necessary.
Author
Lars Hoffmann

Definition at line 3852 of file mptrac.c.

3857 {
3858
3859 /* Set timer... */
3860 SELECT_TIMER("MODULE_TIMESTEPS", "PHYSICS", NVTX_GPU);
3861
3862 const double latmin = gsl_stats_min(met0->lat, 1, (size_t) met0->ny),
3863 latmax = gsl_stats_max(met0->lat, 1, (size_t) met0->ny);
3864
3865 const int local =
3866 (fabs(met0->lon[met0->nx - 1] - met0->lon[0] - 360.0) >= 0.01);
3867
3868 /* Loop over particles... */
3869 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,atm,met0,dt)") {
3870
3871 /* Set time step for each air parcel... */
3872 if ((ctl->direction * (atm->time[ip] - ctl->t_start) >= 0
3873 && ctl->direction * (atm->time[ip] - ctl->t_stop) <= 0
3874 && ctl->direction * (atm->time[ip] - t) < 0))
3875 dt[ip] = t - atm->time[ip];
3876 else
3877 dt[ip] = 0.0;
3878
3879 /* Check horizontal boundaries of local meteo data... */
3880 if (local && (atm->lon[ip] <= met0->lon[0]
3881 || atm->lon[ip] >= met0->lon[met0->nx - 1]
3882 || atm->lat[ip] <= latmin || atm->lat[ip] >= latmax))
3883 dt[ip] = 0.0;
3884 }
3885}

◆ module_timesteps_init()

void module_timesteps_init ( ctl_t ctl,
atm_t atm 
)

Initialize start time and time interval for time-stepping.

This function initializes the start time and time interval for time-stepping based on the direction of simulation and the provided atmospheric data. It sets the start time according to the minimum or maximum time in the atmospheric data, depending on the simulation direction. Additionally, it checks the time interval and adjusts the start time accordingly for rounding purposes.

Parameters
ctlPointer to the control structure containing simulation parameters.
atmPointer to the atmospheric data structure containing air parcel information.
Note
The function sets the start time based on the direction of simulation and the minimum or maximum time in the atmospheric data.
It checks the time interval to ensure that there is a valid time range for simulation and adjusts the start time for rounding purposes.
Author
Lars Hoffmann

Definition at line 3889 of file mptrac.c.

3891 {
3892
3893 /* Set timer... */
3894 SELECT_TIMER("MODULE_TIMESTEPS", "PHYSICS", NVTX_GPU);
3895
3896 /* Set start time... */
3897 if (ctl->direction == 1) {
3898 ctl->t_start = gsl_stats_min(atm->time, 1, (size_t) atm->np);
3899 if (ctl->t_stop > 1e99)
3900 ctl->t_stop = gsl_stats_max(atm->time, 1, (size_t) atm->np);
3901 } else {
3902 ctl->t_start = gsl_stats_max(atm->time, 1, (size_t) atm->np);
3903 if (ctl->t_stop > 1e99)
3904 ctl->t_stop = gsl_stats_min(atm->time, 1, (size_t) atm->np);
3905 }
3906
3907 /* Check time interval... */
3908 if (ctl->direction * (ctl->t_stop - ctl->t_start) <= 0)
3909 ERRMSG("Nothing to do! Check T_STOP and DIRECTION!");
3910
3911 /* Round start time... */
3912 if (ctl->direction == 1)
3913 ctl->t_start = floor(ctl->t_start / ctl->dt_mod) * ctl->dt_mod;
3914 else
3915 ctl->t_start = ceil(ctl->t_start / ctl->dt_mod) * ctl->dt_mod;
3916}

◆ module_tracer_chem()

void module_tracer_chem ( ctl_t ctl,
clim_t clim,
met_t met0,
met_t met1,
atm_t atm,
double *  dt 
)

Simulate chemical reactions involving long-lived atmospheric tracers.

This function simulates chemical reactions involving atmospheric tracers, such as CFC-10, CFC-11, CFC-12, and N2O. It calculates the change in tracer concentrations over time based on reaction rates and environmental factors such as temperature, ozone concentration, solar zenith angle, and O(1D) volume mixing ratio.

Parameters
ctlPointer to the control structure containing simulation parameters.
climPointer to the climatological data structure.
met0Pointer to the first meteorological data structure.
met1Pointer to the second meteorological data structure.
atmPointer to the atmospheric data structure containing particle information.
dtPointer to an array containing the time step for each particle.
Note
The function assumes that the necessary control structure (ctl), climatological data structure (clim), meteorological data structures (met0, met1), and atmospheric data structure (atm) have been initialized and are accessible.
Chemical reactions involving CFC-10, CFC-11, CFC-12, and N2O are simulated for each particle in the atmospheric data structure.
The function calculates reaction rates based on temperature, solar zenith angle, total column ozone, and the volume mixing ratio of O(1D).
The exponential decay of tracer concentrations due to chemical reactions is calculated using reaction rate coefficients and the time step (dt) for each particle.
If the particle has a quantity flag for the tracer species (e.g., ctl->qnt_Cccl4, ctl->qnt_Cccl3f, ctl->qnt_Cccl2f2, ctl->qnt_Cn2o), the function updates the concentration of the tracer based on the exponential decay.
Authors
Mingzhao Liu
Lars Hoffmann

Definition at line 3920 of file mptrac.c.

3926 {
3927
3928 /* Set timer... */
3929 SELECT_TIMER("MODULE_TRACERCHEM", "PHYSICS", NVTX_GPU);
3930
3931 /* Loop over particles... */
3932 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,clim,met0,atm,met1,dt)") {
3933
3934 /* Get temperature... */
3935 double t;
3937 INTPOL_3D(t, 1);
3938
3939 /* Get molecular density... */
3940 double M = MOLEC_DENS(atm->p[ip], t);
3941
3942 /* Get total column ozone... */
3943 double o3c;
3944 INTPOL_2D(o3c, 1);
3945
3946 /* Get solar zenith angle... */
3947 double sza = sza_calc(atm->time[ip], atm->lon[ip], atm->lat[ip]);
3948
3949 /* Get O(1D) volume mixing ratio... */
3950 double o1d = clim_zm(&clim->o1d, atm->time[ip], atm->lat[ip], atm->p[ip]);
3951
3952 /* Reactions for CFC-10... */
3953 if (ctl->qnt_Cccl4 >= 0) {
3954 double K_o1d = ARRHENIUS(3.30e-10, 0, t) * o1d * M;
3955 double K_hv = clim_photo(clim->photo.ccl4, &(clim->photo),
3956 atm->p[ip], sza, o3c);
3957 atm->q[ctl->qnt_Cccl4][ip] *= exp(-dt[ip] * (K_hv + K_o1d));
3958 }
3959
3960 /* Reactions for CFC-11... */
3961 if (ctl->qnt_Cccl3f >= 0) {
3962 double K_o1d = ARRHENIUS(2.30e-10, 0, t) * o1d * M;
3963 double K_hv = clim_photo(clim->photo.ccl3f, &(clim->photo),
3964 atm->p[ip], sza, o3c);
3965 atm->q[ctl->qnt_Cccl3f][ip] *= exp(-dt[ip] * (K_hv + K_o1d));
3966 }
3967
3968 /* Reactions for CFC-12... */
3969 if (ctl->qnt_Cccl2f2 >= 0) {
3970 double K_o1d = ARRHENIUS(1.40e-10, -25, t) * o1d * M;
3971 double K_hv = clim_photo(clim->photo.ccl2f2, &(clim->photo),
3972 atm->p[ip], sza, o3c);
3973 atm->q[ctl->qnt_Cccl2f2][ip] *= exp(-dt[ip] * (K_hv + K_o1d));
3974 }
3975
3976 /* Reactions for N2O... */
3977 if (ctl->qnt_Cn2o >= 0) {
3978 double K_o1d = ARRHENIUS(1.19e-10, -20, t) * o1d * M;
3979 double K_hv = clim_photo(clim->photo.n2o, &(clim->photo),
3980 atm->p[ip], sza, o3c);
3981 atm->q[ctl->qnt_Cn2o][ip] *= exp(-dt[ip] * (K_hv + K_o1d));
3982 }
3983 }
3984}
double clim_photo(double rate[CP][CSZA][CO3], clim_photo_t *photo, double p, double sza, double o3c)
Calculates the photolysis rate for a given set of atmospheric conditions.
Definition: mptrac.c:142
#define ARRHENIUS(a, b, t)
Calculate the Arrhenius rate constant.
Definition: mptrac.h:411
double ccl2f2[CP][CSZA][CO3]
CCl2F2 photolysis rate [1/s].
Definition: mptrac.h:3150
double ccl3f[CP][CSZA][CO3]
CCl3F photolysis rate [1/s].
Definition: mptrac.h:3147
double n2o[CP][CSZA][CO3]
N2O photolysis rate [1/s].
Definition: mptrac.h:3141
double ccl4[CP][CSZA][CO3]
CCl4 photolysis rate [1/s].
Definition: mptrac.h:3144
clim_photo_t photo
Photolysis rates.
Definition: mptrac.h:3246
Here is the call graph for this function:

◆ module_wet_deposition()

void module_wet_deposition ( ctl_t ctl,
met_t met0,
met_t met1,
atm_t atm,
double *  dt 
)

Perform wet deposition calculations for air parcels.

This function calculates the wet deposition process for each air parcel based on provided atmospheric and meteorological data. It estimates the precipitation rate and scavenging coefficients for particles and gases inside and below cloud layers. The scavenging coefficients are used to calculate the exponential decay of mass or volume mixing ratio over time due to wet deposition.

Parameters
ctlPointer to the control structure containing simulation parameters.
met0Pointer to the initial meteorological data structure.
met1Pointer to the updated meteorological data structure.
atmPointer to the atmospheric data structure containing air parcel information.
dtArray containing the time step for each air parcel.
Note
The function calculates the wet deposition process for particles and gases based on precipitation rate and scavenging coefficients inside and below cloud layers.
It estimates the exponential decay of mass or volume mixing ratio over time due to wet deposition.
Authors
Lars Hoffmann
Mingzhao Liu

Definition at line 3988 of file mptrac.c.

3993 {
3994
3995 /* Set timer... */
3996 SELECT_TIMER("MODULE_WETDEPO", "PHYSICS", NVTX_GPU);
3997
3998 /* Check quantity flags... */
3999 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
4000 ERRMSG("Module needs quantity mass or volume mixing ratio!");
4001
4002 /* Loop over particles... */
4003 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,met0,met1,atm,dt)") {
4004
4005 /* Check whether particle is below cloud top... */
4006 double pct;
4008 INTPOL_2D(pct, 1);
4009 if (!isfinite(pct) || atm->p[ip] <= pct)
4010 continue;
4011
4012 /* Get cloud bottom pressure... */
4013 double pcb;
4014 INTPOL_2D(pcb, 0);
4015
4016 /* Estimate precipitation rate (Pisso et al., 2019)... */
4017 double cl;
4018 INTPOL_2D(cl, 0);
4019 double Is =
4020 pow(1. / ctl->wet_depo_pre[0] * cl, 1. / ctl->wet_depo_pre[1]);
4021 if (Is < 0.01)
4022 continue;
4023
4024 /* Check whether particle is inside or below cloud... */
4025 double lwc, rwc, iwc, swc;
4026 INTPOL_3D(lwc, 1);
4027 INTPOL_3D(rwc, 0);
4028 INTPOL_3D(iwc, 0);
4029 INTPOL_3D(swc, 0);
4030 int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
4031
4032 /* Get temperature... */
4033 double t;
4034 INTPOL_3D(t, 0);
4035
4036 /* Calculate in-cloud scavenging coefficient... */
4037 double lambda = 0;
4038 if (inside) {
4039
4040 /* Calculate retention factor... */
4041 double eta;
4042 if (t > 273.15)
4043 eta = 1;
4044 else if (t <= 238.15)
4045 eta = ctl->wet_depo_ic_ret_ratio;
4046 else
4047 eta = LIN(273.15, 1, 238.15, ctl->wet_depo_ic_ret_ratio, t);
4048
4049 /* Use exponential dependency for particles ... */
4050 if (ctl->wet_depo_ic_a > 0)
4051 lambda = ctl->wet_depo_ic_a * pow(Is, ctl->wet_depo_ic_b) * eta;
4052
4053 /* Use Henry's law for gases... */
4054 else if (ctl->wet_depo_ic_h[0] > 0) {
4055
4056 /* Get Henry's constant (Sander, 2015)... */
4057 double h = ctl->wet_depo_ic_h[0]
4058 * exp(ctl->wet_depo_ic_h[1] * (1. / t - 1. / 298.15));
4059
4060 /* Use effective Henry's constant for SO2
4061 (Berglen, 2004; Simpson, 2012)... */
4062 if (ctl->wet_depo_ic_h[2] > 0) {
4063 double H_ion = pow(10, ctl->wet_depo_ic_h[2] * (-1));
4064 double K_1 = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
4065 double K_2 = 6e-8 * exp(1.12e3 * (1. / t - 1. / 298.15));
4066 h *= (1 + K_1 / H_ion + K_1 * K_2 / pow(H_ion, 2));
4067 }
4068
4069 /* Estimate depth of cloud layer... */
4070 double dz = 1e3 * (Z(pct) - Z(pcb));
4071
4072 /* Calculate scavenging coefficient (Draxler and Hess, 1997)... */
4073 lambda = h * RI * t * Is / 3.6e6 / dz * eta;
4074 }
4075 }
4076
4077 /* Calculate below-cloud scavenging coefficient... */
4078 else {
4079
4080 /* Calculate retention factor... */
4081 double eta;
4082 if (t > 270)
4083 eta = 1;
4084 else
4085 eta = ctl->wet_depo_bc_ret_ratio;
4086
4087 /* Use exponential dependency for particles... */
4088 if (ctl->wet_depo_bc_a > 0)
4089 lambda = ctl->wet_depo_bc_a * pow(Is, ctl->wet_depo_bc_b) * eta;
4090
4091 /* Use Henry's law for gases... */
4092 else if (ctl->wet_depo_bc_h[0] > 0) {
4093
4094 /* Get Henry's constant (Sander, 2015)... */
4095 double h = ctl->wet_depo_bc_h[0]
4096 * exp(ctl->wet_depo_bc_h[1] * (1. / t - 1. / 298.15));
4097
4098 /* Estimate depth of cloud layer... */
4099 double dz = 1e3 * (Z(pct) - Z(pcb));
4100
4101 /* Calculate scavenging coefficient (Draxler and Hess, 1997)... */
4102 lambda = h * RI * t * Is / 3.6e6 / dz * eta;
4103 }
4104 }
4105
4106 /* Calculate exponential decay of mass... */
4107 double aux = exp(-dt[ip] * lambda);
4108 if (ctl->qnt_m >= 0) {
4109 if (ctl->qnt_mloss_wet >= 0)
4110 atm->q[ctl->qnt_mloss_wet][ip]
4111 += atm->q[ctl->qnt_m][ip] * (1 - aux);
4112 atm->q[ctl->qnt_m][ip] *= aux;
4113 if (ctl->qnt_loss_rate >= 0)
4114 atm->q[ctl->qnt_loss_rate][ip] += lambda;
4115 }
4116 if (ctl->qnt_vmr >= 0)
4117 atm->q[ctl->qnt_vmr][ip] *= aux;
4118 }
4119}
double wet_depo_ic_a
Coefficient A for wet deposition in cloud (exponential form).
Definition: mptrac.h:2813
double wet_depo_bc_a
Coefficient A for wet deposition below cloud (exponential form).
Definition: mptrac.h:2807
int qnt_mloss_wet
Quantity array index for total mass loss due to wet deposition.
Definition: mptrac.h:2325
double wet_depo_ic_h[3]
Coefficients for wet deposition in cloud (Henry's law: Hb, Cb, pH).
Definition: mptrac.h:2819
double wet_depo_pre[2]
Coefficients for precipitation calculation.
Definition: mptrac.h:2804
double wet_depo_bc_h[2]
Coefficients for wet deposition below cloud (Henry's law: Hb, Cb).
Definition: mptrac.h:2822
double wet_depo_bc_ret_ratio
Coefficients for wet deposition below cloud: retention ratio.
Definition: mptrac.h:2828
double wet_depo_ic_ret_ratio
Coefficients for wet deposition in cloud: retention ratio.
Definition: mptrac.h:2825
double wet_depo_ic_b
Coefficient B for wet deposition in cloud (exponential form).
Definition: mptrac.h:2816
double wet_depo_bc_b
Coefficient B for wet deposition below cloud (exponential form).
Definition: mptrac.h:2810

◆ nat_temperature()

double nat_temperature ( const double  p,
const double  h2o,
const double  hno3 
)

Calculates the nitric acid trihydrate (NAT) temperature.

This function computes the temperature at which nitric acid trihydrate (NAT) can form given the partial pressures of water vapor and nitric acid in the atmosphere.

Parameters
pThe total atmospheric pressure (in hPa).
h2oThe volume mixing ratio of water vapor (H2O).
hno3The volume mixing ratio of nitric acid (HNO3).
Returns
The NAT temperature (in Kelvin).

This function follows these steps:

  • Ensures the water vapor volume mixing ratio is above a minimum threshold.
  • Converts the volume mixing ratios of H2O and HNO3 to partial pressures.
  • Uses these partial pressures to compute coefficients for the quadratic equation that determines the NAT temperature.
  • Solves the quadratic equation to find the NAT temperature.

The calculations are based on empirical relationships involving logarithms of the partial pressures of H2O and HNO3.

Note
The constants and formulae used are specific to the context of atmospheric chemistry and the formation of NAT.
Author
Lars Hoffmann

Definition at line 4123 of file mptrac.c.

4126 {
4127
4128 /* Check water vapor volume mixing ratio... */
4129 double h2o_help = MAX(h2o, 0.1e-6);
4130
4131 /* Calculate T_NAT... */
4132 double p_hno3 = hno3 * p / 1.333224;
4133 double p_h2o = h2o_help * p / 1.333224;
4134 double a = 0.009179 - 0.00088 * log10(p_h2o);
4135 double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
4136 double c = -11397.0 / a;
4137 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
4138 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
4139 if (x2 > 0)
4140 tnat = x2;
4141
4142 return tnat;
4143}

◆ read_atm()

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

Reads air parcel data from a specified file into the given atmospheric structure.

This function reads air parcel data from a file and populates the provided atm_t structure based on the type of data specified in the ctl_t control structure. It supports various data formats including ASCII, binary, netCDF, and CLaMS.

Parameters
filenameThe name of the file containing the atmospheric data.
ctlA pointer to the control structure (ctl_t) that specifies the type of data.
atmA pointer to the atmospheric structure (atm_t) that will be populated with the data.
Returns
Returns 1 on success, and 0 on failure.

This function performs the following steps:

  • Sets a timer for performance measurement.
  • Initializes the atmospheric structure.
  • Logs the file being read.
  • Reads data from the file based on the specified type (ctl->atm_type):
    • 0 for ASCII data
    • 1 for binary data
    • 2 for netCDF data
    • 3 or 4 for CLaMS data
  • Handles errors if the data type is not supported.
  • Checks the result of the data reading function and ensures data was read successfully.
  • Logs information about the number of air parcels and the ranges of various parameters (time, altitude, pressure, longitude, latitude, and other quantities).

The function utilizes several helper functions and macros:

  • SELECT_TIMER for setting the timer.
  • LOG for logging information.
  • ERRMSG for handling error messages.
  • gsl_stats_minmax for calculating minimum and maximum values.
  • Z for converting altitude.
Author
Lars Hoffmann

Definition at line 4147 of file mptrac.c.

4150 {
4151
4152 int result;
4153
4154 /* Set timer... */
4155 SELECT_TIMER("READ_ATM", "INPUT", NVTX_READ);
4156
4157 /* Init... */
4158 atm->np = 0;
4159
4160 /* Write info... */
4161 LOG(1, "Read atmospheric data: %s", filename);
4162
4163 /* Read ASCII data... */
4164 if (ctl->atm_type == 0)
4165 result = read_atm_asc(filename, ctl, atm);
4166
4167 /* Read binary data... */
4168 else if (ctl->atm_type == 1)
4169 result = read_atm_bin(filename, ctl, atm);
4170
4171 /* Read netCDF data... */
4172 else if (ctl->atm_type == 2)
4173 result = read_atm_nc(filename, ctl, atm);
4174
4175 /* Read CLaMS data... */
4176 else if (ctl->atm_type == 3 || ctl->atm_type == 4)
4177 result = read_atm_clams(filename, ctl, atm);
4178
4179 /* Error... */
4180 else
4181 ERRMSG("Atmospheric data type not supported!");
4182
4183 /* Check result... */
4184 if (result != 1)
4185 return 0;
4186
4187 /* Check number of air parcels... */
4188 if (atm->np < 1)
4189 ERRMSG("Can not read any data!");
4190
4191 /* Write info... */
4192 double mini, maxi;
4193 LOG(2, "Number of particles: %d", atm->np);
4194 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
4195 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
4196 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
4197 LOG(2, "Altitude range: %g ... %g km", Z(maxi), Z(mini));
4198 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
4199 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
4200 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
4201 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
4202 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
4203 for (int iq = 0; iq < ctl->nq; iq++) {
4204 char msg[5 * LEN];
4205 sprintf(msg, "Quantity %s range: %s ... %s %s",
4206 ctl->qnt_name[iq], ctl->qnt_format[iq],
4207 ctl->qnt_format[iq], ctl->qnt_unit[iq]);
4208 gsl_stats_minmax(&mini, &maxi, atm->q[iq], 1, (size_t) atm->np);
4209 LOG(2, msg, mini, maxi);
4210 }
4211
4212 /* Return success... */
4213 return 1;
4214}
int read_atm_nc(const char *filename, ctl_t *ctl, atm_t *atm)
Reads air parcel data from a generic netCDF file and populates the given atmospheric structure.
Definition: mptrac.c:4372
int read_atm_asc(const char *filename, ctl_t *ctl, atm_t *atm)
Reads air parcel data from an ASCII file and populates the given atmospheric structure.
Definition: mptrac.c:4218
int read_atm_clams(const char *filename, ctl_t *ctl, atm_t *atm)
Reads air parcel data from a CLaMS netCDF file and populates the given atmospheric structure.
Definition: mptrac.c:4316
int read_atm_bin(const char *filename, ctl_t *ctl, atm_t *atm)
Reads air parcel data from a binary file and populates the given atmospheric structure.
Definition: mptrac.c:4260
char qnt_format[NQ][LEN]
Quantity output format.
Definition: mptrac.h:2172
int atm_type
Type of atmospheric data files (0=ASCII, 1=binary, 2=netCDF, 3=CLaMS).
Definition: mptrac.h:2863
char qnt_unit[NQ][LEN]
Quantity units.
Definition: mptrac.h:2169
char qnt_name[NQ][LEN]
Quantity names.
Definition: mptrac.h:2163
Here is the call graph for this function:

◆ read_atm_asc()

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

Reads air parcel data from an ASCII file and populates the given atmospheric structure.

This function reads air parcel data from an ASCII file and stores the data in the provided atm_t structure. It reads each line of the file, extracts the necessary data fields, and converts the altitude to pressure.

Parameters
filenameThe name of the ASCII file containing the atmospheric data.
ctlA pointer to the control structure (ctl_t) that specifies the number of quantities.
atmA pointer to the atmospheric structure (atm_t) that will be populated with the data.
Returns
Returns 1 on success, and 0 on failure.

This function performs the following steps:

  • Attempts to open the specified file for reading.
  • Logs a warning and returns 0 if the file cannot be opened.
  • Reads each line of the file and extracts data values for time, altitude, longitude, latitude, and other specified quantities.
  • Converts the altitude to pressure.
  • Increments the data point counter.
  • Checks if the number of data points exceeds the maximum allowed (NP) and logs an error message if so.
  • Closes the file after reading all data.
  • Returns 1 to indicate successful data reading.

The function utilizes several macros and helper functions:

  • WARN for logging warnings.
  • ERRMSG for handling error messages.
  • TOK for tokenizing and reading values from the line.
  • P for converting altitude to pressure.
Author
Lars Hoffmann

Definition at line 4218 of file mptrac.c.

4221 {
4222
4223 /* Open file... */
4224 FILE *in;
4225 if (!(in = fopen(filename, "r"))) {
4226 WARN("Cannot open file!");
4227 return 0;
4228 }
4229
4230 /* Read line... */
4231 char line[LEN];
4232 while (fgets(line, LEN, in)) {
4233
4234 /* Read data... */
4235 char *tok;
4236 TOK(line, tok, "%lg", atm->time[atm->np]);
4237 TOK(NULL, tok, "%lg", atm->p[atm->np]);
4238 TOK(NULL, tok, "%lg", atm->lon[atm->np]);
4239 TOK(NULL, tok, "%lg", atm->lat[atm->np]);
4240 for (int iq = 0; iq < ctl->nq; iq++)
4241 TOK(NULL, tok, "%lg", atm->q[iq][atm->np]);
4242
4243 /* Convert altitude to pressure... */
4244 atm->p[atm->np] = P(atm->p[atm->np]);
4245
4246 /* Increment data point counter... */
4247 if ((++atm->np) > NP)
4248 ERRMSG("Too many data points!");
4249 }
4250
4251 /* Close file... */
4252 fclose(in);
4253
4254 /* Return success... */
4255 return 1;
4256}
#define TOK(line, tok, format, var)
Get string tokens.
Definition: mptrac.h:1659

◆ read_atm_bin()

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

Reads air parcel data from a binary file and populates the given atmospheric structure.

This function reads air parcel data from a binary file and stores the data in the provided atm_t structure. It checks the version of the binary data, reads the data values, and verifies the integrity of the data read.

Parameters
filenameThe name of the binary file containing the atmospheric data.
ctlA pointer to the control structure (ctl_t) that specifies the number of quantities.
atmA pointer to the atmospheric structure (atm_t) that will be populated with the data.
Returns
Returns 1 on success, and 0 on failure.

This function performs the following steps:

  • Attempts to open the specified file for reading.
  • Returns 0 if the file cannot be opened.
  • Checks the version of the binary data and logs an error message if the version is incorrect.
  • Reads the number of data points (np).
  • Reads the data arrays for time, pressure, longitude, latitude, and other specified quantities.
  • Checks a final flag to ensure the data was read correctly.
  • Logs an error message if the final flag is incorrect.
  • Closes the file after reading all data.
  • Returns 1 to indicate successful data reading.

The function utilizes several macros and helper functions:

  • ERRMSG for handling error messages.
  • FREAD for reading data from the binary file.
Author
Lars Hoffmann

Definition at line 4260 of file mptrac.c.

4263 {
4264
4265 /* Open file... */
4266 FILE *in;
4267 if (!(in = fopen(filename, "r")))
4268 return 0;
4269
4270 /* Check version of binary data... */
4271 int version;
4272 FREAD(&version, int,
4273 1,
4274 in);
4275 if (version != 100)
4276 ERRMSG("Wrong version of binary data!");
4277
4278 /* Read data... */
4279 FREAD(&atm->np, int,
4280 1,
4281 in);
4282 FREAD(atm->time, double,
4283 (size_t) atm->np,
4284 in);
4285 FREAD(atm->p, double,
4286 (size_t) atm->np,
4287 in);
4288 FREAD(atm->lon, double,
4289 (size_t) atm->np,
4290 in);
4291 FREAD(atm->lat, double,
4292 (size_t) atm->np,
4293 in);
4294 for (int iq = 0; iq < ctl->nq; iq++)
4295 FREAD(atm->q[iq], double,
4296 (size_t) atm->np,
4297 in);
4298
4299 /* Read final flag... */
4300 int final;
4301 FREAD(&final, int,
4302 1,
4303 in);
4304 if (final != 999)
4305 ERRMSG("Error while reading binary data!");
4306
4307 /* Close file... */
4308 fclose(in);
4309
4310 /* Return success... */
4311 return 1;
4312}

◆ read_atm_clams()

int read_atm_clams ( const char *  filename,
ctl_t ctl,
atm_t atm 
)

Reads air parcel data from a CLaMS netCDF file and populates the given atmospheric structure.

This function reads air parcel data from a CLaMS (Chemical Lagrangian Model of the Stratosphere) netCDF file and stores the data in the provided atm_t structure. It handles various coordinate systems and ensures the necessary data is correctly read and stored.

Parameters
filenameThe name of the netCDF file containing the atmospheric data.
ctlA pointer to the control structure (ctl_t) that specifies the vertical coordinate system and quantities.
atmA pointer to the atmospheric structure (atm_t) that will be populated with the data.
Returns
Returns 1 on success, and 0 on failure.

This function performs the following steps:

  • Attempts to open the specified netCDF file for reading.
  • Returns 0 if the file cannot be opened.
  • Retrieves the number of particles (np) from the "NPARTS" dimension.
  • Reads the initial time (TIME_INIT) if available, otherwise uses the "time" variable.
  • Reads the vertical coordinate data based on the specified system (vert_coord_ap):
    • If vert_coord_ap is 1, reads "ZETA" and optionally "PRESS".
    • Otherwise, reads "PRESS_INIT" if available, otherwise uses "PRESS".
  • Reads the longitude ("LON") and latitude ("LAT") data.
  • Closes the netCDF file.
  • Returns 1 to indicate successful data reading.

The function utilizes several macros and helper functions:

  • NC_INQ_DIM for inquiring about dimensions in the netCDF file.
  • NC_GET_DOUBLE for reading double values from the netCDF file.
  • NC for checking netCDF function return values.
  • WARN for logging warnings.
Author
Jan Clemens

Definition at line 4316 of file mptrac.c.

4319 {
4320
4321 int ncid, varid;
4322
4323 /* Open file... */
4324 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
4325 return 0;
4326
4327 /* Get dimensions... */
4328 NC_INQ_DIM("NPARTS", &atm->np, 1, NP);
4329
4330 /* Get time... */
4331 if (nc_inq_varid(ncid, "TIME_INIT", &varid) == NC_NOERR) {
4332 NC(nc_get_var_double(ncid, varid, atm->time));
4333 } else {
4334 WARN("TIME_INIT not found use time instead!");
4335 double time_init;
4336 NC_GET_DOUBLE("time", &time_init, 1);
4337 for (int ip = 0; ip < atm->np; ip++) {
4338 atm->time[ip] = time_init;
4339 }
4340 }
4341
4342 /* Read zeta coordinate, pressure is optional... */
4343 if (ctl->advect_vert_coord == 1) {
4344 NC_GET_DOUBLE("ZETA", atm->q[ctl->qnt_zeta], 1);
4345 NC_GET_DOUBLE("PRESS", atm->p, 0);
4346 }
4347
4348 /* Read pressure, zeta coordinate is optional... */
4349 else {
4350 if (nc_inq_varid(ncid, "PRESS_INIT", &varid) == NC_NOERR) {
4351 NC(nc_get_var_double(ncid, varid, atm->p));
4352 } else {
4353 WARN("PRESS_INIT not found use PRESS instead!");
4354 nc_inq_varid(ncid, "PRESS", &varid);
4355 NC(nc_get_var_double(ncid, varid, atm->p));
4356 }
4357 }
4358
4359 /* Read longitude and latitude... */
4360 NC_GET_DOUBLE("LON", atm->lon, 1);
4361 NC_GET_DOUBLE("LAT", atm->lat, 1);
4362
4363 /* Close file... */
4364 NC(nc_close(ncid));
4365
4366 /* Return success... */
4367 return 1;
4368}
#define NC(cmd)
Execute a NetCDF command and check for errors.
Definition: mptrac.h:981
#define NC_INQ_DIM(dimname, ptr, min, max)
Inquire the length of a dimension in a NetCDF file.
Definition: mptrac.h:1054
#define NC_GET_DOUBLE(varname, ptr, force)
Retrieve a double-precision variable from a NetCDF file.
Definition: mptrac.h:1026

◆ read_atm_nc()

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

Reads air parcel data from a generic netCDF file and populates the given atmospheric structure.

This function reads air parcel data from a netCDF file and stores the data in the provided atm_t structure. It retrieves the dimensions, geolocations (time, pressure, longitude, latitude), and specified variables from the file.

Parameters
filenameThe name of the netCDF file containing the atmospheric data.
ctlA pointer to the control structure (ctl_t) that specifies the number of quantities and their names.
atmA pointer to the atmospheric structure (atm_t) that will be populated with the data.
Returns
Returns 1 on success, and 0 on failure.

This function performs the following steps:

  • Attempts to open the specified netCDF file for reading.
  • Returns 0 if the file cannot be opened.
  • Retrieves the number of observations (np) from the "obs" dimension.
  • Reads the geolocation data arrays for time, pressure, longitude, and latitude.
  • Reads the specified variables into the corresponding arrays in the atm_t structure.
  • Closes the netCDF file after reading all data.
  • Returns 1 to indicate successful data reading.

The function utilizes several macros and helper functions:

  • NC_INQ_DIM for inquiring about dimensions in the netCDF file.
  • NC_GET_DOUBLE for reading double values from the netCDF file.
  • NC for checking netCDF function return values.
Author
Lars Hoffmann

Definition at line 4372 of file mptrac.c.

4375 {
4376
4377 int ncid, varid;
4378
4379 /* Open file... */
4380 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
4381 return 0;
4382
4383 /* Get dimensions... */
4384 NC_INQ_DIM("obs", &atm->np, 1, NP);
4385
4386 /* Read geolocations... */
4387 NC_GET_DOUBLE("time", atm->time, 1);
4388 NC_GET_DOUBLE("press", atm->p, 1);
4389 NC_GET_DOUBLE("lon", atm->lon, 1);
4390 NC_GET_DOUBLE("lat", atm->lat, 1);
4391
4392 /* Read variables... */
4393 for (int iq = 0; iq < ctl->nq; iq++)
4394 NC_GET_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
4395
4396 /* Close file... */
4397 NC(nc_close(ncid));
4398
4399 /* Return success... */
4400 return 1;
4401}

◆ read_clim()

void read_clim ( ctl_t ctl,
clim_t clim 
)

Reads various climatological data and populates the given climatology structure.

This function reads a range of climatological datasets based on the specified control settings and stores the data in the provided clim_t structure. It handles initialization of tropopause climatology, photolysis rates, and multiple gas species' climatologies and time series.

Parameters
ctlA pointer to the control structure (ctl_t) that specifies file names and parameters for climatology data.
climA pointer to the climatology structure (clim_t) that will be populated with the data.

This function performs the following steps:

  • Sets a timer for reading climatology data.
  • Initializes the tropopause climatology.
  • Reads photolysis rates if specified in ctl.
  • Reads HNO3 climatology if specified in ctl.
  • Reads OH climatology if specified in ctl and applies a diurnal correction if specified.
  • Reads H2O2, HO2, O(1D) climatologies if specified in ctl.
  • Reads time series data for various gases (CFC-10, CFC-11, CFC-12, N2O, SF6) if specified in ctl.

The function utilizes several helper functions:

  • clim_tropo_init for initializing tropopause climatology.
  • read_clim_photo for reading photolysis rates.
  • read_clim_zm for reading zonal mean climatologies.
  • clim_oh_diurnal_correction for applying diurnal correction to OH climatology.
  • read_clim_ts for reading time series data.
Authors
Lars Hoffmann
Mingzhao Liu

Definition at line 4405 of file mptrac.c.

4407 {
4408
4409 /* Set timer... */
4410 SELECT_TIMER("READ_CLIM", "INPUT", NVTX_READ);
4411
4412 /* Init tropopause climatology... */
4413 clim_tropo_init(clim);
4414
4415 /* Read photolysis rates... */
4416 if (ctl->clim_photo[0] != '-')
4417 read_clim_photo(ctl->clim_photo, &clim->photo);
4418
4419 /* Read HNO3 climatology... */
4420 if (ctl->clim_hno3_filename[0] != '-')
4421 read_clim_zm(ctl->clim_hno3_filename, "HNO3", &clim->hno3);
4422
4423 /* Read OH climatology... */
4424 if (ctl->clim_oh_filename[0] != '-') {
4425 read_clim_zm(ctl->clim_oh_filename, "OH", &clim->oh);
4426 if (ctl->oh_chem_beta > 0)
4427 clim_oh_diurnal_correction(ctl, clim);
4428 }
4429
4430 /* Read H2O2 climatology... */
4431 if (ctl->clim_h2o2_filename[0] != '-')
4432 read_clim_zm(ctl->clim_h2o2_filename, "H2O2", &clim->h2o2);
4433
4434 /* Read HO2 climatology... */
4435 if (ctl->clim_ho2_filename[0] != '-')
4436 read_clim_zm(ctl->clim_ho2_filename, "HO2", &clim->ho2);
4437
4438 /* Read O(1D) climatology... */
4439 if (ctl->clim_o1d_filename[0] != '-')
4440 read_clim_zm(ctl->clim_o1d_filename, "O1D", &clim->o1d);
4441
4442 /* Read CFC-10 time series... */
4443 if (ctl->clim_ccl4_timeseries[0] != '-')
4445
4446 /* Read CFC-11 time series... */
4447 if (ctl->clim_ccl3f_timeseries[0] != '-')
4449
4450 /* Read CFC-12 time series... */
4451 if (ctl->clim_ccl2f2_timeseries[0] != '-')
4453
4454 /* Read N2O time series... */
4455 if (ctl->clim_n2o_timeseries[0] != '-')
4456 read_clim_ts(ctl->clim_n2o_timeseries, &clim->n2o);
4457
4458 /* Read SF6 time series... */
4459 if (ctl->clim_sf6_timeseries[0] != '-')
4460 read_clim_ts(ctl->clim_sf6_timeseries, &clim->sf6);
4461}
void read_clim_photo(const char *filename, clim_photo_t *photo)
Reads photolysis rates from a NetCDF file and populates the given photolysis structure.
Definition: mptrac.c:4465
int read_clim_ts(const char *filename, clim_ts_t *ts)
Reads a climatological time series from a file and populates the given time series structure.
Definition: mptrac.c:4600
void clim_oh_diurnal_correction(ctl_t *ctl, clim_t *clim)
Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data.
Definition: mptrac.c:112
void read_clim_zm(const char *filename, char *varname, clim_zm_t *zm)
Reads zonally averaged climatological data from a netCDF file and populates the given structure.
Definition: mptrac.c:4654
void clim_tropo_init(clim_t *clim)
Initializes the tropopause data in the climatology structure.
Definition: mptrac.c:221
char clim_ho2_filename[LEN]
Filename of HO2 climatology.
Definition: mptrac.h:2696
char clim_o1d_filename[LEN]
Filename of O(1D) climatology.
Definition: mptrac.h:2699
char clim_photo[LEN]
Filename of photolysis rates climatology.
Definition: mptrac.h:2684
char clim_h2o2_filename[LEN]
Filename of H2O2 climatology.
Definition: mptrac.h:2693
char clim_oh_filename[LEN]
Filename of OH climatology.
Definition: mptrac.h:2690
char clim_hno3_filename[LEN]
Filename of HNO3 climatology.
Definition: mptrac.h:2687
Here is the call graph for this function:

◆ read_clim_photo()

void read_clim_photo ( const char *  filename,
clim_photo_t photo 
)

Reads photolysis rates from a NetCDF file and populates the given photolysis structure.

This function opens a NetCDF file specified by the filename, reads various dimensions and data related to photolysis rates, and stores this data in the provided clim_photo_t structure. It includes checks for data consistency and logs detailed information about the loaded data.

Parameters
filenameA string containing the path to the NetCDF file containing photolysis rate data.
photoA pointer to the photolysis structure (clim_photo_t) that will be populated with the data.

The function performs the following steps:

  • Logs the initiation of reading photolysis rates.
  • Opens the NetCDF file in read-only mode.
  • Reads pressure data and checks for descending order.
  • Reads total column ozone data and checks for ascending order.
  • Reads solar zenith angle data and checks for ascending order.
  • Allocates memory for temporary arrays to hold the data.
  • Reads various photolysis rates (e.g., J_N2O, J_CCl4, J_CFC-11, J_CFC-12, J_O2, J_O3b, J_O3a, J_H2O2, J_H2O) and stores them in the clim_photo_t structure.
  • Frees the allocated memory for temporary arrays.
  • Closes the NetCDF file.
  • Logs detailed information about the loaded data, including pressure levels, solar zenith angles, and photolysis rates.
Author
Mingzhao Liu

Definition at line 4465 of file mptrac.c.

4467 {
4468
4469 int ncid, varid, ip, is, io;
4470
4471 double *help1, *help2, *help3, *help4;
4472
4473 /* Write info... */
4474 LOG(1, "Read photolysis rates: %s", filename);
4475
4476 /* Open netCDF file... */
4477 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
4478 WARN("Photolysis rate data are missing!");
4479 return;
4480 }
4481
4482 /* Read pressure data... */
4483 NC_INQ_DIM("press", &photo->np, 2, CP);
4484 NC_GET_DOUBLE("press", photo->p, 1);
4485 if (photo->p[0] < photo->p[1])
4486 ERRMSG("Pressure data are not descending!");
4487
4488 /* Read total column ozone data... */
4489 NC_INQ_DIM("total_o3col", &photo->no3c, 2, CO3);
4490 NC_GET_DOUBLE("total_o3col", photo->o3c, 1);
4491 if (photo->o3c[0] > photo->o3c[1])
4492 ERRMSG("Total column ozone data are not ascending!");
4493
4494 /* Read solar zenith angle data... */
4495 NC_INQ_DIM("sza", &photo->nsza, 2, CSZA);
4496 NC_GET_DOUBLE("sza", photo->sza, 1);
4497 if (photo->sza[0] > photo->sza[1])
4498 ERRMSG("Solar zenith angle data are not ascending!");
4499
4500 /* Read data... */
4501 ALLOC(help1, double,
4502 photo->np * photo->nsza * photo->no3c);
4503 ALLOC(help2, double,
4504 photo->np * photo->nsza * photo->no3c);
4505 ALLOC(help3, double,
4506 photo->np * photo->nsza * photo->no3c);
4507 ALLOC(help4, double,
4508 photo->np * photo->nsza * photo->no3c);
4509 NC_GET_DOUBLE("J_N2O", help1, 1);
4510 NC_GET_DOUBLE("J_CCl4", help2, 1);
4511 NC_GET_DOUBLE("J_CFC-11", help3, 1);
4512 NC_GET_DOUBLE("J_CFC-12", help4, 1);
4513 for (ip = 0; ip < photo->np; ip++)
4514 for (is = 0; is < photo->nsza; is++)
4515 for (io = 0; io < photo->no3c; io++) {
4516 photo->n2o[ip][is][io] =
4517 help1[ARRAY_3D(ip, is, photo->nsza, io, photo->no3c)];
4518 photo->ccl4[ip][is][io] =
4519 help2[ARRAY_3D(ip, is, photo->nsza, io, photo->no3c)];
4520 photo->ccl3f[ip][is][io] =
4521 help3[ARRAY_3D(ip, is, photo->nsza, io, photo->no3c)];
4522 photo->ccl2f2[ip][is][io] =
4523 help4[ARRAY_3D(ip, is, photo->nsza, io, photo->no3c)];
4524 }
4525
4526 NC_GET_DOUBLE("J_O2", help1, 1);
4527 NC_GET_DOUBLE("J_O3b", help2, 1);
4528 NC_GET_DOUBLE("J_O3a", help3, 1);
4529 NC_GET_DOUBLE("J_H2O2", help4, 1);
4530 for (ip = 0; ip < photo->np; ip++)
4531 for (is = 0; is < photo->nsza; is++)
4532 for (io = 0; io < photo->no3c; io++) {
4533 photo->o2[ip][is][io] =
4534 help1[ARRAY_3D(ip, is, photo->nsza, io, photo->no3c)];
4535 photo->o3_1[ip][is][io] =
4536 help2[ARRAY_3D(ip, is, photo->nsza, io, photo->no3c)];
4537 photo->o3_2[ip][is][io] =
4538 help3[ARRAY_3D(ip, is, photo->nsza, io, photo->no3c)];
4539 photo->h2o2[ip][is][io] =
4540 help4[ARRAY_3D(ip, is, photo->nsza, io, photo->no3c)];
4541 }
4542 NC_GET_DOUBLE("J_H2O", help1, 1);
4543 for (ip = 0; ip < photo->np; ip++)
4544 for (is = 0; is < photo->nsza; is++)
4545 for (io = 0; io < photo->no3c; io++)
4546 photo->h2o[ip][is][io] =
4547 help1[ARRAY_3D(ip, is, photo->nsza, io, photo->no3c)];
4548 free(help1);
4549 free(help2);
4550 free(help3);
4551 free(help4);
4552
4553 /* Close netCDF file... */
4554 NC(nc_close(ncid));
4555
4556 /* Write info... */
4557 LOG(2, "Number of pressure levels: %d", photo->np);
4558 LOG(2, "Altitude levels: %g, %g ... %g km",
4559 Z(photo->p[0]), Z(photo->p[1]), Z(photo->p[photo->np - 1]));
4560 LOG(2, "Pressure levels: %g, %g ... %g hPa",
4561 photo->p[0], photo->p[1], photo->p[photo->np - 1]);
4562 LOG(2, "Number of solar zenith angles: %d", photo->nsza);
4563 LOG(2, "Solar zenith angles: %g, %g ... %g deg",
4564 photo->sza[0] * 180. / M_PI, photo->sza[1] * 180. / M_PI,
4565 photo->sza[photo->nsza - 1] * 180. / M_PI);
4566 LOG(2, "Number of total column ozone values: %d", photo->no3c);
4567 LOG(2, "Total column ozone: %g, %g ... %g DU",
4568 photo->o3c[0], photo->o3c[1], photo->o3c[photo->no3c - 1]);
4569 LOG(2, "N2O photolysis rate: %g, %g ... %g s**-1",
4570 photo->n2o[0][0][0], photo->n2o[1][0][0],
4571 photo->n2o[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
4572 LOG(2, "CCl4 photolysis rate: %g, %g ... %g s**-1",
4573 photo->ccl4[0][0][0], photo->ccl4[1][0][0],
4574 photo->ccl4[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
4575 LOG(2, "CFC-11 photolysis rate: %g, %g ... %g s**-1",
4576 photo->ccl3f[0][0][0], photo->ccl3f[1][0][0],
4577 photo->ccl3f[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
4578 LOG(2, "CFC-12 photolysis rate: %g, %g ... %g s**-1",
4579 photo->ccl2f2[0][0][0], photo->ccl2f2[1][0][0],
4580 photo->ccl2f2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
4581 LOG(2, "O2 photolysis rate: %g, %g ... %g s**-1",
4582 photo->o2[0][0][0], photo->o2[1][0][0],
4583 photo->o2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
4584 LOG(2, "O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
4585 photo->o3_1[0][0][0], photo->o3_1[1][0][0],
4586 photo->o3_1[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
4587 LOG(2, "O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
4588 photo->o3_2[0][0][0], photo->o3_2[1][0][0],
4589 photo->o3_2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
4590 LOG(2, "H2O2 photolysis rate: %g, %g ... %g s**-1",
4591 photo->h2o2[0][0][0], photo->h2o2[1][0][0],
4592 photo->h2o2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
4593 LOG(2, "H2O photolysis rate: %g, %g ... %g s**-1",
4594 photo->h2o[0][0][0], photo->h2o[1][0][0],
4595 photo->h2o[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
4596}
#define CP
Maximum number of pressure levels for climatological data.
Definition: mptrac.h:296
#define CO3
Maximum number of total column ozone data for climatological data.
Definition: mptrac.h:291
#define CSZA
Maximum number of solar zenith angles for climatological data.
Definition: mptrac.h:301
double o3_1[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O1d + O2) [1/s].
Definition: mptrac.h:3156
double o2[CP][CSZA][CO3]
O2 photolysis rate [1/s].
Definition: mptrac.h:3153
double h2o2[CP][CSZA][CO3]
H2O2 photolysis rate [1/s].
Definition: mptrac.h:3162
double h2o[CP][CSZA][CO3]
H2O photolysis rate [1/s].
Definition: mptrac.h:3165
double o3_2[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O3p + O2) [1/s].
Definition: mptrac.h:3159

◆ read_clim_ts()

int read_clim_ts ( const char *  filename,
clim_ts_t ts 
)

Reads a climatological time series from a file and populates the given time series structure.

This function reads time and volume mixing ratio (VMR) data from a specified file, processes the data, and stores it in the provided clim_ts_t structure. It also includes checks for data consistency and logs detailed information about the loaded data.

Parameters
filenameA string containing the path to the file containing the climatological time series data.
tsA pointer to the time series structure (clim_ts_t) that will be populated with the data.
Returns
Returns 1 on success, and 0 on failure (e.g., if the file cannot be opened or data is invalid).

The function performs the following steps:

  • Logs the initiation of reading the climatological time series.
  • Opens the file for reading.
  • Reads time and VMR data from the file, converting years to seconds.
  • Checks for ascending order of time data and ensures the number of data points does not exceed the limit.
  • Closes the file after reading.
  • Checks if there are enough data points.
  • Logs detailed information about the loaded data, including the number of time steps and the range of VMR values.
Author
Lars Hoffmann

Definition at line 4600 of file mptrac.c.

4602 {
4603
4604 /* Write info... */
4605 LOG(1, "Read climatological time series: %s", filename);
4606
4607 /* Open file... */
4608 FILE *in;
4609 if (!(in = fopen(filename, "r"))) {
4610 WARN("Cannot open file!");
4611 return 0;
4612 }
4613
4614 /* Read data... */
4615 char line[LEN];
4616 int nh = 0;
4617 while (fgets(line, LEN, in))
4618 if (sscanf(line, "%lg %lg", &ts->time[nh], &ts->vmr[nh]) == 2) {
4619
4620 /* Convert years to seconds... */
4621 ts->time[nh] = (ts->time[nh] - 2000.0) * 365.25 * 86400.;
4622
4623 /* Check data... */
4624 if (nh > 0 && ts->time[nh] <= ts->time[nh - 1])
4625 ERRMSG("Time series must be ascending!");
4626
4627 /* Count time steps... */
4628 if ((++nh) >= CTS)
4629 ERRMSG("Too many data points!");
4630 }
4631
4632 /* Close file... */
4633 fclose(in);
4634
4635 /* Check number of data points... */
4636 ts->ntime = nh;
4637 if (nh < 2)
4638 ERRMSG("Not enough data points!");
4639
4640 /* Write info... */
4641 LOG(2, "Number of time steps: %d", ts->ntime);
4642 LOG(2, "Time steps: %.2f, %.2f ... %.2f s", ts->time[0], ts->time[1],
4643 ts->time[nh - 1]);
4644 LOG(2, "Volume mixing ratio range: %g ... %g ppv",
4645 gsl_stats_min(ts->vmr, 1, (size_t) nh), gsl_stats_max(ts->vmr, 1,
4646 (size_t) nh));
4647
4648 /* Exit success... */
4649 return 1;
4650}
#define CTS
Maximum number of data points of climatological time series.
Definition: mptrac.h:311

◆ read_clim_zm()

void read_clim_zm ( const char *  filename,
char *  varname,
clim_zm_t zm 
)

Reads zonally averaged climatological data from a netCDF file and populates the given structure.

This function reads data from a specified netCDF file, including pressure levels, latitudes, and volume mixing ratios (VMR) for a specified variable. It performs necessary checks and logs detailed information about the loaded data.

Parameters
filenameA string containing the path to the netCDF file.
varnameA string containing the name of the variable to be read from the netCDF file.
zmA pointer to the structure (clim_zm_t) that will be populated with the data.

The function performs the following steps:

  • Logs the initiation of reading the specified data.
  • Opens the netCDF file for reading.
  • Reads pressure level data and checks for descending order.
  • Reads latitude data and checks for ascending order.
  • Sets the time data for monthly means.
  • Checks the number of time steps.
  • Reads the specified variable data from the file.
  • Fixes any gaps in the data by interpolating from valid values.
  • Logs detailed information about the loaded data, including the number of time steps, pressure levels, latitude values, and the range of the variable's volume mixing ratios.
Author
Lars Hoffmann

Definition at line 4654 of file mptrac.c.

4657 {
4658
4659 int ncid, varid, it, iy, iz, iz2, nt;
4660
4661 double *help, varmin = 1e99, varmax = -1e99;
4662
4663 /* Write info... */
4664 LOG(1, "Read %s data: %s", varname, filename);
4665
4666 /* Open netCDF file... */
4667 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
4668 WARN("%s climatology data are missing!", varname);
4669 return;
4670 }
4671
4672 /* Read pressure data... */
4673 NC_INQ_DIM("press", &zm->np, 2, CP);
4674 NC_GET_DOUBLE("press", zm->p, 1);
4675 if (zm->p[0] < zm->p[1])
4676 ERRMSG("Pressure data are not descending!");
4677
4678 /* Read latitudes... */
4679 NC_INQ_DIM("lat", &zm->nlat, 2, CY);
4680 NC_GET_DOUBLE("lat", zm->lat, 1);
4681 if (zm->lat[0] > zm->lat[1])
4682 ERRMSG("Latitude data are not ascending!");
4683
4684 /* Set time data (for monthly means)... */
4685 zm->ntime = 12;
4686 zm->time[0] = 1209600.00;
4687 zm->time[1] = 3888000.00;
4688 zm->time[2] = 6393600.00;
4689 zm->time[3] = 9072000.00;
4690 zm->time[4] = 11664000.00;
4691 zm->time[5] = 14342400.00;
4692 zm->time[6] = 16934400.00;
4693 zm->time[7] = 19612800.00;
4694 zm->time[8] = 22291200.00;
4695 zm->time[9] = 24883200.00;
4696 zm->time[10] = 27561600.00;
4697 zm->time[11] = 30153600.00;
4698
4699 /* Check number of timesteps... */
4700 NC_INQ_DIM("time", &nt, 12, 12);
4701
4702 /* Read data... */
4703 ALLOC(help, double,
4704 zm->nlat * zm->np * zm->ntime);
4705 NC_GET_DOUBLE(varname, help, 1);
4706 for (it = 0; it < zm->ntime; it++)
4707 for (iz = 0; iz < zm->np; iz++)
4708 for (iy = 0; iy < zm->nlat; iy++)
4709 zm->vmr[it][iz][iy] = help[ARRAY_3D(it, iz, zm->np, iy, zm->nlat)];
4710 free(help);
4711
4712 /* Fix data gaps... */
4713 for (it = 0; it < zm->ntime; it++)
4714 for (iy = 0; iy < zm->nlat; iy++)
4715 for (iz = 0; iz < zm->np; iz++) {
4716 if (zm->vmr[it][iz][iy] < 0) {
4717 for (iz2 = 0; iz2 < zm->np; iz2++)
4718 if (zm->vmr[it][iz2][iy] >= 0) {
4719 zm->vmr[it][iz][iy] = zm->vmr[it][iz2][iy];
4720 break;
4721 }
4722 for (iz2 = zm->np - 1; iz2 >= 0; iz2--)
4723 if (zm->vmr[it][iz2][iy] >= 0) {
4724 zm->vmr[it][iz][iy] = zm->vmr[it][iz2][iy];
4725 break;
4726 }
4727 }
4728 varmin = MIN(varmin, zm->vmr[it][iz][iy]);
4729 varmax = MAX(varmax, zm->vmr[it][iz][iy]);
4730 }
4731
4732 /* Close netCDF file... */
4733 NC(nc_close(ncid));
4734
4735 /* Write info... */
4736 LOG(2, "Number of time steps: %d", zm->ntime);
4737 LOG(2, "Time steps: %.2f, %.2f ... %.2f s",
4738 zm->time[0], zm->time[1], zm->time[zm->ntime - 1]);
4739 LOG(2, "Number of pressure levels: %d", zm->np);
4740 LOG(2, "Altitude levels: %g, %g ... %g km",
4741 Z(zm->p[0]), Z(zm->p[1]), Z(zm->p[zm->np - 1]));
4742 LOG(2, "Pressure levels: %g, %g ... %g hPa", zm->p[0],
4743 zm->p[1], zm->p[zm->np - 1]);
4744 LOG(2, "Number of latitudes: %d", zm->nlat);
4745 LOG(2, "Latitudes: %g, %g ... %g deg",
4746 zm->lat[0], zm->lat[1], zm->lat[zm->nlat - 1]);
4747 LOG(2, "%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
4748 varmax);
4749}
#define CY
Maximum number of latitudes for climatological data.
Definition: mptrac.h:286

◆ read_ctl()

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

Reads control parameters from a configuration file and populates the given structure.

This function reads control parameters from a specified configuration file and command line arguments, populating the provided ctl_t structure with the parsed data. It handles a wide range of parameters, performing necessary checks and providing default values where applicable.

Parameters
filenameA string containing the path to the configuration file.
argcAn integer representing the number of command line arguments.
argvAn array of strings containing the command line arguments.
ctlA pointer to the structure (ctl_t) that will be populated with the control parameters.

The function performs the following steps:

  • Sets a timer for reading the control file.
  • Logs information about the MPTRAC executable version and compilation details.
  • Initializes quantity indices.
  • Reads and sets various control parameters such as quantities, vertical coordinates, time steps, meteorological data, sorting options, isosurface parameters, random number generator type, advection parameters, diffusion parameters, convection parameters, boundary conditions, species parameters, molar mass, OH chemistry parameters, H2O2 chemistry parameters, KPP chemistry parameters, first order tracer chemistry parameters, wet deposition parameters, dry deposition parameters, climatological data paths, mixing parameters, chemistry grid parameters, exponential decay parameters, PSC analysis parameters, output parameters for atmospheric data, CSI data, ensemble data, grid data, profile data, sample data, station data, and VTK data.
Author
Lars Hoffmann

Definition at line 4753 of file mptrac.c.

4757 {
4758
4759 /* Set timer... */
4760 SELECT_TIMER("READ_CTL", "INPUT", NVTX_READ);
4761
4762 /* Write info... */
4763 LOG(1, "\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
4764 "(executable: %s | version: %s | compiled: %s, %s)\n",
4765 argv[0], VERSION, __DATE__, __TIME__);
4766
4767 /* Initialize quantity indices... */
4768 ctl->qnt_idx = -1;
4769 ctl->qnt_ens = -1;
4770 ctl->qnt_stat = -1;
4771 ctl->qnt_m = -1;
4772 ctl->qnt_vmr = -1;
4773 ctl->qnt_rp = -1;
4774 ctl->qnt_rhop = -1;
4775 ctl->qnt_ps = -1;
4776 ctl->qnt_ts = -1;
4777 ctl->qnt_zs = -1;
4778 ctl->qnt_us = -1;
4779 ctl->qnt_vs = -1;
4780 ctl->qnt_lsm = -1;
4781 ctl->qnt_sst = -1;
4782 ctl->qnt_pbl = -1;
4783 ctl->qnt_pt = -1;
4784 ctl->qnt_tt = -1;
4785 ctl->qnt_zt = -1;
4786 ctl->qnt_h2ot = -1;
4787 ctl->qnt_zg = -1;
4788 ctl->qnt_p = -1;
4789 ctl->qnt_t = -1;
4790 ctl->qnt_rho = -1;
4791 ctl->qnt_u = -1;
4792 ctl->qnt_v = -1;
4793 ctl->qnt_w = -1;
4794 ctl->qnt_h2o = -1;
4795 ctl->qnt_o3 = -1;
4796 ctl->qnt_lwc = -1;
4797 ctl->qnt_rwc = -1;
4798 ctl->qnt_iwc = -1;
4799 ctl->qnt_swc = -1;
4800 ctl->qnt_cc = -1;
4801 ctl->qnt_pct = -1;
4802 ctl->qnt_pcb = -1;
4803 ctl->qnt_cl = -1;
4804 ctl->qnt_plcl = -1;
4805 ctl->qnt_plfc = -1;
4806 ctl->qnt_pel = -1;
4807 ctl->qnt_cape = -1;
4808 ctl->qnt_cin = -1;
4809 ctl->qnt_o3c = -1;
4810 ctl->qnt_hno3 = -1;
4811 ctl->qnt_oh = -1;
4812 ctl->qnt_h2o2 = -1;
4813 ctl->qnt_ho2 = -1;
4814 ctl->qnt_o1d = -1;
4815 ctl->qnt_mloss_oh = -1;
4816 ctl->qnt_mloss_h2o2 = -1;
4817 ctl->qnt_mloss_kpp = -1;
4818 ctl->qnt_mloss_wet = -1;
4819 ctl->qnt_mloss_dry = -1;
4820 ctl->qnt_mloss_decay = -1;
4821 ctl->qnt_loss_rate = -1;
4822 ctl->qnt_psat = -1;
4823 ctl->qnt_psice = -1;
4824 ctl->qnt_pw = -1;
4825 ctl->qnt_sh = -1;
4826 ctl->qnt_rh = -1;
4827 ctl->qnt_rhice = -1;
4828 ctl->qnt_theta = -1;
4829 ctl->qnt_zeta = -1;
4830 ctl->qnt_zeta_d = -1;
4831 ctl->qnt_tvirt = -1;
4832 ctl->qnt_lapse = -1;
4833 ctl->qnt_vh = -1;
4834 ctl->qnt_vz = -1;
4835 ctl->qnt_pv = -1;
4836 ctl->qnt_tdew = -1;
4837 ctl->qnt_tice = -1;
4838 ctl->qnt_tsts = -1;
4839 ctl->qnt_tnat = -1;
4840 ctl->qnt_Cx = -1;
4841 ctl->qnt_Ch2o = -1;
4842 ctl->qnt_Co3 = -1;
4843 ctl->qnt_Cco = -1;
4844 ctl->qnt_Coh = -1;
4845 ctl->qnt_Ch = -1;
4846 ctl->qnt_Cho2 = -1;
4847 ctl->qnt_Ch2o2 = -1;
4848 ctl->qnt_Co1d = -1;
4849 ctl->qnt_Co3p = -1;
4850 ctl->qnt_Cccl4 = -1;
4851 ctl->qnt_Cccl3f = -1;
4852 ctl->qnt_Cccl2f2 = -1;
4853 ctl->qnt_Cn2o = -1;
4854 ctl->qnt_Csf6 = -1;
4855 ctl->qnt_aoa = -1;
4856
4857 /* Read quantities... */
4858 ctl->nq = (int) scan_ctl(filename, argc, argv, "NQ", -1, "0", NULL);
4859 if (ctl->nq > NQ)
4860 ERRMSG("Too many quantities!");
4861 for (int iq = 0; iq < ctl->nq; iq++) {
4862
4863 /* Read quantity name and format... */
4864 scan_ctl(filename, argc, argv, "QNT_NAME", iq, "", ctl->qnt_name[iq]);
4865 scan_ctl(filename, argc, argv, "QNT_LONGNAME", iq, ctl->qnt_name[iq],
4866 ctl->qnt_longname[iq]);
4867 scan_ctl(filename, argc, argv, "QNT_FORMAT", iq, "%g",
4868 ctl->qnt_format[iq]);
4869 if (strcasecmp(ctl->qnt_name[iq], "aoa") == 0)
4870 sprintf(ctl->qnt_format[iq], "%%.2f");
4871
4872 /* Try to identify quantity... */
4873 SET_QNT(qnt_idx, "idx", "particle index", "-")
4874 SET_QNT(qnt_ens, "ens", "ensemble index", "-")
4875 SET_QNT(qnt_stat, "stat", "station flag", "-")
4876 SET_QNT(qnt_m, "m", "mass", "kg")
4877 SET_QNT(qnt_vmr, "vmr", "volume mixing ratio", "ppv")
4878 SET_QNT(qnt_rp, "rp", "particle radius", "microns")
4879 SET_QNT(qnt_rhop, "rhop", "particle density", "kg/m^3")
4880 SET_QNT(qnt_ps, "ps", "surface pressure", "hPa")
4881 SET_QNT(qnt_ts, "ts", "surface temperature", "K")
4882 SET_QNT(qnt_zs, "zs", "surface height", "km")
4883 SET_QNT(qnt_us, "us", "surface zonal wind", "m/s")
4884 SET_QNT(qnt_vs, "vs", "surface meridional wind", "m/s")
4885 SET_QNT(qnt_lsm, "lsm", "land-sea mask", "1")
4886 SET_QNT(qnt_sst, "sst", "sea surface temperature", "K")
4887 SET_QNT(qnt_pbl, "pbl", "planetary boundary layer", "hPa")
4888 SET_QNT(qnt_pt, "pt", "tropopause pressure", "hPa")
4889 SET_QNT(qnt_tt, "tt", "tropopause temperature", "K")
4890 SET_QNT(qnt_zt, "zt", "tropopause geopotential height", "km")
4891 SET_QNT(qnt_h2ot, "h2ot", "tropopause water vapor", "ppv")
4892 SET_QNT(qnt_zg, "zg", "geopotential height", "km")
4893 SET_QNT(qnt_p, "p", "pressure", "hPa")
4894 SET_QNT(qnt_t, "t", "temperature", "K")
4895 SET_QNT(qnt_rho, "rho", "air density", "kg/m^3")
4896 SET_QNT(qnt_u, "u", "zonal wind", "m/s")
4897 SET_QNT(qnt_v, "v", "meridional wind", "m/s")
4898 SET_QNT(qnt_w, "w", "vertical velocity", "hPa/s")
4899 SET_QNT(qnt_h2o, "h2o", "water vapor", "ppv")
4900 SET_QNT(qnt_o3, "o3", "ozone", "ppv")
4901 SET_QNT(qnt_lwc, "lwc", "cloud liquid water content", "kg/kg")
4902 SET_QNT(qnt_rwc, "rwc", "cloud rain water content", "kg/kg")
4903 SET_QNT(qnt_iwc, "iwc", "cloud ice water content", "kg/kg")
4904 SET_QNT(qnt_swc, "iwc", "cloud snow water content", "kg/kg")
4905 SET_QNT(qnt_cc, "cc", "cloud cover", "1")
4906 SET_QNT(qnt_pct, "pct", "cloud top pressure", "hPa")
4907 SET_QNT(qnt_pcb, "pcb", "cloud bottom pressure", "hPa")
4908 SET_QNT(qnt_cl, "cl", "total column cloud water", "kg/m^2")
4909 SET_QNT(qnt_plcl, "plcl", "lifted condensation level", "hPa")
4910 SET_QNT(qnt_plfc, "plfc", "level of free convection", "hPa")
4911 SET_QNT(qnt_pel, "pel", "equilibrium level", "hPa")
4912 SET_QNT(qnt_cape, "cape", "convective available potential energy",
4913 "J/kg")
4914 SET_QNT(qnt_cin, "cin", "convective inhibition", "J/kg")
4915 SET_QNT(qnt_o3c, "o3c", "total column ozone", "DU")
4916 SET_QNT(qnt_hno3, "hno3", "nitric acid", "ppv")
4917 SET_QNT(qnt_oh, "oh", "hydroxyl radical", "ppv")
4918 SET_QNT(qnt_h2o2, "h2o2", "hydrogen peroxide", "ppv")
4919 SET_QNT(qnt_ho2, "ho2", "hydroperoxyl radical", "ppv")
4920 SET_QNT(qnt_o1d, "o1d", "atomic oxygen", "ppv")
4921 SET_QNT(qnt_mloss_oh, "mloss_oh", "mass loss due to OH chemistry", "kg")
4922 SET_QNT(qnt_mloss_h2o2, "mloss_h2o2", "mass loss due to H2O2 chemistry",
4923 "kg")
4924 SET_QNT(qnt_mloss_kpp, "mloss_kpp", "mass loss due to kpp chemistry",
4925 "kg")
4926 SET_QNT(qnt_mloss_wet, "mloss_wet", "mass loss due to wet deposition",
4927 "kg")
4928 SET_QNT(qnt_mloss_dry, "mloss_dry", "mass loss due to dry deposition",
4929 "kg")
4930 SET_QNT(qnt_mloss_decay, "mloss_decay",
4931 "mass loss due to exponential decay", "kg")
4932 SET_QNT(qnt_loss_rate, "loss_rate", "total loss rate", "s^-1")
4933 SET_QNT(qnt_psat, "psat", "saturation pressure over water", "hPa")
4934 SET_QNT(qnt_psice, "psice", "saturation pressure over ice", "hPa")
4935 SET_QNT(qnt_pw, "pw", "partial water vapor pressure", "hPa")
4936 SET_QNT(qnt_sh, "sh", "specific humidity", "kg/kg")
4937 SET_QNT(qnt_rh, "rh", "relative humidity", "%%")
4938 SET_QNT(qnt_rhice, "rhice", "relative humidity over ice", "%%")
4939 SET_QNT(qnt_theta, "theta", "potential temperature", "K")
4940 SET_QNT(qnt_zeta, "zeta", "zeta coordinate", "K")
4941 SET_QNT(qnt_zeta_d, "zeta_d", "diagnosed zeta coordinate", "K")
4942 SET_QNT(qnt_tvirt, "tvirt", "virtual temperature", "K")
4943 SET_QNT(qnt_lapse, "lapse", "temperature lapse rate", "K/km")
4944 SET_QNT(qnt_vh, "vh", "horizontal velocity", "m/s")
4945 SET_QNT(qnt_vz, "vz", "vertical velocity", "m/s")
4946 SET_QNT(qnt_pv, "pv", "potential vorticity", "PVU")
4947 SET_QNT(qnt_tdew, "tdew", "dew point temperature", "K")
4948 SET_QNT(qnt_tice, "tice", "frost point temperature", "K")
4949 SET_QNT(qnt_tsts, "tsts", "STS existence temperature", "K")
4950 SET_QNT(qnt_tnat, "tnat", "NAT existence temperature", "K")
4951 SET_QNT(qnt_Cx, "Cx", "Trace species x volume mixing ratio", "ppv")
4952 SET_QNT(qnt_Ch2o, "Ch2o", "H2O volume mixing ratio", "ppv")
4953 SET_QNT(qnt_Co3, "Co3", "O3 volume mixing ratio", "ppv")
4954 SET_QNT(qnt_Cco, "Cco", "CO volume mixing ratio", "ppv")
4955 SET_QNT(qnt_Coh, "Coh", "HO volume mixing ratio", "ppv")
4956 SET_QNT(qnt_Ch, "Ch", "H radical volume mixing ratio", "ppv")
4957 SET_QNT(qnt_Cho2, "Cho2", "HO2 volume mixing ratio", "ppv")
4958 SET_QNT(qnt_Ch2o2, "Ch2o2", "H2O2 volume mixing ratio", "ppv")
4959 SET_QNT(qnt_Co1d, "Co1d", "O(1D) volume mixing ratio", "ppv")
4960 SET_QNT(qnt_Co3p, "Co3p", "O(3P) radical volume mixing ratio", "ppv")
4961 SET_QNT(qnt_Cccl4, "Cccl4", "CCl4 (CFC-10) volume mixing ratio", "ppv")
4962 SET_QNT(qnt_Cccl3f, "Cccl3f", "CCl3F (CFC-11) volume mixing ratio",
4963 "ppv")
4964 SET_QNT(qnt_Cccl2f2, "Cccl2f2", "CCl2F2 (CFC-12) volume mixing ratio",
4965 "ppv")
4966 SET_QNT(qnt_Cn2o, "Cn2o", "N2O volume mixing ratio", "ppv")
4967 SET_QNT(qnt_Csf6, "Csf6", "SF6 volume mixing ratio", "ppv")
4968 SET_QNT(qnt_aoa, "aoa", "age of air", "s")
4969 scan_ctl(filename, argc, argv, "QNT_UNIT", iq, "", ctl->qnt_unit[iq]);
4970 }
4971
4972 /* Vertical coordinates and velocities... */
4973 ctl->advect_vert_coord =
4974 (int) scan_ctl(filename, argc, argv, "ADVECT_VERT_COORD", -1, "0", NULL);
4975 if (ctl->advect_vert_coord < 0 || ctl->advect_vert_coord > 2)
4976 ERRMSG("Set advect_vert_coord to 0, 1, or 2!");
4977 if (ctl->advect_vert_coord == 1 && ctl->qnt_zeta < 0)
4978 ERRMSG("Please add zeta to your quantities for diabatic calculations!");
4979 ctl->met_vert_coord =
4980 (int) scan_ctl(filename, argc, argv, "MET_VERT_COORD", -1, "0", NULL);
4981 if (ctl->advect_vert_coord == 2 && ctl->met_vert_coord != 1)
4982 ERRMSG
4983 ("Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
4984 ctl->met_clams =
4985 (int) scan_ctl(filename, argc, argv, "MET_CLAMS", -1, "0", NULL);
4986 ctl->advect_cpl_zeta_and_press_modules =
4987 (int) scan_ctl(filename, argc, argv, "ADVECT_ZETA_PRESS_MODULES", -1, "1",
4988 NULL);
4989
4990 /* Time steps of simulation... */
4991 ctl->direction =
4992 (int) scan_ctl(filename, argc, argv, "DIRECTION", -1, "1", NULL);
4993 if (ctl->direction != -1 && ctl->direction != 1)
4994 ERRMSG("Set DIRECTION to -1 or 1!");
4995 ctl->t_stop = scan_ctl(filename, argc, argv, "T_STOP", -1, "1e100", NULL);
4996 ctl->dt_mod = scan_ctl(filename, argc, argv, "DT_MOD", -1, "180", NULL);
4997
4998 /* Meteo data... */
4999 scan_ctl(filename, argc, argv, "METBASE", -1, "-", ctl->metbase);
5000 ctl->dt_met = scan_ctl(filename, argc, argv, "DT_MET", -1, "3600", NULL);
5001 ctl->met_convention =
5002 (int) scan_ctl(filename, argc, argv, "MET_CONVENTION", -1, "0", NULL);
5003 ctl->met_type =
5004 (int) scan_ctl(filename, argc, argv, "MET_TYPE", -1, "0", NULL);
5005 if (ctl->advect_vert_coord == 1 && ctl->met_type != 0)
5006 ERRMSG
5007 ("Please use meteorological files in netcdf format for diabatic calculations.");
5008 ctl->met_nc_scale =
5009 (int) scan_ctl(filename, argc, argv, "MET_NC_SCALE", -1, "1", NULL);
5010 ctl->met_zfp_prec =
5011 (int) scan_ctl(filename, argc, argv, "MET_ZFP_PREC", -1, "8", NULL);
5012 ctl->met_zfp_tol_t =
5013 scan_ctl(filename, argc, argv, "MET_ZFP_TOL_T", -1, "5.0", NULL);
5014 ctl->met_zfp_tol_z =
5015 scan_ctl(filename, argc, argv, "MET_ZFP_TOL_Z", -1, "0.5", NULL);
5016 ctl->met_cms_heur =
5017 (int) scan_ctl(filename, argc, argv, "MET_CMS_HEUR", -1, "1", NULL);
5018 ctl->met_cms_eps_z =
5019 scan_ctl(filename, argc, argv, "MET_CMS_EPS_Z", -1, "3.0", NULL);
5020 ctl->met_cms_eps_t =
5021 scan_ctl(filename, argc, argv, "MET_CMS_EPS_T", -1, "3.0", NULL);
5022 ctl->met_cms_eps_u =
5023 scan_ctl(filename, argc, argv, "MET_CMS_EPS_U", -1, "3.0", NULL);
5024 ctl->met_cms_eps_v =
5025 scan_ctl(filename, argc, argv, "MET_CMS_EPS_V", -1, "3.0", NULL);
5026 ctl->met_cms_eps_w =
5027 scan_ctl(filename, argc, argv, "MET_CMS_EPS_W", -1, "3.0", NULL);
5028 ctl->met_cms_eps_pv =
5029 scan_ctl(filename, argc, argv, "MET_CMS_EPS_PV", -1, "3.0", NULL);
5030 ctl->met_cms_eps_h2o =
5031 scan_ctl(filename, argc, argv, "MET_CMS_EPS_H2O", -1, "3.0", NULL);
5032 ctl->met_cms_eps_o3 =
5033 scan_ctl(filename, argc, argv, "MET_CMS_EPS_O3", -1, "3.0", NULL);
5034 ctl->met_cms_eps_lwc =
5035 scan_ctl(filename, argc, argv, "MET_CMS_EPS_LWC", -1, "3.0", NULL);
5036 ctl->met_cms_eps_rwc =
5037 scan_ctl(filename, argc, argv, "MET_CMS_EPS_RWC", -1, "3.0", NULL);
5038 ctl->met_cms_eps_iwc =
5039 scan_ctl(filename, argc, argv, "MET_CMS_EPS_IWC", -1, "3.0", NULL);
5040 ctl->met_cms_eps_swc =
5041 scan_ctl(filename, argc, argv, "MET_CMS_EPS_SWC", -1, "3.0", NULL);
5042 ctl->met_cms_eps_cc =
5043 scan_ctl(filename, argc, argv, "MET_CMS_EPS_CC", -1, "3.0", NULL);
5044 ctl->met_dx = (int) scan_ctl(filename, argc, argv, "MET_DX", -1, "1", NULL);
5045 ctl->met_dy = (int) scan_ctl(filename, argc, argv, "MET_DY", -1, "1", NULL);
5046 ctl->met_dp = (int) scan_ctl(filename, argc, argv, "MET_DP", -1, "1", NULL);
5047 if (ctl->met_dx < 1 || ctl->met_dy < 1 || ctl->met_dp < 1)
5048 ERRMSG("MET_DX, MET_DY, and MET_DP need to be greater than zero!");
5049 ctl->met_sx = (int) scan_ctl(filename, argc, argv, "MET_SX", -1, "1", NULL);
5050 ctl->met_sy = (int) scan_ctl(filename, argc, argv, "MET_SY", -1, "1", NULL);
5051 ctl->met_sp = (int) scan_ctl(filename, argc, argv, "MET_SP", -1, "1", NULL);
5052 if (ctl->met_sx < 1 || ctl->met_sy < 1 || ctl->met_sp < 1)
5053 ERRMSG("MET_SX, MET_SY, and MET_SP need to be greater than zero!");
5054 ctl->met_detrend =
5055 scan_ctl(filename, argc, argv, "MET_DETREND", -1, "-999", NULL);
5056 ctl->met_np = (int) scan_ctl(filename, argc, argv, "MET_NP", -1, "0", NULL);
5057 if (ctl->met_np > EP)
5058 ERRMSG("Too many levels!");
5059 ctl->met_press_level_def =
5060 (int) scan_ctl(filename, argc, argv, "MET_PRESS_LEVEL_DEF", -1, "-1",
5061 NULL);
5062 if (ctl->met_press_level_def >= 0) {
5063 level_definitions(ctl);
5064 } else {
5065 if (ctl->met_np > 0) {
5066 for (int ip = 0; ip < ctl->met_np; ip++)
5067 ctl->met_p[ip] =
5068 scan_ctl(filename, argc, argv, "MET_P", ip, "", NULL);
5069 }
5070 }
5071 ctl->met_geopot_sx
5072 = (int) scan_ctl(filename, argc, argv, "MET_GEOPOT_SX", -1, "-1", NULL);
5073 ctl->met_geopot_sy
5074 = (int) scan_ctl(filename, argc, argv, "MET_GEOPOT_SY", -1, "-1", NULL);
5075 ctl->met_relhum
5076 = (int) scan_ctl(filename, argc, argv, "MET_RELHUM", -1, "0", NULL);
5077 ctl->met_tropo =
5078 (int) scan_ctl(filename, argc, argv, "MET_TROPO", -1, "3", NULL);
5079 if (ctl->met_tropo < 0 || ctl->met_tropo > 5)
5080 ERRMSG("Set MET_TROPO = 0 ... 5!");
5081 ctl->met_tropo_pv =
5082 scan_ctl(filename, argc, argv, "MET_TROPO_PV", -1, "3.5", NULL);
5083 ctl->met_tropo_theta =
5084 scan_ctl(filename, argc, argv, "MET_TROPO_THETA", -1, "380", NULL);
5085 ctl->met_tropo_spline =
5086 (int) scan_ctl(filename, argc, argv, "MET_TROPO_SPLINE", -1, "1", NULL);
5087 ctl->met_dt_out =
5088 scan_ctl(filename, argc, argv, "MET_DT_OUT", -1, "0.1", NULL);
5089 ctl->met_cache =
5090 (int) scan_ctl(filename, argc, argv, "MET_CACHE", -1, "0", NULL);
5091 ctl->met_mpi_share =
5092 (int) scan_ctl(filename, argc, argv, "MET_MPI_SHARE", -1, "0", NULL);
5093
5094 /* Sorting... */
5095 ctl->sort_dt = scan_ctl(filename, argc, argv, "SORT_DT", -1, "-999", NULL);
5096
5097 /* Isosurface parameters... */
5098 ctl->isosurf =
5099 (int) scan_ctl(filename, argc, argv, "ISOSURF", -1, "0", NULL);
5100 scan_ctl(filename, argc, argv, "BALLOON", -1, "-", ctl->balloon);
5101
5102 /* Random number generator... */
5103 ctl->rng_type =
5104 (int) scan_ctl(filename, argc, argv, "RNG_TYPE", -1, "0", NULL);
5105 if (ctl->rng_type < 0 || ctl->rng_type > 2)
5106 ERRMSG("Set RNG_TYPE to 0, 1, or 2!");
5107
5108 /* Advection parameters... */
5109 ctl->advect = (int) scan_ctl(filename, argc, argv, "ADVECT", -1, "2", NULL);
5110 if (!(ctl->advect == 0 || ctl->advect == 1
5111 || ctl->advect == 2 || ctl->advect == 4))
5112 ERRMSG("Set ADVECT to 0, 1, 2, or 4!");
5113 ctl->reflect =
5114 (int) scan_ctl(filename, argc, argv, "REFLECT", -1, "0", NULL);
5115
5116 /* Diffusion parameters... */
5117 ctl->turb_dx_trop =
5118 scan_ctl(filename, argc, argv, "TURB_DX_TROP", -1, "50", NULL);
5119 ctl->turb_dx_strat =
5120 scan_ctl(filename, argc, argv, "TURB_DX_STRAT", -1, "0", NULL);
5121 ctl->turb_dz_trop =
5122 scan_ctl(filename, argc, argv, "TURB_DZ_TROP", -1, "0", NULL);
5123 ctl->turb_dz_strat =
5124 scan_ctl(filename, argc, argv, "TURB_DZ_STRAT", -1, "0.1", NULL);
5125 ctl->turb_mesox =
5126 scan_ctl(filename, argc, argv, "TURB_MESOX", -1, "0.16", NULL);
5127 ctl->turb_mesoz =
5128 scan_ctl(filename, argc, argv, "TURB_MESOZ", -1, "0.16", NULL);
5129
5130 /* Convection... */
5131 ctl->conv_cape
5132 = scan_ctl(filename, argc, argv, "CONV_CAPE", -1, "-999", NULL);
5133 ctl->conv_cin
5134 = scan_ctl(filename, argc, argv, "CONV_CIN", -1, "-999", NULL);
5135 ctl->conv_dt = scan_ctl(filename, argc, argv, "CONV_DT", -1, "-999", NULL);
5136 ctl->conv_mix_bot
5137 = (int) scan_ctl(filename, argc, argv, "CONV_MIX_BOT", -1, "1", NULL);
5138 ctl->conv_mix_top
5139 = (int) scan_ctl(filename, argc, argv, "CONV_MIX_TOP", -1, "1", NULL);
5140
5141 /* Boundary conditions... */
5142 ctl->bound_mass =
5143 scan_ctl(filename, argc, argv, "BOUND_MASS", -1, "-999", NULL);
5144 ctl->bound_mass_trend =
5145 scan_ctl(filename, argc, argv, "BOUND_MASS_TREND", -1, "0", NULL);
5146 ctl->bound_vmr =
5147 scan_ctl(filename, argc, argv, "BOUND_VMR", -1, "-999", NULL);
5148 ctl->bound_vmr_trend =
5149 scan_ctl(filename, argc, argv, "BOUND_VMR_TREND", -1, "0", NULL);
5150 ctl->bound_lat0 =
5151 scan_ctl(filename, argc, argv, "BOUND_LAT0", -1, "-999", NULL);
5152 ctl->bound_lat1 =
5153 scan_ctl(filename, argc, argv, "BOUND_LAT1", -1, "-999", NULL);
5154 ctl->bound_p0 =
5155 scan_ctl(filename, argc, argv, "BOUND_P0", -1, "-999", NULL);
5156 ctl->bound_p1 =
5157 scan_ctl(filename, argc, argv, "BOUND_P1", -1, "-999", NULL);
5158 ctl->bound_dps =
5159 scan_ctl(filename, argc, argv, "BOUND_DPS", -1, "-999", NULL);
5160 ctl->bound_dzs =
5161 scan_ctl(filename, argc, argv, "BOUND_DZS", -1, "-999", NULL);
5162 ctl->bound_zetas =
5163 scan_ctl(filename, argc, argv, "BOUND_ZETAS", -1, "-999", NULL);
5164 ctl->bound_pbl =
5165 (int) scan_ctl(filename, argc, argv, "BOUND_PBL", -1, "0", NULL);
5166
5167 /* Species parameters... */
5168 scan_ctl(filename, argc, argv, "SPECIES", -1, "-", ctl->species);
5169 if (strcasecmp(ctl->species, "CF2Cl2") == 0) {
5170 ctl->molmass = 120.907;
5171 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 3e-5;
5172 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3500.0;
5173 } else if (strcasecmp(ctl->species, "CFCl3") == 0) {
5174 ctl->molmass = 137.359;
5175 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.1e-4;
5176 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3300.0;
5177 } else if (strcasecmp(ctl->species, "CH4") == 0) {
5178 ctl->molmass = 16.043;
5179 ctl->oh_chem_reaction = 2;
5180 ctl->oh_chem[0] = 2.45e-12;
5181 ctl->oh_chem[1] = 1775;
5182 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.4e-5;
5183 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1600.0;
5184 } else if (strcasecmp(ctl->species, "CO") == 0) {
5185 ctl->molmass = 28.01;
5186 ctl->oh_chem_reaction = 3;
5187 ctl->oh_chem[0] = 6.9e-33;
5188 ctl->oh_chem[1] = 2.1;
5189 ctl->oh_chem[2] = 1.1e-12;
5190 ctl->oh_chem[3] = -1.3;
5191 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 9.7e-6;
5192 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1300.0;
5193 } else if (strcasecmp(ctl->species, "CO2") == 0) {
5194 ctl->molmass = 44.009;
5195 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 3.3e-4;
5196 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2400.0;
5197 } else if (strcasecmp(ctl->species, "H2O") == 0) {
5198 ctl->molmass = 18.01528;
5199 } else if (strcasecmp(ctl->species, "N2O") == 0) {
5200 ctl->molmass = 44.013;
5201 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.4e-4;
5202 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2600.;
5203 } else if (strcasecmp(ctl->species, "NH3") == 0) {
5204 ctl->molmass = 17.031;
5205 ctl->oh_chem_reaction = 2;
5206 ctl->oh_chem[0] = 1.7e-12;
5207 ctl->oh_chem[1] = 710;
5208 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 5.9e-1;
5209 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 4200.0;
5210 } else if (strcasecmp(ctl->species, "HNO3") == 0) {
5211 ctl->molmass = 63.012;
5212 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.1e3;
5213 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 8700.0;
5214 } else if (strcasecmp(ctl->species, "NO") == 0) {
5215 ctl->molmass = 30.006;
5216 ctl->oh_chem_reaction = 3;
5217 ctl->oh_chem[0] = 7.1e-31;
5218 ctl->oh_chem[1] = 2.6;
5219 ctl->oh_chem[2] = 3.6e-11;
5220 ctl->oh_chem[3] = 0.1;
5221 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.9e-5;
5222 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1600.0;
5223 } else if (strcasecmp(ctl->species, "NO2") == 0) {
5224 ctl->molmass = 46.005;
5225 ctl->oh_chem_reaction = 3;
5226 ctl->oh_chem[0] = 1.8e-30;
5227 ctl->oh_chem[1] = 3.0;
5228 ctl->oh_chem[2] = 2.8e-11;
5229 ctl->oh_chem[3] = 0.0;
5230 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.2e-4;
5231 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2400.0;
5232 } else if (strcasecmp(ctl->species, "O3") == 0) {
5233 ctl->molmass = 47.997;
5234 ctl->oh_chem_reaction = 2;
5235 ctl->oh_chem[0] = 1.7e-12;
5236 ctl->oh_chem[1] = 940;
5237 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1e-4;
5238 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2800.0;
5239 } else if (strcasecmp(ctl->species, "SF6") == 0) {
5240 ctl->molmass = 146.048;
5241 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.4e-6;
5242 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3100.0;
5243 } else if (strcasecmp(ctl->species, "SO2") == 0) {
5244 ctl->molmass = 64.066;
5245 ctl->oh_chem_reaction = 3;
5246 ctl->oh_chem[0] = 2.9e-31;
5247 ctl->oh_chem[1] = 4.1;
5248 ctl->oh_chem[2] = 1.7e-12;
5249 ctl->oh_chem[3] = -0.2;
5250 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.3e-2;
5251 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2900.0;
5252 }
5253
5254 /* Molar mass... */
5255 char defstr[LEN];
5256 sprintf(defstr, "%g", ctl->molmass);
5257 ctl->molmass = scan_ctl(filename, argc, argv, "MOLMASS", -1, defstr, NULL);
5258
5259 /* OH chemistry... */
5260 sprintf(defstr, "%d", ctl->oh_chem_reaction);
5261 ctl->oh_chem_reaction =
5262 (int) scan_ctl(filename, argc, argv, "OH_CHEM_REACTION", -1, defstr,
5263 NULL);
5264 for (int ip = 0; ip < 4; ip++) {
5265 sprintf(defstr, "%g", ctl->oh_chem[ip]);
5266 ctl->oh_chem[ip] =
5267 scan_ctl(filename, argc, argv, "OH_CHEM", ip, defstr, NULL);
5268 }
5269 ctl->oh_chem_beta =
5270 scan_ctl(filename, argc, argv, "OH_CHEM_BETA", -1, "0", NULL);
5271
5272 /* H2O2 chemistry... */
5273 ctl->h2o2_chem_reaction =
5274 (int) scan_ctl(filename, argc, argv, "H2O2_CHEM_REACTION", -1, "0", NULL);
5275
5276 /* KPP chemistry... */
5277 ctl->kpp_chem =
5278 (int) scan_ctl(filename, argc, argv, "KPP_CHEM", -1, "0", NULL);
5279 ctl->dt_kpp = scan_ctl(filename, argc, argv, "DT_KPP", -1, "1800", NULL);
5280
5281 /* First order tracer chemistry... */
5282 ctl->tracer_chem =
5283 (int) scan_ctl(filename, argc, argv, "TRACER_CHEM", -1, "0", NULL);
5284
5285 /* Wet deposition... */
5286 for (int ip = 0; ip < 3; ip++) {
5287 sprintf(defstr, "%g", ctl->wet_depo_ic_h[ip]);
5288 ctl->wet_depo_ic_h[ip] =
5289 scan_ctl(filename, argc, argv, "WET_DEPO_IC_H", ip, defstr, NULL);
5290 }
5291 for (int ip = 0; ip < 1; ip++) {
5292 sprintf(defstr, "%g", ctl->wet_depo_bc_h[ip]);
5293 ctl->wet_depo_bc_h[ip] =
5294 scan_ctl(filename, argc, argv, "WET_DEPO_BC_H", ip, defstr, NULL);
5295 }
5296 ctl->wet_depo_ic_a =
5297 scan_ctl(filename, argc, argv, "WET_DEPO_IC_A", -1, "0", NULL);
5298 ctl->wet_depo_ic_b =
5299 scan_ctl(filename, argc, argv, "WET_DEPO_IC_B", -1, "0", NULL);
5300 ctl->wet_depo_bc_a =
5301 scan_ctl(filename, argc, argv, "WET_DEPO_BC_A", -1, "0", NULL);
5302 ctl->wet_depo_bc_b =
5303 scan_ctl(filename, argc, argv, "WET_DEPO_BC_B", -1, "0", NULL);
5304 ctl->wet_depo_pre[0] =
5305 scan_ctl(filename, argc, argv, "WET_DEPO_PRE", 0, "0.5", NULL);
5306 ctl->wet_depo_pre[1] =
5307 scan_ctl(filename, argc, argv, "WET_DEPO_PRE", 1, "0.36", NULL);
5309 scan_ctl(filename, argc, argv, "WET_DEPO_IC_RET_RATIO", -1, "1", NULL);
5311 scan_ctl(filename, argc, argv, "WET_DEPO_BC_RET_RATIO", -1, "1", NULL);
5312
5313 /* Dry deposition... */
5314 ctl->dry_depo_vdep =
5315 scan_ctl(filename, argc, argv, "DRY_DEPO_VDEP", -1, "0", NULL);
5316 ctl->dry_depo_dp =
5317 scan_ctl(filename, argc, argv, "DRY_DEPO_DP", -1, "30", NULL);
5318
5319 /* Climatological data... */
5320 scan_ctl(filename, argc, argv, "CLIM_PHOTO", -1,
5321 "../../data/clams_photolysis_rates.nc", ctl->clim_photo);
5322 scan_ctl(filename, argc, argv, "CLIM_HNO3_FILENAME", -1,
5323 "../../data/gozcards_HNO3.nc", ctl->clim_hno3_filename);
5324 scan_ctl(filename, argc, argv, "CLIM_OH_FILENAME", -1,
5325 "../../data/clams_radical_species_vmr.nc", ctl->clim_oh_filename);
5326 scan_ctl(filename, argc, argv, "CLIM_H2O2_FILENAME", -1,
5327 "../../data/cams_H2O2.nc", ctl->clim_h2o2_filename);
5328 scan_ctl(filename, argc, argv, "CLIM_HO2_FILENAME", -1,
5329 "../../data/clams_radical_species_vmr.nc", ctl->clim_ho2_filename);
5330 scan_ctl(filename, argc, argv, "CLIM_O1D_FILENAME", -1,
5331 "../../data/clams_radical_species_vmr.nc", ctl->clim_o1d_filename);
5332 scan_ctl(filename, argc, argv, "CLIM_CCL4_TIMESERIES", -1,
5333 "../../data/noaa_gml_ccl4.tab", ctl->clim_ccl4_timeseries);
5334 scan_ctl(filename, argc, argv, "CLIM_CCL3F_TIMESERIES", -1,
5335 "../../data/noaa_gml_cfc11.tab", ctl->clim_ccl3f_timeseries);
5336 scan_ctl(filename, argc, argv, "CLIM_CCL2F2_TIMESERIES", -1,
5337 "../../data/noaa_gml_cfc12.tab", ctl->clim_ccl2f2_timeseries);
5338 scan_ctl(filename, argc, argv, "CLIM_N2O_TIMESERIES", -1,
5339 "../../data/noaa_gml_n2o.tab", ctl->clim_n2o_timeseries);
5340 scan_ctl(filename, argc, argv, "CLIM_SF6_TIMESERIES", -1,
5341 "../../data/noaa_gml_sf6.tab", ctl->clim_sf6_timeseries);
5342
5343 /* Mixing... */
5344 ctl->mixing_dt =
5345 scan_ctl(filename, argc, argv, "MIXING_DT", -1, "3600.", NULL);
5346 ctl->mixing_trop =
5347 scan_ctl(filename, argc, argv, "MIXING_TROP", -1, "-999", NULL);
5348 ctl->mixing_strat =
5349 scan_ctl(filename, argc, argv, "MIXING_STRAT", -1, "-999", NULL);
5350 ctl->mixing_z0 =
5351 scan_ctl(filename, argc, argv, "MIXING_Z0", -1, "-5", NULL);
5352 ctl->mixing_z1 =
5353 scan_ctl(filename, argc, argv, "MIXING_Z1", -1, "85", NULL);
5354 ctl->mixing_nz =
5355 (int) scan_ctl(filename, argc, argv, "MIXING_NZ", -1, "90", NULL);
5356 ctl->mixing_lon0 =
5357 scan_ctl(filename, argc, argv, "MIXING_LON0", -1, "-180", NULL);
5358 ctl->mixing_lon1 =
5359 scan_ctl(filename, argc, argv, "MIXING_LON1", -1, "180", NULL);
5360 ctl->mixing_nx =
5361 (int) scan_ctl(filename, argc, argv, "MIXING_NX", -1, "360", NULL);
5362 ctl->mixing_lat0 =
5363 scan_ctl(filename, argc, argv, "MIXING_LAT0", -1, "-90", NULL);
5364 ctl->mixing_lat1 =
5365 scan_ctl(filename, argc, argv, "MIXING_LAT1", -1, "90", NULL);
5366 ctl->mixing_ny =
5367 (int) scan_ctl(filename, argc, argv, "MIXING_NY", -1, "180", NULL);
5368
5369 /* Chemistry grid... */
5370 ctl->chemgrid_z0 =
5371 scan_ctl(filename, argc, argv, "CHEMGRID_Z0", -1, "-5", NULL);
5372 ctl->chemgrid_z1 =
5373 scan_ctl(filename, argc, argv, "CHEMGRID_Z1", -1, "85", NULL);
5374 ctl->chemgrid_nz =
5375 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NZ", -1, "90", NULL);
5376 ctl->chemgrid_lon0 =
5377 scan_ctl(filename, argc, argv, "CHEMGRID_LON0", -1, "-180", NULL);
5378 ctl->chemgrid_lon1 =
5379 scan_ctl(filename, argc, argv, "CHEMGRID_LON1", -1, "180", NULL);
5380 ctl->chemgrid_nx =
5381 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NX", -1, "360", NULL);
5382 ctl->chemgrid_lat0 =
5383 scan_ctl(filename, argc, argv, "CHEMGRID_LAT0", -1, "-90", NULL);
5384 ctl->chemgrid_lat1 =
5385 scan_ctl(filename, argc, argv, "CHEMGRID_LAT1", -1, "90", NULL);
5386 ctl->chemgrid_ny =
5387 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NY", -1, "180", NULL);
5388
5389 /* Exponential decay... */
5390 ctl->tdec_trop = scan_ctl(filename, argc, argv, "TDEC_TROP", -1, "0", NULL);
5391 ctl->tdec_strat
5392 = scan_ctl(filename, argc, argv, "TDEC_STRAT", -1, "0", NULL);
5393
5394 /* PSC analysis... */
5395 ctl->psc_h2o = scan_ctl(filename, argc, argv, "PSC_H2O", -1, "4e-6", NULL);
5396 ctl->psc_hno3 =
5397 scan_ctl(filename, argc, argv, "PSC_HNO3", -1, "9e-9", NULL);
5398
5399 /* Output of atmospheric data... */
5400 scan_ctl(filename, argc, argv, "ATM_BASENAME", -1, "-", ctl->atm_basename);
5401 scan_ctl(filename, argc, argv, "ATM_GPFILE", -1, "-", ctl->atm_gpfile);
5402 ctl->atm_dt_out =
5403 scan_ctl(filename, argc, argv, "ATM_DT_OUT", -1, "86400", NULL);
5404 ctl->atm_filter =
5405 (int) scan_ctl(filename, argc, argv, "ATM_FILTER", -1, "0", NULL);
5406 ctl->atm_stride =
5407 (int) scan_ctl(filename, argc, argv, "ATM_STRIDE", -1, "1", NULL);
5408 ctl->atm_type =
5409 (int) scan_ctl(filename, argc, argv, "ATM_TYPE", -1, "0", NULL);
5410 ctl->atm_type_out =
5411 (int) scan_ctl(filename, argc, argv, "ATM_TYPE_OUT", -1, "-1", NULL);
5412 if (ctl->atm_type_out == -1)
5413 ctl->atm_type_out = ctl->atm_type;
5414 ctl->obs_type =
5415 (int) scan_ctl(filename, argc, argv, "OBS_TYPE", -1, "0", NULL);
5416
5417 /* Output of CSI data... */
5418 scan_ctl(filename, argc, argv, "CSI_BASENAME", -1, "-", ctl->csi_basename);
5419 scan_ctl(filename, argc, argv, "CSI_KERNEL", -1, "-", ctl->csi_kernel);
5420 ctl->csi_dt_out =
5421 scan_ctl(filename, argc, argv, "CSI_DT_OUT", -1, "86400", NULL);
5422 scan_ctl(filename, argc, argv, "CSI_OBSFILE", -1, "-", ctl->csi_obsfile);
5423 ctl->csi_obsmin =
5424 scan_ctl(filename, argc, argv, "CSI_OBSMIN", -1, "0", NULL);
5425 ctl->csi_modmin =
5426 scan_ctl(filename, argc, argv, "CSI_MODMIN", -1, "0", NULL);
5427 ctl->csi_z0 = scan_ctl(filename, argc, argv, "CSI_Z0", -1, "-5", NULL);
5428 ctl->csi_z1 = scan_ctl(filename, argc, argv, "CSI_Z1", -1, "85", NULL);
5429 ctl->csi_nz = (int) scan_ctl(filename, argc, argv, "CSI_NZ", -1, "1", NULL);
5430 ctl->csi_lon0 =
5431 scan_ctl(filename, argc, argv, "CSI_LON0", -1, "-180", NULL);
5432 ctl->csi_lon1 = scan_ctl(filename, argc, argv, "CSI_LON1", -1, "180", NULL);
5433 ctl->csi_nx =
5434 (int) scan_ctl(filename, argc, argv, "CSI_NX", -1, "360", NULL);
5435 ctl->csi_lat0 = scan_ctl(filename, argc, argv, "CSI_LAT0", -1, "-90", NULL);
5436 ctl->csi_lat1 = scan_ctl(filename, argc, argv, "CSI_LAT1", -1, "90", NULL);
5437 ctl->csi_ny =
5438 (int) scan_ctl(filename, argc, argv, "CSI_NY", -1, "180", NULL);
5439
5440 /* Output of ensemble data... */
5441 scan_ctl(filename, argc, argv, "ENS_BASENAME", -1, "-", ctl->ens_basename);
5442 ctl->ens_dt_out =
5443 scan_ctl(filename, argc, argv, "ENS_DT_OUT", -1, "86400", NULL);
5444
5445 /* Output of grid data... */
5446 scan_ctl(filename, argc, argv, "GRID_BASENAME", -1, "-",
5447 ctl->grid_basename);
5448 scan_ctl(filename, argc, argv, "GRID_KERNEL", -1, "-", ctl->grid_kernel);
5449 scan_ctl(filename, argc, argv, "GRID_GPFILE", -1, "-", ctl->grid_gpfile);
5450 ctl->grid_dt_out =
5451 scan_ctl(filename, argc, argv, "GRID_DT_OUT", -1, "86400", NULL);
5452 ctl->grid_sparse =
5453 (int) scan_ctl(filename, argc, argv, "GRID_SPARSE", -1, "0", NULL);
5454 ctl->grid_stddev =
5455 (int) scan_ctl(filename, argc, argv, "GRID_STDDEV", -1, "0", NULL);
5456 ctl->grid_z0 = scan_ctl(filename, argc, argv, "GRID_Z0", -1, "-5", NULL);
5457 ctl->grid_z1 = scan_ctl(filename, argc, argv, "GRID_Z1", -1, "85", NULL);
5458 ctl->grid_nz =
5459 (int) scan_ctl(filename, argc, argv, "GRID_NZ", -1, "1", NULL);
5460 ctl->grid_lon0 =
5461 scan_ctl(filename, argc, argv, "GRID_LON0", -1, "-180", NULL);
5462 ctl->grid_lon1 =
5463 scan_ctl(filename, argc, argv, "GRID_LON1", -1, "180", NULL);
5464 ctl->grid_nx =
5465 (int) scan_ctl(filename, argc, argv, "GRID_NX", -1, "360", NULL);
5466 ctl->grid_lat0 =
5467 scan_ctl(filename, argc, argv, "GRID_LAT0", -1, "-90", NULL);
5468 ctl->grid_lat1 =
5469 scan_ctl(filename, argc, argv, "GRID_LAT1", -1, "90", NULL);
5470 ctl->grid_ny =
5471 (int) scan_ctl(filename, argc, argv, "GRID_NY", -1, "180", NULL);
5472 ctl->grid_type =
5473 (int) scan_ctl(filename, argc, argv, "GRID_TYPE", -1, "0", NULL);
5474
5475 /* Output of profile data... */
5476 scan_ctl(filename, argc, argv, "PROF_BASENAME", -1, "-",
5477 ctl->prof_basename);
5478 scan_ctl(filename, argc, argv, "PROF_OBSFILE", -1, "-", ctl->prof_obsfile);
5479 ctl->prof_z0 = scan_ctl(filename, argc, argv, "PROF_Z0", -1, "0", NULL);
5480 ctl->prof_z1 = scan_ctl(filename, argc, argv, "PROF_Z1", -1, "60", NULL);
5481 ctl->prof_nz =
5482 (int) scan_ctl(filename, argc, argv, "PROF_NZ", -1, "60", NULL);
5483 ctl->prof_lon0 =
5484 scan_ctl(filename, argc, argv, "PROF_LON0", -1, "-180", NULL);
5485 ctl->prof_lon1 =
5486 scan_ctl(filename, argc, argv, "PROF_LON1", -1, "180", NULL);
5487 ctl->prof_nx =
5488 (int) scan_ctl(filename, argc, argv, "PROF_NX", -1, "360", NULL);
5489 ctl->prof_lat0 =
5490 scan_ctl(filename, argc, argv, "PROF_LAT0", -1, "-90", NULL);
5491 ctl->prof_lat1 =
5492 scan_ctl(filename, argc, argv, "PROF_LAT1", -1, "90", NULL);
5493 ctl->prof_ny =
5494 (int) scan_ctl(filename, argc, argv, "PROF_NY", -1, "180", NULL);
5495
5496 /* Output of sample data... */
5497 scan_ctl(filename, argc, argv, "SAMPLE_BASENAME", -1, "-",
5498 ctl->sample_basename);
5499 scan_ctl(filename, argc, argv, "SAMPLE_KERNEL", -1, "-",
5500 ctl->sample_kernel);
5501 scan_ctl(filename, argc, argv, "SAMPLE_OBSFILE", -1, "-",
5502 ctl->sample_obsfile);
5503 ctl->sample_dx =
5504 scan_ctl(filename, argc, argv, "SAMPLE_DX", -1, "50", NULL);
5505 ctl->sample_dz =
5506 scan_ctl(filename, argc, argv, "SAMPLE_DZ", -1, "-999", NULL);
5507
5508 /* Output of station data... */
5509 scan_ctl(filename, argc, argv, "STAT_BASENAME", -1, "-",
5510 ctl->stat_basename);
5511 ctl->stat_lon = scan_ctl(filename, argc, argv, "STAT_LON", -1, "0", NULL);
5512 ctl->stat_lat = scan_ctl(filename, argc, argv, "STAT_LAT", -1, "0", NULL);
5513 ctl->stat_r = scan_ctl(filename, argc, argv, "STAT_R", -1, "50", NULL);
5514 ctl->stat_t0 =
5515 scan_ctl(filename, argc, argv, "STAT_T0", -1, "-1e100", NULL);
5516 ctl->stat_t1 = scan_ctl(filename, argc, argv, "STAT_T1", -1, "1e100", NULL);
5517
5518 /* Output of VTK data... */
5519 scan_ctl(filename, argc, argv, "VTK_BASENAME", -1, "-", ctl->vtk_basename);
5520 ctl->vtk_dt_out =
5521 scan_ctl(filename, argc, argv, "VTK_DT_OUT", -1, "86400", NULL);
5522 ctl->vtk_stride =
5523 (int) scan_ctl(filename, argc, argv, "VTK_STRIDE", -1, "1", NULL);
5524 ctl->vtk_scale =
5525 scan_ctl(filename, argc, argv, "VTK_SCALE", -1, "1.0", NULL);
5526 ctl->vtk_offset =
5527 scan_ctl(filename, argc, argv, "VTK_OFFSET", -1, "0.0", NULL);
5528 ctl->vtk_sphere =
5529 (int) scan_ctl(filename, argc, argv, "VTK_SPHERE", -1, "0", NULL);
5530}
void level_definitions(ctl_t *ctl)
Defines pressure levels for meteorological data.
Definition: mptrac.c:1812
double scan_ctl(const char *filename, int argc, char *argv[], const char *varname, int arridx, const char *defvalue, char *value)
Scans a control file or command-line arguments for a specified variable.
Definition: mptrac.c:7907
#define NQ
Maximum number of quantities per data point.
Definition: mptrac.h:246
#define SET_QNT(qnt, name, longname, unit)
Set atmospheric quantity index.
Definition: mptrac.h:1488
double grid_z0
Lower altitude of gridded data [km].
Definition: mptrac.h:2946
int qnt_o3
Quantity array index for ozone volume mixing ratio.
Definition: mptrac.h:2256
double csi_lat1
Upper latitude of gridded CSI data [deg].
Definition: mptrac.h:2916
char csi_obsfile[LEN]
Observation data file for CSI analysis.
Definition: mptrac.h:2883
int qnt_pel
Quantity array index for pressure at equilibrium level (EL).
Definition: mptrac.h:2289
int csi_nz
Number of altitudes of gridded CSI data.
Definition: mptrac.h:2892
int qnt_p
Quantity array index for pressure.
Definition: mptrac.h:2235
char atm_gpfile[LEN]
Gnuplot file for atmospheric data.
Definition: mptrac.h:2850
int qnt_swc
Quantity array index for cloud snow water content.
Definition: mptrac.h:2268
double csi_obsmin
Minimum observation index to trigger detection.
Definition: mptrac.h:2886
int qnt_pcb
Quantity array index for cloud bottom pressure.
Definition: mptrac.h:2277
double csi_lon1
Upper longitude of gridded CSI data [deg].
Definition: mptrac.h:2907
int qnt_u
Quantity array index for zonal wind.
Definition: mptrac.h:2244
double stat_lon
Longitude of station [deg].
Definition: mptrac.h:3024
double sort_dt
Time step for sorting of particle data [s].
Definition: mptrac.h:2584
double stat_r
Search radius around station [km].
Definition: mptrac.h:3030
int csi_ny
Number of latitudes of gridded CSI data.
Definition: mptrac.h:2910
int vtk_sphere
Spherical projection for VTK data (0=no, 1=yes).
Definition: mptrac.h:3054
int qnt_iwc
Quantity array index for cloud ice water content.
Definition: mptrac.h:2265
int qnt_pw
Quantity array index for partial water vapor pressure.
Definition: mptrac.h:2343
char prof_basename[LEN]
Basename for profile output file.
Definition: mptrac.h:2973
double grid_z1
Upper altitude of gridded data [km].
Definition: mptrac.h:2949
double met_dt_out
Time step for sampling of meteo data along trajectories [s].
Definition: mptrac.h:2571
int qnt_h2o2
Quantity array index for H2O2 volume mixing ratio (climatology).
Definition: mptrac.h:2307
int qnt_vh
Quantity array index for horizontal wind.
Definition: mptrac.h:2370
char species[LEN]
Species.
Definition: mptrac.h:2672
int csi_nx
Number of longitudes of gridded CSI data.
Definition: mptrac.h:2901
double csi_lat0
Lower latitude of gridded CSI data [deg].
Definition: mptrac.h:2913
int qnt_lwc
Quantity array index for cloud liquid water content.
Definition: mptrac.h:2259
int grid_nx
Number of longitudes of gridded data.
Definition: mptrac.h:2952
double grid_lat0
Lower latitude of gridded data [deg].
Definition: mptrac.h:2964
int qnt_ts
Quantity array index for surface temperature.
Definition: mptrac.h:2199
int qnt_plfc
Quantity array index for pressure at level of free convection (LCF).
Definition: mptrac.h:2286
double grid_lon0
Lower longitude of gridded data [deg].
Definition: mptrac.h:2955
int qnt_o1d
Quantity array index for O(1D) volume mixing ratio (climatology).
Definition: mptrac.h:2313
int met_tropo_spline
Tropopause interpolation method (0=linear, 1=spline).
Definition: mptrac.h:2568
char sample_kernel[LEN]
Kernel data file for sample output.
Definition: mptrac.h:3009
int qnt_tvirt
Quantity array index for virtual temperature.
Definition: mptrac.h:2364
int met_geopot_sy
Latitudinal smoothing of geopotential heights.
Definition: mptrac.h:2552
char grid_gpfile[LEN]
Gnuplot file for gridded data.
Definition: mptrac.h:2931
int qnt_lsm
Quantity array index for land-sea mask.
Definition: mptrac.h:2211
int qnt_theta
Quantity array index for potential temperature.
Definition: mptrac.h:2355
double stat_t1
Stop time for station output [s].
Definition: mptrac.h:3036
char csi_kernel[LEN]
Kernel data file for CSI output.
Definition: mptrac.h:2877
int grid_type
Type of grid data files (0=ASCII, 1=netCDF).
Definition: mptrac.h:2970
double csi_lon0
Lower longitude of gridded CSI data [deg].
Definition: mptrac.h:2904
int qnt_pbl
Quantity array index for boundary layer pressure.
Definition: mptrac.h:2217
int grid_stddev
Include standard deviations in grid output (0=no, 1=yes).
Definition: mptrac.h:2940
int qnt_psice
Quantity array index for saturation pressure over ice.
Definition: mptrac.h:2340
int met_geopot_sx
Longitudinal smoothing of geopotential heights.
Definition: mptrac.h:2549
int qnt_ps
Quantity array index for surface pressure.
Definition: mptrac.h:2196
char prof_obsfile[LEN]
Observation data file for profile output.
Definition: mptrac.h:2976
int qnt_zs
Quantity array index for surface geopotential height.
Definition: mptrac.h:2202
int prof_nz
Number of altitudes of gridded profile data.
Definition: mptrac.h:2979
double csi_dt_out
Time step for CSI output [s].
Definition: mptrac.h:2880
double csi_modmin
Minimum column density to trigger detection [kg/m^2].
Definition: mptrac.h:2889
char grid_kernel[LEN]
Kernel data file for grid output.
Definition: mptrac.h:2928
double prof_z0
Lower altitude of gridded profile data [km].
Definition: mptrac.h:2982
int qnt_w
Quantity array index for vertical velocity.
Definition: mptrac.h:2250
double met_tropo_pv
Dynamical tropopause potential vorticity threshold [PVU].
Definition: mptrac.h:2562
int prof_nx
Number of longitudes of gridded profile data.
Definition: mptrac.h:2988
int qnt_stat
Quantity array index for station flag.
Definition: mptrac.h:2181
int met_mpi_share
Use MPI to share meteo (0=no, 1=yes).
Definition: mptrac.h:2577
int qnt_vz
Quantity array index for vertical velocity.
Definition: mptrac.h:2373
int qnt_ho2
Quantity array index for HO2 volume mixing ratio (climatology).
Definition: mptrac.h:2310
double csi_z1
Upper altitude of gridded CSI data [km].
Definition: mptrac.h:2898
double stat_t0
Start time for station output [s].
Definition: mptrac.h:3033
int atm_type_out
Type of atmospheric data files for output (-1=same as ATM_TYPE, 0=netCDF, 1=binary,...
Definition: mptrac.h:2867
double dt_kpp
Time step for KPP chemistry [s].
Definition: mptrac.h:2798
char csi_basename[LEN]
Basename of CSI data files.
Definition: mptrac.h:2874
int qnt_vs
Quantity array index for surface meridional wind.
Definition: mptrac.h:2208
double vtk_dt_out
Time step for VTK data output [s].
Definition: mptrac.h:3042
double conv_dt
Time interval for convection module [s].
Definition: mptrac.h:2627
char sample_obsfile[LEN]
Observation data file for sample output.
Definition: mptrac.h:3012
int qnt_hno3
Quantity array index for HNO3 volume mixing ratio (climatology).
Definition: mptrac.h:2301
char grid_basename[LEN]
Basename of grid data files.
Definition: mptrac.h:2925
int qnt_h2ot
Quantity array index for tropopause water vapor volume mixing ratio.
Definition: mptrac.h:2229
int qnt_rh
Quantity array index for relative humidity over water.
Definition: mptrac.h:2349
int qnt_zeta_d
Quantity array index for diagnosed zeta vertical coordinate.
Definition: mptrac.h:2361
int tracer_chem
Switch for first order tracer chemistry module (0=off, 1=on).
Definition: mptrac.h:2801
int qnt_zg
Quantity array index for geopotential height.
Definition: mptrac.h:2232
double vtk_offset
Vertical offset for VTK data [km].
Definition: mptrac.h:3051
int qnt_v
Quantity array index for meridional wind.
Definition: mptrac.h:2247
int qnt_oh
Quantity array index for OH volume mixing ratio (climatology).
Definition: mptrac.h:2304
int qnt_h2o
Quantity array index for water vapor volume mixing ratio.
Definition: mptrac.h:2253
int prof_ny
Number of latitudes of gridded profile data.
Definition: mptrac.h:2997
int qnt_rhice
Quantity array index for relative humidity over ice.
Definition: mptrac.h:2352
int qnt_rho
Quantity array index for density of air.
Definition: mptrac.h:2241
double sample_dz
Layer depth for sample output [km].
Definition: mptrac.h:3018
int obs_type
Type of observation data files (0=ASCII, 1=netCDF).
Definition: mptrac.h:2871
int qnt_us
Quantity array index for surface zonal wind.
Definition: mptrac.h:2205
double grid_lon1
Upper longitude of gridded data [deg].
Definition: mptrac.h:2958
char atm_basename[LEN]
Basename of atmospheric data files.
Definition: mptrac.h:2847
int qnt_pt
Quantity array index for tropopause pressure.
Definition: mptrac.h:2220
int qnt_cl
Quantity array index for total column cloud water.
Definition: mptrac.h:2280
double prof_z1
Upper altitude of gridded profile data [km].
Definition: mptrac.h:2985
int qnt_t
Quantity array index for temperature.
Definition: mptrac.h:2238
int atm_filter
Time filter for atmospheric data output (0=none, 1=missval, 2=remove).
Definition: mptrac.h:2856
int kpp_chem
Switch for KPP chemistry module (0=off, 1=on).
Definition: mptrac.h:2795
char ens_basename[LEN]
Basename of ensemble data file.
Definition: mptrac.h:2919
double csi_z0
Lower altitude of gridded CSI data [km].
Definition: mptrac.h:2895
int qnt_lapse
Quantity array index for lapse rate.
Definition: mptrac.h:2367
double stat_lat
Latitude of station [deg].
Definition: mptrac.h:3027
int grid_ny
Number of latitudes of gridded data.
Definition: mptrac.h:2961
int qnt_cape
Quantity array index for convective available potential energy (CAPE).
Definition: mptrac.h:2292
int qnt_o3c
Quantity array index for total column ozone.
Definition: mptrac.h:2298
int grid_nz
Number of altitudes of gridded data.
Definition: mptrac.h:2943
double ens_dt_out
Time step for ensemble output [s].
Definition: mptrac.h:2922
char sample_basename[LEN]
Basename of sample data file.
Definition: mptrac.h:3006
int atm_stride
Particle index stride for atmospheric data files.
Definition: mptrac.h:2859
int met_relhum
Try to read relative humidity (0=no, 1=yes).
Definition: mptrac.h:2555
double atm_dt_out
Time step for atmospheric data output [s].
Definition: mptrac.h:2853
double prof_lat1
Upper latitude of gridded profile data [deg].
Definition: mptrac.h:3003
double psc_h2o
H2O volume mixing ratio for PSC analysis.
Definition: mptrac.h:2837
double prof_lon0
Lower longitude of gridded profile data [deg].
Definition: mptrac.h:2991
int qnt_pct
Quantity array index for cloud top pressure.
Definition: mptrac.h:2274
int qnt_mloss_kpp
Quantity array index for total mass loss due to KPP chemistry.
Definition: mptrac.h:2322
int qnt_psat
Quantity array index for saturation pressure over water.
Definition: mptrac.h:2337
double prof_lat0
Lower latitude of gridded profile data [deg].
Definition: mptrac.h:3000
int qnt_cin
Quantity array index for convective inhibition (CIN).
Definition: mptrac.h:2295
double psc_hno3
HNO3 volume mixing ratio for PSC analysis.
Definition: mptrac.h:2840
double prof_lon1
Upper longitude of gridded profile data [deg].
Definition: mptrac.h:2994
int h2o2_chem_reaction
Reaction type for H2O2 chemistry (0=none, 1=SO2).
Definition: mptrac.h:2792
int grid_sparse
Sparse output in grid data files (0=no, 1=yes).
Definition: mptrac.h:2937
char vtk_basename[LEN]
Basename of VTK data files.
Definition: mptrac.h:3039
int qnt_tt
Quantity array index for tropopause temperature.
Definition: mptrac.h:2223
int qnt_ens
Quantity array index for ensemble IDs.
Definition: mptrac.h:2178
double mixing_dt
Time interval for mixing [s].
Definition: mptrac.h:2720
double vtk_scale
Vertical scaling factor for VTK data.
Definition: mptrac.h:3048
int qnt_pv
Quantity array index for potential vorticity.
Definition: mptrac.h:2376
int qnt_sst
Quantity array index for sea surface temperature.
Definition: mptrac.h:2214
int qnt_sh
Quantity array index for specific humidity.
Definition: mptrac.h:2346
int qnt_idx
Quantity array index for air parcel IDs.
Definition: mptrac.h:2175
double met_tropo_theta
Dynamical tropopause potential temperature threshold [K].
Definition: mptrac.h:2565
int qnt_rwc
Quantity array index for cloud rain water content.
Definition: mptrac.h:2262
char qnt_longname[NQ][LEN]
Quantity long names.
Definition: mptrac.h:2166
double sample_dx
Horizontal radius for sample output [km].
Definition: mptrac.h:3015
int vtk_stride
Particle index stride for VTK data.
Definition: mptrac.h:3045
char stat_basename[LEN]
Basename of station data file.
Definition: mptrac.h:3021
double grid_lat1
Upper latitude of gridded data [deg].
Definition: mptrac.h:2967
int qnt_zt
Quantity array index for tropopause geopotential height.
Definition: mptrac.h:2226
int qnt_cc
Quantity array index for cloud cover.
Definition: mptrac.h:2271
int qnt_plcl
Quantity array index for pressure at lifted condensation level (LCL).
Definition: mptrac.h:2283
double grid_dt_out
Time step for gridded data output [s].
Definition: mptrac.h:2934
int qnt_tdew
Quantity array index for dew point temperature.
Definition: mptrac.h:2379
Here is the call graph for this function:

◆ read_kernel()

void read_kernel ( const char *  filename,
double  kz[EP],
double  kw[EP],
int *  nk 
)

Reads kernel function data from a file and populates the provided arrays.

This function reads kernel function data from a specified file, populating the provided arrays kz and kw with the parsed data. It also updates the variable pointed to by nk with the number of data points read. The function ensures that the height levels are in ascending order and performs checks for the number of height levels read.

Parameters
filenameA string containing the path to the file containing kernel function data.
kzA double array to store the height levels of the kernel function.
kwA double array to store the weights corresponding to the height levels.
nkA pointer to an integer variable representing the number of data points read.

The function performs the following steps:

  • Logs information indicating the kernel function file being read.
  • Attempts to open the specified file for reading.
  • Reads data from the file line by line, parsing height levels and weights.
  • Checks that the height levels are in ascending order and that the number of data points does not exceed the defined maximum.
  • Closes the file after reading.
  • Updates the value of nk with the number of data points read.
  • Normalizes the kernel function weights by dividing each weight by the maximum weight.
Author
Lars Hoffmann

Definition at line 5534 of file mptrac.c.

5538 {
5539
5540 /* Write info... */
5541 LOG(1, "Read kernel function: %s", filename);
5542
5543 /* Open file... */
5544 FILE *in;
5545 if (!(in = fopen(filename, "r")))
5546 ERRMSG("Cannot open file!");
5547
5548 /* Read data... */
5549 char line[LEN];
5550 int n = 0;
5551 while (fgets(line, LEN, in))
5552 if (sscanf(line, "%lg %lg", &kz[n], &kw[n]) == 2) {
5553 if (n > 0 && kz[n] < kz[n - 1])
5554 ERRMSG("Height levels must be ascending!");
5555 if ((++n) >= EP)
5556 ERRMSG("Too many height levels!");
5557 }
5558
5559 /* Close file... */
5560 fclose(in);
5561
5562 /* Check number of data points... */
5563 *nk = n;
5564 if (n < 2)
5565 ERRMSG("Not enough height levels!");
5566
5567 /* Normalize kernel function... */
5568 double kmax = gsl_stats_max(kw, 1, (size_t) n);
5569 for (int iz = 0; iz < n; iz++)
5570 kw[iz] /= kmax;
5571}

◆ read_met()

int read_met ( const char *  filename,
ctl_t ctl,
clim_t clim,
met_t met 
)

Reads meteorological data from a file and populates the provided structures.

This function reads meteorological data from a specified file, populating the provided structures ctl, clim, and met with the parsed data. The function handles both netCDF and binary data formats. For netCDF data, it performs various data processing steps such as reading coordinates, surface data, atmospheric levels, and calculating derived quantities. For binary data, it reads the data directly into the appropriate arrays and structures.

Parameters
filenameA string containing the path to the file containing meteorological data.
ctlA pointer to a structure containing control parameters.
climA pointer to a structure containing climatological data.
metA pointer to a structure to store the meteorological data.
Returns
Returns 1 on success and 0 on failure.

The function performs the following steps:

  • Logs information indicating the meteorological data file being read.
  • Determines the type of meteorological data (netCDF or binary).
  • For netCDF data:
    • Opens the netCDF file and reads various data components including grid coordinates, atmospheric levels, surface data, and derived quantities.
    • Performs data processing steps such as extrapolation, boundary condition handling, downsampling, and calculations of geopotential heights, potential vorticity, boundary layer data, tropopause data, cloud properties, convective available potential energy, total column ozone, and detrending.
    • Checks and adjusts meteorological data as necessary, including monotonicity of vertical coordinates.
    • Closes the netCDF file after reading.
  • For binary data:
    • Opens the binary file and reads metadata including the type and version of the data, time information, dimensions, and grid coordinates.
    • Reads surface data, level data, and final flag from the binary file.
    • Closes the binary file after reading.
  • Copies wind data to a cache for subsequent use.
  • Returns 1 on successful reading and processing of meteorological data.
Note
The function handles different types of meteorological data formats and performs appropriate processing and error checking for each format.
Author
Lars Hoffmann

Definition at line 5575 of file mptrac.c.

5579 {
5580
5581 /* Write info... */
5582 LOG(1, "Read meteo data: %s", filename);
5583
5584 /* Initialize rank... */
5585 int rank = 0;
5586#ifdef MPI
5587 if (ctl->met_mpi_share)
5588 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5589#endif
5590
5591 /* Read netCDF data... */
5592 if (!ctl->met_mpi_share || rank == 0) {
5593 if (ctl->met_type == 0) {
5594
5595 int ncid;
5596
5597 /* Open netCDF file... */
5598 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
5599 WARN("Cannot open file!");
5600 return 0;
5601 }
5602
5603 /* Read coordinates of meteo data... */
5604 read_met_grid(filename, ncid, ctl, met);
5605
5606 /* Read meteo data on vertical levels... */
5607 read_met_levels(ncid, ctl, met);
5608
5609 /* Extrapolate data for lower boundary... */
5611
5612 /* Read surface data... */
5613 read_met_surface(ncid, met, ctl);
5614
5615 /* Fix polar winds... */
5617
5618 /* Create periodic boundary conditions... */
5619 read_met_periodic(met);
5620
5621 /* Downsampling... */
5622 read_met_sample(ctl, met);
5623
5624 /* Calculate geopotential heights... */
5625 read_met_geopot(ctl, met);
5626
5627 /* Calculate potential vorticity... */
5628 read_met_pv(met);
5629
5630 /* Calculate boundary layer data... */
5631 read_met_pbl(met);
5632
5633 /* Calculate tropopause data... */
5634 read_met_tropo(ctl, clim, met);
5635
5636 /* Calculate cloud properties... */
5637 read_met_cloud(met);
5638
5639 /* Calculate convective available potential energy... */
5640 read_met_cape(clim, met);
5641
5642 /* Calculate total column ozone... */
5643 read_met_ozone(met);
5644
5645 /* Detrending... */
5646 read_met_detrend(ctl, met);
5647
5648 /* Check meteo data and smooth zeta profiles ... */
5649 if (ctl->advect_vert_coord == 1)
5651
5652 /* Close file... */
5653 NC(nc_close(ncid));
5654 }
5655
5656 /* Read binary data... */
5657 else if (ctl->met_type >= 1 && ctl->met_type <= 5) {
5658
5659 FILE *in;
5660
5661 double r;
5662
5663 int year, mon, day, hour, min, sec;
5664
5665 /* Set timer... */
5666 SELECT_TIMER("READ_MET_BIN", "INPUT", NVTX_READ);
5667
5668 /* Open file... */
5669 if (!(in = fopen(filename, "r"))) {
5670 WARN("Cannot open file!");
5671 return 0;
5672 }
5673
5674 /* Check type of binary data... */
5675 int met_type;
5676 FREAD(&met_type, int,
5677 1,
5678 in);
5679 if (met_type != ctl->met_type)
5680 ERRMSG("Wrong MET_TYPE of binary data!");
5681
5682 /* Check version of binary data... */
5683 int version;
5684 FREAD(&version, int,
5685 1,
5686 in);
5687 if (version != 100 && version != 101 && version != 102)
5688 ERRMSG("Wrong version of binary data!");
5689
5690 /* Read time... */
5691 FREAD(&met->time, double,
5692 1,
5693 in);
5694 jsec2time(met->time, &year, &mon, &day, &hour, &min, &sec, &r);
5695 LOG(2, "Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
5696 met->time, year, mon, day, hour, min);
5697 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
5698 || day < 1 || day > 31 || hour < 0 || hour > 23)
5699 ERRMSG("Error while reading time!");
5700
5701 /* Read dimensions... */
5702 FREAD(&met->nx, int,
5703 1,
5704 in);
5705 LOG(2, "Number of longitudes: %d", met->nx);
5706 if (met->nx < 2 || met->nx > EX)
5707 ERRMSG("Number of longitudes out of range!");
5708
5709 FREAD(&met->ny, int,
5710 1,
5711 in);
5712 LOG(2, "Number of latitudes: %d", met->ny);
5713 if (met->ny < 2 || met->ny > EY)
5714 ERRMSG("Number of latitudes out of range!");
5715
5716 FREAD(&met->np, int,
5717 1,
5718 in);
5719 LOG(2, "Number of levels: %d", met->np);
5720 if (met->np < 2 || met->np > EP)
5721 ERRMSG("Number of levels out of range!");
5722
5723 /* Read grid... */
5724 FREAD(met->lon, double,
5725 (size_t) met->nx,
5726 in);
5727 LOG(2, "Longitudes: %g, %g ... %g deg",
5728 met->lon[0], met->lon[1], met->lon[met->nx - 1]);
5729
5730 FREAD(met->lat, double,
5731 (size_t) met->ny,
5732 in);
5733 LOG(2, "Latitudes: %g, %g ... %g deg",
5734 met->lat[0], met->lat[1], met->lat[met->ny - 1]);
5735
5736 FREAD(met->p, double,
5737 (size_t) met->np,
5738 in);
5739 LOG(2, "Altitude levels: %g, %g ... %g km",
5740 Z(met->p[0]), Z(met->p[1]), Z(met->p[met->np - 1]));
5741 LOG(2, "Pressure levels: %g, %g ... %g hPa",
5742 met->p[0], met->p[1], met->p[met->np - 1]);
5743
5744 /* Read surface data... */
5745 read_met_bin_2d(in, met, met->ps, "PS");
5746 read_met_bin_2d(in, met, met->ts, "TS");
5747 read_met_bin_2d(in, met, met->zs, "ZS");
5748 read_met_bin_2d(in, met, met->us, "US");
5749 read_met_bin_2d(in, met, met->vs, "VS");
5750 if (version >= 101) {
5751 read_met_bin_2d(in, met, met->lsm, "LSM");
5752 read_met_bin_2d(in, met, met->sst, "SST");
5753 }
5754 read_met_bin_2d(in, met, met->pbl, "PBL");
5755 read_met_bin_2d(in, met, met->pt, "PT");
5756 read_met_bin_2d(in, met, met->tt, "TT");
5757 read_met_bin_2d(in, met, met->zt, "ZT");
5758 read_met_bin_2d(in, met, met->h2ot, "H2OT");
5759 read_met_bin_2d(in, met, met->pct, "PCT");
5760 read_met_bin_2d(in, met, met->pcb, "PCB");
5761 read_met_bin_2d(in, met, met->cl, "CL");
5762 read_met_bin_2d(in, met, met->plcl, "PLCL");
5763 read_met_bin_2d(in, met, met->plfc, "PLFC");
5764 read_met_bin_2d(in, met, met->pel, "PEL");
5765 read_met_bin_2d(in, met, met->cape, "CAPE");
5766 read_met_bin_2d(in, met, met->cin, "CIN");
5767
5768 /* Read level data... */
5769 read_met_bin_3d(in, ctl, met, met->z, "Z", -1e34f, 1e34f);
5770 read_met_bin_3d(in, ctl, met, met->t, "T", 0, 1e34f);
5771 read_met_bin_3d(in, ctl, met, met->u, "U", -1e34f, 1e34f);
5772 read_met_bin_3d(in, ctl, met, met->v, "V", -1e34f, 1e34f);
5773 read_met_bin_3d(in, ctl, met, met->w, "W", -1e34f, 1e34f);
5774 read_met_bin_3d(in, ctl, met, met->pv, "PV", -1e34f, 1e34f);
5775 read_met_bin_3d(in, ctl, met, met->h2o, "H2O", 0, 1e34f);
5776 read_met_bin_3d(in, ctl, met, met->o3, "O3", 0, 1e34f);
5777 read_met_bin_3d(in, ctl, met, met->lwc, "LWC", 0, 1e34f);
5778 if (version >= 102)
5779 read_met_bin_3d(in, ctl, met, met->rwc, "RWC", 0, 1e34f);
5780 read_met_bin_3d(in, ctl, met, met->iwc, "IWC", 0, 1e34f);
5781 if (version >= 102)
5782 read_met_bin_3d(in, ctl, met, met->swc, "SWC", 0, 1e34f);
5783 if (version >= 101)
5784 read_met_bin_3d(in, ctl, met, met->cc, "CC", 0, 1);
5785
5786 /* Read final flag... */
5787 int final;
5788 FREAD(&final, int,
5789 1,
5790 in);
5791 if (final != 999)
5792 ERRMSG("Error while reading binary data!");
5793
5794 /* Close file... */
5795 fclose(in);
5796 }
5797
5798 /* Not implemented... */
5799 else
5800 ERRMSG("MET_TYPE not implemented!");
5801 }
5802
5803 /* Broadcast data via MPI... */
5804#ifdef MPI
5805 if (ctl->met_mpi_share) {
5806
5807 /* Set timer... */
5808 SELECT_TIMER("READ_MET_MPI_BCAST", "COMM", NVTX_SEND);
5809 LOG(2, "Broadcast data on rank %d...", rank);
5810
5811 /* Broadcast... */
5812 broadcast_large_data(met, sizeof(met_t));
5813 }
5814#endif
5815
5816 /* Return success... */
5817 return 1;
5818}
void read_met_bin_2d(FILE *in, met_t *met, float var[EX][EY], char *varname)
Reads a 2-dimensional meteorological variable from a binary file and stores it in the provided array.
Definition: mptrac.c:5822
void read_met_extrapolate(met_t *met)
Extrapolates meteorological data.
Definition: mptrac.c:6202
void read_met_levels(int ncid, ctl_t *ctl, met_t *met)
Reads meteorological variables at different vertical levels from a NetCDF file.
Definition: mptrac.c:6487
void read_met_cloud(met_t *met)
Calculates cloud-related variables for each grid point.
Definition: mptrac.c:6047
void read_met_grid(const char *filename, int ncid, ctl_t *ctl, met_t *met)
Reads meteorological grid information from a NetCDF file.
Definition: mptrac.c:6369
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
Definition: mptrac.c:7118
void read_met_pbl(met_t *met)
Calculates the planetary boundary layer (PBL) height for each grid point.
Definition: mptrac.c:7047
void read_met_sample(ctl_t *ctl, met_t *met)
Downsamples meteorological data based on specified parameters.
Definition: mptrac.c:7366
void read_met_monotonize(met_t *met)
Makes zeta and pressure profiles monotone.
Definition: mptrac.c:6672
void read_met_bin_3d(FILE *in, ctl_t *ctl, met_t *met, float var[EX][EY][EP], char *varname, float bound_min, float bound_max)
Reads 3D meteorological data from a binary file, potentially using different compression methods.
Definition: mptrac.c:5851
void read_met_detrend(ctl_t *ctl, met_t *met)
Detrends meteorological data.
Definition: mptrac.c:6098
void read_met_ozone(met_t *met)
Calculates the total column ozone from meteorological ozone data.
Definition: mptrac.c:7338
void read_met_surface(int ncid, met_t *met, ctl_t *ctl)
Reads surface meteorological data from a netCDF file and stores it in the meteorological data structu...
Definition: mptrac.c:7514
void read_met_pv(met_t *met)
Calculates potential vorticity (PV) from meteorological data.
Definition: mptrac.c:7232
void read_met_polar_winds(met_t *met)
Applies a fix for polar winds in meteorological data.
Definition: mptrac.c:7173
void read_met_cape(clim_t *clim, met_t *met)
Calculates Convective Available Potential Energy (CAPE) for each grid point.
Definition: mptrac.c:5937
void read_met_geopot(ctl_t *ctl, met_t *met)
Calculates geopotential heights from meteorological data.
Definition: mptrac.c:6242
#define EY
Maximum number of latitudes for meteo data.
Definition: mptrac.h:266
void broadcast_large_data(void *data, size_t N)
Broadcasts large data across all processes in an MPI communicator.
float zt[EX][EY]
Tropopause geopotential height [km].
Definition: mptrac.h:3347
float sst[EX][EY]
Sea surface temperature [K].
Definition: mptrac.h:3335
float rwc[EX][EY][EP]
Cloud rain water content [kg/kg].
Definition: mptrac.h:3407
float cape[EX][EY]
Convective available potential energy [J/kg].
Definition: mptrac.h:3371
float pct[EX][EY]
Cloud top pressure [hPa].
Definition: mptrac.h:3353
float lwc[EX][EY][EP]
Cloud liquid water content [kg/kg].
Definition: mptrac.h:3404
float us[EX][EY]
Surface zonal wind [m/s].
Definition: mptrac.h:3326
float cc[EX][EY][EP]
Cloud cover [1].
Definition: mptrac.h:3416
float ts[EX][EY]
Surface temperature [K].
Definition: mptrac.h:3320
float pcb[EX][EY]
Cloud bottom pressure [hPa].
Definition: mptrac.h:3356
float pel[EX][EY]
Pressure at equilibrium level [hPa].
Definition: mptrac.h:3368
float cin[EX][EY]
Convective inhibition [J/kg].
Definition: mptrac.h:3374
float plcl[EX][EY]
Pressure at lifted condensation level (LCL) [hPa].
Definition: mptrac.h:3362
float tt[EX][EY]
Tropopause temperature [K].
Definition: mptrac.h:3344
float pbl[EX][EY]
Boundary layer pressure [hPa].
Definition: mptrac.h:3338
float vs[EX][EY]
Surface meridional wind [m/s].
Definition: mptrac.h:3329
float lsm[EX][EY]
Land-sea mask [1].
Definition: mptrac.h:3332
float iwc[EX][EY][EP]
Cloud ice water content [kg/kg].
Definition: mptrac.h:3410
float h2ot[EX][EY]
Tropopause water vapor volume mixing ratio [ppv].
Definition: mptrac.h:3350
float pv[EX][EY][EP]
Potential vorticity [PVU].
Definition: mptrac.h:3395
float cl[EX][EY]
Total column cloud water [kg/m^2].
Definition: mptrac.h:3359
float plfc[EX][EY]
Pressure at level of free convection (LFC) [hPa].
Definition: mptrac.h:3365
float swc[EX][EY][EP]
Cloud snow water content [kg/kg].
Definition: mptrac.h:3413
Here is the call graph for this function:

◆ read_met_bin_2d()

void read_met_bin_2d ( FILE *  in,
met_t met,
float  var[EX][EY],
char *  varname 
)

Reads a 2-dimensional meteorological variable from a binary file and stores it in the provided array.

This function reads a 2-dimensional meteorological variable from a binary file, which is assumed to be uncompressed, and stores it in the provided 2-dimensional array var. The variable name is used for logging purposes to identify the data being read.

Parameters
inA pointer to the FILE structure representing the binary file to read from.
metA pointer to a structure containing meteorological data.
varA 2-dimensional array to store the read variable.
varnameA string containing the name of the variable being read.

The function performs the following steps:

  • Allocates memory for a temporary buffer to hold the uncompressed data.
  • Logs information about the variable being read from the file.
  • Reads the uncompressed data from the file into the temporary buffer.
  • Copies the data from the temporary buffer to the provided 2-dimensional array.
  • Frees the memory allocated for the temporary buffer.
Note
The function assumes that the binary file contains uncompressed data and reads the data directly into the provided array without any additional processing.
Author
Lars Hoffmann

Definition at line 5822 of file mptrac.c.

5826 {
5827
5828 float *help;
5829
5830 /* Allocate... */
5831 ALLOC(help, float,
5832 EX * EY);
5833
5834 /* Read uncompressed... */
5835 LOG(2, "Read 2-D variable: %s (uncompressed)", varname);
5836 FREAD(help, float,
5837 (size_t) (met->nx * met->ny),
5838 in);
5839
5840 /* Copy data... */
5841 for (int ix = 0; ix < met->nx; ix++)
5842 for (int iy = 0; iy < met->ny; iy++)
5843 var[ix][iy] = help[ARRAY_2D(ix, iy, met->ny)];
5844
5845 /* Free... */
5846 free(help);
5847}
#define ARRAY_2D(ix, iy, ny)
Macro for computing the linear index of a 2D array element.
Definition: mptrac.h:367

◆ read_met_bin_3d()

void read_met_bin_3d ( FILE *  in,
ctl_t ctl,
met_t met,
float  var[EX][EY][EP],
char *  varname,
float  bound_min,
float  bound_max 
)

Reads 3D meteorological data from a binary file, potentially using different compression methods.

This function reads 3-dimensional meteorological data from a binary file into a specified variable array. The data can be read in uncompressed form or using one of several supported compression methods. The data is then clamped to specified minimum and maximum bounds.

Parameters
[in]inPointer to the input file from which to read the data.
[in]ctlPointer to the control structure that contains metadata about the type of data and how it is stored.
[in]metPointer to the meteorological structure that contains the dimensions of the data.
[out]var3D array to store the read data, with dimensions [EX][EY][EP].
[in]varnameName of the variable being read, used for logging and debugging.
[in]bound_minMinimum bound to which data values should be clamped.
[in]bound_maxMaximum bound to which data values should be clamped.

The function supports the following types of data:

  • Uncompressed data
  • Packed data
  • ZFP compressed data (if compiled with ZFP support)
  • ZSTD compressed data (if compiled with ZSTD support)
  • CMULTISCALE compressed data (if compiled with CMS support)

Depending on the compression type specified in the control structure, the appropriate reading and decompression function is used. The data is read into a temporary buffer, then copied into the output array, applying the specified bounds to each value.

Note
The function assumes that the dimensions EX, EY, and EP are correctly defined and match the dimensions specified in the met structure.
If the appropriate compression support is not compiled, an error message is generated.
Author
Lars Hoffmann

Definition at line 5851 of file mptrac.c.

5858 {
5859
5860 float *help;
5861
5862 /* Allocate... */
5863 ALLOC(help, float,
5864 EX * EY * EP);
5865
5866 /* Read uncompressed data... */
5867 if (ctl->met_type == 1) {
5868 LOG(2, "Read 3-D variable: %s (uncompressed)", varname);
5869 FREAD(help, float,
5870 (size_t) (met->nx * met->ny * met->np),
5871 in);
5872 }
5873
5874 /* Read packed data... */
5875 else if (ctl->met_type == 2)
5876 compress_pck(varname, help, (size_t) (met->ny * met->nx),
5877 (size_t) met->np, 1, in);
5878
5879 /* Read zfp data... */
5880 else if (ctl->met_type == 3) {
5881#ifdef ZFP
5882 int precision;
5883 FREAD(&precision, int,
5884 1,
5885 in);
5886
5887 double tolerance;
5888 FREAD(&tolerance, double,
5889 1,
5890 in);
5891
5892 compress_zfp(varname, help, met->np, met->ny, met->nx, precision,
5893 tolerance, 1, in);
5894#else
5895 ERRMSG("MPTRAC was compiled without zfp compression!");
5896#endif
5897 }
5898
5899 /* Read zstd data... */
5900 else if (ctl->met_type == 4) {
5901#ifdef ZSTD
5902 compress_zstd(varname, help, (size_t) (met->np * met->ny * met->nx), 1,
5903 in);
5904#else
5905 ERRMSG("MPTRAC was compiled without zstd compression!");
5906#endif
5907 }
5908
5909 /* Read cmultiscale data... */
5910 else if (ctl->met_type == 5) {
5911#ifdef CMS
5912 compress_cms(ctl, varname, help, (size_t) met->nx, (size_t) met->ny,
5913 (size_t) met->np, 1, in);
5914#else
5915 ERRMSG("MPTRAC was compiled without cmultiscale compression!");
5916#endif
5917 }
5918
5919 /* Copy data... */
5920#pragma omp parallel for default(shared) collapse(2)
5921 for (int ix = 0; ix < met->nx; ix++)
5922 for (int iy = 0; iy < met->ny; iy++)
5923 for (int ip = 0; ip < met->np; ip++) {
5924 var[ix][iy][ip] = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
5925 if (var[ix][iy][ip] < bound_min)
5926 var[ix][iy][ip] = bound_min;
5927 else if (var[ix][iy][ip] > bound_max)
5928 var[ix][iy][ip] = bound_max;
5929 }
5930
5931 /* Free... */
5932 free(help);
5933}
void compress_pck(char *varname, float *array, size_t nxy, size_t nz, int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats.
Definition: mptrac.c:575
void compress_cms(ctl_t *ctl, char *varname, float *array, size_t nx, size_t ny, size_t np, int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm.
void compress_zstd(char *varname, float *array, size_t n, int decompress, FILE *inout)
Compresses or decompresses an array of floats using the Zstandard (ZSTD) library.
void compress_zfp(char *varname, float *array, int nx, int ny, int nz, int precision, double tolerance, int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using the ZFP library.
Here is the call graph for this function:

◆ read_met_cape()

void read_met_cape ( clim_t clim,
met_t met 
)

Calculates Convective Available Potential Energy (CAPE) for each grid point.

This function calculates the Convective Available Potential Energy (CAPE) at each grid point based on the provided meteorological data. CAPE is a measure of the energy available for deep convection, which is essential for severe weather development.

Parameters
climA pointer to a structure containing climatological data.
metA pointer to a structure containing meteorological data.

The function performs the following steps:

  • Sets up a timer to monitor the calculation time.
  • Initializes variables and constants required for the computation, such as vertical spacing and pressure levels.
  • Iterates over each grid point in parallel using OpenMP.
  • Calculates CAPE by integrating the difference in virtual temperatures between the environment and the parcel, up to the level of free convection (LFC).
  • Determines the lifted condensation level (LCL), level of free convection (LFC), equilibrium level (EL), and Convective Inhibition (CIN) for each grid point.
  • Checks the results and updates the corresponding fields in the meteorological data structure.
Note
The function utilizes OpenMP for parallelization to enhance performance by distributing the computation across multiple threads.
Author
Lars Hoffmann

Definition at line 5937 of file mptrac.c.

5939 {
5940
5941 /* Set timer... */
5942 SELECT_TIMER("READ_MET_CAPE", "METPROC", NVTX_READ);
5943 LOG(2, "Calculate CAPE...");
5944
5945 /* Vertical spacing (about 100 m)... */
5946 const double pfac = 1.01439, dz0 = RI / MA / G0 * log(pfac);
5947
5948 /* Loop over columns... */
5949#pragma omp parallel for default(shared) collapse(2)
5950 for (int ix = 0; ix < met->nx; ix++)
5951 for (int iy = 0; iy < met->ny; iy++) {
5952
5953 /* Get potential temperature and water vapor at lowest 50 hPa... */
5954 int n = 0;
5955 double h2o = 0, t, theta = 0;
5956 double pbot = MIN(met->ps[ix][iy], met->p[0]);
5957 double ptop = pbot - 50.;
5958 for (int ip = 0; ip < met->np; ip++) {
5959 if (met->p[ip] <= pbot) {
5960 theta += THETA(met->p[ip], met->t[ix][iy][ip]);
5961 h2o += met->h2o[ix][iy][ip];
5962 n++;
5963 }
5964 if (met->p[ip] < ptop && n > 0)
5965 break;
5966 }
5967 theta /= n;
5968 h2o /= n;
5969
5970 /* Cannot compute anything if water vapor is missing... */
5971 met->plcl[ix][iy] = NAN;
5972 met->plfc[ix][iy] = NAN;
5973 met->pel[ix][iy] = NAN;
5974 met->cape[ix][iy] = NAN;
5975 met->cin[ix][iy] = NAN;
5976 if (h2o <= 0)
5977 continue;
5978
5979 /* Find lifted condensation level (LCL)... */
5980 ptop = P(20.);
5981 pbot = met->ps[ix][iy];
5982 do {
5983 met->plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
5984 t = theta / pow(1000. / met->plcl[ix][iy], 0.286);
5985 if (RH(met->plcl[ix][iy], t, h2o) > 100.)
5986 ptop = met->plcl[ix][iy];
5987 else
5988 pbot = met->plcl[ix][iy];
5989 } while (pbot - ptop > 0.1);
5990
5991 /* Calculate CIN up to LCL... */
5993 double dcape, dz, h2o_env, t_env;
5994 double p = met->ps[ix][iy];
5995 met->cape[ix][iy] = met->cin[ix][iy] = 0;
5996 do {
5997 dz = dz0 * TVIRT(t, h2o);
5998 p /= pfac;
5999 t = theta / pow(1000. / p, 0.286);
6000 intpol_met_space_3d(met, met->t, p, met->lon[ix], met->lat[iy],
6001 &t_env, ci, cw, 1);
6002 intpol_met_space_3d(met, met->h2o, p, met->lon[ix], met->lat[iy],
6003 &h2o_env, ci, cw, 0);
6004 dcape = 1e3 * G0 * (TVIRT(t, h2o) - TVIRT(t_env, h2o_env)) /
6005 TVIRT(t_env, h2o_env) * dz;
6006 if (dcape < 0)
6007 met->cin[ix][iy] += fabsf((float) dcape);
6008 } while (p > met->plcl[ix][iy]);
6009
6010 /* Calculate level of free convection (LFC), equilibrium level (EL),
6011 and convective available potential energy (CAPE)... */
6012 dcape = 0;
6013 p = met->plcl[ix][iy];
6014 t = theta / pow(1000. / p, 0.286);
6015 ptop = 0.75 * clim_tropo(clim, met->time, met->lat[iy]);
6016 do {
6017 dz = dz0 * TVIRT(t, h2o);
6018 p /= pfac;
6019 t -= lapse_rate(t, h2o) * dz;
6020 double psat = PSAT(t);
6021 h2o = psat / (p - (1. - EPS) * psat);
6022 intpol_met_space_3d(met, met->t, p, met->lon[ix], met->lat[iy],
6023 &t_env, ci, cw, 1);
6024 intpol_met_space_3d(met, met->h2o, p, met->lon[ix], met->lat[iy],
6025 &h2o_env, ci, cw, 0);
6026 double dcape_old = dcape;
6027 dcape = 1e3 * G0 * (TVIRT(t, h2o) - TVIRT(t_env, h2o_env)) /
6028 TVIRT(t_env, h2o_env) * dz;
6029 if (dcape > 0) {
6030 met->cape[ix][iy] += (float) dcape;
6031 if (!isfinite(met->plfc[ix][iy]))
6032 met->plfc[ix][iy] = (float) p;
6033 } else if (dcape_old > 0)
6034 met->pel[ix][iy] = (float) p;
6035 if (dcape < 0 && !isfinite(met->plfc[ix][iy]))
6036 met->cin[ix][iy] += fabsf((float) dcape);
6037 } while (p > ptop);
6038
6039 /* Check results... */
6040 if (!isfinite(met->plfc[ix][iy]))
6041 met->cin[ix][iy] = NAN;
6042 }
6043}
double clim_tropo(const clim_t *clim, const double t, const double lat)
Calculates the tropopause pressure based on climatological data.
Definition: mptrac.c:193
Here is the call graph for this function:

◆ read_met_cloud()

void read_met_cloud ( met_t met)

Calculates cloud-related variables for each grid point.

This function calculates cloud-related variables, such as cloud cover, cloud top pressure, cloud bottom pressure, and total cloud water content, based on the provided meteorological data.

Parameters
metA pointer to a structure containing meteorological data.

The function performs the following steps:

  • Sets up a timer to monitor the calculation time.
  • Initializes variables and constants required for the computation.
  • Iterates over each grid point in parallel using OpenMP.
  • Determines cloud-related variables based on thresholds for liquid water content (LWC), rain water content (RWC), ice water content (IWC) and snow water content (SWC).
  • Calculates cloud cover, cloud top pressure, cloud bottom pressure, and total cloud water content for each grid point.
  • Updates the corresponding fields in the meteorological data structure.
Note
The function utilizes OpenMP for parallelization to enhance performance by distributing the computation across multiple threads.
Author
Lars Hoffmann

Definition at line 6047 of file mptrac.c.

6048 {
6049
6050 /* Set timer... */
6051 SELECT_TIMER("READ_MET_CLOUD", "METPROC", NVTX_READ);
6052 LOG(2, "Calculate cloud data...");
6053
6054 /* Loop over columns... */
6055#pragma omp parallel for default(shared) collapse(2)
6056 for (int ix = 0; ix < met->nx; ix++)
6057 for (int iy = 0; iy < met->ny; iy++) {
6058
6059 /* Init... */
6060 met->pct[ix][iy] = NAN;
6061 met->pcb[ix][iy] = NAN;
6062 met->cl[ix][iy] = 0;
6063
6064 /* Loop over pressure levels... */
6065 for (int ip = 0; ip < met->np - 1; ip++) {
6066
6067 /* Check pressure... */
6068 if (met->p[ip] > met->ps[ix][iy] || met->p[ip] < P(20.))
6069 continue;
6070
6071 /* Check ice water and liquid water content... */
6072 if (met->iwc[ix][iy][ip] > 0 || met->rwc[ix][iy][ip] > 0
6073 || met->lwc[ix][iy][ip] > 0 || met->swc[ix][iy][ip] > 0) {
6074
6075 /* Get cloud top pressure ... */
6076 met->pct[ix][iy]
6077 = (float) (0.5 * (met->p[ip] + (float) met->p[ip + 1]));
6078
6079 /* Get cloud bottom pressure ... */
6080 if (!isfinite(met->pcb[ix][iy]))
6081 met->pcb[ix][iy]
6082 = (float) (0.5 * (met->p[ip] + met->p[MAX(ip - 1, 0)]));
6083 }
6084
6085 /* Get cloud water... */
6086 met->cl[ix][iy] += (float)
6087 (0.5 * (met->lwc[ix][iy][ip] + met->lwc[ix][iy][ip + 1]
6088 + met->rwc[ix][iy][ip] + met->rwc[ix][iy][ip + 1]
6089 + met->iwc[ix][iy][ip] + met->iwc[ix][iy][ip + 1]
6090 + met->swc[ix][iy][ip] + met->swc[ix][iy][ip + 1])
6091 * 100. * (met->p[ip] - met->p[ip + 1]) / G0);
6092 }
6093 }
6094}

◆ read_met_detrend()

void read_met_detrend ( ctl_t ctl,
met_t met 
)

Detrends meteorological data.

This function detrends meteorological data by removing spatially varying backgrounds from each grid point. Detrending helps in removing systematic biases and trends from the data, enabling better analysis and modeling.

Parameters
ctlA pointer to a structure containing control parameters.
metA pointer to a structure containing meteorological data.

The function performs the following steps:

  • Checks if detrending is enabled based on the control parameters.
  • Sets up a timer to monitor the detrending time.
  • Allocates memory for a temporary meteorological data structure.
  • Calculates the standard deviation and box size for detrending.
  • Calculates the detrended data by subtracting spatially varying backgrounds.
  • Updates the original meteorological data with the detrended values.
  • Frees the allocated memory.
Note
Detrending is performed by subtracting spatially varying backgrounds calculated from neighboring grid points.
OpenMP is utilized for parallelization to enhance performance by distributing the computation across multiple threads.
Author
Lars Hoffmann

Definition at line 6098 of file mptrac.c.

6100 {
6101
6102 met_t *help;
6103
6104 /* Check parameters... */
6105 if (ctl->met_detrend <= 0)
6106 return;
6107
6108 /* Set timer... */
6109 SELECT_TIMER("READ_MET_DETREND", "METPROC", NVTX_READ);
6110 LOG(2, "Detrend meteo data...");
6111
6112 /* Allocate... */
6113 ALLOC(help, met_t, 1);
6114
6115 /* Calculate standard deviation... */
6116 double sigma = ctl->met_detrend / 2.355;
6117 double tssq = 2. * SQR(sigma);
6118
6119 /* Calculate box size in latitude... */
6120 int sy = (int) (3. * DY2DEG(sigma) / fabs(met->lat[1] - met->lat[0]));
6121 sy = MIN(MAX(1, sy), met->ny / 2);
6122
6123 /* Calculate background... */
6124#pragma omp parallel for default(shared) collapse(2)
6125 for (int ix = 0; ix < met->nx; ix++) {
6126 for (int iy = 0; iy < met->ny; iy++) {
6127
6128 /* Calculate Cartesian coordinates... */
6129 double x0[3];
6130 geo2cart(0.0, met->lon[ix], met->lat[iy], x0);
6131
6132 /* Calculate box size in longitude... */
6133 int sx =
6134 (int) (3. * DX2DEG(sigma, met->lat[iy]) /
6135 fabs(met->lon[1] - met->lon[0]));
6136 sx = MIN(MAX(1, sx), met->nx / 2);
6137
6138 /* Init... */
6139 float wsum = 0;
6140 for (int ip = 0; ip < met->np; ip++) {
6141 help->t[ix][iy][ip] = 0;
6142 help->u[ix][iy][ip] = 0;
6143 help->v[ix][iy][ip] = 0;
6144 help->w[ix][iy][ip] = 0;
6145 }
6146
6147 /* Loop over neighboring grid points... */
6148 for (int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
6149 int ix3 = ix2;
6150 if (ix3 < 0)
6151 ix3 += met->nx;
6152 else if (ix3 >= met->nx)
6153 ix3 -= met->nx;
6154 for (int iy2 = MAX(iy - sy, 0);
6155 iy2 <= MIN(iy + sy, met->ny - 1); iy2++) {
6156
6157 /* Calculate Cartesian coordinates... */
6158 double x1[3];
6159 geo2cart(0.0, met->lon[ix3], met->lat[iy2], x1);
6160
6161 /* Calculate weighting factor... */
6162 float w = (float) exp(-DIST2(x0, x1) / tssq);
6163
6164 /* Add data... */
6165 wsum += w;
6166 for (int ip = 0; ip < met->np; ip++) {
6167 help->t[ix][iy][ip] += w * met->t[ix3][iy2][ip];
6168 help->u[ix][iy][ip] += w * met->u[ix3][iy2][ip];
6169 help->v[ix][iy][ip] += w * met->v[ix3][iy2][ip];
6170 help->w[ix][iy][ip] += w * met->w[ix3][iy2][ip];
6171 }
6172 }
6173 }
6174
6175 /* Normalize... */
6176 for (int ip = 0; ip < met->np; ip++) {
6177 help->t[ix][iy][ip] /= wsum;
6178 help->u[ix][iy][ip] /= wsum;
6179 help->v[ix][iy][ip] /= wsum;
6180 help->w[ix][iy][ip] /= wsum;
6181 }
6182 }
6183 }
6184
6185 /* Subtract background... */
6186#pragma omp parallel for default(shared) collapse(3)
6187 for (int ix = 0; ix < met->nx; ix++)
6188 for (int iy = 0; iy < met->ny; iy++)
6189 for (int ip = 0; ip < met->np; ip++) {
6190 met->t[ix][iy][ip] -= help->t[ix][iy][ip];
6191 met->u[ix][iy][ip] -= help->u[ix][iy][ip];
6192 met->v[ix][iy][ip] -= help->v[ix][iy][ip];
6193 met->w[ix][iy][ip] -= help->w[ix][iy][ip];
6194 }
6195
6196 /* Free... */
6197 free(help);
6198}
void geo2cart(const double z, const double lon, const double lat, double *x)
Converts geographic coordinates (longitude, latitude, altitude) to Cartesian coordinates.
Definition: mptrac.c:905
#define DIST2(a, b)
Calculate the squared Euclidean distance between two points in Cartesian coordinates.
Definition: mptrac.h:568
double met_detrend
FWHM of horizontal Gaussian used for detrending [km].
Definition: mptrac.h:2540
Here is the call graph for this function:

◆ read_met_extrapolate()

void read_met_extrapolate ( met_t met)

Extrapolates meteorological data.

This function extrapolates meteorological data by filling missing or invalid data points with values from the nearest valid point above. Extrapolation is performed column-wise, ensuring that missing data points are replaced with valid values.

Parameters
metA pointer to a structure containing meteorological data.

The function performs the following steps:

  • Sets up a timer to monitor the extrapolation time.
  • Loops over each grid column in parallel.
  • Finds the lowest valid data point within each column.
  • Extrapolates missing or invalid data points by copying values from the nearest valid point above.
  • Updates the meteorological data structure with the extrapolated values.
Note
Extrapolation is performed by copying values from the nearest valid point above to fill missing or invalid data points. OpenMP is utilized for parallelization to enhance performance by distributing the computation across multiple threads.
Author
Lars Hoffmann

Definition at line 6202 of file mptrac.c.

6203 {
6204
6205 /* Set timer... */
6206 SELECT_TIMER("READ_MET_EXTRAPOLATE", "METPROC", NVTX_READ);
6207 LOG(2, "Extrapolate meteo data...");
6208
6209 /* Loop over columns... */
6210#pragma omp parallel for default(shared) collapse(2)
6211 for (int ix = 0; ix < met->nx; ix++)
6212 for (int iy = 0; iy < met->ny; iy++) {
6213
6214 /* Find lowest valid data point... */
6215 int ip0;
6216 for (ip0 = met->np - 1; ip0 >= 0; ip0--)
6217 if (!isfinite(met->t[ix][iy][ip0])
6218 || !isfinite(met->u[ix][iy][ip0])
6219 || !isfinite(met->v[ix][iy][ip0])
6220 || !isfinite(met->w[ix][iy][ip0]))
6221 break;
6222
6223 /* Extrapolate... */
6224 for (int ip = ip0; ip >= 0; ip--) {
6225 met->t[ix][iy][ip] = met->t[ix][iy][ip + 1];
6226 met->u[ix][iy][ip] = met->u[ix][iy][ip + 1];
6227 met->v[ix][iy][ip] = met->v[ix][iy][ip + 1];
6228 met->w[ix][iy][ip] = met->w[ix][iy][ip + 1];
6229 met->h2o[ix][iy][ip] = met->h2o[ix][iy][ip + 1];
6230 met->o3[ix][iy][ip] = met->o3[ix][iy][ip + 1];
6231 met->lwc[ix][iy][ip] = met->lwc[ix][iy][ip + 1];
6232 met->rwc[ix][iy][ip] = met->rwc[ix][iy][ip + 1];
6233 met->iwc[ix][iy][ip] = met->iwc[ix][iy][ip + 1];
6234 met->swc[ix][iy][ip] = met->swc[ix][iy][ip + 1];
6235 met->cc[ix][iy][ip] = met->cc[ix][iy][ip + 1];
6236 }
6237 }
6238}

◆ read_met_geopot()

void read_met_geopot ( ctl_t ctl,
met_t met 
)

Calculates geopotential heights from meteorological data.

This function calculates geopotential heights from provided meteorological data using the hydrostatic equation. Geopotential heights are computed column-wise for each grid point based on the temperature, pressure, and surface height information. Optionally, the calculated geopotential heights can be smoothed horizontally using a weighted averaging scheme.

Parameters
ctlA pointer to a structure containing control parameters.
metA pointer to a structure containing meteorological data.

The function performs the following steps:

  • Sets up a timer to monitor the geopotential height calculation time.
  • Calculates the logarithm of pressure levels for efficient computation.
  • Applies the hydrostatic equation to determine geopotential heights based on temperature, pressure, and height information.
  • Optionally, performs horizontal smoothing on the calculated geopotential heights.
  • Updates the meteorological data structure with the computed geopotential heights.
Note
The hydrostatic equation is utilized to calculate geopotential heights, ensuring consistency with atmospheric conditions. Optionally, horizontal smoothing can be applied to the calculated geopotential heights to reduce spatial variability. OpenMP is utilized for parallelization to enhance performance by distributing the computation across multiple threads.
Author
Lars Hoffmann

Definition at line 6242 of file mptrac.c.

6244 {
6245
6246 float *help;
6247
6248 double logp[EP];
6249
6250 int dx = ctl->met_geopot_sx, dy = ctl->met_geopot_sy;
6251
6252 /* Set timer... */
6253 SELECT_TIMER("READ_MET_GEOPOT", "METPROC", NVTX_READ);
6254 LOG(2, "Calculate geopotential heights...");
6255
6256 /* Allocate... */
6257 ALLOC(help, float,
6258 EX * EY * EP);
6259
6260 /* Calculate log pressure... */
6261#pragma omp parallel for default(shared)
6262 for (int ip = 0; ip < met->np; ip++)
6263 logp[ip] = log(met->p[ip]);
6264
6265 /* Apply hydrostatic equation to calculate geopotential heights... */
6266#pragma omp parallel for default(shared) collapse(2)
6267 for (int ix = 0; ix < met->nx; ix++)
6268 for (int iy = 0; iy < met->ny; iy++) {
6269
6270 /* Get surface height and pressure... */
6271 double zs = met->zs[ix][iy];
6272 double lnps = log(met->ps[ix][iy]);
6273
6274 /* Get temperature and water vapor at the surface... */
6275 int ip0 = locate_irr(met->p, met->np, met->ps[ix][iy]);
6276 double ts = LIN(met->p[ip0], met->t[ix][iy][ip0], met->p[ip0 + 1],
6277 met->t[ix][iy][ip0 + 1], met->ps[ix][iy]);
6278 double h2os = LIN(met->p[ip0], met->h2o[ix][iy][ip0], met->p[ip0 + 1],
6279 met->h2o[ix][iy][ip0 + 1], met->ps[ix][iy]);
6280
6281 /* Upper part of profile... */
6282 met->z[ix][iy][ip0 + 1]
6283 = (float) (zs +
6284 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
6285 met->t[ix][iy][ip0 + 1], met->h2o[ix][iy][ip0 + 1]));
6286 for (int ip = ip0 + 2; ip < met->np; ip++)
6287 met->z[ix][iy][ip]
6288 = (float) (met->z[ix][iy][ip - 1] +
6289 ZDIFF(logp[ip - 1], met->t[ix][iy][ip - 1],
6290 met->h2o[ix][iy][ip - 1], logp[ip],
6291 met->t[ix][iy][ip], met->h2o[ix][iy][ip]));
6292
6293 /* Lower part of profile... */
6294 met->z[ix][iy][ip0]
6295 = (float) (zs +
6296 ZDIFF(lnps, ts, h2os, logp[ip0],
6297 met->t[ix][iy][ip0], met->h2o[ix][iy][ip0]));
6298 for (int ip = ip0 - 1; ip >= 0; ip--)
6299 met->z[ix][iy][ip]
6300 = (float) (met->z[ix][iy][ip + 1] +
6301 ZDIFF(logp[ip + 1], met->t[ix][iy][ip + 1],
6302 met->h2o[ix][iy][ip + 1], logp[ip],
6303 met->t[ix][iy][ip], met->h2o[ix][iy][ip]));
6304 }
6305
6306 /* Check control parameters... */
6307 if (dx == 0 || dy == 0)
6308 return;
6309
6310 /* Default smoothing parameters... */
6311 if (dx < 0 || dy < 0) {
6312 if (fabs(met->lon[1] - met->lon[0]) < 0.5) {
6313 dx = 3;
6314 dy = 2;
6315 } else {
6316 dx = 6;
6317 dy = 4;
6318 }
6319 }
6320
6321 /* Calculate weights for smoothing... */
6322 float ws[dx + 1][dy + 1];
6323#pragma omp parallel for default(shared) collapse(2)
6324 for (int ix = 0; ix <= dx; ix++)
6325 for (int iy = 0; iy < dy; iy++)
6326 ws[ix][iy] = (1.0f - (float) ix / (float) dx)
6327 * (1.0f - (float) iy / (float) dy);
6328
6329 /* Copy data... */
6330#pragma omp parallel for default(shared) collapse(3)
6331 for (int ix = 0; ix < met->nx; ix++)
6332 for (int iy = 0; iy < met->ny; iy++)
6333 for (int ip = 0; ip < met->np; ip++)
6334 help[ARRAY_3D(ip, ix, met->nx, iy, met->ny)] = met->z[ix][iy][ip];
6335
6336 /* Horizontal smoothing... */
6337#pragma omp parallel for default(shared) collapse(3)
6338 for (int ip = 0; ip < met->np; ip++)
6339 for (int ix = 0; ix < met->nx; ix++)
6340 for (int iy = 0; iy < met->ny; iy++) {
6341 float res = 0, wsum = 0;
6342 int iy0 = MAX(iy - dy + 1, 0);
6343 int iy1 = MIN(iy + dy - 1, met->ny - 1);
6344 for (int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
6345 int ix3 = ix2;
6346 if (ix3 < 0)
6347 ix3 += met->nx;
6348 else if (ix3 >= met->nx)
6349 ix3 -= met->nx;
6350 for (int iy2 = iy0; iy2 <= iy1; ++iy2)
6351 if (isfinite(help[ARRAY_3D(ip, ix3, met->nx, iy2, met->ny)])) {
6352 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
6353 res += w * help[ARRAY_3D(ip, ix3, met->nx, iy2, met->ny)];
6354 wsum += w;
6355 }
6356 }
6357 if (wsum > 0)
6358 met->z[ix][iy][ip] = res / wsum;
6359 else
6360 met->z[ix][iy][ip] = NAN;
6361 }
6362
6363 /* Free... */
6364 free(help);
6365}
#define ZDIFF(lnp0, t0, h2o0, lnp1, t1, h2o1)
Calculate geopotential height difference.
Definition: mptrac.h:1737
Here is the call graph for this function:

◆ read_met_grid()

void read_met_grid ( const char *  filename,
int  ncid,
ctl_t ctl,
met_t met 
)

Reads meteorological grid information from a NetCDF file.

This function reads meteorological grid information from a NetCDF file, including time, spatial dimensions, and pressure levels. It also extracts longitudes, latitudes, and pressure levels from the NetCDF file based on the specified control parameters. The function determines the time information either from the filename or from the data file, depending on the file type.

Parameters
filenameThe filename of the NetCDF file.
ncidThe NetCDF file identifier.
ctlA pointer to a structure containing control parameters.
metA pointer to a structure to store meteorological data.

The function performs the following steps:

  • Sets up a timer to monitor the reading time for meteorological grid information.
  • Determines the time information from either the filename or the data file based on the file type.
  • Checks the validity of the time information.
  • Retrieves grid dimensions (longitude, latitude, and vertical levels) from the NetCDF file.
  • Reads longitudes, latitudes, and pressure levels from the NetCDF file.
  • Converts pressure levels to hPa if necessary.
  • Logs the retrieved grid information for verification and debugging purposes.
Note
This function supports reading meteorological grid information from different types of NetCDF files, including MPTRAC and CLaMS. The time information is extracted either from the filename or from the data file, depending on the file type and control parameters. Spatial dimensions (longitude, latitude, and vertical levels) and pressure levels are retrieved from the NetCDF file.
Authors
Lars Hoffmann
Jan Clemens

Definition at line 6369 of file mptrac.c.

6373 {
6374
6375 char levname[LEN], tstr[10];
6376
6377 double rtime = 0, r, r2;
6378
6379 int varid, year2, mon2, day2, hour2, min2, sec2,
6380 year, mon, day, hour, min, sec;
6381
6382 size_t np;
6383
6384 /* Set timer... */
6385 SELECT_TIMER("READ_MET_GRID", "INPUT", NVTX_READ);
6386 LOG(2, "Read meteo grid information...");
6387
6388 /* MPTRAC meteo files... */
6389 if (ctl->met_clams == 0) {
6390
6391 /* Get time from filename... */
6392 met->time = time_from_filename(filename, 16);
6393
6394 /* Check time information from data file... */
6395 jsec2time(met->time, &year, &mon, &day, &hour, &min, &sec, &r);
6396 if (nc_inq_varid(ncid, "time", &varid) == NC_NOERR) {
6397 NC(nc_get_var_double(ncid, varid, &rtime));
6398 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
6399 WARN("Time information in meteo file does not match filename!");
6400 } else
6401 WARN("Time information in meteo file is missing!");
6402 }
6403
6404 /* CLaMS meteo files... */
6405 else {
6406
6407 /* Read time from file... */
6408 NC_GET_DOUBLE("time", &rtime, 0);
6409
6410 /* Get time from filename (considering the century)... */
6411 if (rtime < 0)
6412 sprintf(tstr, "19%.2s", &filename[strlen(filename) - 11]);
6413 else
6414 sprintf(tstr, "20%.2s", &filename[strlen(filename) - 11]);
6415 year = atoi(tstr);
6416 sprintf(tstr, "%.2s", &filename[strlen(filename) - 9]);
6417 mon = atoi(tstr);
6418 sprintf(tstr, "%.2s", &filename[strlen(filename) - 7]);
6419 day = atoi(tstr);
6420 sprintf(tstr, "%.2s", &filename[strlen(filename) - 5]);
6421 hour = atoi(tstr);
6422 time2jsec(year, mon, day, hour, 0, 0, 0, &met->time);
6423 }
6424
6425 /* Check time... */
6426 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
6427 || day < 1 || day > 31 || hour < 0 || hour > 23)
6428 ERRMSG("Cannot read time from filename!");
6429 jsec2time(met->time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
6430 LOG(2, "Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
6431 met->time, year2, mon2, day2, hour2, min2);
6432
6433 /* Get grid dimensions... */
6434 NC_INQ_DIM("lon", &met->nx, 2, EX);
6435 LOG(2, "Number of longitudes: %d", met->nx);
6436
6437 NC_INQ_DIM("lat", &met->ny, 2, EY);
6438 LOG(2, "Number of latitudes: %d", met->ny);
6439
6440 int dimid2;
6441 sprintf(levname, "lev");
6442 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
6443 sprintf(levname, "plev");
6444 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
6445 sprintf(levname, "hybrid");
6446
6447 NC_INQ_DIM(levname, &met->np, 1, EP);
6448 if (met->np == 1) {
6449 sprintf(levname, "lev_2");
6450 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR) {
6451 sprintf(levname, "plev");
6452 NC(nc_inq_dimid(ncid, levname, &dimid2));
6453 }
6454 NC(nc_inq_dimlen(ncid, dimid2, &np));
6455 met->np = (int) np;
6456 }
6457 LOG(2, "Number of levels: %d", met->np);
6458 if (met->np < 2 || met->np > EP)
6459 ERRMSG("Number of levels out of range!");
6460
6461 /* Read longitudes and latitudes... */
6462 NC_GET_DOUBLE("lon", met->lon, 1);
6463 LOG(2, "Longitudes: %g, %g ... %g deg",
6464 met->lon[0], met->lon[1], met->lon[met->nx - 1]);
6465 NC_GET_DOUBLE("lat", met->lat, 1);
6466 LOG(2, "Latitudes: %g, %g ... %g deg",
6467 met->lat[0], met->lat[1], met->lat[met->ny - 1]);
6468
6469 /* Read pressure levels... */
6470 if (ctl->met_np <= 0) {
6471 NC_GET_DOUBLE(levname, met->p, 1);
6472 for (int ip = 0; ip < met->np; ip++)
6473 met->p[ip] /= 100.;
6474 LOG(2, "Altitude levels: %g, %g ... %g km",
6475 Z(met->p[0]), Z(met->p[1]), Z(met->p[met->np - 1]));
6476 LOG(2, "Pressure levels: %g, %g ... %g hPa",
6477 met->p[0], met->p[1], met->p[met->np - 1]);
6478 }
6479
6480 /* Read hybrid levels... */
6481 if (strcasecmp(levname, "hybrid") == 0)
6482 NC_GET_DOUBLE("hybrid", met->hybrid, 1);
6483}
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.
Definition: mptrac.c:8123
double time_from_filename(const char *filename, int offset)
Extracts and converts a timestamp from a filename to Julian seconds.
Definition: mptrac.c:8222
double hybrid[EP]
Model hybrid levels.
Definition: mptrac.h:3314
Here is the call graph for this function:

◆ read_met_levels()

void read_met_levels ( int  ncid,
ctl_t ctl,
met_t met 
)

Reads meteorological variables at different vertical levels from a NetCDF file.

This function reads meteorological variables such as temperature, wind components, specific humidity, ozone data, cloud parameters, and cloud cover at various vertical levels from a NetCDF file. The function supports reading meteorological data from both MPTRAC and CLaMS formats. Depending on the file format, it reads specific variables and performs necessary conversions or interpolations.

Parameters
ncidThe NetCDF file identifier.
ctlA pointer to a structure containing control parameters.
metA pointer to a structure to store meteorological data.

The function performs the following steps:

  • Sets up a timer to monitor the reading time for meteorological level data.
  • Reads meteorological variables from the NetCDF file based on the specified control parameters and file format.
  • Handles specific variables differently depending on the file format, such as reading temperature, wind components, humidity, ozone data, and cloud parameters.
  • Performs conversions or interpolations if necessary, such as converting specific humidity and ozone data from mixing ratio to volume mixing ratio.
  • Transfers velocity components to model levels for diabatic advection if applicable.
  • Reads pressure on model levels if specified in the control parameters.
  • Performs vertical interpolation from model levels to pressure levels if needed.
  • Checks the ordering of pressure levels to ensure they are in descending order.
Note
This function supports reading meteorological variables from NetCDF files in MPTRAC or CLaMS formats and handles specific variables differently based on the file format and control parameters. It performs necessary conversions or interpolations and ensures the correctness of pressure levels.
Authors
Lars Hoffmann
Jan Clemens

Definition at line 6487 of file mptrac.c.

6490 {
6491
6492 /* Set timer... */
6493 SELECT_TIMER("READ_MET_LEVELS", "INPUT", NVTX_READ);
6494 LOG(2, "Read level data...");
6495
6496 /* Read temperature... */
6497 if (!read_met_nc_3d(ncid, "t", "T", "temp", "TEMP", ctl, met, met->t, 1.0))
6498 ERRMSG("Cannot read temperature!");
6499
6500 /* Read horizontal wind and vertical velocity... */
6501 if (!read_met_nc_3d(ncid, "u", "U", NULL, NULL, ctl, met, met->u, 1.0))
6502 ERRMSG("Cannot read zonal wind!");
6503 if (!read_met_nc_3d(ncid, "v", "V", NULL, NULL, ctl, met, met->v, 1.0))
6504 ERRMSG("Cannot read meridional wind!");
6505 if (!read_met_nc_3d
6506 (ncid, "w", "W", "omega", "OMEGA", ctl, met, met->w, 0.01f))
6507 WARN("Cannot read vertical velocity!");
6508
6509 /* Read water vapor... */
6510 if (!ctl->met_relhum) {
6511 if (!read_met_nc_3d
6512 (ncid, "q", "Q", "sh", "SH", ctl, met, met->h2o, (float) (MA / MH2O)))
6513 WARN("Cannot read specific humidity!");
6514 } else {
6515 if (!read_met_nc_3d
6516 (ncid, "rh", "RH", NULL, NULL, ctl, met, met->h2o, 0.01f))
6517 WARN("Cannot read relative humidity!");
6518#pragma omp parallel for default(shared) collapse(2)
6519 for (int ix = 0; ix < met->nx; ix++)
6520 for (int iy = 0; iy < met->ny; iy++)
6521 for (int ip = 0; ip < met->np; ip++) {
6522 double pw = met->h2o[ix][iy][ip] * PSAT(met->t[ix][iy][ip]);
6523 met->h2o[ix][iy][ip] =
6524 (float) (pw / (met->p[ip] - (1.0 - EPS) * pw));
6525 }
6526 }
6527
6528 /* Read ozone... */
6529 if (!read_met_nc_3d
6530 (ncid, "o3", "O3", NULL, NULL, ctl, met, met->o3, (float) (MA / MO3)))
6531 WARN("Cannot read ozone data!");
6532
6533 /* Read cloud data... */
6534 if (!read_met_nc_3d
6535 (ncid, "clwc", "CLWC", NULL, NULL, ctl, met, met->lwc, 1.0))
6536 WARN("Cannot read cloud liquid water content!");
6537 if (!read_met_nc_3d
6538 (ncid, "crwc", "CRWC", NULL, NULL, ctl, met, met->rwc, 1.0))
6539 WARN("Cannot read cloud rain water content!");
6540 if (!read_met_nc_3d
6541 (ncid, "ciwc", "CIWC", NULL, NULL, ctl, met, met->iwc, 1.0))
6542 WARN("Cannot read cloud ice water content!");
6543 if (!read_met_nc_3d
6544 (ncid, "cswc", "CSWC", NULL, NULL, ctl, met, met->swc, 1.0))
6545 WARN("Cannot read cloud snow water content!");
6546 if (!read_met_nc_3d(ncid, "cc", "CC", NULL, NULL, ctl, met, met->cc, 1.0))
6547 WARN("Cannot read cloud cover!");
6548
6549 /* Read zeta and zeta_dot... */
6550 if (!read_met_nc_3d
6551 (ncid, "ZETA", "zeta", NULL, NULL, ctl, met, met->zetal, 1.0))
6552 WARN("Cannot read ZETA in meteo data!");
6553 if (ctl->advect_vert_coord == 1) {
6554 if (!read_met_nc_3d
6555 (ncid, "ZETA_DOT_TOT", "zeta_dot_clr", NULL, NULL, ctl, met,
6556 met->zeta_dotl, 0.00001157407f)) {
6557 if (!read_met_nc_3d
6558 (ncid, "ZETA_DOT_TOT", "ZETA_DOT_clr", NULL, NULL, ctl, met,
6559 met->zeta_dotl, 0.00001157407f)) {
6560 WARN("Cannot read vertical velocity!");
6561 }
6562 }
6563 }
6564
6565 /* Store velocities on model levels for diabatic advection... */
6566 if (ctl->met_vert_coord == 1) {
6567 for (int ix = 0; ix < met->nx; ix++)
6568 for (int iy = 0; iy < met->ny; iy++)
6569 for (int ip = 0; ip < met->np; ip++) {
6570 met->ul[ix][iy][ip] = met->u[ix][iy][ip];
6571 met->vl[ix][iy][ip] = met->v[ix][iy][ip];
6572 met->wl[ix][iy][ip] = met->w[ix][iy][ip];
6573 }
6574
6575 /* Original number of vertical levels... */
6576 met->npl = met->np;
6577 }
6578
6579 /* Read pressure on model levels... */
6580 if (ctl->met_np > 0 || ctl->met_vert_coord == 1) {
6581
6582 /* Read data... */
6583 if (!read_met_nc_3d
6584 (ncid, "pl", "PL", "pressure", "PRESSURE", ctl, met, met->pl, 0.01f))
6585 if (!read_met_nc_3d
6586 (ncid, "press", "PRESS", NULL, NULL, ctl, met, met->pl, 1.0))
6587 ERRMSG("Cannot read pressure on model levels!");
6588
6589 /* Check ordering of pressure levels... */
6590 for (int ix = 0; ix < met->nx; ix++)
6591 for (int iy = 0; iy < met->ny; iy++)
6592 for (int ip = 1; ip < met->np; ip++)
6593 if ((met->pl[ix][iy][0] > met->pl[ix][iy][1]
6594 && met->pl[ix][iy][ip - 1] <= met->pl[ix][iy][ip])
6595 || (met->pl[ix][iy][0] < met->pl[ix][iy][1]
6596 && met->pl[ix][iy][ip - 1] >= met->pl[ix][iy][ip]))
6597 ERRMSG("Pressure profiles are not monotonic!");
6598 }
6599
6600 /* Interpolate from model levels to pressure levels... */
6601 if (ctl->met_np > 0) {
6602
6603 /* Interpolate variables... */
6604 read_met_ml2pl(ctl, met, met->t, "T");
6605 read_met_ml2pl(ctl, met, met->u, "U");
6606 read_met_ml2pl(ctl, met, met->v, "V");
6607 read_met_ml2pl(ctl, met, met->w, "W");
6608 read_met_ml2pl(ctl, met, met->h2o, "H2O");
6609 read_met_ml2pl(ctl, met, met->o3, "O3");
6610 read_met_ml2pl(ctl, met, met->lwc, "LWC");
6611 read_met_ml2pl(ctl, met, met->rwc, "RWC");
6612 read_met_ml2pl(ctl, met, met->iwc, "IWC");
6613 read_met_ml2pl(ctl, met, met->swc, "SWC");
6614 read_met_ml2pl(ctl, met, met->cc, "CC");
6615
6616 /* Set new pressure levels... */
6617 met->np = ctl->met_np;
6618 for (int ip = 0; ip < met->np; ip++)
6619 met->p[ip] = ctl->met_p[ip];
6620 }
6621
6622 /* Check ordering of pressure levels... */
6623 for (int ip = 1; ip < met->np; ip++)
6624 if (met->p[ip - 1] < met->p[ip])
6625 ERRMSG("Pressure levels must be descending!");
6626}
void read_met_ml2pl(ctl_t *ctl, met_t *met, float var[EX][EY][EP], char *varname)
Interpolates meteorological data to specified pressure levels.
Definition: mptrac.c:6630
int read_met_nc_3d(int ncid, char *varname, char *varname2, char *varname3, char *varname4, ctl_t *ctl, met_t *met, float dest[EX][EY][EP], float scl)
Reads a 3-dimensional meteorological variable from a NetCDF file.
Definition: mptrac.c:6901
#define MH2O
Molar mass of water vapor [g/mol].
Definition: mptrac.h:197
#define MO3
Molar mass of ozone [g/mol].
Definition: mptrac.h:202
int met_vert_coord
Vertical coordinate of input meteo data (0=pressure-level, 1=model-level).
Definition: mptrac.h:2150
Here is the call graph for this function:

◆ read_met_ml2pl()

void read_met_ml2pl ( ctl_t ctl,
met_t met,
float  var[EX][EY][EP],
char *  varname 
)

Interpolates meteorological data to specified pressure levels.

This function interpolates meteorological data from model levels to pressure levels. The interpolation is performed in parallel over the spatial grid defined in the meteorological data structure.

Parameters
[in]ctlA pointer to a control structure containing the number of pressure levels (met_np) and the pressure levels themselves (met_p).
[in]metA pointer to a meteorological data structure containing the grid dimensions (nx, ny) and the pressure profile (pl).
[in,out]varA 3D array containing the meteorological variable to be interpolated. On output, this array will contain the interpolated values at the specified pressure levels.
[in]varnameA string representing the name of the meteorological variable being interpolated.

This function performs the following steps:

  • Sets a timer for the operation.
  • Logs the start of the interpolation process with the variable name.
  • Loops over the spatial columns (grid points).
  • For each column, copies the pressure profile.
  • Interpolates the meteorological variable to the specified pressure levels.
  • Copies the interpolated data back into the var array.
Note
The interpolation is performed in parallel using OpenMP.
Author
Lars Hoffmann

Definition at line 6630 of file mptrac.c.

6634 {
6635
6636 double aux[EP], p[EP];
6637
6638 /* Set timer... */
6639 SELECT_TIMER("READ_MET_ML2PL", "METPROC", NVTX_READ);
6640 LOG(2, "Interpolate meteo data to pressure levels: %s", varname);
6641
6642 /* Loop over columns... */
6643#pragma omp parallel for default(shared) private(aux,p) collapse(2)
6644 for (int ix = 0; ix < met->nx; ix++)
6645 for (int iy = 0; iy < met->ny; iy++) {
6646
6647 /* Copy pressure profile... */
6648 for (int ip = 0; ip < met->np; ip++)
6649 p[ip] = met->pl[ix][iy][ip];
6650
6651 /* Interpolate... */
6652 for (int ip = 0; ip < ctl->met_np; ip++) {
6653 double pt = ctl->met_p[ip];
6654 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
6655 pt = p[0];
6656 else if ((pt > p[met->np - 1] && p[1] > p[0])
6657 || (pt < p[met->np - 1] && p[1] < p[0]))
6658 pt = p[met->np - 1];
6659 int ip2 = locate_irr(p, met->np, pt);
6660 aux[ip] = LIN(p[ip2], var[ix][iy][ip2],
6661 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
6662 }
6663
6664 /* Copy data... */
6665 for (int ip = 0; ip < ctl->met_np; ip++)
6666 var[ix][iy][ip] = (float) aux[ip];
6667 }
6668}
Here is the call graph for this function:

◆ read_met_monotonize()

void read_met_monotonize ( met_t met)

Makes zeta and pressure profiles monotone.

This function ensures that zeta and pressure profiles are monotone increasing and decreasing with altitude. It iterates over each grid point and each level to identify inversions and linearly interpolate between them to maintain monotonicity. The interpolation is performed for both zeta and pressure profiles.

Parameters
metA pointer to a structure containing meteorological data.

The function performs the following steps:

  • Sets up a timer to monitor the processing time.
  • Iterates over each grid point in parallel using OpenMP.
  • Identifies inversions in both zeta and pressure profiles and interpolates linearly between them to make the profiles monotone increasing.
Note
This function is crucial for maintaining the physical consistency of meteorological profiles, ensuring accurate atmospheric simulations.
Author
Jan Clemens

Definition at line 6672 of file mptrac.c.

6673 {
6674
6675 /* Set timer... */
6676 SELECT_TIMER("READ_MET_MONOTONIZE", "METPROC", NVTX_READ);
6677 LOG(2, "Make zeta profiles monotone...");
6678
6679 /* Create monotone zeta profiles... */
6680#pragma omp parallel for default(shared) collapse(2)
6681 for (int i = 0; i < met->nx; i++)
6682 for (int j = 0; j < met->ny; j++) {
6683 int k = 1;
6684
6685 while (k < met->npl) { /* Check if there is an inversion at level k... */
6686 if ((met->zetal[i][j][k - 1] >= met->zetal[i][j][k])) {
6687 /* Find the upper level k+l over the inversion... */
6688 int l = 0;
6689 do {
6690 l++;
6691 }
6692 while ((met->zetal[i][j][k - 1] >=
6693 met->zetal[i][j][k + l]) & (k + l < met->npl));
6694
6695 /* Interpolate linear between the top and bottom
6696 of the inversion... */
6697 float s =
6698 (float) (met->zetal[i][j][k + l] - met->zetal[i][j][k - 1])
6699 / (float) (met->hybrid[k + l] - met->hybrid[k - 1]);
6700
6701 for (int m = k; m < k + l; m++) {
6702 float d = (float) (met->hybrid[m] - met->hybrid[k - 1]);
6703 met->zetal[i][j][m] = s * d + met->zetal[i][j][k - 1];
6704 }
6705
6706 /* Search for more inversions above the last inversion ... */
6707 k = k + l;
6708 } else {
6709 k++;
6710 }
6711 }
6712 }
6713
6714 /* Create monotone pressure profiles... */
6715#pragma omp parallel for default(shared) collapse(2)
6716 for (int i = 0; i < met->nx; i++)
6717 for (int j = 0; j < met->ny; j++) {
6718 int k = 1;
6719
6720 while (k < met->npl) { /* Check if there is an inversion at level k... */
6721 if ((met->pl[i][j][k - 1] <= met->pl[i][j][k])) {
6722 /* Find the upper level k+l over the inversion... */
6723 int l = 0;
6724 do {
6725 l++;
6726 }
6727 while ((met->pl[i][j][k - 1] <= met->pl[i][j][k + l]) & (k + l <
6728 met->npl));
6729
6730 /* Interpolate linear between the top and bottom
6731 of the inversion... */
6732 float s = (float) (met->pl[i][j][k + l] - met->pl[i][j][k - 1])
6733 / (float) (met->hybrid[k + l] - met->hybrid[k - 1]);
6734
6735 for (int m = k; m < k + l; m++) {
6736 float d = (float) (met->hybrid[m] - met->hybrid[k - 1]);
6737 met->pl[i][j][m] = s * d + met->pl[i][j][k - 1];
6738 }
6739
6740 /* Search for more inversions above the last inversion ... */
6741 k = k + l;
6742 } else {
6743 k++;
6744 }
6745 }
6746 }
6747}

◆ read_met_nc_2d()

int read_met_nc_2d ( int  ncid,
char *  varname,
char *  varname2,
char *  varname3,
char *  varname4,
ctl_t ctl,
met_t met,
float  dest[EX][EY],
float  scl,
int  init 
)

Reads a 2-dimensional meteorological variable from a NetCDF file.

This function reads a 2-dimensional meteorological variable from a NetCDF file and stores it in a specified destination array. It supports both packed and unpacked data formats and handles missing values and scaling factors accordingly. The function also checks the meteorological data layout to ensure correct data copying.

Parameters
ncidThe NetCDF file ID.
varnameThe name of the variable to read.
varname2An alternative name of the variable to read (in case varname is not found).
varname3An alternative name of the variable to read (in case varname2 is not found).
varname4An alternative name of the variable to read (in case varname3 is not found).
ctlA pointer to a structure containing control parameters.
metA pointer to a structure containing meteorological data.
destThe destination array to store the read data.
sclA scaling factor to apply to the read data.
initFlag indicating whether to initialize the destination array before reading.
Returns
Returns 1 on success, 0 on failure.

The function performs the following steps:

  • Checks if the specified variable exists in the NetCDF file.
  • Reads packed data if scaling factors are available, otherwise reads unpacked data.
  • Handles missing values and scaling factors appropriately.
  • Copies the data to the destination array, applying the scaling factor if provided.
Author
Lars Hoffmann

Definition at line 6751 of file mptrac.c.

6761 {
6762
6763 char varsel[LEN];
6764
6765 float offset, scalfac;
6766
6767 int varid;
6768
6769 /* Check if variable exists... */
6770 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
6771 sprintf(varsel, "%s", varname);
6772 else if (varname2 != NULL
6773 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
6774 sprintf(varsel, "%s", varname2);
6775 else if (varname3 != NULL
6776 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
6777 sprintf(varsel, "%s", varname3);
6778 else if (varname4 != NULL
6779 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
6780 sprintf(varsel, "%s", varname4);
6781 else
6782 return 0;
6783
6784 /* Read packed data... */
6785 if (ctl->met_nc_scale
6786 && nc_get_att_float(ncid, varid, "add_offset", &offset) == NC_NOERR
6787 && nc_get_att_float(ncid, varid, "scale_factor",
6788 &scalfac) == NC_NOERR) {
6789
6790 /* Allocate... */
6791 short *help;
6792 ALLOC(help, short,
6793 EX * EY * EP);
6794
6795 /* Read fill value and missing value... */
6796 short fillval, missval;
6797 if (nc_get_att_short(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
6798 fillval = 0;
6799 if (nc_get_att_short(ncid, varid, "missing_value", &missval) != NC_NOERR)
6800 missval = 0;
6801
6802 /* Write info... */
6803 LOG(2, "Read 2-D variable: %s"
6804 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
6805 varsel, fillval, missval, scalfac, offset);
6806
6807 /* Read data... */
6808 NC(nc_get_var_short(ncid, varid, help));
6809
6810 /* Check meteo data layout... */
6811 if (ctl->met_convention != 0)
6812 ERRMSG("Meteo data layout not implemented for packed netCDF files!");
6813
6814 /* Copy and check data... */
6815#pragma omp parallel for default(shared) num_threads(12)
6816 for (int ix = 0; ix < met->nx; ix++)
6817 for (int iy = 0; iy < met->ny; iy++) {
6818 if (init)
6819 dest[ix][iy] = 0;
6820 short aux = help[ARRAY_2D(iy, ix, met->nx)];
6821 if ((fillval == 0 || aux != fillval)
6822 && (missval == 0 || aux != missval)
6823 && fabsf(aux * scalfac + offset) < 1e14f)
6824 dest[ix][iy] += scl * (aux * scalfac + offset);
6825 else
6826 dest[ix][iy] = NAN;
6827 }
6828
6829 /* Free... */
6830 free(help);
6831 }
6832
6833 /* Unpacked data... */
6834 else {
6835
6836 /* Allocate... */
6837 float *help;
6838 ALLOC(help, float,
6839 EX * EY);
6840
6841 /* Read fill value and missing value... */
6842 float fillval, missval;
6843 if (nc_get_att_float(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
6844 fillval = 0;
6845 if (nc_get_att_float(ncid, varid, "missing_value", &missval) != NC_NOERR)
6846 missval = 0;
6847
6848 /* Write info... */
6849 LOG(2, "Read 2-D variable: %s (FILL = %g, MISS = %g)",
6850 varsel, fillval, missval);
6851
6852 /* Read data... */
6853 NC(nc_get_var_float(ncid, varid, help));
6854
6855 /* Check meteo data layout... */
6856 if (ctl->met_convention == 0) {
6857
6858 /* Copy and check data (ordering: lat, lon)... */
6859#pragma omp parallel for default(shared) num_threads(12)
6860 for (int ix = 0; ix < met->nx; ix++)
6861 for (int iy = 0; iy < met->ny; iy++) {
6862 if (init)
6863 dest[ix][iy] = 0;
6864 float aux = help[ARRAY_2D(iy, ix, met->nx)];
6865 if ((fillval == 0 || aux != fillval)
6866 && (missval == 0 || aux != missval)
6867 && fabsf(aux) < 1e14f)
6868 dest[ix][iy] += scl * aux;
6869 else
6870 dest[ix][iy] = NAN;
6871 }
6872
6873 } else {
6874
6875 /* Copy and check data (ordering: lon, lat)... */
6876#pragma omp parallel for default(shared) num_threads(12)
6877 for (int iy = 0; iy < met->ny; iy++)
6878 for (int ix = 0; ix < met->nx; ix++) {
6879 if (init)
6880 dest[ix][iy] = 0;
6881 float aux = help[ARRAY_2D(ix, iy, met->ny)];
6882 if ((fillval == 0 || aux != fillval)
6883 && (missval == 0 || aux != missval)
6884 && fabsf(aux) < 1e14f)
6885 dest[ix][iy] += scl * aux;
6886 else
6887 dest[ix][iy] = NAN;
6888 }
6889 }
6890
6891 /* Free... */
6892 free(help);
6893 }
6894
6895 /* Return... */
6896 return 1;
6897}
int met_nc_scale
Check netCDF scaling factors (0=no, 1=yes).
Definition: mptrac.h:2467
int met_convention
Meteo data layout (0=[lev, lat, lon], 1 = [lon, lat, lev]).
Definition: mptrac.h:2461

◆ read_met_nc_3d()

int read_met_nc_3d ( int  ncid,
char *  varname,
char *  varname2,
char *  varname3,
char *  varname4,
ctl_t ctl,
met_t met,
float  dest[EX][EY][EP],
float  scl 
)

Reads a 3-dimensional meteorological variable from a NetCDF file.

This function reads a 3-dimensional meteorological variable from a NetCDF file and stores it in a specified destination array. It supports both packed and unpacked data formats and handles missing values and scaling factors accordingly. The function also checks the meteorological data layout to ensure correct data copying.

Parameters
ncidThe NetCDF file ID.
varnameThe name of the variable to read.
varname2An alternative name of the variable to read (in case varname is not found).
varname3An alternative name of the variable to read (in case varname2 is not found).
varname4An alternative name of the variable to read (in case varname3 is not found).
ctlA pointer to a structure containing control parameters.
metA pointer to a structure containing meteorological data.
destThe destination array to store the read data.
sclA scaling factor to apply to the read data.
Returns
Returns 1 on success, 0 on failure.

The function performs the following steps:

  • Checks if the specified variable exists in the NetCDF file.
  • Reads packed data if scaling factors are available, otherwise reads unpacked data.
  • Handles missing values and scaling factors appropriately.
  • Copies the data to the destination array, applying the scaling factor if provided.
Author
Lars Hoffmann

Definition at line 6901 of file mptrac.c.

6910 {
6911
6912 char varsel[LEN];
6913
6914 float offset, scalfac;
6915
6916 int varid;
6917
6918 /* Check if variable exists... */
6919 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
6920 sprintf(varsel, "%s", varname);
6921 else if (varname2 != NULL
6922 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
6923 sprintf(varsel, "%s", varname2);
6924 else if (varname3 != NULL
6925 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
6926 sprintf(varsel, "%s", varname3);
6927 else if (varname4 != NULL
6928 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
6929 sprintf(varsel, "%s", varname4);
6930 else
6931 return 0;
6932
6933 /* Read packed data... */
6934 if (ctl->met_nc_scale
6935 && nc_get_att_float(ncid, varid, "add_offset", &offset) == NC_NOERR
6936 && nc_get_att_float(ncid, varid, "scale_factor",
6937 &scalfac) == NC_NOERR) {
6938
6939 /* Allocate... */
6940 short *help;
6941 ALLOC(help, short,
6942 EX * EY * EP);
6943
6944 /* Read fill value and missing value... */
6945 short fillval, missval;
6946 if (nc_get_att_short(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
6947 fillval = 0;
6948 if (nc_get_att_short(ncid, varid, "missing_value", &missval) != NC_NOERR)
6949 missval = 0;
6950
6951 /* Write info... */
6952 LOG(2, "Read 3-D variable: %s "
6953 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
6954 varsel, fillval, missval, scalfac, offset);
6955
6956 /* Read data... */
6957 NC(nc_get_var_short(ncid, varid, help));
6958
6959 /* Check meteo data layout... */
6960 if (ctl->met_convention != 0)
6961 ERRMSG("Meteo data layout not implemented for packed netCDF files!");
6962
6963 /* Copy and check data... */
6964#pragma omp parallel for default(shared) num_threads(12)
6965 for (int ix = 0; ix < met->nx; ix++)
6966 for (int iy = 0; iy < met->ny; iy++)
6967 for (int ip = 0; ip < met->np; ip++) {
6968 short aux = help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)];
6969 if ((fillval == 0 || aux != fillval)
6970 && (missval == 0 || aux != missval)
6971 && fabsf(aux * scalfac + offset) < 1e14f)
6972 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
6973 else
6974 dest[ix][iy][ip] = NAN;
6975 }
6976
6977 /* Free... */
6978 free(help);
6979 }
6980
6981 /* Unpacked data... */
6982 else {
6983
6984 /* Allocate... */
6985 float *help;
6986 ALLOC(help, float,
6987 EX * EY * EP);
6988
6989 /* Read fill value and missing value... */
6990 float fillval, missval;
6991 if (nc_get_att_float(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
6992 fillval = 0;
6993 if (nc_get_att_float(ncid, varid, "missing_value", &missval) != NC_NOERR)
6994 missval = 0;
6995
6996 /* Write info... */
6997 LOG(2, "Read 3-D variable: %s (FILL = %g, MISS = %g)",
6998 varsel, fillval, missval);
6999
7000 /* Read data... */
7001 NC(nc_get_var_float(ncid, varid, help));
7002
7003 /* Check meteo data layout... */
7004 if (ctl->met_convention == 0) {
7005
7006 /* Copy and check data (ordering: lev, lat, lon)... */
7007#pragma omp parallel for default(shared) num_threads(12)
7008 for (int ix = 0; ix < met->nx; ix++)
7009 for (int iy = 0; iy < met->ny; iy++)
7010 for (int ip = 0; ip < met->np; ip++) {
7011 float aux = help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)];
7012 if ((fillval == 0 || aux != fillval)
7013 && (missval == 0 || aux != missval)
7014 && fabsf(aux) < 1e14f)
7015 dest[ix][iy][ip] = scl * aux;
7016 else
7017 dest[ix][iy][ip] = NAN;
7018 }
7019
7020 } else {
7021
7022 /* Copy and check data (ordering: lon, lat, lev)... */
7023#pragma omp parallel for default(shared) num_threads(12)
7024 for (int ip = 0; ip < met->np; ip++)
7025 for (int iy = 0; iy < met->ny; iy++)
7026 for (int ix = 0; ix < met->nx; ix++) {
7027 float aux = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
7028 if ((fillval == 0 || aux != fillval)
7029 && (missval == 0 || aux != missval)
7030 && fabsf(aux) < 1e14f)
7031 dest[ix][iy][ip] = scl * aux;
7032 else
7033 dest[ix][iy][ip] = NAN;
7034 }
7035 }
7036
7037 /* Free... */
7038 free(help);
7039 }
7040
7041 /* Return... */
7042 return 1;
7043}

◆ read_met_pbl()

void read_met_pbl ( met_t met)

Calculates the planetary boundary layer (PBL) height for each grid point.

This function estimates the height of the planetary boundary layer (PBL) based on various meteorological parameters. The method used is based on empirical relationships, such as those proposed by Vogelezang and Holtslag (1996) or Seidel et al. (2012). It computes the PBL height by analyzing the vertical profiles of temperature, wind speed, humidity, and pressure.

Parameters
metA pointer to a structure containing meteorological data.

The function performs the following steps:

  • Sets timer for performance monitoring.
  • Iterates over each grid point to calculate the PBL height.
  • Determines the bottom level of the PBL based on pressure and a specified thickness.
  • Finds the lowest model level near the bottom of the PBL.
  • Interpolates meteorological variables to the near-surface level.
  • Computes virtual potential temperature (theta_v) at the surface.
  • Initializes variables for Richardson number calculation.
  • Loops over vertical levels to calculate Richardson number and identify the PBL height.
  • Determines the PBL height based on the critical Richardson number criterion.
  • Stores the calculated PBL height in the meteorological data structure.
Note
This function plays a crucial role in atmospheric modeling applications for characterizing the height of the boundary layer, which influences atmospheric dynamics and pollutant dispersion.
Author
Lars Hoffmann

Definition at line 7047 of file mptrac.c.

7048 {
7049
7050 /* Set timer... */
7051 SELECT_TIMER("READ_MET_PBL", "METPROC", NVTX_READ);
7052 LOG(2, "Calculate planetary boundary layer...");
7053
7054 /* Parameters used to estimate the height of the PBL
7055 (e.g., Vogelezang and Holtslag, 1996; Seidel et al., 2012)... */
7056 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
7057
7058 /* Loop over grid points... */
7059#pragma omp parallel for default(shared) collapse(2)
7060 for (int ix = 0; ix < met->nx; ix++)
7061 for (int iy = 0; iy < met->ny; iy++) {
7062
7063 /* Set bottom level of PBL... */
7064 double pbl_bot = met->ps[ix][iy] + DZ2DP(dz, met->ps[ix][iy]);
7065
7066 /* Find lowest level near the bottom... */
7067 int ip;
7068 for (ip = 1; ip < met->np; ip++)
7069 if (met->p[ip] < pbl_bot)
7070 break;
7071
7072 /* Get near surface data... */
7073 double zs = LIN(met->p[ip - 1], met->z[ix][iy][ip - 1],
7074 met->p[ip], met->z[ix][iy][ip], pbl_bot);
7075 double ts = LIN(met->p[ip - 1], met->t[ix][iy][ip - 1],
7076 met->p[ip], met->t[ix][iy][ip], pbl_bot);
7077 double us = LIN(met->p[ip - 1], met->u[ix][iy][ip - 1],
7078 met->p[ip], met->u[ix][iy][ip], pbl_bot);
7079 double vs = LIN(met->p[ip - 1], met->v[ix][iy][ip - 1],
7080 met->p[ip], met->v[ix][iy][ip], pbl_bot);
7081 double h2os = LIN(met->p[ip - 1], met->h2o[ix][iy][ip - 1],
7082 met->p[ip], met->h2o[ix][iy][ip], pbl_bot);
7083 double tvs = THETAVIRT(pbl_bot, ts, h2os);
7084
7085 /* Init... */
7086 double rib_old = 0;
7087
7088 /* Loop over levels... */
7089 for (; ip < met->np; ip++) {
7090
7091 /* Get squared horizontal wind speed... */
7092 double vh2
7093 = SQR(met->u[ix][iy][ip] - us) + SQR(met->v[ix][iy][ip] - vs);
7094 vh2 = MAX(vh2, SQR(umin));
7095
7096 /* Calculate bulk Richardson number... */
7097 double rib = G0 * 1e3 * (met->z[ix][iy][ip] - zs) / tvs
7098 * (THETAVIRT(met->p[ip], met->t[ix][iy][ip],
7099 met->h2o[ix][iy][ip]) - tvs) / vh2;
7100
7101 /* Check for critical value... */
7102 if (rib >= rib_crit) {
7103 met->pbl[ix][iy] = (float) (LIN(rib_old, met->p[ip - 1],
7104 rib, met->p[ip], rib_crit));
7105 if (met->pbl[ix][iy] > pbl_bot)
7106 met->pbl[ix][iy] = (float) pbl_bot;
7107 break;
7108 }
7109
7110 /* Save Richardson number... */
7111 rib_old = rib;
7112 }
7113 }
7114}
#define THETAVIRT(p, t, h2o)
Compute virtual potential temperature.
Definition: mptrac.h:1638

◆ read_met_periodic()

void read_met_periodic ( met_t met)

Applies periodic boundary conditions to meteorological data along longitudinal axis.

This function applies periodic boundary conditions to meteorological data along the longitudinal axis. It checks if the difference between the last and first longitudes and the difference between the second and first longitudes are approximately equal to 360 degrees, indicating periodicity. If the condition is met, the function increases the longitude counter, sets the longitude value for the new grid point, and copies meteorological data from the first grid point to the last grid point to ensure periodicity.

Parameters
metA pointer to a structure containing meteorological data.

The function performs the following steps:

  • Sets timer for performance monitoring.
  • Checks if the difference between the last and first longitudes and the difference between the second and first longitudes are approximately equal to 360 degrees, indicating periodicity.
  • If periodicity is confirmed:
    • Increases the longitude counter.
    • Sets the longitude value for the new grid point by adding the difference between the second and first longitudes to the longitude of the penultimate grid point.
    • Copies meteorological data from the first grid point to the last grid point to ensure periodicity:
      • Surface variables (e.g., pressure, temperature, wind speed, land-sea mask, sea surface temperature) are copied.
      • Meteorological variables at each pressure level are copied.
      • Meteorological variables at each hybrid pressure level are copied.
Note
This function is useful for generating continuous meteorological fields over a periodic domain, which is common in atmospheric modeling, especially for global simulations.
Author
Lars Hoffmann

Definition at line 7118 of file mptrac.c.

7119 {
7120
7121 /* Set timer... */
7122 SELECT_TIMER("READ_MET_PERIODIC", "METPROC", NVTX_READ);
7123 LOG(2, "Apply periodic boundary conditions...");
7124
7125 /* Check longitudes... */
7126 if (!(fabs(met->lon[met->nx - 1] - met->lon[0]
7127 + met->lon[1] - met->lon[0] - 360) < 0.01))
7128 return;
7129
7130 /* Increase longitude counter... */
7131 if ((++met->nx) >= EX)
7132 ERRMSG("Cannot create periodic boundary conditions!");
7133
7134 /* Set longitude... */
7135 met->lon[met->nx - 1] = met->lon[met->nx - 2] + met->lon[1] - met->lon[0];
7136
7137 /* Loop over latitudes and pressure levels... */
7138#pragma omp parallel for default(shared)
7139 for (int iy = 0; iy < met->ny; iy++) {
7140 met->ps[met->nx - 1][iy] = met->ps[0][iy];
7141 met->zs[met->nx - 1][iy] = met->zs[0][iy];
7142 met->ts[met->nx - 1][iy] = met->ts[0][iy];
7143 met->us[met->nx - 1][iy] = met->us[0][iy];
7144 met->vs[met->nx - 1][iy] = met->vs[0][iy];
7145 met->lsm[met->nx - 1][iy] = met->lsm[0][iy];
7146 met->sst[met->nx - 1][iy] = met->sst[0][iy];
7147 for (int ip = 0; ip < met->np; ip++) {
7148 met->t[met->nx - 1][iy][ip] = met->t[0][iy][ip];
7149 met->u[met->nx - 1][iy][ip] = met->u[0][iy][ip];
7150 met->v[met->nx - 1][iy][ip] = met->v[0][iy][ip];
7151 met->w[met->nx - 1][iy][ip] = met->w[0][iy][ip];
7152 met->h2o[met->nx - 1][iy][ip] = met->h2o[0][iy][ip];
7153 met->o3[met->nx - 1][iy][ip] = met->o3[0][iy][ip];
7154 met->lwc[met->nx - 1][iy][ip] = met->lwc[0][iy][ip];
7155 met->rwc[met->nx - 1][iy][ip] = met->rwc[0][iy][ip];
7156 met->iwc[met->nx - 1][iy][ip] = met->iwc[0][iy][ip];
7157 met->swc[met->nx - 1][iy][ip] = met->swc[0][iy][ip];
7158 met->cc[met->nx - 1][iy][ip] = met->cc[0][iy][ip];
7159 }
7160 for (int ip = 0; ip < met->npl; ip++) {
7161 met->ul[met->nx - 1][iy][ip] = met->ul[0][iy][ip];
7162 met->vl[met->nx - 1][iy][ip] = met->vl[0][iy][ip];
7163 met->wl[met->nx - 1][iy][ip] = met->wl[0][iy][ip];
7164 met->pl[met->nx - 1][iy][ip] = met->pl[0][iy][ip];
7165 met->zetal[met->nx - 1][iy][ip] = met->zetal[0][iy][ip];
7166 met->zeta_dotl[met->nx - 1][iy][ip] = met->zeta_dotl[0][iy][ip];
7167 }
7168 }
7169}

◆ read_met_polar_winds()

void read_met_polar_winds ( met_t met)

Applies a fix for polar winds in meteorological data.

This function applies a fix for polar winds in meteorological data, particularly focusing on the u and v wind components. It checks if the latitudes at the top and bottom of the grid are close to the poles. If so, it transforms the winds at 89-degree latitude into Cartesian coordinates, takes their mean, and replaces the winds at 90-degree latitude with this mean, effectively fixing the unrealistic behavior of winds at the poles.

Parameters
metA pointer to a structure containing meteorological data.

The function performs the following steps:

  • Sets a timer for performance monitoring.
  • Checks if the latitudes at the top and bottom of the grid are close to the poles (within 0.001 degree latitude of the poles).
  • For each hemisphere (north and south):
    • Sets latitude indices for 89 degrees and 90 degrees.
    • Determines the sign of longitude adjustments based on the hemisphere.
    • Constructs lookup tables for cosine and sine of longitudes.
    • Loops over pressure levels and performs the following operations:
      • Transforms u and v wind components at 89 degrees latitude into Cartesian coordinates and calculates their mean.
      • Replaces u and v wind components at 90 degrees latitude with the calculated mean, effectively fixing the polar winds.
Note
This function is useful for correcting unrealistic behavior of winds near the poles in meteorological data, which can affect various atmospheric simulations.
Based on a Python code provided by Jens-Uwe Grooß.
Author
Lars Hoffmann

Definition at line 7173 of file mptrac.c.

7174 {
7175
7176 /* Set timer... */
7177 SELECT_TIMER("READ_MET_POLAR_WINDS", "METPROC", NVTX_READ);
7178 LOG(2, "Apply fix for polar winds...");
7179
7180 /* Check latitudes... */
7181 if (fabs(met->lat[0]) < 89.999 || fabs(met->lat[met->ny - 1]) < 89.999)
7182 return;
7183
7184 /* Loop over hemispheres... */
7185 for (int ihem = 0; ihem < 2; ihem++) {
7186
7187 /* Set latitude indices... */
7188 int i89 = 1, i90 = 0, sign = 1;
7189 if (ihem == 1) {
7190 i89 = met->ny - 2;
7191 i90 = met->ny - 1;
7192 }
7193 if (met->lat[i90] < 0)
7194 sign = -1;
7195
7196 /* Look-up table of cosinus and sinus... */
7197 double clon[EX], slon[EX];
7198#pragma omp parallel for default(shared)
7199 for (int ix = 0; ix < met->nx; ix++) {
7200 clon[ix] = cos(sign * met->lon[ix] / 180. * M_PI);
7201 slon[ix] = sin(sign * met->lon[ix] / 180. * M_PI);
7202 }
7203
7204 /* Loop over levels... */
7205#pragma omp parallel for default(shared)
7206 for (int ip = 0; ip < met->np; ip++) {
7207
7208 /* Transform 89 degree u and v winds into Cartesian coordinates and take the mean... */
7209 double vel89x = 0, vel89y = 0;
7210 for (int ix = 0; ix < met->nx; ix++) {
7211 vel89x +=
7212 (met->u[ix][i89][ip] * clon[ix] -
7213 met->v[ix][i89][ip] * slon[ix]) / met->nx;
7214 vel89y +=
7215 (met->u[ix][i89][ip] * slon[ix] +
7216 met->v[ix][i89][ip] * clon[ix]) / met->nx;
7217 }
7218
7219 /* Replace 90 degree winds by 89 degree mean... */
7220 for (int ix = 0; ix < met->nx; ix++) {
7221 met->u[ix][i90][ip]
7222 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
7223 met->v[ix][i90][ip]
7224 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
7225 }
7226 }
7227 }
7228}

◆ read_met_pv()

void read_met_pv ( met_t met)

Calculates potential vorticity (PV) from meteorological data.

This function calculates the potential vorticity (PV) from the provided meteorological data. It employs finite difference methods to estimate gradients of temperature, wind components, and pressure in longitude, latitude, and pressure dimensions. These gradients are then used to compute PV at each grid point. Additionally, a fix for polar regions is applied to ensure smoothness of PV values in these regions.

Parameters
metA pointer to a structure containing meteorological data.

The function performs the following steps:

  • Sets a timer for performance monitoring.
  • Computes powers for pressure calculation.
  • Loops over grid points in longitude:
    • Sets latitude indices.
    • Loops over grid points in latitude:
      • Sets indices and auxiliary variables.
      • Loops over pressure levels:
        • Computes gradients in longitude, latitude, and pressure.
        • Calculates PV using computed gradients.
  • Applies a fix for polar regions to ensure smoothness of PV values.
Note
Potential vorticity is a fundamental quantity in atmospheric dynamics, representing the potential of a fluid parcel to rotate due to changes in pressure, temperature, and wind fields.
Based on a Python code by Mathew Barlow (https://github.com/mathewbarlow/potential-vorticity).
Author
Lars Hoffmann

Definition at line 7232 of file mptrac.c.

7233 {
7234
7235 double pows[EP];
7236
7237 /* Set timer... */
7238 SELECT_TIMER("READ_MET_PV", "METPROC", NVTX_READ);
7239 LOG(2, "Calculate potential vorticity...");
7240
7241 /* Set powers... */
7242#pragma omp parallel for default(shared)
7243 for (int ip = 0; ip < met->np; ip++)
7244 pows[ip] = pow(1000. / met->p[ip], 0.286);
7245
7246 /* Loop over grid points... */
7247#pragma omp parallel for default(shared)
7248 for (int ix = 0; ix < met->nx; ix++) {
7249
7250 /* Set indices... */
7251 int ix0 = MAX(ix - 1, 0);
7252 int ix1 = MIN(ix + 1, met->nx - 1);
7253
7254 /* Loop over grid points... */
7255 for (int iy = 0; iy < met->ny; iy++) {
7256
7257 /* Set indices... */
7258 int iy0 = MAX(iy - 1, 0);
7259 int iy1 = MIN(iy + 1, met->ny - 1);
7260
7261 /* Set auxiliary variables... */
7262 double latr = 0.5 * (met->lat[iy1] + met->lat[iy0]);
7263 double dx = 1000. * DEG2DX(met->lon[ix1] - met->lon[ix0], latr);
7264 double dy = 1000. * DEG2DY(met->lat[iy1] - met->lat[iy0]);
7265 double c0 = cos(met->lat[iy0] / 180. * M_PI);
7266 double c1 = cos(met->lat[iy1] / 180. * M_PI);
7267 double cr = cos(latr / 180. * M_PI);
7268 double vort = 2 * 7.2921e-5 * sin(latr * M_PI / 180.);
7269
7270 /* Loop over grid points... */
7271 for (int ip = 0; ip < met->np; ip++) {
7272
7273 /* Get gradients in longitude... */
7274 double dtdx
7275 = (met->t[ix1][iy][ip] - met->t[ix0][iy][ip]) * pows[ip] / dx;
7276 double dvdx = (met->v[ix1][iy][ip] - met->v[ix0][iy][ip]) / dx;
7277
7278 /* Get gradients in latitude... */
7279 double dtdy
7280 = (met->t[ix][iy1][ip] - met->t[ix][iy0][ip]) * pows[ip] / dy;
7281 double dudy
7282 = (met->u[ix][iy1][ip] * c1 - met->u[ix][iy0][ip] * c0) / dy;
7283
7284 /* Set indices... */
7285 int ip0 = MAX(ip - 1, 0);
7286 int ip1 = MIN(ip + 1, met->np - 1);
7287
7288 /* Get gradients in pressure... */
7289 double dtdp, dudp, dvdp;
7290 double dp0 = 100. * (met->p[ip] - met->p[ip0]);
7291 double dp1 = 100. * (met->p[ip1] - met->p[ip]);
7292 if (ip != ip0 && ip != ip1) {
7293 double denom = dp0 * dp1 * (dp0 + dp1);
7294 dtdp = (dp0 * dp0 * met->t[ix][iy][ip1] * pows[ip1]
7295 - dp1 * dp1 * met->t[ix][iy][ip0] * pows[ip0]
7296 + (dp1 * dp1 - dp0 * dp0) * met->t[ix][iy][ip] * pows[ip])
7297 / denom;
7298 dudp = (dp0 * dp0 * met->u[ix][iy][ip1]
7299 - dp1 * dp1 * met->u[ix][iy][ip0]
7300 + (dp1 * dp1 - dp0 * dp0) * met->u[ix][iy][ip])
7301 / denom;
7302 dvdp = (dp0 * dp0 * met->v[ix][iy][ip1]
7303 - dp1 * dp1 * met->v[ix][iy][ip0]
7304 + (dp1 * dp1 - dp0 * dp0) * met->v[ix][iy][ip])
7305 / denom;
7306 } else {
7307 double denom = dp0 + dp1;
7308 dtdp =
7309 (met->t[ix][iy][ip1] * pows[ip1] -
7310 met->t[ix][iy][ip0] * pows[ip0]) / denom;
7311 dudp = (met->u[ix][iy][ip1] - met->u[ix][iy][ip0]) / denom;
7312 dvdp = (met->v[ix][iy][ip1] - met->v[ix][iy][ip0]) / denom;
7313 }
7314
7315 /* Calculate PV... */
7316 met->pv[ix][iy][ip] = (float)
7317 (1e6 * G0 *
7318 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
7319 }
7320 }
7321 }
7322
7323 /* Fix for polar regions... */
7324#pragma omp parallel for default(shared)
7325 for (int ix = 0; ix < met->nx; ix++)
7326 for (int ip = 0; ip < met->np; ip++) {
7327 met->pv[ix][0][ip]
7328 = met->pv[ix][1][ip]
7329 = met->pv[ix][2][ip];
7330 met->pv[ix][met->ny - 1][ip]
7331 = met->pv[ix][met->ny - 2][ip]
7332 = met->pv[ix][met->ny - 3][ip];
7333 }
7334}
#define DEG2DY(dlat)
Convert a latitude difference to a distance in the y-direction (north-south).
Definition: mptrac.h:456
#define DEG2DX(dlon, lat)
Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude.
Definition: mptrac.h:435

◆ read_met_ozone()

void read_met_ozone ( met_t met)

Calculates the total column ozone from meteorological ozone data.

This function calculates the total column ozone from the provided meteorological ozone data. It integrates ozone concentrations over altitude to obtain the column ozone density. The result is then converted to Dobson units, which represent the thickness of the ozone layer if compressed into one layer at standard temperature and pressure.

Parameters
metA pointer to a structure containing meteorological ozone data.

The function performs the following steps:

  • Sets a timer for performance monitoring.
  • Loops over columns in longitude and latitude:
    • Integrates ozone concentrations over altitude.
    • Converts the integrated ozone density to Dobson units.
Note
Total column ozone is a critical metric for understanding ozone distribution in the atmosphere, with implications for climate, air quality, and UV radiation.
Author
Lars Hoffmann

Definition at line 7338 of file mptrac.c.

7339 {
7340
7341 /* Set timer... */
7342 SELECT_TIMER("READ_MET_OZONE", "METPROC", NVTX_READ);
7343 LOG(2, "Calculate total column ozone...");
7344
7345 /* Loop over columns... */
7346#pragma omp parallel for default(shared) collapse(2)
7347 for (int ix = 0; ix < met->nx; ix++)
7348 for (int iy = 0; iy < met->ny; iy++) {
7349
7350 /* Integrate... */
7351 double cd = 0;
7352 for (int ip = 1; ip < met->np; ip++)
7353 if (met->p[ip - 1] <= met->ps[ix][iy]) {
7354 double vmr = 0.5 * (met->o3[ix][iy][ip - 1] + met->o3[ix][iy][ip]);
7355 double dp = met->p[ip - 1] - met->p[ip];
7356 cd += vmr * MO3 / MA * dp * 1e2 / G0;
7357 }
7358
7359 /* Convert to Dobson units... */
7360 met->o3c[ix][iy] = (float) (cd / 2.1415e-5);
7361 }
7362}
float o3c[EX][EY]
Total column ozone [DU].
Definition: mptrac.h:3377

◆ read_met_sample()

void read_met_sample ( ctl_t ctl,
met_t met 
)

Downsamples meteorological data based on specified parameters.

This function downsamples meteorological data based on the provided control parameters. It reduces the resolution of meteorological data by averaging over specified intervals in longitude, latitude, and altitude.

Parameters
ctlA pointer to a structure containing control parameters for downsampling.
metA pointer to a structure containing meteorological data to be downsampled.

The function performs the following steps:

  • Checks if downsampling parameters are set to a value less than or equal to 1, if so, returns without downsampling.
  • Sets a timer for performance monitoring.
  • Allocates memory for a temporary meteorological data structure.
  • Copies metadata from the original structure to the temporary structure.
  • Performs downsampling by smoothing over specified intervals:
    • Computes weighted averages over the specified intervals.
    • Updates the temporary structure with the smoothed values.
  • Downsamples the smoothed data:
    • Updates longitude and latitude arrays with downsampled values.
    • Stores downsampled meteorological variables in the original structure.
  • Frees memory allocated for the temporary structure.
Note
Downsampling meteorological data can be useful for reducing computational cost while preserving essential features for modeling and analysis.
Author
Lars Hoffmann

Definition at line 7366 of file mptrac.c.

7368 {
7369
7370 met_t *help;
7371
7372 /* Check parameters... */
7373 if (ctl->met_dp <= 1 && ctl->met_dx <= 1 && ctl->met_dy <= 1
7374 && ctl->met_sp <= 1 && ctl->met_sx <= 1 && ctl->met_sy <= 1)
7375 return;
7376
7377 /* Set timer... */
7378 SELECT_TIMER("READ_MET_SAMPLE", "METPROC", NVTX_READ);
7379 LOG(2, "Downsampling of meteo data...");
7380
7381 /* Allocate... */
7382 ALLOC(help, met_t, 1);
7383
7384 /* Copy data... */
7385 help->nx = met->nx;
7386 help->ny = met->ny;
7387 help->np = met->np;
7388 memcpy(help->lon, met->lon, sizeof(met->lon));
7389 memcpy(help->lat, met->lat, sizeof(met->lat));
7390 memcpy(help->p, met->p, sizeof(met->p));
7391
7392 /* Smoothing... */
7393 for (int ix = 0; ix < met->nx; ix += ctl->met_dx) {
7394 for (int iy = 0; iy < met->ny; iy += ctl->met_dy) {
7395 for (int ip = 0; ip < met->np; ip += ctl->met_dp) {
7396 help->ps[ix][iy] = 0;
7397 help->zs[ix][iy] = 0;
7398 help->ts[ix][iy] = 0;
7399 help->us[ix][iy] = 0;
7400 help->vs[ix][iy] = 0;
7401 help->lsm[ix][iy] = 0;
7402 help->sst[ix][iy] = 0;
7403 help->t[ix][iy][ip] = 0;
7404 help->u[ix][iy][ip] = 0;
7405 help->v[ix][iy][ip] = 0;
7406 help->w[ix][iy][ip] = 0;
7407 help->h2o[ix][iy][ip] = 0;
7408 help->o3[ix][iy][ip] = 0;
7409 help->lwc[ix][iy][ip] = 0;
7410 help->rwc[ix][iy][ip] = 0;
7411 help->iwc[ix][iy][ip] = 0;
7412 help->swc[ix][iy][ip] = 0;
7413 help->cc[ix][iy][ip] = 0;
7414 float wsum = 0;
7415 for (int ix2 = ix - ctl->met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
7416 ix2++) {
7417 int ix3 = ix2;
7418 if (ix3 < 0)
7419 ix3 += met->nx;
7420 else if (ix3 >= met->nx)
7421 ix3 -= met->nx;
7422
7423 for (int iy2 = MAX(iy - ctl->met_sy + 1, 0);
7424 iy2 <= MIN(iy + ctl->met_sy - 1, met->ny - 1); iy2++)
7425 for (int ip2 = MAX(ip - ctl->met_sp + 1, 0);
7426 ip2 <= MIN(ip + ctl->met_sp - 1, met->np - 1); ip2++) {
7427 float w = (1.0f - (float) abs(ix - ix2) / (float) ctl->met_sx)
7428 * (1.0f - (float) abs(iy - iy2) / (float) ctl->met_sy)
7429 * (1.0f - (float) abs(ip - ip2) / (float) ctl->met_sp);
7430 help->ps[ix][iy] += w * met->ps[ix3][iy2];
7431 help->zs[ix][iy] += w * met->zs[ix3][iy2];
7432 help->ts[ix][iy] += w * met->ts[ix3][iy2];
7433 help->us[ix][iy] += w * met->us[ix3][iy2];
7434 help->vs[ix][iy] += w * met->vs[ix3][iy2];
7435 help->lsm[ix][iy] += w * met->lsm[ix3][iy2];
7436 help->sst[ix][iy] += w * met->sst[ix3][iy2];
7437 help->t[ix][iy][ip] += w * met->t[ix3][iy2][ip2];
7438 help->u[ix][iy][ip] += w * met->u[ix3][iy2][ip2];
7439 help->v[ix][iy][ip] += w * met->v[ix3][iy2][ip2];
7440 help->w[ix][iy][ip] += w * met->w[ix3][iy2][ip2];
7441 help->h2o[ix][iy][ip] += w * met->h2o[ix3][iy2][ip2];
7442 help->o3[ix][iy][ip] += w * met->o3[ix3][iy2][ip2];
7443 help->lwc[ix][iy][ip] += w * met->lwc[ix3][iy2][ip2];
7444 help->rwc[ix][iy][ip] += w * met->rwc[ix3][iy2][ip2];
7445 help->iwc[ix][iy][ip] += w * met->iwc[ix3][iy2][ip2];
7446 help->swc[ix][iy][ip] += w * met->swc[ix3][iy2][ip2];
7447 help->cc[ix][iy][ip] += w * met->cc[ix3][iy2][ip2];
7448 wsum += w;
7449 }
7450 }
7451 help->ps[ix][iy] /= wsum;
7452 help->zs[ix][iy] /= wsum;
7453 help->ts[ix][iy] /= wsum;
7454 help->us[ix][iy] /= wsum;
7455 help->vs[ix][iy] /= wsum;
7456 help->lsm[ix][iy] /= wsum;
7457 help->sst[ix][iy] /= wsum;
7458 help->t[ix][iy][ip] /= wsum;
7459 help->u[ix][iy][ip] /= wsum;
7460 help->v[ix][iy][ip] /= wsum;
7461 help->w[ix][iy][ip] /= wsum;
7462 help->h2o[ix][iy][ip] /= wsum;
7463 help->o3[ix][iy][ip] /= wsum;
7464 help->lwc[ix][iy][ip] /= wsum;
7465 help->rwc[ix][iy][ip] /= wsum;
7466 help->iwc[ix][iy][ip] /= wsum;
7467 help->swc[ix][iy][ip] /= wsum;
7468 help->cc[ix][iy][ip] /= wsum;
7469 }
7470 }
7471 }
7472
7473 /* Downsampling... */
7474 met->nx = 0;
7475 for (int ix = 0; ix < help->nx; ix += ctl->met_dx) {
7476 met->lon[met->nx] = help->lon[ix];
7477 met->ny = 0;
7478 for (int iy = 0; iy < help->ny; iy += ctl->met_dy) {
7479 met->lat[met->ny] = help->lat[iy];
7480 met->ps[met->nx][met->ny] = help->ps[ix][iy];
7481 met->zs[met->nx][met->ny] = help->zs[ix][iy];
7482 met->ts[met->nx][met->ny] = help->ts[ix][iy];
7483 met->us[met->nx][met->ny] = help->us[ix][iy];
7484 met->vs[met->nx][met->ny] = help->vs[ix][iy];
7485 met->lsm[met->nx][met->ny] = help->lsm[ix][iy];
7486 met->sst[met->nx][met->ny] = help->sst[ix][iy];
7487 met->np = 0;
7488 for (int ip = 0; ip < help->np; ip += ctl->met_dp) {
7489 met->p[met->np] = help->p[ip];
7490 met->t[met->nx][met->ny][met->np] = help->t[ix][iy][ip];
7491 met->u[met->nx][met->ny][met->np] = help->u[ix][iy][ip];
7492 met->v[met->nx][met->ny][met->np] = help->v[ix][iy][ip];
7493 met->w[met->nx][met->ny][met->np] = help->w[ix][iy][ip];
7494 met->h2o[met->nx][met->ny][met->np] = help->h2o[ix][iy][ip];
7495 met->o3[met->nx][met->ny][met->np] = help->o3[ix][iy][ip];
7496 met->lwc[met->nx][met->ny][met->np] = help->lwc[ix][iy][ip];
7497 met->rwc[met->nx][met->ny][met->np] = help->rwc[ix][iy][ip];
7498 met->iwc[met->nx][met->ny][met->np] = help->iwc[ix][iy][ip];
7499 met->swc[met->nx][met->ny][met->np] = help->swc[ix][iy][ip];
7500 met->cc[met->nx][met->ny][met->np] = help->cc[ix][iy][ip];
7501 met->np++;
7502 }
7503 met->ny++;
7504 }
7505 met->nx++;
7506 }
7507
7508 /* Free... */
7509 free(help);
7510}
int met_dp
Stride for pressure levels.
Definition: mptrac.h:2528
int met_sy
Smoothing for latitudes.
Definition: mptrac.h:2534
int met_sx
Smoothing for longitudes.
Definition: mptrac.h:2531
int met_dx
Stride for longitudes.
Definition: mptrac.h:2522
int met_sp
Smoothing for pressure levels.
Definition: mptrac.h:2537
int met_dy
Stride for latitudes.
Definition: mptrac.h:2525

◆ read_met_surface()

void read_met_surface ( int  ncid,
met_t met,
ctl_t ctl 
)

Reads surface meteorological data from a netCDF file and stores it in the meteorological data structure.

This function reads various surface meteorological variables from a netCDF file and stores them in the provided meteorological data structure. Depending on the configuration, it may read data for surface pressure, geopotential height, temperature, zonal and meridional wind components, land-sea mask, and sea surface temperature.

Parameters
ncidNetCDF file identifier.
metA pointer to the meteorological data structure to store the read data.
ctlA pointer to a structure containing control parameters.

The function performs the following steps:

  • Sets a timer for performance monitoring.
  • Reads surface meteorological data based on the configuration:
    • For MPTRAC meteorological data:
      • Reads surface pressure from "lnsp", "ps", or "sp" variables.
      • Converts surface pressure to Pa if necessary.
      • Reads geopotential height at the surface from "z" or "zm" variables.
      • Reads surface temperature from "t2m" or "2t" variables.
      • Reads zonal wind at the surface from "u10m" or "10u" variables.
      • Reads meridional wind at the surface from "v10m" or "10v" variables.
      • Reads land-sea mask from "lsm" variable.
      • Reads sea surface temperature from "sstk" or "sst" variables.
    • For CLaMS meteorological data:
      • Reads surface pressure from "ps" variable.
      • Reads geopotential height at the surface using the lowest level of the 3-D data field.
      • Reads surface temperature from "t2" variable.
      • Reads zonal wind at the surface from "u10" variable.
      • Reads meridional wind at the surface from "v10" variable.
      • Reads land-sea mask from "lsm" variable.
      • Reads sea surface temperature from "sstk" variable.
Note
The function handles different variable names and units according to the specified meteorological data source (MPTRAC or CLaMS).
Authors
Lars Hoffmann
Jan Clemens

Definition at line 7514 of file mptrac.c.

7517 {
7518
7519 /* Set timer... */
7520 SELECT_TIMER("READ_MET_SURFACE", "INPUT", NVTX_READ);
7521 LOG(2, "Read surface data...");
7522
7523 /* MPTRAC meteo data... */
7524 if (ctl->met_clams == 0) {
7525
7526 /* Read surface pressure... */
7527 if (read_met_nc_2d
7528 (ncid, "lnsp", "LNSP", NULL, NULL, ctl, met, met->ps, 1.0f, 1)) {
7529 for (int ix = 0; ix < met->nx; ix++)
7530 for (int iy = 0; iy < met->ny; iy++)
7531 met->ps[ix][iy] = (float) (exp(met->ps[ix][iy]) / 100.);
7532 } else
7533 if (!read_met_nc_2d
7534 (ncid, "ps", "PS", "sp", "SP", ctl, met, met->ps, 0.01f, 1)) {
7535 WARN("Cannot not read surface pressure data (use lowest level)!");
7536 for (int ix = 0; ix < met->nx; ix++)
7537 for (int iy = 0; iy < met->ny; iy++)
7538 met->ps[ix][iy] = (float) met->p[0];
7539 }
7540
7541 /* Read geopotential height at the surface... */
7542 if (!read_met_nc_2d
7543 (ncid, "z", "Z", NULL, NULL, ctl, met, met->zs,
7544 (float) (1. / (1000. * G0)), 1))
7545 if (!read_met_nc_2d
7546 (ncid, "zm", "ZM", NULL, NULL, ctl, met, met->zs,
7547 (float) (1. / 1000.), 1))
7548 WARN("Cannot read surface geopotential height!");
7549
7550 /* Read temperature at the surface... */
7551 if (!read_met_nc_2d
7552 (ncid, "t2m", "T2M", "2t", "2T", ctl, met, met->ts, 1.0, 1))
7553 WARN("Cannot read surface temperature!");
7554
7555 /* Read zonal wind at the surface... */
7556 if (!read_met_nc_2d
7557 (ncid, "u10m", "U10M", "10u", "10U", ctl, met, met->us, 1.0, 1))
7558 WARN("Cannot read surface zonal wind!");
7559
7560 /* Read meridional wind at the surface... */
7561 if (!read_met_nc_2d
7562 (ncid, "v10m", "V10M", "10v", "10V", ctl, met, met->vs, 1.0, 1))
7563 WARN("Cannot read surface meridional wind!");
7564
7565 /* Read land-sea mask... */
7566 if (!read_met_nc_2d
7567 (ncid, "lsm", "LSM", NULL, NULL, ctl, met, met->lsm, 1.0, 1))
7568 WARN("Cannot read land-sea mask!");
7569
7570 /* Read sea surface temperature... */
7571 if (!read_met_nc_2d
7572 (ncid, "sstk", "SSTK", "sst", "SST", ctl, met, met->sst, 1.0, 1))
7573 WARN("Cannot read sea surface temperature!");
7574 }
7575
7576 /* CLaMS meteo data... */
7577 else {
7578
7579 /* Read surface pressure... */
7580 if (!read_met_nc_2d
7581 (ncid, "ps", "PS", NULL, NULL, ctl, met, met->ps, 0.01f, 1)) {
7582 WARN("Cannot not read surface pressure data (use lowest level)!");
7583 for (int ix = 0; ix < met->nx; ix++)
7584 for (int iy = 0; iy < met->ny; iy++)
7585 met->ps[ix][iy] = (float) met->p[0];
7586 }
7587
7588 /* Read geopotential height at the surface
7589 (use lowermost level of 3-D data field)... */
7590 float *help;
7591 ALLOC(help, float,
7592 EX * EY * EP);
7593 memcpy(help, met->pl, sizeof(met->pl));
7594 if (!read_met_nc_3d
7595 (ncid, "gph", "GPH", NULL, NULL, ctl, met, met->pl,
7596 (float) (1e-3 / G0))) {
7597 ERRMSG("Cannot read geopotential height!");
7598 } else
7599 for (int ix = 0; ix < met->nx; ix++)
7600 for (int iy = 0; iy < met->ny; iy++)
7601 met->zs[ix][iy] = met->pl[ix][iy][0];
7602 memcpy(met->pl, help, sizeof(met->pl));
7603 free(help);
7604
7605 /* Read temperature at the surface... */
7606 if (!read_met_nc_2d
7607 (ncid, "t2", "T2", NULL, NULL, ctl, met, met->ts, 1.0, 1))
7608 WARN("Cannot read surface temperature!");
7609
7610 /* Read zonal wind at the surface... */
7611 if (!read_met_nc_2d
7612 (ncid, "u10", "U10", NULL, NULL, ctl, met, met->us, 1.0, 1))
7613 WARN("Cannot read surface zonal wind!");
7614
7615 /* Read meridional wind at the surface... */
7616 if (!read_met_nc_2d
7617 (ncid, "v10", "V10", NULL, NULL, ctl, met, met->vs, 1.0, 1))
7618 WARN("Cannot read surface meridional wind!");
7619
7620 /* Read land-sea mask... */
7621 if (!read_met_nc_2d
7622 (ncid, "lsm", "LSM", NULL, NULL, ctl, met, met->lsm, 1.0, 1))
7623 WARN("Cannot read land-sea mask!");
7624
7625 /* Read sea surface temperature... */
7626 if (!read_met_nc_2d
7627 (ncid, "sstk", "SSTK", NULL, NULL, ctl, met, met->sst, 1.0, 1))
7628 WARN("Cannot read sea surface temperature!");
7629 }
7630}
int read_met_nc_2d(int ncid, char *varname, char *varname2, char *varname3, char *varname4, ctl_t *ctl, met_t *met, float dest[EX][EY], float scl, int init)
Reads a 2-dimensional meteorological variable from a NetCDF file.
Definition: mptrac.c:6751
Here is the call graph for this function:

◆ read_met_tropo()

void read_met_tropo ( ctl_t ctl,
clim_t clim,
met_t met 
)

Calculates the tropopause and related meteorological variables based on various methods and stores the results in the meteorological data structure.

This function calculates the tropopause and related meteorological variables using different methods specified by the control parameters. The calculated tropopause pressure is stored in the provided meteorological data structure.

Parameters
ctlA pointer to a structure containing control parameters.
climA pointer to the climatological data structure.
metA pointer to the meteorological data structure to store the calculated tropopause pressure and related variables.

The function performs the following steps:

  • Sets a timer for performance monitoring.
  • Retrieves altitude and pressure profiles from the meteorological data structure.
  • Depending on the control parameters (ctl->met_tropo), it calculates the tropopause using one of the following methods:
    • If ctl->met_tropo == 0, it does not calculate the tropopause and assigns NaN values to the tropopause pressure.
    • If ctl->met_tropo == 1, it uses tropopause climatology to estimate the tropopause pressure based on latitude and time.
    • If ctl->met_tropo == 2, it calculates the tropopause based on the cold point method, finding the altitude where the temperature is at a minimum.
    • If ctl->met_tropo == 3 or ctl->met_tropo == 4, it calculates the tropopause using the WMO definition, which involves identifying a sharp temperature lapse rate between two pressure levels.
    • If ctl->met_tropo == 5, it calculates the dynamical tropopause based on potential vorticity and potential temperature profiles.
  • Interpolates temperature, geopotential height, and water vapor content to the tropopause pressure level using spatial interpolation.
  • Stores the interpolated values in the meteorological data structure.
Note
The function supports parallelization using OpenMP directives to improve performance.
Author
Lars Hoffmann

Definition at line 7634 of file mptrac.c.

7637 {
7638
7639 double p2[200], pv[EP], pv2[200], t[EP], t2[200], th[EP],
7640 th2[200], z[EP], z2[200];
7641
7642 /* Set timer... */
7643 SELECT_TIMER("READ_MET_TROPO", "METPROC", NVTX_READ);
7644 LOG(2, "Calculate tropopause...");
7645
7646 /* Get altitude and pressure profiles... */
7647#pragma omp parallel for default(shared)
7648 for (int iz = 0; iz < met->np; iz++)
7649 z[iz] = Z(met->p[iz]);
7650#pragma omp parallel for default(shared)
7651 for (int iz = 0; iz <= 190; iz++) {
7652 z2[iz] = 4.5 + 0.1 * iz;
7653 p2[iz] = P(z2[iz]);
7654 }
7655
7656 /* Do not calculate tropopause... */
7657 if (ctl->met_tropo == 0)
7658#pragma omp parallel for default(shared) collapse(2)
7659 for (int ix = 0; ix < met->nx; ix++)
7660 for (int iy = 0; iy < met->ny; iy++)
7661 met->pt[ix][iy] = NAN;
7662
7663 /* Use tropopause climatology... */
7664 else if (ctl->met_tropo == 1) {
7665#pragma omp parallel for default(shared) collapse(2)
7666 for (int ix = 0; ix < met->nx; ix++)
7667 for (int iy = 0; iy < met->ny; iy++)
7668 met->pt[ix][iy] = (float) clim_tropo(clim, met->time, met->lat[iy]);
7669 }
7670
7671 /* Use cold point... */
7672 else if (ctl->met_tropo == 2) {
7673
7674 /* Loop over grid points... */
7675#pragma omp parallel for default(shared) private(t,t2) collapse(2)
7676 for (int ix = 0; ix < met->nx; ix++)
7677 for (int iy = 0; iy < met->ny; iy++) {
7678
7679 /* Interpolate temperature profile... */
7680 for (int iz = 0; iz < met->np; iz++)
7681 t[iz] = met->t[ix][iy][iz];
7682 spline(z, t, met->np, z2, t2, 171, ctl->met_tropo_spline);
7683
7684 /* Find minimum... */
7685 int iz = (int) gsl_stats_min_index(t2, 1, 171);
7686 if (iz > 0 && iz < 170)
7687 met->pt[ix][iy] = (float) p2[iz];
7688 else
7689 met->pt[ix][iy] = NAN;
7690 }
7691 }
7692
7693 /* Use WMO definition... */
7694 else if (ctl->met_tropo == 3 || ctl->met_tropo == 4) {
7695
7696 /* Loop over grid points... */
7697#pragma omp parallel for default(shared) private(t,t2) collapse(2)
7698 for (int ix = 0; ix < met->nx; ix++)
7699 for (int iy = 0; iy < met->ny; iy++) {
7700
7701 /* Interpolate temperature profile... */
7702 int iz;
7703 for (iz = 0; iz < met->np; iz++)
7704 t[iz] = met->t[ix][iy][iz];
7705 spline(z, t, met->np, z2, t2, 191, ctl->met_tropo_spline);
7706
7707 /* Find 1st tropopause... */
7708 met->pt[ix][iy] = NAN;
7709 for (iz = 0; iz <= 170; iz++) {
7710 int found = 1;
7711 for (int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
7712 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
7713 found = 0;
7714 break;
7715 }
7716 if (found) {
7717 if (iz > 0 && iz < 170)
7718 met->pt[ix][iy] = (float) p2[iz];
7719 break;
7720 }
7721 }
7722
7723 /* Find 2nd tropopause... */
7724 if (ctl->met_tropo == 4) {
7725 met->pt[ix][iy] = NAN;
7726 for (; iz <= 170; iz++) {
7727 int found = 1;
7728 for (int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
7729 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
7730 found = 0;
7731 break;
7732 }
7733 if (found)
7734 break;
7735 }
7736 for (; iz <= 170; iz++) {
7737 int found = 1;
7738 for (int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
7739 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
7740 found = 0;
7741 break;
7742 }
7743 if (found) {
7744 if (iz > 0 && iz < 170)
7745 met->pt[ix][iy] = (float) p2[iz];
7746 break;
7747 }
7748 }
7749 }
7750 }
7751 }
7752
7753 /* Use dynamical tropopause... */
7754 else if (ctl->met_tropo == 5) {
7755
7756 /* Loop over grid points... */
7757#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
7758 for (int ix = 0; ix < met->nx; ix++)
7759 for (int iy = 0; iy < met->ny; iy++) {
7760
7761 /* Interpolate potential vorticity profile... */
7762 for (int iz = 0; iz < met->np; iz++)
7763 pv[iz] = met->pv[ix][iy][iz];
7764 spline(z, pv, met->np, z2, pv2, 171, ctl->met_tropo_spline);
7765
7766 /* Interpolate potential temperature profile... */
7767 for (int iz = 0; iz < met->np; iz++)
7768 th[iz] = THETA(met->p[iz], met->t[ix][iy][iz]);
7769 spline(z, th, met->np, z2, th2, 171, ctl->met_tropo_spline);
7770
7771 /* Find dynamical tropopause... */
7772 met->pt[ix][iy] = NAN;
7773 for (int iz = 0; iz <= 170; iz++)
7774 if (fabs(pv2[iz]) >= ctl->met_tropo_pv
7775 || th2[iz] >= ctl->met_tropo_theta) {
7776 if (iz > 0 && iz < 170)
7777 met->pt[ix][iy] = (float) p2[iz];
7778 break;
7779 }
7780 }
7781 }
7782
7783 else
7784 ERRMSG("Cannot calculate tropopause!");
7785
7786 /* Interpolate temperature, geopotential height, and water vapor... */
7787#pragma omp parallel for default(shared) collapse(2)
7788 for (int ix = 0; ix < met->nx; ix++)
7789 for (int iy = 0; iy < met->ny; iy++) {
7790 double h2ot, tt, zt;
7792 intpol_met_space_3d(met, met->t, met->pt[ix][iy], met->lon[ix],
7793 met->lat[iy], &tt, ci, cw, 1);
7794 intpol_met_space_3d(met, met->z, met->pt[ix][iy], met->lon[ix],
7795 met->lat[iy], &zt, ci, cw, 0);
7796 intpol_met_space_3d(met, met->h2o, met->pt[ix][iy], met->lon[ix],
7797 met->lat[iy], &h2ot, ci, cw, 0);
7798 met->tt[ix][iy] = (float) tt;
7799 met->zt[ix][iy] = (float) zt;
7800 met->h2ot[ix][iy] = (float) h2ot;
7801 }
7802}
void spline(const double *x, const double *y, const int n, const double *x2, double *y2, const int n2, const int method)
Performs spline interpolation or linear interpolation.
Definition: mptrac.c:8012
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
Definition: mptrac.h:808
Here is the call graph for this function:

◆ read_obs()

void read_obs ( const char *  filename,
ctl_t ctl,
double *  rt,
double *  rz,
double *  rlon,
double *  rlat,
double *  robs,
int *  nobs 
)

Reads observation data from a file and stores it in arrays.

This function reads observation data from a specified file in either ASCII or NetCDF format, depending on the value of the OBS_TYPE control parameter. It stores the time, altitude, longitude, latitude, and observation values in the provided arrays.

Parameters
filenameThe path to the observation data file.
ctlA pointer to a structure containing control parameters.
rtAn array to store the time values of the observations.
rzAn array to store the altitude values of the observations.
rlonAn array to store the longitude values of the observations.
rlatAn array to store the latitude values of the observations.
robsAn array to store the observation values.
nobsA pointer to an integer variable to store the number of observations read.

The function performs the following steps:

  • Logs an informational message indicating the observation data file being read.
  • Reads the observation data from the file based on the OBS_TYPE control parameter:
    • If ctl->obs_type == 0, it reads the data from an ASCII file using the read_obs_asc function.
    • If ctl->obs_type == 1, it reads the data from a NetCDF file using the read_obs_nc function.
    • If ctl->obs_type is neither 0 nor 1, it generates an error message indicating that the OBS_TYPE must be set to 0 or 1.
  • Checks if the time values are in ascending order and generates an error message if not.
  • Logs statistical information about the observation data, including the number of observations, time range, altitude range, longitude range, latitude range, and observation value range.
Note
The function assumes that the observation data file is formatted correctly and that the arrays provided have sufficient memory allocated to store the data.
Author
Lars Hoffmann
Mingzhao Liu

Definition at line 7806 of file mptrac.c.

7814 {
7815
7816 /* Write info... */
7817 LOG(1, "Read observation data: %s", filename);
7818
7819 /* Read data... */
7820 if (ctl->obs_type == 0)
7821 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
7822 else if (ctl->obs_type == 1)
7823 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
7824 else
7825 ERRMSG("Set OBS_TYPE to 0 or 1!");
7826
7827 /* Check time... */
7828 for (int i = 1; i < *nobs; i++)
7829 if (rt[i] < rt[i - 1])
7830 ERRMSG("Time must be ascending!");
7831
7832 /* Write info... */
7833 int n = *nobs;
7834 double mini, maxi;
7835 LOG(2, "Number of observations: %d", *nobs);
7836 gsl_stats_minmax(&mini, &maxi, rt, 1, (size_t) n);
7837 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
7838 gsl_stats_minmax(&mini, &maxi, rz, 1, (size_t) n);
7839 LOG(2, "Altitude range: %g ... %g km", mini, maxi);
7840 gsl_stats_minmax(&mini, &maxi, rlon, 1, (size_t) n);
7841 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
7842 gsl_stats_minmax(&mini, &maxi, rlat, 1, (size_t) n);
7843 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
7844 gsl_stats_minmax(&mini, &maxi, robs, 1, (size_t) n);
7845 LOG(2, "Observation range: %g ... %g", mini, maxi);
7846}
void read_obs_asc(const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from an ASCII file.
Definition: mptrac.c:7850
void read_obs_nc(const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from a NetCDF file.
Definition: mptrac.c:7878
Here is the call graph for this function:

◆ read_obs_asc()

void read_obs_asc ( const char *  filename,
double *  rt,
double *  rz,
double *  rlon,
double *  rlat,
double *  robs,
int *  nobs 
)

Reads observation data from an ASCII file.

This function reads observation data from a specified ASCII file. It extracts time, altitude, longitude, latitude, and observation values from each line of the file and stores them in the provided arrays.

Parameters
filenameThe path to the ASCII file containing the observation data.
rtAn array to store the time values of the observations.
rzAn array to store the altitude values of the observations.
rlonAn array to store the longitude values of the observations.
rlatAn array to store the latitude values of the observations.
robsAn array to store the observation values.
nobsA pointer to an integer variable to store the number of observations read.

The function performs the following steps:

  • Attempts to open the specified observation data file in read mode.
  • Reads each line of the file and parses it to extract the time, altitude, longitude, latitude, and observation values using the sscanf function.
  • Stores the extracted values in the respective arrays.
  • Checks if the number of observations exceeds the maximum allowed limit (NOBS) and generates an error message if so.
  • Closes the observation data file after reading all data.
Note
The function assumes that the observation data file is properly formatted and that the arrays provided have sufficient memory allocated to store the data.
Author
Lars Hoffmann

Definition at line 7850 of file mptrac.c.

7857 {
7858
7859 /* Open observation data file... */
7860 FILE *in;
7861 if (!(in = fopen(filename, "r")))
7862 ERRMSG("Cannot open file!");
7863
7864 /* Read observations... */
7865 char line[LEN];
7866 while (fgets(line, LEN, in))
7867 if (sscanf(line, "%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
7868 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
7869 if ((++(*nobs)) >= NOBS)
7870 ERRMSG("Too many observations!");
7871
7872 /* Close observation data file... */
7873 fclose(in);
7874}
#define NOBS
Maximum number of observation data points.
Definition: mptrac.h:276

◆ read_obs_nc()

void read_obs_nc ( const char *  filename,
double *  rt,
double *  rz,
double *  rlon,
double *  rlat,
double *  robs,
int *  nobs 
)

Reads observation data from a NetCDF file.

This function reads observation data from a specified NetCDF file. It extracts time, altitude, longitude, latitude, and observation values from the variables in the NetCDF file and stores them in the provided arrays.

Parameters
filenameThe path to the NetCDF file containing the observation data.
rtAn array to store the time values of the observations.
rzAn array to store the altitude values of the observations.
rlonAn array to store the longitude values of the observations.
rlatAn array to store the latitude values of the observations.
robsAn array to store the observation values.
nobsA pointer to an integer variable to store the number of observations read.

The function performs the following steps:

  • Attempts to open the specified NetCDF file in read-only mode using the nc_open function.
  • Queries the dimensions of the 'nobs' variable in the NetCDF file to determine the number of observations using the NC_INQ_DIM macro.
  • Reads the 'time', 'alt', 'lon', 'lat', and 'obs' variables from the NetCDF file using the NC_GET_DOUBLE macro and stores them in the respective arrays.
  • Closes the NetCDF file after reading all data using the nc_close function.
Note
The function assumes that the NetCDF file contains the required variables ('time', 'alt', 'lon', 'lat', 'obs') and that the arrays provided have sufficient memory allocated to store the data.
Author
Lars Hoffmann

Definition at line 7878 of file mptrac.c.

7885 {
7886
7887 int ncid, varid;
7888
7889 /* Open netCDF file... */
7890 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7891 ERRMSG("Cannot open file!");
7892
7893 /* Read the observations from the NetCDF file... */
7894 NC_INQ_DIM("nobs", nobs, 1, NOBS);
7895 NC_GET_DOUBLE("time", rt, 1);
7896 NC_GET_DOUBLE("alt", rz, 1);
7897 NC_GET_DOUBLE("lon", rlon, 1);
7898 NC_GET_DOUBLE("lat", rlat, 1);
7899 NC_GET_DOUBLE("obs", robs, 1);
7900
7901 /* Close file... */
7902 NC(nc_close(ncid));
7903}

◆ scan_ctl()

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

Scans a control file or command-line arguments for a specified variable.

This function scans either a control file or command-line arguments for a specified variable name and retrieves its value. It searches for the variable name in the control file or command-line arguments and returns its corresponding value. If the variable is not found, it returns a default value specified by the user.

Parameters
filenameThe name of the control file to be scanned. If NULL, only command-line arguments will be scanned.
argcThe number of command-line arguments.
argvAn array of command-line arguments.
varnameThe name of the variable to be searched.
arridxThe index of the variable array, if applicable. Set to -1 if not an array.
defvalueThe default value to be returned if the variable is not found.
valueA pointer to a character array to store the retrieved value.
Returns
The retrieved value of the variable as a double.

The function performs the following steps:

  • Attempts to open the specified control file in read mode using the fopen function. If the filename ends with a '-', the file is not opened.
  • Constructs the full variable name based on the variable name and array index provided.
  • Reads data from the control file, searching for the full variable name. If found, it sets the contain flag to 1 and breaks the loop.
  • Searches through the command-line arguments for the full variable name. If found, it sets the value and contain flag and breaks the loop.
  • Closes the control file if opened.
  • If the variable is not found, it sets the value to the default value provided or throws an error if no default value is provided.
  • Writes the variable name and its value to the log.
  • Copies the retrieved value to the value parameter if it is not NULL.
  • Returns the retrieved value as a double after converting it from a string using the atof function.
Note
This function assumes that the variable names and their values in the control file or command-line arguments are separated by whitespace.
Author
Lars Hoffmann

Definition at line 7907 of file mptrac.c.

7914 {
7915
7916 FILE *in = NULL;
7917
7918 char fullname1[LEN], fullname2[LEN], rval[LEN];
7919
7920 int contain = 0, i;
7921
7922 /* Open file... */
7923 if (filename[strlen(filename) - 1] != '-')
7924 if (!(in = fopen(filename, "r")))
7925 ERRMSG("Cannot open file!");
7926
7927 /* Set full variable name... */
7928 if (arridx >= 0) {
7929 sprintf(fullname1, "%s[%d]", varname, arridx);
7930 sprintf(fullname2, "%s[*]", varname);
7931 } else {
7932 sprintf(fullname1, "%s", varname);
7933 sprintf(fullname2, "%s", varname);
7934 }
7935
7936 /* Read data... */
7937 if (in != NULL) {
7938 char dummy[LEN], line[LEN], rvarname[LEN];
7939 while (fgets(line, LEN, in)) {
7940 if (sscanf(line, "%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
7941 if (strcasecmp(rvarname, fullname1) == 0 ||
7942 strcasecmp(rvarname, fullname2) == 0) {
7943 contain = 1;
7944 break;
7945 }
7946 }
7947 }
7948 for (i = 1; i < argc - 1; i++)
7949 if (strcasecmp(argv[i], fullname1) == 0 ||
7950 strcasecmp(argv[i], fullname2) == 0) {
7951 sprintf(rval, "%s", argv[i + 1]);
7952 contain = 1;
7953 break;
7954 }
7955
7956 /* Close file... */
7957 if (in != NULL)
7958 fclose(in);
7959
7960 /* Check for missing variables... */
7961 if (!contain) {
7962 if (strlen(defvalue) > 0)
7963 sprintf(rval, "%s", defvalue);
7964 else
7965 ERRMSG("Missing variable %s!\n", fullname1);
7966 }
7967
7968 /* Write info... */
7969 LOG(1, "%s = %s", fullname1, rval);
7970
7971 /* Return values... */
7972 if (value != NULL)
7973 sprintf(value, "%s", rval);
7974 return atof(rval);
7975}

◆ sedi()

double sedi ( const double  p,
const double  T,
const double  rp,
const double  rhop 
)

Calculates the sedimentation velocity of a particle in air.

This function calculates the sedimentation velocity of a particle in air using the given parameters.

Parameters
pThe atmospheric pressure [hPa].
TThe temperature [K].
rpThe radius of the particle [microns].
rhopThe density of the particle [kg/m^3].
Returns
The sedimentation velocity of the particle [m/s].

The function performs the following steps:

  • Converts the radius of the particle from microns to meters.
  • Calculates the density of dry air using the given atmospheric pressure and temperature.
  • Calculates the dynamic viscosity of air using Sutherland's formula.
  • Calculates the thermal velocity of an air molecule using the given temperature.
  • Calculates the mean free path of an air molecule.
  • Computes the Knudsen number for air based on the ratio of mean free path to particle radius.
  • Applies the Cunningham slip-flow correction factor to account for particle size.
  • Computes the sedimentation velocity of the particle based on the difference in densities between the particle and air, incorporating the slip-flow correction.
Note
This function assumes that the ideal gas law and Stokes' law are applicable for calculating the sedimentation velocity of the particle.
Author
Lars Hoffmann

Definition at line 7979 of file mptrac.c.

7983 {
7984
7985 /* Convert particle radius from microns to m... */
7986 double rp_help = rp * 1e-6;
7987
7988 /* Density of dry air [kg / m^3]... */
7989 double rho = RHO(p, T);
7990
7991 /* Dynamic viscosity of air [kg / (m s)]... */
7992 double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
7993
7994 /* Thermal velocity of an air molecule [m / s]... */
7995 double v = sqrt(8. * KB * T / (M_PI * 4.8096e-26));
7996
7997 /* Mean free path of an air molecule [m]... */
7998 double lambda = 2. * eta / (rho * v);
7999
8000 /* Knudsen number for air (dimensionless)... */
8001 double K = lambda / rp_help;
8002
8003 /* Cunningham slip-flow correction (dimensionless)... */
8004 double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
8005
8006 /* Sedimentation velocity [m / s]... */
8007 return 2. * SQR(rp_help) * (rhop - rho) * G0 / (9. * eta) * G;
8008}
#define KB
Boltzmann constant [kg m^2/(K s^2)].
Definition: mptrac.h:187

◆ spline()

void spline ( const double *  x,
const double *  y,
const int  n,
const double *  x2,
double *  y2,
const int  n2,
const int  method 
)

Performs spline interpolation or linear interpolation.

This function interpolates a set of data points using either cubic spline interpolation or linear interpolation, depending on the specified method.

Parameters
xThe array of x-coordinates of the data points.
yThe array of y-coordinates of the data points.
nThe number of data points.
x2The array of x-coordinates where interpolation is required.
y2The array to store the interpolated y-values.
n2The number of points to interpolate.
methodThe interpolation method: 1 for cubic spline, 0 for linear interpolation.

If the method is set to 1 (cubic spline interpolation):

  • The function initializes a cubic spline interpolator using GSL.
  • It interpolates the y-values at the specified x-coordinates using the spline.
  • The interpolated y-values are stored in the provided y2 array.

If the method is set to 0 (linear interpolation):

  • The function performs linear interpolation between adjacent data points.
  • It locates the interval where each interpolation point falls and calculates the interpolated y-value using linear interpolation.
  • The interpolated y-values are stored in the provided y2 array.
Note
The x-coordinates in both arrays (x and x2) must be sorted in ascending order.
Author
Lars Hoffmann

Definition at line 8012 of file mptrac.c.

8019 {
8020
8021 /* Cubic spline interpolation... */
8022 if (method == 1) {
8023
8024 /* Allocate... */
8025 gsl_interp_accel *acc;
8026 gsl_spline *s;
8027 acc = gsl_interp_accel_alloc();
8028 s = gsl_spline_alloc(gsl_interp_cspline, (size_t) n);
8029
8030 /* Interpolate profile... */
8031 gsl_spline_init(s, x, y, (size_t) n);
8032 for (int i = 0; i < n2; i++)
8033 if (x2[i] <= x[0])
8034 y2[i] = y[0];
8035 else if (x2[i] >= x[n - 1])
8036 y2[i] = y[n - 1];
8037 else
8038 y2[i] = gsl_spline_eval(s, x2[i], acc);
8039
8040 /* Free... */
8041 gsl_spline_free(s);
8042 gsl_interp_accel_free(acc);
8043 }
8044
8045 /* Linear interpolation... */
8046 else {
8047 for (int i = 0; i < n2; i++)
8048 if (x2[i] <= x[0])
8049 y2[i] = y[0];
8050 else if (x2[i] >= x[n - 1])
8051 y2[i] = y[n - 1];
8052 else {
8053 int idx = locate_irr(x, n, x2[i]);
8054 y2[i] = LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
8055 }
8056 }
8057}
Here is the call graph for this function:

◆ stddev()

float stddev ( const float *  data,
const int  n 
)

Calculates the standard deviation of a set of data.

This function calculates the standard deviation of a set of floating-point data values.

Parameters
dataPointer to the array of data values.
nNumber of data values in the array.
Returns
The standard deviation of the data values. If the number of data values is less than or equal to 0, returns 0.

The standard deviation is calculated using the formula:

\[ \sigma = \sqrt{\frac{\sum_{i=1}^{n} (x_i - \bar{x})^2}{n}} \]

where:

  • \( \sigma \) is the standard deviation,
  • \( x_i \) is each data value,
  • \( \bar{x} \) is the mean of the data values, and
  • \( n \) is the total number of data values.
Author
Lars Hoffmann

Definition at line 8061 of file mptrac.c.

8063 {
8064
8065 if (n <= 0)
8066 return 0;
8067
8068 float mean = 0, var = 0;
8069
8070 for (int i = 0; i < n; ++i) {
8071 mean += data[i];
8072 var += SQR(data[i]);
8073 }
8074
8075 var = var / (float) n - SQR(mean / (float) n);
8076
8077 return (var > 0 ? sqrtf(var) : 0);
8078}

◆ sza_calc()

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

Calculates the solar zenith angle.

This function calculates the solar zenith angle, which is the angle between the zenith (straight up) and the line connecting the observer to the center of the sun.

Parameters
secSeconds elapsed since 2000-01-01T12:00Z.
lonObserver's longitude in degrees.
latObserver's latitude in degrees.
Returns
The solar zenith angle in radians.

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

Note
This function assumes that the input longitude and latitude are given in degrees.
Author
Lars Hoffmann

Definition at line 8082 of file mptrac.c.

8085 {
8086
8087 /* Number of days and fraction with respect to 2000-01-01T12:00Z... */
8088 const double D = sec / 86400 - 0.5;
8089
8090 /* Geocentric apparent ecliptic longitude [rad]... */
8091 const double g = (357.529 + 0.98560028 * D) * M_PI / 180;
8092 const double q = 280.459 + 0.98564736 * D;
8093 const double L = (q + 1.915 * sin(g) + 0.020 * sin(2 * g)) * M_PI / 180;
8094
8095 /* Mean obliquity of the ecliptic [rad]... */
8096 const double e = (23.439 - 0.00000036 * D) * M_PI / 180;
8097
8098 /* Declination [rad]... */
8099 const double sindec = sin(e) * sin(L);
8100
8101 /* Right ascension [rad]... */
8102 const double ra = atan2(cos(e) * sin(L), cos(L));
8103
8104 /* Greenwich Mean Sidereal Time [h]... */
8105 const double GMST = 18.697374558 + 24.06570982441908 * D;
8106
8107 /* Local Sidereal Time [h]... */
8108 const double LST = GMST + lon / 15;
8109
8110 /* Hour angle [rad]... */
8111 const double h = LST / 12 * M_PI - ra;
8112
8113 /* Convert latitude... */
8114 const double lat_help = lat * M_PI / 180;
8115
8116 /* Return solar zenith angle [rad]... */
8117 return acos(sin(lat_help) * sindec +
8118 cos(lat_help) * sqrt(1 - SQR(sindec)) * cos(h));
8119}

◆ 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 8123 of file mptrac.c.

8131 {
8132
8133 struct tm t0, t1;
8134
8135 t0.tm_year = 100;
8136 t0.tm_mon = 0;
8137 t0.tm_mday = 1;
8138 t0.tm_hour = 0;
8139 t0.tm_min = 0;
8140 t0.tm_sec = 0;
8141
8142 t1.tm_year = year - 1900;
8143 t1.tm_mon = mon - 1;
8144 t1.tm_mday = day;
8145 t1.tm_hour = hour;
8146 t1.tm_min = min;
8147 t1.tm_sec = sec;
8148
8149 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
8150}

◆ timer()

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

Measures and reports elapsed time for named and grouped timers.

The timer function measures elapsed time for a specified named timer and an optional group of timers, accumulating time statistics such as minimum, maximum, and mean elapsed times. It also provides an option to log the timing statistics to an output.

Parameters
nameA string representing the name of the timer.
groupA string representing the group to which the timer belongs.
outputAn integer flag indicating whether to report the timing statistics (non-zero to report).

The function keeps track of multiple timers and groups. When called, it:

  • Gets the current time and calculates the elapsed time since the last call.
  • Adds the elapsed time to the current timers' statistics.
  • Reports the statistics if the output parameter is non-zero.
  • Identifies the IDs of the next timer and group based on the provided name and group.
  • Checks if the name and group are new, and if so, initializes them.
  • Saves the starting time for the next measurement.
Note
The function uses OpenMP's omp_get_wtime() to get the current wall time.
The function maintains static arrays and variables to store timer names, groups, and statistics.
The maximum number of timers and groups is defined by the NTIMER macro.
Warning
If the number of timers or groups exceeds NTIMER, the function will trigger an error message.
Author
Lars Hoffmann

Definition at line 8154 of file mptrac.c.

8157 {
8158
8159 static char names[NTIMER][100], groups[NTIMER][100];
8160
8161 static double rt_name[NTIMER], rt_group[NTIMER],
8162 rt_min[NTIMER], rt_max[NTIMER], dt, t0, t1;
8163
8164 static int iname = -1, igroup = -1, nname, ngroup, ct_name[NTIMER];
8165
8166 /* Get time... */
8167 t1 = omp_get_wtime();
8168 dt = t1 - t0;
8169
8170 /* Add elapsed time to current timers... */
8171 if (iname >= 0) {
8172 rt_name[iname] += dt;
8173 rt_min[iname] = (ct_name[iname] <= 0 ? dt : MIN(rt_min[iname], dt));
8174 rt_max[iname] = (ct_name[iname] <= 0 ? dt : MAX(rt_max[iname], dt));
8175 ct_name[iname]++;
8176 }
8177 if (igroup >= 0)
8178 rt_group[igroup] += t1 - t0;
8179
8180 /* Report timers... */
8181 if (output) {
8182 for (int i = 0; i < nname; i++)
8183 LOG(1, "TIMER_%s = %.3f s (min= %g s, mean= %g s,"
8184 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
8185 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
8186 for (int i = 0; i < ngroup; i++)
8187 LOG(1, "TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
8188 double total = 0.0;
8189 for (int i = 0; i < nname; i++)
8190 total += rt_name[i];
8191 LOG(1, "TIMER_TOTAL = %.3f s", total);
8192 }
8193
8194 /* Identify IDs of next timer... */
8195 for (iname = 0; iname < nname; iname++)
8196 if (strcasecmp(name, names[iname]) == 0)
8197 break;
8198 for (igroup = 0; igroup < ngroup; igroup++)
8199 if (strcasecmp(group, groups[igroup]) == 0)
8200 break;
8201
8202 /* Check whether this is a new timer... */
8203 if (iname >= nname) {
8204 sprintf(names[iname], "%s", name);
8205 if ((++nname) >= NTIMER)
8206 ERRMSG("Too many timers!");
8207 }
8208
8209 /* Check whether this is a new group... */
8210 if (igroup >= ngroup) {
8211 sprintf(groups[igroup], "%s", group);
8212 if ((++ngroup) >= NTIMER)
8213 ERRMSG("Too many groups!");
8214 }
8215
8216 /* Save starting time... */
8217 t0 = t1;
8218}
#define NTIMER
Maximum number of timers.
Definition: mptrac.h:1925

◆ time_from_filename()

double time_from_filename ( const char *  filename,
int  offset 
)

Extracts and converts a timestamp from a filename to Julian seconds.

The time_from_filename function parses a given filename to extract a timestamp and converts it to Julian seconds. The timestamp is expected to follow a specific format and position within the filename, defined by the offset parameter.

Parameters
filenameA string representing the filename containing the timestamp.
offsetAn integer indicating the position from the end of the filename where the timestamp starts.
Returns
The time in Julian seconds as a double.

The function performs the following steps:

  • Extracts the year, month, day, hour, and minute components of the timestamp from the filename using the given offset.
  • Validates the extracted components to ensure they represent a valid date and time.
  • Converts the validated date and time components to Julian seconds using the time2jsec function.
  • Returns the computed time in Julian seconds.
Note
The expected format of the timestamp in the filename is YYYY-MM-DD_HH-MM (e.g., "2023-05-27_14-45").
Warning
If the extracted components do not represent a valid date and time, the function will trigger an error message.
Author
Lars Hoffmann

Definition at line 8222 of file mptrac.c.

8224 {
8225
8226 char tstr[10];
8227
8228 double t;
8229
8230 /* Get time from filename... */
8231 int len = (int) strlen(filename);
8232 sprintf(tstr, "%.4s", &filename[len - offset]);
8233 int year = atoi(tstr);
8234 sprintf(tstr, "%.2s", &filename[len - offset + 5]);
8235 int mon = atoi(tstr);
8236 sprintf(tstr, "%.2s", &filename[len - offset + 8]);
8237 int day = atoi(tstr);
8238 sprintf(tstr, "%.2s", &filename[len - offset + 11]);
8239 int hour = atoi(tstr);
8240 sprintf(tstr, "%.2s", &filename[len - offset + 14]);
8241 int min = atoi(tstr);
8242
8243 /* Check time... */
8244 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
8245 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
8246 ERRMSG("Cannot read time from filename!");
8247
8248 /* Convert time to Julian seconds... */
8249 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
8250
8251 /* Return time... */
8252 return t;
8253}
Here is the call graph for this function:

◆ tropo_weight()

double tropo_weight ( const clim_t clim,
const double  t,
const double  lat,
const double  p 
)

Computes the weighting factor for a given pressure with respect to the tropopause.

The tropo_weight function calculates a weighting factor that indicates how much a given pressure p is influenced by the tropopause based on climatological data.

Parameters
climA pointer to a clim_t structure containing climatological tropopause data.
tThe time parameter, typically representing the time of year or specific temporal context.
latThe latitude for which the weighting factor is being calculated.
pThe pressure for which the weighting factor is to be computed.
Returns
A double representing the weighting factor.

The function performs the following steps:

  • Calculates the tropopause pressure pt using the clim_tropo function.
  • Determines the pressure range around the tropopause: p1 (lower bound) and p0 (upper bound).
  • Computes the weighting factor based on the given pressure p:
    • Returns 1 if p is greater than p0 (troposphere).
    • Returns 0 if p is less than p1 (stratosphere).
    • Linearly interpolates between 1 and 0 for pressures between p0 and p1.
Note
The clim_tropo function is assumed to provide the tropopause pressure based on climatological data.
The constants used in the pressure range calculation (0.866877899 and its reciprocal) are specific to the function's logic.
Author
Lars Hoffmann

Definition at line 8257 of file mptrac.c.

8261 {
8262
8263 /* Get tropopause pressure... */
8264 double pt = clim_tropo(clim, t, lat);
8265
8266 /* Get pressure range... */
8267 double p1 = pt * 0.866877899;
8268 double p0 = pt / 0.866877899;
8269
8270 /* Get weighting factor... */
8271 if (p > p0)
8272 return 1;
8273 else if (p < p1)
8274 return 0;
8275 else
8276 return LIN(p0, 1.0, p1, 0.0, p);
8277}
Here is the call graph for this function:

◆ write_atm()

void write_atm ( const char *  filename,
ctl_t ctl,
atm_t atm,
double  t 
)

Writes air parcel data to a file in various formats.

The write_atm function writes the air parcel data stored in the atm structure to a file specified by filename. The format of the output file is determined by the atm_type_out field in the ctl control structure.

Parameters
filenameA string representing the name of the file to write the data to.
ctlA pointer to a ctl_t structure containing control parameters.
atmA pointer to an atm_t structure containing atmospheric data.
tThe current time, used for certain output formats.

The function performs the following steps:

  • Sets a timer for the write operation using the SELECT_TIMER macro.
  • Logs the beginning of the write operation with the specified filename.
  • Depending on the atm_type_out value in the ctl structure, writes the data in one of the following formats:
    • ASCII (atm_type_out == 0): Calls write_atm_asc.
    • Binary (atm_type_out == 1): Calls write_atm_bin.
    • netCDF (atm_type_out == 2): Calls write_atm_nc.
    • CLaMS trajectory (atm_type_out == 3): Calls write_atm_clams_traj.
    • CLaMS position (atm_type_out == 4): Calls write_atm_clams.
  • If the atm_type_out value is not supported, triggers an error message.
  • Logs various statistics about the atmospheric data, including the number of particles, time range, altitude range, pressure range, longitude range, and latitude range.
  • Logs the range for each quantity specified in the ctl structure.
Author
Lars Hoffmann

Definition at line 8281 of file mptrac.c.

8285 {
8286
8287 /* Set timer... */
8288 SELECT_TIMER("WRITE_ATM", "OUTPUT", NVTX_WRITE);
8289
8290 /* Write info... */
8291 LOG(1, "Write atmospheric data: %s", filename);
8292
8293 /* Write ASCII data... */
8294 if (ctl->atm_type_out == 0)
8295 write_atm_asc(filename, ctl, atm, t);
8296
8297 /* Write binary data... */
8298 else if (ctl->atm_type_out == 1)
8299 write_atm_bin(filename, ctl, atm);
8300
8301 /* Write netCDF data... */
8302 else if (ctl->atm_type_out == 2)
8303 write_atm_nc(filename, ctl, atm);
8304
8305 /* Write CLaMS trajectory data... */
8306 else if (ctl->atm_type_out == 3)
8307 write_atm_clams_traj(filename, ctl, atm, t);
8308
8309 /* Write CLaMS pos data... */
8310 else if (ctl->atm_type_out == 4)
8311 write_atm_clams(filename, ctl, atm);
8312
8313 /* Error... */
8314 else
8315 ERRMSG("Atmospheric data type not supported!");
8316
8317 /* Write info... */
8318 double mini, maxi;
8319 LOG(2, "Number of particles: %d", atm->np);
8320 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
8321 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
8322 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
8323 LOG(2, "Altitude range: %g ... %g km", Z(maxi), Z(mini));
8324 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
8325 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
8326 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
8327 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
8328 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
8329 for (int iq = 0; iq < ctl->nq; iq++) {
8330 char msg[5 * LEN];
8331 sprintf(msg, "Quantity %s range: %s ... %s %s",
8332 ctl->qnt_name[iq], ctl->qnt_format[iq],
8333 ctl->qnt_format[iq], ctl->qnt_unit[iq]);
8334 gsl_stats_minmax(&mini, &maxi, atm->q[iq], 1, (size_t) atm->np);
8335 LOG(2, msg, mini, maxi);
8336 }
8337}
void write_atm_asc(const char *filename, ctl_t *ctl, atm_t *atm, double t)
Writes air parcel data to an ASCII file or gnuplot.
Definition: mptrac.c:8341
void write_atm_clams_traj(const char *dirname, ctl_t *ctl, atm_t *atm, double t)
Writes CLaMS trajectory data to a NetCDF file.
Definition: mptrac.c:8523
void write_atm_clams(const char *filename, ctl_t *ctl, atm_t *atm)
Writes air parcel data to a NetCDF file in the CLaMS format.
Definition: mptrac.c:8473
void write_atm_bin(const char *filename, ctl_t *ctl, atm_t *atm)
Writes air parcel data to a binary file.
Definition: mptrac.c:8423
void write_atm_nc(const char *filename, ctl_t *ctl, atm_t *atm)
Writes air parcel data to a NetCDF file.
Definition: mptrac.c:8672
Here is the call graph for this function:

◆ write_atm_asc()

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

Writes air parcel data to an ASCII file or gnuplot.

The write_atm_asc function writes the atmospheric data stored in the atm structure to an ASCII file specified by filename or to pipe to gnuplot if requested.

Parameters
filenameA string representing the name of the file to write the data to.
ctlA pointer to a ctl_t structure containing control parameters.
atmA pointer to an atm_t structure containing atmospheric data.
tThe current time used for filtering and timestamping.

The function performs the following steps:

  • Sets the time interval for the output data based on the control parameters.
  • Checks if gnuplot output is requested and, if so, creates a pipe to gnuplot and sets up the plot.
  • If gnuplot output is not requested, creates an ASCII file for writing.
  • Writes the header information to the output file, including the description of each column.
  • Iterates over the particles in the atm structure, filtering by time if specified, and writes the data to the output file.
  • Closes the output file or gnuplot pipe.
Author
Lars Hoffmann

Definition at line 8341 of file mptrac.c.

8345 {
8346
8347 FILE *out;
8348
8349 /* Set time interval for output... */
8350 double t0 = t - 0.5 * ctl->dt_mod;
8351 double t1 = t + 0.5 * ctl->dt_mod;
8352
8353 /* Check if gnuplot output is requested... */
8354 if (ctl->atm_gpfile[0] != '-') {
8355
8356 /* Create gnuplot pipe... */
8357 if (!(out = popen("gnuplot", "w")))
8358 ERRMSG("Cannot create pipe to gnuplot!");
8359
8360 /* Set plot filename... */
8361 fprintf(out, "set out \"%s.png\"\n", filename);
8362
8363 /* Set time string... */
8364 double r;
8365 int year, mon, day, hour, min, sec;
8366 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
8367 fprintf(out, "timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
8368 year, mon, day, hour, min);
8369
8370 /* Dump gnuplot file to pipe... */
8371 FILE *in;
8372 if (!(in = fopen(ctl->atm_gpfile, "r")))
8373 ERRMSG("Cannot open file!");
8374 char line[LEN];
8375 while (fgets(line, LEN, in))
8376 fprintf(out, "%s", line);
8377 fclose(in);
8378 }
8379
8380 else {
8381
8382 /* Create file... */
8383 if (!(out = fopen(filename, "w")))
8384 ERRMSG("Cannot create file!");
8385 }
8386
8387 /* Write header... */
8388 fprintf(out,
8389 "# $1 = time [s]\n"
8390 "# $2 = altitude [km]\n"
8391 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
8392 for (int iq = 0; iq < ctl->nq; iq++)
8393 fprintf(out, "# $%i = %s [%s]\n", iq + 5, ctl->qnt_name[iq],
8394 ctl->qnt_unit[iq]);
8395 fprintf(out, "\n");
8396
8397 /* Write data... */
8398 for (int ip = 0; ip < atm->np; ip += ctl->atm_stride) {
8399
8400 /* Check time... */
8401 if (ctl->atm_filter == 2 && (atm->time[ip] < t0 || atm->time[ip] > t1))
8402 continue;
8403
8404 /* Write output... */
8405 fprintf(out, "%.2f %g %g %g", atm->time[ip], Z(atm->p[ip]),
8406 atm->lon[ip], atm->lat[ip]);
8407 for (int iq = 0; iq < ctl->nq; iq++) {
8408 fprintf(out, " ");
8409 if (ctl->atm_filter == 1 && (atm->time[ip] < t0 || atm->time[ip] > t1))
8410 fprintf(out, ctl->qnt_format[iq], NAN);
8411 else
8412 fprintf(out, ctl->qnt_format[iq], atm->q[iq][ip]);
8413 }
8414 fprintf(out, "\n");
8415 }
8416
8417 /* Close file... */
8418 fclose(out);
8419}
Here is the call graph for this function:

◆ write_atm_bin()

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

Writes air parcel data to a binary file.

The write_atm_bin function writes the air parcel data stored in the atm structure to a binary file specified by filename. The function includes versioning information and ensures that all relevant data arrays are written in a consistent binary format.

Parameters
filenameA string representing the name of the file to write the data to.
ctlA pointer to a ctl_t structure containing control parameters.
atmA pointer to an atm_t structure containing atmospheric data.

The function performs the following steps:

  • Creates the binary file for writing. If the file cannot be created, it triggers an error message.
  • Writes a version number for the binary data format.
  • Writes the number of particles to the file.
  • Writes the time, pressure, longitude, and latitude arrays to the file.
  • Iterates over the quantities specified in the ctl structure and writes each quantity array to the file.
  • Writes a final flag to indicate the end of the binary data.
  • Closes the file.
Author
Lars Hoffmann

Definition at line 8423 of file mptrac.c.

8426 {
8427
8428 FILE *out;
8429
8430 /* Create file... */
8431 if (!(out = fopen(filename, "w")))
8432 ERRMSG("Cannot create file!");
8433
8434 /* Write version of binary data... */
8435 int version = 100;
8436 FWRITE(&version, int,
8437 1,
8438 out);
8439
8440 /* Write data... */
8441 FWRITE(&atm->np, int,
8442 1,
8443 out);
8444 FWRITE(atm->time, double,
8445 (size_t) atm->np,
8446 out);
8447 FWRITE(atm->p, double,
8448 (size_t) atm->np,
8449 out);
8450 FWRITE(atm->lon, double,
8451 (size_t) atm->np,
8452 out);
8453 FWRITE(atm->lat, double,
8454 (size_t) atm->np,
8455 out);
8456 for (int iq = 0; iq < ctl->nq; iq++)
8457 FWRITE(atm->q[iq], double,
8458 (size_t) atm->np,
8459 out);
8460
8461 /* Write final flag... */
8462 int final = 999;
8463 FWRITE(&final, int,
8464 1,
8465 out);
8466
8467 /* Close file... */
8468 fclose(out);
8469}

◆ write_atm_clams()

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

Writes air parcel data to a NetCDF file in the CLaMS format.

The write_atm_clams function creates a NetCDF file and writes air parcel data into it. The data includes time, latitude, longitude, pressure, and other specified quantities. The function defines the dimensions and variables, sets global attributes, and writes the data to the file.

Parameters
filenameA string representing the name of the output file.
ctlA pointer to a ctl_t structure containing control parameters.
atmA pointer to an atm_t structure containing atmospheric data.

The function performs the following steps:

  • Creates the NetCDF file with the specified filename.
  • Defines the dimensions for time and the number of particles (NPARTS).
  • Defines variables for time, latitude, longitude, pressure, zeta, and other quantities.
  • Sets global attributes for the vertical coordinate name and model.
  • Writes the data into the NetCDF file.
  • Closes the NetCDF file after writing.
Author
Jan Clemens

Definition at line 8473 of file mptrac.c.

8476 {
8477
8478 int tid, pid, ncid, varid;
8479 size_t start[2], count[2];
8480
8481 /* Create file... */
8482 nc_create(filename, NC_CLOBBER, &ncid);
8483
8484 /* Define dimensions... */
8485 NC(nc_def_dim(ncid, "time", 1, &tid));
8486 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
8487
8488 int dim_ids[2] = { tid, pid };
8489
8490 /* Define variables and their attributes... */
8491 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
8492 "seconds since 2000-01-01 00:00:00 UTC");
8493 NC_DEF_VAR("LAT", NC_DOUBLE, 1, &pid, "Latitude", "deg");
8494 NC_DEF_VAR("LON", NC_DOUBLE, 1, &pid, "Longitude", "deg");
8495 NC_DEF_VAR("PRESS", NC_DOUBLE, 1, &pid, "Pressure", "hPa");
8496 NC_DEF_VAR("ZETA", NC_DOUBLE, 1, &pid, "Zeta", "K");
8497 for (int iq = 0; iq < ctl->nq; iq++)
8498 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
8499 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
8500
8501 /* Define global attributes... */
8502 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
8503 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
8504
8505 /* End definitions... */
8506 NC(nc_enddef(ncid));
8507
8508 /* Write data... */
8509 NC_PUT_DOUBLE("time", atm->time, 0);
8510 NC_PUT_DOUBLE("LAT", atm->lat, 0);
8511 NC_PUT_DOUBLE("LON", atm->lon, 0);
8512 NC_PUT_DOUBLE("PRESS", atm->p, 0);
8513 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 0);
8514 for (int iq = 0; iq < ctl->nq; iq++)
8515 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
8516
8517 /* Close file... */
8518 NC(nc_close(ncid));
8519}
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
Definition: mptrac.h:1163
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
Write double precision data to a NetCDF variable.
Definition: mptrac.h:1077
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units)
Define a NetCDF variable with attributes.
Definition: mptrac.h:1003

◆ write_atm_clams_traj()

void write_atm_clams_traj ( const char *  dirname,
ctl_t ctl,
atm_t atm,
double  t 
)

Writes CLaMS trajectory data to a NetCDF file.

The write_atm_clams_traj function writes trajectory data for the CLaMS model to a NetCDF file. The file is created and populated with data including time, latitude, longitude, pressure, and other quantities. The function also handles the creation of a final initialization file at the last time step.

Parameters
dirnameA string representing the directory name where the file will be created.
ctlA pointer to a ctl_t structure containing control parameters.
atmA pointer to an atm_t structure containing atmospheric data.
tThe current time in seconds since a reference epoch.

The function performs the following steps:

  • Determines the start and stop times of the calculation.
  • Constructs the output filename based on the start and stop times.
  • Defines the hyperslab for the trajectory file.
  • Creates the NetCDF file if it's the first time step and defines dimensions and variables.
  • Writes the trajectory data to the NetCDF file.
  • At the last time step, creates an initialization file with the final data.
Author
Jan Clemens

Definition at line 8523 of file mptrac.c.

8527 {
8528
8529 /* Global Counter... */
8530 static size_t out_cnt = 0;
8531
8532 double r, r_start, r_stop;
8533 int year, mon, day, hour, min, sec;
8534 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
8535 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
8536 char filename_out[2 * LEN] = "traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
8537
8538 int ncid, varid, tid, pid, cid;
8539 int dim_ids[2];
8540
8541 /* time, nparc */
8542 size_t start[2];
8543 size_t count[2];
8544
8545 /* Determine start and stop times of calculation... */
8546 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
8547 jsec2time(ctl->t_start, &year_start, &mon_start, &day_start, &hour_start,
8548 &min_start, &sec_start, &r_start);
8549 jsec2time(ctl->t_stop, &year_stop, &mon_stop, &day_stop, &hour_stop,
8550 &min_stop, &sec_stop, &r_stop);
8551
8552 sprintf(filename_out, "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc",
8553 dirname,
8554 year_start % 100, mon_start, day_start, hour_start,
8555 year_stop % 100, mon_stop, day_stop, hour_stop);
8556 LOG(1, "Write traj file: %s", filename_out);
8557
8558 /* Define hyperslap for the traj_file... */
8559 start[0] = out_cnt;
8560 start[1] = 0;
8561 count[0] = 1;
8562 count[1] = (size_t) atm->np;
8563
8564 /* Create the file at the first timestep... */
8565 if (out_cnt == 0) {
8566
8567 /* Create file... */
8568 nc_create(filename_out, NC_CLOBBER, &ncid);
8569
8570 /* Define dimensions... */
8571 NC(nc_def_dim(ncid, "time", NC_UNLIMITED, &tid));
8572 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
8573 NC(nc_def_dim(ncid, "TMDT", 7, &cid));
8574 dim_ids[0] = tid;
8575 dim_ids[1] = pid;
8576
8577 /* Define variables and their attributes... */
8578 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
8579 "seconds since 2000-01-01 00:00:00 UTC");
8580 NC_DEF_VAR("LAT", NC_DOUBLE, 2, dim_ids, "Latitude", "deg");
8581 NC_DEF_VAR("LON", NC_DOUBLE, 2, dim_ids, "Longitude", "deg");
8582 NC_DEF_VAR("PRESS", NC_DOUBLE, 2, dim_ids, "Pressure", "hPa");
8583 NC_DEF_VAR("ZETA", NC_DOUBLE, 2, dim_ids, "Zeta", "K");
8584 for (int iq = 0; iq < ctl->nq; iq++)
8585 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
8586 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
8587
8588 /* Define global attributes... */
8589 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
8590 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
8591
8592 /* End definitions... */
8593 NC(nc_enddef(ncid));
8594 NC(nc_close(ncid));
8595 }
8596
8597 /* Increment global counter to change hyperslap... */
8598 out_cnt++;
8599
8600 /* Open file... */
8601 NC(nc_open(filename_out, NC_WRITE, &ncid));
8602
8603 /* Write data... */
8604 NC_PUT_DOUBLE("time", atm->time, 1);
8605 NC_PUT_DOUBLE("LAT", atm->lat, 1);
8606 NC_PUT_DOUBLE("LON", atm->lon, 1);
8607 NC_PUT_DOUBLE("PRESS", atm->p, 1);
8608 if (ctl->advect_vert_coord == 1) {
8609 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta], 1);
8610 } else if (ctl->qnt_zeta >= 0) {
8611 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 1);
8612 }
8613 for (int iq = 0; iq < ctl->nq; iq++)
8614 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 1);
8615
8616 /* Close file... */
8617 NC(nc_close(ncid));
8618
8619 /* At the last time step create the init_fix_YYYYMMDDHH file... */
8620 if ((year == year_stop) && (mon == mon_stop)
8621 && (day == day_stop) && (hour == hour_stop)) {
8622
8623 /* Set filename... */
8624 char filename_init[2 * LEN] = "./init_fix_YYYYMMDDHH.nc";
8625 sprintf(filename_init, "%s/init_fix_%02d%02d%02d%02d.nc",
8626 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
8627 LOG(1, "Write init file: %s", filename_init);
8628
8629 /* Create file... */
8630 nc_create(filename_init, NC_CLOBBER, &ncid);
8631
8632 /* Define dimensions... */
8633 NC(nc_def_dim(ncid, "time", 1, &tid));
8634 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
8635 dim_ids[0] = tid;
8636 dim_ids[1] = pid;
8637
8638 /* Define variables and their attributes... */
8639 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
8640 "seconds since 2000-01-01 00:00:00 UTC");
8641 NC_DEF_VAR("LAT", NC_DOUBLE, 1, &pid, "Latitude", "deg");
8642 NC_DEF_VAR("LON", NC_DOUBLE, 1, &pid, "Longitude", "deg");
8643 NC_DEF_VAR("PRESS", NC_DOUBLE, 1, &pid, "Pressure", "hPa");
8644 NC_DEF_VAR("ZETA", NC_DOUBLE, 1, &pid, "Zeta", "K");
8645 for (int iq = 0; iq < ctl->nq; iq++)
8646 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
8647 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
8648
8649 /* Define global attributes... */
8650 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
8651 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
8652
8653 /* End definitions... */
8654 NC(nc_enddef(ncid));
8655
8656 /* Write data... */
8657 NC_PUT_DOUBLE("time", atm->time, 0);
8658 NC_PUT_DOUBLE("LAT", atm->lat, 0);
8659 NC_PUT_DOUBLE("LON", atm->lon, 0);
8660 NC_PUT_DOUBLE("PRESS", atm->p, 0);
8661 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 0);
8662 for (int iq = 0; iq < ctl->nq; iq++)
8663 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
8664
8665 /* Close file... */
8666 NC(nc_close(ncid));
8667 }
8668}
Here is the call graph for this function:

◆ write_atm_nc()

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

Writes air parcel data to a NetCDF file.

The write_atm_nc function creates a NetCDF file and writes air parcel data into it. The data includes time, pressure, longitude, latitude, and other specified quantities. The function defines the dimensions and variables, sets global attributes, and writes the data to the file.

Parameters
filenameA string representing the name of the output file.
ctlA pointer to a ctl_t structure containing control parameters.
atmA pointer to an atm_t structure containing atmospheric data.

The function performs the following steps:

  • Creates the NetCDF file with the specified filename.
  • Defines the dimension for the number of observations (obs).
  • Defines variables for time, pressure, longitude, latitude, and other quantities.
  • Sets global attributes for the feature type.
  • Writes the data into the NetCDF file.
  • Closes the NetCDF file after writing.
Author
Lars Hoffmann

Definition at line 8672 of file mptrac.c.

8675 {
8676
8677 int ncid, obsid, varid;
8678
8679 size_t start[2], count[2];
8680
8681 /* Create file... */
8682 NC(nc_create(filename, NC_CLOBBER, &ncid));
8683
8684 /* Define dimensions... */
8685 NC(nc_def_dim(ncid, "obs", (size_t) atm->np, &obsid));
8686
8687 /* Define variables and their attributes... */
8688 NC_DEF_VAR("time", NC_DOUBLE, 1, &obsid, "time",
8689 "seconds since 2000-01-01 00:00:00 UTC");
8690 NC_DEF_VAR("press", NC_DOUBLE, 1, &obsid, "pressure", "hPa");
8691 NC_DEF_VAR("lon", NC_DOUBLE, 1, &obsid, "longitude", "degrees_east");
8692 NC_DEF_VAR("lat", NC_DOUBLE, 1, &obsid, "latitude", "degrees_north");
8693 for (int iq = 0; iq < ctl->nq; iq++)
8694 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 1, &obsid,
8695 ctl->qnt_longname[iq], ctl->qnt_unit[iq]);
8696
8697 /* Define global attributes... */
8698 NC_PUT_ATT_GLOBAL("featureType", "point");
8699
8700 /* End definitions... */
8701 NC(nc_enddef(ncid));
8702
8703 /* Write data... */
8704 NC_PUT_DOUBLE("time", atm->time, 0);
8705 NC_PUT_DOUBLE("press", atm->p, 0);
8706 NC_PUT_DOUBLE("lon", atm->lon, 0);
8707 NC_PUT_DOUBLE("lat", atm->lat, 0);
8708 for (int iq = 0; iq < ctl->nq; iq++)
8709 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
8710
8711 /* Close file... */
8712 NC(nc_close(ncid));
8713}

◆ write_csi()

void write_csi ( const char *  filename,
ctl_t ctl,
atm_t atm,
double  t 
)

Writes Critical Success Index (CSI) data to a file.

The write_csi function processes air parcel and observation data to calculate and write various verification statistics, including the Critical Success Index (CSI), to a specified output file at regular intervals. The statistics include measures such as the number of hits, misses, and false alarms, bias, probability of detection, false alarm rate, equitable threat score, and correlation coefficients.

Parameters
filenameA string representing the name of the output file.
ctlA pointer to a ctl_t structure containing control parameters.
atmA pointer to an atm_t structure containing atmospheric data.
tA double representing the current time.

The function performs the following steps:

  • Initializes resources and sets up the output file if the current time is the start time.
  • Reads observation data and kernel data if provided.
  • Sets grid box sizes and horizontal coordinates.
  • Allocates memory for mean and count arrays.
  • Loops over observations and model data to accumulate mean values and counts.
  • Analyzes the grid cells to calculate CSI and other statistics.
  • Writes the calculated statistics to the output file at specified intervals.
  • Frees allocated resources and closes the file when the processing is complete.
Author
Lars Hoffmann

Definition at line 8717 of file mptrac.c.

8721 {
8722
8723 static FILE *out;
8724
8725 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
8726 *area, dlon, dlat, dz, x[NCSI], y[NCSI], obsstdn[NCSI], kz[EP], kw[EP];
8727
8728 static int *obscount, ct, cx, cy, cz, ip, ix, iy, iz, n, nobs, nk;
8729
8730 /* Set timer... */
8731 SELECT_TIMER("WRITE_CSI", "OUTPUT", NVTX_WRITE);
8732
8733 /* Init... */
8734 if (t == ctl->t_start) {
8735
8736 /* Check quantity index for mass... */
8737 if (ctl->qnt_m < 0)
8738 ERRMSG("Need quantity mass!");
8739
8740 /* Allocate... */
8741 ALLOC(area, double,
8742 ctl->csi_ny);
8743 ALLOC(rt, double,
8744 NOBS);
8745 ALLOC(rz, double,
8746 NOBS);
8747 ALLOC(rlon, double,
8748 NOBS);
8749 ALLOC(rlat, double,
8750 NOBS);
8751 ALLOC(robs, double,
8752 NOBS);
8753
8754 /* Read observation data... */
8755 read_obs(ctl->csi_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
8756
8757 /* Read kernel data... */
8758 if (ctl->csi_kernel[0] != '-')
8759 read_kernel(ctl->csi_kernel, kz, kw, &nk);
8760
8761 /* Create new file... */
8762 LOG(1, "Write CSI data: %s", filename);
8763 if (!(out = fopen(filename, "w")))
8764 ERRMSG("Cannot create file!");
8765
8766 /* Write header... */
8767 fprintf(out,
8768 "# $1 = time [s]\n"
8769 "# $2 = number of hits (cx)\n"
8770 "# $3 = number of misses (cy)\n"
8771 "# $4 = number of false alarms (cz)\n"
8772 "# $5 = number of observations (cx + cy)\n"
8773 "# $6 = number of forecasts (cx + cz)\n"
8774 "# $7 = bias (ratio of forecasts and observations) [%%]\n"
8775 "# $8 = probability of detection (POD) [%%]\n"
8776 "# $9 = false alarm rate (FAR) [%%]\n"
8777 "# $10 = critical success index (CSI) [%%]\n");
8778 fprintf(out,
8779 "# $11 = hits associated with random chance\n"
8780 "# $12 = equitable threat score (ETS) [%%]\n"
8781 "# $13 = Pearson linear correlation coefficient\n"
8782 "# $14 = Spearman rank-order correlation coefficient\n"
8783 "# $15 = column density mean error (F - O) [kg/m^2]\n"
8784 "# $16 = column density root mean square error (RMSE) [kg/m^2]\n"
8785 "# $17 = column density mean absolute error [kg/m^2]\n"
8786 "# $18 = log-likelihood function\n"
8787 "# $19 = number of data points\n\n");
8788
8789 /* Set grid box size... */
8790 dz = (ctl->csi_z1 - ctl->csi_z0) / ctl->csi_nz;
8791 dlon = (ctl->csi_lon1 - ctl->csi_lon0) / ctl->csi_nx;
8792 dlat = (ctl->csi_lat1 - ctl->csi_lat0) / ctl->csi_ny;
8793
8794 /* Set horizontal coordinates... */
8795 for (iy = 0; iy < ctl->csi_ny; iy++) {
8796 double lat = ctl->csi_lat0 + dlat * (iy + 0.5);
8797 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(lat * M_PI / 180.);
8798 }
8799 }
8800
8801 /* Set time interval... */
8802 double t0 = t - 0.5 * ctl->dt_mod;
8803 double t1 = t + 0.5 * ctl->dt_mod;
8804
8805 /* Allocate... */
8806 ALLOC(modmean, double,
8807 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
8808 ALLOC(obsmean, double,
8809 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
8810 ALLOC(obscount, int,
8811 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
8812 ALLOC(obsstd, double,
8813 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
8814
8815 /* Loop over observations... */
8816 for (int i = 0; i < nobs; i++) {
8817
8818 /* Check time... */
8819 if (rt[i] < t0)
8820 continue;
8821 else if (rt[i] >= t1)
8822 break;
8823
8824 /* Check observation data... */
8825 if (!isfinite(robs[i]))
8826 continue;
8827
8828 /* Calculate indices... */
8829 ix = (int) ((rlon[i] - ctl->csi_lon0) / dlon);
8830 iy = (int) ((rlat[i] - ctl->csi_lat0) / dlat);
8831 iz = (int) ((rz[i] - ctl->csi_z0) / dz);
8832
8833 /* Check indices... */
8834 if (ix < 0 || ix >= ctl->csi_nx ||
8835 iy < 0 || iy >= ctl->csi_ny || iz < 0 || iz >= ctl->csi_nz)
8836 continue;
8837
8838 /* Get mean observation index... */
8839 int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
8840 obsmean[idx] += robs[i];
8841 obsstd[idx] += SQR(robs[i]);
8842 obscount[idx]++;
8843 }
8844
8845 /* Analyze model data... */
8846 for (ip = 0; ip < atm->np; ip++) {
8847
8848 /* Check time... */
8849 if (atm->time[ip] < t0 || atm->time[ip] > t1)
8850 continue;
8851
8852 /* Get indices... */
8853 ix = (int) ((atm->lon[ip] - ctl->csi_lon0) / dlon);
8854 iy = (int) ((atm->lat[ip] - ctl->csi_lat0) / dlat);
8855 iz = (int) ((Z(atm->p[ip]) - ctl->csi_z0) / dz);
8856
8857 /* Check indices... */
8858 if (ix < 0 || ix >= ctl->csi_nx ||
8859 iy < 0 || iy >= ctl->csi_ny || iz < 0 || iz >= ctl->csi_nz)
8860 continue;
8861
8862 /* Get total mass in grid cell... */
8863 int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
8864 modmean[idx] += kernel_weight(kz, kw, nk, atm->p[ip])
8865 * atm->q[ctl->qnt_m][ip];
8866 }
8867
8868 /* Analyze all grid cells... */
8869 for (ix = 0; ix < ctl->csi_nx; ix++)
8870 for (iy = 0; iy < ctl->csi_ny; iy++)
8871 for (iz = 0; iz < ctl->csi_nz; iz++) {
8872
8873 /* Calculate mean observation index... */
8874 int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
8875 if (obscount[idx] > 0) {
8876 obsmean[idx] /= obscount[idx];
8877 obsstd[idx] -= SQR(obsmean[idx]);
8878 obsstd[idx] = sqrt(obsstd[idx]);
8879 }
8880
8881 /* Calculate column density... */
8882 if (modmean[idx] > 0)
8883 modmean[idx] /= (1e6 * area[iy]);
8884
8885 /* Calculate CSI... */
8886 if (obscount[idx] > 0) {
8887 ct++;
8888 if (obsmean[idx] >= ctl->csi_obsmin &&
8889 modmean[idx] >= ctl->csi_modmin)
8890 cx++;
8891 else if (obsmean[idx] >= ctl->csi_obsmin &&
8892 modmean[idx] < ctl->csi_modmin)
8893 cy++;
8894 else if (obsmean[idx] < ctl->csi_obsmin &&
8895 modmean[idx] >= ctl->csi_modmin)
8896 cz++;
8897 }
8898
8899 /* Save data for other verification statistics... */
8900 if (obscount[idx] > 0
8901 && (obsmean[idx] >= ctl->csi_obsmin
8902 || modmean[idx] >= ctl->csi_modmin)) {
8903 x[n] = modmean[idx];
8904 y[n] = obsmean[idx];
8905 if (modmean[idx] >= ctl->csi_modmin)
8906 obsstdn[n] = obsstd[idx];
8907 if ((++n) >= NCSI)
8908 ERRMSG("Too many data points to calculate statistics!");
8909 }
8910 }
8911
8912 /* Write output... */
8913 if (fmod(t, ctl->csi_dt_out) == 0) {
8914
8915 /* Calculate verification statistics
8916 (https://www.cawcr.gov.au/projects/verification/) ... */
8917 static double work[2 * NCSI], work2[2 * NCSI];;
8918 int n_obs = cx + cy;
8919 int n_for = cx + cz;
8920 double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
8921 double pod = (n_obs > 0) ? (100. * cx) / n_obs : NAN;
8922 double far = (n_for > 0) ? (100. * cz) / n_for : NAN;
8923 double csi = (cx + cy + cz > 0) ? (100. * cx) / (cx + cy + cz) : NAN;
8924 double cx_rd = (ct > 0) ? (1. * n_obs * n_for) / ct : NAN;
8925 double ets = (cx + cy + cz - cx_rd > 0) ?
8926 (100. * (cx - cx_rd)) / (cx + cy + cz - cx_rd) : NAN;
8927 double rho_p =
8928 (n > 0) ? gsl_stats_correlation(x, 1, y, 1, (size_t) n) : NAN;
8929 double rho_s =
8930 (n > 0) ? gsl_stats_spearman(x, 1, y, 1, (size_t) n, work) : NAN;
8931 for (int i = 0; i < n; i++) {
8932 work[i] = x[i] - y[i];
8933 work2[i] = (obsstdn[i] != 0) ? (x[i] - y[i]) / obsstdn[i] : 0;
8934 }
8935 double mean = (n > 0) ? gsl_stats_mean(work, 1, (size_t) n) : NAN;
8936 double rmse = (n > 0) ? gsl_stats_sd_with_fixed_mean(work, 1, (size_t) n,
8937 0.0) : NAN;
8938 double absdev =
8939 (n > 0) ? gsl_stats_absdev_m(work, 1, (size_t) n, 0.0) : NAN;
8940 double loglikelihood =
8941 (n > 0) ? gsl_stats_tss(work2, 1, (size_t) n) * (-0.5) : GSL_NAN;
8942
8943 /* Write... */
8944 fprintf(out,
8945 "%.2f %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n", t,
8946 cx, cy, cz, n_obs, n_for, bias, pod, far, csi, cx_rd, ets, rho_p,
8947 rho_s, mean, rmse, absdev, loglikelihood, n);
8948
8949 /* Set counters to zero... */
8950 n = ct = cx = cy = cz = 0;
8951 }
8952
8953 /* Free... */
8954 free(modmean);
8955 free(obsmean);
8956 free(obscount);
8957 free(obsstd);
8958
8959 /* Finalize... */
8960 if (t == ctl->t_stop) {
8961
8962 /* Close output file... */
8963 fclose(out);
8964
8965 /* Free... */
8966 free(area);
8967 free(rt);
8968 free(rz);
8969 free(rlon);
8970 free(rlat);
8971 free(robs);
8972 }
8973}
void read_obs(const char *filename, ctl_t *ctl, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from a file and stores it in arrays.
Definition: mptrac.c:7806
void read_kernel(const char *filename, double kz[EP], double kw[EP], int *nk)
Reads kernel function data from a file and populates the provided arrays.
Definition: mptrac.c:5534
double kernel_weight(const double kz[EP], const double kw[EP], const int nk, const double p)
Calculates the kernel weight based on altitude and given kernel data.
Definition: mptrac.c:1768
#define NCSI
Maximum number of data points for CSI calculation.
Definition: mptrac.h:251
Here is the call graph for this function:

◆ write_ens()

void write_ens ( const char *  filename,
ctl_t ctl,
atm_t atm,
double  t 
)

Writes ensemble data to a file.

The write_ens function processes air parcel data to calculate ensemble means and standard deviations for various quantities and writes them to a specified output file. It handles ensemble members and calculates statistics such as means and standard deviations for each ensemble, along with latitude, longitude, altitude, and time information.

Parameters
filenameA string representing the name of the output file.
ctlA pointer to a ctl_t structure containing control parameters.
atmA pointer to an atm_t structure containing atmospheric data.
tA double representing the current time.

The function performs the following steps:

  • Initializes resources and sets up necessary variables.
  • Sets a time interval for processing data.
  • Loops over air parcels to accumulate means and standard deviations for each ensemble member.
  • Creates an output file and writes header information.
  • Writes ensemble data, including time, altitude, latitude, longitude, means, standard deviations, and the number of members.
  • Closes the output file.
Author
Lars Hoffmann

Definition at line 8977 of file mptrac.c.

8981 {
8982
8983 static FILE *out;
8984
8985 static double dummy, lat, lon, qm[NQ][NENS], qs[NQ][NENS], xm[NENS][3],
8986 x[3], zm[NENS];
8987
8988 static int n[NENS];
8989
8990 /* Set timer... */
8991 SELECT_TIMER("WRITE_ENS", "OUTPUT", NVTX_WRITE);
8992
8993 /* Check quantities... */
8994 if (ctl->qnt_ens < 0)
8995 ERRMSG("Missing ensemble IDs!");
8996
8997 /* Set time interval... */
8998 double t0 = t - 0.5 * ctl->dt_mod;
8999 double t1 = t + 0.5 * ctl->dt_mod;
9000
9001 /* Init... */
9002 for (int i = 0; i < NENS; i++) {
9003 for (int iq = 0; iq < ctl->nq; iq++)
9004 qm[iq][i] = qs[iq][i] = 0;
9005 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
9006 n[i] = 0;
9007 }
9008
9009 /* Loop over air parcels... */
9010 for (int ip = 0; ip < atm->np; ip++) {
9011
9012 /* Check time... */
9013 if (atm->time[ip] < t0 || atm->time[ip] > t1)
9014 continue;
9015
9016 /* Check ensemble ID... */
9017 if (atm->q[ctl->qnt_ens][ip] < 0 || atm->q[ctl->qnt_ens][ip] >= NENS)
9018 ERRMSG("Ensemble ID is out of range!");
9019
9020 /* Get means... */
9021 geo2cart(0, atm->lon[ip], atm->lat[ip], x);
9022 for (int iq = 0; iq < ctl->nq; iq++) {
9023 qm[iq][ctl->qnt_ens] += atm->q[iq][ip];
9024 qs[iq][ctl->qnt_ens] += SQR(atm->q[iq][ip]);
9025 }
9026 xm[ctl->qnt_ens][0] += x[0];
9027 xm[ctl->qnt_ens][1] += x[1];
9028 xm[ctl->qnt_ens][2] += x[2];
9029 zm[ctl->qnt_ens] += Z(atm->p[ip]);
9030 n[ctl->qnt_ens]++;
9031 }
9032
9033 /* Create file... */
9034 LOG(1, "Write ensemble data: %s", filename);
9035 if (!(out = fopen(filename, "w")))
9036 ERRMSG("Cannot create file!");
9037
9038 /* Write header... */
9039 fprintf(out,
9040 "# $1 = time [s]\n"
9041 "# $2 = altitude [km]\n"
9042 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
9043 for (int iq = 0; iq < ctl->nq; iq++)
9044 fprintf(out, "# $%d = %s (mean) [%s]\n", 5 + iq,
9045 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
9046 for (int iq = 0; iq < ctl->nq; iq++)
9047 fprintf(out, "# $%d = %s (sigma) [%s]\n", 5 + ctl->nq + iq,
9048 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
9049 fprintf(out, "# $%d = number of members\n\n", 5 + 2 * ctl->nq);
9050
9051 /* Write data... */
9052 for (int i = 0; i < NENS; i++)
9053 if (n[i] > 0) {
9054 cart2geo(xm[i], &dummy, &lon, &lat);
9055 fprintf(out, "%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
9056 for (int iq = 0; iq < ctl->nq; iq++) {
9057 fprintf(out, " ");
9058 fprintf(out, ctl->qnt_format[iq], qm[iq][i] / n[i]);
9059 }
9060 for (int iq = 0; iq < ctl->nq; iq++) {
9061 fprintf(out, " ");
9062 double var = qs[iq][i] / n[i] - SQR(qm[iq][i] / n[i]);
9063 fprintf(out, ctl->qnt_format[iq], (var > 0 ? sqrt(var) : 0));
9064 }
9065 fprintf(out, " %d\n", n[i]);
9066 }
9067
9068 /* Close file... */
9069 fclose(out);
9070}
void cart2geo(const double *x, double *z, double *lon, double *lat)
State variables of cuRAND random number generator.
Definition: mptrac.c:74
#define NENS
Maximum number of data points for ensemble analysis.
Definition: mptrac.h:271
Here is the call graph for this function:

◆ write_grid()

void write_grid ( const char *  filename,
ctl_t ctl,
met_t met0,
met_t met1,
atm_t atm,
double  t 
)

Writes grid data to a file in ASCII or netCDF format.

The write_grid function processes air parcel data to calculate various grid-based statistics such as column density, mean, and standard deviation for specified quantities. It then writes this data to a specified output file either in ASCII or netCDF format based on the configuration parameters provided in the ctl structure.

Parameters
filenameA string representing the name of the output file.
ctlA pointer to a ctl_t structure containing control parameters.
met0A pointer to a met_t structure containing meteorological data for the initial time step.
met1A pointer to a met_t structure containing meteorological data for the final time step.
atmA pointer to an atm_t structure containing atmospheric data.
tA double representing the current time.

The function performs the following steps:

  • Initializes resources and sets up necessary variables.
  • Reads kernel data if it is specified in the control parameters.
  • Allocates memory for various arrays to store grid data.
  • Determines the grid box size and sets up vertical and horizontal coordinates.
  • Sets a time interval for output data processing.
  • Calculates grid box indices for atmospheric model data.
  • Averages data within each grid box.
  • Calculates column density and volume mixing ratio.
  • Writes data to the output file either in ASCII or netCDF format based on the specified grid_type in the control parameters.
  • Frees allocated memory.
Note
The function supports parallel processing using OpenMP for certain computational tasks to improve performance.
Author
Lars Hoffmann

Definition at line 9074 of file mptrac.c.

9080 {
9081
9082 static double kz[EP], kw[EP];
9083
9084 static int nk;
9085
9086 double *cd, *mean[NQ], *sigma[NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
9087
9088 int *ixs, *iys, *izs, *np;
9089
9090 /* Set timer... */
9091 SELECT_TIMER("WRITE_GRID", "OUTPUT", NVTX_WRITE);
9092
9093 /* Write info... */
9094 LOG(1, "Write grid data: %s", filename);
9095
9096 /* Init... */
9097 if (t == ctl->t_start) {
9098
9099 /* Read kernel data... */
9100 if (ctl->grid_kernel[0] != '-')
9101 read_kernel(ctl->grid_kernel, kz, kw, &nk);
9102 }
9103
9104 /* Allocate... */
9105 ALLOC(cd, double,
9106 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
9107 for (int iq = 0; iq < ctl->nq; iq++) {
9108 ALLOC(mean[iq], double,
9109 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
9110 ALLOC(sigma[iq], double,
9111 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
9112 }
9113 ALLOC(vmr_impl, double,
9114 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
9115 ALLOC(z, double,
9116 ctl->grid_nz);
9117 ALLOC(lon, double,
9118 ctl->grid_nx);
9119 ALLOC(lat, double,
9120 ctl->grid_ny);
9121 ALLOC(area, double,
9122 ctl->grid_ny);
9123 ALLOC(press, double,
9124 ctl->grid_nz);
9125 ALLOC(np, int,
9126 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
9127 ALLOC(ixs, int,
9128 atm->np);
9129 ALLOC(iys, int,
9130 atm->np);
9131 ALLOC(izs, int,
9132 atm->np);
9133
9134 /* Set grid box size... */
9135 double dz = (ctl->grid_z1 - ctl->grid_z0) / ctl->grid_nz;
9136 double dlon = (ctl->grid_lon1 - ctl->grid_lon0) / ctl->grid_nx;
9137 double dlat = (ctl->grid_lat1 - ctl->grid_lat0) / ctl->grid_ny;
9138
9139 /* Set vertical coordinates... */
9140#pragma omp parallel for default(shared)
9141 for (int iz = 0; iz < ctl->grid_nz; iz++) {
9142 z[iz] = ctl->grid_z0 + dz * (iz + 0.5);
9143 press[iz] = P(z[iz]);
9144 }
9145
9146 /* Set horizontal coordinates... */
9147 for (int ix = 0; ix < ctl->grid_nx; ix++)
9148 lon[ix] = ctl->grid_lon0 + dlon * (ix + 0.5);
9149#pragma omp parallel for default(shared)
9150 for (int iy = 0; iy < ctl->grid_ny; iy++) {
9151 lat[iy] = ctl->grid_lat0 + dlat * (iy + 0.5);
9152 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.)
9153 * cos(lat[iy] * M_PI / 180.);
9154 }
9155
9156 /* Set time interval for output... */
9157 double t0 = t - 0.5 * ctl->dt_mod;
9158 double t1 = t + 0.5 * ctl->dt_mod;
9159
9160 /* Get grid box indices... */
9161#pragma omp parallel for default(shared)
9162 for (int ip = 0; ip < atm->np; ip++) {
9163 ixs[ip] = (int) ((atm->lon[ip] - ctl->grid_lon0) / dlon);
9164 iys[ip] = (int) ((atm->lat[ip] - ctl->grid_lat0) / dlat);
9165 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->grid_z0) / dz);
9166 if (atm->time[ip] < t0 || atm->time[ip] > t1
9167 || ixs[ip] < 0 || ixs[ip] >= ctl->grid_nx
9168 || iys[ip] < 0 || iys[ip] >= ctl->grid_ny
9169 || izs[ip] < 0 || izs[ip] >= ctl->grid_nz)
9170 izs[ip] = -1;
9171 }
9172
9173 /* Average data... */
9174 for (int ip = 0; ip < atm->np; ip++)
9175 if (izs[ip] >= 0) {
9176 int idx =
9177 ARRAY_3D(ixs[ip], iys[ip], ctl->grid_ny, izs[ip], ctl->grid_nz);
9178 double kernel = kernel_weight(kz, kw, nk, atm->p[ip]);
9179 np[idx]++;
9180 for (int iq = 0; iq < ctl->nq; iq++) {
9181 mean[iq][idx] += kernel * atm->q[iq][ip];
9182 sigma[iq][idx] += SQR(kernel * atm->q[iq][ip]);
9183 }
9184 }
9185
9186 /* Calculate column density and volume mixing ratio... */
9187#pragma omp parallel for default(shared)
9188 for (int ix = 0; ix < ctl->grid_nx; ix++)
9189 for (int iy = 0; iy < ctl->grid_ny; iy++)
9190 for (int iz = 0; iz < ctl->grid_nz; iz++) {
9191
9192 /* Get grid index... */
9193 int idx = ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz);
9194
9195 /* Calculate column density... */
9196 cd[idx] = NAN;
9197 if (ctl->qnt_m >= 0)
9198 cd[idx] = mean[ctl->qnt_m][idx] / (1e6 * area[iy]);
9199
9200 /* Calculate volume mixing ratio (implicit)... */
9201 vmr_impl[idx] = NAN;
9202 if (ctl->qnt_m >= 0 && ctl->molmass > 0 && met0 != NULL
9203 && met1 != NULL) {
9204 vmr_impl[idx] = 0;
9205 if (mean[ctl->qnt_m][idx] > 0) {
9206
9207 /* Get temperature... */
9208 double temp;
9210 intpol_met_time_3d(met0, met0->t, met1, met1->t, t, press[iz],
9211 lon[ix], lat[iy], &temp, ci, cw, 1);
9212
9213 /* Calculate volume mixing ratio... */
9214 vmr_impl[idx] = MA / ctl->molmass * mean[ctl->qnt_m][idx]
9215 / (RHO(press[iz], temp) * 1e6 * area[iy] * 1e3 * dz);
9216 }
9217 }
9218
9219 /* Calculate mean... */
9220 if (np[idx] > 0)
9221 for (int iq = 0; iq < ctl->nq; iq++) {
9222 mean[iq][idx] /= np[idx];
9223 double var = sigma[iq][idx] / np[idx] - SQR(mean[iq][idx]);
9224 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
9225 } else
9226 for (int iq = 0; iq < ctl->nq; iq++) {
9227 mean[iq][idx] = NAN;
9228 sigma[iq][idx] = NAN;
9229 }
9230 }
9231
9232 /* Write ASCII data... */
9233 if (ctl->grid_type == 0)
9234 write_grid_asc(filename, ctl, cd, mean, sigma, vmr_impl,
9235 t, z, lon, lat, area, dz, np);
9236
9237 /* Write netCDF data... */
9238 else if (ctl->grid_type == 1)
9239 write_grid_nc(filename, ctl, cd, mean, sigma, vmr_impl,
9240 t, z, lon, lat, area, dz, np);
9241
9242 /* Error message... */
9243 else
9244 ERRMSG("Grid data format GRID_TYPE unknown!");
9245
9246 /* Free... */
9247 free(cd);
9248 for (int iq = 0; iq < ctl->nq; iq++) {
9249 free(mean[iq]);
9250 free(sigma[iq]);
9251 }
9252 free(vmr_impl);
9253 free(z);
9254 free(lon);
9255 free(lat);
9256 free(area);
9257 free(press);
9258 free(np);
9259 free(ixs);
9260 free(iys);
9261 free(izs);
9262}
void write_grid_asc(const char *filename, ctl_t *ctl, double *cd, double *mean[NQ], double *sigma[NQ], double *vmr_impl, double t, double *z, double *lon, double *lat, double *area, double dz, int *np)
Writes grid data to an ASCII file.
Definition: mptrac.c:9266
void write_grid_nc(const char *filename, ctl_t *ctl, double *cd, double *mean[NQ], double *sigma[NQ], double *vmr_impl, double t, double *z, double *lon, double *lat, double *area, double dz, int *np)
Writes grid data to a NetCDF file.
Definition: mptrac.c:9370
Here is the call graph for this function:

◆ write_grid_asc()

void write_grid_asc ( const char *  filename,
ctl_t ctl,
double *  cd,
double *  mean[NQ],
double *  sigma[NQ],
double *  vmr_impl,
double  t,
double *  z,
double *  lon,
double *  lat,
double *  area,
double  dz,
int *  np 
)

Writes grid data to an ASCII file.

The write_grid_asc function writes gridded air parcel data, including column density, mean and standard deviation for specified quantities, and volume mixing ratio (if available), to an ASCII file. The function also supports writing gnuplot commands to generate plots if requested in the control parameters.

Parameters
filenameA string representing the name of the output file.
ctlA pointer to a ctl_t structure containing control parameters.
cdAn array of doubles representing column density values.
meanAn array of arrays of doubles representing the mean values for specified quantities.
sigmaAn array of arrays of doubles representing the standard deviation values for specified quantities.
vmr_implAn array of doubles representing the volume mixing ratio (implicit) values.
tA double representing the current time.
zAn array of doubles representing vertical coordinates (altitude).
lonAn array of doubles representing longitudinal coordinates.
latAn array of doubles representing latitudinal coordinates.
areaAn array of doubles representing surface area values.
dzA double representing the layer depth.
npAn array of integers representing the number of particles.

The function performs the following steps:

  • Checks if gnuplot output is requested in the control parameters and sets up a gnuplot pipe if needed.
  • If gnuplot output is requested, sets the plot filename and time string, and dumps gnuplot file contents to the pipe.
  • Otherwise, creates the output file for writing in ASCII format.
  • Writes the header information to the output file, including column labels.
  • Writes the grid data to the output file, including time, altitude, coordinates, surface area, layer depth, column density, volume mixing ratio, number of particles, mean values for specified quantities, and standard deviation values if requested.
  • Closes the output file.
Note
The function supports writing gnuplot commands to generate plots if requested in the control parameters. It also supports writing mean and standard deviation values for specified quantities if requested.
Author
Lars Hoffmann

Definition at line 9266 of file mptrac.c.

9279 {
9280
9281 FILE *out;
9282
9283 /* Check if gnuplot output is requested... */
9284 if (ctl->grid_gpfile[0] != '-') {
9285
9286 /* Create gnuplot pipe... */
9287 if (!(out = popen("gnuplot", "w")))
9288 ERRMSG("Cannot create pipe to gnuplot!");
9289
9290 /* Set plot filename... */
9291 fprintf(out, "set out \"%s.png\"\n", filename);
9292
9293 /* Set time string... */
9294 double r;
9295 int year, mon, day, hour, min, sec;
9296 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
9297 fprintf(out, "timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
9298 year, mon, day, hour, min);
9299
9300 /* Dump gnuplot file to pipe... */
9301 FILE *in;
9302 char line[LEN];
9303 if (!(in = fopen(ctl->grid_gpfile, "r")))
9304 ERRMSG("Cannot open file!");
9305 while (fgets(line, LEN, in))
9306 fprintf(out, "%s", line);
9307 fclose(in);
9308 }
9309
9310 else {
9311
9312 /* Create file... */
9313 if (!(out = fopen(filename, "w")))
9314 ERRMSG("Cannot create file!");
9315 }
9316
9317 /* Write header... */
9318 fprintf(out,
9319 "# $1 = time [s]\n"
9320 "# $2 = altitude [km]\n"
9321 "# $3 = longitude [deg]\n"
9322 "# $4 = latitude [deg]\n"
9323 "# $5 = surface area [km^2]\n"
9324 "# $6 = layer depth [km]\n"
9325 "# $7 = column density (implicit) [kg/m^2]\n"
9326 "# $8 = volume mixing ratio (implicit) [ppv]\n"
9327 "# $9 = number of particles [1]\n");
9328 for (int iq = 0; iq < ctl->nq; iq++)
9329 fprintf(out, "# $%i = %s (mean) [%s]\n", 10 + iq, ctl->qnt_name[iq],
9330 ctl->qnt_unit[iq]);
9331 if (ctl->grid_stddev)
9332 for (int iq = 0; iq < ctl->nq; iq++)
9333 fprintf(out, "# $%i = %s (stddev) [%s]\n", 10 + ctl->nq + iq,
9334 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
9335 fprintf(out, "\n");
9336
9337 /* Write data... */
9338 for (int ix = 0; ix < ctl->grid_nx; ix++) {
9339 if (ix > 0 && ctl->grid_ny > 1 && !ctl->grid_sparse)
9340 fprintf(out, "\n");
9341 for (int iy = 0; iy < ctl->grid_ny; iy++) {
9342 if (iy > 0 && ctl->grid_nz > 1 && !ctl->grid_sparse)
9343 fprintf(out, "\n");
9344 for (int iz = 0; iz < ctl->grid_nz; iz++) {
9345 int idx = ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz);
9346 if (!ctl->grid_sparse || vmr_impl[idx] > 0) {
9347 fprintf(out, "%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
9348 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
9349 for (int iq = 0; iq < ctl->nq; iq++) {
9350 fprintf(out, " ");
9351 fprintf(out, ctl->qnt_format[iq], mean[iq][idx]);
9352 }
9353 if (ctl->grid_stddev)
9354 for (int iq = 0; iq < ctl->nq; iq++) {
9355 fprintf(out, " ");
9356 fprintf(out, ctl->qnt_format[iq], sigma[iq][idx]);
9357 }
9358 fprintf(out, "\n");
9359 }
9360 }
9361 }
9362 }
9363
9364 /* Close file... */
9365 fclose(out);
9366}
Here is the call graph for this function:

◆ write_grid_nc()

void write_grid_nc ( const char *  filename,
ctl_t ctl,
double *  cd,
double *  mean[NQ],
double *  sigma[NQ],
double *  vmr_impl,
double  t,
double *  z,
double *  lon,
double *  lat,
double *  area,
double  dz,
int *  np 
)

Writes grid data to a NetCDF file.

The write_grid_nc function writes gridded air parcel data, including column density, mean and standard deviation for specified quantities, and volume mixing ratio (if available), to a NetCDF file. NetCDF is a self-describing, machine-independent data format for storing scientific data.

Parameters
filenameA string representing the name of the output file.
ctlA pointer to a ctl_t structure containing control parameters.
cdAn array of doubles representing column density values.
meanAn array of arrays of doubles representing the mean values for specified quantities.
sigmaAn array of arrays of doubles representing the standard deviation values for specified quantities.
vmr_implAn array of doubles representing the volume mixing ratio (implicit) values.
tA double representing the current time.
zAn array of doubles representing vertical coordinates (altitude).
lonAn array of doubles representing longitudinal coordinates.
latAn array of doubles representing latitudinal coordinates.
areaAn array of doubles representing surface area values.
dzA double representing the layer depth.
npAn array of integers representing the number of particles.

The function performs the following steps:

  • Allocates memory for temporary arrays required for writing data.
  • Creates a NetCDF file with the specified filename.
  • Defines dimensions and variables in the NetCDF file, along with their attributes.
  • Writes the data arrays to the NetCDF file.
  • Closes the NetCDF file.
  • Frees allocated memory.
Note
NetCDF files are commonly used in scientific computing and can be accessed by various programming languages and software packages. Additionally, the function supports writing mean and standard deviation values for specified quantities if requested.
Author
Lars Hoffmann

Definition at line 9370 of file mptrac.c.

9383 {
9384
9385 char longname[2 * LEN], varname[2 * LEN];
9386
9387 double *help;
9388
9389 int *help2, ncid, dimid[10], varid;
9390
9391 size_t start[2], count[2];
9392
9393 /* Allocate... */
9394 ALLOC(help, double,
9395 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
9396 ALLOC(help2, int,
9397 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
9398
9399 /* Create file... */
9400 NC(nc_create(filename, NC_CLOBBER, &ncid));
9401
9402 /* Define dimensions... */
9403 NC(nc_def_dim(ncid, "time", 1, &dimid[0]));
9404 NC(nc_def_dim(ncid, "z", (size_t) ctl->grid_nz, &dimid[1]));
9405 NC(nc_def_dim(ncid, "lat", (size_t) ctl->grid_ny, &dimid[2]));
9406 NC(nc_def_dim(ncid, "lon", (size_t) ctl->grid_nx, &dimid[3]));
9407 NC(nc_def_dim(ncid, "dz", 1, &dimid[4]));
9408
9409 /* Define variables and their attributes... */
9410 NC_DEF_VAR("time", NC_DOUBLE, 1, &dimid[0], "time",
9411 "seconds since 2000-01-01 00:00:00 UTC");
9412 NC_DEF_VAR("z", NC_DOUBLE, 1, &dimid[1], "altitude", "km");
9413 NC_DEF_VAR("lat", NC_DOUBLE, 1, &dimid[2], "latitude", "degrees_north");
9414 NC_DEF_VAR("lon", NC_DOUBLE, 1, &dimid[3], "longitude", "degrees_east");
9415 NC_DEF_VAR("dz", NC_DOUBLE, 1, &dimid[1], "layer depth", "km");
9416 NC_DEF_VAR("area", NC_DOUBLE, 1, &dimid[2], "surface area", "km**2");
9417 NC_DEF_VAR("cd", NC_FLOAT, 4, dimid, "column density", "kg m**-2");
9418 NC_DEF_VAR("vmr_impl", NC_FLOAT, 4, dimid,
9419 "volume mixing ratio (implicit)", "ppv");
9420 NC_DEF_VAR("np", NC_INT, 4, dimid, "number of particles", "1");
9421 for (int iq = 0; iq < ctl->nq; iq++) {
9422 sprintf(varname, "%s_mean", ctl->qnt_name[iq]);
9423 sprintf(longname, "%s (mean)", ctl->qnt_longname[iq]);
9424 NC_DEF_VAR(varname, NC_DOUBLE, 4, dimid, longname, ctl->qnt_unit[iq]);
9425 if (ctl->grid_stddev) {
9426 sprintf(varname, "%s_stddev", ctl->qnt_name[iq]);
9427 sprintf(longname, "%s (stddev)", ctl->qnt_longname[iq]);
9428 NC_DEF_VAR(varname, NC_DOUBLE, 4, dimid, longname, ctl->qnt_unit[iq]);
9429 }
9430 }
9431 /* End definitions... */
9432 NC(nc_enddef(ncid));
9433
9434 /* Write data... */
9435 NC_PUT_DOUBLE("time", &t, 0);
9436 NC_PUT_DOUBLE("lon", lon, 0);
9437 NC_PUT_DOUBLE("lat", lat, 0);
9438 NC_PUT_DOUBLE("z", z, 0);
9439 NC_PUT_DOUBLE("area", area, 0);
9440 NC_PUT_DOUBLE("dz", &dz, 0);
9441
9442 for (int ix = 0; ix < ctl->grid_nx; ix++)
9443 for (int iy = 0; iy < ctl->grid_ny; iy++)
9444 for (int iz = 0; iz < ctl->grid_nz; iz++)
9445 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
9446 cd[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
9447 NC_PUT_DOUBLE("cd", help, 0);
9448
9449 for (int ix = 0; ix < ctl->grid_nx; ix++)
9450 for (int iy = 0; iy < ctl->grid_ny; iy++)
9451 for (int iz = 0; iz < ctl->grid_nz; iz++)
9452 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
9453 vmr_impl[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
9454 NC_PUT_DOUBLE("vmr_impl", help, 0);
9455
9456 for (int ix = 0; ix < ctl->grid_nx; ix++)
9457 for (int iy = 0; iy < ctl->grid_ny; iy++)
9458 for (int iz = 0; iz < ctl->grid_nz; iz++)
9459 help2[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
9460 np[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
9461 NC_PUT_INT("np", help2, 0);
9462
9463 for (int iq = 0; iq < ctl->nq; iq++) {
9464 sprintf(varname, "%s_mean", ctl->qnt_name[iq]);
9465 for (int ix = 0; ix < ctl->grid_nx; ix++)
9466 for (int iy = 0; iy < ctl->grid_ny; iy++)
9467 for (int iz = 0; iz < ctl->grid_nz; iz++)
9468 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
9469 mean[iq][ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
9470 NC_PUT_DOUBLE(varname, help, 0);
9471 }
9472
9473 if (ctl->grid_stddev)
9474 for (int iq = 0; iq < ctl->nq; iq++) {
9475 sprintf(varname, "%s_stddev", ctl->qnt_name[iq]);
9476 for (int ix = 0; ix < ctl->grid_nx; ix++)
9477 for (int iy = 0; iy < ctl->grid_ny; iy++)
9478 for (int iz = 0; iz < ctl->grid_nz; iz++)
9479 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
9480 sigma[iq][ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
9481 NC_PUT_DOUBLE(varname, help, 0);
9482 }
9483
9484 /* Close file... */
9485 NC(nc_close(ncid));
9486
9487 /* Free... */
9488 free(help);
9489 free(help2);
9490}
#define NC_PUT_INT(varname, ptr, hyperslab)
Write integer data to a NetCDF variable.
Definition: mptrac.h:1124

◆ write_met()

int write_met ( const char *  filename,
ctl_t ctl,
met_t met 
)

Writes meteorological data to a binary file.

The write_met function writes meteorological data, including surface data and level data, to a binary file specified by the filename parameter. The data is written in binary format for efficient storage and transfer.

Parameters
filenameA string representing the name of the output file.
ctlA pointer to a ctl_t structure containing control parameters.
metA pointer to a met_t structure containing meteorological data.

The function performs the following steps:

  • Sets a timer to measure the execution time.
  • Writes information about the meteorological data being written to the log.
  • Checks if compression flags are enabled and displays error messages if required compression methods are not available.
  • Writes binary data to the file, including the type and version of the data, grid data (time, dimensions, coordinates), surface data, and level data.
  • Closes the file after writing all data.
Returns
Returns an integer value indicating the success or failure of the function. A value of 0 indicates successful execution.
Note
This function supports writing meteorological data in different binary formats, including uncompressed and compressed formats using various compression algorithms such as packing, ZFP, ZSTD, and cmultiscale. The specific compression method used depends on the configuration specified in the ctl_t structure.
Author
Lars Hoffmann

Definition at line 9494 of file mptrac.c.

9497 {
9498
9499 /* Set timer... */
9500 SELECT_TIMER("WRITE_MET", "OUTPUT", NVTX_WRITE);
9501
9502 /* Write info... */
9503 LOG(1, "Write meteo data: %s", filename);
9504
9505 /* Check compression flags... */
9506#ifndef ZFP
9507 if (ctl->met_type == 3)
9508 ERRMSG("MPTRAC was compiled without zfp compression!");
9509#endif
9510#ifndef ZSTD
9511 if (ctl->met_type == 4)
9512 ERRMSG("MPTRAC was compiled without zstd compression!");
9513#endif
9514#ifndef CMS
9515 if (ctl->met_type == 5)
9516 ERRMSG("MPTRAC was compiled without cmultiscale compression!");
9517#endif
9518
9519 /* Write binary data... */
9520 if (ctl->met_type >= 1 && ctl->met_type <= 5) {
9521
9522 /* Create file... */
9523 FILE *out;
9524 if (!(out = fopen(filename, "w")))
9525 ERRMSG("Cannot create file!");
9526
9527 /* Write type of binary data... */
9528 FWRITE(&ctl->met_type, int,
9529 1,
9530 out);
9531
9532 /* Write version of binary data... */
9533 int version = 102;
9534 FWRITE(&version, int,
9535 1,
9536 out);
9537
9538 /* Write grid data... */
9539 FWRITE(&met->time, double,
9540 1,
9541 out);
9542 FWRITE(&met->nx, int,
9543 1,
9544 out);
9545 FWRITE(&met->ny, int,
9546 1,
9547 out);
9548 FWRITE(&met->np, int,
9549 1,
9550 out);
9551 FWRITE(met->lon, double,
9552 (size_t) met->nx,
9553 out);
9554 FWRITE(met->lat, double,
9555 (size_t) met->ny,
9556 out);
9557 FWRITE(met->p, double,
9558 (size_t) met->np,
9559 out);
9560
9561 /* Write surface data... */
9562 write_met_bin_2d(out, met, met->ps, "PS");
9563 write_met_bin_2d(out, met, met->ts, "TS");
9564 write_met_bin_2d(out, met, met->zs, "ZS");
9565 write_met_bin_2d(out, met, met->us, "US");
9566 write_met_bin_2d(out, met, met->vs, "VS");
9567 write_met_bin_2d(out, met, met->lsm, "LSM");
9568 write_met_bin_2d(out, met, met->sst, "SST");
9569 write_met_bin_2d(out, met, met->pbl, "PBL");
9570 write_met_bin_2d(out, met, met->pt, "PT");
9571 write_met_bin_2d(out, met, met->tt, "TT");
9572 write_met_bin_2d(out, met, met->zt, "ZT");
9573 write_met_bin_2d(out, met, met->h2ot, "H2OT");
9574 write_met_bin_2d(out, met, met->pct, "PCT");
9575 write_met_bin_2d(out, met, met->pcb, "PCB");
9576 write_met_bin_2d(out, met, met->cl, "CL");
9577 write_met_bin_2d(out, met, met->plcl, "PLCL");
9578 write_met_bin_2d(out, met, met->plfc, "PLFC");
9579 write_met_bin_2d(out, met, met->pel, "PEL");
9580 write_met_bin_2d(out, met, met->cape, "CAPE");
9581 write_met_bin_2d(out, met, met->cin, "CIN");
9582
9583 /* Write level data... */
9584 write_met_bin_3d(out, ctl, met, met->z, "Z",
9585 (ctl->met_zfp_tol_z <= 0 ? ctl->met_zfp_prec : 0),
9586 ctl->met_zfp_tol_z);
9587 write_met_bin_3d(out, ctl, met, met->t, "T",
9588 (ctl->met_zfp_tol_t <= 0 ? ctl->met_zfp_prec : 0),
9589 ctl->met_zfp_tol_t);
9590 write_met_bin_3d(out, ctl, met, met->u, "U", ctl->met_zfp_prec, 0);
9591 write_met_bin_3d(out, ctl, met, met->v, "V", ctl->met_zfp_prec, 0);
9592 write_met_bin_3d(out, ctl, met, met->w, "W", ctl->met_zfp_prec, 0);
9593 write_met_bin_3d(out, ctl, met, met->pv, "PV", ctl->met_zfp_prec, 0);
9594 write_met_bin_3d(out, ctl, met, met->h2o, "H2O", ctl->met_zfp_prec, 0);
9595 write_met_bin_3d(out, ctl, met, met->o3, "O3", ctl->met_zfp_prec, 0);
9596 write_met_bin_3d(out, ctl, met, met->lwc, "LWC", ctl->met_zfp_prec, 0);
9597 write_met_bin_3d(out, ctl, met, met->rwc, "RWC", ctl->met_zfp_prec, 0);
9598 write_met_bin_3d(out, ctl, met, met->iwc, "IWC", ctl->met_zfp_prec, 0);
9599 write_met_bin_3d(out, ctl, met, met->swc, "SWC", ctl->met_zfp_prec, 0);
9600 write_met_bin_3d(out, ctl, met, met->cc, "CC", ctl->met_zfp_prec, 0);
9601
9602 /* Write final flag... */
9603 int final = 999;
9604 FWRITE(&final, int,
9605 1,
9606 out);
9607
9608 /* Close file... */
9609 fclose(out);
9610 }
9611
9612 return 0;
9613}
void write_met_bin_3d(FILE *out, ctl_t *ctl, met_t *met, float var[EX][EY][EP], char *varname, int precision, double tolerance)
Writes a 3-dimensional meteorological variable to a binary file.
Definition: mptrac.c:9646
void write_met_bin_2d(FILE *out, met_t *met, float var[EX][EY], char *varname)
Writes a 2-dimensional meteorological variable to a binary file.
Definition: mptrac.c:9617
int met_zfp_prec
ZFP compression precision for all variables, except z and T.
Definition: mptrac.h:2470
double met_zfp_tol_t
ZFP compression tolerance for temperature.
Definition: mptrac.h:2473
double met_zfp_tol_z
ZFP compression tolerance for geopotential height.
Definition: mptrac.h:2476
Here is the call graph for this function:

◆ write_met_bin_2d()

void write_met_bin_2d ( FILE *  out,
met_t met,
float  var[EX][EY],
char *  varname 
)

Writes a 2-dimensional meteorological variable to a binary file.

The write_met_bin_2d function writes a 2-dimensional meteorological variable to a binary file specified by the out parameter. The variable data is provided in a 2-dimensional array var with maximum dimensions EX by EY. The variable name is provided as a string in the varname parameter.

Parameters
outA pointer to a FILE structure representing the output file.
metA pointer to a met_t structure containing meteorological data.
varAn array of floats representing the 2-dimensional variable data.
varnameA string containing the name of the variable being written.

The function performs the following steps:

  • Allocates memory for a temporary buffer to hold the variable data.
  • Copies the variable data from the 2-dimensional array var to the temporary buffer help.
  • Writes the uncompressed variable data to the binary file specified by out.
  • Logs a message indicating the successful writing of the variable data.
  • Frees the allocated memory.
Note
This function is typically used to write surface data or other 2-dimensional meteorological variables to a binary file.
Author
Lars Hoffmann

Definition at line 9617 of file mptrac.c.

9621 {
9622
9623 float *help;
9624
9625 /* Allocate... */
9626 ALLOC(help, float,
9627 EX * EY);
9628
9629 /* Copy data... */
9630 for (int ix = 0; ix < met->nx; ix++)
9631 for (int iy = 0; iy < met->ny; iy++)
9632 help[ARRAY_2D(ix, iy, met->ny)] = var[ix][iy];
9633
9634 /* Write uncompressed data... */
9635 LOG(2, "Write 2-D variable: %s (uncompressed)", varname);
9636 FWRITE(help, float,
9637 (size_t) (met->nx * met->ny),
9638 out);
9639
9640 /* Free... */
9641 free(help);
9642}

◆ write_met_bin_3d()

void write_met_bin_3d ( FILE *  out,
ctl_t ctl,
met_t met,
float  var[EX][EY][EP],
char *  varname,
int  precision,
double  tolerance 
)

Writes a 3-dimensional meteorological variable to a binary file.

The write_met_bin_3d function writes a 3-dimensional meteorological variable to a binary file specified by the out parameter. The variable data is provided in a 3-dimensional array var with maximum dimensions EX by EY by EP. The variable name is provided as a string in the varname parameter. Additionally, the function takes parameters for specifying the compression precision and tolerance.

Parameters
outA pointer to a FILE structure representing the output file.
ctlA pointer to a ctl_t structure containing control parameters.
metA pointer to a met_t structure containing meteorological data.
varAn array of floats representing the 3-dimensional variable data.
varnameA string containing the name of the variable being written.
precisionAn integer specifying the precision of compression (for certain compression methods).
toleranceA double specifying the tolerance for compression (for certain compression methods).

The function performs the following steps:

  • Allocates memory for a temporary buffer to hold the variable data.
  • Copies the variable data from the 3-dimensional array var to the temporary buffer help.
  • Writes the variable data to the binary file specified by out using the specified compression method (uncompressed, packed, zfp, zstd, cmultiscale).
  • Logs a message indicating the successful writing of the variable data.
  • Frees the allocated memory.
Note
This function is typically used to write level data or other 3-dimensional meteorological variables to a binary file.
Depending on the value of ctl->met_type, the function writes the variable data using different compression methods. If ctl->met_type is not supported, an error message is logged.
Author
Lars Hoffmann

Definition at line 9646 of file mptrac.c.

9653 {
9654
9655 float *help;
9656
9657 /* Allocate... */
9658 ALLOC(help, float,
9659 EX * EY * EP);
9660
9661 /* Copy data... */
9662#pragma omp parallel for default(shared) collapse(2)
9663 for (int ix = 0; ix < met->nx; ix++)
9664 for (int iy = 0; iy < met->ny; iy++)
9665 for (int ip = 0; ip < met->np; ip++)
9666 help[ARRAY_3D(ix, iy, met->ny, ip, met->np)] = var[ix][iy][ip];
9667
9668 /* Write uncompressed data... */
9669 if (ctl->met_type == 1) {
9670 LOG(2, "Write 3-D variable: %s (uncompressed)", varname);
9671 FWRITE(help, float,
9672 (size_t) (met->nx * met->ny * met->np),
9673 out);
9674 }
9675
9676 /* Write packed data... */
9677 else if (ctl->met_type == 2)
9678 compress_pck(varname, help, (size_t) (met->ny * met->nx),
9679 (size_t) met->np, 0, out);
9680
9681 /* Write zfp data... */
9682#ifdef ZFP
9683 else if (ctl->met_type == 3) {
9684 FWRITE(&precision, int,
9685 1,
9686 out);
9687 FWRITE(&tolerance, double,
9688 1,
9689 out);
9690 compress_zfp(varname, help, met->np, met->ny, met->nx, precision,
9691 tolerance, 0, out);
9692 }
9693#endif
9694
9695 /* Write zstd data... */
9696#ifdef ZSTD
9697 else if (ctl->met_type == 4)
9698 compress_zstd(varname, help, (size_t) (met->np * met->ny * met->nx), 0,
9699 out);
9700#endif
9701
9702 /* Write cmultiscale data... */
9703#ifdef CMS
9704 else if (ctl->met_type == 5) {
9705 compress_cms(ctl, varname, help, (size_t) met->nx, (size_t) met->ny,
9706 (size_t) met->np, 0, out);
9707 }
9708#endif
9709
9710 /* Unknown method... */
9711 else {
9712 ERRMSG("MET_TYPE not supported!");
9713 LOG(3, "%d %g", precision, tolerance);
9714 }
9715
9716 /* Free... */
9717 free(help);
9718}
Here is the call graph for this function:

◆ write_output()

void write_output ( const char *  dirname,
ctl_t ctl,
met_t met0,
met_t met1,
atm_t atm,
double  t 
)

Writes various types of output data to files in a specified directory.

The write_output function writes various types of output data to files in the directory specified by the dirname parameter. The function takes control parameters (ctl), two meteorological data structures (met0 and met1), an atmospheric data structure (atm), and a time value (t) as input.

Parameters
dirnameA string representing the directory path where output files will be written.
ctlA pointer to a ctl_t structure containing control parameters.
met0A pointer to a met_t structure representing the first set of meteorological data.
met1A pointer to a met_t structure representing the second set of meteorological data.
atmA pointer to an atm_t structure representing atmospheric data.
tA double value representing the time at which the output is being written.

The function performs the following steps:

  • Parses the input time (t) to extract year, month, day, hour, minute, and second.
  • Updates host memory if necessary based on control parameters.
  • Writes atmospheric data to files if specified by control parameters.
  • Writes gridded data to files if specified by control parameters.
  • Writes CSI (Critical Success Index) data to files if specified by control parameters.
  • Writes ensemble data to files if specified by control parameters.
  • Writes profile data to files if specified by control parameters.
  • Writes sample data to files if specified by control parameters.
  • Writes station data to files if specified by control parameters.
  • Writes VTK (Visualization Toolkit) data to files if specified by control parameters.
Note
This function orchestrates the writing of various types of output data to files based on control parameters and the current simulation time.
Author
Lars Hoffmann

Definition at line 9722 of file mptrac.c.

9728 {
9729
9730 char ext[10], filename[2 * LEN];
9731
9732 double r;
9733
9734 int year, mon, day, hour, min, sec;
9735
9736 /* Get time... */
9737 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
9738
9739 /* Update host... */
9740#ifdef _OPENACC
9741 if ((ctl->atm_basename[0] != '-' && fmod(t, ctl->atm_dt_out) == 0)
9742 || (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0)
9743 || (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0)
9744 || ctl->csi_basename[0] != '-' || ctl->prof_basename[0] != '-'
9745 || ctl->sample_basename[0] != '-' || ctl->stat_basename[0] != '-'
9746 || (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0)) {
9747 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_D2H);
9748#pragma acc update host(atm[:1])
9749 }
9750#endif
9751
9752 /* Write atmospheric data... */
9753 if (ctl->atm_basename[0] != '-' &&
9754 (fmod(t, ctl->atm_dt_out) == 0 || t == ctl->t_stop)) {
9755 if (ctl->atm_type_out == 0)
9756 sprintf(ext, "tab");
9757 else if (ctl->atm_type_out == 1)
9758 sprintf(ext, "bin");
9759 else if (ctl->atm_type_out == 2)
9760 sprintf(ext, "nc");
9761 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
9762 dirname, ctl->atm_basename, year, mon, day, hour, min, ext);
9763 write_atm(filename, ctl, atm, t);
9764 }
9765
9766 /* Write gridded data... */
9767 if (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0) {
9768 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
9769 dirname, ctl->grid_basename, year, mon, day, hour, min,
9770 ctl->grid_type == 0 ? "tab" : "nc");
9771 write_grid(filename, ctl, met0, met1, atm, t);
9772 }
9773
9774 /* Write CSI data... */
9775 if (ctl->csi_basename[0] != '-') {
9776 sprintf(filename, "%s/%s.tab", dirname, ctl->csi_basename);
9777 write_csi(filename, ctl, atm, t);
9778 }
9779
9780 /* Write ensemble data... */
9781 if (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0) {
9782 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
9783 dirname, ctl->ens_basename, year, mon, day, hour, min);
9784 write_ens(filename, ctl, atm, t);
9785 }
9786
9787 /* Write profile data... */
9788 if (ctl->prof_basename[0] != '-') {
9789 sprintf(filename, "%s/%s.tab", dirname, ctl->prof_basename);
9790 write_prof(filename, ctl, met0, met1, atm, t);
9791 }
9792
9793 /* Write sample data... */
9794 if (ctl->sample_basename[0] != '-') {
9795 sprintf(filename, "%s/%s.tab", dirname, ctl->sample_basename);
9796 write_sample(filename, ctl, met0, met1, atm, t);
9797 }
9798
9799 /* Write station data... */
9800 if (ctl->stat_basename[0] != '-') {
9801 sprintf(filename, "%s/%s.tab", dirname, ctl->stat_basename);
9802 write_station(filename, ctl, atm, t);
9803 }
9804
9805 /* Write VTK data... */
9806 if (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0) {
9807 static int nvtk;
9808 if (t == ctl->t_start)
9809 nvtk = 0;
9810 sprintf(filename, "%s/%s_%05d.vtk", dirname, ctl->vtk_basename, ++nvtk);
9811 write_vtk(filename, ctl, atm, t);
9812 }
9813}
void write_vtk(const char *filename, ctl_t *ctl, atm_t *atm, double t)
Writes VTK (Visualization Toolkit) data to a specified file.
Definition: mptrac.c:10294
void write_grid(const char *filename, ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, double t)
Writes grid data to a file in ASCII or netCDF format.
Definition: mptrac.c:9074
void write_sample(const char *filename, ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, double t)
Writes sample data to a specified file.
Definition: mptrac.c:10045
void write_station(const char *filename, ctl_t *ctl, atm_t *atm, double t)
Writes station data to a specified file.
Definition: mptrac.c:10208
void write_atm(const char *filename, ctl_t *ctl, atm_t *atm, double t)
Writes air parcel data to a file in various formats.
Definition: mptrac.c:8281
void write_csi(const char *filename, ctl_t *ctl, atm_t *atm, double t)
Writes Critical Success Index (CSI) data to a file.
Definition: mptrac.c:8717
void write_prof(const char *filename, ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, double t)
Writes profile data to a specified file.
Definition: mptrac.c:9817
void write_ens(const char *filename, ctl_t *ctl, atm_t *atm, double t)
Writes ensemble data to a file.
Definition: mptrac.c:8977
Here is the call graph for this function:

◆ write_prof()

void write_prof ( const char *  filename,
ctl_t ctl,
met_t met0,
met_t met1,
atm_t atm,
double  t 
)

Writes profile data to a specified file.

The write_prof function writes profile data to a file specified by the filename parameter. It takes control parameters (ctl), two meteorological data structures (met0 and met1), an atmospheric data structure (atm), and a time value (t) as input.

Parameters
filenameA string representing the filename where the profile data will be written.
ctlA pointer to a ctl_t structure containing control parameters.
met0A pointer to a met_t structure representing the first set of meteorological data.
met1A pointer to a met_t structure representing the second set of meteorological data.
atmA pointer to an atm_t structure representing atmospheric data.
tA double value representing the time at which the profile data is being written.

The function performs the following steps:

  • Initializes variables and allocates memory if it's the start of the simulation.
  • Reads observation data and creates a new output file if necessary.
  • Writes header information to the output file.
  • Sets grid box size and vertical coordinates.
  • Processes observations and model data within the specified time interval.
  • Calculates and writes output data for each grid cell.
  • Finalizes by closing the output file and freeing allocated memory if it's the end of the simulation.
Note
This function writes profile data to a file, including time, altitude, coordinates, atmospheric properties, observed data, and the number of observations.
Author
Lars Hoffmann

Definition at line 9817 of file mptrac.c.

9823 {
9824
9825 static FILE *out;
9826
9827 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
9828 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
9829
9830 static int nobs, *obscount, ip, okay;
9831
9832 /* Set timer... */
9833 SELECT_TIMER("WRITE_PROF", "OUTPUT", NVTX_WRITE);
9834
9835 /* Init... */
9836 if (t == ctl->t_start) {
9837
9838 /* Check quantity index for mass... */
9839 if (ctl->qnt_m < 0)
9840 ERRMSG("Need quantity mass!");
9841
9842 /* Check molar mass... */
9843 if (ctl->molmass <= 0)
9844 ERRMSG("Specify molar mass!");
9845
9846 /* Allocate... */
9847 ALLOC(lon, double,
9848 ctl->prof_nx);
9849 ALLOC(lat, double,
9850 ctl->prof_ny);
9851 ALLOC(area, double,
9852 ctl->prof_ny);
9853 ALLOC(z, double,
9854 ctl->prof_nz);
9855 ALLOC(press, double,
9856 ctl->prof_nz);
9857 ALLOC(rt, double,
9858 NOBS);
9859 ALLOC(rz, double,
9860 NOBS);
9861 ALLOC(rlon, double,
9862 NOBS);
9863 ALLOC(rlat, double,
9864 NOBS);
9865 ALLOC(robs, double,
9866 NOBS);
9867
9868 /* Read observation data... */
9869 read_obs(ctl->prof_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
9870
9871 /* Create new output file... */
9872 LOG(1, "Write profile data: %s", filename);
9873 if (!(out = fopen(filename, "w")))
9874 ERRMSG("Cannot create file!");
9875
9876 /* Write header... */
9877 fprintf(out,
9878 "# $1 = time [s]\n"
9879 "# $2 = altitude [km]\n"
9880 "# $3 = longitude [deg]\n"
9881 "# $4 = latitude [deg]\n"
9882 "# $5 = pressure [hPa]\n"
9883 "# $6 = temperature [K]\n"
9884 "# $7 = volume mixing ratio [ppv]\n"
9885 "# $8 = H2O volume mixing ratio [ppv]\n"
9886 "# $9 = O3 volume mixing ratio [ppv]\n"
9887 "# $10 = observed BT index [K]\n"
9888 "# $11 = number of observations\n");
9889
9890 /* Set grid box size... */
9891 dz = (ctl->prof_z1 - ctl->prof_z0) / ctl->prof_nz;
9892 dlon = (ctl->prof_lon1 - ctl->prof_lon0) / ctl->prof_nx;
9893 dlat = (ctl->prof_lat1 - ctl->prof_lat0) / ctl->prof_ny;
9894
9895 /* Set vertical coordinates... */
9896 for (int iz = 0; iz < ctl->prof_nz; iz++) {
9897 z[iz] = ctl->prof_z0 + dz * (iz + 0.5);
9898 press[iz] = P(z[iz]);
9899 }
9900
9901 /* Set horizontal coordinates... */
9902 for (int ix = 0; ix < ctl->prof_nx; ix++)
9903 lon[ix] = ctl->prof_lon0 + dlon * (ix + 0.5);
9904 for (int iy = 0; iy < ctl->prof_ny; iy++) {
9905 lat[iy] = ctl->prof_lat0 + dlat * (iy + 0.5);
9906 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.)
9907 * cos(lat[iy] * M_PI / 180.);
9908 }
9909 }
9910
9911 /* Set time interval... */
9912 double t0 = t - 0.5 * ctl->dt_mod;
9913 double t1 = t + 0.5 * ctl->dt_mod;
9914
9915 /* Allocate... */
9916 ALLOC(mass, double,
9917 ctl->prof_nx * ctl->prof_ny * ctl->prof_nz);
9918 ALLOC(obsmean, double,
9919 ctl->prof_nx * ctl->prof_ny);
9920 ALLOC(obscount, int,
9921 ctl->prof_nx * ctl->prof_ny);
9922
9923 /* Loop over observations... */
9924 for (int i = 0; i < nobs; i++) {
9925
9926 /* Check time... */
9927 if (rt[i] < t0)
9928 continue;
9929 else if (rt[i] >= t1)
9930 break;
9931
9932 /* Check observation data... */
9933 if (!isfinite(robs[i]))
9934 continue;
9935
9936 /* Calculate indices... */
9937 int ix = (int) ((rlon[i] - ctl->prof_lon0) / dlon);
9938 int iy = (int) ((rlat[i] - ctl->prof_lat0) / dlat);
9939
9940 /* Check indices... */
9941 if (ix < 0 || ix >= ctl->prof_nx || iy < 0 || iy >= ctl->prof_ny)
9942 continue;
9943
9944 /* Get mean observation index... */
9945 int idx = ARRAY_2D(ix, iy, ctl->prof_ny);
9946 obsmean[idx] += robs[i];
9947 obscount[idx]++;
9948 }
9949
9950 /* Analyze model data... */
9951 for (ip = 0; ip < atm->np; ip++) {
9952
9953 /* Check time... */
9954 if (atm->time[ip] < t0 || atm->time[ip] > t1)
9955 continue;
9956
9957 /* Get indices... */
9958 int ix = (int) ((atm->lon[ip] - ctl->prof_lon0) / dlon);
9959 int iy = (int) ((atm->lat[ip] - ctl->prof_lat0) / dlat);
9960 int iz = (int) ((Z(atm->p[ip]) - ctl->prof_z0) / dz);
9961
9962 /* Check indices... */
9963 if (ix < 0 || ix >= ctl->prof_nx ||
9964 iy < 0 || iy >= ctl->prof_ny || iz < 0 || iz >= ctl->prof_nz)
9965 continue;
9966
9967 /* Get total mass in grid cell... */
9968 int idx = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
9969 mass[idx] += atm->q[ctl->qnt_m][ip];
9970 }
9971
9972 /* Extract profiles... */
9973 for (int ix = 0; ix < ctl->prof_nx; ix++)
9974 for (int iy = 0; iy < ctl->prof_ny; iy++) {
9975 int idx2 = ARRAY_2D(ix, iy, ctl->prof_ny);
9976 if (obscount[idx2] > 0) {
9977
9978 /* Check profile... */
9979 okay = 0;
9980 for (int iz = 0; iz < ctl->prof_nz; iz++) {
9981 int idx3 = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
9982 if (mass[idx3] > 0) {
9983 okay = 1;
9984 break;
9985 }
9986 }
9987 if (!okay)
9988 continue;
9989
9990 /* Write output... */
9991 fprintf(out, "\n");
9992
9993 /* Loop over altitudes... */
9994 for (int iz = 0; iz < ctl->prof_nz; iz++) {
9995
9996 /* Get temperature, water vapor, and ozone... */
9998 intpol_met_time_3d(met0, met0->t, met1, met1->t, t, press[iz],
9999 lon[ix], lat[iy], &temp, ci, cw, 1);
10000 intpol_met_time_3d(met0, met0->h2o, met1, met1->h2o, t, press[iz],
10001 lon[ix], lat[iy], &h2o, ci, cw, 0);
10002 intpol_met_time_3d(met0, met0->o3, met1, met1->o3, t, press[iz],
10003 lon[ix], lat[iy], &o3, ci, cw, 0);
10004
10005 /* Calculate volume mixing ratio... */
10006 int idx3 = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
10007 vmr = MA / ctl->molmass * mass[idx3]
10008 / (RHO(press[iz], temp) * area[iy] * dz * 1e9);
10009
10010 /* Write output... */
10011 fprintf(out, "%.2f %g %g %g %g %g %g %g %g %g %d\n",
10012 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
10013 obsmean[idx2] / obscount[idx2], obscount[idx2]);
10014 }
10015 }
10016 }
10017
10018 /* Free... */
10019 free(mass);
10020 free(obsmean);
10021 free(obscount);
10022
10023 /* Finalize... */
10024 if (t == ctl->t_stop) {
10025
10026 /* Close output file... */
10027 fclose(out);
10028
10029 /* Free... */
10030 free(lon);
10031 free(lat);
10032 free(area);
10033 free(z);
10034 free(press);
10035 free(rt);
10036 free(rz);
10037 free(rlon);
10038 free(rlat);
10039 free(robs);
10040 }
10041}
Here is the call graph for this function:

◆ write_sample()

void write_sample ( const char *  filename,
ctl_t ctl,
met_t met0,
met_t met1,
atm_t atm,
double  t 
)

Writes sample data to a specified file.

The write_sample function writes sample data to a file specified by the filename parameter. It takes control parameters (ctl), two meteorological data structures (met0 and met1), an atmospheric data structure (atm), and a time value (t) as input.

Parameters
filenameA string representing the filename where the sample data will be written.
ctlA pointer to a ctl_t structure containing control parameters.
met0A pointer to a met_t structure representing the first set of meteorological data.
met1A pointer to a met_t structure representing the second set of meteorological data.
atmA pointer to an atm_t structure representing atmospheric data.
tA double value representing the time at which the sample data is being written.

The function performs the following steps:

  • Initializes variables and allocates memory if it's the start of the simulation.
  • Reads observation data and kernel data if necessary.
  • Creates a new output file and writes header information to it.
  • Sets latitude range, squared radius, and area.
  • Processes observations and calculates sample data within the specified time interval.
  • Writes output data for each observation.
  • Finalizes by closing the output file and freeing allocated memory if it's the end of the simulation.
Note
This function writes sample data to a file, including time, altitude, coordinates, surface area, layer depth, number of particles, column density, volume mixing ratio, and observed data.
Author
Lars Hoffmann

Definition at line 10045 of file mptrac.c.

10051 {
10052
10053 static FILE *out;
10054
10055 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[EP],
10056 kw[EP];
10057
10058 static int nobs, nk;
10059
10060 /* Set timer... */
10061 SELECT_TIMER("WRITE_SAMPLE", "OUTPUT", NVTX_WRITE);
10062
10063 /* Init... */
10064 if (t == ctl->t_start) {
10065
10066 /* Allocate... */
10067 ALLOC(rt, double,
10068 NOBS);
10069 ALLOC(rz, double,
10070 NOBS);
10071 ALLOC(rlon, double,
10072 NOBS);
10073 ALLOC(rlat, double,
10074 NOBS);
10075 ALLOC(robs, double,
10076 NOBS);
10077
10078 /* Read observation data... */
10079 read_obs(ctl->sample_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
10080
10081 /* Read kernel data... */
10082 if (ctl->sample_kernel[0] != '-')
10083 read_kernel(ctl->sample_kernel, kz, kw, &nk);
10084
10085 /* Create output file... */
10086 LOG(1, "Write sample data: %s", filename);
10087 if (!(out = fopen(filename, "w")))
10088 ERRMSG("Cannot create file!");
10089
10090 /* Write header... */
10091 fprintf(out,
10092 "# $1 = time [s]\n"
10093 "# $2 = altitude [km]\n"
10094 "# $3 = longitude [deg]\n"
10095 "# $4 = latitude [deg]\n"
10096 "# $5 = surface area [km^2]\n"
10097 "# $6 = layer depth [km]\n"
10098 "# $7 = number of particles [1]\n"
10099 "# $8 = column density [kg/m^2]\n"
10100 "# $9 = volume mixing ratio [ppv]\n"
10101 "# $10 = observed BT index [K]\n\n");
10102
10103 /* Set latitude range, squared radius, and area... */
10104 dlat = DY2DEG(ctl->sample_dx);
10105 rmax2 = SQR(ctl->sample_dx);
10106 area = M_PI * rmax2;
10107 }
10108
10109 /* Set time interval for output... */
10110 double t0 = t - 0.5 * ctl->dt_mod;
10111 double t1 = t + 0.5 * ctl->dt_mod;
10112
10113 /* Loop over observations... */
10114 for (int i = 0; i < nobs; i++) {
10115
10116 /* Check time... */
10117 if (rt[i] < t0)
10118 continue;
10119 else if (rt[i] >= t1)
10120 break;
10121
10122 /* Calculate Cartesian coordinates... */
10123 double x0[3];
10124 geo2cart(0, rlon[i], rlat[i], x0);
10125
10126 /* Set pressure range... */
10127 double rp = P(rz[i]);
10128 double ptop = P(rz[i] + ctl->sample_dz);
10129 double pbot = P(rz[i] - ctl->sample_dz);
10130
10131 /* Init... */
10132 double mass = 0;
10133 int np = 0;
10134
10135 /* Loop over air parcels... */
10136#pragma omp parallel for default(shared) reduction(+:mass,np)
10137 for (int ip = 0; ip < atm->np; ip++) {
10138
10139 /* Check time... */
10140 if (atm->time[ip] < t0 || atm->time[ip] > t1)
10141 continue;
10142
10143 /* Check latitude... */
10144 if (fabs(rlat[i] - atm->lat[ip]) > dlat)
10145 continue;
10146
10147 /* Check horizontal distance... */
10148 double x1[3];
10149 geo2cart(0, atm->lon[ip], atm->lat[ip], x1);
10150 if (DIST2(x0, x1) > rmax2)
10151 continue;
10152
10153 /* Check pressure... */
10154 if (ctl->sample_dz > 0)
10155 if (atm->p[ip] > pbot || atm->p[ip] < ptop)
10156 continue;
10157
10158 /* Add mass... */
10159 if (ctl->qnt_m >= 0)
10160 mass +=
10161 kernel_weight(kz, kw, nk, atm->p[ip]) * atm->q[ctl->qnt_m][ip];
10162 np++;
10163 }
10164
10165 /* Calculate column density... */
10166 double cd = mass / (1e6 * area);
10167
10168 /* Calculate volume mixing ratio... */
10169 double vmr = 0;
10170 if (ctl->molmass > 0 && ctl->sample_dz > 0) {
10171 if (mass > 0) {
10172
10173 /* Get temperature... */
10174 double temp;
10176 intpol_met_time_3d(met0, met0->t, met1, met1->t, rt[i], rp,
10177 rlon[i], rlat[i], &temp, ci, cw, 1);
10178
10179 /* Calculate volume mixing ratio... */
10180 vmr = MA / ctl->molmass * mass
10181 / (RHO(rp, temp) * 1e6 * area * 1e3 * ctl->sample_dz);
10182 }
10183 } else
10184 vmr = NAN;
10185
10186 /* Write output... */
10187 fprintf(out, "%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
10188 rlon[i], rlat[i], area, ctl->sample_dz, np, cd, vmr, robs[i]);
10189 }
10190
10191 /* Finalize...... */
10192 if (t == ctl->t_stop) {
10193
10194 /* Close output file... */
10195 fclose(out);
10196
10197 /* Free... */
10198 free(rt);
10199 free(rz);
10200 free(rlon);
10201 free(rlat);
10202 free(robs);
10203 }
10204}
Here is the call graph for this function:

◆ write_station()

void write_station ( const char *  filename,
ctl_t ctl,
atm_t atm,
double  t 
)

Writes station data to a specified file.

The write_station function writes station data to a file specified by the filename parameter. It takes control parameters (ctl), an atmospheric data structure (atm), and a time value (t) as input.

Parameters
filenameA string representing the filename where the station data will be written.
ctlA pointer to a ctl_t structure containing control parameters.
atmA pointer to an atm_t structure representing atmospheric data.
tA double value representing the time at which the station data is being written.

The function performs the following steps:

  • Initializes variables and opens a new file if it's the start of the simulation.
  • Writes header information to the output file.
  • Sets geolocation and search radius for station data.
  • Processes air parcels and writes station data within the specified time interval and search radius.
  • Writes station data for each air parcel satisfying the criteria.
  • Closes the output file if it's the end of the simulation.
Note
This function writes station data to a file, including time, altitude, longitude, latitude, and additional quantities specified in the control parameters.
Author
Lars Hoffmann

Definition at line 10208 of file mptrac.c.

10212 {
10213
10214 static FILE *out;
10215
10216 static double rmax2, x0[3], x1[3];
10217
10218 /* Set timer... */
10219 SELECT_TIMER("WRITE_STATION", "OUTPUT", NVTX_WRITE);
10220
10221 /* Init... */
10222 if (t == ctl->t_start) {
10223
10224 /* Write info... */
10225 LOG(1, "Write station data: %s", filename);
10226
10227 /* Create new file... */
10228 if (!(out = fopen(filename, "w")))
10229 ERRMSG("Cannot create file!");
10230
10231 /* Write header... */
10232 fprintf(out,
10233 "# $1 = time [s]\n"
10234 "# $2 = altitude [km]\n"
10235 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
10236 for (int iq = 0; iq < ctl->nq; iq++)
10237 fprintf(out, "# $%i = %s [%s]\n", (iq + 5),
10238 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
10239 fprintf(out, "\n");
10240
10241 /* Set geolocation and search radius... */
10242 geo2cart(0, ctl->stat_lon, ctl->stat_lat, x0);
10243 rmax2 = SQR(ctl->stat_r);
10244 }
10245
10246 /* Set time interval for output... */
10247 double t0 = t - 0.5 * ctl->dt_mod;
10248 double t1 = t + 0.5 * ctl->dt_mod;
10249
10250 /* Loop over air parcels... */
10251 for (int ip = 0; ip < atm->np; ip++) {
10252
10253 /* Check time... */
10254 if (atm->time[ip] < t0 || atm->time[ip] > t1)
10255 continue;
10256
10257 /* Check time range for station output... */
10258 if (atm->time[ip] < ctl->stat_t0 || atm->time[ip] > ctl->stat_t1)
10259 continue;
10260
10261 /* Check station flag... */
10262 if (ctl->qnt_stat >= 0)
10263 if ((int) atm->q[ctl->qnt_stat][ip])
10264 continue;
10265
10266 /* Get Cartesian coordinates... */
10267 geo2cart(0, atm->lon[ip], atm->lat[ip], x1);
10268
10269 /* Check horizontal distance... */
10270 if (DIST2(x0, x1) > rmax2)
10271 continue;
10272
10273 /* Set station flag... */
10274 if (ctl->qnt_stat >= 0)
10275 atm->q[ctl->qnt_stat][ip] = 1;
10276
10277 /* Write data... */
10278 fprintf(out, "%.2f %g %g %g",
10279 atm->time[ip], Z(atm->p[ip]), atm->lon[ip], atm->lat[ip]);
10280 for (int iq = 0; iq < ctl->nq; iq++) {
10281 fprintf(out, " ");
10282 fprintf(out, ctl->qnt_format[iq], atm->q[iq][ip]);
10283 }
10284 fprintf(out, "\n");
10285 }
10286
10287 /* Close file... */
10288 if (t == ctl->t_stop)
10289 fclose(out);
10290}
Here is the call graph for this function:

◆ write_vtk()

void write_vtk ( const char *  filename,
ctl_t ctl,
atm_t atm,
double  t 
)

Writes VTK (Visualization Toolkit) data to a specified file.

The write_vtk function writes VTK data to a file specified by the filename parameter. It takes control parameters (ctl), an atmospheric data structure (atm), and a time value (t) as input.

Parameters
filenameA string representing the filename where the VTK data will be written.
ctlA pointer to a ctl_t structure containing control parameters.
atmA pointer to an atm_t structure representing atmospheric data.
tA double value representing the time at which the VTK data is being written.

The function performs the following steps:

  • Sets a timer and logs information about writing VTK data.
  • Sets a time interval for output based on the specified time and control parameters.
  • Creates a new file and checks if the file creation was successful.
  • Counts the number of data points to be written.
  • Writes the VTK header, including metadata.
  • Writes point coordinates based on the sphere or Cartesian coordinate system.
  • Writes point data for each quantity specified in the control parameters.
  • Closes the output file.
Note
This function writes VTK data in ASCII format, including point coordinates and associated scalar data for visualization purposes.
Author
Lars Hoffmann

Definition at line 10294 of file mptrac.c.

10298 {
10299
10300 FILE *out;
10301
10302 /* Set timer... */
10303 SELECT_TIMER("WRITE_VTK", "OUTPUT", NVTX_WRITE);
10304
10305 /* Write info... */
10306 LOG(1, "Write VTK data: %s", filename);
10307
10308 /* Set time interval for output... */
10309 double t0 = t - 0.5 * ctl->dt_mod;
10310 double t1 = t + 0.5 * ctl->dt_mod;
10311
10312 /* Create file... */
10313 if (!(out = fopen(filename, "w")))
10314 ERRMSG("Cannot create file!");
10315
10316 /* Count data points... */
10317 int np = 0;
10318 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
10319 if (atm->time[ip] < t0 || atm->time[ip] > t1)
10320 continue;
10321 np++;
10322 }
10323
10324 /* Write header... */
10325 fprintf(out,
10326 "# vtk DataFile Version 3.0\n"
10327 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
10328
10329 /* Write point coordinates... */
10330 fprintf(out, "POINTS %d float\n", np);
10331 if (ctl->vtk_sphere) {
10332 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
10333 if (atm->time[ip] < t0 || atm->time[ip] > t1)
10334 continue;
10335 double radius = (RE + Z(atm->p[ip]) * ctl->vtk_scale
10336 + ctl->vtk_offset) / RE;
10337 double x = radius * cos(atm->lat[ip] / 180. * M_PI)
10338 * cos(atm->lon[ip] / 180. * M_PI);
10339 double y = radius * cos(atm->lat[ip] / 180. * M_PI)
10340 * sin(atm->lon[ip] / 180. * M_PI);
10341 double z = radius * sin(atm->lat[ip] / 180. * M_PI);
10342 fprintf(out, "%g %g %g\n", x, y, z);
10343 }
10344 } else
10345 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
10346 if (atm->time[ip] < t0 || atm->time[ip] > t1)
10347 continue;
10348 fprintf(out, "%g %g %g\n", atm->lon[ip], atm->lat[ip],
10349 Z(atm->p[ip]) * ctl->vtk_scale + ctl->vtk_offset);
10350 }
10351
10352 /* Write point data... */
10353 fprintf(out, "POINT_DATA %d\n", np);
10354 for (int iq = 0; iq < ctl->nq; iq++) {
10355 fprintf(out, "SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
10356 ctl->qnt_name[iq]);
10357 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
10358 if (atm->time[ip] < t0 || atm->time[ip] > t1)
10359 continue;
10360 fprintf(out, "%g\n", atm->q[iq][ip]);
10361 }
10362 }
10363
10364 /* Close file... */
10365 fclose(out);
10366}