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 KARMAN   0.40
 Karman's constant. 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)    (RE * DEG2RAD(dlon) * cos(DEG2RAD(lat)))
 Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude. More...
 
#define DEG2DY(dlat)    (RE * DEG2RAD(dlat))
 Convert a latitude difference to a distance in the y-direction (north-south). More...
 
#define DEG2RAD(deg)    ((deg) * (M_PI / 180.0))
 Converts degrees to radians. 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, level, quant)
 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 RAD2DEG(rad)    ((rad) * (180.0 / M_PI))
 Converts radians to degrees. 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 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)
 Computes the value of the zeta vertical coordinate. 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 (const ctl_t *ctl, clim_t *clim)
 Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data. More...
 
double clim_photo (const double rate[CP][CSZA][CO3], const clim_photo_t *photo, const double p, const double sza, const 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 (const ctl_t *ctl, const char *varname, float *array, const size_t nx, const size_t ny, const size_t np, const int decompress, FILE *inout)
 Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm. More...
 
void compress_pck (const char *varname, float *array, const size_t nxy, const size_t nz, const int decompress, FILE *inout)
 Compresses or decompresses a 3D array of floats. More...
 
void compress_zfp (const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
 Compresses or decompresses a 3D array of floats using the ZFP library. More...
 
void compress_zstd (const char *varname, float *array, const size_t n, const 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, const 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_help (const ctl_t *ctl, const double t, const int direct, const char *metbase, const double dt_met, char *filename)
 Generates a formatted filename for meteorological data files based on the input parameters. 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 (const int met_tropo, ctl_t *ctl, clim_t *clim, met_t *met, const double *lons, const int nx, const double *lats, const 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 (const met_t *met0, float height0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float height1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double height, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
 Interpolates meteorological variables to a given position and time. More...
 
void intpol_met_space_3d (const met_t *met, float array[EX][EY][EP], const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
 Interpolates meteorological variables in 3D space. More...
 
void intpol_met_space_3d_ml (const met_t *met, float zs[EX][EY][EP], float vals[EX][EY][EP], const double z, const double lon, const double lat, double *val)
 Interpolates meteorological data in 3D space. More...
 
void intpol_met_space_2d (const met_t *met, float array[EX][EY], const double lon, const double lat, double *var, int *ci, double *cw, const int init)
 Interpolates meteorological variables in 2D space. More...
 
void intpol_met_time_3d (const met_t *met0, float array0[EX][EY][EP], const met_t *met1, float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
 Interpolates meteorological data in 3D space and time. More...
 
void intpol_met_time_3d_ml (const met_t *met0, float zs0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float zs1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var)
 Interpolates meteorological data in both space and time. More...
 
void intpol_met_time_2d (const met_t *met0, float array0[EX][EY], const met_t *met1, float array1[EX][EY], const double ts, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
 Interpolates meteorological data in 2D space and time. More...
 
void intpol_tropo_3d (const double time0, float array0[EX][EY], const double time1, float array1[EX][EY], const double lons[EX], const double lats[EY], const int nlon, const int nlat, const double time, const double lon, const double lat, const 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_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], const int np, const int lon_ap_ind, const int lat_ap_ind, const double alt_ap, int *ind)
 Locate the four vertical indizes of a box for a given height value. More...
 
void module_advect (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Performs the advection of atmospheric particles using meteorological data. More...
 
void module_advect_init (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Initializes the advection module by setting up pressure fields. More...
 
void module_bound_cond (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Apply boundary conditions to particles based on meteorological and climatological data. More...
 
void module_chem_grid (const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double t)
 Calculate grid data for chemistry modules. More...
 
void module_chem_init (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Initializes the chemistry modules by setting atmospheric composition. More...
 
void module_convection (const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Performs convective mixing of atmospheric particles. More...
 
void module_decay (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, atm_t *atm)
 Simulate exponential decay processes for atmospheric particles. More...
 
void module_diff_meso (const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Simulate mesoscale diffusion for atmospheric particles. More...
 
void module_diff_pbl (const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Computes particle diffusion within the planetary boundary layer (PBL). More...
 
void module_diff_turb (const ctl_t *ctl, cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Applies turbulent diffusion processes to atmospheric particles. More...
 
void module_dry_depo (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Simulate dry deposition of atmospheric particles. More...
 
void module_h2o2_chem (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Perform chemical reactions involving H2O2 within cloud particles. More...
 
void module_isosurf_init (const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Initialize the isosurface module based on atmospheric data. More...
 
void module_isosurf (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Apply the isosurface module to adjust atmospheric properties. More...
 
void module_kpp_chem (ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 KPP chemistry module. More...
 
void module_meteo (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Update atmospheric properties using meteorological data. More...
 
void module_mixing (const ctl_t *ctl, const clim_t *clim, atm_t *atm, const double t)
 Update atmospheric properties through interparcel mixing. More...
 
void module_mixing_help (const ctl_t *ctl, const clim_t *clim, atm_t *atm, const int *ixs, const int *iys, const int *izs, const int qnt_idx)
 Perform interparcel mixing for a specific quantity. More...
 
void module_oh_chem (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Perform hydroxyl chemistry calculations for atmospheric particles. More...
 
void module_position (const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Update the positions and pressure levels of atmospheric particles. More...
 
void module_rng_init (const int ntask)
 Initialize random number generators for parallel tasks. More...
 
void module_rng (const ctl_t *ctl, double *rs, const size_t n, const int method)
 Generate random numbers using various methods and distributions. More...
 
void module_sedi (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Simulate sedimentation of particles in the atmosphere. More...
 
void module_sort (const 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 (const ctl_t *ctl, cache_t *cache, met_t *met0, atm_t *atm, const double t)
 Calculate time steps for air parcels based on specified conditions. More...
 
void module_timesteps_init (ctl_t *ctl, const atm_t *atm)
 Initialize start time and time interval for time-stepping. More...
 
void module_tracer_chem (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Simulate chemical reactions involving long-lived atmospheric tracers. More...
 
void module_wet_depo (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Perform wet deposition calculations for air parcels. More...
 
void mptrac_alloc (ctl_t **ctl, cache_t **cache, clim_t **clim, met_t **met0, met_t **met1, atm_t **atm)
 Allocates and initializes memory resources for MPTRAC. More...
 
void mptrac_free (ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Frees memory resources allocated for MPTRAC. More...
 
void mptrac_get_met (ctl_t *ctl, clim_t *clim, const double t, met_t **met0, met_t **met1)
 Retrieves meteorological data for the specified time. More...
 
void mptrac_init (ctl_t *ctl, cache_t *cache, clim_t *clim, atm_t *atm, const int ntask)
 Initializes the MPTRAC model and its associated components. More...
 
int mptrac_read_atm (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads air parcel data from a specified file into the given atmospheric structure. More...
 
void mptrac_read_clim (const ctl_t *ctl, clim_t *clim)
 Reads various climatological data and populates the given climatology structure. More...
 
void mptrac_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...
 
int mptrac_read_met (const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met)
 Reads meteorological data from a file, supporting multiple formats and MPI broadcasting. More...
 
void mptrac_run_timestep (ctl_t *ctl, cache_t *cache, clim_t *clim, met_t **met0, met_t **met1, atm_t *atm, double t)
 Executes a single timestep of the MPTRAC model simulation. More...
 
void mptrac_write_atm (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes air parcel data to a file in various formats. More...
 
void mptrac_write_met (const char *filename, const ctl_t *ctl, met_t *met)
 Writes meteorological data to a file, supporting multiple formats and compression options. More...
 
void mptrac_write_output (const char *dirname, const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double t)
 Writes various types of output data to files in a specified directory. More...
 
void mptrac_update_device (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
 Updates device memory for specified data structures. More...
 
void mptrac_update_host (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
 Updates host memory for specified data structures. More...
 
double nat_temperature (const double p, const double h2o, const double hno3)
 Calculates the nitric acid trihydrate (NAT) temperature. More...
 
double pbl_weight (const ctl_t *ctl, const atm_t *atm, const int ip, const double pbl, const double ps)
 Computes a weighting factor based on planetary boundary layer pressure. More...
 
int read_atm_asc (const char *filename, const 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, const 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, const 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, const 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_photo (const char *filename, clim_photo_t *photo)
 Reads photolysis rates from a NetCDF file and populates the given photolysis structure. More...
 
void read_clim_photo_help (const int ncid, const char *varname, const clim_photo_t *photo, double var[CP][CSZA][CO3])
 Reads a 3D climatological photochemistry variable from a NetCDF file. 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, const char *varname, clim_zm_t *zm)
 Reads zonally averaged climatological data from a netCDF 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_bin (const char *filename, const ctl_t *ctl, met_t *met)
 Reads meteorological data from a binary file. More...
 
void read_met_bin_2d (FILE *in, const met_t *met, float var[EX][EY], const 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, const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname, const float bound_min, const float bound_max)
 Reads 3D meteorological data from a binary file, potentially using different compression methods. More...
 
void read_met_cape (const ctl_t *ctl, const 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 (const 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 (const ctl_t *ctl, met_t *met)
 Calculates geopotential heights from meteorological data. More...
 
void read_met_grid (const char *filename, const int ncid, const ctl_t *ctl, met_t *met)
 Reads meteorological grid information from a NetCDF file. More...
 
void read_met_levels (const int ncid, const ctl_t *ctl, met_t *met)
 Reads meteorological variables at different vertical levels from a NetCDF file. More...
 
void read_met_ml2pl (const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const 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 (const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met)
 Reads meteorological data from a NetCDF file and processes it. More...
 
int read_met_nc_2d (const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const char *varname5, const char *varname6, const ctl_t *ctl, const met_t *met, float dest[EX][EY], const float scl, const int init)
 Reads a 2-dimensional meteorological variable from a NetCDF file. More...
 
int read_met_nc_3d (const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const ctl_t *ctl, const met_t *met, float dest[EX][EY][EP], const float scl)
 Reads a 3-dimensional meteorological variable from a NetCDF file. More...
 
void read_met_pbl (const ctl_t *ctl, met_t *met)
 Computes the planetary boundary layer (PBL) pressure based on meteorological data. 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 (const ctl_t *ctl, met_t *met)
 Downsamples meteorological data based on specified parameters. More...
 
void read_met_surface (const int ncid, const ctl_t *ctl, met_t *met)
 Reads surface meteorological data from a netCDF file and stores it in the meteorological data structure. More...
 
void read_met_tropo (const ctl_t *ctl, const 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, const 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, const 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, const int output)
 Measures and reports elapsed time for named and grouped timers. More...
 
double time_from_filename (const char *filename, const int offset)
 Extracts and converts a timestamp from a filename to Julian seconds. More...
 
double tropo_weight (const clim_t *clim, const atm_t *atm, const int ip)
 Computes a weighting factor based on tropopause pressure. More...
 
void write_atm_asc (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes air parcel data to an ASCII file or gnuplot. More...
 
void write_atm_bin (const char *filename, const ctl_t *ctl, const atm_t *atm)
 Writes air parcel data to a binary file. More...
 
void write_atm_clams (const char *filename, const ctl_t *ctl, const atm_t *atm)
 Writes air parcel data to a NetCDF file in the CLaMS format. More...
 
void write_atm_clams_traj (const char *dirname, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes CLaMS trajectory data to a NetCDF file. More...
 
void write_atm_nc (const char *filename, const ctl_t *ctl, const atm_t *atm)
 Writes air parcel data to a NetCDF file. More...
 
void write_csi (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes Critical Success Index (CSI) data to a file. More...
 
void write_ens (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes ensemble data to a file. More...
 
void write_grid (const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
 Writes grid data to a file in ASCII or netCDF format. More...
 
void write_grid_asc (const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
 Writes grid data to an ASCII file. More...
 
void write_grid_nc (const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
 Writes grid data to a NetCDF file. More...
 
void write_met_bin (const char *filename, const ctl_t *ctl, met_t *met)
 Writes meteorological data in binary format to a specified file. More...
 
void write_met_bin_2d (FILE *out, met_t *met, float var[EX][EY], const char *varname)
 Writes a 2-dimensional meteorological variable to a binary file. More...
 
void write_met_bin_3d (FILE *out, const ctl_t *ctl, met_t *met, float var[EX][EY][EP], const char *varname, const int precision, const double tolerance)
 Writes a 3-dimensional meteorological variable to a binary file. More...
 
void write_met_nc (const char *filename, const ctl_t *ctl, met_t *met)
 Writes meteorological data to a NetCDF file. More...
 
void write_met_nc_2d (const int ncid, const char *varname, met_t *met, float var[EX][EY], const float scl)
 Writes a 2D meteorological variable to a NetCDF file. More...
 
void write_met_nc_3d (const int ncid, const char *varname, met_t *met, float var[EX][EY][EP], const float scl)
 Writes a 3D meteorological variable to a NetCDF file. More...
 
void write_prof (const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
 Writes profile data to a specified file. More...
 
void write_sample (const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
 Writes sample data to a specified file. More...
 
void write_station (const char *filename, const ctl_t *ctl, atm_t *atm, const double t)
 Writes station data to a specified file. More...
 
void write_vtk (const char *filename, const ctl_t *ctl, const atm_t *atm, const 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.

◆ KARMAN

#define KARMAN   0.40

Karman's constant.

Definition at line 187 of file mptrac.h.

◆ KB

#define KB   1.3806504e-23

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

Definition at line 192 of file mptrac.h.

◆ MA

#define MA   28.9644

Molar mass of dry air [g/mol].

Definition at line 197 of file mptrac.h.

◆ MH2O

#define MH2O   18.01528

Molar mass of water vapor [g/mol].

Definition at line 202 of file mptrac.h.

◆ MO3

#define MO3   48.00

Molar mass of ozone [g/mol].

Definition at line 207 of file mptrac.h.

◆ P0

#define P0   1013.25

Standard pressure [hPa].

Definition at line 212 of file mptrac.h.

◆ RA

#define RA   (1e3 * RI / MA)

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

Definition at line 217 of file mptrac.h.

◆ RE

#define RE   6367.421

Mean radius of Earth [km].

Definition at line 222 of file mptrac.h.

◆ RI

#define RI   8.3144598

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

Definition at line 227 of file mptrac.h.

◆ T0

#define T0   273.15

Standard temperature [K].

Definition at line 232 of file mptrac.h.

◆ LEN

#define LEN   5000

Maximum length of ASCII data lines.

Definition at line 241 of file mptrac.h.

◆ NP

#define NP   10000000

Maximum number of atmospheric data points.

Definition at line 246 of file mptrac.h.

◆ NQ

#define NQ   15

Maximum number of quantities per data point.

Definition at line 251 of file mptrac.h.

◆ NCSI

#define NCSI   1000000

Maximum number of data points for CSI calculation.

Definition at line 256 of file mptrac.h.

◆ EP

#define EP   140

Maximum number of pressure levels for meteo data.

Definition at line 261 of file mptrac.h.

◆ EX

#define EX   1202

Maximum number of longitudes for meteo data.

Definition at line 266 of file mptrac.h.

◆ EY

#define EY   602

Maximum number of latitudes for meteo data.

Definition at line 271 of file mptrac.h.

◆ NENS

#define NENS   2000

Maximum number of data points for ensemble analysis.

Definition at line 276 of file mptrac.h.

◆ NOBS

#define NOBS   10000000

Maximum number of observation data points.

Definition at line 281 of file mptrac.h.

◆ NTHREADS

#define NTHREADS   512

Maximum number of OpenMP threads.

Definition at line 286 of file mptrac.h.

◆ CY

#define CY   250

Maximum number of latitudes for climatological data.

Definition at line 291 of file mptrac.h.

◆ CO3

#define CO3   30

Maximum number of total column ozone data for climatological data.

Definition at line 296 of file mptrac.h.

◆ CP

#define CP   70

Maximum number of pressure levels for climatological data.

Definition at line 301 of file mptrac.h.

◆ CSZA

#define CSZA   50

Maximum number of solar zenith angles for climatological data.

Definition at line 306 of file mptrac.h.

◆ CT

#define CT   12

Maximum number of time steps for climatological data.

Definition at line 311 of file mptrac.h.

◆ CTS

#define CTS   1000

Maximum number of data points of climatological time series.

Definition at line 316 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 349 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 372 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 391 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 416 of file mptrac.h.

◆ DEG2DX

#define DEG2DX (   dlon,
  lat 
)     (RE * DEG2RAD(dlon) * cos(DEG2RAD(lat)))

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 440 of file mptrac.h.

◆ DEG2DY

#define DEG2DY (   dlat)     (RE * DEG2RAD(dlat))

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 461 of file mptrac.h.

◆ DEG2RAD

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

Converts degrees to radians.

This macro converts an angle from degrees to radians using the formula: radians = degrees * (Ï€ / 180)

Parameters
degThe angle in degrees to be converted.
Returns
The angle in radians.
Note
This macro uses the M_PI constant from <math.h> for the value of π.
Author
Lars Hoffmann

Definition at line 478 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.
Warning
Don't use this for large values of dp!
Author
Lars Hoffmann

Definition at line 503 of file mptrac.h.

◆ DX2DEG

#define DX2DEG (   dx,
  lat 
)
Value:
(((lat) < -89.999 || (lat) > 89.999) ? 0 \
: (dx) * 180. / (M_PI * RE * cos(DEG2RAD(lat))))
#define RE
Mean radius of Earth [km].
Definition: mptrac.h:222
#define DEG2RAD(deg)
Converts degrees to radians.
Definition: mptrac.h:478

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 525 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 543 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.
Warning
Don't use this for large values of dz!
Author
Lars Hoffmann

Definition at line 562 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 578 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 594 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 610 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 629 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 647 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 667 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 682 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(const met_t *met0, float array0[EX][EY], const met_t *met1, float array1[EX][EY], const double ts, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 2D space and time.
Definition: mptrac.c:1556

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 696 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(const met_t *met0, float array0[EX][EY][EP], const met_t *met1, float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 3D space and time.
Definition: mptrac.c:1502

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 713 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 732 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 786 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:217
#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 840 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 859 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 886 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 900 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 987 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 1002 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 1016 of file mptrac.h.

◆ NC_DEF_VAR

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

Define a NetCDF variable with attributes.

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

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

Definition at line 1045 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:1871

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 1075 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 1103 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 1126 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 1150 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 1173 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 1195 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 1212 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 1232 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 1247 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 || cache->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 1274 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 1304 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 1328 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 1352 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 1379 of file mptrac.h.

◆ RAD2DEG

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

Converts radians to degrees.

This macro converts an angle from radians to degrees using the formula: degrees = radians * (180 / π)

Parameters
radThe angle in radians to be converted.
Returns
The angle in degrees.
Note
This macro uses the M_PI constant from <math.h> for the value of π.
Author
Lars Hoffmann

Definition at line 1396 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 1426 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 1456 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 1481 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 1500 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 1523 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 1544 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 1557 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 1571 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:1379
#define T0
Standard temperature [K].
Definition: mptrac.h:232

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 1595 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 1620 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 1644 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 1673 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:1904

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 1694 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 1719 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 1741 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:1719
#define MA
Molar mass of dry air [g/mol].
Definition: mptrac.h:197
#define RI
Ideal gas constant [J/(mol K)].
Definition: mptrac.h:227

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 1772 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:1644

Computes the value of the zeta vertical coordinate.

This macro calculates the zeta vertical coordinate based on the given surface pressure (ps), pressure (p), and temperature (t). The calculation depends on the ratio p/ps:

  • If p/ps <= 0.3, the function returns 1.0 multiplied by THETA(p, t).
  • Otherwise, it computes a sine function transformation scaled by THETA(p, t).
Parameters
psSurface pressure.
pPressure at the given level.
tTemperature at the given level.
Returns
Computed zeta vertical coordinate value.
Author
Lars Hoffmann

Definition at line 1791 of file mptrac.h.

◆ LOGLEV

#define LOGLEV   2

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

Definition at line 1802 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:1802

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 1834 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 1871 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 1904 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 1939 of file mptrac.h.

◆ NTIMER

#define NTIMER   100

Maximum number of timers.

Definition at line 1948 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 1963 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 1984 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 2003 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 2018 of file mptrac.h.

◆ NVTX_PUSH

#define NVTX_PUSH (   range_title,
  range_color 
)    {}

Definition at line 2110 of file mptrac.h.

◆ NVTX_POP

#define NVTX_POP   {}

Definition at line 2111 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 const double radius = NORM(x);
81
82 *lat = RAD2DEG(asin(x[2] / radius));
83 *lon = RAD2DEG(atan2(x[1], x[0]));
84 *z = radius - RE;
85}
#define NORM(a)
Compute the norm (magnitude) of a vector.
Definition: mptrac.h:1247
#define RAD2DEG(rad)
Converts radians to degrees.
Definition: mptrac.h:1396

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

95 {
96
97 /* Set SZA threshold... */
98 const double sza_thresh = DEG2RAD(85.), cos_sza_thresh = cos(sza_thresh);
99
100 /* Get OH data from climatology... */
101 const double oh = clim_zm(&clim->oh, t, lat, p);
102
103 /* Apply diurnal correction... */
104 if (ctl->oh_chem_beta > 0) {
105 double sza = sza_calc(t, lon, lat);
106 if (sza <= sza_thresh)
107 return oh * exp(-ctl->oh_chem_beta / cos(sza));
108 else
109 return oh * exp(-ctl->oh_chem_beta / cos_sza_thresh);
110 } else
111 return oh;
112}
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:401
double sza_calc(const double sec, const double lon, const double lat)
Calculates the solar zenith angle.
Definition: mptrac.c:9019
clim_zm_t oh
OH zonal means.
Definition: mptrac.h:3328
double oh_chem_beta
Beta parameter for diurnal variablity of OH.
Definition: mptrac.h:2844
Here is the call graph for this function:

◆ clim_oh_diurnal_correction()

void clim_oh_diurnal_correction ( const 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 116 of file mptrac.c.

118 {
119
120 /* Set SZA threshold... */
121 const double sza_thresh = DEG2RAD(85.), cos_sza_thresh = cos(sza_thresh);
122
123 /* Loop over climatology data points... */
124 for (int it = 0; it < clim->oh.ntime; it++)
125 for (int iz = 0; iz < clim->oh.np; iz++)
126 for (int iy = 0; iy < clim->oh.nlat; iy++) {
127
128 /* Init... */
129 int n = 0;
130 double sum = 0;
131
132 /* Integrate day/night correction factor over longitude... */
133 for (double lon = -180; lon < 180; lon += 1.0) {
134 double sza = sza_calc(clim->oh.time[it], lon, clim->oh.lat[iy]);
135 if (sza <= sza_thresh)
136 sum += exp(-ctl->oh_chem_beta / cos(sza));
137 else
138 sum += exp(-ctl->oh_chem_beta / cos_sza_thresh);
139 n++;
140 }
141
142 /* Apply scaling factor to OH data... */
143 clim->oh.vmr[it][iz][iy] /= (sum / (double) n);
144 }
145}
double time[CT]
Time [s].
Definition: mptrac.h:3284
int np
Number of pressure levels.
Definition: mptrac.h:3281
double vmr[CT][CP][CY]
Volume mixing ratio [ppv].
Definition: mptrac.h:3293
int ntime
Number of timesteps.
Definition: mptrac.h:3275
int nlat
Number of latitudes.
Definition: mptrac.h:3278
double lat[CY]
Latitude [deg].
Definition: mptrac.h:3287
Here is the call graph for this function:

◆ clim_photo()

double clim_photo ( const double  rate[CP][CSZA][CO3],
const clim_photo_t photo,
const double  p,
const double  sza,
const 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 149 of file mptrac.c.

154 {
155
156 /* Check pressure range... */
157 double p_help = p;
158 if (p < photo->p[photo->np - 1])
159 p_help = photo->p[photo->np - 1];
160 else if (p > photo->p[0])
161 p_help = photo->p[0];
162
163 /* Check sza range... */
164 double sza_help = sza;
165 if (sza < photo->sza[0])
166 sza_help = photo->sza[0];
167 else if (sza > photo->sza[photo->nsza - 1])
168 sza_help = photo->sza[photo->nsza - 1];
169
170 /* Check ozone column range... */
171 double o3c_help = o3c;
172 if (o3c < photo->o3c[0])
173 o3c_help = photo->o3c[0];
174 else if (o3c > photo->o3c[photo->no3c - 1])
175 o3c_help = photo->o3c[photo->no3c - 1];
176
177 /* Get indices... */
178 const int ip = locate_irr(photo->p, photo->np, p_help);
179 const int isza = locate_reg(photo->sza, photo->nsza, sza_help);
180 const int io3c = locate_reg(photo->o3c, photo->no3c, o3c_help);
181
182 /* Interpolate photolysis rate... */
183 double aux00 = LIN(photo->p[ip], rate[ip][isza][io3c],
184 photo->p[ip + 1], rate[ip + 1][isza][io3c], p_help);
185 double aux01 = LIN(photo->p[ip], rate[ip][isza][io3c + 1],
186 photo->p[ip + 1], rate[ip + 1][isza][io3c + 1], p_help);
187 double aux10 = LIN(photo->p[ip], rate[ip][isza + 1][io3c],
188 photo->p[ip + 1], rate[ip + 1][isza + 1][io3c], p_help);
189 double aux11 = LIN(photo->p[ip], rate[ip][isza + 1][io3c + 1],
190 photo->p[ip + 1], rate[ip + 1][isza + 1][io3c + 1],
191 p_help);
192 aux00 = LIN(photo->o3c[io3c], aux00, photo->o3c[io3c + 1], aux01, o3c_help);
193 aux11 = LIN(photo->o3c[io3c], aux10, photo->o3c[io3c + 1], aux11, o3c_help);
194 aux00 = LIN(photo->sza[isza], aux00, photo->sza[isza + 1], aux11, sza_help);
195 return MAX(aux00, 0.0);
196}
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:2030
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:1966
#define LIN(x0, y0, x1, y1, x)
Linear interpolation.
Definition: mptrac.h:859
#define MAX(a, b)
Macro to determine the maximum of two values.
Definition: mptrac.h:886
int nsza
Number of solar zenith angles.
Definition: mptrac.h:3202
double sza[CSZA]
Solar zenith angle [rad].
Definition: mptrac.h:3211
double p[CP]
Pressure [hPa].
Definition: mptrac.h:3208
double o3c[CO3]
Total column ozone [DU].
Definition: mptrac.h:3214
int np
Number of pressure levels.
Definition: mptrac.h:3199
int no3c
Number of total ozone columns.
Definition: mptrac.h:3205
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 200 of file mptrac.c.

203 {
204
205 /* Get seconds since begin of year... */
206 double sec = FMOD(t, 365.25 * 86400.);
207 while (sec < 0)
208 sec += 365.25 * 86400.;
209
210 /* Get indices... */
211 const int isec = locate_irr(clim->tropo_time, clim->tropo_ntime, sec);
212 const int ilat = locate_reg(clim->tropo_lat, clim->tropo_nlat, lat);
213
214 /* Interpolate tropopause pressure... */
215 const double p0 = LIN(clim->tropo_lat[ilat],
216 clim->tropo[isec][ilat],
217 clim->tropo_lat[ilat + 1],
218 clim->tropo[isec][ilat + 1], lat);
219 const double p1 = LIN(clim->tropo_lat[ilat],
220 clim->tropo[isec + 1][ilat],
221 clim->tropo_lat[ilat + 1],
222 clim->tropo[isec + 1][ilat + 1], lat);
223 return LIN(clim->tropo_time[isec], p0, clim->tropo_time[isec + 1], p1, sec);
224}
#define FMOD(x, y)
Calculate the floating-point remainder of dividing x by y.
Definition: mptrac.h:629
int tropo_ntime
Number of tropopause timesteps.
Definition: mptrac.h:3307
double tropo_lat[73]
Tropopause latitudes [deg].
Definition: mptrac.h:3316
int tropo_nlat
Number of tropopause latitudes.
Definition: mptrac.h:3310
double tropo[12][73]
Tropopause pressure values [hPa].
Definition: mptrac.h:3319
double tropo_time[12]
Tropopause time steps [s].
Definition: mptrac.h:3313
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 228 of file mptrac.c.

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

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

385 {
386
387 /* Interpolate... */
388 if (t <= ts->time[0])
389 return ts->vmr[0];
390 else if (t >= ts->time[ts->ntime - 1])
391 return ts->vmr[ts->ntime - 1];
392 else {
393 int idx = locate_irr(ts->time, ts->ntime, t);
394 return LIN(ts->time[idx], ts->vmr[idx],
395 ts->time[idx + 1], ts->vmr[idx + 1], t);
396 }
397}
double vmr[CTS]
Volume mixing ratio [ppv].
Definition: mptrac.h:3261
double time[CTS]
Time [s].
Definition: mptrac.h:3258
int ntime
Number of timesteps.
Definition: mptrac.h:3255
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 401 of file mptrac.c.

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

◆ compress_cms()

void compress_cms ( const ctl_t ctl,
const char *  varname,
float *  array,
const size_t  nx,
const size_t  ny,
const size_t  np,
const 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 ( const char *  varname,
float *  array,
const size_t  nxy,
const size_t  nz,
const 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 657 of file mptrac.c.

663 {
664
665 double min[EP], max[EP], off[EP], scl[EP];
666
667 unsigned short *sarray;
668
669 /* Allocate... */
670 ALLOC(sarray, unsigned short,
671 nxy * nz);
672
673 /* Read compressed stream and decompress array... */
674 if (decompress) {
675
676 /* Write info... */
677 LOG(2, "Read 3-D variable: %s (pck, RATIO= %g)",
678 varname, (double) sizeof(float) / (double) sizeof(unsigned short));
679
680 /* Read data... */
681 FREAD(&scl, double,
682 nz,
683 inout);
684 FREAD(&off, double,
685 nz,
686 inout);
687 FREAD(sarray, unsigned short,
688 nxy * nz,
689 inout);
690
691 /* Convert to float... */
692#pragma omp parallel for default(shared)
693 for (size_t ixy = 0; ixy < nxy; ixy++)
694 for (size_t iz = 0; iz < nz; iz++)
695 array[ixy * nz + iz]
696 = (float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
697 }
698
699 /* Compress array and output compressed stream... */
700 else {
701
702 /* Write info... */
703 LOG(2, "Write 3-D variable: %s (pck, RATIO= %g)",
704 varname, (double) sizeof(float) / (double) sizeof(unsigned short));
705
706 /* Get range... */
707 for (size_t iz = 0; iz < nz; iz++) {
708 min[iz] = array[iz];
709 max[iz] = array[iz];
710 }
711 for (size_t ixy = 1; ixy < nxy; ixy++)
712 for (size_t iz = 0; iz < nz; iz++) {
713 if (array[ixy * nz + iz] < min[iz])
714 min[iz] = array[ixy * nz + iz];
715 if (array[ixy * nz + iz] > max[iz])
716 max[iz] = array[ixy * nz + iz];
717 }
718
719 /* Get offset and scaling factor... */
720 for (size_t iz = 0; iz < nz; iz++) {
721 scl[iz] = (max[iz] - min[iz]) / 65533.;
722 off[iz] = min[iz];
723 }
724
725 /* Convert to short... */
726#pragma omp parallel for default(shared)
727 for (size_t ixy = 0; ixy < nxy; ixy++)
728 for (size_t iz = 0; iz < nz; iz++)
729 if (scl[iz] != 0)
730 sarray[ixy * nz + iz] = (unsigned short)
731 ((array[ixy * nz + iz] - off[iz]) / scl[iz] + .5);
732 else
733 sarray[ixy * nz + iz] = 0;
734
735 /* Write data... */
736 FWRITE(&scl, double,
737 nz,
738 inout);
739 FWRITE(&off, double,
740 nz,
741 inout);
742 FWRITE(sarray, unsigned short,
743 nxy * nz,
744 inout);
745 }
746
747 /* Free... */
748 free(sarray);
749}
#define FWRITE(ptr, type, size, out)
Write data from memory to a file stream.
Definition: mptrac.h:667
#define FREAD(ptr, type, size, in)
Read data from a file stream and store it in memory.
Definition: mptrac.h:647
#define ALLOC(ptr, type, n)
Allocate memory for a pointer with error handling.
Definition: mptrac.h:349
#define EP
Maximum number of pressure levels for meteo data.
Definition: mptrac.h:261

◆ compress_zfp()

void compress_zfp ( const char *  varname,
float *  array,
const int  nx,
const int  ny,
const int  nz,
const int  precision,
const double  tolerance,
const 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 ( const char *  varname,
float *  array,
const size_t  n,
const 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 897 of file mptrac.c.

901 {
902
903 const int
904 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
905 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
906
907 /* Get day of year... */
908 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
909 *doy = d0l[mon - 1] + day - 1;
910 else
911 *doy = d0[mon - 1] + day - 1;
912}

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

920 {
921
922 const int
923 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
924 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
925
926 int i;
927
928 /* Get month and day... */
929 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
930 for (i = 11; i > 0; i--)
931 if (d0l[i] <= doy)
932 break;
933 *mon = i + 1;
934 *day = doy - d0l[i] + 1;
935 } else {
936 for (i = 11; i > 0; i--)
937 if (d0[i] <= doy)
938 break;
939 *mon = i + 1;
940 *day = doy - d0[i] + 1;
941 }
942}

◆ fft_help()

void fft_help ( double *  fcReal,
double *  fcImag,
const 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 946 of file mptrac.c.

949 {
950
951 double data[2 * EX];
952
953 /* Check size... */
954 if (n > EX)
955 ERRMSG("Too many data points!");
956
957 /* Allocate... */
958 gsl_fft_complex_wavetable *wavetable =
959 gsl_fft_complex_wavetable_alloc((size_t) n);
960 gsl_fft_complex_workspace *workspace =
961 gsl_fft_complex_workspace_alloc((size_t) n);
962
963 /* Set data (real, complex)... */
964 for (int i = 0; i < n; i++) {
965 data[2 * i] = fcReal[i];
966 data[2 * i + 1] = fcImag[i];
967 }
968
969 /* Calculate FFT... */
970 gsl_fft_complex_forward(data, 1, (size_t) n, wavetable, workspace);
971
972 /* Copy data... */
973 for (int i = 0; i < n; i++) {
974 fcReal[i] = data[2 * i];
975 fcImag[i] = data[2 * i + 1];
976 }
977
978 /* Free... */
979 gsl_fft_complex_wavetable_free(wavetable);
980 gsl_fft_complex_workspace_free(workspace);
981}
#define EX
Maximum number of longitudes for meteo data.
Definition: mptrac.h:266

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

989 {
990
991 const double radius = z + RE;
992 const double latrad = DEG2RAD(lat);
993 const double lonrad = DEG2RAD(lon);
994 const double coslat = cos(latrad);
995
996 x[0] = radius * coslat * cos(lonrad);
997 x[1] = radius * coslat * sin(lonrad);
998 x[2] = radius * sin(latrad);
999}

◆ get_met_help()

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

Generates a formatted filename for meteorological data files based on the input parameters.

This function determines a rounded time interval, decodes the time components (year, month, day, hour, minute, second), and constructs a filename string for meteorological data files in various formats. The filename is adjusted based on the input control settings.

Parameters
[in]ctlPointer to the control structure containing configuration settings.
[in]tThe time value in seconds since a reference epoch.
[in]directDirection to round the time value. Use -1 for rounding down and 1 for rounding up.
[in]metbaseBase string for the filename, representing the dataset.
[in]dt_metTime interval for rounding in seconds.
[out]filenameOutput buffer to store the generated filename.
Note
The function modifies the provided filename buffer to include placeholders (e.g., YYYY, MM, DD, HH) replaced with the corresponding time values. The format of the filename depends on the values in the control structure (e.g., ctl->met_type).
Warning
Ensure that the filename buffer has sufficient size to accommodate the resulting string.
Author
Lars Hoffmann

Definition at line 1003 of file mptrac.c.

1009 {
1010
1011 char repl[LEN];
1012
1013 double t6, r;
1014
1015 int year, mon, day, hour, min, sec;
1016
1017 /* Round time to fixed intervals... */
1018 if (direct == -1)
1019 t6 = floor(t / dt_met) * dt_met;
1020 else
1021 t6 = ceil(t / dt_met) * dt_met;
1022
1023 /* Decode time... */
1024 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
1025
1026 /* Set filename of MPTRAC meteo files... */
1027 if (ctl->met_clams == 0) {
1028 if (ctl->met_type == 0)
1029 sprintf(filename, "%s_YYYY_MM_DD_HH.nc", metbase);
1030 else if (ctl->met_type == 1)
1031 sprintf(filename, "%s_YYYY_MM_DD_HH.bin", metbase);
1032 else if (ctl->met_type == 2)
1033 sprintf(filename, "%s_YYYY_MM_DD_HH.pck", metbase);
1034 else if (ctl->met_type == 3)
1035 sprintf(filename, "%s_YYYY_MM_DD_HH.zfp", metbase);
1036 else if (ctl->met_type == 4)
1037 sprintf(filename, "%s_YYYY_MM_DD_HH.zstd", metbase);
1038 else if (ctl->met_type == 5)
1039 sprintf(filename, "%s_YYYY_MM_DD_HH.cms", metbase);
1040 sprintf(repl, "%d", year);
1041 get_met_replace(filename, "YYYY", repl);
1042 sprintf(repl, "%02d", mon);
1043 get_met_replace(filename, "MM", repl);
1044 sprintf(repl, "%02d", day);
1045 get_met_replace(filename, "DD", repl);
1046 sprintf(repl, "%02d", hour);
1047 get_met_replace(filename, "HH", repl);
1048 }
1049
1050 /* Set filename of CLaMS meteo files... */
1051 else {
1052 sprintf(filename, "%s_YYMMDDHH.nc", metbase);
1053 sprintf(repl, "%d", year);
1054 get_met_replace(filename, "YYYY", repl);
1055 sprintf(repl, "%02d", year % 100);
1056 get_met_replace(filename, "YY", repl);
1057 sprintf(repl, "%02d", mon);
1058 get_met_replace(filename, "MM", repl);
1059 sprintf(repl, "%02d", day);
1060 get_met_replace(filename, "DD", repl);
1061 sprintf(repl, "%02d", hour);
1062 get_met_replace(filename, "HH", repl);
1063 }
1064}
void get_met_replace(char *orig, char *search, char *repl)
Replaces occurrences of a substring in a string with another substring.
Definition: mptrac.c:1068
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:1683
int met_clams
Read MPTRAC or CLaMS meteo data (0=MPTRAC, 1=CLaMS).
Definition: mptrac.h:2486
int met_type
Type of meteo data files (0=netCDF, 1=binary, 2=pck, 3=zfp, 4=zstd, 5=cms).
Definition: mptrac.h:2483
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 1068 of file mptrac.c.

1071 {
1072
1073 char buffer[LEN];
1074
1075 /* Iterate... */
1076 for (int i = 0; i < 3; i++) {
1077
1078 /* Replace sub-string... */
1079 char *ch;
1080 if (!(ch = strstr(orig, search)))
1081 return;
1082 strncpy(buffer, orig, (size_t) (ch - orig));
1083 buffer[ch - orig] = 0;
1084 sprintf(buffer + (ch - orig), "%s%s", repl, ch + strlen(search));
1085 orig[0] = 0;
1086 strcpy(orig, buffer);
1087 }
1088}

◆ get_tropo()

void get_tropo ( const int  met_tropo,
ctl_t ctl,
clim_t clim,
met_t met,
const double *  lons,
const int  nx,
const double *  lats,
const 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 1092 of file mptrac.c.

1107 {
1108
1110
1111 ctl->met_tropo = met_tropo;
1112 read_met_tropo(ctl, clim, met);
1113#pragma omp parallel for default(shared) private(ci,cw)
1114 for (int ix = 0; ix < nx; ix++)
1115 for (int iy = 0; iy < ny; iy++) {
1116 intpol_met_space_2d(met, met->pt, lons[ix], lats[iy],
1117 &pt[iy * nx + ix], ci, cw, 1);
1118 intpol_met_space_2d(met, met->ps, lons[ix], lats[iy],
1119 &ps[iy * nx + ix], ci, cw, 0);
1120 intpol_met_space_2d(met, met->zs, lons[ix], lats[iy],
1121 &zs[iy * nx + ix], ci, cw, 0);
1122 intpol_met_space_3d(met, met->z, pt[iy * nx + ix], lons[ix],
1123 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
1124 intpol_met_space_3d(met, met->t, pt[iy * nx + ix], lons[ix],
1125 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
1126 intpol_met_space_3d(met, met->h2o, pt[iy * nx + ix], lons[ix],
1127 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
1128 intpol_met_space_3d(met, met->o3, pt[iy * nx + ix], lons[ix],
1129 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
1130 }
1131}
void intpol_met_space_2d(const met_t *met, float array[EX][EY], const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables in 2D space.
Definition: mptrac.c:1442
void read_met_tropo(const ctl_t *ctl, const clim_t *clim, met_t *met)
Calculates the tropopause and related meteorological variables based on various methods and stores th...
Definition: mptrac.c:8573
void intpol_met_space_3d(const met_t *met, float array[EX][EY][EP], const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables in 3D space.
Definition: mptrac.c:1313
#define INTPOL_INIT
Initialize arrays for interpolation.
Definition: mptrac.h:682
int met_tropo
Tropopause definition (0=none, 1=clim, 2=cold point, 3=WMO_1st, 4=WMO_2nd, 5=dynamical).
Definition: mptrac.h:2605
float h2o[EX][EY][EP]
Water vapor volume mixing ratio [1].
Definition: mptrac.h:3483
float ps[EX][EY]
Surface pressure [hPa].
Definition: mptrac.h:3393
float zs[EX][EY]
Surface geopotential height [km].
Definition: mptrac.h:3399
float o3[EX][EY][EP]
Ozone volume mixing ratio [1].
Definition: mptrac.h:3486
float t[EX][EY][EP]
Temperature [K].
Definition: mptrac.h:3468
float pt[EX][EY]
Tropopause pressure [hPa].
Definition: mptrac.h:3426
float z[EX][EY][EP]
Geopotential height [km].
Definition: mptrac.h:3465
Here is the call graph for this function:

◆ intpol_met_4d_coord()

void intpol_met_4d_coord ( const met_t met0,
float  height0[EX][EY][EP],
float  array0[EX][EY][EP],
const met_t met1,
float  height1[EX][EY][EP],
float  array1[EX][EY][EP],
const double  ts,
const double  height,
const double  lon,
const double  lat,
double *  var,
int *  ci,
double *  cw,
const 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 1135 of file mptrac.c.

1149 {
1150
1151 if (init) {
1152
1153 /* Check longitude... */
1154 double lon2 = FMOD(lon, 360.);
1155 if (lon2 < met0->lon[0])
1156 lon2 += 360;
1157 else if (lon2 > met0->lon[met0->nx - 1])
1158 lon2 -= 360;
1159
1160 /* Get horizontal indizes... */
1161 ci[0] = locate_irr(met0->lon, met0->nx, lon2);
1162 ci[1] = locate_irr(met0->lat, met0->ny, lat);
1163
1164 /* Locate the vertical indizes for each edge of the column... */
1165 int ind[2][4];
1166 locate_vert(heights0, met0->npl, ci[0], ci[1], height, ind[0]);
1167 locate_vert(heights1, met1->npl, ci[0], ci[1], height, ind[1]);
1168
1169 /* Find minimum and maximum indizes... */
1170 ci[2] = ind[0][0];
1171 int k_max = ind[0][0];
1172 for (int i = 0; i < 2; i++)
1173 for (int j = 0; j < 4; j++) {
1174 if (ci[2] > ind[i][j])
1175 ci[2] = ind[i][j];
1176 if (k_max < ind[i][j])
1177 k_max = ind[i][j];
1178 }
1179
1180 /* Get weighting factors for time, longitude and latitude... */
1181 cw[3] = (ts - met0->time) / (met1->time - met0->time);
1182 cw[0] = (lon2 - met0->lon[ci[0]]) /
1183 (met0->lon[ci[0] + 1] - met0->lon[ci[0]]);
1184 cw[1] = (lat - met0->lat[ci[1]]) /
1185 (met0->lat[ci[1] + 1] - met0->lat[ci[1]]);
1186
1187 /* Start determiniation of the altitude weighting factor... */
1188 double height_top, height_bot;
1189 double height00, height01, height10, height11, height0, height1;
1190
1191 /* Interpolate in time at the lowest level... */
1192 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
1193 - heights0[ci[0]][ci[1]][ci[2]])
1194 + heights0[ci[0]][ci[1]][ci[2]];
1195 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
1196 - heights0[ci[0]][ci[1] + 1][ci[2]])
1197 + heights0[ci[0]][ci[1] + 1][ci[2]];
1198 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
1199 - heights0[ci[0] + 1][ci[1]][ci[2]])
1200 + heights0[ci[0] + 1][ci[1]][ci[2]];
1201 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
1202 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
1203 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
1204
1205 /* Interpolate in latitude direction... */
1206 height0 = cw[1] * (height01 - height00) + height00;
1207 height1 = cw[1] * (height11 - height10) + height10;
1208
1209 /* Interpolate in longitude direction... */
1210 height_bot = cw[0] * (height1 - height0) + height0;
1211
1212 /* Interpolate in time at the upper level... */
1213 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
1214 - heights0[ci[0]][ci[1]][ci[2] + 1])
1215 + heights0[ci[0]][ci[1]][ci[2] + 1];
1216 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
1217 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
1218 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
1219 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
1220 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
1221 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
1222 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1223 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1224 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1225
1226 /* Interpolate in latitude direction... */
1227 height0 = cw[1] * (height01 - height00) + height00;
1228 height1 = cw[1] * (height11 - height10) + height10;
1229
1230 /* Interpolate in longitude direction... */
1231 height_top = cw[0] * (height1 - height0) + height0;
1232
1233 /* Search at higher levels if height is not in box... */
1234 while (((heights0[0][0][0] > heights0[0][0][1]) &&
1235 ((height_bot <= height) || (height_top > height))
1236 && (height_bot >= height) && (ci[2] < k_max))
1237 ||
1238 ((heights0[0][0][0] < heights0[0][0][1]) &&
1239 ((height_bot >= height) || (height_top < height))
1240 && (height_bot <= height) && (ci[2] < k_max))
1241 ) {
1242
1243 ci[2]++;
1244 height_bot = height_top;
1245
1246 /* Interpolate in time at the next level... */
1247 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
1248 - heights0[ci[0]][ci[1]][ci[2] + 1])
1249 + heights0[ci[0]][ci[1]][ci[2] + 1];
1250 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
1251 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
1252 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
1253 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
1254 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
1255 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
1256 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1257 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1258 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1259
1260 /* Interpolate in latitude direction... */
1261 height0 = cw[1] * (height01 - height00) + height00;
1262 height1 = cw[1] * (height11 - height10) + height10;
1263
1264 /* Interpolate in longitude direction... */
1265 height_top = cw[0] * (height1 - height0) + height0;
1266 }
1267
1268 /* Get vertical weighting factors... */
1269 cw[2] = (height - height_bot)
1270 / (height_top - height_bot);
1271 }
1272
1273 /* Calculate the needed array values... */
1274 double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
1275 - array0[ci[0]][ci[1]][ci[2]])
1276 + array0[ci[0]][ci[1]][ci[2]];
1277 double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
1278 - array0[ci[0] + 1][ci[1]][ci[2]])
1279 + array0[ci[0] + 1][ci[1]][ci[2]];
1280 double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
1281 - array0[ci[0]][ci[1] + 1][ci[2]])
1282 + array0[ci[0]][ci[1] + 1][ci[2]];
1283 double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
1284 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
1285 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
1286 double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
1287 - array0[ci[0]][ci[1]][ci[2] + 1])
1288 + array0[ci[0]][ci[1]][ci[2] + 1];
1289 double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
1290 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
1291 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
1292 double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
1293 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
1294 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
1295 double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1296 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1297 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1298
1299 double array00 = cw[0] * (array100 - array000) + array000;
1300 double array10 = cw[0] * (array110 - array010) + array010;
1301 double array01 = cw[0] * (array101 - array001) + array001;
1302 double array11 = cw[0] * (array111 - array011) + array011;
1303
1304 double aux0 = cw[1] * (array10 - array00) + array00;
1305 double aux1 = cw[1] * (array11 - array01) + array01;
1306
1307 /* Interpolate vertically... */
1308 *var = cw[2] * (aux1 - aux0) + aux0;
1309}
void locate_vert(float profiles[EX][EY][EP], const int np, const int lon_ap_ind, const int lat_ap_ind, const double height_ap, int *ind)
Locate the four vertical indizes of a box for a given height value.
Definition: mptrac.c:2049
int nx
Number of longitudes.
Definition: mptrac.h:3369
int ny
Number of latitudes.
Definition: mptrac.h:3372
double lon[EX]
Longitude [deg].
Definition: mptrac.h:3381
int npl
Number of model levels.
Definition: mptrac.h:3378
double time
Time [s].
Definition: mptrac.h:3366
double lat[EY]
Latitude [deg].
Definition: mptrac.h:3384
Here is the call graph for this function:

◆ intpol_met_space_3d()

void intpol_met_space_3d ( const met_t met,
float  array[EX][EY][EP],
const double  p,
const double  lon,
const double  lat,
double *  var,
int *  ci,
double *  cw,
const 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 1313 of file mptrac.c.

1322 {
1323
1324 /* Initialize interpolation... */
1325 if (init) {
1326
1327 /* Check longitude... */
1328 double lon2 = FMOD(lon, 360.);
1329 if (lon2 < met->lon[0])
1330 lon2 += 360;
1331 else if (lon2 > met->lon[met->nx - 1])
1332 lon2 -= 360;
1333
1334 /* Get interpolation indices... */
1335 ci[0] = locate_irr(met->p, met->np, p);
1336 ci[1] = locate_reg(met->lon, met->nx, lon2);
1337 ci[2] = locate_reg(met->lat, met->ny, lat);
1338
1339 /* Get interpolation weights... */
1340 cw[0] = (met->p[ci[0] + 1] - p)
1341 / (met->p[ci[0] + 1] - met->p[ci[0]]);
1342 cw[1] = (met->lon[ci[1] + 1] - lon2)
1343 / (met->lon[ci[1] + 1] - met->lon[ci[1]]);
1344 cw[2] = (met->lat[ci[2] + 1] - lat)
1345 / (met->lat[ci[2] + 1] - met->lat[ci[2]]);
1346 }
1347
1348 /* Interpolate vertically... */
1349 double aux00 =
1350 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
1351 + array[ci[1]][ci[2]][ci[0] + 1];
1352 double aux01 =
1353 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
1354 array[ci[1]][ci[2] + 1][ci[0] + 1])
1355 + array[ci[1]][ci[2] + 1][ci[0] + 1];
1356 double aux10 =
1357 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
1358 array[ci[1] + 1][ci[2]][ci[0] + 1])
1359 + array[ci[1] + 1][ci[2]][ci[0] + 1];
1360 double aux11 =
1361 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
1362 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
1363 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
1364
1365 /* Interpolate horizontally... */
1366 aux00 = cw[2] * (aux00 - aux01) + aux01;
1367 aux11 = cw[2] * (aux10 - aux11) + aux11;
1368 *var = cw[1] * (aux00 - aux11) + aux11;
1369}
int np
Number of pressure levels.
Definition: mptrac.h:3375
double p[EP]
Pressure levels [hPa].
Definition: mptrac.h:3387
Here is the call graph for this function:

◆ intpol_met_space_3d_ml()

void intpol_met_space_3d_ml ( const met_t met,
float  zs[EX][EY][EP],
float  vals[EX][EY][EP],
const double  z,
const double  lon,
const double  lat,
double *  val 
)

Interpolates meteorological data in 3D space.

This function performs trilinear interpolation to estimate a meteorological variable at a given altitude (z), longitude (lon), and latitude (lat). It uses a structured 3D grid with irregular vertical spacing and regular horizontal spacing.

Parameters
metPointer to the meteorological data structure containing grid information.
zs3D array of altitude levels at each horizontal grid point.
array3D array of meteorological data values corresponding to the grid points.
zTarget altitude for interpolation.
lonTarget longitude for interpolation.
latTarget latitude for interpolation.
varPointer to a variable where the interpolated value will be stored.
Author
Lars Hoffmann

Definition at line 1373 of file mptrac.c.

1380 {
1381
1382 /* Check longitude... */
1383 double lon2 = FMOD(lon, 360.);
1384 if (lon2 < met->lon[0])
1385 lon2 += 360;
1386 else if (lon2 > met->lon[met->nx - 1])
1387 lon2 -= 360;
1388
1389 /* Get horizontal indices... */
1390 int ix = locate_reg(met->lon, met->nx, lon2);
1391 int iy = locate_reg(met->lat, met->ny, lat);
1392
1393 /* Interpolate vertically... */
1394 int iz = locate_irr_float(zs[ix][iy], met->npl, z, 0);
1395 double aux00;
1396 if (z >= zs[ix][iy][iz + 1])
1397 aux00 = array[ix][iy][iz + 1];
1398 else if (z <= zs[ix][iy][iz])
1399 aux00 = array[ix][iy][iz];
1400 else
1401 aux00 = LIN(zs[ix][iy][iz], array[ix][iy][iz],
1402 zs[ix][iy][iz + 1], array[ix][iy][iz + 1], z);
1403
1404 iz = locate_irr_float(zs[ix][iy + 1], met->npl, z, iz);
1405 double aux01;
1406 if (z >= zs[ix][iy + 1][iz + 1])
1407 aux01 = array[ix][iy + 1][iz + 1];
1408 else if (z <= zs[ix][iy + 1][iz])
1409 aux01 = array[ix][iy + 1][iz];
1410 else
1411 aux01 = LIN(zs[ix][iy + 1][iz], array[ix][iy + 1][iz],
1412 zs[ix][iy + 1][iz + 1], array[ix][iy + 1][iz + 1], z);
1413
1414 iz = locate_irr_float(zs[ix + 1][iy], met->npl, z, iz);
1415 double aux10;
1416 if (z >= zs[ix + 1][iy][iz + 1])
1417 aux10 = array[ix + 1][iy][iz + 1];
1418 else if (z <= zs[ix + 1][iy][iz])
1419 aux10 = array[ix + 1][iy][iz];
1420 else
1421 aux10 = LIN(zs[ix + 1][iy][iz], array[ix + 1][iy][iz],
1422 zs[ix + 1][iy][iz + 1], array[ix + 1][iy][iz + 1], z);
1423
1424 iz = locate_irr_float(zs[ix + 1][iy + 1], met->npl, z, iz);
1425 double aux11;
1426 if (z >= zs[ix + 1][iy + 1][iz + 1])
1427 aux11 = array[ix + 1][iy + 1][iz + 1];
1428 else if (z <= zs[ix + 1][iy + 1][iz])
1429 aux11 = array[ix + 1][iy + 1][iz];
1430 else
1431 aux11 = LIN(zs[ix + 1][iy + 1][iz], array[ix + 1][iy + 1][iz],
1432 zs[ix + 1][iy + 1][iz + 1], array[ix + 1][iy + 1][iz + 1], z);
1433
1434 /* Interpolate horizontally... */
1435 double aux0 = LIN(met->lat[iy], aux00, met->lat[iy + 1], aux01, lat);
1436 double aux1 = LIN(met->lat[iy], aux10, met->lat[iy + 1], aux11, lat);
1437 *var = LIN(met->lon[ix], aux0, met->lon[ix + 1], aux1, lon2);
1438}
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:1996
Here is the call graph for this function:

◆ intpol_met_space_2d()

void intpol_met_space_2d ( const met_t met,
float  array[EX][EY],
const double  lon,
const double  lat,
double *  var,
int *  ci,
double *  cw,
const 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 1442 of file mptrac.c.

1450 {
1451
1452 /* Initialize interpolation... */
1453 if (init) {
1454
1455 /* Check longitude... */
1456 double lon2 = FMOD(lon, 360.);
1457 if (lon2 < met->lon[0])
1458 lon2 += 360;
1459 else if (lon2 > met->lon[met->nx - 1])
1460 lon2 -= 360;
1461
1462 /* Get interpolation indices... */
1463 ci[1] = locate_reg(met->lon, met->nx, lon2);
1464 ci[2] = locate_reg(met->lat, met->ny, lat);
1465
1466 /* Get interpolation weights... */
1467 cw[1] = (met->lon[ci[1] + 1] - lon2)
1468 / (met->lon[ci[1] + 1] - met->lon[ci[1]]);
1469 cw[2] = (met->lat[ci[2] + 1] - lat)
1470 / (met->lat[ci[2] + 1] - met->lat[ci[2]]);
1471 }
1472
1473 /* Set variables... */
1474 double aux00 = array[ci[1]][ci[2]];
1475 double aux01 = array[ci[1]][ci[2] + 1];
1476 double aux10 = array[ci[1] + 1][ci[2]];
1477 double aux11 = array[ci[1] + 1][ci[2] + 1];
1478
1479 /* Interpolate horizontally... */
1480 if (isfinite(aux00) && isfinite(aux01)
1481 && isfinite(aux10) && isfinite(aux11)) {
1482 aux00 = cw[2] * (aux00 - aux01) + aux01;
1483 aux11 = cw[2] * (aux10 - aux11) + aux11;
1484 *var = cw[1] * (aux00 - aux11) + aux11;
1485 } else {
1486 if (cw[2] < 0.5) {
1487 if (cw[1] < 0.5)
1488 *var = aux11;
1489 else
1490 *var = aux01;
1491 } else {
1492 if (cw[1] < 0.5)
1493 *var = aux10;
1494 else
1495 *var = aux00;
1496 }
1497 }
1498}
Here is the call graph for this function:

◆ intpol_met_time_3d()

void intpol_met_time_3d ( const met_t met0,
float  array0[EX][EY][EP],
const met_t met1,
float  array1[EX][EY][EP],
const double  ts,
const double  p,
const double  lon,
const double  lat,
double *  var,
int *  ci,
double *  cw,
const 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 1502 of file mptrac.c.

1514 {
1515
1516 double var0, var1;
1517
1518 /* Spatial interpolation... */
1519 intpol_met_space_3d(met0, array0, p, lon, lat, &var0, ci, cw, init);
1520 intpol_met_space_3d(met1, array1, p, lon, lat, &var1, ci, cw, 0);
1521
1522 /* Get weighting factor... */
1523 const double wt = (met1->time - ts) / (met1->time - met0->time);
1524
1525 /* Interpolate... */
1526 *var = wt * (var0 - var1) + var1;
1527}
Here is the call graph for this function:

◆ intpol_met_time_3d_ml()

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

Interpolates meteorological data in both space and time.

This function performs 3D spatial interpolation at two time steps (met0 and met1), then interpolates the results in time to estimate the meteorological variable at a given time (ts), pressure level (p), longitude (lon), and latitude (lat).

Parameters
met0Pointer to the meteorological data structure at the earlier time step.
zs03D array of altitude levels for met0.
array03D array of meteorological data values corresponding to met0.
met1Pointer to the meteorological data structure at the later time step.
zs13D array of altitude levels for met1.
array13D array of meteorological data values corresponding to met1.
tsTarget time for interpolation.
pTarget pressure level for interpolation.
lonTarget longitude for interpolation.
latTarget latitude for interpolation.
varPointer to a variable where the interpolated value will be stored.
Author
Lars Hoffmann

Definition at line 1531 of file mptrac.c.

1542 {
1543
1544 double var0, var1;
1545
1546 /* Spatial interpolation... */
1547 intpol_met_space_3d_ml(met0, zs0, array0, p, lon, lat, &var0);
1548 intpol_met_space_3d_ml(met1, zs1, array1, p, lon, lat, &var1);
1549
1550 /* Interpolate... */
1551 *var = LIN(met0->time, var0, met1->time, var1, ts);
1552}
void intpol_met_space_3d_ml(const met_t *met, float zs[EX][EY][EP], float array[EX][EY][EP], const double z, const double lon, const double lat, double *var)
Interpolates meteorological data in 3D space.
Definition: mptrac.c:1373
Here is the call graph for this function:

◆ intpol_met_time_2d()

void intpol_met_time_2d ( const met_t met0,
float  array0[EX][EY],
const met_t met1,
float  array1[EX][EY],
const double  ts,
const double  lon,
const double  lat,
double *  var,
int *  ci,
double *  cw,
const 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 1556 of file mptrac.c.

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

◆ intpol_tropo_3d()

void intpol_tropo_3d ( const double  time0,
float  array0[EX][EY],
const double  time1,
float  array1[EX][EY],
const double  lons[EX],
const double  lats[EY],
const int  nlon,
const int  nlat,
const double  time,
const double  lon,
const double  lat,
const 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 1589 of file mptrac.c.

1603 {
1604
1605 double aux0, aux1, aux00, aux01, aux10, aux11, mean = 0;
1606
1607 int n = 0;
1608
1609 /* Check longitude... */
1610 double lon2 = FMOD(lon, 360.);
1611 if (lon2 < lons[0])
1612 lon2 += 360;
1613 else if (lon2 > lons[nlon - 1])
1614 lon2 -= 360;
1615
1616 /* Get indices... */
1617 const int ix = locate_reg(lons, (int) nlon, lon2);
1618 const int iy = locate_reg(lats, (int) nlat, lat);
1619
1620 /* Calculate standard deviation... */
1621 *sigma = 0;
1622 for (int dx = 0; dx < 2; dx++)
1623 for (int dy = 0; dy < 2; dy++) {
1624 if (isfinite(array0[ix + dx][iy + dy])) {
1625 mean += array0[ix + dx][iy + dy];
1626 *sigma += SQR(array0[ix + dx][iy + dy]);
1627 n++;
1628 }
1629 if (isfinite(array1[ix + dx][iy + dy])) {
1630 mean += array1[ix + dx][iy + dy];
1631 *sigma += SQR(array1[ix + dx][iy + dy]);
1632 n++;
1633 }
1634 }
1635 if (n > 0)
1636 *sigma = sqrt(MAX(*sigma / n - SQR(mean / n), 0.0));
1637
1638 /* Linear interpolation... */
1639 if (method == 1 && isfinite(array0[ix][iy])
1640 && isfinite(array0[ix][iy + 1])
1641 && isfinite(array0[ix + 1][iy])
1642 && isfinite(array0[ix + 1][iy + 1])
1643 && isfinite(array1[ix][iy])
1644 && isfinite(array1[ix][iy + 1])
1645 && isfinite(array1[ix + 1][iy])
1646 && isfinite(array1[ix + 1][iy + 1])) {
1647
1648 aux00 = LIN(lons[ix], array0[ix][iy],
1649 lons[ix + 1], array0[ix + 1][iy], lon2);
1650 aux01 = LIN(lons[ix], array0[ix][iy + 1],
1651 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
1652 aux0 = LIN(lats[iy], aux00, lats[iy + 1], aux01, lat);
1653
1654 aux10 = LIN(lons[ix], array1[ix][iy],
1655 lons[ix + 1], array1[ix + 1][iy], lon2);
1656 aux11 = LIN(lons[ix], array1[ix][iy + 1],
1657 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
1658 aux1 = LIN(lats[iy], aux10, lats[iy + 1], aux11, lat);
1659
1660 *var = LIN(time0, aux0, time1, aux1, time);
1661 }
1662
1663 /* Nearest neighbor interpolation... */
1664 else {
1665 aux00 = NN(lons[ix], array0[ix][iy],
1666 lons[ix + 1], array0[ix + 1][iy], lon2);
1667 aux01 = NN(lons[ix], array0[ix][iy + 1],
1668 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
1669 aux0 = NN(lats[iy], aux00, lats[iy + 1], aux01, lat);
1670
1671 aux10 = NN(lons[ix], array1[ix][iy],
1672 lons[ix + 1], array1[ix + 1][iy], lon2);
1673 aux11 = NN(lons[ix], array1[ix][iy + 1],
1674 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
1675 aux1 = NN(lats[iy], aux10, lats[iy + 1], aux11, lat);
1676
1677 *var = NN(time0, aux0, time1, aux1, time);
1678 }
1679}
#define NN(x0, y0, x1, y1, x)
Perform nearest-neighbor interpolation.
Definition: mptrac.h:1232
#define SQR(x)
Compute the square of a value.
Definition: mptrac.h:1557
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 1683 of file mptrac.c.

1691 {
1692
1693 struct tm t0, *t1;
1694
1695 t0.tm_year = 100;
1696 t0.tm_mon = 0;
1697 t0.tm_mday = 1;
1698 t0.tm_hour = 0;
1699 t0.tm_min = 0;
1700 t0.tm_sec = 0;
1701
1702 const time_t jsec0 = (time_t) jsec + timegm(&t0);
1703 t1 = gmtime(&jsec0);
1704
1705 *year = t1->tm_year + 1900;
1706 *mon = t1->tm_mon + 1;
1707 *day = t1->tm_mday;
1708 *hour = t1->tm_hour;
1709 *min = t1->tm_min;
1710 *sec = t1->tm_sec;
1711 *remain = jsec - floor(jsec);
1712}

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

1720 {
1721
1722 /* Check number of data points... */
1723 if (nk < 2)
1724 return 1.0;
1725
1726 /* Get altitude... */
1727 const double z = Z(p);
1728
1729 /* Get weighting factor... */
1730 if (z < kz[0])
1731 return kw[0];
1732 else if (z > kz[nk - 1])
1733 return kw[nk - 1];
1734 else {
1735 int idx = locate_irr(kz, nk, z);
1736 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
1737 }
1738}
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 1742 of file mptrac.c.

1744 {
1745
1746 /*
1747 Calculate moist adiabatic lapse rate [K/km] from temperature [K]
1748 and water vapor volume mixing ratio [1].
1749
1750 Reference: https://en.wikipedia.org/wiki/Lapse_rate
1751 */
1752
1753 const double a = RA * SQR(t), r = SH(h2o) / (1. - SH(h2o));
1754
1755 return 1e3 * G0 * (a + LV * r * t) / (CPD * a + SQR(LV) * r * EPS);
1756}
#define SH(h2o)
Compute specific humidity from water vapor volume mixing ratio.
Definition: mptrac.h:1544
#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 1760 of file mptrac.c.

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

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

1969 {
1970
1971 int ilo = 0;
1972 int ihi = n - 1;
1973 int i = (ihi + ilo) >> 1;
1974
1975 if (xx[i] < xx[i + 1])
1976 while (ihi > ilo + 1) {
1977 i = (ihi + ilo) >> 1;
1978 if (xx[i] > x)
1979 ihi = i;
1980 else
1981 ilo = i;
1982 } else
1983 while (ihi > ilo + 1) {
1984 i = (ihi + ilo) >> 1;
1985 if (xx[i] <= x)
1986 ihi = i;
1987 else
1988 ilo = i;
1989 }
1990
1991 return ilo;
1992}

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

2000 {
2001
2002 int ilo = 0;
2003 int ihi = n - 1;
2004 int i = (ihi + ilo) >> 1;
2005
2006 if (x >= xx[ig] && x < xx[ig + 1])
2007 return ig;
2008
2009 if (xx[i] < xx[i + 1])
2010 while (ihi > ilo + 1) {
2011 i = (ihi + ilo) >> 1;
2012 if (xx[i] > x)
2013 ihi = i;
2014 else
2015 ilo = i;
2016 } else
2017 while (ihi > ilo + 1) {
2018 i = (ihi + ilo) >> 1;
2019 if (xx[i] <= x)
2020 ihi = i;
2021 else
2022 ilo = i;
2023 }
2024
2025 return ilo;
2026}

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

2033 {
2034
2035 /* Calculate index... */
2036 int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2037
2038 /* Check range... */
2039 if (i < 0)
2040 return 0;
2041 else if (i > n - 2)
2042 return n - 2;
2043 else
2044 return i;
2045}

◆ locate_vert()

void locate_vert ( float  profiles[EX][EY][EP],
const int  np,
const int  lon_ap_ind,
const int  lat_ap_ind,
const 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 2049 of file mptrac.c.

2055 {
2056
2057 ind[0] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind],
2058 np, height_ap, 0);
2059 ind[1] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind],
2060 np, height_ap, ind[0]);
2061 ind[2] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind + 1],
2062 np, height_ap, ind[1]);
2063 ind[3] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind + 1],
2064 np, height_ap, ind[2]);
2065}
Here is the call graph for this function:

◆ module_advect()

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

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.
cachePointer to the cache structure for temporary data and random numbers.
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_ADVECT" 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 2069 of file mptrac.c.

2074 {
2075
2076 /* Set timer... */
2077 SELECT_TIMER("MODULE_ADVECT", "PHYSICS", NVTX_GPU);
2078
2079 /* Pressure coordinate... */
2080 if (ctl->advect_vert_coord == 0 || ctl->advect_vert_coord == 2) {
2081
2082 /* Loop over particles... */
2083 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2084
2085 /* Init... */
2087 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
2088 x[3] = { 0, 0, 0 };
2089
2090 /* Loop over integration nodes... */
2091 for (int i = 0; i < ctl->advect; i++) {
2092
2093 /* Set position... */
2094 if (i == 0) {
2095 dts = 0.0;
2096 x[0] = atm->lon[ip];
2097 x[1] = atm->lat[ip];
2098 x[2] = atm->p[ip];
2099 } else {
2100 dts = (i == 3 ? 1.0 : 0.5) * cache->dt[ip];
2101 x[0] = atm->lon[ip] + DX2DEG(dts * u[i - 1] / 1000., atm->lat[ip]);
2102 x[1] = atm->lat[ip] + DY2DEG(dts * v[i - 1] / 1000.);
2103 x[2] = atm->p[ip] + dts * w[i - 1];
2104 }
2105 const double tm = atm->time[ip] + dts;
2106
2107 /* Interpolate meteo data on pressure levels... */
2108 if (ctl->advect_vert_coord == 0) {
2109 intpol_met_time_3d(met0, met0->u, met1, met1->u,
2110 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2111 intpol_met_time_3d(met0, met0->v, met1, met1->v,
2112 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2113 intpol_met_time_3d(met0, met0->w, met1, met1->w,
2114 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
2115 }
2116
2117 /* Interpolate meteo data on model levels... */
2118 else {
2119 intpol_met_time_3d_ml(met0, met0->pl, met0->ul,
2120 met1, met1->pl, met1->ul,
2121 tm, x[2], x[0], x[1], &u[i]);
2122 intpol_met_time_3d_ml(met0, met0->pl, met0->vl,
2123 met1, met1->pl, met1->vl,
2124 tm, x[2], x[0], x[1], &v[i]);
2125 intpol_met_time_3d_ml(met0, met0->pl, met0->wl,
2126 met1, met1->pl, met1->wl,
2127 tm, x[2], x[0], x[1], &w[i]);
2128 }
2129
2130 /* Get mean wind... */
2131 double k = 1.0;
2132 if (ctl->advect == 2)
2133 k = (i == 0 ? 0.0 : 1.0);
2134 else if (ctl->advect == 4)
2135 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2136 um += k * u[i];
2137 vm += k * v[i];
2138 wm += k * w[i];
2139 }
2140
2141 /* Set new position... */
2142 atm->time[ip] += cache->dt[ip];
2143 atm->lon[ip] += DX2DEG(cache->dt[ip] * um / 1000.,
2144 (ctl->advect == 2 ? x[1] : atm->lat[ip]));
2145 atm->lat[ip] += DY2DEG(cache->dt[ip] * vm / 1000.);
2146 atm->p[ip] += cache->dt[ip] * wm;
2147 }
2148 }
2149
2150 /* Zeta coordinate... */
2151 else if (ctl->advect_vert_coord == 1) {
2152
2153 /* Loop over particles... */
2154 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2155
2156 /* Convert pressure to zeta... */
2158
2159 // TODO: can we use intpol_met_time_3d_ml instead of intpol_met_4d_coord?
2160
2161 intpol_met_4d_coord(met0, met0->pl, met0->zetal, met1,
2162 met1->pl, met1->zetal, atm->time[ip], atm->p[ip],
2163 atm->lon[ip], atm->lat[ip],
2164 &atm->q[ctl->qnt_zeta][ip], ci, cw, 1);
2165
2166 /* Init... */
2167 double dts, u[4], um = 0, v[4], vm = 0, zeta_dot[4],
2168 zeta_dotm = 0, x[3] = { 0, 0, 0 };
2169
2170 /* Loop over integration nodes... */
2171 for (int i = 0; i < ctl->advect; i++) {
2172
2173 /* Set position... */
2174 if (i == 0) {
2175 dts = 0.0;
2176 x[0] = atm->lon[ip];
2177 x[1] = atm->lat[ip];
2178 x[2] = atm->q[ctl->qnt_zeta][ip];
2179 } else {
2180 dts = (i == 3 ? 1.0 : 0.5) * cache->dt[ip];
2181 x[0] = atm->lon[ip] + DX2DEG(dts * u[i - 1] / 1000., atm->lat[ip]);
2182 x[1] = atm->lat[ip] + DY2DEG(dts * v[i - 1] / 1000.);
2183 x[2] = atm->q[ctl->qnt_zeta][ip] + dts * zeta_dot[i - 1];
2184 }
2185 const double tm = atm->time[ip] + dts;
2186
2187 /* Interpolate meteo data... */
2188 intpol_met_4d_coord(met0, met0->zetal, met0->ul, met1, met1->zetal,
2189 met1->ul, tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2190 intpol_met_4d_coord(met0, met0->zetal, met0->vl, met1, met0->zetal,
2191 met1->vl, tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2192 intpol_met_4d_coord(met0, met0->zetal, met0->zeta_dotl, met1,
2193 met1->zetal, met1->zeta_dotl, tm, x[2], x[0],
2194 x[1], &zeta_dot[i], ci, cw, 0);
2195
2196 /* Get mean wind... */
2197 double k = 1.0;
2198 if (ctl->advect == 2)
2199 k = (i == 0 ? 0.0 : 1.0);
2200 else if (ctl->advect == 4)
2201 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2202 um += k * u[i];
2203 vm += k * v[i];
2204 zeta_dotm += k * zeta_dot[i];
2205 }
2206
2207 /* Set new position... */
2208 atm->time[ip] += cache->dt[ip];
2209 atm->lon[ip] += DX2DEG(cache->dt[ip] * um / 1000.,
2210 (ctl->advect == 2 ? x[1] : atm->lat[ip]));
2211 atm->lat[ip] += DY2DEG(cache->dt[ip] * vm / 1000.);
2212 atm->q[ctl->qnt_zeta][ip] += cache->dt[ip] * zeta_dotm;
2213
2214 /* Check if zeta is below zero... */
2215 if (atm->q[ctl->qnt_zeta][ip] < 0)
2216 atm->q[ctl->qnt_zeta][ip] = 0; /* TODO: reflect particle, or skip this test (use module_position) */
2217
2218 /* Convert zeta to pressure... */
2219 intpol_met_4d_coord(met0, met0->zetal, met0->pl, met1, met1->zetal,
2220 met1->pl, atm->time[ip], atm->q[ctl->qnt_zeta][ip],
2221 atm->lon[ip], atm->lat[ip], &atm->p[ip], ci, cw, 1);
2222 }
2223 }
2224}
void intpol_met_4d_coord(const met_t *met0, float heights0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float heights1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double height, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables to a given position and time.
Definition: mptrac.c:1135
void intpol_met_time_3d(const met_t *met0, float array0[EX][EY][EP], const met_t *met1, float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 3D space and time.
Definition: mptrac.c:1502
void intpol_met_time_3d_ml(const met_t *met0, float zs0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float zs1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var)
Interpolates meteorological data in both space and time.
Definition: mptrac.c:1531
#define PARTICLE_LOOP(ip0, ip1, check_dt,...)
Loop over particle indices with OpenACC acceleration.
Definition: mptrac.h:1274
#define DX2DEG(dx, lat)
Convert a distance in kilometers to degrees longitude at a given latitude.
Definition: mptrac.h:525
#define SELECT_TIMER(id, group, color)
Select and start a timer with specific attributes.
Definition: mptrac.h:1984
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
Definition: mptrac.h:543
double time[NP]
Time [s].
Definition: mptrac.h:3142
double lat[NP]
Latitude [deg].
Definition: mptrac.h:3151
double lon[NP]
Longitude [deg].
Definition: mptrac.h:3148
int np
Number of air parcels.
Definition: mptrac.h:3139
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
Definition: mptrac.h:3154
double p[NP]
Pressure [hPa].
Definition: mptrac.h:3145
double dt[NP]
Timesteps [s].
Definition: mptrac.h:3185
int advect
Advection scheme (0=off, 1=Euler, 2=midpoint, 4=Runge-Kutta).
Definition: mptrac.h:2640
int qnt_zeta
Quantity array index for zeta vertical coordinate.
Definition: mptrac.h:2372
int advect_vert_coord
Vertical coordinate of air parcels (0=pressure, 1=zeta, 2=eta).
Definition: mptrac.h:2643
float zeta_dotl[EX][EY][EP]
Vertical velocity on model levels [K/s].
Definition: mptrac.h:3519
float w[EX][EY][EP]
Vertical velocity [hPa/s].
Definition: mptrac.h:3477
float wl[EX][EY][EP]
Vertical velocity on model levels [hPa/s].
Definition: mptrac.h:3513
float vl[EX][EY][EP]
Meridional wind on model levels [m/s].
Definition: mptrac.h:3510
float u[EX][EY][EP]
Zonal wind [m/s].
Definition: mptrac.h:3471
float ul[EX][EY][EP]
Zonal wind on model levels [m/s].
Definition: mptrac.h:3507
float v[EX][EY][EP]
Meridional wind [m/s].
Definition: mptrac.h:3474
float pl[EX][EY][EP]
Pressure on model levels [hPa].
Definition: mptrac.h:3504
float zetal[EX][EY][EP]
Zeta on model levels [K].
Definition: mptrac.h:3516
Here is the call graph for this function:

◆ module_advect_init()

void module_advect_init ( const ctl_t ctl,
const cache_t cache,
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.
cachePointer to the cache structure for temporary data and random numbers.
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_ADVECT_INIT" 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 2228 of file mptrac.c.

2233 {
2234
2235 /* Check parameters... */
2236 if (ctl->advect_vert_coord != 1)
2237 return;
2238
2239 /* Set timer... */
2240 SELECT_TIMER("MODULE_ADVECT_INIT", "PHYSICS", NVTX_GPU);
2241
2242 /* Loop over particles... */
2243 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,met0,met1,atm)") {
2244
2245 /* Initialize pressure consistent with zeta... */
2247 intpol_met_4d_coord(met0, met0->zetal, met0->pl, met1, met1->zetal,
2248 met1->pl, atm->time[ip], atm->q[ctl->qnt_zeta][ip],
2249 atm->lon[ip], atm->lat[ip], &atm->p[ip], ci, cw, 1);
2250 }
2251}
Here is the call graph for this function:

◆ module_bound_cond()

void module_bound_cond ( const ctl_t ctl,
const cache_t cache,
const clim_t clim,
met_t met0,
met_t met1,
atm_t atm 
)

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.
cachePointer to the cache structure for temporary data and random numbers.
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.
Authors
Lars Hoffmann
Mingzhao Liu

Definition at line 2255 of file mptrac.c.

2261 {
2262
2263 /* Set timer... */
2264 SELECT_TIMER("MODULE_BOUND_COND", "PHYSICS", NVTX_GPU);
2265
2266 /* Check quantity flags... */
2267 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0 && ctl->qnt_Cccl4
2268 && ctl->qnt_Cccl3f < 0 && ctl->qnt_Cccl2f2 < 0
2269 && ctl->qnt_Cn2o < 0 && ctl->qnt_Csf6 < 0 && ctl->qnt_aoa < 0)
2270 return;
2271
2272 /* Loop over particles... */
2273 PARTICLE_LOOP(0, atm->np, 1,
2274 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2275
2276 /* Check latitude and pressure range... */
2277 if (atm->lat[ip] < ctl->bound_lat0 || atm->lat[ip] > ctl->bound_lat1
2278 || atm->p[ip] > ctl->bound_p0 || atm->p[ip] < ctl->bound_p1)
2279 continue;
2280
2281 /* Check surface layer... */
2282 if (ctl->bound_dps > 0 || ctl->bound_dzs > 0
2283 || ctl->bound_zetas > 0 || ctl->bound_pbl) {
2284
2285 /* Get surface pressure... */
2286 double ps;
2288 INTPOL_2D(ps, 1);
2289
2290 /* Check pressure... */
2291 if (ctl->bound_dps > 0 && atm->p[ip] < ps - ctl->bound_dps)
2292 continue;
2293
2294 /* Check height... */
2295 if (ctl->bound_dzs > 0 && Z(atm->p[ip]) > Z(ps) + ctl->bound_dzs)
2296 continue;
2297
2298 /* Check zeta range... */
2299 if (ctl->bound_zetas > 0) {
2300 double t;
2301 INTPOL_3D(t, 1);
2302 if (ZETA(ps, atm->p[ip], t) > ctl->bound_zetas)
2303 continue;
2304 }
2305
2306 /* Check planetary boundary layer... */
2307 if (ctl->bound_pbl) {
2308 double pbl;
2309 INTPOL_2D(pbl, 0);
2310 if (atm->p[ip] < pbl)
2311 continue;
2312 }
2313 }
2314
2315 /* Set mass and volume mixing ratio... */
2316 if (ctl->qnt_m >= 0 && ctl->bound_mass >= 0)
2317 atm->q[ctl->qnt_m][ip] =
2318 ctl->bound_mass + ctl->bound_mass_trend * atm->time[ip];
2319 if (ctl->qnt_vmr >= 0 && ctl->bound_vmr >= 0)
2320 atm->q[ctl->qnt_vmr][ip] =
2321 ctl->bound_vmr + ctl->bound_vmr_trend * atm->time[ip];
2322
2323 /* Set CFC-10 volume mixing ratio... */
2324 if (ctl->qnt_Cccl4 >= 0 && ctl->clim_ccl4_timeseries[0] != '-')
2325 atm->q[ctl->qnt_Cccl4][ip] = clim_ts(&clim->ccl4, atm->time[ip]);
2326
2327 /* Set CFC-11 volume mixing ratio... */
2328 if (ctl->qnt_Cccl3f >= 0 && ctl->clim_ccl3f_timeseries[0] != '-')
2329 atm->q[ctl->qnt_Cccl3f][ip] = clim_ts(&clim->ccl3f, atm->time[ip]);
2330
2331 /* Set CFC-12 volume mixing ratio... */
2332 if (ctl->qnt_Cccl2f2 >= 0 && ctl->clim_ccl2f2_timeseries[0] != '-')
2333 atm->q[ctl->qnt_Cccl2f2][ip] = clim_ts(&clim->ccl2f2, atm->time[ip]);
2334
2335 /* Set N2O volume mixing ratio... */
2336 if (ctl->qnt_Cn2o >= 0 && ctl->clim_n2o_timeseries[0] != '-')
2337 atm->q[ctl->qnt_Cn2o][ip] = clim_ts(&clim->n2o, atm->time[ip]);
2338
2339 /* Set SF6 volume mixing ratio... */
2340 if (ctl->qnt_Csf6 >= 0 && ctl->clim_sf6_timeseries[0] != '-')
2341 atm->q[ctl->qnt_Csf6][ip] = clim_ts(&clim->sf6, atm->time[ip]);
2342
2343 /* Set age of air... */
2344 if (ctl->qnt_aoa >= 0)
2345 atm->q[ctl->qnt_aoa][ip] = atm->time[ip];
2346 }
2347}
double clim_ts(const clim_ts_t *ts, const double t)
Interpolates a time series of climatological variables.
Definition: mptrac.c:383
#define INTPOL_3D(var, init)
Perform 3D interpolation for a meteorological variable.
Definition: mptrac.h:713
#define ZETA(ps, p, t)
Computes the value of the zeta vertical coordinate.
Definition: mptrac.h:1791
#define INTPOL_2D(var, init)
Perform 2D interpolation for a meteorological variable.
Definition: mptrac.h:696
clim_ts_t ccl2f2
CFC-12 time series.
Definition: mptrac.h:3346
clim_ts_t sf6
SF6 time series.
Definition: mptrac.h:3352
clim_ts_t ccl4
CFC-10 time series.
Definition: mptrac.h:3340
clim_ts_t ccl3f
CFC-11 time series.
Definition: mptrac.h:3343
clim_ts_t n2o
N2O time series.
Definition: mptrac.h:3349
int qnt_Cccl2f2
Quantity array index for CFC-12 volume mixing ratio (chemistry code).
Definition: mptrac.h:2441
int qnt_m
Quantity array index for mass.
Definition: mptrac.h:2189
int qnt_aoa
Quantity array index for age of air.
Definition: mptrac.h:2450
char clim_n2o_timeseries[LEN]
Filename of N2O time series.
Definition: mptrac.h:2769
double bound_dzs
Boundary conditions surface layer depth [km].
Definition: mptrac.h:2718
int qnt_Cccl4
Quantity array index for CFC-10 volume mixing ratio (chemistry code).
Definition: mptrac.h:2435
double bound_mass
Boundary conditions mass per particle [kg].
Definition: mptrac.h:2691
int qnt_vmr
Quantity array index for volume mixing ratio.
Definition: mptrac.h:2192
double bound_lat1
Boundary conditions maximum longitude [deg].
Definition: mptrac.h:2706
int bound_pbl
Boundary conditions planetary boundary layer (0=no, 1=yes).
Definition: mptrac.h:2724
double bound_p1
Boundary conditions top pressure [hPa].
Definition: mptrac.h:2712
double bound_vmr
Boundary conditions volume mixing ratio [ppv].
Definition: mptrac.h:2697
double bound_lat0
Boundary conditions minimum longitude [deg].
Definition: mptrac.h:2703
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
Definition: mptrac.h:2700
int qnt_Cn2o
Quantity array index for N2O volume mixing ratio (chemistry code).
Definition: mptrac.h:2444
int qnt_Cccl3f
Quantity array index for CFC-11 volume mixing ratio (chemistry code).
Definition: mptrac.h:2438
int qnt_Csf6
Quantity array index for SF6 volume mixing ratio (chemistry code).
Definition: mptrac.h:2447
double bound_dps
Boundary conditions surface layer depth [hPa].
Definition: mptrac.h:2715
double bound_mass_trend
Boundary conditions mass per particle trend [kg/s].
Definition: mptrac.h:2694
double bound_p0
Boundary conditions bottom pressure [hPa].
Definition: mptrac.h:2709
char clim_ccl4_timeseries[LEN]
Filename of CFC-10 time series.
Definition: mptrac.h:2760
char clim_sf6_timeseries[LEN]
Filename of SF6 time series.
Definition: mptrac.h:2772
char clim_ccl3f_timeseries[LEN]
Filename of CFC-11 time series.
Definition: mptrac.h:2763
char clim_ccl2f2_timeseries[LEN]
Filename of CFC-12 time series.
Definition: mptrac.h:2766
double bound_zetas
Boundary conditions surface layer zeta [K].
Definition: mptrac.h:2721
Here is the call graph for this function:

◆ module_chem_grid()

void module_chem_grid ( const ctl_t ctl,
met_t met0,
met_t met1,
atm_t atm,
const 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 2351 of file mptrac.c.

2356 {
2357
2358 /* Check quantities... */
2359 if (ctl->qnt_m < 0 || ctl->qnt_Cx < 0)
2360 return;
2361 if (ctl->molmass <= 0)
2362 ERRMSG("Molar mass is not defined!");
2363
2364 /* Set timer... */
2365 SELECT_TIMER("MODULE_CHEM_GRID", "PHYSICS", NVTX_GPU);
2366
2367 /* Allocate... */
2368 const int np = atm->np;
2369 const int nz = ctl->chemgrid_nz;
2370 const int nx = ctl->chemgrid_nx;
2371 const int ny = ctl->chemgrid_ny;
2372 const int ngrid = nx * ny * nz;
2373
2374 double *restrict const z = (double *) malloc((size_t) nz * sizeof(double));
2375 double *restrict const press =
2376 (double *) malloc((size_t) nz * sizeof(double));
2377 double *restrict const mass =
2378 (double *) calloc((size_t) ngrid, sizeof(double));
2379 double *restrict const area =
2380 (double *) malloc((size_t) ny * sizeof(double));
2381 double *restrict const lon =
2382 (double *) malloc((size_t) nx * sizeof(double));
2383 double *restrict const lat =
2384 (double *) malloc((size_t) ny * sizeof(double));
2385
2386 int *restrict const ixs = (int *) malloc((size_t) np * sizeof(int));
2387 int *restrict const iys = (int *) malloc((size_t) np * sizeof(int));
2388 int *restrict const izs = (int *) malloc((size_t) np * sizeof(int));
2389
2390 /* Set grid box size... */
2391 const double dz = (ctl->chemgrid_z1 - ctl->chemgrid_z0) / nz;
2392 const double dlon = (ctl->chemgrid_lon1 - ctl->chemgrid_lon0) / nx;
2393 const double dlat = (ctl->chemgrid_lat1 - ctl->chemgrid_lat0) / ny;
2394
2395 /* Set vertical coordinates... */
2396#ifdef _OPENACC
2397#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])
2398#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
2399#pragma acc parallel loop independent gang vector
2400#else
2401#pragma omp parallel for default(shared)
2402#endif
2403 for (int iz = 0; iz < nz; iz++) {
2404 z[iz] = ctl->chemgrid_z0 + dz * (iz + 0.5);
2405 press[iz] = P(z[iz]);
2406 }
2407
2408 /* Set time interval for output... */
2409 const double t0 = tt - 0.5 * ctl->dt_mod;
2410 const double t1 = tt + 0.5 * ctl->dt_mod;
2411
2412 /* Get indices... */
2413#ifdef _OPENACC
2414#pragma acc parallel loop independent gang vector
2415#else
2416#pragma omp parallel for default(shared)
2417#endif
2418 for (int ip = 0; ip < np; ip++) {
2419 ixs[ip] = (int) ((atm->lon[ip] - ctl->chemgrid_lon0) / dlon);
2420 iys[ip] = (int) ((atm->lat[ip] - ctl->chemgrid_lat0) / dlat);
2421 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->chemgrid_z0) / dz);
2422 if (atm->time[ip] < t0 || atm->time[ip] > t1
2423 || ixs[ip] < 0 || ixs[ip] >= nx
2424 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
2425 izs[ip] = -1;
2426 }
2427
2428 /* Set horizontal coordinates... */
2429#ifdef _OPENACC
2430#pragma acc parallel loop independent gang vector
2431#else
2432#pragma omp parallel for default(shared)
2433#endif
2434 for (int ix = 0; ix < nx; ix++)
2435 lon[ix] = ctl->chemgrid_lon0 + dlon * (ix + 0.5);
2436#ifdef _OPENACC
2437#pragma acc parallel loop independent gang vector
2438#else
2439#pragma omp parallel for default(shared)
2440#endif
2441 for (int iy = 0; iy < ny; iy++) {
2442 lat[iy] = ctl->chemgrid_lat0 + dlat * (iy + 0.5);
2443 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
2444 }
2445
2446 /* Get mass per grid box... */
2447#ifdef _OPENACC
2448#pragma acc parallel loop independent gang vector
2449#endif
2450 for (int ip = 0; ip < np; ip++)
2451 if (izs[ip] >= 0)
2452#ifdef _OPENACC
2453#pragma acc atomic update
2454#endif
2455 mass[ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz)]
2456 += atm->q[ctl->qnt_m][ip];
2457
2458 /* Assign grid data to air parcels ... */
2459#ifdef _OPENACC
2460#pragma acc parallel loop independent gang vector
2461#else
2462#pragma omp parallel for default(shared)
2463#endif
2464 for (int ip = 0; ip < np; ip++)
2465 if (izs[ip] >= 0) {
2466
2467 /* Interpolate temperature... */
2468 double temp;
2470 intpol_met_time_3d(met0, met0->t, met1, met1->t, tt, press[izs[ip]],
2471 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
2472
2473 /* Set mass... */
2474 const double m = mass[ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz)];
2475
2476 /* Calculate volume mixing ratio... */
2477 atm->q[ctl->qnt_Cx][ip] = MA / ctl->molmass * m
2478 / (RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
2479 }
2480#ifdef _OPENACC
2481#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
2482#endif
2483
2484 /* Free... */
2485 free(mass);
2486 free(lon);
2487 free(lat);
2488 free(area);
2489 free(z);
2490 free(press);
2491 free(ixs);
2492 free(iys);
2493 free(izs);
2494}
#define ARRAY_3D(ix, iy, ny, iz, nz)
Compute the linear index of a 3D array element.
Definition: mptrac.h:391
#define P(z)
Compute pressure at given altitude.
Definition: mptrac.h:1304
#define RHO(p, t)
Compute density of air.
Definition: mptrac.h:1481
double molmass
Molar mass [g/mol].
Definition: mptrac.h:2730
double chemgrid_z1
Upper altitude of chemistry grid [km].
Definition: mptrac.h:2817
double chemgrid_z0
Lower altitude of chemistry grid [km].
Definition: mptrac.h:2814
double chemgrid_lat0
Lower latitude of chemistry grid [deg].
Definition: mptrac.h:2832
double chemgrid_lat1
Upper latitude of chemistry grid [deg].
Definition: mptrac.h:2835
double chemgrid_lon0
Lower longitude of chemistry grid [deg].
Definition: mptrac.h:2823
double chemgrid_lon1
Upper longitude of chemistry grid [deg].
Definition: mptrac.h:2826
double dt_mod
Time step of simulation [s].
Definition: mptrac.h:2462
int chemgrid_nz
Number of altitudes of chemistry grid.
Definition: mptrac.h:2811
int chemgrid_nx
Number of longitudes of chemistry grid.
Definition: mptrac.h:2820
int chemgrid_ny
Number of latitudes of chemistry grid.
Definition: mptrac.h:2829
int qnt_Cx
Quantity array index for trace species x volume mixing ratio (chemistry code).
Definition: mptrac.h:2405
Here is the call graph for this function:

◆ module_chem_init()

void module_chem_init ( const ctl_t ctl,
const cache_t cache,
const 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 2498 of file mptrac.c.

2504 {
2505
2506 /* Set timer... */
2507 SELECT_TIMER("MODULE_CHEM_INIT", "PHYSICS", NVTX_GPU);
2508
2509 /* Loop over particles... */
2510 PARTICLE_LOOP(0, atm->np, 0,
2511 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2512
2513 /* Set H2O and O3 using meteo data... */
2515 if (ctl->qnt_Ch2o >= 0) {
2516 double h2o;
2517 INTPOL_3D(h2o, 1);
2518 SET_ATM(qnt_Ch2o, h2o);
2519 }
2520 if (ctl->qnt_Co3 >= 0) {
2521 double o3;
2522 INTPOL_3D(o3, 1);
2523 SET_ATM(qnt_Co3, o3);
2524 }
2525
2526 /* Set radical species... */
2527 SET_ATM(qnt_Coh, clim_oh(ctl, clim, atm->time[ip],
2528 atm->lon[ip], atm->lat[ip], atm->p[ip]));
2529 SET_ATM(qnt_Cho2, clim_zm(&clim->ho2, atm->time[ip],
2530 atm->lat[ip], atm->p[ip]));
2531 SET_ATM(qnt_Ch2o2, clim_zm(&clim->h2o2, atm->time[ip],
2532 atm->lat[ip], atm->p[ip]));
2533 SET_ATM(qnt_Co1d, clim_zm(&clim->o1d, atm->time[ip],
2534 atm->lat[ip], atm->p[ip]));
2535 }
2536}
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:89
#define SET_ATM(qnt, val)
Set atmospheric quantity value.
Definition: mptrac.h:1500
clim_zm_t ho2
HO2 zonal means.
Definition: mptrac.h:3334
clim_zm_t o1d
O(1D) zonal means.
Definition: mptrac.h:3337
clim_zm_t h2o2
H2O2 zonal means.
Definition: mptrac.h:3331
int qnt_Ch2o
Quantity array index for H2O volume mixing ratio (chemistry code).
Definition: mptrac.h:2408
int qnt_Co3
Quantity array index for O3 volume mixing ratio (chemistry code).
Definition: mptrac.h:2411
Here is the call graph for this function:

◆ module_convection()

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

Performs convective mixing of atmospheric particles.

This function adjusts the pressure of atmospheric particles based on boundary layer (PBL) mixing and convective conditions driven by CAPE (Convective Available Potential Energy) and CIN (Convective Inhibition). It uses meteorological data and random numbers for vertical mixing calculations.

Parameters
[in]ctlPointer to the control structure with simulation settings.
[in,out]cachePointer to the cache structure for temporary data and random numbers.
[in,out]met0Pointer to the meteorological data at the initial timestep.
[in,out]met1Pointer to the meteorological data at the subsequent timestep.
[in,out]atmPointer to the atmospheric data structure with particle properties.
Note
  • This function modifies the atm structure in place.
  • Interpolates CAPE, CIN, and other meteorological parameters.
  • Determines the pressure range for PBL and convective mixing.
  • Updates the pressure of particles based on calculated mixing.
Author
Lars Hoffmann

Definition at line 2540 of file mptrac.c.

2545 {
2546
2547 /* Set timer... */
2548 SELECT_TIMER("MODULE_CONVECTION", "PHYSICS", NVTX_GPU);
2549
2550 /* Create random numbers... */
2551 module_rng(ctl, cache->rs, (size_t) atm->np, 0);
2552
2553 /* Loop over particles... */
2554 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2555
2556 /* Interpolate CAPE... */
2557 double ps;
2559 INTPOL_2D(ps, 1);
2560
2561 /* Initialize pressure range for vertical mixing... */
2562 double pbot = ps, ptop = ps;
2563
2564 /* Mixing in the PBL... */
2565 if (ctl->conv_mix_pbl) {
2566
2567 /* Interpolate PBL... */
2568 double pbl;
2569 INTPOL_2D(pbl, 0);
2570
2571 /* Set pressure range... */
2572 ptop = pbl - ctl->conv_pbl_trans * (ps - pbl);
2573 }
2574
2575 /* Convective mixing... */
2576 if (ctl->conv_cape >= 0) {
2577
2578 /* Interpolate CAPE, CIN, and equilibrium level... */
2579 double cape, cin, pel;
2580 INTPOL_2D(cape, 0);
2581 INTPOL_2D(cin, 0);
2582 INTPOL_2D(pel, 0);
2583
2584 /* Set pressure range... */
2585 if (isfinite(cape) && cape >= ctl->conv_cape
2586 && (ctl->conv_cin <= 0 || (isfinite(cin) && cin >= ctl->conv_cin)))
2587 ptop = GSL_MIN(ptop, pel);
2588 }
2589
2590 /* Apply vertical mixing... */
2591 if (ptop != pbot && atm->p[ip] >= ptop) {
2592
2593 /* Get density range... */
2594 double tbot, ttop;
2595 intpol_met_time_3d(met0, met0->t, met1, met1->t, atm->time[ip],
2596 pbot, atm->lon[ip], atm->lat[ip], &tbot, ci, cw, 1);
2597 intpol_met_time_3d(met0, met0->t, met1, met1->t, atm->time[ip],
2598 ptop, atm->lon[ip], atm->lat[ip], &ttop, ci, cw, 1);
2599 const double rhobot = pbot / tbot;
2600 const double rhotop = ptop / ttop;
2601
2602 /* Get new density... */
2603 const double rho = rhobot + (rhotop - rhobot) * cache->rs[ip];
2604
2605 /* Get pressure... */
2606 atm->p[ip] = LIN(rhobot, pbot, rhotop, ptop, rho);
2607 }
2608 }
2609}
void module_rng(const ctl_t *ctl, double *rs, const size_t n, const int method)
Generate random numbers using various methods and distributions.
Definition: mptrac.c:3684
double rs[3 *NP+1]
Random numbers.
Definition: mptrac.h:3182
double conv_cape
CAPE threshold for convection module [J/kg].
Definition: mptrac.h:2682
double conv_pbl_trans
Depth of PBL transition layer (fraction of PBL depth).
Definition: mptrac.h:2679
int conv_mix_pbl
Vertical mixing in the PBL (0=off, 1=on).
Definition: mptrac.h:2676
double conv_cin
CIN threshold for convection module [J/kg].
Definition: mptrac.h:2685
Here is the call graph for this function:

◆ module_decay()

void module_decay ( const ctl_t ctl,
const cache_t cache,
const clim_t clim,
atm_t atm 
)

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.
cachePointer to the cache structure for temporary data and random numbers.
climPointer to the climate data structure containing atmospheric data.
atmPointer to the atmospheric data structure containing particle information.
Author
Lars Hoffmann

Definition at line 2613 of file mptrac.c.

2617 {
2618
2619 /* Set timer... */
2620 SELECT_TIMER("MODULE_DECAY", "PHYSICS", NVTX_GPU);
2621
2622 /* Check quantity flags... */
2623 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
2624 ERRMSG("Module needs quantity mass or volume mixing ratio!");
2625
2626 /* Loop over particles... */
2627 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,clim,atm)") {
2628
2629 /* Get weighting factor... */
2630 const double w = tropo_weight(clim, atm, ip);
2631
2632 /* Set lifetime... */
2633 const double tdec = w * ctl->tdec_trop + (1 - w) * ctl->tdec_strat;
2634
2635 /* Calculate exponential decay... */
2636 const double aux = exp(-cache->dt[ip] / tdec);
2637 if (ctl->qnt_m >= 0) {
2638 if (ctl->qnt_mloss_decay >= 0)
2639 atm->q[ctl->qnt_mloss_decay][ip]
2640 += atm->q[ctl->qnt_m][ip] * (1 - aux);
2641 atm->q[ctl->qnt_m][ip] *= aux;
2642 if (ctl->qnt_loss_rate >= 0)
2643 atm->q[ctl->qnt_loss_rate][ip] += 1. / tdec;
2644 }
2645 if (ctl->qnt_vmr >= 0)
2646 atm->q[ctl->qnt_vmr][ip] *= aux;
2647 }
2648}
double tropo_weight(const clim_t *clim, const atm_t *atm, const int ip)
Computes a weighting factor based on tropopause pressure.
Definition: mptrac.c:9194
int qnt_loss_rate
Quantity array index for total loss rate.
Definition: mptrac.h:2348
int qnt_mloss_decay
Quantity array index for total mass loss due to exponential decay.
Definition: mptrac.h:2345
double tdec_strat
Life time of particles in the stratosphere [s].
Definition: mptrac.h:2736
double tdec_trop
Life time of particles in the troposphere [s].
Definition: mptrac.h:2733
Here is the call graph for this function:

◆ module_diff_meso()

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

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.
cachePointer to the cache structure for temporary data and random numbers.
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.
Note
Control parameters TURB_MESOX and TURB_MESOZ define the subgrid-scale variability as a fraction of the grid-scale variance. Stohl et al. (2005) recommend a default value of 0.16 for both parameters, providing a standard approach for turbulence representation. However, recent findings by Bakels et al. (2024) suggest disabling this approach to improve model accuracy under certain conditions. It is advised to evaluate the applicability of these recommendations based on the specific simulation context and objectives.
Author
Lars Hoffmann

Definition at line 2652 of file mptrac.c.

2657 {
2658
2659 /* Set timer... */
2660 SELECT_TIMER("MODULE_DIFF_MESO", "PHYSICS", NVTX_GPU);
2661
2662 /* Create random numbers... */
2663 module_rng(ctl, cache->rs, 3 * (size_t) atm->np, 1);
2664
2665 /* Loop over particles... */
2666 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2667
2668 /* Get indices... */
2669 const int ix = locate_reg(met0->lon, met0->nx, atm->lon[ip]);
2670 const int iy = locate_reg(met0->lat, met0->ny, atm->lat[ip]);
2671 const int iz = locate_irr(met0->p, met0->np, atm->p[ip]);
2672
2673 /* Get standard deviations of local wind data... */
2674 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
2675 for (int i = 0; i < 2; i++)
2676 for (int j = 0; j < 2; j++)
2677 for (int k = 0; k < 2; k++) {
2678 umean += met0->u[ix + i][iy + j][iz + k];
2679 usig += SQR(met0->u[ix + i][iy + j][iz + k]);
2680 vmean += met0->v[ix + i][iy + j][iz + k];
2681 vsig += SQR(met0->v[ix + i][iy + j][iz + k]);
2682 wmean += met0->w[ix + i][iy + j][iz + k];
2683 wsig += SQR(met0->w[ix + i][iy + j][iz + k]);
2684
2685 umean += met1->u[ix + i][iy + j][iz + k];
2686 usig += SQR(met1->u[ix + i][iy + j][iz + k]);
2687 vmean += met1->v[ix + i][iy + j][iz + k];
2688 vsig += SQR(met1->v[ix + i][iy + j][iz + k]);
2689 wmean += met1->w[ix + i][iy + j][iz + k];
2690 wsig += SQR(met1->w[ix + i][iy + j][iz + k]);
2691 }
2692 usig = usig / 16.f - SQR(umean / 16.f);
2693 usig = (usig > 0 ? sqrtf(usig) : 0);
2694 vsig = vsig / 16.f - SQR(vmean / 16.f);
2695 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
2696 wsig = wsig / 16.f - SQR(wmean / 16.f);
2697 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
2698
2699 /* Set temporal correlations for mesoscale fluctuations... */
2700 const double r = 1 - 2 * fabs(cache->dt[ip]) / ctl->dt_met;
2701 const double r2 = sqrt(1 - r * r);
2702
2703 /* Calculate horizontal mesoscale wind fluctuations... */
2704 if (ctl->turb_mesox > 0) {
2705 cache->uvwp[ip][0] =
2706 (float) (r * cache->uvwp[ip][0] +
2707 r2 * cache->rs[3 * ip] * ctl->turb_mesox * usig);
2708 atm->lon[ip] +=
2709 DX2DEG(cache->uvwp[ip][0] * cache->dt[ip] / 1000., atm->lat[ip]);
2710
2711 cache->uvwp[ip][1] =
2712 (float) (r * cache->uvwp[ip][1] +
2713 r2 * cache->rs[3 * ip + 1] * ctl->turb_mesox * vsig);
2714 atm->lat[ip] += DY2DEG(cache->uvwp[ip][1] * cache->dt[ip] / 1000.);
2715 }
2716
2717 /* Calculate vertical mesoscale wind fluctuations... */
2718 if (ctl->turb_mesoz > 0) {
2719 cache->uvwp[ip][2] =
2720 (float) (r * cache->uvwp[ip][2] +
2721 r2 * cache->rs[3 * ip + 2] * ctl->turb_mesoz * wsig);
2722 atm->p[ip] += cache->uvwp[ip][2] * cache->dt[ip];
2723 }
2724 }
2725}
float uvwp[NP][3]
Wind perturbations [m/s].
Definition: mptrac.h:3179
double turb_mesoz
Vertical scaling factor for mesoscale wind fluctuations.
Definition: mptrac.h:2673
double dt_met
Time step of meteo data [s].
Definition: mptrac.h:2472
double turb_mesox
Horizontal scaling factor for mesoscale wind fluctuations.
Definition: mptrac.h:2670
Here is the call graph for this function:

◆ module_diff_pbl()

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

Computes particle diffusion within the planetary boundary layer (PBL).

This function handles the effects of turbulence on particles within the PBL. It calculates turbulent velocity variances, Lagrangian timescales, and updates particle positions and perturbations based on random fluctuations and boundary layer physics. This module adapts the approach of Ryall and Maryon (1998) and Stohl et al. (2005).

Parameters
ctlPointer to the control structure containing model settings.
cachePointer to the cache structure for temporary data and random numbers.
met0Pointer to the meteorological data structure for the current timestep.
met1Pointer to the meteorological data structure for the next timestep.
atmPointer to the atmospheric data structure containing particle states.

The function:

  • Allocates memory for random numbers and generates them using module_rng.
  • Loops over all particles to compute their behavior within the boundary layer.
  • Handles both stable/neutral and unstable conditions based on the surface sensible heat flux.
  • Calculates turbulent velocity variances (sig_u, sig_w), their vertical derivatives, and Lagrangian timescales (tau_u, tau_w).
  • Updates particle velocity perturbations and positions using turbulent diffusion equations.

The function uses OpenACC directives for GPU acceleration.

Note
The function handles edge cases like zero diffusivity and imposes minimum limits on calculated values to ensure stability.
Warning
Ensure that all input pointers are properly initialized and accessible before calling this function.
Author
Lars Hoffmann

Definition at line 2729 of file mptrac.c.

2734 {
2735
2736 /* Set timer... */
2737 SELECT_TIMER("MODULE_DIFF_PBL", "PHYSICS", NVTX_GPU);
2738
2739 /* Create random numbers... */
2740 module_rng(ctl, cache->rs, 3 * (size_t) atm->np, 1);
2741
2742 /* Loop over particles... */
2743 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2744
2745 double dsigw_dz = 0.0, sig_u = 0.25, sig_w = 0.1,
2746 tau_u = 300., tau_w = 100.;
2747
2748 /* Get surface and PBL pressure... */
2749 double pbl, ps;
2751 INTPOL_2D(ps, 1);
2752 INTPOL_2D(pbl, 0);
2753
2754 /* Boundary layer... */
2755 if (atm->p[ip] >= pbl) {
2756
2757 /* Calculate heights... */
2758 const double p = MIN(atm->p[ip], ps);
2759 const double zs = Z(ps);
2760 const double z = 1e3 * (Z(p) - zs);
2761 const double zi = 1e3 * (Z(pbl) - zs);
2762 const double zratio = z / zi;
2763
2764 /* Calculate friction velocity... */
2765 double ess, nss, h2o, t;
2766 INTPOL_2D(ess, 0);
2767 INTPOL_2D(nss, 0);
2768 INTPOL_3D(t, 1);
2769 INTPOL_3D(h2o, 0);
2770 const double rho = RHO(p, TVIRT(t, h2o));
2771 const double tau = sqrt(SQR(ess) + SQR(nss));
2772 const double ustar = sqrt(tau / rho);
2773
2774 /* Get surface sensible heat flux... */
2775 double shf;
2776 INTPOL_2D(shf, 1);
2777
2778 /* Stable or neutral conditions... */
2779 if (shf <= 0) {
2780
2781 /* Calcalute turbulent velocity variances... */
2782 sig_u = 1e-2 + 2.0 * ustar * (1.0 - zratio);
2783 sig_w = 1e-2 + 1.3 * ustar * (1.0 - zratio);
2784
2785 /* Calculate derivative dsig_w/dz... */
2786 dsigw_dz = -1.3 * ustar / zi;
2787
2788 /* Calcalute Lagrangian timescales... */
2789 tau_u = 0.07 * zi / sig_u * sqrt(zratio);
2790 tau_w = 0.1 * zi / sig_w * pow(zratio, 0.8);
2791 }
2792
2793 /* Unstable conditions... */
2794 else {
2795
2796 /* Convective velocity... */
2797 const double wstar =
2798 pow(G0 / THETAVIRT(p, t, h2o) * shf / (rho * CPD) * zi, 1. / 3.);
2799
2800 /* Calcalute turbulent velocity variances... */
2801 sig_u = 1e-2
2802 + sqrt(0.4 * SQR(wstar) + (5.0 - 4.0 * zratio) * SQR(ustar));
2803 sig_w = 1e-2 + sqrt(1.2 * SQR(wstar) * (1.0 - 0.9 * zratio)
2804 * pow(zratio, 2.0 / 3.0)
2805 + (1.8 - 1.4 * zratio) * SQR(ustar));
2806
2807 /* Calculate derivative dsig_w/dz... */
2808 dsigw_dz = 0.5 / sig_w / zi * (-1.4 * SQR(ustar) + SQR(wstar)
2809 * (0.8 *
2810 pow(MAX(zratio, 1e-3), -1.0 / 3.0)
2811 - 1.8 * pow(zratio, 2.0 / 3.0)));
2812
2813 /* Calcalute Lagrangian timescales... */
2814 const double C0 = 3.0; // TODO: typically 3...6, NAME model uses 3?
2815 const double eps =
2816 (1.5 - 1.2 * pow(zratio, 1.0 / 3.0)) * SQR(wstar) * wstar / zi
2817 + SQR(ustar) * ustar * (1.0 - 0.8 * zratio) / (KARMAN * z);
2818 tau_u = 2 * SQR(sig_u) / (C0 * eps);
2819 tau_w = 2 * SQR(sig_w) / (C0 * eps);
2820 }
2821 }
2822
2823 /* Set minimum values... */
2824 sig_u = MAX(sig_u, 0.25);
2825 sig_w = MAX(sig_w, 0.1);
2826 tau_u = MAX(tau_u, 300.);
2827 tau_w = MAX(tau_w, 100.);
2828
2829 /* Update perturbations... */
2830 const double ru = exp(-fabs(cache->dt[ip]) / tau_u);
2831 const double ru2 = sqrt(1.0 - SQR(ru));
2832 cache->uvwp[ip][0]
2833 = (float) (cache->uvwp[ip][0] * ru + ru2 * cache->rs[3 * ip]);
2834 cache->uvwp[ip][1]
2835 = (float) (cache->uvwp[ip][1] * ru + ru2 * cache->rs[3 * ip + 1]);
2836
2837 const double rw = exp(-fabs(cache->dt[ip]) / tau_w);
2838 const double rw2 = sqrt(1.0 - SQR(rw));
2839 cache->uvwp[ip][2]
2840 = (float) (cache->uvwp[ip][2] * rw + rw2 * cache->rs[3 * ip + 2]
2841 + sig_w * dsigw_dz * cache->dt[ip]); // TODO: check approx for density correction?
2842
2843 /* Calculate new air parcel position... */
2844 atm->lon[ip] +=
2845 DX2DEG(cache->uvwp[ip][0] * cache->dt[ip] / 1000., atm->lat[ip]);
2846 atm->lat[ip] += DY2DEG(cache->uvwp[ip][1] * cache->dt[ip] / 1000.);
2847 atm->p[ip] +=
2848 DZ2DP(cache->uvwp[ip][2] * cache->dt[ip] / 1000., atm->p[ip]);
2849 }
2850}
#define KARMAN
Karman's constant.
Definition: mptrac.h:187
#define THETAVIRT(p, t, h2o)
Compute virtual potential temperature.
Definition: mptrac.h:1673
#define DZ2DP(dz, p)
Convert a change in altitude to a change in pressure.
Definition: mptrac.h:562
Here is the call graph for this function:

◆ module_diff_turb()

void module_diff_turb ( const ctl_t ctl,
cache_t cache,
const clim_t clim,
met_t met0,
met_t met1,
atm_t atm 
)

Applies turbulent diffusion processes to atmospheric particles.

This function calculates and applies turbulent diffusion effects, including horizontal and vertical diffusion, as well as vertical mixing in the planetary boundary layer (PBL), to a set of atmospheric particles based on input parameters and environmental conditions.

Parameters
[in]ctlPointer to the control structure containing simulation parameters.
[in,out]cachePointer to the cache structure for temporary data and random numbers.
[in]climPointer to the climate structure containing climatological data.
[in,out]met0Pointer to the meteorological data structure for the initial timestep.
[in,out]met1Pointer to the meteorological data structure for the next timestep.
[in,out]atmPointer to the atmospheric structure containing particle data.

The function performs the following operations:

  • Allocates temporary arrays for random number generation.
  • Generates random numbers for simulating diffusion effects.
  • Loops over atmospheric particles to compute and apply:
    • Horizontal turbulent diffusion, based on prescribed diffusivity values.
    • Vertical turbulent diffusion, using vertical diffusivity values.
  • Cleans up allocated resources after processing.

Turbulent diffusivity parameters are derived from control inputs and weighted based on atmospheric layer influences (PBL, troposphere, stratosphere).

Note
  • Control parameters TURB_DX_PBL, TURB_DX_TROP, TURB_DX_STRAT, TURB_DZ_TROP and TURB_DZ_PBL, TURB_DZ_TROP, TURB_DZ_STRAT define horizontal and vertical diffusivities (in units of m**2 s**-1) in the PBL, troposphere, and stratosphere, respectively. The control parameter DIFF_MIX_PBL is used to switch vertical mixing in the PBL on or off.
  • Apply the following settings to reproduce Stohl et al. (2005): TURB_DX_PBL = 50 TURB_DX_TROP = 50 TURB_DX_STRAT = 0 TURB_DX_PBL = 0 TURB_DX_TROP = 0 TURB_DX_STRAT = 0.1 TURB_MESOX = 0.16 TURB_MESOZ = 0.16 DIFF_MIX_PBL = 0
  • Apply the following setting to reproduce Maryon et al. (1991) and Ryall et al. (1998): TURB_DX_PBL = 5300 TURB_DX_TROP = 1325 TURB_DX_STRAT = 1325 TURB_DX_PBL = 0 TURB_DX_TROP = 1.5 TURB_DX_STRAT = 1.5 TURB_MESOX = 0 TURB_MESOZ = 0 DIFF_MIX_PBL = 1
Author
Lars Hoffmann

Definition at line 2854 of file mptrac.c.

2860 {
2861
2862 /* Set timer... */
2863 SELECT_TIMER("MODULE_DIFF_TURB", "PHYSICS", NVTX_GPU);
2864
2865 /* Create random numbers... */
2866 module_rng(ctl, cache->rs, 3 * (size_t) atm->np, 1);
2867
2868 /* Loop over particles... */
2869 PARTICLE_LOOP(0, atm->np, 1,
2870 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2871
2872 /* Get PBL and surface pressure... */
2873 double pbl, ps;
2875 INTPOL_2D(pbl, 1);
2876 INTPOL_2D(ps, 0);
2877
2878 /* Get weighting factors... */
2879 const double wpbl = pbl_weight(ctl, atm, ip, pbl, ps);
2880 const double wtrop = tropo_weight(clim, atm, ip) * (1.0 - wpbl);
2881 const double wstrat = 1.0 - wpbl - wtrop;
2882
2883 /* Set diffusivity... */
2884 const double dx = wpbl * ctl->turb_dx_pbl + wtrop * ctl->turb_dx_trop
2885 + wstrat * ctl->turb_dx_strat;
2886 const double dz = wpbl * ctl->turb_dz_pbl + wtrop * ctl->turb_dz_trop
2887 + wstrat * ctl->turb_dz_strat;
2888
2889 /* Horizontal turbulent diffusion... */
2890 if (dx > 0) {
2891 const double sigma = sqrt(2.0 * dx * fabs(cache->dt[ip])) / 1000.;
2892 atm->lon[ip] += DX2DEG(cache->rs[3 * ip] * sigma, atm->lat[ip]);
2893 atm->lat[ip] += DY2DEG(cache->rs[3 * ip + 1] * sigma);
2894 }
2895
2896 /* Vertical turbulent diffusion... */
2897 if (dz > 0) {
2898 const double sigma = sqrt(2.0 * dz * fabs(cache->dt[ip])) / 1000.;
2899 atm->p[ip] += DZ2DP(cache->rs[3 * ip + 2] * sigma, atm->p[ip]);
2900 }
2901 }
2902}
double pbl_weight(const ctl_t *ctl, const atm_t *atm, const int ip, const double pbl, const double ps)
Computes a weighting factor based on planetary boundary layer pressure.
Definition: mptrac.c:5872
double turb_dz_trop
Vertical turbulent diffusion coefficient (troposphere) [m^2/s].
Definition: mptrac.h:2664
double turb_dx_strat
Horizontal turbulent diffusion coefficient (stratosphere) [m^2/s].
Definition: mptrac.h:2658
double turb_dx_trop
Horizontal turbulent diffusion coefficient (troposphere) [m^2/s].
Definition: mptrac.h:2655
double turb_dx_pbl
Horizontal turbulent diffusion coefficient (PBL) [m^2/s].
Definition: mptrac.h:2652
double turb_dz_strat
Vertical turbulent diffusion coefficient (stratosphere) [m^2/s].
Definition: mptrac.h:2667
double turb_dz_pbl
Vertical turbulent diffusion coefficient (PBL) [m^2/s].
Definition: mptrac.h:2661
Here is the call graph for this function:

◆ module_dry_depo()

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

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.
cachePointer to the cache structure for temporary data and random numbers.
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.
Author
Lars Hoffmann

Definition at line 2906 of file mptrac.c.

2911 {
2912
2913 /* Set timer... */
2914 SELECT_TIMER("MODULE_DRY_DEPO", "PHYSICS", NVTX_GPU);
2915
2916 /* Check quantity flags... */
2917 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
2918 ERRMSG("Module needs quantity mass or volume mixing ratio!");
2919
2920 /* Loop over particles... */
2921 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2922
2923 /* Get surface pressure... */
2924 double ps;
2926 INTPOL_2D(ps, 1);
2927
2928 /* Check whether particle is above the surface layer... */
2929 if (atm->p[ip] < ps - ctl->dry_depo_dp)
2930 continue;
2931
2932 /* Set depth of surface layer... */
2933 const double dz = 1000. * (Z(ps - ctl->dry_depo_dp) - Z(ps));
2934
2935 /* Calculate sedimentation velocity for particles... */
2936 double v_dep;
2937 if (ctl->qnt_rp > 0 && ctl->qnt_rhop > 0) {
2938
2939 /* Get temperature... */
2940 double t;
2941 INTPOL_3D(t, 1);
2942
2943 /* Set deposition velocity... */
2944 v_dep = sedi(atm->p[ip], t, atm->q[ctl->qnt_rp][ip],
2945 atm->q[ctl->qnt_rhop][ip]);
2946 }
2947
2948 /* Use explicit sedimentation velocity for gases... */
2949 else
2950 v_dep = ctl->dry_depo_vdep;
2951
2952 /* Calculate loss of mass based on deposition velocity... */
2953 const double aux = exp(-cache->dt[ip] * v_dep / dz);
2954 if (ctl->qnt_m >= 0) {
2955 if (ctl->qnt_mloss_dry >= 0)
2956 atm->q[ctl->qnt_mloss_dry][ip]
2957 += atm->q[ctl->qnt_m][ip] * (1 - aux);
2958 atm->q[ctl->qnt_m][ip] *= aux;
2959 if (ctl->qnt_loss_rate >= 0)
2960 atm->q[ctl->qnt_loss_rate][ip] += v_dep / dz;
2961 }
2962 if (ctl->qnt_vmr >= 0)
2963 atm->q[ctl->qnt_vmr][ip] *= aux;
2964 }
2965}
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:8918
int qnt_rhop
Quantity array index for particle density.
Definition: mptrac.h:2198
int qnt_rp
Quantity array index for particle radius.
Definition: mptrac.h:2195
double dry_depo_dp
Dry deposition surface layer [hPa].
Definition: mptrac.h:2889
int qnt_mloss_dry
Quantity array index for total mass loss due to dry deposition.
Definition: mptrac.h:2342
double dry_depo_vdep
Dry deposition velocity [m/s].
Definition: mptrac.h:2892
Here is the call graph for this function:

◆ module_h2o2_chem()

void module_h2o2_chem ( const ctl_t ctl,
const cache_t cache,
const clim_t clim,
met_t met0,
met_t met1,
atm_t atm 
)

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.
cachePointer to the cache structure for temporary data and random numbers.
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.
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 2969 of file mptrac.c.

2975 {
2976
2977 /* Set timer... */
2978 SELECT_TIMER("MODULE_H2O2_CHEM", "PHYSICS", NVTX_GPU);
2979
2980 /* Check quantity flags... */
2981 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
2982 ERRMSG("Module needs quantity mass or volume mixing ratio!");
2983
2984 /* Parameter of SO2 correction... */
2985 const double a = 3.12541941e-06;
2986 const double b = -5.72532259e-01;
2987 const double low = pow(1. / a, 1. / b);
2988
2989 /* Loop over particles... */
2990 PARTICLE_LOOP(0, atm->np, 1,
2991 "acc data present(ctl,cache,ctl,met0,met1,atm)") {
2992
2993 /* Check whether particle is inside cloud... */
2994 double lwc, rwc;
2996 INTPOL_3D(lwc, 1);
2997 INTPOL_3D(rwc, 0);
2998 if (!(lwc > 0 || rwc > 0))
2999 continue;
3000
3001 /* Get temperature... */
3002 double t;
3003 INTPOL_3D(t, 0);
3004
3005 /* Get molecular density... */
3006 const double M = MOLEC_DENS(atm->p[ip], t);
3007
3008 /* Reaction rate (Berglen et al., 2004)... */
3009 const double k = 9.1e7 * exp(-29700. / RI * (1. / t - 1. / 298.15)); /* (Maass, 1999), unit: M^(-2) */
3010
3011 /* Henry constant of SO2... */
3012 const double H_SO2 =
3013 1.3e-2 * exp(2900. * (1. / t - 1. / 298.15)) * RI * t;
3014 const double K_1S = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15)); /* unit: mol/L */
3015
3016 /* Henry constant of H2O2... */
3017 const double H_h2o2 =
3018 8.3e2 * exp(7600. * (1. / t - 1. / 298.15)) * RI * t;
3019
3020 /* Correction factor for high SO2 concentration
3021 (if qnt_Cx is defined, the correction is switched on)... */
3022 double cor = 1.0;
3023 if (ctl->qnt_Cx >= 0)
3024 cor = atm->q[ctl->qnt_Cx][ip] >
3025 low ? a * pow(atm->q[ctl->qnt_Cx][ip], b) : 1;
3026
3027 const double h2o2 = H_h2o2
3028 * clim_zm(&clim->h2o2, atm->time[ip], atm->lat[ip], atm->p[ip])
3029 * M * cor * 1000. / AVO; /* unit: mol/L */
3030
3031 /* Volume water content in cloud [m^3 m^(-3)]... */
3032 const double rho_air = atm->p[ip] / (RI * t) * MA / 10.;
3033 const double CWC = (lwc + rwc) * rho_air / 1e3;
3034
3035 /* Calculate exponential decay (Rolph et al., 1992)... */
3036 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
3037 const double aux = exp(-cache->dt[ip] * rate_coef);
3038 if (ctl->qnt_m >= 0) {
3039 if (ctl->qnt_mloss_h2o2 >= 0)
3040 atm->q[ctl->qnt_mloss_h2o2][ip] += atm->q[ctl->qnt_m][ip] * (1 - aux);
3041 atm->q[ctl->qnt_m][ip] *= aux;
3042 if (ctl->qnt_loss_rate >= 0)
3043 atm->q[ctl->qnt_loss_rate][ip] += rate_coef;
3044 }
3045 if (ctl->qnt_vmr >= 0)
3046 atm->q[ctl->qnt_vmr][ip] *= aux;
3047 }
3048}
#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:1002
int qnt_mloss_h2o2
Quantity array index for total mass loss due to H2O2 chemistry.
Definition: mptrac.h:2333
Here is the call graph for this function:

◆ module_isosurf_init()

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

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

3057 {
3058
3059 double t;
3060
3061 /* Set timer... */
3062 SELECT_TIMER("MODULE_ISOSURF_INIT", "PHYSICS", NVTX_GPU);
3063
3064 /* Save pressure... */
3065 if (ctl->isosurf == 1) {
3066 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,atm)") {
3067 cache->iso_var[ip] = atm->p[ip];
3068 }
3069 }
3070
3071 /* Save density... */
3072 else if (ctl->isosurf == 2) {
3073 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,met0,met1,atm)") {
3075 INTPOL_3D(t, 1);
3076 cache->iso_var[ip] = atm->p[ip] / t;
3077 }
3078 }
3079
3080 /* Save potential temperature... */
3081 else if (ctl->isosurf == 3) {
3082 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,met0,met1,atm)") {
3084 INTPOL_3D(t, 1);
3085 cache->iso_var[ip] = THETA(atm->p[ip], t);
3086 }
3087 }
3088
3089 /* Read balloon pressure data... */
3090 else if (ctl->isosurf == 4) {
3091
3092 /* Write info... */
3093 LOG(1, "Read balloon pressure data: %s", ctl->balloon);
3094
3095 /* Open file... */
3096 FILE *in;
3097 if (!(in = fopen(ctl->balloon, "r")))
3098 ERRMSG("Cannot open file!");
3099
3100 /* Read pressure time series... */
3101 char line[LEN];
3102 while (fgets(line, LEN, in))
3103 if (sscanf(line, "%lg %lg", &(cache->iso_ts[cache->iso_n]),
3104 &(cache->iso_ps[cache->iso_n])) == 2)
3105 if ((++cache->iso_n) > NP)
3106 ERRMSG("Too many data points!");
3107
3108 /* Check number of points... */
3109 if (cache->iso_n < 1)
3110 ERRMSG("Could not read any data!");
3111
3112 /* Close file... */
3113 fclose(in);
3114
3115 /* Update of cache data on device... */
3116 mptrac_update_device(NULL, cache, NULL, NULL, NULL, NULL);
3117 }
3118}
void mptrac_update_device(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates device memory for specified data structures.
Definition: mptrac.c:5545
#define NP
Maximum number of atmospheric data points.
Definition: mptrac.h:246
double iso_ts[NP]
Isosurface balloon time [s].
Definition: mptrac.h:3173
int iso_n
Isosurface balloon number of data points.
Definition: mptrac.h:3176
double iso_ps[NP]
Isosurface balloon pressure [hPa].
Definition: mptrac.h:3170
double iso_var[NP]
Isosurface variables.
Definition: mptrac.h:3167
char balloon[LEN]
Balloon position filename.
Definition: mptrac.h:2637
int isosurf
Isosurface parameter (0=none, 1=pressure, 2=density, 3=theta, 4=balloon).
Definition: mptrac.h:2634
Here is the call graph for this function:

◆ module_isosurf()

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

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.
cachePointer to the cache structure for temporary data and random numbers.
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.
Author
Lars Hoffmann

Definition at line 3122 of file mptrac.c.

3127 {
3128
3129 /* Set timer... */
3130 SELECT_TIMER("MODULE_ISOSURF", "PHYSICS", NVTX_GPU);
3131
3132 /* Loop over particles... */
3133 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,cache,met0,met1,atm)") {
3134
3135 /* Init... */
3136 double t;
3138
3139 /* Restore pressure... */
3140 if (ctl->isosurf == 1)
3141 atm->p[ip] = cache->iso_var[ip];
3142
3143 /* Restore density... */
3144 else if (ctl->isosurf == 2) {
3145 INTPOL_3D(t, 1);
3146 atm->p[ip] = cache->iso_var[ip] * t;
3147 }
3148
3149 /* Restore potential temperature... */
3150 else if (ctl->isosurf == 3) {
3151 INTPOL_3D(t, 1);
3152 atm->p[ip] = 1000. * pow(cache->iso_var[ip] / t, -1. / 0.286);
3153 }
3154
3155 /* Interpolate pressure... */
3156 else if (ctl->isosurf == 4) {
3157 if (atm->time[ip] <= cache->iso_ts[0])
3158 atm->p[ip] = cache->iso_ps[0];
3159 else if (atm->time[ip] >= cache->iso_ts[cache->iso_n - 1])
3160 atm->p[ip] = cache->iso_ps[cache->iso_n - 1];
3161 else {
3162 int idx = locate_irr(cache->iso_ts, cache->iso_n, atm->time[ip]);
3163 atm->p[ip] = LIN(cache->iso_ts[idx], cache->iso_ps[idx],
3164 cache->iso_ts[idx + 1], cache->iso_ps[idx + 1],
3165 atm->time[ip]);
3166 }
3167 }
3168 }
3169}
Here is the call graph for this function:

◆ module_kpp_chem()

void module_kpp_chem ( ctl_t ctl,
cache_t cache,
clim_t clim,
met_t met0,
met_t met1,
atm_t atm 
)

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.
cachePointer to the cache structure for temporary data and random numbers.
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.
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 ( const ctl_t ctl,
const cache_t cache,
const clim_t clim,
met_t met0,
met_t met1,
atm_t atm 
)

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.
cachePointer to the cache structure for temporary data and random numbers.
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.
Author
Lars Hoffmann

Definition at line 3227 of file mptrac.c.

3233 {
3234
3235 /* Set timer... */
3236 SELECT_TIMER("MODULE_METEO", "PHYSICS", NVTX_GPU);
3237
3238 /* Check quantity flags... */
3239 if (ctl->qnt_tsts >= 0)
3240 if (ctl->qnt_tice < 0 || ctl->qnt_tnat < 0)
3241 ERRMSG("Need T_ice and T_NAT to calculate T_STS!");
3242
3243 /* Loop over particles... */
3244 PARTICLE_LOOP(0, atm->np, 0,
3245 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3246
3247 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb, cl,
3248 plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot, o3, lwc,
3249 rwc, iwc, swc, cc, z, zt;
3250
3251 /* Interpolate meteo data... */
3253 INTPOL_TIME_ALL(atm->time[ip], atm->p[ip], atm->lon[ip], atm->lat[ip]);
3254
3255 /* Set quantities... */
3256 SET_ATM(qnt_ps, ps);
3257 SET_ATM(qnt_ts, ts);
3258 SET_ATM(qnt_zs, zs);
3259 SET_ATM(qnt_us, us);
3260 SET_ATM(qnt_vs, vs);
3261 SET_ATM(qnt_ess, ess);
3262 SET_ATM(qnt_nss, nss);
3263 SET_ATM(qnt_shf, shf);
3264 SET_ATM(qnt_lsm, lsm);
3265 SET_ATM(qnt_sst, sst);
3266 SET_ATM(qnt_pbl, pbl);
3267 SET_ATM(qnt_pt, pt);
3268 SET_ATM(qnt_tt, tt);
3269 SET_ATM(qnt_zt, zt);
3270 SET_ATM(qnt_h2ot, h2ot);
3271 SET_ATM(qnt_zg, z);
3272 SET_ATM(qnt_p, atm->p[ip]);
3273 SET_ATM(qnt_t, t);
3274 SET_ATM(qnt_rho, RHO(atm->p[ip], t));
3275 SET_ATM(qnt_u, u);
3276 SET_ATM(qnt_v, v);
3277 SET_ATM(qnt_w, w);
3278 SET_ATM(qnt_h2o, h2o);
3279 SET_ATM(qnt_o3, o3);
3280 SET_ATM(qnt_lwc, lwc);
3281 SET_ATM(qnt_rwc, rwc);
3282 SET_ATM(qnt_iwc, iwc);
3283 SET_ATM(qnt_swc, swc);
3284 SET_ATM(qnt_cc, cc);
3285 SET_ATM(qnt_pct, pct);
3286 SET_ATM(qnt_pcb, pcb);
3287 SET_ATM(qnt_cl, cl);
3288 SET_ATM(qnt_plcl, plcl);
3289 SET_ATM(qnt_plfc, plfc);
3290 SET_ATM(qnt_pel, pel);
3291 SET_ATM(qnt_cape, cape);
3292 SET_ATM(qnt_cin, cin);
3293 SET_ATM(qnt_o3c, o3c);
3294 SET_ATM(qnt_hno3,
3295 clim_zm(&clim->hno3, atm->time[ip], atm->lat[ip], atm->p[ip]));
3296 SET_ATM(qnt_oh, clim_oh(ctl, clim, atm->time[ip],
3297 atm->lon[ip], atm->lat[ip], atm->p[ip]));
3298 SET_ATM(qnt_h2o2, clim_zm(&clim->h2o2, atm->time[ip],
3299 atm->lat[ip], atm->p[ip]));
3300 SET_ATM(qnt_ho2, clim_zm(&clim->ho2, atm->time[ip],
3301 atm->lat[ip], atm->p[ip]));
3302 SET_ATM(qnt_o1d, clim_zm(&clim->o1d, atm->time[ip],
3303 atm->lat[ip], atm->p[ip]));
3304 SET_ATM(qnt_vh, sqrt(u * u + v * v));
3305 SET_ATM(qnt_vz, -1e3 * H0 / atm->p[ip] * w);
3306 SET_ATM(qnt_psat, PSAT(t));
3307 SET_ATM(qnt_psice, PSICE(t));
3308 SET_ATM(qnt_pw, PW(atm->p[ip], h2o));
3309 SET_ATM(qnt_sh, SH(h2o));
3310 SET_ATM(qnt_rh, RH(atm->p[ip], t, h2o));
3311 SET_ATM(qnt_rhice, RHICE(atm->p[ip], t, h2o));
3312 SET_ATM(qnt_theta, THETA(atm->p[ip], t));
3313 SET_ATM(qnt_zeta, atm->q[ctl->qnt_zeta][ip]);
3314 SET_ATM(qnt_zeta_d, ZETA(ps, atm->p[ip], t));
3315 SET_ATM(qnt_tvirt, TVIRT(t, h2o));
3316 SET_ATM(qnt_lapse, lapse_rate(t, h2o));
3317 SET_ATM(qnt_pv, pv);
3318 SET_ATM(qnt_tdew, TDEW(atm->p[ip], h2o));
3319 SET_ATM(qnt_tice, TICE(atm->p[ip], h2o));
3320 SET_ATM(qnt_tnat,
3321 nat_temperature(atm->p[ip], h2o,
3322 clim_zm(&clim->hno3, atm->time[ip],
3323 atm->lat[ip], atm->p[ip])));
3324 SET_ATM(qnt_tsts,
3325 0.5 * (atm->q[ctl->qnt_tice][ip] + atm->q[ctl->qnt_tnat][ip]));
3326 }
3327}
double nat_temperature(const double p, const double h2o, const double hno3)
Calculates the nitric acid trihydrate (NAT) temperature.
Definition: mptrac.c:5848
double lapse_rate(const double t, const double h2o)
Calculates the moist adiabatic lapse rate in Kelvin per kilometer.
Definition: mptrac.c:1742
#define H0
Scale height [km].
Definition: mptrac.h:177
#define PSICE(t)
Compute saturation pressure over ice (WMO, 2018).
Definition: mptrac.h:1352
#define TICE(p, h2o)
Calculate frost point temperature (WMO, 2018).
Definition: mptrac.h:1620
#define RHICE(p, t, h2o)
Compute relative humidity over ice.
Definition: mptrac.h:1456
#define INTPOL_TIME_ALL(time, p, lon, lat)
Interpolate multiple meteorological variables in time.
Definition: mptrac.h:786
#define RH(p, t, h2o)
Compute relative humidity over water.
Definition: mptrac.h:1426
#define TDEW(p, h2o)
Calculate dew point temperature.
Definition: mptrac.h:1595
#define PSAT(t)
Compute saturation pressure over water.
Definition: mptrac.h:1328
clim_zm_t hno3
HNO3 zonal means.
Definition: mptrac.h:3325
int qnt_tnat
Quantity array index for T_NAT.
Definition: mptrac.h:2402
int qnt_tice
Quantity array index for T_ice.
Definition: mptrac.h:2396
int qnt_tsts
Quantity array index for T_STS.
Definition: mptrac.h:2399
Here is the call graph for this function:

◆ module_mixing()

void module_mixing ( const ctl_t ctl,
const clim_t clim,
atm_t atm,
const 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 3331 of file mptrac.c.

3335 {
3336
3337 /* Set timer... */
3338 SELECT_TIMER("MODULE_MIXING", "PHYSICS", NVTX_GPU);
3339
3340 /* Allocate... */
3341 const int np = atm->np;
3342 int *restrict const ixs = (int *) malloc((size_t) np * sizeof(int));
3343 int *restrict const iys = (int *) malloc((size_t) np * sizeof(int));
3344 int *restrict const izs = (int *) malloc((size_t) np * sizeof(int));
3345
3346 /* Set grid box size... */
3347 const double dz = (ctl->mixing_z1 - ctl->mixing_z0) / ctl->mixing_nz;
3348 const double dlon = (ctl->mixing_lon1 - ctl->mixing_lon0) / ctl->mixing_nx;
3349 const double dlat = (ctl->mixing_lat1 - ctl->mixing_lat0) / ctl->mixing_ny;
3350
3351 /* Set time interval... */
3352 const double t0 = t - 0.5 * ctl->dt_mod;
3353 const double t1 = t + 0.5 * ctl->dt_mod;
3354
3355 /* Get indices... */
3356#ifdef _OPENACC
3357#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
3358#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
3359#pragma acc parallel loop independent gang vector
3360#else
3361#pragma omp parallel for default(shared)
3362#endif
3363 for (int ip = 0; ip < np; ip++) {
3364 ixs[ip] = (int) ((atm->lon[ip] - ctl->mixing_lon0) / dlon);
3365 iys[ip] = (int) ((atm->lat[ip] - ctl->mixing_lat0) / dlat);
3366 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->mixing_z0) / dz);
3367 if (atm->time[ip] < t0 || atm->time[ip] > t1
3368 || ixs[ip] < 0 || ixs[ip] >= ctl->mixing_nx
3369 || iys[ip] < 0 || iys[ip] >= ctl->mixing_ny
3370 || izs[ip] < 0 || izs[ip] >= ctl->mixing_nz)
3371 izs[ip] = -1;
3372 }
3373
3374 /* Calculate interparcel mixing... */
3375 if (ctl->qnt_m >= 0)
3376 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_m);
3377 if (ctl->qnt_vmr >= 0)
3378 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_vmr);
3379 if (ctl->qnt_Ch2o >= 0)
3380 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Ch2o);
3381 if (ctl->qnt_Co3 >= 0)
3382 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Co3);
3383 if (ctl->qnt_Cco >= 0)
3384 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cco);
3385 if (ctl->qnt_Coh >= 0)
3386 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Coh);
3387 if (ctl->qnt_Ch >= 0)
3388 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Ch);
3389 if (ctl->qnt_Cho2 >= 0)
3390 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cho2);
3391 if (ctl->qnt_Ch2o2 >= 0)
3392 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Ch2o2);
3393 if (ctl->qnt_Co1d >= 0)
3394 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Co1d);
3395 if (ctl->qnt_Co3p >= 0)
3396 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Co3p);
3397 if (ctl->qnt_Cccl4 >= 0)
3398 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cccl4);
3399 if (ctl->qnt_Cccl3f >= 0)
3400 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cccl3f);
3401 if (ctl->qnt_Cccl2f2 >= 0)
3402 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cccl2f2);
3403 if (ctl->qnt_Cn2o >= 0)
3404 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cn2o);
3405 if (ctl->qnt_Csf6 >= 0)
3406 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Csf6);
3407 if (ctl->qnt_aoa >= 0)
3408 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_aoa);
3409
3410 /* Free... */
3411#ifdef _OPENACC
3412#pragma acc exit data delete(ixs,iys,izs)
3413#endif
3414 free(ixs);
3415 free(iys);
3416 free(izs);
3417}
void module_mixing_help(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const int *ixs, const int *iys, const int *izs, const int qnt_idx)
Perform interparcel mixing for a specific quantity.
Definition: mptrac.c:3421
int qnt_Coh
Quantity array index for OH volume mixing ratio (chemistry code).
Definition: mptrac.h:2417
int mixing_nx
Number of longitudes of mixing grid.
Definition: mptrac.h:2793
double mixing_z1
Upper altitude of mixing grid [km].
Definition: mptrac.h:2790
int qnt_Co1d
Quantity array index for O(1D) volume mixing ratio (chemistry code).
Definition: mptrac.h:2429
double mixing_z0
Lower altitude of mixing grid [km].
Definition: mptrac.h:2787
int qnt_Cco
Quantity array index for CO volume mixing ratio (chemistry code).
Definition: mptrac.h:2414
int mixing_ny
Number of latitudes of mixing grid.
Definition: mptrac.h:2802
int qnt_Ch
Quantity array index for H volume mixing ratio (chemistry code).
Definition: mptrac.h:2420
double mixing_lat0
Lower latitude of mixing grid [deg].
Definition: mptrac.h:2805
int qnt_Cho2
Quantity array index for HO2 volume mixing ratio (chemistry code).
Definition: mptrac.h:2423
int mixing_nz
Number of altitudes of mixing grid.
Definition: mptrac.h:2784
double mixing_lon0
Lower longitude of mixing grid [deg].
Definition: mptrac.h:2796
double mixing_lat1
Upper latitude of mixing grid [deg].
Definition: mptrac.h:2808
int qnt_Co3p
Quantity array index for O(3P) volume mixing ratio (chemistry code).
Definition: mptrac.h:2432
int qnt_Ch2o2
Quantity array index for H2O2 volume mixing ratio (chemistry code).
Definition: mptrac.h:2426
double mixing_lon1
Upper longitude of mixing grid [deg].
Definition: mptrac.h:2799
Here is the call graph for this function:

◆ module_mixing_help()

void module_mixing_help ( const ctl_t ctl,
const clim_t clim,
atm_t atm,
const int *  ixs,
const int *  iys,
const int *  izs,
const 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 3421 of file mptrac.c.

3428 {
3429
3430 /* Allocate... */
3431 const int np = atm->np;
3432 const int ngrid = ctl->mixing_nx * ctl->mixing_ny * ctl->mixing_nz;
3433 double *restrict const cmean =
3434 (double *) malloc((size_t) ngrid * sizeof(double));
3435 int *restrict const count = (int *) malloc((size_t) ngrid * sizeof(int));
3436
3437 /* Init... */
3438#ifdef _OPENACC
3439#pragma acc enter data create(cmean[0:ngrid],count[0:ngrid])
3440#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
3441#pragma acc parallel loop independent gang vector
3442#else
3443#ifdef __NVCOMPILER
3444#pragma novector
3445#endif
3446#pragma omp parallel for
3447#endif
3448 for (int i = 0; i < ngrid; i++) {
3449 count[i] = 0;
3450 cmean[i] = 0;
3451 }
3452
3453 /* Loop over particles... */
3454#ifdef _OPENACC
3455#pragma acc parallel loop independent gang vector
3456#endif
3457 for (int ip = 0; ip < np; ip++)
3458 if (izs[ip] >= 0) {
3459 int idx = ARRAY_3D
3460 (ixs[ip], iys[ip], ctl->mixing_ny, izs[ip], ctl->mixing_nz);
3461#ifdef _OPENACC
3462#pragma acc atomic update
3463#endif
3464 cmean[idx] += atm->q[qnt_idx][ip];
3465#ifdef _OPENACC
3466#pragma acc atomic update
3467#endif
3468 count[idx]++;
3469 }
3470#ifdef _OPENACC
3471#pragma acc parallel loop independent gang vector
3472#else
3473#ifdef __NVCOMPILER
3474#pragma novector
3475#endif
3476#pragma omp parallel for
3477#endif
3478 for (int i = 0; i < ngrid; i++)
3479 if (count[i] > 0)
3480 cmean[i] /= count[i];
3481
3482 /* Calculate interparcel mixing... */
3483#ifdef _OPENACC
3484#pragma acc parallel loop independent gang vector
3485#else
3486#pragma omp parallel for
3487#endif
3488 for (int ip = 0; ip < np; ip++)
3489 if (izs[ip] >= 0) {
3490
3491 /* Set mixing parameter... */
3492 double mixparam = 1.0;
3493 if (ctl->mixing_trop < 1 || ctl->mixing_strat < 1) {
3494 double w = tropo_weight(clim, atm, ip);
3495 mixparam = w * ctl->mixing_trop + (1 - w) * ctl->mixing_strat;
3496 }
3497
3498 /* Adjust quantity... */
3499 atm->q[qnt_idx][ip] +=
3500 (cmean
3501 [ARRAY_3D(ixs[ip], iys[ip], ctl->mixing_ny, izs[ip], ctl->mixing_nz)]
3502 - atm->q[qnt_idx][ip]) * mixparam;
3503 }
3504
3505 /* Free... */
3506#ifdef _OPENACC
3507#pragma acc exit data delete(cmean,count)
3508#endif
3509 free(cmean);
3510 free(count);
3511}
double mixing_trop
Interparcel exchange parameter for mixing in the troposphere.
Definition: mptrac.h:2778
double mixing_strat
Interparcel exchange parameter for mixing in the stratosphere.
Definition: mptrac.h:2781
Here is the call graph for this function:

◆ module_oh_chem()

void module_oh_chem ( const ctl_t ctl,
const cache_t cache,
const clim_t clim,
met_t met0,
met_t met1,
atm_t atm 
)

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.
cachePointer to the cache structure for temporary data and random numbers.
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.
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 3515 of file mptrac.c.

3521 {
3522
3523 /* Set timer... */
3524 SELECT_TIMER("MODULE_OH_CHEM", "PHYSICS", NVTX_GPU);
3525
3526 /* Check quantity flags... */
3527 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
3528 ERRMSG("Module needs quantity mass or volume mixing ratio!");
3529
3530 /* Parameter of SO2 correction... */
3531 const double a = 4.71572206e-08;
3532 const double b = -8.28782867e-01;
3533 const double low = pow(1. / a, 1. / b);
3534
3535 /* Loop over particles... */
3536 PARTICLE_LOOP(0, atm->np, 1,
3537 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3538
3539 /* Get temperature... */
3540 double t;
3542 INTPOL_3D(t, 1);
3543
3544 /* Calculate molecular density... */
3545 const double M = MOLEC_DENS(atm->p[ip], t);
3546
3547 /* Use constant reaction rate... */
3548 double k = NAN;
3549 if (ctl->oh_chem_reaction == 1)
3550 k = ctl->oh_chem[0];
3551
3552 /* Calculate bimolecular reaction rate... */
3553 else if (ctl->oh_chem_reaction == 2)
3554 k = ctl->oh_chem[0] * exp(-ctl->oh_chem[1] / t);
3555
3556 /* Calculate termolecular reaction rate... */
3557 if (ctl->oh_chem_reaction == 3) {
3558
3559 /* Calculate rate coefficient for X + OH + M -> XOH + M
3560 (JPL Publication 19-05) ... */
3561 const double k0 =
3562 ctl->oh_chem[0] * (ctl->oh_chem[1] !=
3563 0 ? pow(298. / t, ctl->oh_chem[1]) : 1.);
3564 const double ki =
3565 ctl->oh_chem[2] * (ctl->oh_chem[3] !=
3566 0 ? pow(298. / t, ctl->oh_chem[3]) : 1.);
3567 const double c = log10(k0 * M / ki);
3568 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
3569 }
3570
3571 /* Correction factor for high SO2 concentration
3572 (if qnt_Cx is defined, the correction is switched on)... */
3573 double cor = 1;
3574 if (ctl->qnt_Cx >= 0)
3575 cor =
3576 atm->q[ctl->qnt_Cx][ip] >
3577 low ? a * pow(atm->q[ctl->qnt_Cx][ip], b) : 1;
3578
3579 /* Calculate exponential decay... */
3580 const double rate_coef =
3581 k * clim_oh(ctl, clim, atm->time[ip], atm->lon[ip],
3582 atm->lat[ip], atm->p[ip]) * M * cor;
3583 const double aux = exp(-cache->dt[ip] * rate_coef);
3584 if (ctl->qnt_m >= 0) {
3585 if (ctl->qnt_mloss_oh >= 0)
3586 atm->q[ctl->qnt_mloss_oh][ip]
3587 += atm->q[ctl->qnt_m][ip] * (1 - aux);
3588 atm->q[ctl->qnt_m][ip] *= aux;
3589 if (ctl->qnt_loss_rate >= 0)
3590 atm->q[ctl->qnt_loss_rate][ip] += rate_coef;
3591 }
3592 if (ctl->qnt_vmr >= 0)
3593 atm->q[ctl->qnt_vmr][ip] *= aux;
3594 }
3595}
double oh_chem[4]
Coefficients for OH reaction rate (A, E/R or k0, n, kinf, m).
Definition: mptrac.h:2841
int oh_chem_reaction
Reaction type for OH chemistry (0=none, 2=bimolecular, 3=termolecular).
Definition: mptrac.h:2838
int qnt_mloss_oh
Quantity array index for total mass loss due to OH chemistry.
Definition: mptrac.h:2330
Here is the call graph for this function:

◆ module_position()

void module_position ( const cache_t cache,
met_t met0,
met_t met1,
atm_t atm 
)

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
cachePointer to the cache structure for temporary data and random numbers.
met0Pointer to the first meteorological data structure.
met1Pointer to the second meteorological data structure.
atmPointer to the atmospheric data structure containing particle information.
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 3599 of file mptrac.c.

3603 {
3604
3605 /* Set timer... */
3606 SELECT_TIMER("MODULE_POSITION", "PHYSICS", NVTX_GPU);
3607
3608 /* Loop over particles... */
3609 PARTICLE_LOOP(0, atm->np, 1, "acc data present(cache,met0,met1,atm)") {
3610
3611 /* Init... */
3612 double ps;
3614
3615 /* Calculate modulo... */
3616 atm->lon[ip] = FMOD(atm->lon[ip], 360.);
3617 atm->lat[ip] = FMOD(atm->lat[ip], 360.);
3618
3619 /* Check latitude... */
3620 while (atm->lat[ip] < -90 || atm->lat[ip] > 90) {
3621 if (atm->lat[ip] > 90) {
3622 atm->lat[ip] = 180 - atm->lat[ip];
3623 atm->lon[ip] += 180;
3624 }
3625 if (atm->lat[ip] < -90) {
3626 atm->lat[ip] = -180 - atm->lat[ip];
3627 atm->lon[ip] += 180;
3628 }
3629 }
3630
3631 /* Check longitude... */
3632 while (atm->lon[ip] < -180)
3633 atm->lon[ip] += 360;
3634 while (atm->lon[ip] >= 180)
3635 atm->lon[ip] -= 360;
3636
3637 /* Check pressure... */
3638 if (atm->p[ip] < met0->p[met0->np - 1]) {
3639 // TODO: add reflection: atm->p[ip] = 2. * met0->p[met0->np - 1] - atm->p[ip];
3640 atm->p[ip] = met0->p[met0->np - 1];
3641 } else if (atm->p[ip] > 300.) {
3642 INTPOL_2D(ps, 1);
3643 // TODO: add reflection: if (atm->p[ip] > ps)
3644 // atm->p[ip] = 2. * ps - atm->p[ip];
3645 if (atm->p[ip] > ps)
3646 atm->p[ip] = ps;
3647 }
3648 }
3649}

◆ module_rng_init()

void module_rng_init ( const 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 3653 of file mptrac.c.

3654 {
3655
3656 /* Initialize GSL random number generators... */
3657 gsl_rng_env_setup();
3658 if (omp_get_max_threads() > NTHREADS)
3659 ERRMSG("Too many threads!");
3660 for (int i = 0; i < NTHREADS; i++) {
3661 rng[i] = gsl_rng_alloc(gsl_rng_default);
3662 gsl_rng_set(rng[i], gsl_rng_default_seed
3663 + (long unsigned) (ntask * NTHREADS + i));
3664 }
3665
3666 /* Initialize cuRAND random number generators... */
3667#ifdef CURAND
3668 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
3669 CURAND_STATUS_SUCCESS)
3670 ERRMSG("Cannot create random number generator!");
3671 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
3672 CURAND_STATUS_SUCCESS)
3673 ERRMSG("Cannot set seed for random number generator!");
3674 if (curandSetStream
3675 (rng_curand,
3676 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
3677 CURAND_STATUS_SUCCESS)
3678 ERRMSG("Cannot set stream for random number generator!");
3679#endif
3680}
#define NTHREADS
Maximum number of OpenMP threads.
Definition: mptrac.h:286

◆ module_rng()

void module_rng ( const ctl_t ctl,
double *  rs,
const size_t  n,
const 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 3684 of file mptrac.c.

3688 {
3689
3690 /* Use GSL random number generators... */
3691 if (ctl->rng_type == 0) {
3692
3693 /* Uniform distribution... */
3694 if (method == 0) {
3695#pragma omp parallel for default(shared)
3696 for (size_t i = 0; i < n; ++i)
3697 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
3698 }
3699
3700 /* Normal distribution... */
3701 else if (method == 1) {
3702#pragma omp parallel for default(shared)
3703 for (size_t i = 0; i < n; ++i)
3704 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
3705 }
3706
3707 /* Update of random numbers on device... */
3708#ifdef _OPENACC
3709 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
3710#pragma acc update device(rs[:n])
3711#endif
3712 }
3713
3714 /* Use Squares random number generator (Widynski, 2022)... */
3715 else if (ctl->rng_type == 1) {
3716
3717 /* Set key (don't change this!)... */
3718 const uint64_t key = 0xc8e4fd154ce32f6d;
3719
3720 /* Uniform distribution... */
3721#ifdef _OPENACC
3722#pragma acc data present(rs)
3723#pragma acc parallel loop independent gang vector
3724#else
3725#pragma omp parallel for default(shared)
3726#endif
3727 for (size_t i = 0; i < n + 1; ++i) {
3728 uint64_t r, t, x, y, z;
3729 y = x = (rng_ctr + i) * key;
3730 z = y + key;
3731 x = x * x + y;
3732 x = (x >> 32) | (x << 32);
3733 x = x * x + z;
3734 x = (x >> 32) | (x << 32);
3735 x = x * x + y;
3736 x = (x >> 32) | (x << 32);
3737 t = x = x * x + z;
3738 x = (x >> 32) | (x << 32);
3739 r = t ^ ((x * x + y) >> 32);
3740 rs[i] = (double) r / (double) UINT64_MAX;
3741 }
3742 rng_ctr += n + 1;
3743
3744 /* Normal distribution... */
3745 if (method == 1) {
3746#ifdef _OPENACC
3747#pragma acc parallel loop independent gang vector
3748#else
3749#pragma omp parallel for default(shared)
3750#endif
3751 for (size_t i = 0; i < n; i += 2) {
3752 const double r = sqrt(-2.0 * log(rs[i]));
3753 const double phi = 2.0 * M_PI * rs[i + 1];
3754 rs[i] = r * cosf((float) phi);
3755 rs[i + 1] = r * sinf((float) phi);
3756 }
3757 }
3758 }
3759
3760 /* Use cuRAND random number generators... */
3761 else if (ctl->rng_type == 2) {
3762#ifdef CURAND
3763#pragma acc host_data use_device(rs)
3764 {
3765
3766 /* Uniform distribution... */
3767 if (method == 0) {
3768 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
3769 CURAND_STATUS_SUCCESS)
3770 ERRMSG("Cannot create random numbers!");
3771 }
3772
3773 /* Normal distribution... */
3774 else if (method == 1) {
3775 if (curandGenerateNormalDouble
3776 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
3777 1.0) != CURAND_STATUS_SUCCESS)
3778 ERRMSG("Cannot create random numbers!");
3779 }
3780 }
3781#else
3782 ERRMSG("MPTRAC was compiled without cuRAND!");
3783#endif
3784 }
3785}
int rng_type
Random number generator (0=GSL, 1=Squares, 2=cuRAND).
Definition: mptrac.h:2646

◆ module_sedi()

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

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.
cachePointer to the cache structure for temporary data and random numbers.
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.
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 3789 of file mptrac.c.

3794 {
3795
3796 /* Set timer... */
3797 SELECT_TIMER("MODULE_SEDI", "PHYSICS", NVTX_GPU);
3798
3799 /* Loop over particles... */
3800 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
3801
3802 /* Get temperature... */
3803 double t;
3805 INTPOL_3D(t, 1);
3806
3807 /* Sedimentation velocity... */
3808 const double v_s = sedi(atm->p[ip], t, atm->q[ctl->qnt_rp][ip],
3809 atm->q[ctl->qnt_rhop][ip]);
3810
3811 /* Calculate pressure change... */
3812 atm->p[ip] += DZ2DP(v_s * cache->dt[ip] / 1000., atm->p[ip]);
3813 }
3814}
Here is the call graph for this function:

◆ module_sort()

void module_sort ( const 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 3818 of file mptrac.c.

3821 {
3822
3823 /* Set timer... */
3824 SELECT_TIMER("MODULE_SORT", "PHYSICS", NVTX_GPU);
3825
3826 /* Allocate... */
3827 const int np = atm->np;
3828 double *restrict const a = (double *) malloc((size_t) np * sizeof(double));
3829 int *restrict const p = (int *) malloc((size_t) np * sizeof(int));
3830
3831#ifdef _OPENACC
3832#pragma acc enter data create(a[0:np],p[0:np])
3833#pragma acc data present(ctl,met0,atm,a,p)
3834#endif
3835
3836 /* Get box index... */
3837#ifdef _OPENACC
3838#pragma acc parallel loop independent gang vector
3839#else
3840#pragma omp parallel for default(shared)
3841#endif
3842 for (int ip = 0; ip < np; ip++) {
3843 a[ip] =
3844 (double) ((locate_reg(met0->lon, met0->nx, atm->lon[ip]) * met0->ny +
3845 locate_reg(met0->lat, met0->ny, atm->lat[ip]))
3846 * met0->np + locate_irr(met0->p, met0->np, atm->p[ip]));
3847 p[ip] = ip;
3848 }
3849
3850 /* Sorting... */
3851#ifdef _OPENACC
3852#pragma acc host_data use_device(a,p)
3853#endif
3854#ifdef THRUST
3855 thrustSortWrapper(a, np, p);
3856#else
3857 ERRMSG("MPTRAC was compiled without Thrust library!");
3858#endif
3859
3860 /* Sort data... */
3861 module_sort_help(atm->time, p, np);
3862 module_sort_help(atm->p, p, np);
3863 module_sort_help(atm->lon, p, np);
3864 module_sort_help(atm->lat, p, np);
3865 for (int iq = 0; iq < ctl->nq; iq++)
3866 module_sort_help(atm->q[iq], p, np);
3867
3868 /* Free... */
3869#ifdef _OPENACC
3870#pragma acc exit data delete(a,p)
3871#endif
3872 free(a);
3873 free(p);
3874}
void module_sort_help(double *a, const int *p, const int np)
Reorder an array based on a given permutation.
Definition: mptrac.c:3878
void thrustSortWrapper(double *__restrict__ c, int n, int *__restrict__ index)
Wrapper to Thrust sorting function.
int nq
Number of quantities.
Definition: mptrac.h:2165
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 3878 of file mptrac.c.

3881 {
3882
3883 /* Allocate... */
3884 double *restrict const help =
3885 (double *) malloc((size_t) np * sizeof(double));
3886
3887 /* Reordering of array... */
3888#ifdef _OPENACC
3889#pragma acc enter data create(help[0:np])
3890#pragma acc data present(a,p,help)
3891#pragma acc parallel loop independent gang vector
3892#else
3893#pragma omp parallel for default(shared)
3894#endif
3895 for (int ip = 0; ip < np; ip++)
3896 help[ip] = a[p[ip]];
3897#ifdef _OPENACC
3898#pragma acc parallel loop independent gang vector
3899#else
3900#pragma omp parallel for default(shared)
3901#endif
3902 for (int ip = 0; ip < np; ip++)
3903 a[ip] = help[ip];
3904
3905 /* Free... */
3906#ifdef _OPENACC
3907#pragma acc exit data delete(help)
3908#endif
3909 free(help);
3910}

◆ module_timesteps()

void module_timesteps ( const ctl_t ctl,
cache_t cache,
met_t met0,
atm_t atm,
const 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.
cachePointer to the cache structure for temporary data and random numbers.
met0Pointer to the initial meteorological data structure.
atmPointer to the atmospheric data structure containing air parcel information.
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 3914 of file mptrac.c.

3919 {
3920
3921 /* Set timer... */
3922 SELECT_TIMER("MODULE_TIMESTEPS", "PHYSICS", NVTX_GPU);
3923
3924 const double latmin = gsl_stats_min(met0->lat, 1, (size_t) met0->ny),
3925 latmax = gsl_stats_max(met0->lat, 1, (size_t) met0->ny);
3926
3927 const int local =
3928 (fabs(met0->lon[met0->nx - 1] - met0->lon[0] - 360.0) >= 0.01);
3929
3930 /* Loop over particles... */
3931 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,cache,met0,atm)") {
3932
3933 /* Set time step for each air parcel... */
3934 if ((ctl->direction * (atm->time[ip] - ctl->t_start) >= 0
3935 && ctl->direction * (atm->time[ip] - ctl->t_stop) <= 0
3936 && ctl->direction * (atm->time[ip] - t) < 0))
3937 cache->dt[ip] = t - atm->time[ip];
3938 else
3939 cache->dt[ip] = 0.0;
3940
3941 /* Check horizontal boundaries of local meteo data... */
3942 if (local && (atm->lon[ip] <= met0->lon[0]
3943 || atm->lon[ip] >= met0->lon[met0->nx - 1]
3944 || atm->lat[ip] <= latmin || atm->lat[ip] >= latmax))
3945 cache->dt[ip] = 0.0;
3946 }
3947}
int direction
Direction flag (1=forward calculation, -1=backward calculation).
Definition: mptrac.h:2453
double t_stop
Stop time of simulation [s].
Definition: mptrac.h:2459
double t_start
Start time of simulation [s].
Definition: mptrac.h:2456

◆ module_timesteps_init()

void module_timesteps_init ( ctl_t ctl,
const 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 3951 of file mptrac.c.

3953 {
3954
3955 /* Set timer... */
3956 SELECT_TIMER("MODULE_TIMESTEPS_INIT", "PHYSICS", NVTX_GPU);
3957
3958 /* Set start time... */
3959 if (ctl->direction == 1) {
3960 ctl->t_start = gsl_stats_min(atm->time, 1, (size_t) atm->np);
3961 if (ctl->t_stop > 1e99)
3962 ctl->t_stop = gsl_stats_max(atm->time, 1, (size_t) atm->np);
3963 } else {
3964 ctl->t_start = gsl_stats_max(atm->time, 1, (size_t) atm->np);
3965 if (ctl->t_stop > 1e99)
3966 ctl->t_stop = gsl_stats_min(atm->time, 1, (size_t) atm->np);
3967 }
3968
3969 /* Check time interval... */
3970 if (ctl->direction * (ctl->t_stop - ctl->t_start) <= 0)
3971 ERRMSG("Nothing to do! Check T_STOP and DIRECTION!");
3972
3973 /* Round start time... */
3974 if (ctl->direction == 1)
3975 ctl->t_start = floor(ctl->t_start / ctl->dt_mod) * ctl->dt_mod;
3976 else
3977 ctl->t_start = ceil(ctl->t_start / ctl->dt_mod) * ctl->dt_mod;
3978}

◆ module_tracer_chem()

void module_tracer_chem ( const ctl_t ctl,
const cache_t cache,
const clim_t clim,
met_t met0,
met_t met1,
atm_t atm 
)

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.
cachePointer to the cache structure for temporary data and random numbers.
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.
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 3982 of file mptrac.c.

3988 {
3989
3990 /* Set timer... */
3991 SELECT_TIMER("MODULE_TRACER_CHEM", "PHYSICS", NVTX_GPU);
3992
3993 /* Loop over particles... */
3994 PARTICLE_LOOP(0, atm->np, 1,
3995 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3996
3997 /* Get temperature... */
3998 double t;
4000 INTPOL_3D(t, 1);
4001
4002 /* Get molecular density... */
4003 const double M = MOLEC_DENS(atm->p[ip], t);
4004
4005 /* Get total column ozone... */
4006 double o3c;
4007 INTPOL_2D(o3c, 1);
4008
4009 /* Get solar zenith angle... */
4010 const double sza = sza_calc(atm->time[ip], atm->lon[ip], atm->lat[ip]);
4011
4012 /* Get O(1D) volume mixing ratio... */
4013 const double o1d =
4014 clim_zm(&clim->o1d, atm->time[ip], atm->lat[ip], atm->p[ip]);
4015
4016 /* Reactions for CFC-10... */
4017 if (ctl->qnt_Cccl4 >= 0) {
4018 const double K_o1d = ARRHENIUS(3.30e-10, 0, t) * o1d * M;
4019 const double K_hv = clim_photo(clim->photo.ccl4, &(clim->photo),
4020 atm->p[ip], sza, o3c);
4021 atm->q[ctl->qnt_Cccl4][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4022 }
4023
4024 /* Reactions for CFC-11... */
4025 if (ctl->qnt_Cccl3f >= 0) {
4026 const double K_o1d = ARRHENIUS(2.30e-10, 0, t) * o1d * M;
4027 const double K_hv = clim_photo(clim->photo.ccl3f, &(clim->photo),
4028 atm->p[ip], sza, o3c);
4029 atm->q[ctl->qnt_Cccl3f][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4030 }
4031
4032 /* Reactions for CFC-12... */
4033 if (ctl->qnt_Cccl2f2 >= 0) {
4034 const double K_o1d = ARRHENIUS(1.40e-10, -25, t) * o1d * M;
4035 const double K_hv = clim_photo(clim->photo.ccl2f2, &(clim->photo),
4036 atm->p[ip], sza, o3c);
4037 atm->q[ctl->qnt_Cccl2f2][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4038 }
4039
4040 /* Reactions for N2O... */
4041 if (ctl->qnt_Cn2o >= 0) {
4042 const double K_o1d = ARRHENIUS(1.19e-10, -20, t) * o1d * M;
4043 const double K_hv = clim_photo(clim->photo.n2o, &(clim->photo),
4044 atm->p[ip], sza, o3c);
4045 atm->q[ctl->qnt_Cn2o][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4046 }
4047 }
4048}
double clim_photo(const double rate[CP][CSZA][CO3], const clim_photo_t *photo, const double p, const double sza, const double o3c)
Calculates the photolysis rate for a given set of atmospheric conditions.
Definition: mptrac.c:149
#define ARRHENIUS(a, b, t)
Calculate the Arrhenius rate constant.
Definition: mptrac.h:416
double ccl2f2[CP][CSZA][CO3]
CCl2F2 photolysis rate [1/s].
Definition: mptrac.h:3226
double ccl3f[CP][CSZA][CO3]
CCl3F photolysis rate [1/s].
Definition: mptrac.h:3223
double n2o[CP][CSZA][CO3]
N2O photolysis rate [1/s].
Definition: mptrac.h:3217
double ccl4[CP][CSZA][CO3]
CCl4 photolysis rate [1/s].
Definition: mptrac.h:3220
clim_photo_t photo
Photolysis rates.
Definition: mptrac.h:3322
Here is the call graph for this function:

◆ module_wet_depo()

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

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.
cachePointer to the cache structure for temporary data and random numbers.
met0Pointer to the initial meteorological data structure.
met1Pointer to the updated meteorological data structure.
atmPointer to the atmospheric data structure containing air parcel information.
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.
For exponential form A and B coefficients see Bakels et al. (2024, Table B2).
For Henry's law constants see Sander (2023) or https://henrys-law.org/.
Some species (e.g. SO2) require an effective Henry constant to account not only for physical solubility in water but also for chemical reactions, such as hydrolysis and ionization, which significantly enhance dissolution in aqueous solutions.
Authors
Lars Hoffmann
Mingzhao Liu

Definition at line 4052 of file mptrac.c.

4057 {
4058
4059 /* Set timer... */
4060 SELECT_TIMER("MODULE_WET_DEPO", "PHYSICS", NVTX_GPU);
4061
4062 /* Check quantity flags... */
4063 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
4064 ERRMSG("Module needs quantity mass or volume mixing ratio!");
4065
4066 /* Loop over particles... */
4067 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
4068
4069 /* Check whether particle is below cloud top... */
4070 double pct;
4072 INTPOL_2D(pct, 1);
4073 if (!isfinite(pct) || atm->p[ip] <= pct)
4074 continue;
4075
4076 /* Get cloud bottom pressure... */
4077 double pcb;
4078 INTPOL_2D(pcb, 0);
4079
4080 /* Estimate precipitation rate (Pisso et al., 2019)... */
4081 double cl;
4082 INTPOL_2D(cl, 0);
4083 const double Is =
4084 pow(1. / ctl->wet_depo_pre[0] * cl, 1. / ctl->wet_depo_pre[1]);
4085 if (Is < 0.01)
4086 continue;
4087
4088 /* Check whether particle is inside or below cloud... */
4089 double lwc, rwc, iwc, swc;
4090 INTPOL_3D(lwc, 1);
4091 INTPOL_3D(rwc, 0);
4092 INTPOL_3D(iwc, 0);
4093 INTPOL_3D(swc, 0);
4094 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
4095
4096 /* Get temperature... */
4097 double t;
4098 INTPOL_3D(t, 0);
4099
4100 /* Calculate in-cloud scavenging coefficient... */
4101 double lambda = 0;
4102 if (inside) {
4103
4104 /* Calculate retention factor... */
4105 double eta;
4106 if (t > 273.15)
4107 eta = 1;
4108 else if (t <= 238.15)
4109 eta = ctl->wet_depo_ic_ret_ratio;
4110 else
4111 eta = LIN(273.15, 1, 238.15, ctl->wet_depo_ic_ret_ratio, t);
4112
4113 /* Use exponential dependency for particles (Bakels et al., 2024)... */
4114 if (ctl->wet_depo_ic_a > 0)
4115 lambda = ctl->wet_depo_ic_a * pow(Is, ctl->wet_depo_ic_b) * eta;
4116
4117 /* Use Henry's law for gases... */
4118 else if (ctl->wet_depo_ic_h[0] > 0) {
4119
4120 /* Get Henry's constant (Burkholder et al., 2019; Sander, 2023)... */
4121 double h = ctl->wet_depo_ic_h[0]
4122 * exp(ctl->wet_depo_ic_h[1] * (1. / t - 1. / 298.15));
4123
4124 /* Use effective Henry's constant for SO2
4125 (Berglen, 2004; Simpson, 2012)... */
4126 if (ctl->wet_depo_so2_ph > 0) {
4127 const double H_ion = pow(10., -ctl->wet_depo_so2_ph);
4128 const double K_1 = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
4129 const double K_2 = 6e-8 * exp(1.12e3 * (1. / t - 1. / 298.15));
4130 h *= (1. + K_1 / H_ion + K_1 * K_2 / SQR(H_ion));
4131 }
4132
4133 /* Estimate depth of cloud layer... */
4134 const double dz = 1e3 * (Z(pct) - Z(pcb));
4135
4136 /* Calculate scavenging coefficient... */
4137 lambda = h * RI * t * Is / 3.6e6 / dz * eta;
4138 }
4139 }
4140
4141 /* Calculate below-cloud scavenging coefficient... */
4142 else {
4143
4144 /* Calculate retention factor... */
4145 double eta;
4146 if (t > 270)
4147 eta = 1;
4148 else
4149 eta = ctl->wet_depo_bc_ret_ratio;
4150
4151 /* Use exponential dependency for particles (Bakels et al., 2024)... */
4152 if (ctl->wet_depo_bc_a > 0)
4153 lambda = ctl->wet_depo_bc_a * pow(Is, ctl->wet_depo_bc_b) * eta;
4154
4155 /* Use Henry's law for gases... */
4156 else if (ctl->wet_depo_bc_h[0] > 0) {
4157
4158 /* Get Henry's constant (Burkholder et al., 2019; Sander, 2023)... */
4159 const double h = ctl->wet_depo_bc_h[0]
4160 * exp(ctl->wet_depo_bc_h[1] * (1. / t - 1. / 298.15));
4161
4162 /* Estimate depth of cloud layer... */
4163 const double dz = 1e3 * (Z(pct) - Z(pcb));
4164
4165 /* Calculate scavenging coefficient... */
4166 lambda = h * RI * t * Is / 3.6e6 / dz * eta;
4167 }
4168 }
4169
4170 /* Calculate exponential decay of mass... */
4171 const double aux = exp(-cache->dt[ip] * lambda);
4172 if (ctl->qnt_m >= 0) {
4173 if (ctl->qnt_mloss_wet >= 0)
4174 atm->q[ctl->qnt_mloss_wet][ip]
4175 += atm->q[ctl->qnt_m][ip] * (1 - aux);
4176 atm->q[ctl->qnt_m][ip] *= aux;
4177 if (ctl->qnt_loss_rate >= 0)
4178 atm->q[ctl->qnt_loss_rate][ip] += lambda;
4179 }
4180 if (ctl->qnt_vmr >= 0)
4181 atm->q[ctl->qnt_vmr][ip] *= aux;
4182 }
4183}
double wet_depo_ic_a
Coefficient A for wet deposition in cloud (exponential form).
Definition: mptrac.h:2868
double wet_depo_bc_a
Coefficient A for wet deposition below cloud (exponential form).
Definition: mptrac.h:2862
int qnt_mloss_wet
Quantity array index for total mass loss due to wet deposition.
Definition: mptrac.h:2339
double wet_depo_so2_ph
pH value used to calculate effective Henry constant of SO2.
Definition: mptrac.h:2880
double wet_depo_pre[2]
Coefficients for precipitation calculation.
Definition: mptrac.h:2859
double wet_depo_bc_h[2]
Coefficients for wet deposition below cloud (Henry's law: Hb, Cb).
Definition: mptrac.h:2877
double wet_depo_bc_ret_ratio
Coefficients for wet deposition below cloud: retention ratio.
Definition: mptrac.h:2886
double wet_depo_ic_h[2]
Coefficients for wet deposition in cloud (Henry's law: Hb, Cb).
Definition: mptrac.h:2874
double wet_depo_ic_ret_ratio
Coefficients for wet deposition in cloud: retention ratio.
Definition: mptrac.h:2883
double wet_depo_ic_b
Coefficient B for wet deposition in cloud (exponential form).
Definition: mptrac.h:2871
double wet_depo_bc_b
Coefficient B for wet deposition below cloud (exponential form).
Definition: mptrac.h:2865

◆ mptrac_alloc()

void mptrac_alloc ( ctl_t **  ctl,
cache_t **  cache,
clim_t **  clim,
met_t **  met0,
met_t **  met1,
atm_t **  atm 
)

Allocates and initializes memory resources for MPTRAC.

This function handles memory allocation for various data structures and sets up GPU resources if available. It also creates the necessary data regions on GPUs for OpenACC-enabled execution.

Parameters
[out]ctlPointer to the control structure (ctl_t).
[out]cachePointer to the cache structure (cache_t).
[out]climPointer to the climatology structure (clim_t).
[out]met0Pointer to the first meteorology structure (met_t).
[out]met1Pointer to the second meteorology structure (met_t).
[out]atmPointer to the atmospheric structure (atm_t).
Note
This function uses OpenACC for GPU initialization and memory management. If OpenACC is not enabled, the GPU-specific code is ignored.
Precondition
The function requires an environment supporting OpenACC for GPU operations. MPI support is optional but assumed if compiled with MPI.
Postcondition
Allocated structures are ready for use, and data regions on GPUs are initialized if OpenACC is enabled.
Exceptions
Runtimeerror if no GPU devices are available when OpenACC is enabled.
Author
Lars Hoffmann

Definition at line 4187 of file mptrac.c.

4193 {
4194
4195 /* Initialize GPU... */
4196#ifdef _OPENACC
4197 SELECT_TIMER("ACC_INIT", "INIT", NVTX_GPU);
4198 int rank = 0;
4199#ifdef MPI
4200 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
4201#endif
4202 if (acc_get_num_devices(acc_device_nvidia) <= 0)
4203 ERRMSG("Not running on a GPU device!");
4204 acc_set_device_num(rank % acc_get_num_devices(acc_device_nvidia),
4205 acc_device_nvidia);
4206 acc_device_t device_type = acc_get_device_type();
4207 acc_init(device_type);
4208#endif
4209
4210 /* Allocate... */
4211 SELECT_TIMER("ALLOC", "MEMORY", NVTX_CPU);
4212 ALLOC(*ctl, ctl_t, 1);
4213 ALLOC(*cache, cache_t, 1);
4214 ALLOC(*clim, clim_t, 1);
4215 ALLOC(*met0, met_t, 1);
4216 ALLOC(*met1, met_t, 1);
4217 ALLOC(*atm, atm_t, 1);
4218
4219 /* Create data region on GPU... */
4220#ifdef _OPENACC
4221 SELECT_TIMER("CREATE_DATA_REGION", "MEMORY", NVTX_GPU);
4222 ctl_t *ctlup = *ctl;
4223 cache_t *cacheup = *cache;
4224 clim_t *climup = *clim;
4225 met_t *met0up = *met0;
4226 met_t *met1up = *met1;
4227 atm_t *atmup = *atm;
4228#pragma acc enter data create(ctlup[:1],cacheup[:1],climup[:1],met0up[:1],met1up[:1],atmup[:1])
4229#endif
4230}
Air parcel data.
Definition: mptrac.h:3136
Cache data structure.
Definition: mptrac.h:3164
Climatological data.
Definition: mptrac.h:3304
Control parameters.
Definition: mptrac.h:2158
Meteo data structure.
Definition: mptrac.h:3363

◆ mptrac_free()

void mptrac_free ( ctl_t ctl,
cache_t cache,
clim_t clim,
met_t met0,
met_t met1,
atm_t atm 
)

Frees memory resources allocated for MPTRAC.

This function releases the memory allocated for various data structures and deletes any associated data regions on GPUs if OpenACC is enabled.

Parameters
[in]ctlPointer to the control structure (ctl_t) to be freed.
[in]cachePointer to the cache structure (cache_t) to be freed.
[in]climPointer to the climatology structure (clim_t) to be freed.
[in]met0Pointer to the first meteorology structure (met_t) to be freed.
[in]met1Pointer to the second meteorology structure (met_t) to be freed.
[in]atmPointer to the atmospheric structure (atm_t) to be freed.
Note
This function uses OpenACC for GPU memory management. If OpenACC is not enabled, the GPU-specific code is ignored.
Precondition
All input pointers must point to valid allocated memory. The function assumes that the memory was allocated using compatible allocation methods.
Postcondition
All input pointers are freed, and the associated data regions on GPUs are deleted if OpenACC is enabled.
Warning
Ensure that the input pointers are not used after calling this function as they will be invalidated.
Author
Lars Hoffmann

Definition at line 4234 of file mptrac.c.

4240 {
4241
4242 /* Delete data region on GPU... */
4243#ifdef _OPENACC
4244 SELECT_TIMER("DELETE_DATA_REGION", "MEMORY", NVTX_GPU);
4245#pragma acc exit data delete (ctl,cache,clim,met0,met1,atm)
4246#endif
4247
4248 /* Free... */
4249 SELECT_TIMER("FREE", "MEMORY", NVTX_CPU);
4250 free(atm);
4251 free(ctl);
4252 free(cache);
4253 free(clim);
4254 free(met0);
4255 free(met1);
4256}

◆ mptrac_get_met()

void mptrac_get_met ( ctl_t ctl,
clim_t clim,
const 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 4260 of file mptrac.c.

4265 {
4266
4267 static int init;
4268
4269 met_t *mets;
4270
4271 char cachefile[LEN], cmd[2 * LEN], filename[LEN];
4272
4273 /* Set timer... */
4274 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4275
4276 /* Init... */
4277 if (t == ctl->t_start || !init) {
4278 init = 1;
4279
4280 /* Read meteo data... */
4281 get_met_help(ctl, t + (ctl->direction == -1 ? -1 : 0), -1,
4282 ctl->metbase, ctl->dt_met, filename);
4283 if (!mptrac_read_met(filename, ctl, clim, *met0))
4284 ERRMSG("Cannot open file!");
4285
4286 get_met_help(ctl, t + (ctl->direction == 1 ? 1 : 0), 1,
4287 ctl->metbase, ctl->dt_met, filename);
4288 if (!mptrac_read_met(filename, ctl, clim, *met1))
4289 ERRMSG("Cannot open file!");
4290
4291 /* Update GPU... */
4292 mptrac_update_device(NULL, NULL, NULL, met0, met1, NULL);
4293 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4294
4295 /* Caching... */
4296 if (ctl->met_cache && t != ctl->t_stop) {
4297 get_met_help(ctl, t + 1.1 * ctl->dt_met * ctl->direction,
4298 ctl->direction, ctl->metbase, ctl->dt_met, cachefile);
4299 sprintf(cmd, "cat %s > /dev/null &", cachefile);
4300 LOG(1, "Caching: %s", cachefile);
4301 if (system(cmd) != 0)
4302 WARN("Caching command failed!");
4303 }
4304 }
4305
4306 /* Read new data for forward trajectories... */
4307 if (t > (*met1)->time) {
4308
4309 /* Pointer swap... */
4310 mets = *met1;
4311 *met1 = *met0;
4312 *met0 = mets;
4313
4314 /* Read new meteo data... */
4315 get_met_help(ctl, t, 1, ctl->metbase, ctl->dt_met, filename);
4316 if (!mptrac_read_met(filename, ctl, clim, *met1))
4317 ERRMSG("Cannot open file!");
4318
4319 /* Update GPU... */
4320 mptrac_update_device(NULL, NULL, NULL, NULL, met1, NULL);
4321 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4322
4323 /* Caching... */
4324 if (ctl->met_cache && t != ctl->t_stop) {
4325 get_met_help(ctl, t + ctl->dt_met, 1, ctl->metbase, ctl->dt_met,
4326 cachefile);
4327 sprintf(cmd, "cat %s > /dev/null &", cachefile);
4328 LOG(1, "Caching: %s", cachefile);
4329 if (system(cmd) != 0)
4330 WARN("Caching command failed!");
4331 }
4332 }
4333
4334 /* Read new data for backward trajectories... */
4335 if (t < (*met0)->time) {
4336
4337 /* Pointer swap... */
4338 mets = *met1;
4339 *met1 = *met0;
4340 *met0 = mets;
4341
4342 /* Read new meteo data... */
4343 get_met_help(ctl, t, -1, ctl->metbase, ctl->dt_met, filename);
4344 if (!mptrac_read_met(filename, ctl, clim, *met0))
4345 ERRMSG("Cannot open file!");
4346
4347 /* Update GPU... */
4348 mptrac_update_device(NULL, NULL, NULL, met0, NULL, NULL);
4349 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4350
4351 /* Caching... */
4352 if (ctl->met_cache && t != ctl->t_stop) {
4353 get_met_help(ctl, t - ctl->dt_met, -1, ctl->metbase, ctl->dt_met,
4354 cachefile);
4355 sprintf(cmd, "cat %s > /dev/null &", cachefile);
4356 LOG(1, "Caching: %s", cachefile);
4357 if (system(cmd) != 0)
4358 WARN("Caching command failed!");
4359 }
4360 }
4361
4362 /* Check that grids are consistent... */
4363 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
4364 if ((*met0)->nx != (*met1)->nx
4365 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
4366 ERRMSG("Meteo grid dimensions do not match!");
4367 for (int ix = 0; ix < (*met0)->nx; ix++)
4368 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
4369 ERRMSG("Meteo grid longitudes do not match!");
4370 for (int iy = 0; iy < (*met0)->ny; iy++)
4371 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
4372 ERRMSG("Meteo grid latitudes do not match!");
4373 for (int ip = 0; ip < (*met0)->np; ip++)
4374 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
4375 ERRMSG("Meteo grid pressure levels do not match!");
4376 }
4377}
int mptrac_read_met(const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met)
Reads meteorological data from a file, supporting multiple formats and MPI broadcasting.
Definition: mptrac.c:5353
void get_met_help(const ctl_t *ctl, const double t, const int direct, const char *metbase, const double dt_met, char *filename)
Generates a formatted filename for meteorological data files based on the input parameters.
Definition: mptrac.c:1003
int met_cache
Preload meteo data into disk cache (0=no, 1=yes).
Definition: mptrac.h:2620
char metbase[LEN]
Basename for meteo data.
Definition: mptrac.h:2469
Here is the call graph for this function:

◆ mptrac_init()

void mptrac_init ( ctl_t ctl,
cache_t cache,
clim_t clim,
atm_t atm,
const int  ntask 
)

Initializes the MPTRAC model and its associated components.

This function sets up the necessary components and subsystems for the MPTRAC module, including timesteps, random number generation, and GPU memory updates.

Parameters
ctlPointer to the control structure containing configuration and state information.
cachePointer to the cache structure used for data storage and retrieval.
climPointer to the climatology structure containing climate-related data.
atmPointer to the atmospheric structure containing atmospheric state data.
ntaskNumber of tasks or threads to initialize for the random number generator.

The function performs the following operations:

  • Initializes the timesteps using the module_timesteps_init function.
  • Initializes the random number generator using the module_rng_init function.
  • Updates GPU memory using the mptrac_update_device function.
Author
Lars Hoffmann

Definition at line 4381 of file mptrac.c.

4386 {
4387
4388 /* Initialize timesteps... */
4389 module_timesteps_init(ctl, atm);
4390
4391 /* Initialize random number generator... */
4392 module_rng_init(ntask);
4393
4394 /* Update GPU memory... */
4395 mptrac_update_device(ctl, cache, clim, NULL, NULL, atm);
4396}
void module_timesteps_init(ctl_t *ctl, const atm_t *atm)
Initialize start time and time interval for time-stepping.
Definition: mptrac.c:3951
void module_rng_init(const int ntask)
Initialize random number generators for parallel tasks.
Definition: mptrac.c:3653
Here is the call graph for this function:

◆ mptrac_read_atm()

int mptrac_read_atm ( const char *  filename,
const 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 4400 of file mptrac.c.

4403 {
4404
4405 int result;
4406
4407 /* Set timer... */
4408 SELECT_TIMER("READ_ATM", "INPUT", NVTX_READ);
4409
4410 /* Init... */
4411 atm->np = 0;
4412
4413 /* Write info... */
4414 LOG(1, "Read atmospheric data: %s", filename);
4415
4416 /* Read ASCII data... */
4417 if (ctl->atm_type == 0)
4418 result = read_atm_asc(filename, ctl, atm);
4419
4420 /* Read binary data... */
4421 else if (ctl->atm_type == 1)
4422 result = read_atm_bin(filename, ctl, atm);
4423
4424 /* Read netCDF data... */
4425 else if (ctl->atm_type == 2)
4426 result = read_atm_nc(filename, ctl, atm);
4427
4428 /* Read CLaMS data... */
4429 else if (ctl->atm_type == 3 || ctl->atm_type == 4)
4430 result = read_atm_clams(filename, ctl, atm);
4431
4432 /* Error... */
4433 else
4434 ERRMSG("Atmospheric data type not supported!");
4435
4436 /* Check result... */
4437 if (result != 1)
4438 return 0;
4439
4440 /* Check number of air parcels... */
4441 if (atm->np < 1)
4442 ERRMSG("Can not read any data!");
4443
4444 /* Write info... */
4445 double mini, maxi;
4446 LOG(2, "Number of particles: %d", atm->np);
4447 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
4448 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
4449 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
4450 LOG(2, "Altitude range: %g ... %g km", Z(maxi), Z(mini));
4451 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
4452 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
4453 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
4454 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
4455 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
4456 for (int iq = 0; iq < ctl->nq; iq++) {
4457 char msg[5 * LEN];
4458 sprintf(msg, "Quantity %s range: %s ... %s %s",
4459 ctl->qnt_name[iq], ctl->qnt_format[iq],
4460 ctl->qnt_format[iq], ctl->qnt_unit[iq]);
4461 gsl_stats_minmax(&mini, &maxi, atm->q[iq], 1, (size_t) atm->np);
4462 LOG(2, msg, mini, maxi);
4463 }
4464
4465 /* Return success... */
4466 return 1;
4467}
int read_atm_nc(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a generic netCDF file and populates the given atmospheric structure.
Definition: mptrac.c:6048
int read_atm_bin(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a binary file and populates the given atmospheric structure.
Definition: mptrac.c:5936
int read_atm_clams(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a CLaMS netCDF file and populates the given atmospheric structure.
Definition: mptrac.c:5992
int read_atm_asc(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from an ASCII file and populates the given atmospheric structure.
Definition: mptrac.c:5894
char qnt_format[NQ][LEN]
Quantity output format.
Definition: mptrac.h:2177
int atm_type
Type of atmospheric data files (0=ASCII, 1=binary, 2=netCDF, 3=CLaMS_traj, 4=CLaMS_pos).
Definition: mptrac.h:2921
char qnt_unit[NQ][LEN]
Quantity units.
Definition: mptrac.h:2174
char qnt_name[NQ][LEN]
Quantity names.
Definition: mptrac.h:2168
Here is the call graph for this function:

◆ mptrac_read_clim()

void mptrac_read_clim ( const 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 4471 of file mptrac.c.

4473 {
4474
4475 /* Set timer... */
4476 SELECT_TIMER("READ_CLIM", "INPUT", NVTX_READ);
4477
4478 /* Init tropopause climatology... */
4479 clim_tropo_init(clim);
4480
4481 /* Read photolysis rates... */
4482 if (ctl->clim_photo[0] != '-')
4483 read_clim_photo(ctl->clim_photo, &clim->photo);
4484
4485 /* Read HNO3 climatology... */
4486 if (ctl->clim_hno3_filename[0] != '-')
4487 read_clim_zm(ctl->clim_hno3_filename, "HNO3", &clim->hno3);
4488
4489 /* Read OH climatology... */
4490 if (ctl->clim_oh_filename[0] != '-') {
4491 read_clim_zm(ctl->clim_oh_filename, "OH", &clim->oh);
4492 if (ctl->oh_chem_beta > 0)
4493 clim_oh_diurnal_correction(ctl, clim);
4494 }
4495
4496 /* Read H2O2 climatology... */
4497 if (ctl->clim_h2o2_filename[0] != '-')
4498 read_clim_zm(ctl->clim_h2o2_filename, "H2O2", &clim->h2o2);
4499
4500 /* Read HO2 climatology... */
4501 if (ctl->clim_ho2_filename[0] != '-')
4502 read_clim_zm(ctl->clim_ho2_filename, "HO2", &clim->ho2);
4503
4504 /* Read O(1D) climatology... */
4505 if (ctl->clim_o1d_filename[0] != '-')
4506 read_clim_zm(ctl->clim_o1d_filename, "O1D", &clim->o1d);
4507
4508 /* Read CFC-10 time series... */
4509 if (ctl->clim_ccl4_timeseries[0] != '-')
4511
4512 /* Read CFC-11 time series... */
4513 if (ctl->clim_ccl3f_timeseries[0] != '-')
4515
4516 /* Read CFC-12 time series... */
4517 if (ctl->clim_ccl2f2_timeseries[0] != '-')
4519
4520 /* Read N2O time series... */
4521 if (ctl->clim_n2o_timeseries[0] != '-')
4522 read_clim_ts(ctl->clim_n2o_timeseries, &clim->n2o);
4523
4524 /* Read SF6 time series... */
4525 if (ctl->clim_sf6_timeseries[0] != '-')
4526 read_clim_ts(ctl->clim_sf6_timeseries, &clim->sf6);
4527}
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:6081
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:6200
void read_clim_zm(const char *filename, const char *varname, clim_zm_t *zm)
Reads zonally averaged climatological data from a netCDF file and populates the given structure.
Definition: mptrac.c:6254
void clim_tropo_init(clim_t *clim)
Initializes the tropopause data in the climatology structure.
Definition: mptrac.c:228
void clim_oh_diurnal_correction(const ctl_t *ctl, clim_t *clim)
Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data.
Definition: mptrac.c:116
char clim_ho2_filename[LEN]
Filename of HO2 climatology.
Definition: mptrac.h:2751
char clim_o1d_filename[LEN]
Filename of O(1D) climatology.
Definition: mptrac.h:2754
char clim_photo[LEN]
Filename of photolysis rates climatology.
Definition: mptrac.h:2739
char clim_h2o2_filename[LEN]
Filename of H2O2 climatology.
Definition: mptrac.h:2748
char clim_oh_filename[LEN]
Filename of OH climatology.
Definition: mptrac.h:2745
char clim_hno3_filename[LEN]
Filename of HNO3 climatology.
Definition: mptrac.h:2742
Here is the call graph for this function:

◆ mptrac_read_ctl()

void mptrac_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 4531 of file mptrac.c.

4535 {
4536
4537 /* Set timer... */
4538 SELECT_TIMER("READ_CTL", "INPUT", NVTX_READ);
4539
4540 /* Write info... */
4541 LOG(1, "\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
4542 "(executable: %s | version: %s | compiled: %s, %s)\n",
4543 argv[0], VERSION, __DATE__, __TIME__);
4544
4545 /* Initialize quantity indices... */
4546 ctl->qnt_idx = -1;
4547 ctl->qnt_ens = -1;
4548 ctl->qnt_stat = -1;
4549 ctl->qnt_m = -1;
4550 ctl->qnt_vmr = -1;
4551 ctl->qnt_rp = -1;
4552 ctl->qnt_rhop = -1;
4553 ctl->qnt_ps = -1;
4554 ctl->qnt_ts = -1;
4555 ctl->qnt_zs = -1;
4556 ctl->qnt_us = -1;
4557 ctl->qnt_vs = -1;
4558 ctl->qnt_ess = -1;
4559 ctl->qnt_nss = -1;
4560 ctl->qnt_shf = -1;
4561 ctl->qnt_lsm = -1;
4562 ctl->qnt_sst = -1;
4563 ctl->qnt_pbl = -1;
4564 ctl->qnt_pt = -1;
4565 ctl->qnt_tt = -1;
4566 ctl->qnt_zt = -1;
4567 ctl->qnt_h2ot = -1;
4568 ctl->qnt_zg = -1;
4569 ctl->qnt_p = -1;
4570 ctl->qnt_t = -1;
4571 ctl->qnt_rho = -1;
4572 ctl->qnt_u = -1;
4573 ctl->qnt_v = -1;
4574 ctl->qnt_w = -1;
4575 ctl->qnt_h2o = -1;
4576 ctl->qnt_o3 = -1;
4577 ctl->qnt_lwc = -1;
4578 ctl->qnt_rwc = -1;
4579 ctl->qnt_iwc = -1;
4580 ctl->qnt_swc = -1;
4581 ctl->qnt_cc = -1;
4582 ctl->qnt_pct = -1;
4583 ctl->qnt_pcb = -1;
4584 ctl->qnt_cl = -1;
4585 ctl->qnt_plcl = -1;
4586 ctl->qnt_plfc = -1;
4587 ctl->qnt_pel = -1;
4588 ctl->qnt_cape = -1;
4589 ctl->qnt_cin = -1;
4590 ctl->qnt_o3c = -1;
4591 ctl->qnt_hno3 = -1;
4592 ctl->qnt_oh = -1;
4593 ctl->qnt_h2o2 = -1;
4594 ctl->qnt_ho2 = -1;
4595 ctl->qnt_o1d = -1;
4596 ctl->qnt_mloss_oh = -1;
4597 ctl->qnt_mloss_h2o2 = -1;
4598 ctl->qnt_mloss_kpp = -1;
4599 ctl->qnt_mloss_wet = -1;
4600 ctl->qnt_mloss_dry = -1;
4601 ctl->qnt_mloss_decay = -1;
4602 ctl->qnt_loss_rate = -1;
4603 ctl->qnt_psat = -1;
4604 ctl->qnt_psice = -1;
4605 ctl->qnt_pw = -1;
4606 ctl->qnt_sh = -1;
4607 ctl->qnt_rh = -1;
4608 ctl->qnt_rhice = -1;
4609 ctl->qnt_theta = -1;
4610 ctl->qnt_zeta = -1;
4611 ctl->qnt_zeta_d = -1;
4612 ctl->qnt_tvirt = -1;
4613 ctl->qnt_lapse = -1;
4614 ctl->qnt_vh = -1;
4615 ctl->qnt_vz = -1;
4616 ctl->qnt_pv = -1;
4617 ctl->qnt_tdew = -1;
4618 ctl->qnt_tice = -1;
4619 ctl->qnt_tsts = -1;
4620 ctl->qnt_tnat = -1;
4621 ctl->qnt_Cx = -1;
4622 ctl->qnt_Ch2o = -1;
4623 ctl->qnt_Co3 = -1;
4624 ctl->qnt_Cco = -1;
4625 ctl->qnt_Coh = -1;
4626 ctl->qnt_Ch = -1;
4627 ctl->qnt_Cho2 = -1;
4628 ctl->qnt_Ch2o2 = -1;
4629 ctl->qnt_Co1d = -1;
4630 ctl->qnt_Co3p = -1;
4631 ctl->qnt_Cccl4 = -1;
4632 ctl->qnt_Cccl3f = -1;
4633 ctl->qnt_Cccl2f2 = -1;
4634 ctl->qnt_Cn2o = -1;
4635 ctl->qnt_Csf6 = -1;
4636 ctl->qnt_aoa = -1;
4637
4638 /* Read quantities... */
4639 ctl->nq = (int) scan_ctl(filename, argc, argv, "NQ", -1, "0", NULL);
4640 if (ctl->nq > NQ)
4641 ERRMSG("Too many quantities!");
4642 for (int iq = 0; iq < ctl->nq; iq++) {
4643
4644 /* Read quantity name and format... */
4645 scan_ctl(filename, argc, argv, "QNT_NAME", iq, "", ctl->qnt_name[iq]);
4646 scan_ctl(filename, argc, argv, "QNT_LONGNAME", iq, ctl->qnt_name[iq],
4647 ctl->qnt_longname[iq]);
4648 scan_ctl(filename, argc, argv, "QNT_FORMAT", iq, "%g",
4649 ctl->qnt_format[iq]);
4650 if (strcasecmp(ctl->qnt_name[iq], "aoa") == 0)
4651 sprintf(ctl->qnt_format[iq], "%%.2f");
4652
4653 /* Try to identify quantity... */
4654 SET_QNT(qnt_idx, "idx", "particle index", "-")
4655 SET_QNT(qnt_ens, "ens", "ensemble index", "-")
4656 SET_QNT(qnt_stat, "stat", "station flag", "-")
4657 SET_QNT(qnt_m, "m", "mass", "kg")
4658 SET_QNT(qnt_vmr, "vmr", "volume mixing ratio", "ppv")
4659 SET_QNT(qnt_rp, "rp", "particle radius", "microns")
4660 SET_QNT(qnt_rhop, "rhop", "particle density", "kg/m^3")
4661 SET_QNT(qnt_ps, "ps", "surface pressure", "hPa")
4662 SET_QNT(qnt_ts, "ts", "surface temperature", "K")
4663 SET_QNT(qnt_zs, "zs", "surface height", "km")
4664 SET_QNT(qnt_us, "us", "surface zonal wind", "m/s")
4665 SET_QNT(qnt_vs, "vs", "surface meridional wind", "m/s")
4666 SET_QNT(qnt_ess, "ess", "eastward turbulent surface stress", "N/m^2")
4667 SET_QNT(qnt_nss, "nss", "northward turbulent surface stress", "N/m^2")
4668 SET_QNT(qnt_shf, "shf", "surface sensible heat flux", "W/m^2")
4669 SET_QNT(qnt_lsm, "lsm", "land-sea mask", "1")
4670 SET_QNT(qnt_sst, "sst", "sea surface temperature", "K")
4671 SET_QNT(qnt_pbl, "pbl", "planetary boundary layer", "hPa")
4672 SET_QNT(qnt_pt, "pt", "tropopause pressure", "hPa")
4673 SET_QNT(qnt_tt, "tt", "tropopause temperature", "K")
4674 SET_QNT(qnt_zt, "zt", "tropopause geopotential height", "km")
4675 SET_QNT(qnt_h2ot, "h2ot", "tropopause water vapor", "ppv")
4676 SET_QNT(qnt_zg, "zg", "geopotential height", "km")
4677 SET_QNT(qnt_p, "p", "pressure", "hPa")
4678 SET_QNT(qnt_t, "t", "temperature", "K")
4679 SET_QNT(qnt_rho, "rho", "air density", "kg/m^3")
4680 SET_QNT(qnt_u, "u", "zonal wind", "m/s")
4681 SET_QNT(qnt_v, "v", "meridional wind", "m/s")
4682 SET_QNT(qnt_w, "w", "vertical velocity", "hPa/s")
4683 SET_QNT(qnt_h2o, "h2o", "water vapor", "ppv")
4684 SET_QNT(qnt_o3, "o3", "ozone", "ppv")
4685 SET_QNT(qnt_lwc, "lwc", "cloud liquid water content", "kg/kg")
4686 SET_QNT(qnt_rwc, "rwc", "cloud rain water content", "kg/kg")
4687 SET_QNT(qnt_iwc, "iwc", "cloud ice water content", "kg/kg")
4688 SET_QNT(qnt_swc, "iwc", "cloud snow water content", "kg/kg")
4689 SET_QNT(qnt_cc, "cc", "cloud cover", "1")
4690 SET_QNT(qnt_pct, "pct", "cloud top pressure", "hPa")
4691 SET_QNT(qnt_pcb, "pcb", "cloud bottom pressure", "hPa")
4692 SET_QNT(qnt_cl, "cl", "total column cloud water", "kg/m^2")
4693 SET_QNT(qnt_plcl, "plcl", "lifted condensation level", "hPa")
4694 SET_QNT(qnt_plfc, "plfc", "level of free convection", "hPa")
4695 SET_QNT(qnt_pel, "pel", "equilibrium level", "hPa")
4696 SET_QNT(qnt_cape, "cape", "convective available potential energy",
4697 "J/kg")
4698 SET_QNT(qnt_cin, "cin", "convective inhibition", "J/kg")
4699 SET_QNT(qnt_o3c, "o3c", "total column ozone", "DU")
4700 SET_QNT(qnt_hno3, "hno3", "nitric acid", "ppv")
4701 SET_QNT(qnt_oh, "oh", "hydroxyl radical", "ppv")
4702 SET_QNT(qnt_h2o2, "h2o2", "hydrogen peroxide", "ppv")
4703 SET_QNT(qnt_ho2, "ho2", "hydroperoxyl radical", "ppv")
4704 SET_QNT(qnt_o1d, "o1d", "atomic oxygen", "ppv")
4705 SET_QNT(qnt_mloss_oh, "mloss_oh", "mass loss due to OH chemistry", "kg")
4706 SET_QNT(qnt_mloss_h2o2, "mloss_h2o2", "mass loss due to H2O2 chemistry",
4707 "kg")
4708 SET_QNT(qnt_mloss_kpp, "mloss_kpp", "mass loss due to kpp chemistry",
4709 "kg")
4710 SET_QNT(qnt_mloss_wet, "mloss_wet", "mass loss due to wet deposition",
4711 "kg")
4712 SET_QNT(qnt_mloss_dry, "mloss_dry", "mass loss due to dry deposition",
4713 "kg")
4714 SET_QNT(qnt_mloss_decay, "mloss_decay",
4715 "mass loss due to exponential decay", "kg")
4716 SET_QNT(qnt_loss_rate, "loss_rate", "total loss rate", "s^-1")
4717 SET_QNT(qnt_psat, "psat", "saturation pressure over water", "hPa")
4718 SET_QNT(qnt_psice, "psice", "saturation pressure over ice", "hPa")
4719 SET_QNT(qnt_pw, "pw", "partial water vapor pressure", "hPa")
4720 SET_QNT(qnt_sh, "sh", "specific humidity", "kg/kg")
4721 SET_QNT(qnt_rh, "rh", "relative humidity", "%%")
4722 SET_QNT(qnt_rhice, "rhice", "relative humidity over ice", "%%")
4723 SET_QNT(qnt_theta, "theta", "potential temperature", "K")
4724 SET_QNT(qnt_zeta, "zeta", "zeta coordinate", "K")
4725 SET_QNT(qnt_zeta_d, "zeta_d", "diagnosed zeta coordinate", "K")
4726 SET_QNT(qnt_tvirt, "tvirt", "virtual temperature", "K")
4727 SET_QNT(qnt_lapse, "lapse", "temperature lapse rate", "K/km")
4728 SET_QNT(qnt_vh, "vh", "horizontal velocity", "m/s")
4729 SET_QNT(qnt_vz, "vz", "vertical velocity", "m/s")
4730 SET_QNT(qnt_pv, "pv", "potential vorticity", "PVU")
4731 SET_QNT(qnt_tdew, "tdew", "dew point temperature", "K")
4732 SET_QNT(qnt_tice, "tice", "frost point temperature", "K")
4733 SET_QNT(qnt_tsts, "tsts", "STS existence temperature", "K")
4734 SET_QNT(qnt_tnat, "tnat", "NAT existence temperature", "K")
4735 SET_QNT(qnt_Cx, "Cx", "Trace species x volume mixing ratio", "ppv")
4736 SET_QNT(qnt_Ch2o, "Ch2o", "H2O volume mixing ratio", "ppv")
4737 SET_QNT(qnt_Co3, "Co3", "O3 volume mixing ratio", "ppv")
4738 SET_QNT(qnt_Cco, "Cco", "CO volume mixing ratio", "ppv")
4739 SET_QNT(qnt_Coh, "Coh", "HO volume mixing ratio", "ppv")
4740 SET_QNT(qnt_Ch, "Ch", "H radical volume mixing ratio", "ppv")
4741 SET_QNT(qnt_Cho2, "Cho2", "HO2 volume mixing ratio", "ppv")
4742 SET_QNT(qnt_Ch2o2, "Ch2o2", "H2O2 volume mixing ratio", "ppv")
4743 SET_QNT(qnt_Co1d, "Co1d", "O(1D) volume mixing ratio", "ppv")
4744 SET_QNT(qnt_Co3p, "Co3p", "O(3P) radical volume mixing ratio", "ppv")
4745 SET_QNT(qnt_Cccl4, "Cccl4", "CCl4 (CFC-10) volume mixing ratio", "ppv")
4746 SET_QNT(qnt_Cccl3f, "Cccl3f", "CCl3F (CFC-11) volume mixing ratio",
4747 "ppv")
4748 SET_QNT(qnt_Cccl2f2, "Cccl2f2", "CCl2F2 (CFC-12) volume mixing ratio",
4749 "ppv")
4750 SET_QNT(qnt_Cn2o, "Cn2o", "N2O volume mixing ratio", "ppv")
4751 SET_QNT(qnt_Csf6, "Csf6", "SF6 volume mixing ratio", "ppv")
4752 SET_QNT(qnt_aoa, "aoa", "age of air", "s")
4753 scan_ctl(filename, argc, argv, "QNT_UNIT", iq, "", ctl->qnt_unit[iq]);
4754 }
4755
4756 /* Vertical coordinates and velocities... */
4757 ctl->advect_vert_coord =
4758 (int) scan_ctl(filename, argc, argv, "ADVECT_VERT_COORD", -1, "0", NULL);
4759 if (ctl->advect_vert_coord < 0 || ctl->advect_vert_coord > 2)
4760 ERRMSG("Set advect_vert_coord to 0, 1, or 2!");
4761 if (ctl->advect_vert_coord == 1 && ctl->qnt_zeta < 0)
4762 ERRMSG("Please add zeta to your quantities for diabatic calculations!");
4763 ctl->met_vert_coord =
4764 (int) scan_ctl(filename, argc, argv, "MET_VERT_COORD", -1, "0", NULL);
4765 if (ctl->met_vert_coord < 0 || ctl->met_vert_coord > 2)
4766 ERRMSG("Set MET_VERT_COORD to 0, 1, or 2!");
4767 if (ctl->advect_vert_coord == 2 && ctl->met_vert_coord == 0)
4768 ERRMSG
4769 ("Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
4770
4771 /* Time steps of simulation... */
4772 ctl->direction =
4773 (int) scan_ctl(filename, argc, argv, "DIRECTION", -1, "1", NULL);
4774 if (ctl->direction != -1 && ctl->direction != 1)
4775 ERRMSG("Set DIRECTION to -1 or 1!");
4776 ctl->t_stop = scan_ctl(filename, argc, argv, "T_STOP", -1, "1e100", NULL);
4777 ctl->dt_mod = scan_ctl(filename, argc, argv, "DT_MOD", -1, "180", NULL);
4778
4779 /* Meteo data... */
4780 scan_ctl(filename, argc, argv, "METBASE", -1, "-", ctl->metbase);
4781 ctl->dt_met = scan_ctl(filename, argc, argv, "DT_MET", -1, "3600", NULL);
4782 ctl->met_convention =
4783 (int) scan_ctl(filename, argc, argv, "MET_CONVENTION", -1, "0", NULL);
4784 ctl->met_type =
4785 (int) scan_ctl(filename, argc, argv, "MET_TYPE", -1, "0", NULL);
4786 if (ctl->advect_vert_coord == 1 && ctl->met_type != 0)
4787 ERRMSG
4788 ("Please use meteorological files in netcdf format for diabatic calculations.");
4789 ctl->met_clams =
4790 (int) scan_ctl(filename, argc, argv, "MET_CLAMS", -1, "0", NULL);
4791 ctl->met_nc_scale =
4792 (int) scan_ctl(filename, argc, argv, "MET_NC_SCALE", -1, "1", NULL);
4793 ctl->met_nc_level =
4794 (int) scan_ctl(filename, argc, argv, "MET_NC_LEVEL", -1, "0", NULL);
4795 ctl->met_nc_quant =
4796 (int) scan_ctl(filename, argc, argv, "MET_NC_QUANT", -1, "0", NULL);
4797 ctl->met_zfp_prec =
4798 (int) scan_ctl(filename, argc, argv, "MET_ZFP_PREC", -1, "8", NULL);
4799 ctl->met_zfp_tol_t =
4800 scan_ctl(filename, argc, argv, "MET_ZFP_TOL_T", -1, "5.0", NULL);
4801 ctl->met_zfp_tol_z =
4802 scan_ctl(filename, argc, argv, "MET_ZFP_TOL_Z", -1, "0.5", NULL);
4803 ctl->met_cms_batch =
4804 (int) scan_ctl(filename, argc, argv, "MET_CMS_BATCH", -1, "-1", NULL);
4805 ctl->met_cms_heur =
4806 (int) scan_ctl(filename, argc, argv, "MET_CMS_HEUR", -1, "1", NULL);
4807 ctl->met_cms_eps_z =
4808 scan_ctl(filename, argc, argv, "MET_CMS_EPS_Z", -1, "1.0", NULL);
4809 ctl->met_cms_eps_t =
4810 scan_ctl(filename, argc, argv, "MET_CMS_EPS_T", -1, "0.05", NULL);
4811 ctl->met_cms_eps_u =
4812 scan_ctl(filename, argc, argv, "MET_CMS_EPS_U", -1, "0.05", NULL);
4813 ctl->met_cms_eps_v =
4814 scan_ctl(filename, argc, argv, "MET_CMS_EPS_V", -1, "0.05", NULL);
4815 ctl->met_cms_eps_w =
4816 scan_ctl(filename, argc, argv, "MET_CMS_EPS_W", -1, "1.0", NULL);
4817 ctl->met_cms_eps_pv =
4818 scan_ctl(filename, argc, argv, "MET_CMS_EPS_PV", -1, "1.0", NULL);
4819 ctl->met_cms_eps_h2o =
4820 scan_ctl(filename, argc, argv, "MET_CMS_EPS_H2O", -1, "1.0", NULL);
4821 ctl->met_cms_eps_o3 =
4822 scan_ctl(filename, argc, argv, "MET_CMS_EPS_O3", -1, "1.0", NULL);
4823 ctl->met_cms_eps_lwc =
4824 scan_ctl(filename, argc, argv, "MET_CMS_EPS_LWC", -1, "1.0", NULL);
4825 ctl->met_cms_eps_rwc =
4826 scan_ctl(filename, argc, argv, "MET_CMS_EPS_RWC", -1, "1.0", NULL);
4827 ctl->met_cms_eps_iwc =
4828 scan_ctl(filename, argc, argv, "MET_CMS_EPS_IWC", -1, "1.0", NULL);
4829 ctl->met_cms_eps_swc =
4830 scan_ctl(filename, argc, argv, "MET_CMS_EPS_SWC", -1, "1.0", NULL);
4831 ctl->met_cms_eps_cc =
4832 scan_ctl(filename, argc, argv, "MET_CMS_EPS_CC", -1, "1.0", NULL);
4833 ctl->met_dx = (int) scan_ctl(filename, argc, argv, "MET_DX", -1, "1", NULL);
4834 ctl->met_dy = (int) scan_ctl(filename, argc, argv, "MET_DY", -1, "1", NULL);
4835 ctl->met_dp = (int) scan_ctl(filename, argc, argv, "MET_DP", -1, "1", NULL);
4836 if (ctl->met_dx < 1 || ctl->met_dy < 1 || ctl->met_dp < 1)
4837 ERRMSG("MET_DX, MET_DY, and MET_DP need to be greater than zero!");
4838 ctl->met_sx = (int) scan_ctl(filename, argc, argv, "MET_SX", -1, "1", NULL);
4839 ctl->met_sy = (int) scan_ctl(filename, argc, argv, "MET_SY", -1, "1", NULL);
4840 ctl->met_sp = (int) scan_ctl(filename, argc, argv, "MET_SP", -1, "1", NULL);
4841 if (ctl->met_sx < 1 || ctl->met_sy < 1 || ctl->met_sp < 1)
4842 ERRMSG("MET_SX, MET_SY, and MET_SP need to be greater than zero!");
4843 ctl->met_detrend =
4844 scan_ctl(filename, argc, argv, "MET_DETREND", -1, "-999", NULL);
4845 ctl->met_np = (int) scan_ctl(filename, argc, argv, "MET_NP", -1, "0", NULL);
4846 if (ctl->met_np > EP)
4847 ERRMSG("Too many levels!");
4848 ctl->met_press_level_def =
4849 (int) scan_ctl(filename, argc, argv, "MET_PRESS_LEVEL_DEF", -1, "-1",
4850 NULL);
4851 if (ctl->met_press_level_def >= 0) {
4852 level_definitions(ctl);
4853 } else {
4854 if (ctl->met_np > 0) {
4855 for (int ip = 0; ip < ctl->met_np; ip++)
4856 ctl->met_p[ip] =
4857 scan_ctl(filename, argc, argv, "MET_P", ip, "", NULL);
4858 }
4859 }
4860 ctl->met_geopot_sx =
4861 (int) scan_ctl(filename, argc, argv, "MET_GEOPOT_SX", -1, "-1", NULL);
4862 ctl->met_geopot_sy =
4863 (int) scan_ctl(filename, argc, argv, "MET_GEOPOT_SY", -1, "-1", NULL);
4864 ctl->met_relhum =
4865 (int) scan_ctl(filename, argc, argv, "MET_RELHUM", -1, "0", NULL);
4866 ctl->met_cape =
4867 (int) scan_ctl(filename, argc, argv, "MET_CAPE", -1, "1", NULL);
4868 if (ctl->met_cape < 0 || ctl->met_cape > 1)
4869 ERRMSG("Set MET_CAPE to 0 or 1!");
4870 ctl->met_pbl =
4871 (int) scan_ctl(filename, argc, argv, "MET_PBL", -1, "3", NULL);
4872 if (ctl->met_pbl < 0 || ctl->met_pbl > 3)
4873 ERRMSG("Set MET_PBL to 0 ... 3!");
4874 ctl->met_pbl_min =
4875 scan_ctl(filename, argc, argv, "MET_PBL_MIN", -1, "0.1", NULL);
4876 ctl->met_pbl_max =
4877 scan_ctl(filename, argc, argv, "MET_PBL_MAX", -1, "5.0", NULL);
4878 ctl->met_tropo =
4879 (int) scan_ctl(filename, argc, argv, "MET_TROPO", -1, "3", NULL);
4880 if (ctl->met_tropo < 0 || ctl->met_tropo > 5)
4881 ERRMSG("Set MET_TROPO to 0 ... 5!");
4882 ctl->met_tropo_pv =
4883 scan_ctl(filename, argc, argv, "MET_TROPO_PV", -1, "3.5", NULL);
4884 ctl->met_tropo_theta =
4885 scan_ctl(filename, argc, argv, "MET_TROPO_THETA", -1, "380", NULL);
4886 ctl->met_tropo_spline =
4887 (int) scan_ctl(filename, argc, argv, "MET_TROPO_SPLINE", -1, "1", NULL);
4888 ctl->met_dt_out =
4889 scan_ctl(filename, argc, argv, "MET_DT_OUT", -1, "0.1", NULL);
4890 ctl->met_cache =
4891 (int) scan_ctl(filename, argc, argv, "MET_CACHE", -1, "0", NULL);
4892 ctl->met_mpi_share =
4893 (int) scan_ctl(filename, argc, argv, "MET_MPI_SHARE", -1, "0", NULL);
4894
4895 /* Sorting... */
4896 ctl->sort_dt = scan_ctl(filename, argc, argv, "SORT_DT", -1, "-999", NULL);
4897
4898 /* Isosurface parameters... */
4899 ctl->isosurf =
4900 (int) scan_ctl(filename, argc, argv, "ISOSURF", -1, "0", NULL);
4901 scan_ctl(filename, argc, argv, "BALLOON", -1, "-", ctl->balloon);
4902
4903 /* Random number generator... */
4904 ctl->rng_type =
4905 (int) scan_ctl(filename, argc, argv, "RNG_TYPE", -1, "1", NULL);
4906 if (ctl->rng_type < 0 || ctl->rng_type > 2)
4907 ERRMSG("Set RNG_TYPE to 0, 1, or 2!");
4908
4909 /* Advection parameters... */
4910 ctl->advect = (int) scan_ctl(filename, argc, argv, "ADVECT", -1, "2", NULL);
4911 if (!(ctl->advect == 0 || ctl->advect == 1
4912 || ctl->advect == 2 || ctl->advect == 4))
4913 ERRMSG("Set ADVECT to 0, 1, 2, or 4!");
4914
4915 /* Diffusion parameters... */
4916 ctl->diffusion
4917 = (int) scan_ctl(filename, argc, argv, "DIFFUSION", -1, "0", NULL);
4918 if (ctl->diffusion < 0 || ctl->diffusion > 2)
4919 ERRMSG("Set DIFFUSION to 0, 1 or 2!");
4920 ctl->turb_dx_pbl =
4921 scan_ctl(filename, argc, argv, "TURB_DX_PBL", -1, "50", NULL);
4922 ctl->turb_dx_trop =
4923 scan_ctl(filename, argc, argv, "TURB_DX_TROP", -1, "50", NULL);
4924 ctl->turb_dx_strat =
4925 scan_ctl(filename, argc, argv, "TURB_DX_STRAT", -1, "0", NULL);
4926 ctl->turb_dz_pbl =
4927 scan_ctl(filename, argc, argv, "TURB_DZ_PBL", -1, "0", NULL);
4928 ctl->turb_dz_trop =
4929 scan_ctl(filename, argc, argv, "TURB_DZ_TROP", -1, "0", NULL);
4930 ctl->turb_dz_strat =
4931 scan_ctl(filename, argc, argv, "TURB_DZ_STRAT", -1, "0.1", NULL);
4932 ctl->turb_mesox =
4933 scan_ctl(filename, argc, argv, "TURB_MESOX", -1, "0.16", NULL);
4934 ctl->turb_mesoz =
4935 scan_ctl(filename, argc, argv, "TURB_MESOZ", -1, "0.16", NULL);
4936
4937 /* Convection... */
4938 ctl->conv_mix_pbl
4939 = (int) scan_ctl(filename, argc, argv, "CONV_MIX_PBL", -1, "0", NULL);
4940 ctl->conv_pbl_trans
4941 = scan_ctl(filename, argc, argv, "CONV_PBL_TRANS", -1, "0", NULL);
4942 ctl->conv_cape
4943 = scan_ctl(filename, argc, argv, "CONV_CAPE", -1, "-999", NULL);
4944 ctl->conv_cin
4945 = scan_ctl(filename, argc, argv, "CONV_CIN", -1, "-999", NULL);
4946 ctl->conv_dt = scan_ctl(filename, argc, argv, "CONV_DT", -1, "-999", NULL);
4947
4948 /* Boundary conditions... */
4949 ctl->bound_mass =
4950 scan_ctl(filename, argc, argv, "BOUND_MASS", -1, "-999", NULL);
4951 ctl->bound_mass_trend =
4952 scan_ctl(filename, argc, argv, "BOUND_MASS_TREND", -1, "0", NULL);
4953 ctl->bound_vmr =
4954 scan_ctl(filename, argc, argv, "BOUND_VMR", -1, "-999", NULL);
4955 ctl->bound_vmr_trend =
4956 scan_ctl(filename, argc, argv, "BOUND_VMR_TREND", -1, "0", NULL);
4957 ctl->bound_lat0 =
4958 scan_ctl(filename, argc, argv, "BOUND_LAT0", -1, "-999", NULL);
4959 ctl->bound_lat1 =
4960 scan_ctl(filename, argc, argv, "BOUND_LAT1", -1, "-999", NULL);
4961 ctl->bound_p0 =
4962 scan_ctl(filename, argc, argv, "BOUND_P0", -1, "-999", NULL);
4963 ctl->bound_p1 =
4964 scan_ctl(filename, argc, argv, "BOUND_P1", -1, "-999", NULL);
4965 ctl->bound_dps =
4966 scan_ctl(filename, argc, argv, "BOUND_DPS", -1, "-999", NULL);
4967 ctl->bound_dzs =
4968 scan_ctl(filename, argc, argv, "BOUND_DZS", -1, "-999", NULL);
4969 ctl->bound_zetas =
4970 scan_ctl(filename, argc, argv, "BOUND_ZETAS", -1, "-999", NULL);
4971 ctl->bound_pbl =
4972 (int) scan_ctl(filename, argc, argv, "BOUND_PBL", -1, "0", NULL);
4973
4974 /* Species parameters... */
4975 scan_ctl(filename, argc, argv, "SPECIES", -1, "-", ctl->species);
4976 if (strcasecmp(ctl->species, "CF2Cl2") == 0) {
4977 ctl->molmass = 120.907;
4978 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 3e-5;
4979 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3500.0;
4980 } else if (strcasecmp(ctl->species, "CFCl3") == 0) {
4981 ctl->molmass = 137.359;
4982 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.1e-4;
4983 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3300.0;
4984 } else if (strcasecmp(ctl->species, "CH4") == 0) {
4985 ctl->molmass = 16.043;
4986 ctl->oh_chem_reaction = 2;
4987 ctl->oh_chem[0] = 2.45e-12;
4988 ctl->oh_chem[1] = 1775;
4989 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.4e-5;
4990 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1600.0;
4991 } else if (strcasecmp(ctl->species, "CO") == 0) {
4992 ctl->molmass = 28.01;
4993 ctl->oh_chem_reaction = 3;
4994 ctl->oh_chem[0] = 6.9e-33;
4995 ctl->oh_chem[1] = 2.1;
4996 ctl->oh_chem[2] = 1.1e-12;
4997 ctl->oh_chem[3] = -1.3;
4998 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 9.7e-6;
4999 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1300.0;
5000 } else if (strcasecmp(ctl->species, "CO2") == 0) {
5001 ctl->molmass = 44.009;
5002 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 3.3e-4;
5003 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2400.0;
5004 } else if (strcasecmp(ctl->species, "H2O") == 0) {
5005 ctl->molmass = 18.01528;
5006 } else if (strcasecmp(ctl->species, "N2O") == 0) {
5007 ctl->molmass = 44.013;
5008 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.4e-4;
5009 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2600.;
5010 } else if (strcasecmp(ctl->species, "NH3") == 0) {
5011 ctl->molmass = 17.031;
5012 ctl->oh_chem_reaction = 2;
5013 ctl->oh_chem[0] = 1.7e-12;
5014 ctl->oh_chem[1] = 710;
5015 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 5.9e-1;
5016 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 4200.0;
5017 } else if (strcasecmp(ctl->species, "HNO3") == 0) {
5018 ctl->molmass = 63.012;
5019 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.1e3;
5020 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 8700.0;
5021 } else if (strcasecmp(ctl->species, "NO") == 0) {
5022 ctl->molmass = 30.006;
5023 ctl->oh_chem_reaction = 3;
5024 ctl->oh_chem[0] = 7.1e-31;
5025 ctl->oh_chem[1] = 2.6;
5026 ctl->oh_chem[2] = 3.6e-11;
5027 ctl->oh_chem[3] = 0.1;
5028 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.9e-5;
5029 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1600.0;
5030 } else if (strcasecmp(ctl->species, "NO2") == 0) {
5031 ctl->molmass = 46.005;
5032 ctl->oh_chem_reaction = 3;
5033 ctl->oh_chem[0] = 1.8e-30;
5034 ctl->oh_chem[1] = 3.0;
5035 ctl->oh_chem[2] = 2.8e-11;
5036 ctl->oh_chem[3] = 0.0;
5037 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.2e-4;
5038 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2400.0;
5039 } else if (strcasecmp(ctl->species, "O3") == 0) {
5040 ctl->molmass = 47.997;
5041 ctl->oh_chem_reaction = 2;
5042 ctl->oh_chem[0] = 1.7e-12;
5043 ctl->oh_chem[1] = 940;
5044 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1e-4;
5045 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2800.0;
5046 } else if (strcasecmp(ctl->species, "SF6") == 0) {
5047 ctl->molmass = 146.048;
5048 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.4e-6;
5049 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3100.0;
5050 } else if (strcasecmp(ctl->species, "SO2") == 0) {
5051 ctl->molmass = 64.066;
5052 ctl->oh_chem_reaction = 3;
5053 ctl->oh_chem[0] = 2.9e-31;
5054 ctl->oh_chem[1] = 4.1;
5055 ctl->oh_chem[2] = 1.7e-12;
5056 ctl->oh_chem[3] = -0.2;
5057 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.3e-2;
5058 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2900.0;
5059 }
5060
5061 /* Molar mass... */
5062 char defstr[LEN];
5063 sprintf(defstr, "%g", ctl->molmass);
5064 ctl->molmass = scan_ctl(filename, argc, argv, "MOLMASS", -1, defstr, NULL);
5065
5066 /* OH chemistry... */
5067 sprintf(defstr, "%d", ctl->oh_chem_reaction);
5068 ctl->oh_chem_reaction =
5069 (int) scan_ctl(filename, argc, argv, "OH_CHEM_REACTION", -1, defstr,
5070 NULL);
5071 for (int ip = 0; ip < 4; ip++) {
5072 sprintf(defstr, "%g", ctl->oh_chem[ip]);
5073 ctl->oh_chem[ip] =
5074 scan_ctl(filename, argc, argv, "OH_CHEM", ip, defstr, NULL);
5075 }
5076 ctl->oh_chem_beta =
5077 scan_ctl(filename, argc, argv, "OH_CHEM_BETA", -1, "0", NULL);
5078
5079 /* H2O2 chemistry... */
5080 ctl->h2o2_chem_reaction =
5081 (int) scan_ctl(filename, argc, argv, "H2O2_CHEM_REACTION", -1, "0", NULL);
5082
5083 /* KPP chemistry... */
5084 ctl->kpp_chem =
5085 (int) scan_ctl(filename, argc, argv, "KPP_CHEM", -1, "0", NULL);
5086 ctl->dt_kpp = scan_ctl(filename, argc, argv, "DT_KPP", -1, "1800", NULL);
5087
5088 /* First order tracer chemistry... */
5089 ctl->tracer_chem =
5090 (int) scan_ctl(filename, argc, argv, "TRACER_CHEM", -1, "0", NULL);
5091
5092 /* Wet deposition... */
5093 for (int ip = 0; ip < 2; ip++) {
5094 sprintf(defstr, "%g", ctl->wet_depo_ic_h[ip]);
5095 ctl->wet_depo_ic_h[ip] =
5096 scan_ctl(filename, argc, argv, "WET_DEPO_IC_H", ip, defstr, NULL);
5097 }
5098 for (int ip = 0; ip < 1; ip++) {
5099 sprintf(defstr, "%g", ctl->wet_depo_bc_h[ip]);
5100 ctl->wet_depo_bc_h[ip] =
5101 scan_ctl(filename, argc, argv, "WET_DEPO_BC_H", ip, defstr, NULL);
5102 }
5103 ctl->wet_depo_so2_ph =
5104 scan_ctl(filename, argc, argv, "WET_DEPO_SO2_PH", -1, "0", NULL);
5105 ctl->wet_depo_ic_a =
5106 scan_ctl(filename, argc, argv, "WET_DEPO_IC_A", -1, "0", NULL);
5107 ctl->wet_depo_ic_b =
5108 scan_ctl(filename, argc, argv, "WET_DEPO_IC_B", -1, "0", NULL);
5109 ctl->wet_depo_bc_a =
5110 scan_ctl(filename, argc, argv, "WET_DEPO_BC_A", -1, "0", NULL);
5111 ctl->wet_depo_bc_b =
5112 scan_ctl(filename, argc, argv, "WET_DEPO_BC_B", -1, "0", NULL);
5113 ctl->wet_depo_pre[0] =
5114 scan_ctl(filename, argc, argv, "WET_DEPO_PRE", 0, "0.5", NULL);
5115 ctl->wet_depo_pre[1] =
5116 scan_ctl(filename, argc, argv, "WET_DEPO_PRE", 1, "0.36", NULL);
5118 scan_ctl(filename, argc, argv, "WET_DEPO_IC_RET_RATIO", -1, "1", NULL);
5120 scan_ctl(filename, argc, argv, "WET_DEPO_BC_RET_RATIO", -1, "1", NULL);
5121
5122 /* Dry deposition... */
5123 ctl->dry_depo_vdep =
5124 scan_ctl(filename, argc, argv, "DRY_DEPO_VDEP", -1, "0", NULL);
5125 ctl->dry_depo_dp =
5126 scan_ctl(filename, argc, argv, "DRY_DEPO_DP", -1, "30", NULL);
5127
5128 /* Climatological data... */
5129 scan_ctl(filename, argc, argv, "CLIM_PHOTO", -1,
5130 "../../data/clams_photolysis_rates.nc", ctl->clim_photo);
5131 scan_ctl(filename, argc, argv, "CLIM_HNO3_FILENAME", -1,
5132 "../../data/gozcards_HNO3.nc", ctl->clim_hno3_filename);
5133 scan_ctl(filename, argc, argv, "CLIM_OH_FILENAME", -1,
5134 "../../data/clams_radical_species_vmr.nc", ctl->clim_oh_filename);
5135 scan_ctl(filename, argc, argv, "CLIM_H2O2_FILENAME", -1,
5136 "../../data/cams_H2O2.nc", ctl->clim_h2o2_filename);
5137 scan_ctl(filename, argc, argv, "CLIM_HO2_FILENAME", -1,
5138 "../../data/clams_radical_species_vmr.nc", ctl->clim_ho2_filename);
5139 scan_ctl(filename, argc, argv, "CLIM_O1D_FILENAME", -1,
5140 "../../data/clams_radical_species_vmr.nc", ctl->clim_o1d_filename);
5141 scan_ctl(filename, argc, argv, "CLIM_CCL4_TIMESERIES", -1,
5142 "../../data/noaa_gml_ccl4.tab", ctl->clim_ccl4_timeseries);
5143 scan_ctl(filename, argc, argv, "CLIM_CCL3F_TIMESERIES", -1,
5144 "../../data/noaa_gml_cfc11.tab", ctl->clim_ccl3f_timeseries);
5145 scan_ctl(filename, argc, argv, "CLIM_CCL2F2_TIMESERIES", -1,
5146 "../../data/noaa_gml_cfc12.tab", ctl->clim_ccl2f2_timeseries);
5147 scan_ctl(filename, argc, argv, "CLIM_N2O_TIMESERIES", -1,
5148 "../../data/noaa_gml_n2o.tab", ctl->clim_n2o_timeseries);
5149 scan_ctl(filename, argc, argv, "CLIM_SF6_TIMESERIES", -1,
5150 "../../data/noaa_gml_sf6.tab", ctl->clim_sf6_timeseries);
5151
5152 /* Mixing... */
5153 ctl->mixing_dt =
5154 scan_ctl(filename, argc, argv, "MIXING_DT", -1, "3600.", NULL);
5155 ctl->mixing_trop =
5156 scan_ctl(filename, argc, argv, "MIXING_TROP", -1, "-999", NULL);
5157 ctl->mixing_strat =
5158 scan_ctl(filename, argc, argv, "MIXING_STRAT", -1, "-999", NULL);
5159 ctl->mixing_z0 =
5160 scan_ctl(filename, argc, argv, "MIXING_Z0", -1, "-5", NULL);
5161 ctl->mixing_z1 =
5162 scan_ctl(filename, argc, argv, "MIXING_Z1", -1, "85", NULL);
5163 ctl->mixing_nz =
5164 (int) scan_ctl(filename, argc, argv, "MIXING_NZ", -1, "90", NULL);
5165 ctl->mixing_lon0 =
5166 scan_ctl(filename, argc, argv, "MIXING_LON0", -1, "-180", NULL);
5167 ctl->mixing_lon1 =
5168 scan_ctl(filename, argc, argv, "MIXING_LON1", -1, "180", NULL);
5169 ctl->mixing_nx =
5170 (int) scan_ctl(filename, argc, argv, "MIXING_NX", -1, "360", NULL);
5171 ctl->mixing_lat0 =
5172 scan_ctl(filename, argc, argv, "MIXING_LAT0", -1, "-90", NULL);
5173 ctl->mixing_lat1 =
5174 scan_ctl(filename, argc, argv, "MIXING_LAT1", -1, "90", NULL);
5175 ctl->mixing_ny =
5176 (int) scan_ctl(filename, argc, argv, "MIXING_NY", -1, "180", NULL);
5177
5178 /* Chemistry grid... */
5179 ctl->chemgrid_z0 =
5180 scan_ctl(filename, argc, argv, "CHEMGRID_Z0", -1, "-5", NULL);
5181 ctl->chemgrid_z1 =
5182 scan_ctl(filename, argc, argv, "CHEMGRID_Z1", -1, "85", NULL);
5183 ctl->chemgrid_nz =
5184 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NZ", -1, "90", NULL);
5185 ctl->chemgrid_lon0 =
5186 scan_ctl(filename, argc, argv, "CHEMGRID_LON0", -1, "-180", NULL);
5187 ctl->chemgrid_lon1 =
5188 scan_ctl(filename, argc, argv, "CHEMGRID_LON1", -1, "180", NULL);
5189 ctl->chemgrid_nx =
5190 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NX", -1, "360", NULL);
5191 ctl->chemgrid_lat0 =
5192 scan_ctl(filename, argc, argv, "CHEMGRID_LAT0", -1, "-90", NULL);
5193 ctl->chemgrid_lat1 =
5194 scan_ctl(filename, argc, argv, "CHEMGRID_LAT1", -1, "90", NULL);
5195 ctl->chemgrid_ny =
5196 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NY", -1, "180", NULL);
5197
5198 /* Exponential decay... */
5199 ctl->tdec_trop = scan_ctl(filename, argc, argv, "TDEC_TROP", -1, "0", NULL);
5200 ctl->tdec_strat
5201 = scan_ctl(filename, argc, argv, "TDEC_STRAT", -1, "0", NULL);
5202
5203 /* PSC analysis... */
5204 ctl->psc_h2o = scan_ctl(filename, argc, argv, "PSC_H2O", -1, "4e-6", NULL);
5205 ctl->psc_hno3 =
5206 scan_ctl(filename, argc, argv, "PSC_HNO3", -1, "9e-9", NULL);
5207
5208 /* Output of atmospheric data... */
5209 scan_ctl(filename, argc, argv, "ATM_BASENAME", -1, "-", ctl->atm_basename);
5210 scan_ctl(filename, argc, argv, "ATM_GPFILE", -1, "-", ctl->atm_gpfile);
5211 ctl->atm_dt_out =
5212 scan_ctl(filename, argc, argv, "ATM_DT_OUT", -1, "86400", NULL);
5213 ctl->atm_filter =
5214 (int) scan_ctl(filename, argc, argv, "ATM_FILTER", -1, "0", NULL);
5215 ctl->atm_stride =
5216 (int) scan_ctl(filename, argc, argv, "ATM_STRIDE", -1, "1", NULL);
5217 ctl->atm_type =
5218 (int) scan_ctl(filename, argc, argv, "ATM_TYPE", -1, "0", NULL);
5219 ctl->atm_type_out =
5220 (int) scan_ctl(filename, argc, argv, "ATM_TYPE_OUT", -1, "-1", NULL);
5221 if (ctl->atm_type_out == -1)
5222 ctl->atm_type_out = ctl->atm_type;
5223 ctl->atm_nc_level =
5224 (int) scan_ctl(filename, argc, argv, "ATM_NC_LEVEL", -1, "0", NULL);
5225 for (int iq = 0; iq < ctl->nq; iq++)
5226 ctl->atm_nc_quant[iq] =
5227 (int) scan_ctl(filename, argc, argv, "ATM_NC_QUANT", iq, "0", NULL);
5228 ctl->obs_type =
5229 (int) scan_ctl(filename, argc, argv, "OBS_TYPE", -1, "0", NULL);
5230
5231 /* Output of CSI data... */
5232 scan_ctl(filename, argc, argv, "CSI_BASENAME", -1, "-", ctl->csi_basename);
5233 scan_ctl(filename, argc, argv, "CSI_KERNEL", -1, "-", ctl->csi_kernel);
5234 ctl->csi_dt_out =
5235 scan_ctl(filename, argc, argv, "CSI_DT_OUT", -1, "86400", NULL);
5236 scan_ctl(filename, argc, argv, "CSI_OBSFILE", -1, "-", ctl->csi_obsfile);
5237 ctl->csi_obsmin =
5238 scan_ctl(filename, argc, argv, "CSI_OBSMIN", -1, "0", NULL);
5239 ctl->csi_modmin =
5240 scan_ctl(filename, argc, argv, "CSI_MODMIN", -1, "0", NULL);
5241 ctl->csi_z0 = scan_ctl(filename, argc, argv, "CSI_Z0", -1, "-5", NULL);
5242 ctl->csi_z1 = scan_ctl(filename, argc, argv, "CSI_Z1", -1, "85", NULL);
5243 ctl->csi_nz = (int) scan_ctl(filename, argc, argv, "CSI_NZ", -1, "1", NULL);
5244 ctl->csi_lon0 =
5245 scan_ctl(filename, argc, argv, "CSI_LON0", -1, "-180", NULL);
5246 ctl->csi_lon1 = scan_ctl(filename, argc, argv, "CSI_LON1", -1, "180", NULL);
5247 ctl->csi_nx =
5248 (int) scan_ctl(filename, argc, argv, "CSI_NX", -1, "360", NULL);
5249 ctl->csi_lat0 = scan_ctl(filename, argc, argv, "CSI_LAT0", -1, "-90", NULL);
5250 ctl->csi_lat1 = scan_ctl(filename, argc, argv, "CSI_LAT1", -1, "90", NULL);
5251 ctl->csi_ny =
5252 (int) scan_ctl(filename, argc, argv, "CSI_NY", -1, "180", NULL);
5253
5254 /* Output of ensemble data... */
5255 scan_ctl(filename, argc, argv, "ENS_BASENAME", -1, "-", ctl->ens_basename);
5256 ctl->ens_dt_out =
5257 scan_ctl(filename, argc, argv, "ENS_DT_OUT", -1, "86400", NULL);
5258
5259 /* Output of grid data... */
5260 scan_ctl(filename, argc, argv, "GRID_BASENAME", -1, "-",
5261 ctl->grid_basename);
5262 scan_ctl(filename, argc, argv, "GRID_KERNEL", -1, "-", ctl->grid_kernel);
5263 scan_ctl(filename, argc, argv, "GRID_GPFILE", -1, "-", ctl->grid_gpfile);
5264 ctl->grid_dt_out =
5265 scan_ctl(filename, argc, argv, "GRID_DT_OUT", -1, "86400", NULL);
5266 ctl->grid_sparse =
5267 (int) scan_ctl(filename, argc, argv, "GRID_SPARSE", -1, "0", NULL);
5268 ctl->grid_nc_level =
5269 (int) scan_ctl(filename, argc, argv, "GRID_NC_LEVEL", -1, "0", NULL);
5270 for (int iq = 0; iq < ctl->nq; iq++)
5271 ctl->grid_nc_quant[iq] =
5272 (int) scan_ctl(filename, argc, argv, "GRID_NC_QUANT", iq, "0", NULL);
5273 ctl->grid_stddev =
5274 (int) scan_ctl(filename, argc, argv, "GRID_STDDEV", -1, "0", NULL);
5275 ctl->grid_z0 = scan_ctl(filename, argc, argv, "GRID_Z0", -1, "-5", NULL);
5276 ctl->grid_z1 = scan_ctl(filename, argc, argv, "GRID_Z1", -1, "85", NULL);
5277 ctl->grid_nz =
5278 (int) scan_ctl(filename, argc, argv, "GRID_NZ", -1, "1", NULL);
5279 ctl->grid_lon0 =
5280 scan_ctl(filename, argc, argv, "GRID_LON0", -1, "-180", NULL);
5281 ctl->grid_lon1 =
5282 scan_ctl(filename, argc, argv, "GRID_LON1", -1, "180", NULL);
5283 ctl->grid_nx =
5284 (int) scan_ctl(filename, argc, argv, "GRID_NX", -1, "360", NULL);
5285 ctl->grid_lat0 =
5286 scan_ctl(filename, argc, argv, "GRID_LAT0", -1, "-90", NULL);
5287 ctl->grid_lat1 =
5288 scan_ctl(filename, argc, argv, "GRID_LAT1", -1, "90", NULL);
5289 ctl->grid_ny =
5290 (int) scan_ctl(filename, argc, argv, "GRID_NY", -1, "180", NULL);
5291 ctl->grid_type =
5292 (int) scan_ctl(filename, argc, argv, "GRID_TYPE", -1, "0", NULL);
5293
5294 /* Output of profile data... */
5295 scan_ctl(filename, argc, argv, "PROF_BASENAME", -1, "-",
5296 ctl->prof_basename);
5297 scan_ctl(filename, argc, argv, "PROF_OBSFILE", -1, "-", ctl->prof_obsfile);
5298 ctl->prof_z0 = scan_ctl(filename, argc, argv, "PROF_Z0", -1, "0", NULL);
5299 ctl->prof_z1 = scan_ctl(filename, argc, argv, "PROF_Z1", -1, "60", NULL);
5300 ctl->prof_nz =
5301 (int) scan_ctl(filename, argc, argv, "PROF_NZ", -1, "60", NULL);
5302 ctl->prof_lon0 =
5303 scan_ctl(filename, argc, argv, "PROF_LON0", -1, "-180", NULL);
5304 ctl->prof_lon1 =
5305 scan_ctl(filename, argc, argv, "PROF_LON1", -1, "180", NULL);
5306 ctl->prof_nx =
5307 (int) scan_ctl(filename, argc, argv, "PROF_NX", -1, "360", NULL);
5308 ctl->prof_lat0 =
5309 scan_ctl(filename, argc, argv, "PROF_LAT0", -1, "-90", NULL);
5310 ctl->prof_lat1 =
5311 scan_ctl(filename, argc, argv, "PROF_LAT1", -1, "90", NULL);
5312 ctl->prof_ny =
5313 (int) scan_ctl(filename, argc, argv, "PROF_NY", -1, "180", NULL);
5314
5315 /* Output of sample data... */
5316 scan_ctl(filename, argc, argv, "SAMPLE_BASENAME", -1, "-",
5317 ctl->sample_basename);
5318 scan_ctl(filename, argc, argv, "SAMPLE_KERNEL", -1, "-",
5319 ctl->sample_kernel);
5320 scan_ctl(filename, argc, argv, "SAMPLE_OBSFILE", -1, "-",
5321 ctl->sample_obsfile);
5322 ctl->sample_dx =
5323 scan_ctl(filename, argc, argv, "SAMPLE_DX", -1, "50", NULL);
5324 ctl->sample_dz =
5325 scan_ctl(filename, argc, argv, "SAMPLE_DZ", -1, "-999", NULL);
5326
5327 /* Output of station data... */
5328 scan_ctl(filename, argc, argv, "STAT_BASENAME", -1, "-",
5329 ctl->stat_basename);
5330 ctl->stat_lon = scan_ctl(filename, argc, argv, "STAT_LON", -1, "0", NULL);
5331 ctl->stat_lat = scan_ctl(filename, argc, argv, "STAT_LAT", -1, "0", NULL);
5332 ctl->stat_r = scan_ctl(filename, argc, argv, "STAT_R", -1, "50", NULL);
5333 ctl->stat_t0 =
5334 scan_ctl(filename, argc, argv, "STAT_T0", -1, "-1e100", NULL);
5335 ctl->stat_t1 = scan_ctl(filename, argc, argv, "STAT_T1", -1, "1e100", NULL);
5336
5337 /* Output of VTK data... */
5338 scan_ctl(filename, argc, argv, "VTK_BASENAME", -1, "-", ctl->vtk_basename);
5339 ctl->vtk_dt_out =
5340 scan_ctl(filename, argc, argv, "VTK_DT_OUT", -1, "86400", NULL);
5341 ctl->vtk_stride =
5342 (int) scan_ctl(filename, argc, argv, "VTK_STRIDE", -1, "1", NULL);
5343 ctl->vtk_scale =
5344 scan_ctl(filename, argc, argv, "VTK_SCALE", -1, "1.0", NULL);
5345 ctl->vtk_offset =
5346 scan_ctl(filename, argc, argv, "VTK_OFFSET", -1, "0.0", NULL);
5347 ctl->vtk_sphere =
5348 (int) scan_ctl(filename, argc, argv, "VTK_SPHERE", -1, "0", NULL);
5349}
void level_definitions(ctl_t *ctl)
Defines pressure levels for meteorological data.
Definition: mptrac.c:1760
double scan_ctl(const char *filename, int argc, char *argv[], const char *varname, const int arridx, const char *defvalue, char *value)
Scans a control file or command-line arguments for a specified variable.
Definition: mptrac.c:8846
#define NQ
Maximum number of quantities per data point.
Definition: mptrac.h:251
#define SET_QNT(qnt, name, longname, unit)
Set atmospheric quantity index.
Definition: mptrac.h:1523
double grid_z0
Lower altitude of gridded data [km].
Definition: mptrac.h:3016
int qnt_o3
Quantity array index for ozone volume mixing ratio.
Definition: mptrac.h:2270
double csi_lat1
Upper latitude of gridded CSI data [deg].
Definition: mptrac.h:2980
char csi_obsfile[LEN]
Observation data file for CSI analysis.
Definition: mptrac.h:2947
int qnt_pel
Quantity array index for pressure at equilibrium level (EL).
Definition: mptrac.h:2303
int csi_nz
Number of altitudes of gridded CSI data.
Definition: mptrac.h:2956
int qnt_p
Quantity array index for pressure.
Definition: mptrac.h:2249
char atm_gpfile[LEN]
Gnuplot file for atmospheric data.
Definition: mptrac.h:2908
int qnt_swc
Quantity array index for cloud snow water content.
Definition: mptrac.h:2282
double csi_obsmin
Minimum observation index to trigger detection.
Definition: mptrac.h:2950
int qnt_pcb
Quantity array index for cloud bottom pressure.
Definition: mptrac.h:2291
double csi_lon1
Upper longitude of gridded CSI data [deg].
Definition: mptrac.h:2971
int qnt_u
Quantity array index for zonal wind.
Definition: mptrac.h:2258
double stat_lon
Longitude of station [deg].
Definition: mptrac.h:3094
double sort_dt
Time step for sorting of particle data [s].
Definition: mptrac.h:2630
double stat_r
Search radius around station [km].
Definition: mptrac.h:3100
int csi_ny
Number of latitudes of gridded CSI data.
Definition: mptrac.h:2974
int vtk_sphere
Spherical projection for VTK data (0=no, 1=yes).
Definition: mptrac.h:3124
double met_pbl_min
Minimum depth of planetary boundary layer [km].
Definition: mptrac.h:2598
int qnt_iwc
Quantity array index for cloud ice water content.
Definition: mptrac.h:2279
int qnt_pw
Quantity array index for partial water vapor pressure.
Definition: mptrac.h:2357
char prof_basename[LEN]
Basename for profile output file.
Definition: mptrac.h:3043
double grid_z1
Upper altitude of gridded data [km].
Definition: mptrac.h:3019
double met_dt_out
Time step for sampling of meteo data along trajectories [s].
Definition: mptrac.h:2617
int qnt_h2o2
Quantity array index for H2O2 volume mixing ratio (climatology).
Definition: mptrac.h:2321
int qnt_vh
Quantity array index for horizontal wind.
Definition: mptrac.h:2384
char species[LEN]
Species.
Definition: mptrac.h:2727
int csi_nx
Number of longitudes of gridded CSI data.
Definition: mptrac.h:2965
double csi_lat0
Lower latitude of gridded CSI data [deg].
Definition: mptrac.h:2977
int met_pbl
Planetary boundary layer data (0=file, 1=z2p, 2=Richardson, 3=theta).
Definition: mptrac.h:2595
int qnt_lwc
Quantity array index for cloud liquid water content.
Definition: mptrac.h:2273
int grid_nc_level
zlib compression level of netCDF grid data files (0=off).
Definition: mptrac.h:3004
int grid_nx
Number of longitudes of gridded data.
Definition: mptrac.h:3022
double grid_lat0
Lower latitude of gridded data [deg].
Definition: mptrac.h:3034
int qnt_ts
Quantity array index for surface temperature.
Definition: mptrac.h:2204
int qnt_plfc
Quantity array index for pressure at level of free convection (LCF).
Definition: mptrac.h:2300
double grid_lon0
Lower longitude of gridded data [deg].
Definition: mptrac.h:3025
int qnt_o1d
Quantity array index for O(1D) volume mixing ratio (climatology).
Definition: mptrac.h:2327
int met_tropo_spline
Tropopause interpolation method (0=linear, 1=spline).
Definition: mptrac.h:2614
char sample_kernel[LEN]
Kernel data file for sample output.
Definition: mptrac.h:3079
int qnt_tvirt
Quantity array index for virtual temperature.
Definition: mptrac.h:2378
int met_geopot_sy
Latitudinal smoothing of geopotential heights.
Definition: mptrac.h:2586
char grid_gpfile[LEN]
Gnuplot file for gridded data.
Definition: mptrac.h:2995
int qnt_lsm
Quantity array index for land-sea mask.
Definition: mptrac.h:2225
int qnt_theta
Quantity array index for potential temperature.
Definition: mptrac.h:2369
double stat_t1
Stop time for station output [s].
Definition: mptrac.h:3106
char csi_kernel[LEN]
Kernel data file for CSI output.
Definition: mptrac.h:2941
int grid_type
Type of grid data files (0=ASCII, 1=netCDF).
Definition: mptrac.h:3040
double csi_lon0
Lower longitude of gridded CSI data [deg].
Definition: mptrac.h:2968
int qnt_pbl
Quantity array index for boundary layer pressure.
Definition: mptrac.h:2231
int grid_stddev
Include standard deviations in grid output (0=no, 1=yes).
Definition: mptrac.h:3010
int qnt_psice
Quantity array index for saturation pressure over ice.
Definition: mptrac.h:2354
int met_geopot_sx
Longitudinal smoothing of geopotential heights.
Definition: mptrac.h:2583
int qnt_ps
Quantity array index for surface pressure.
Definition: mptrac.h:2201
char prof_obsfile[LEN]
Observation data file for profile output.
Definition: mptrac.h:3046
int qnt_zs
Quantity array index for surface geopotential height.
Definition: mptrac.h:2207
int prof_nz
Number of altitudes of gridded profile data.
Definition: mptrac.h:3049
double csi_dt_out
Time step for CSI output [s].
Definition: mptrac.h:2944
int met_cape
Convective available potential energy data (0=file, 1=calculate).
Definition: mptrac.h:2592
double csi_modmin
Minimum column density to trigger detection [kg/m^2].
Definition: mptrac.h:2953
char grid_kernel[LEN]
Kernel data file for grid output.
Definition: mptrac.h:2992
double prof_z0
Lower altitude of gridded profile data [km].
Definition: mptrac.h:3052
int qnt_w
Quantity array index for vertical velocity.
Definition: mptrac.h:2264
double met_tropo_pv
Dynamical tropopause potential vorticity threshold [PVU].
Definition: mptrac.h:2608
int prof_nx
Number of longitudes of gridded profile data.
Definition: mptrac.h:3058
int qnt_stat
Quantity array index for station flag.
Definition: mptrac.h:2186
int met_mpi_share
Use MPI to share meteo (0=no, 1=yes).
Definition: mptrac.h:2623
int qnt_vz
Quantity array index for vertical velocity.
Definition: mptrac.h:2387
int qnt_ho2
Quantity array index for HO2 volume mixing ratio (climatology).
Definition: mptrac.h:2324
double csi_z1
Upper altitude of gridded CSI data [km].
Definition: mptrac.h:2962
double stat_t0
Start time for station output [s].
Definition: mptrac.h:3103
int atm_type_out
Type of atmospheric data files for output (-1=same as ATM_TYPE, 0=ASCII, 1=binary,...
Definition: mptrac.h:2926
double dt_kpp
Time step for KPP chemistry [s].
Definition: mptrac.h:2853
char csi_basename[LEN]
Basename of CSI data files.
Definition: mptrac.h:2938
int qnt_shf
Quantity array index for surface sensible heat flux.
Definition: mptrac.h:2222
int qnt_vs
Quantity array index for surface meridional wind.
Definition: mptrac.h:2213
double vtk_dt_out
Time step for VTK data output [s].
Definition: mptrac.h:3112
double conv_dt
Time interval for convection module [s].
Definition: mptrac.h:2688
char sample_obsfile[LEN]
Observation data file for sample output.
Definition: mptrac.h:3082
int qnt_hno3
Quantity array index for HNO3 volume mixing ratio (climatology).
Definition: mptrac.h:2315
char grid_basename[LEN]
Basename of grid data files.
Definition: mptrac.h:2989
int qnt_h2ot
Quantity array index for tropopause water vapor volume mixing ratio.
Definition: mptrac.h:2243
int qnt_rh
Quantity array index for relative humidity over water.
Definition: mptrac.h:2363
double met_pbl_max
Maximum depth of planetary boundary layer [km].
Definition: mptrac.h:2601
int qnt_zeta_d
Quantity array index for diagnosed zeta vertical coordinate.
Definition: mptrac.h:2375
int tracer_chem
Switch for first order tracer chemistry module (0=off, 1=on).
Definition: mptrac.h:2856
int diffusion
Diffusion scheme (0=off, 1=fixed-K, 2=PBL).
Definition: mptrac.h:2649
int qnt_zg
Quantity array index for geopotential height.
Definition: mptrac.h:2246
double vtk_offset
Vertical offset for VTK data [km].
Definition: mptrac.h:3121
int qnt_v
Quantity array index for meridional wind.
Definition: mptrac.h:2261
int qnt_oh
Quantity array index for OH volume mixing ratio (climatology).
Definition: mptrac.h:2318
int qnt_h2o
Quantity array index for water vapor volume mixing ratio.
Definition: mptrac.h:2267
int prof_ny
Number of latitudes of gridded profile data.
Definition: mptrac.h:3067
int qnt_rhice
Quantity array index for relative humidity over ice.
Definition: mptrac.h:2366
int qnt_rho
Quantity array index for density of air.
Definition: mptrac.h:2255
double sample_dz
Layer depth for sample output [km].
Definition: mptrac.h:3088
int obs_type
Type of observation data files (0=ASCII, 1=netCDF).
Definition: mptrac.h:2935
int grid_nc_quant[NQ]
Number of digits for quantization of netCDF grid data files (0=off).
Definition: mptrac.h:3007
int qnt_us
Quantity array index for surface zonal wind.
Definition: mptrac.h:2210
double grid_lon1
Upper longitude of gridded data [deg].
Definition: mptrac.h:3028
char atm_basename[LEN]
Basename of atmospheric data files.
Definition: mptrac.h:2905
int qnt_pt
Quantity array index for tropopause pressure.
Definition: mptrac.h:2234
int qnt_cl
Quantity array index for total column cloud water.
Definition: mptrac.h:2294
double prof_z1
Upper altitude of gridded profile data [km].
Definition: mptrac.h:3055
int qnt_t
Quantity array index for temperature.
Definition: mptrac.h:2252
int atm_filter
Time filter for atmospheric data output (0=none, 1=missval, 2=remove).
Definition: mptrac.h:2914
int kpp_chem
Switch for KPP chemistry module (0=off, 1=on).
Definition: mptrac.h:2850
char ens_basename[LEN]
Basename of ensemble data file.
Definition: mptrac.h:2983
double csi_z0
Lower altitude of gridded CSI data [km].
Definition: mptrac.h:2959
int qnt_lapse
Quantity array index for lapse rate.
Definition: mptrac.h:2381
double stat_lat
Latitude of station [deg].
Definition: mptrac.h:3097
int grid_ny
Number of latitudes of gridded data.
Definition: mptrac.h:3031
int qnt_cape
Quantity array index for convective available potential energy (CAPE).
Definition: mptrac.h:2306
int qnt_o3c
Quantity array index for total column ozone.
Definition: mptrac.h:2312
int grid_nz
Number of altitudes of gridded data.
Definition: mptrac.h:3013
int qnt_nss
Quantity array index for northward turbulent surface stress.
Definition: mptrac.h:2219
double ens_dt_out
Time step for ensemble output [s].
Definition: mptrac.h:2986
char sample_basename[LEN]
Basename of sample data file.
Definition: mptrac.h:3076
int atm_stride
Particle index stride for atmospheric data files.
Definition: mptrac.h:2917
int met_relhum
Try to read relative humidity (0=no, 1=yes).
Definition: mptrac.h:2589
double atm_dt_out
Time step for atmospheric data output [s].
Definition: mptrac.h:2911
double prof_lat1
Upper latitude of gridded profile data [deg].
Definition: mptrac.h:3073
double psc_h2o
H2O volume mixing ratio for PSC analysis.
Definition: mptrac.h:2895
double prof_lon0
Lower longitude of gridded profile data [deg].
Definition: mptrac.h:3061
int qnt_pct
Quantity array index for cloud top pressure.
Definition: mptrac.h:2288
int qnt_mloss_kpp
Quantity array index for total mass loss due to KPP chemistry.
Definition: mptrac.h:2336
int qnt_psat
Quantity array index for saturation pressure over water.
Definition: mptrac.h:2351
double prof_lat0
Lower latitude of gridded profile data [deg].
Definition: mptrac.h:3070
int qnt_cin
Quantity array index for convective inhibition (CIN).
Definition: mptrac.h:2309
double psc_hno3
HNO3 volume mixing ratio for PSC analysis.
Definition: mptrac.h:2898
double prof_lon1
Upper longitude of gridded profile data [deg].
Definition: mptrac.h:3064
int h2o2_chem_reaction
Reaction type for H2O2 chemistry (0=none, 1=SO2).
Definition: mptrac.h:2847
int atm_nc_quant[NQ]
Number of digits for quantization of netCDF atmospheric data files (0=off).
Definition: mptrac.h:2932
int grid_sparse
Sparse output in grid data files (0=no, 1=yes).
Definition: mptrac.h:3001
char vtk_basename[LEN]
Basename of VTK data files.
Definition: mptrac.h:3109
int qnt_tt
Quantity array index for tropopause temperature.
Definition: mptrac.h:2237
int qnt_ens
Quantity array index for ensemble IDs.
Definition: mptrac.h:2183
double mixing_dt
Time interval for mixing [s].
Definition: mptrac.h:2775
double vtk_scale
Vertical scaling factor for VTK data.
Definition: mptrac.h:3118
int qnt_pv
Quantity array index for potential vorticity.
Definition: mptrac.h:2390
int qnt_sst
Quantity array index for sea surface temperature.
Definition: mptrac.h:2228
int atm_nc_level
zlib compression level of netCDF atmospheric data files (0=off).
Definition: mptrac.h:2929
int qnt_sh
Quantity array index for specific humidity.
Definition: mptrac.h:2360
int qnt_ess
Quantity array index for eastward turbulent surface stress.
Definition: mptrac.h:2216
int qnt_idx
Quantity array index for air parcel IDs.
Definition: mptrac.h:2180
double met_tropo_theta
Dynamical tropopause potential temperature threshold [K].
Definition: mptrac.h:2611
int qnt_rwc
Quantity array index for cloud rain water content.
Definition: mptrac.h:2276
char qnt_longname[NQ][LEN]
Quantity long names.
Definition: mptrac.h:2171
double sample_dx
Horizontal radius for sample output [km].
Definition: mptrac.h:3085
int vtk_stride
Particle index stride for VTK data.
Definition: mptrac.h:3115
char stat_basename[LEN]
Basename of station data file.
Definition: mptrac.h:3091
double grid_lat1
Upper latitude of gridded data [deg].
Definition: mptrac.h:3037
int qnt_zt
Quantity array index for tropopause geopotential height.
Definition: mptrac.h:2240
int qnt_cc
Quantity array index for cloud cover.
Definition: mptrac.h:2285
int qnt_plcl
Quantity array index for pressure at lifted condensation level (LCL).
Definition: mptrac.h:2297
double grid_dt_out
Time step for gridded data output [s].
Definition: mptrac.h:2998
int qnt_tdew
Quantity array index for dew point temperature.
Definition: mptrac.h:2393
Here is the call graph for this function:

◆ mptrac_read_met()

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

Reads meteorological data from a file, supporting multiple formats and MPI broadcasting.

This function reads meteorological data from a file specified by the filename parameter. It supports both NetCDF and binary formats based on the met_type field in the ctl_t structure. The function can also handle parallel processing with MPI, broadcasting the data across ranks if required by the configuration.

Parameters
filenameA constant character pointer representing the name of the file to read the meteorological data from.
ctlA pointer to a ctl_t structure, which holds control parameters including the type of meteorological data, MPI sharing flags, and configuration details.
climA pointer to a clim_t structure, which contains climatological data to be used in the process, if applicable.
metA pointer to a met_t structure that will store the meteorological data read from the file.
Returns
Returns an integer, where 1 indicates success.
Note
  • The function logs the action of reading meteorological data, including the file name.
  • It supports MPI parallelization and will share the data across multiple processes if the met_mpi_share flag is set in the control structure.
  • If ctl->met_type is 0, the data is read from a NetCDF file using the read_met_nc function.
  • If ctl->met_type is between 1 and 5, the data is read from a binary file using the read_met_bin function.
  • If the met_type is not recognized, an error message is generated.
Author
Lars Hoffmann

Definition at line 5353 of file mptrac.c.

5357 {
5358
5359 /* Write info... */
5360 LOG(1, "Read meteo data: %s", filename);
5361
5362 /* Set rank... */
5363 int rank = 0;
5364#ifdef MPI
5365 if (ctl->met_mpi_share)
5366 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5367#endif
5368
5369 /* Check rank... */
5370 if (!ctl->met_mpi_share || rank == 0) {
5371
5372 /* Read netCDF data... */
5373 if (ctl->met_type == 0) {
5374 if (read_met_nc(filename, ctl, clim, met) != 1)
5375 return 0;
5376 }
5377
5378 /* Read binary data... */
5379 else if (ctl->met_type >= 1 && ctl->met_type <= 5) {
5380 if (read_met_bin(filename, ctl, met) != 1)
5381 return 0;
5382 }
5383
5384 /* Not implemented... */
5385 else
5386 ERRMSG("MET_TYPE not implemented!");
5387 }
5388
5389 /* Broadcast data via MPI... */
5390#ifdef MPI
5391 if (ctl->met_mpi_share) {
5392
5393 /* Set timer... */
5394 SELECT_TIMER("READ_MET_MPI_BCAST", "COMM", NVTX_SEND);
5395 LOG(2, "Broadcast data on rank %d...", rank);
5396
5397 /* Broadcast... */
5398 broadcast_large_data(met, sizeof(met_t));
5399 }
5400#endif
5401
5402 /* Return success... */
5403 return 1;
5404}
int read_met_nc(const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met)
Reads meteorological data from a NetCDF file and processes it.
Definition: mptrac.c:7497
int read_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a binary file.
Definition: mptrac.c:6394
void broadcast_large_data(void *data, size_t N)
Broadcasts large data across all processes in an MPI communicator.
Here is the call graph for this function:

◆ mptrac_run_timestep()

void mptrac_run_timestep ( ctl_t ctl,
cache_t cache,
clim_t clim,
met_t **  met0,
met_t **  met1,
atm_t atm,
double  t 
)

Executes a single timestep of the MPTRAC model simulation.

This function performs all operations required to advance the model simulation by one timestep. It includes updating air parcel positions, applying advection, diffusion, convection, and other processes such as sedimentation, chemistry, and deposition. Each process is conditionally executed based on the control settings provided in the ctl structure.

Parameters
ctlPointer to the control structure containing model parameters and settings.
cachePointer to the cache structure used for intermediate calculations.
climPointer to the climatology structure containing climatological data.
met0Pointer to the current meteorological data structure.
met1Pointer to the next meteorological data structure.
atmPointer to the atmosphere structure containing air parcel data.
tCurrent simulation time in seconds.
Authors
Lars Hoffmann

Definition at line 5408 of file mptrac.c.

5415 {
5416
5417 /* Initialize modules... */
5418 if (t == ctl->t_start) {
5419
5420 /* Initialize isosurface data... */
5421 if (ctl->isosurf >= 1 && ctl->isosurf <= 4)
5422 module_isosurf_init(ctl, cache, *met0, *met1, atm);
5423
5424 /* Initialize advection... */
5425 module_advect_init(ctl, cache, *met0, *met1, atm);
5426
5427 /* Initialize chemistry... */
5428 module_chem_init(ctl, cache, clim, *met0, *met1, atm);
5429 }
5430
5431 /* Set time steps of air parcels... */
5432 module_timesteps(ctl, cache, *met0, atm, t);
5433
5434 /* Sort particles... */
5435 if (ctl->sort_dt > 0 && fmod(t, ctl->sort_dt) == 0)
5436 module_sort(ctl, *met0, atm);
5437
5438 /* Check positions (initial)... */
5439 module_position(cache, *met0, *met1, atm);
5440
5441 /* Advection... */
5442 if (ctl->advect > 0)
5443 module_advect(ctl, cache, *met0, *met1, atm);
5444
5445 /* Turbulent diffusion... */
5446 if (ctl->diffusion == 1
5447 && (ctl->turb_dx_pbl > 0 || ctl->turb_dz_pbl > 0
5448 || ctl->turb_dx_trop > 0 || ctl->turb_dz_trop > 0
5449 || ctl->turb_dx_strat > 0 || ctl->turb_dz_strat > 0))
5450 module_diff_turb(ctl, cache, clim, *met0, *met1, atm);
5451
5452 /* Mesoscale diffusion... */
5453 if (ctl->diffusion == 1 && (ctl->turb_mesox > 0 || ctl->turb_mesoz > 0))
5454 module_diff_meso(ctl, cache, *met0, *met1, atm);
5455
5456 /* Diffusion... */
5457 if (ctl->diffusion == 2)
5458 module_diff_pbl(ctl, cache, *met0, *met1, atm);
5459
5460 /* Convection... */
5461 if ((ctl->conv_mix_pbl || ctl->conv_cape >= 0)
5462 && (ctl->conv_dt <= 0 || fmod(t, ctl->conv_dt) == 0))
5463 module_convection(ctl, cache, *met0, *met1, atm);
5464
5465 /* Sedimentation... */
5466 if (ctl->qnt_rp >= 0 && ctl->qnt_rhop >= 0)
5467 module_sedi(ctl, cache, *met0, *met1, atm);
5468
5469 /* Isosurface... */
5470 if (ctl->isosurf >= 1 && ctl->isosurf <= 4)
5471 module_isosurf(ctl, cache, *met0, *met1, atm);
5472
5473 /* Check positions (final)... */
5474 module_position(cache, *met0, *met1, atm);
5475
5476 /* Interpolate meteo data... */
5477 if (ctl->met_dt_out > 0
5478 && (ctl->met_dt_out < ctl->dt_mod || fmod(t, ctl->met_dt_out) == 0))
5479 module_meteo(ctl, cache, clim, *met0, *met1, atm);
5480
5481 /* Check boundary conditions (initial)... */
5482 if ((ctl->bound_lat0 < ctl->bound_lat1)
5483 && (ctl->bound_p0 > ctl->bound_p1))
5484 module_bound_cond(ctl, cache, clim, *met0, *met1, atm);
5485
5486 /* Initialize quantity of total loss rate... */
5487 if (ctl->qnt_loss_rate >= 0) {
5488 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,atm)") {
5489 atm->q[ctl->qnt_loss_rate][ip] = 0;
5490 }
5491 }
5492
5493 /* Decay of particle mass... */
5494 if (ctl->tdec_trop > 0 && ctl->tdec_strat > 0)
5495 module_decay(ctl, cache, clim, atm);
5496
5497 /* Interparcel mixing... */
5498 if (ctl->mixing_trop >= 0 && ctl->mixing_strat >= 0
5499 && (ctl->mixing_dt <= 0 || fmod(t, ctl->mixing_dt) == 0))
5500 module_mixing(ctl, clim, atm, t);
5501
5502 /* Calculate the tracer vmr in the chemistry grid... */
5503 if (ctl->oh_chem_reaction != 0 || ctl->h2o2_chem_reaction != 0
5504 || (ctl->kpp_chem && fmod(t, ctl->dt_kpp) == 0))
5505 module_chem_grid(ctl, *met0, *met1, atm, t);
5506
5507 /* OH chemistry... */
5508 if (ctl->oh_chem_reaction != 0)
5509 module_oh_chem(ctl, cache, clim, *met0, *met1, atm);
5510
5511 /* H2O2 chemistry (for SO2 aqueous phase oxidation)... */
5512 if (ctl->h2o2_chem_reaction != 0)
5513 module_h2o2_chem(ctl, cache, clim, *met0, *met1, atm);
5514
5515 /* First-order tracer chemistry... */
5516 if (ctl->tracer_chem)
5517 module_tracer_chem(ctl, cache, clim, *met0, *met1, atm);
5518
5519 /* KPP chemistry... */
5520 if (ctl->kpp_chem && fmod(t, ctl->dt_kpp) == 0) {
5521#ifdef KPP
5522 module_kpp_chem(ctl, cache, clim, *met0, *met1, atm);
5523#else
5524 ERRMSG("Code was compiled without KPP!");
5525#endif
5526 }
5527
5528 /* Wet deposition... */
5529 if ((ctl->wet_depo_ic_a > 0 || ctl->wet_depo_ic_h[0] > 0)
5530 && (ctl->wet_depo_bc_a > 0 || ctl->wet_depo_bc_h[0] > 0))
5531 module_wet_depo(ctl, cache, *met0, *met1, atm);
5532
5533 /* Dry deposition... */
5534 if (ctl->dry_depo_vdep > 0)
5535 module_dry_depo(ctl, cache, *met0, *met1, atm);
5536
5537 /* Check boundary conditions (final)... */
5538 if ((ctl->bound_lat0 < ctl->bound_lat1)
5539 && (ctl->bound_p0 > ctl->bound_p1))
5540 module_bound_cond(ctl, cache, clim, *met0, *met1, atm);
5541}
void module_advect(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Performs the advection of atmospheric particles using meteorological data.
Definition: mptrac.c:2069
void module_timesteps(const ctl_t *ctl, cache_t *cache, met_t *met0, atm_t *atm, const double t)
Calculate time steps for air parcels based on specified conditions.
Definition: mptrac.c:3914
void module_meteo(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Update atmospheric properties using meteorological data.
Definition: mptrac.c:3227
void module_decay(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, atm_t *atm)
Simulate exponential decay processes for atmospheric particles.
Definition: mptrac.c:2613
void module_chem_init(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Initializes the chemistry modules by setting atmospheric composition.
Definition: mptrac.c:2498
void module_mixing(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const double t)
Update atmospheric properties through interparcel mixing.
Definition: mptrac.c:3331
void module_isosurf_init(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initialize the isosurface module based on atmospheric data.
Definition: mptrac.c:3052
void module_wet_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Perform wet deposition calculations for air parcels.
Definition: mptrac.c:4052
void module_chem_grid(const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double tt)
Calculate grid data for chemistry modules.
Definition: mptrac.c:2351
void module_sedi(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate sedimentation of particles in the atmosphere.
Definition: mptrac.c:3789
void module_convection(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Performs convective mixing of atmospheric particles.
Definition: mptrac.c:2540
void module_bound_cond(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Apply boundary conditions to particles based on meteorological and climatological data.
Definition: mptrac.c:2255
void module_advect_init(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initializes the advection module by setting up pressure fields.
Definition: mptrac.c:2228
void module_position(const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Update the positions and pressure levels of atmospheric particles.
Definition: mptrac.c:3599
void module_diff_meso(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate mesoscale diffusion for atmospheric particles.
Definition: mptrac.c:2652
void module_sort(const ctl_t *ctl, met_t *met0, atm_t *atm)
Sort particles according to box index.
Definition: mptrac.c:3818
void module_diff_turb(const ctl_t *ctl, cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Applies turbulent diffusion processes to atmospheric particles.
Definition: mptrac.c:2854
void module_tracer_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Simulate chemical reactions involving long-lived atmospheric tracers.
Definition: mptrac.c:3982
void module_h2o2_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Perform chemical reactions involving H2O2 within cloud particles.
Definition: mptrac.c:2969
void module_diff_pbl(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Computes particle diffusion within the planetary boundary layer (PBL).
Definition: mptrac.c:2729
void module_isosurf(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Apply the isosurface module to adjust atmospheric properties.
Definition: mptrac.c:3122
void module_oh_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Perform hydroxyl chemistry calculations for atmospheric particles.
Definition: mptrac.c:3515
void module_dry_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate dry deposition of atmospheric particles.
Definition: mptrac.c:2906
void module_kpp_chem(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
KPP chemistry module.
Here is the call graph for this function:

◆ mptrac_write_atm()

void mptrac_write_atm ( const char *  filename,
const ctl_t ctl,
const atm_t atm,
const double  t 
)

Writes air parcel data to a file in various formats.

The mptrac_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 data (atm_type_out == 3): Calls write_atm_clams_traj.
    • CLaMS position data (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 5657 of file mptrac.c.

5661 {
5662
5663 /* Set timer... */
5664 SELECT_TIMER("WRITE_ATM", "OUTPUT", NVTX_WRITE);
5665
5666 /* Write info... */
5667 LOG(1, "Write atmospheric data: %s", filename);
5668
5669 /* Write ASCII data... */
5670 if (ctl->atm_type_out == 0)
5671 write_atm_asc(filename, ctl, atm, t);
5672
5673 /* Write binary data... */
5674 else if (ctl->atm_type_out == 1)
5675 write_atm_bin(filename, ctl, atm);
5676
5677 /* Write netCDF data... */
5678 else if (ctl->atm_type_out == 2)
5679 write_atm_nc(filename, ctl, atm);
5680
5681 /* Write CLaMS trajectory data... */
5682 else if (ctl->atm_type_out == 3)
5683 write_atm_clams_traj(filename, ctl, atm, t);
5684
5685 /* Write CLaMS pos data... */
5686 else if (ctl->atm_type_out == 4)
5687 write_atm_clams(filename, ctl, atm);
5688
5689 /* Error... */
5690 else
5691 ERRMSG("Atmospheric data type not supported!");
5692
5693 /* Write info... */
5694 double mini, maxi;
5695 LOG(2, "Number of particles: %d", atm->np);
5696 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
5697 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
5698 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
5699 LOG(2, "Altitude range: %g ... %g km", Z(maxi), Z(mini));
5700 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
5701 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
5702 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
5703 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
5704 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
5705 for (int iq = 0; iq < ctl->nq; iq++) {
5706 char msg[5 * LEN];
5707 sprintf(msg, "Quantity %s range: %s ... %s %s",
5708 ctl->qnt_name[iq], ctl->qnt_format[iq],
5709 ctl->qnt_format[iq], ctl->qnt_unit[iq]);
5710 gsl_stats_minmax(&mini, &maxi, atm->q[iq], 1, (size_t) atm->np);
5711 LOG(2, msg, mini, maxi);
5712 }
5713}
void write_atm_clams_traj(const char *dirname, const ctl_t *ctl, const atm_t *atm, const double t)
Writes CLaMS trajectory data to a NetCDF file.
Definition: mptrac.c:9402
void write_atm_asc(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes air parcel data to an ASCII file or gnuplot.
Definition: mptrac.c:9217
void write_atm_clams(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a NetCDF file in the CLaMS format.
Definition: mptrac.c:9349
void write_atm_bin(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a binary file.
Definition: mptrac.c:9299
void write_atm_nc(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a NetCDF file.
Definition: mptrac.c:9560
Here is the call graph for this function:

◆ mptrac_write_met()

void mptrac_write_met ( const char *  filename,
const ctl_t ctl,
met_t met 
)

Writes meteorological data to a file, supporting multiple formats and compression options.

This function handles writing meteorological data based on the specified control (ctl_t) and meteorological data (met_t) structures. The file format and compression type are determined by the met_type in the control structure. The function supports netCDF, binary output, and various compression methods (ZFP, ZSTD, CMS), while providing error handling for unsupported configurations.

Parameters
filenameA constant character pointer representing the name of the file to write the meteorological data to.
ctlA pointer to a ctl_t structure, which holds the configuration and control parameters for the output, including the type of meteorological data and compression method.
metA pointer to a met_t structure that holds the meteorological data to be written to the file.
Note
  • The function selects a timer for performance profiling or debugging.
  • It logs the action of writing meteorological data, including the file name.
Warning
  • If ctl->met_type is 3, ZFP compression is required, and the function will generate an error if compiled without ZFP support.
  • If ctl->met_type is 4, ZSTD compression is required, and the function will generate an error if compiled without ZSTD support.
  • If ctl->met_type is 5, CMS compression is required, and the function will generate an error if compiled without CMS support.
Note
  • If ctl->met_type is 0, the function writes data in netCDF format via write_met_nc.
  • If ctl->met_type is between 1 and 5, the function writes data in binary format via write_met_bin.
  • If ctl->met_type is not recognized, an error message is generated.
Author
Lars Hoffmann

Definition at line 5717 of file mptrac.c.

5720 {
5721
5722 /* Set timer... */
5723 SELECT_TIMER("WRITE_MET", "OUTPUT", NVTX_WRITE);
5724
5725 /* Write info... */
5726 LOG(1, "Write meteo data: %s", filename);
5727
5728 /* Check compression flags... */
5729#ifndef ZFP
5730 if (ctl->met_type == 3)
5731 ERRMSG("MPTRAC was compiled without zfp compression!");
5732#endif
5733#ifndef ZSTD
5734 if (ctl->met_type == 4)
5735 ERRMSG("MPTRAC was compiled without zstd compression!");
5736#endif
5737#ifndef CMS
5738 if (ctl->met_type == 5)
5739 ERRMSG("MPTRAC was compiled without cmultiscale compression!");
5740#endif
5741
5742 /* Write netCDF data... */
5743 if (ctl->met_type == 0)
5744 write_met_nc(filename, ctl, met);
5745
5746 /* Write binary data... */
5747 else if (ctl->met_type >= 1 && ctl->met_type <= 5)
5748 write_met_bin(filename, ctl, met);
5749
5750 /* Not implemented... */
5751 else
5752 ERRMSG("MET_TYPE not implemented!");
5753}
void write_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a NetCDF file.
Definition: mptrac.c:10599
void write_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data in binary format to a specified file.
Definition: mptrac.c:10393
Here is the call graph for this function:

◆ mptrac_write_output()

void mptrac_write_output ( const char *  dirname,
const ctl_t ctl,
met_t met0,
met_t met1,
atm_t atm,
const double  t 
)

Writes various types of output data to files in a specified directory.

The mptrac_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 5757 of file mptrac.c.

5763 {
5764
5765 char ext[10], filename[2 * LEN];
5766
5767 double r;
5768
5769 int year, mon, day, hour, min, sec;
5770
5771 /* Get time... */
5772 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
5773
5774 /* Update host... */
5775 if ((ctl->atm_basename[0] != '-' && fmod(t, ctl->atm_dt_out) == 0)
5776 || (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0)
5777 || (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0)
5778 || ctl->csi_basename[0] != '-' || ctl->prof_basename[0] != '-'
5779 || ctl->sample_basename[0] != '-' || ctl->stat_basename[0] != '-'
5780 || (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0))
5781 mptrac_update_host(NULL, NULL, NULL, NULL, NULL, atm);
5782
5783 /* Write atmospheric data... */
5784 if (ctl->atm_basename[0] != '-' &&
5785 (fmod(t, ctl->atm_dt_out) == 0 || t == ctl->t_stop)) {
5786 if (ctl->atm_type_out == 0)
5787 sprintf(ext, "tab");
5788 else if (ctl->atm_type_out == 1)
5789 sprintf(ext, "bin");
5790 else if (ctl->atm_type_out == 2)
5791 sprintf(ext, "nc");
5792 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
5793 dirname, ctl->atm_basename, year, mon, day, hour, min, ext);
5794 mptrac_write_atm(filename, ctl, atm, t);
5795 }
5796
5797 /* Write gridded data... */
5798 if (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0) {
5799 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
5800 dirname, ctl->grid_basename, year, mon, day, hour, min,
5801 ctl->grid_type == 0 ? "tab" : "nc");
5802 write_grid(filename, ctl, met0, met1, atm, t);
5803 }
5804
5805 /* Write CSI data... */
5806 if (ctl->csi_basename[0] != '-') {
5807 sprintf(filename, "%s/%s.tab", dirname, ctl->csi_basename);
5808 write_csi(filename, ctl, atm, t);
5809 }
5810
5811 /* Write ensemble data... */
5812 if (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0) {
5813 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
5814 dirname, ctl->ens_basename, year, mon, day, hour, min);
5815 write_ens(filename, ctl, atm, t);
5816 }
5817
5818 /* Write profile data... */
5819 if (ctl->prof_basename[0] != '-') {
5820 sprintf(filename, "%s/%s.tab", dirname, ctl->prof_basename);
5821 write_prof(filename, ctl, met0, met1, atm, t);
5822 }
5823
5824 /* Write sample data... */
5825 if (ctl->sample_basename[0] != '-') {
5826 sprintf(filename, "%s/%s.tab", dirname, ctl->sample_basename);
5827 write_sample(filename, ctl, met0, met1, atm, t);
5828 }
5829
5830 /* Write station data... */
5831 if (ctl->stat_basename[0] != '-') {
5832 sprintf(filename, "%s/%s.tab", dirname, ctl->stat_basename);
5833 write_station(filename, ctl, atm, t);
5834 }
5835
5836 /* Write VTK data... */
5837 if (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0) {
5838 static int nvtk;
5839 if (t == ctl->t_start)
5840 nvtk = 0;
5841 sprintf(filename, "%s/%s_%05d.vtk", dirname, ctl->vtk_basename, ++nvtk);
5842 write_vtk(filename, ctl, atm, t);
5843 }
5844}
void mptrac_write_atm(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes air parcel data to a file in various formats.
Definition: mptrac.c:5657
void write_ens(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes ensemble data to a file.
Definition: mptrac.c:9871
void write_prof(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes profile data to a specified file.
Definition: mptrac.c:10821
void mptrac_update_host(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates host memory for specified data structures.
Definition: mptrac.c:5601
void write_station(const char *filename, const ctl_t *ctl, atm_t *atm, const double t)
Writes station data to a specified file.
Definition: mptrac.c:11210
void write_vtk(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes VTK (Visualization Toolkit) data to a specified file.
Definition: mptrac.c:11296
void write_sample(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes sample data to a specified file.
Definition: mptrac.c:11048
void write_grid(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes grid data to a file in ASCII or netCDF format.
Definition: mptrac.c:9968
void write_csi(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes Critical Success Index (CSI) data to a file.
Definition: mptrac.c:9609
Here is the call graph for this function:

◆ mptrac_update_device()

void mptrac_update_device ( const ctl_t ctl,
const cache_t cache,
const clim_t clim,
met_t **  met0,
met_t **  met1,
const atm_t atm 
)

Updates device memory for specified data structures.

This function updates the GPU memory with the data from the provided host data structures (ctl, cache, clim, atm) using OpenACC directives. It ensures that the host data is transferred to the device for further computation.

Parameters
[in]ctlPointer to the ctl_t structure. If not NULL, the corresponding device memory for ctl is updated.
[in]cachePointer to the cache_t structure. If not NULL, the corresponding device memory for cache is updated.
[in]climPointer to the clim_t structure. If not NULL, the corresponding device memory for clim is updated.
[in]met0Pointer to the first met_t structure. If not NULL, the corresponding device memory for met0 is updated.
[in]met1Pointer to the second met_t structure. If not NULL, the corresponding device memory for met1 is updated.
[in]atmPointer to the atm_t structure. If not NULL, the corresponding device memory for atm is updated.
Note
The function assumes that OpenACC is enabled and uses the #pragma acc update directive for device memory synchronization. Each update operation is wrapped with a timer labeled as "UPDATE_DEVICE" for performance tracking.
Warning
Ensure that the pointers passed to this function are valid and properly initialized before calling this function. Passing invalid or uninitialized pointers may lead to undefined behavior.
Author
Lars Hoffmann

Definition at line 5545 of file mptrac.c.

5551 {
5552
5553 /* Update GPU... */
5554 if (ctl != NULL) {
5555#ifdef _OPENACC
5556 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5557#pragma acc update device(ctl[:1])
5558#endif
5559 }
5560
5561 if (cache != NULL) {
5562#ifdef _OPENACC
5563 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5564#pragma acc update device(cache[:1])
5565#endif
5566 }
5567
5568 if (clim != NULL) {
5569#ifdef _OPENACC
5570 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5571#pragma acc update device(clim[:1])
5572#endif
5573 }
5574
5575 if (met0 != NULL) {
5576#ifdef _OPENACC
5577 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5578 met_t *met0up = *met0;
5579#pragma acc update device(met0up[:1])
5580#endif
5581 }
5582
5583 if (met1 != NULL) {
5584#ifdef _OPENACC
5585 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5586 met_t *met1up = *met1;
5587#pragma acc update device(met1up[:1])
5588#endif
5589 }
5590
5591 if (atm != NULL) {
5592#ifdef _OPENACC
5593 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5594#pragma acc update device(atm[:1])
5595#endif
5596 }
5597}

◆ mptrac_update_host()

void mptrac_update_host ( const ctl_t ctl,
const cache_t cache,
const clim_t clim,
met_t **  met0,
met_t **  met1,
const atm_t atm 
)

Updates host memory for specified data structures.

This function transfers data from the device (GPU) memory back to the host memory for the provided data structures (ctl, cache, clim, atm) using OpenACC directives. It ensures that the latest data from the device is synchronized with the host.

Parameters
[in]ctlPointer to the ctl_t structure. If not NULL, the corresponding host memory for ctl is updated from the device.
[in]cachePointer to the cache_t structure. If not NULL, the corresponding host memory for cache is updated from the device.
[in]climPointer to the clim_t structure. If not NULL, the corresponding host memory for clim is updated from the device.
[in]met0Pointer to the first met_t structure. If not NULL, the corresponding host memory for met0 is updated.
[in]met1Pointer to the second met_t structure. If not NULL, the corresponding host memory for met1 is updated.
[in]atmPointer to the atm_t structure. If not NULL, the corresponding host memory for atm is updated from the device.
Note
The function assumes that OpenACC is enabled and uses the #pragma acc update directive for host memory synchronization. Each update operation is wrapped with a timer labeled as "UPDATE_HOST" for performance tracking.
Warning
Ensure that the pointers passed to this function are valid and properly initialized before calling this function
Author
Lars Hoffmann

Definition at line 5601 of file mptrac.c.

5607 {
5608
5609 /* Update GPU... */
5610 if (ctl != NULL) {
5611#ifdef _OPENACC
5612 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5613#pragma acc update host(ctl[:1])
5614#endif
5615 }
5616
5617 if (cache != NULL) {
5618#ifdef _OPENACC
5619 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5620#pragma acc update host(cache[:1])
5621#endif
5622 }
5623
5624 if (clim != NULL) {
5625#ifdef _OPENACC
5626 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5627#pragma acc update host(clim[:1])
5628#endif
5629 }
5630
5631 if (met0 != NULL) {
5632#ifdef _OPENACC
5633 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5634 met_t *met0up = *met0;
5635#pragma acc update host(met0up[:1])
5636#endif
5637 }
5638
5639 if (met1 != NULL) {
5640#ifdef _OPENACC
5641 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5642 met_t *met1up = *met1;
5643#pragma acc update host(met1up[:1])
5644#endif
5645 }
5646
5647 if (atm != NULL) {
5648#ifdef _OPENACC
5649 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5650#pragma acc update host(atm[:1])
5651#endif
5652 }
5653}

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

5851 {
5852
5853 /* Check water vapor volume mixing ratio... */
5854 const double h2o_help = MAX(h2o, 0.1e-6);
5855
5856 /* Calculate T_NAT... */
5857 const double p_hno3 = hno3 * p / 1.333224;
5858 const double p_h2o = h2o_help * p / 1.333224;
5859 const double a = 0.009179 - 0.00088 * log10(p_h2o);
5860 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
5861 const double c = -11397.0 / a;
5862 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
5863 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
5864 if (x2 > 0)
5865 tnat = x2;
5866
5867 return tnat;
5868}

◆ pbl_weight()

double pbl_weight ( const ctl_t ctl,
const atm_t atm,
const int  ip,
const double  pbl,
const double  ps 
)

Computes a weighting factor based on planetary boundary layer pressure.

This function calculates a weighting factor that determines the contribution of a pressure level to processes within the planetary boundary layer. The factor is based on the relative position of the pressure within a linear transition range defined by pbl and ps.

Parameters
ctlPointer to the control structure containing configuration parameters.
atmPointer to the atmospheric data structure containing pressure levels.
ipIndex of the pressure level in the atmospheric data array.
pblPressure at the planetary boundary layer.
psSurface pressure.
Returns
Weighting factor for the specified pressure level:
  • Returns 1.0 if the pressure is above the upper boundary (p0).
  • Returns 0.0 if the pressure is below the lower boundary (p1).
  • Returns a linearly interpolated value between 1.0 and 0.0 for pressures within the transition range.
Author
Lars Hoffmann

Definition at line 5872 of file mptrac.c.

5877 {
5878
5879 /* Get pressure range... */
5880 const double p1 = pbl - ctl->conv_pbl_trans * (ps - pbl);
5881 const double p0 = pbl;
5882
5883 /* Get weighting factor... */
5884 if (atm->p[ip] > p0)
5885 return 1;
5886 else if (atm->p[ip] < p1)
5887 return 0;
5888 else
5889 return LIN(p0, 1.0, p1, 0.0, atm->p[ip]);
5890}

◆ read_atm_asc()

int read_atm_asc ( const char *  filename,
const 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 5894 of file mptrac.c.

5897 {
5898
5899 /* Open file... */
5900 FILE *in;
5901 if (!(in = fopen(filename, "r"))) {
5902 WARN("Cannot open file!");
5903 return 0;
5904 }
5905
5906 /* Read line... */
5907 char line[LEN];
5908 while (fgets(line, LEN, in)) {
5909
5910 /* Read data... */
5911 char *tok;
5912 TOK(line, tok, "%lg", atm->time[atm->np]);
5913 TOK(NULL, tok, "%lg", atm->p[atm->np]);
5914 TOK(NULL, tok, "%lg", atm->lon[atm->np]);
5915 TOK(NULL, tok, "%lg", atm->lat[atm->np]);
5916 for (int iq = 0; iq < ctl->nq; iq++)
5917 TOK(NULL, tok, "%lg", atm->q[iq][atm->np]);
5918
5919 /* Convert altitude to pressure... */
5920 atm->p[atm->np] = P(atm->p[atm->np]);
5921
5922 /* Increment data point counter... */
5923 if ((++atm->np) > NP)
5924 ERRMSG("Too many data points!");
5925 }
5926
5927 /* Close file... */
5928 fclose(in);
5929
5930 /* Return success... */
5931 return 1;
5932}
#define TOK(line, tok, format, var)
Get string tokens.
Definition: mptrac.h:1694

◆ read_atm_bin()

int read_atm_bin ( const char *  filename,
const 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 5936 of file mptrac.c.

5939 {
5940
5941 /* Open file... */
5942 FILE *in;
5943 if (!(in = fopen(filename, "r")))
5944 return 0;
5945
5946 /* Check version of binary data... */
5947 int version;
5948 FREAD(&version, int,
5949 1,
5950 in);
5951 if (version != 100)
5952 ERRMSG("Wrong version of binary data!");
5953
5954 /* Read data... */
5955 FREAD(&atm->np, int,
5956 1,
5957 in);
5958 FREAD(atm->time, double,
5959 (size_t) atm->np,
5960 in);
5961 FREAD(atm->p, double,
5962 (size_t) atm->np,
5963 in);
5964 FREAD(atm->lon, double,
5965 (size_t) atm->np,
5966 in);
5967 FREAD(atm->lat, double,
5968 (size_t) atm->np,
5969 in);
5970 for (int iq = 0; iq < ctl->nq; iq++)
5971 FREAD(atm->q[iq], double,
5972 (size_t) atm->np,
5973 in);
5974
5975 /* Read final flag... */
5976 int final;
5977 FREAD(&final, int,
5978 1,
5979 in);
5980 if (final != 999)
5981 ERRMSG("Error while reading binary data!");
5982
5983 /* Close file... */
5984 fclose(in);
5985
5986 /* Return success... */
5987 return 1;
5988}

◆ read_atm_clams()

int read_atm_clams ( const char *  filename,
const 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 5992 of file mptrac.c.

5995 {
5996
5997 int ncid, varid;
5998
5999 /* Open file... */
6000 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6001 return 0;
6002
6003 /* Get dimensions... */
6004 NC_INQ_DIM("NPARTS", &atm->np, 1, NP);
6005
6006 /* Get time... */
6007 if (nc_inq_varid(ncid, "TIME_INIT", &varid) == NC_NOERR) {
6008 NC(nc_get_var_double(ncid, varid, atm->time));
6009 } else {
6010 WARN("TIME_INIT not found use time instead!");
6011 double time_init;
6012 NC_GET_DOUBLE("time", &time_init, 1);
6013 for (int ip = 0; ip < atm->np; ip++) {
6014 atm->time[ip] = time_init;
6015 }
6016 }
6017
6018 /* Read zeta coordinate, pressure is optional... */
6019 if (ctl->advect_vert_coord == 1) {
6020 NC_GET_DOUBLE("ZETA", atm->q[ctl->qnt_zeta], 1);
6021 NC_GET_DOUBLE("PRESS", atm->p, 0);
6022 }
6023
6024 /* Read pressure, zeta coordinate is optional... */
6025 else {
6026 if (nc_inq_varid(ncid, "PRESS_INIT", &varid) == NC_NOERR) {
6027 NC(nc_get_var_double(ncid, varid, atm->p));
6028 } else {
6029 WARN("PRESS_INIT not found use PRESS instead!");
6030 nc_inq_varid(ncid, "PRESS", &varid);
6031 NC(nc_get_var_double(ncid, varid, atm->p));
6032 }
6033 }
6034
6035 /* Read longitude and latitude... */
6036 NC_GET_DOUBLE("LON", atm->lon, 1);
6037 NC_GET_DOUBLE("LAT", atm->lat, 1);
6038
6039 /* Close file... */
6040 NC(nc_close(ncid));
6041
6042 /* Return success... */
6043 return 1;
6044}
#define NC(cmd)
Execute a NetCDF command and check for errors.
Definition: mptrac.h:1016
#define NC_INQ_DIM(dimname, ptr, min, max)
Inquire the length of a dimension in a NetCDF file.
Definition: mptrac.h:1103
#define NC_GET_DOUBLE(varname, ptr, force)
Retrieve a double-precision variable from a NetCDF file.
Definition: mptrac.h:1075

◆ read_atm_nc()

int read_atm_nc ( const char *  filename,
const 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 6048 of file mptrac.c.

6051 {
6052
6053 int ncid, varid;
6054
6055 /* Open file... */
6056 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6057 return 0;
6058
6059 /* Get dimensions... */
6060 NC_INQ_DIM("obs", &atm->np, 1, NP);
6061
6062 /* Read geolocations... */
6063 NC_GET_DOUBLE("time", atm->time, 1);
6064 NC_GET_DOUBLE("press", atm->p, 1);
6065 NC_GET_DOUBLE("lon", atm->lon, 1);
6066 NC_GET_DOUBLE("lat", atm->lat, 1);
6067
6068 /* Read variables... */
6069 for (int iq = 0; iq < ctl->nq; iq++)
6070 NC_GET_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
6071
6072 /* Close file... */
6073 NC(nc_close(ncid));
6074
6075 /* Return success... */
6076 return 1;
6077}

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

6083 {
6084
6085 int ncid, varid;
6086
6087 /* Write info... */
6088 LOG(1, "Read photolysis rates: %s", filename);
6089
6090 /* Open netCDF file... */
6091 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
6092 WARN("Photolysis rate data are missing!");
6093 return;
6094 }
6095
6096 /* Read pressure data... */
6097 NC_INQ_DIM("press", &photo->np, 2, CP);
6098 NC_GET_DOUBLE("press", photo->p, 1);
6099 if (photo->p[0] < photo->p[1])
6100 ERRMSG("Pressure data are not descending!");
6101
6102 /* Read total column ozone data... */
6103 NC_INQ_DIM("total_o3col", &photo->no3c, 2, CO3);
6104 NC_GET_DOUBLE("total_o3col", photo->o3c, 1);
6105 if (photo->o3c[0] > photo->o3c[1])
6106 ERRMSG("Total column ozone data are not ascending!");
6107
6108 /* Read solar zenith angle data... */
6109 NC_INQ_DIM("sza", &photo->nsza, 2, CSZA);
6110 NC_GET_DOUBLE("sza", photo->sza, 1);
6111 if (photo->sza[0] > photo->sza[1])
6112 ERRMSG("Solar zenith angle data are not ascending!");
6113
6114 /* Read data... */
6115 read_clim_photo_help(ncid, "J_N2O", photo, photo->n2o);
6116 read_clim_photo_help(ncid, "J_CCl4", photo, photo->ccl4);
6117 read_clim_photo_help(ncid, "J_CFC-11", photo, photo->ccl3f);
6118 read_clim_photo_help(ncid, "J_CFC-12", photo, photo->ccl2f2);
6119 read_clim_photo_help(ncid, "J_O2", photo, photo->o2);
6120 read_clim_photo_help(ncid, "J_O3b", photo, photo->o3_1);
6121 read_clim_photo_help(ncid, "J_O3a", photo, photo->o3_2);
6122 read_clim_photo_help(ncid, "J_H2O2", photo, photo->h2o2);
6123 read_clim_photo_help(ncid, "J_H2O", photo, photo->h2o);
6124
6125 /* Close netCDF file... */
6126 NC(nc_close(ncid));
6127
6128 /* Write info... */
6129 LOG(2, "Number of pressure levels: %d", photo->np);
6130 LOG(2, "Altitude levels: %g, %g ... %g km",
6131 Z(photo->p[0]), Z(photo->p[1]), Z(photo->p[photo->np - 1]));
6132 LOG(2, "Pressure levels: %g, %g ... %g hPa",
6133 photo->p[0], photo->p[1], photo->p[photo->np - 1]);
6134 LOG(2, "Number of solar zenith angles: %d", photo->nsza);
6135 LOG(2, "Solar zenith angles: %g, %g ... %g deg",
6136 RAD2DEG(photo->sza[0]), RAD2DEG(photo->sza[1]),
6137 RAD2DEG(photo->sza[photo->nsza - 1]));
6138 LOG(2, "Number of total column ozone values: %d", photo->no3c);
6139 LOG(2, "Total column ozone: %g, %g ... %g DU",
6140 photo->o3c[0], photo->o3c[1], photo->o3c[photo->no3c - 1]);
6141 LOG(2, "N2O photolysis rate: %g, %g ... %g s**-1",
6142 photo->n2o[0][0][0], photo->n2o[1][0][0],
6143 photo->n2o[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6144 LOG(2, "CCl4 photolysis rate: %g, %g ... %g s**-1",
6145 photo->ccl4[0][0][0], photo->ccl4[1][0][0],
6146 photo->ccl4[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6147 LOG(2, "CFC-11 photolysis rate: %g, %g ... %g s**-1",
6148 photo->ccl3f[0][0][0], photo->ccl3f[1][0][0],
6149 photo->ccl3f[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6150 LOG(2, "CFC-12 photolysis rate: %g, %g ... %g s**-1",
6151 photo->ccl2f2[0][0][0], photo->ccl2f2[1][0][0],
6152 photo->ccl2f2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6153 LOG(2, "O2 photolysis rate: %g, %g ... %g s**-1",
6154 photo->o2[0][0][0], photo->o2[1][0][0],
6155 photo->o2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6156 LOG(2, "O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
6157 photo->o3_1[0][0][0], photo->o3_1[1][0][0],
6158 photo->o3_1[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6159 LOG(2, "O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
6160 photo->o3_2[0][0][0], photo->o3_2[1][0][0],
6161 photo->o3_2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6162 LOG(2, "H2O2 photolysis rate: %g, %g ... %g s**-1",
6163 photo->h2o2[0][0][0], photo->h2o2[1][0][0],
6164 photo->h2o2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6165 LOG(2, "H2O photolysis rate: %g, %g ... %g s**-1",
6166 photo->h2o[0][0][0], photo->h2o[1][0][0],
6167 photo->h2o[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6168}
void read_clim_photo_help(const int ncid, const char *varname, const clim_photo_t *photo, double var[CP][CSZA][CO3])
Reads a 3D climatological photochemistry variable from a NetCDF file.
Definition: mptrac.c:6172
#define CP
Maximum number of pressure levels for climatological data.
Definition: mptrac.h:301
#define CO3
Maximum number of total column ozone data for climatological data.
Definition: mptrac.h:296
#define CSZA
Maximum number of solar zenith angles for climatological data.
Definition: mptrac.h:306
double o3_1[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O1d + O2) [1/s].
Definition: mptrac.h:3232
double o2[CP][CSZA][CO3]
O2 photolysis rate [1/s].
Definition: mptrac.h:3229
double h2o2[CP][CSZA][CO3]
H2O2 photolysis rate [1/s].
Definition: mptrac.h:3238
double h2o[CP][CSZA][CO3]
H2O photolysis rate [1/s].
Definition: mptrac.h:3241
double o3_2[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O3p + O2) [1/s].
Definition: mptrac.h:3235
Here is the call graph for this function:

◆ read_clim_photo_help()

void read_clim_photo_help ( const int  ncid,
const char *  varname,
const clim_photo_t photo,
double  var[CP][CSZA][CO3] 
)

Reads a 3D climatological photochemistry variable from a NetCDF file.

This function reads a variable from a NetCDF file into a 3D array based on the dimensions provided by the clim_photo_t structure.

Parameters
[in]ncidNetCDF file ID.
[in]varnameName of the variable to read from the NetCDF file.
[in]photoPointer to a structure defining the data dimensions (np, nsza, no3c).
[out]var3D array to store the read data, with dimensions [CP][CSZA][CO3].
Note
Allocates temporary memory for reading and copies data into the provided array. The memory is freed after the data is copied.
Author
Lars Hoffmann

Definition at line 6172 of file mptrac.c.

6176 {
6177
6178 /* Allocate... */
6179 double *help;
6180 ALLOC(help, double,
6181 photo->np * photo->nsza * photo->no3c);
6182
6183 /* Read varible... */
6184 int varid;
6185 NC_GET_DOUBLE(varname, help, 1);
6186
6187 /* Copy data... */
6188 for (int ip = 0; ip < photo->np; ip++)
6189 for (int is = 0; is < photo->nsza; is++)
6190 for (int io = 0; io < photo->no3c; io++)
6191 var[ip][is][io] =
6192 help[ARRAY_3D(ip, is, photo->nsza, io, photo->no3c)];
6193
6194 /* Free... */
6195 free(help);
6196}

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

6202 {
6203
6204 /* Write info... */
6205 LOG(1, "Read climatological time series: %s", filename);
6206
6207 /* Open file... */
6208 FILE *in;
6209 if (!(in = fopen(filename, "r"))) {
6210 WARN("Cannot open file!");
6211 return 0;
6212 }
6213
6214 /* Read data... */
6215 char line[LEN];
6216 int nh = 0;
6217 while (fgets(line, LEN, in))
6218 if (sscanf(line, "%lg %lg", &ts->time[nh], &ts->vmr[nh]) == 2) {
6219
6220 /* Convert years to seconds... */
6221 ts->time[nh] = (ts->time[nh] - 2000.0) * 365.25 * 86400.;
6222
6223 /* Check data... */
6224 if (nh > 0 && ts->time[nh] <= ts->time[nh - 1])
6225 ERRMSG("Time series must be ascending!");
6226
6227 /* Count time steps... */
6228 if ((++nh) >= CTS)
6229 ERRMSG("Too many data points!");
6230 }
6231
6232 /* Close file... */
6233 fclose(in);
6234
6235 /* Check number of data points... */
6236 ts->ntime = nh;
6237 if (nh < 2)
6238 ERRMSG("Not enough data points!");
6239
6240 /* Write info... */
6241 LOG(2, "Number of time steps: %d", ts->ntime);
6242 LOG(2, "Time steps: %.2f, %.2f ... %.2f s", ts->time[0], ts->time[1],
6243 ts->time[nh - 1]);
6244 LOG(2, "Volume mixing ratio range: %g ... %g ppv",
6245 gsl_stats_min(ts->vmr, 1, (size_t) nh), gsl_stats_max(ts->vmr, 1,
6246 (size_t) nh));
6247
6248 /* Exit success... */
6249 return 1;
6250}
#define CTS
Maximum number of data points of climatological time series.
Definition: mptrac.h:316

◆ read_clim_zm()

void read_clim_zm ( const char *  filename,
const 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 6254 of file mptrac.c.

6257 {
6258
6259 int ncid, varid, it, iy, iz, iz2, nt;
6260
6261 double *help, varmin = 1e99, varmax = -1e99;
6262
6263 /* Write info... */
6264 LOG(1, "Read %s data: %s", varname, filename);
6265
6266 /* Open netCDF file... */
6267 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
6268 WARN("%s climatology data are missing!", varname);
6269 return;
6270 }
6271
6272 /* Read pressure data... */
6273 NC_INQ_DIM("press", &zm->np, 2, CP);
6274 NC_GET_DOUBLE("press", zm->p, 1);
6275 if (zm->p[0] < zm->p[1])
6276 ERRMSG("Pressure data are not descending!");
6277
6278 /* Read latitudes... */
6279 NC_INQ_DIM("lat", &zm->nlat, 2, CY);
6280 NC_GET_DOUBLE("lat", zm->lat, 1);
6281 if (zm->lat[0] > zm->lat[1])
6282 ERRMSG("Latitude data are not ascending!");
6283
6284 /* Set time data (for monthly means)... */
6285 zm->ntime = 12;
6286 zm->time[0] = 1209600.00;
6287 zm->time[1] = 3888000.00;
6288 zm->time[2] = 6393600.00;
6289 zm->time[3] = 9072000.00;
6290 zm->time[4] = 11664000.00;
6291 zm->time[5] = 14342400.00;
6292 zm->time[6] = 16934400.00;
6293 zm->time[7] = 19612800.00;
6294 zm->time[8] = 22291200.00;
6295 zm->time[9] = 24883200.00;
6296 zm->time[10] = 27561600.00;
6297 zm->time[11] = 30153600.00;
6298
6299 /* Check number of timesteps... */
6300 NC_INQ_DIM("time", &nt, 12, 12);
6301
6302 /* Read data... */
6303 ALLOC(help, double,
6304 zm->nlat * zm->np * zm->ntime);
6305 NC_GET_DOUBLE(varname, help, 1);
6306 for (it = 0; it < zm->ntime; it++)
6307 for (iz = 0; iz < zm->np; iz++)
6308 for (iy = 0; iy < zm->nlat; iy++)
6309 zm->vmr[it][iz][iy] = help[ARRAY_3D(it, iz, zm->np, iy, zm->nlat)];
6310 free(help);
6311
6312 /* Fix data gaps... */
6313 for (it = 0; it < zm->ntime; it++)
6314 for (iy = 0; iy < zm->nlat; iy++)
6315 for (iz = 0; iz < zm->np; iz++) {
6316 if (zm->vmr[it][iz][iy] < 0) {
6317 for (iz2 = 0; iz2 < zm->np; iz2++)
6318 if (zm->vmr[it][iz2][iy] >= 0) {
6319 zm->vmr[it][iz][iy] = zm->vmr[it][iz2][iy];
6320 break;
6321 }
6322 for (iz2 = zm->np - 1; iz2 >= 0; iz2--)
6323 if (zm->vmr[it][iz2][iy] >= 0) {
6324 zm->vmr[it][iz][iy] = zm->vmr[it][iz2][iy];
6325 break;
6326 }
6327 }
6328 varmin = MIN(varmin, zm->vmr[it][iz][iy]);
6329 varmax = MAX(varmax, zm->vmr[it][iz][iy]);
6330 }
6331
6332 /* Close netCDF file... */
6333 NC(nc_close(ncid));
6334
6335 /* Write info... */
6336 LOG(2, "Number of time steps: %d", zm->ntime);
6337 LOG(2, "Time steps: %.2f, %.2f ... %.2f s",
6338 zm->time[0], zm->time[1], zm->time[zm->ntime - 1]);
6339 LOG(2, "Number of pressure levels: %d", zm->np);
6340 LOG(2, "Altitude levels: %g, %g ... %g km",
6341 Z(zm->p[0]), Z(zm->p[1]), Z(zm->p[zm->np - 1]));
6342 LOG(2, "Pressure levels: %g, %g ... %g hPa", zm->p[0],
6343 zm->p[1], zm->p[zm->np - 1]);
6344 LOG(2, "Number of latitudes: %d", zm->nlat);
6345 LOG(2, "Latitudes: %g, %g ... %g deg",
6346 zm->lat[0], zm->lat[1], zm->lat[zm->nlat - 1]);
6347 LOG(2, "%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
6348 varmax);
6349}
#define CY
Maximum number of latitudes for climatological data.
Definition: mptrac.h:291

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

6357 {
6358
6359 /* Write info... */
6360 LOG(1, "Read kernel function: %s", filename);
6361
6362 /* Open file... */
6363 FILE *in;
6364 if (!(in = fopen(filename, "r")))
6365 ERRMSG("Cannot open file!");
6366
6367 /* Read data... */
6368 char line[LEN];
6369 int n = 0;
6370 while (fgets(line, LEN, in))
6371 if (sscanf(line, "%lg %lg", &kz[n], &kw[n]) == 2) {
6372 if (n > 0 && kz[n] < kz[n - 1])
6373 ERRMSG("Height levels must be ascending!");
6374 if ((++n) >= EP)
6375 ERRMSG("Too many height levels!");
6376 }
6377
6378 /* Close file... */
6379 fclose(in);
6380
6381 /* Check number of data points... */
6382 *nk = n;
6383 if (n < 2)
6384 ERRMSG("Not enough height levels!");
6385
6386 /* Normalize kernel function... */
6387 const double kmax = gsl_stats_max(kw, 1, (size_t) n);
6388 for (int iz = 0; iz < n; iz++)
6389 kw[iz] /= kmax;
6390}

◆ read_met_bin()

int read_met_bin ( const char *  filename,
const ctl_t ctl,
met_t met 
)

Reads meteorological data from a binary file.

This function reads meteorological data from a binary file and populates the provided met_t structure with the data. It checks the binary file's format version and met_type, ensuring compatibility with the control structure (ctl_t). The function reads time, grid, surface data, and multi-level data, and supports different binary file versions.

Parameters
filenameA constant character pointer representing the name of the binary file to read the meteorological data from.
ctlA pointer to a ctl_t structure that holds control parameters such as the expected met_type and other configuration options.
metA pointer to a met_t structure that will store the meteorological data read from the binary file.
Note
  • The function logs the progress and details of the read operation, such as time, number of longitudes, latitudes, levels, and various meteorological variables.
  • It uses the FREAD macro for safe binary reading operations, which checks the integrity of the read operation.
  • The function reads and verifies the met_type and binary file version to ensure compatibility.
  • Supported binary file versions include 100, 101, and 102, each of which may include additional variables (e.g., LSM, SST, RWC, SWC, and CC).
Warning
  • The function will raise an error if the met_type in the file does not match the ctl->met_type.
  • It will raise an error if the binary file version is not supported.
  • If the dimensions of the data (e.g., number of longitudes, latitudes, or levels) are outside the expected range, an error will be raised.
Author
Lars Hoffmann

Definition at line 6394 of file mptrac.c.

6397 {
6398
6399 FILE *in;
6400
6401 double r;
6402
6403 int year, mon, day, hour, min, sec;
6404
6405 /* Set timer... */
6406 SELECT_TIMER("READ_MET_BIN", "INPUT", NVTX_READ);
6407
6408 /* Open file... */
6409 if (!(in = fopen(filename, "r"))) {
6410 WARN("Cannot open file!");
6411 return 0;
6412 }
6413
6414 /* Check type of binary data... */
6415 int met_type;
6416 FREAD(&met_type, int,
6417 1,
6418 in);
6419 if (met_type != ctl->met_type)
6420 ERRMSG("Wrong MET_TYPE of binary data!");
6421
6422 /* Check version of binary data... */
6423 int version;
6424 FREAD(&version, int,
6425 1,
6426 in);
6427 if (version != 103)
6428 ERRMSG("Wrong version of binary data!");
6429
6430 /* Read time... */
6431 FREAD(&met->time, double,
6432 1,
6433 in);
6434 jsec2time(met->time, &year, &mon, &day, &hour, &min, &sec, &r);
6435 LOG(2, "Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
6436 met->time, year, mon, day, hour, min);
6437 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
6438 || day < 1 || day > 31 || hour < 0 || hour > 23)
6439 ERRMSG("Error while reading time!");
6440
6441 /* Read dimensions... */
6442 FREAD(&met->nx, int,
6443 1,
6444 in);
6445 LOG(2, "Number of longitudes: %d", met->nx);
6446 if (met->nx < 2 || met->nx > EX)
6447 ERRMSG("Number of longitudes out of range!");
6448
6449 FREAD(&met->ny, int,
6450 1,
6451 in);
6452 LOG(2, "Number of latitudes: %d", met->ny);
6453 if (met->ny < 2 || met->ny > EY)
6454 ERRMSG("Number of latitudes out of range!");
6455
6456 FREAD(&met->np, int,
6457 1,
6458 in);
6459 LOG(2, "Number of levels: %d", met->np);
6460 if (met->np < 2 || met->np > EP)
6461 ERRMSG("Number of levels out of range!");
6462
6463 /* Read grid... */
6464 FREAD(met->lon, double,
6465 (size_t) met->nx,
6466 in);
6467 LOG(2, "Longitudes: %g, %g ... %g deg",
6468 met->lon[0], met->lon[1], met->lon[met->nx - 1]);
6469
6470 FREAD(met->lat, double,
6471 (size_t) met->ny,
6472 in);
6473 LOG(2, "Latitudes: %g, %g ... %g deg",
6474 met->lat[0], met->lat[1], met->lat[met->ny - 1]);
6475
6476 FREAD(met->p, double,
6477 (size_t) met->np,
6478 in);
6479 LOG(2, "Altitude levels: %g, %g ... %g km",
6480 Z(met->p[0]), Z(met->p[1]), Z(met->p[met->np - 1]));
6481 LOG(2, "Pressure levels: %g, %g ... %g hPa",
6482 met->p[0], met->p[1], met->p[met->np - 1]);
6483
6484 /* Read surface data... */
6485 read_met_bin_2d(in, met, met->ps, "PS");
6486 read_met_bin_2d(in, met, met->ts, "TS");
6487 read_met_bin_2d(in, met, met->zs, "ZS");
6488 read_met_bin_2d(in, met, met->us, "US");
6489 read_met_bin_2d(in, met, met->vs, "VS");
6490 read_met_bin_2d(in, met, met->ess, "ESS");
6491 read_met_bin_2d(in, met, met->nss, "NSS");
6492 read_met_bin_2d(in, met, met->shf, "SHF");
6493 read_met_bin_2d(in, met, met->lsm, "LSM");
6494 read_met_bin_2d(in, met, met->sst, "SST");
6495 read_met_bin_2d(in, met, met->pbl, "PBL");
6496 read_met_bin_2d(in, met, met->pt, "PT");
6497 read_met_bin_2d(in, met, met->tt, "TT");
6498 read_met_bin_2d(in, met, met->zt, "ZT");
6499 read_met_bin_2d(in, met, met->h2ot, "H2OT");
6500 read_met_bin_2d(in, met, met->pct, "PCT");
6501 read_met_bin_2d(in, met, met->pcb, "PCB");
6502 read_met_bin_2d(in, met, met->cl, "CL");
6503 read_met_bin_2d(in, met, met->plcl, "PLCL");
6504 read_met_bin_2d(in, met, met->plfc, "PLFC");
6505 read_met_bin_2d(in, met, met->pel, "PEL");
6506 read_met_bin_2d(in, met, met->cape, "CAPE");
6507 read_met_bin_2d(in, met, met->cin, "CIN");
6508 read_met_bin_2d(in, met, met->o3c, "O3C");
6509
6510 /* Read level data... */
6511 read_met_bin_3d(in, ctl, met, met->z, "Z", -1e34f, 1e34f);
6512 read_met_bin_3d(in, ctl, met, met->t, "T", 0, 1e34f);
6513 read_met_bin_3d(in, ctl, met, met->u, "U", -1e34f, 1e34f);
6514 read_met_bin_3d(in, ctl, met, met->v, "V", -1e34f, 1e34f);
6515 read_met_bin_3d(in, ctl, met, met->w, "W", -1e34f, 1e34f);
6516 read_met_bin_3d(in, ctl, met, met->pv, "PV", -1e34f, 1e34f);
6517 read_met_bin_3d(in, ctl, met, met->h2o, "H2O", 0, 1e34f);
6518 read_met_bin_3d(in, ctl, met, met->o3, "O3", 0, 1e34f);
6519 read_met_bin_3d(in, ctl, met, met->lwc, "LWC", 0, 1e34f);
6520 read_met_bin_3d(in, ctl, met, met->rwc, "RWC", 0, 1e34f);
6521 read_met_bin_3d(in, ctl, met, met->iwc, "IWC", 0, 1e34f);
6522 read_met_bin_3d(in, ctl, met, met->swc, "SWC", 0, 1e34f);
6523 read_met_bin_3d(in, ctl, met, met->cc, "CC", 0, 1);
6524
6525 /* Read final flag... */
6526 int final;
6527 FREAD(&final, int,
6528 1,
6529 in);
6530 if (final != 999)
6531 ERRMSG("Error while reading binary data!");
6532
6533 /* Close file... */
6534 fclose(in);
6535
6536 /* Return success... */
6537 return 1;
6538}
void read_met_bin_2d(FILE *in, const met_t *met, float var[EX][EY], const char *varname)
Reads a 2-dimensional meteorological variable from a binary file and stores it in the provided array.
Definition: mptrac.c:6542
void read_met_bin_3d(FILE *in, const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname, const float bound_min, const float bound_max)
Reads 3D meteorological data from a binary file, potentially using different compression methods.
Definition: mptrac.c:6571
#define EY
Maximum number of latitudes for meteo data.
Definition: mptrac.h:271
float zt[EX][EY]
Tropopause geopotential height [km].
Definition: mptrac.h:3432
float sst[EX][EY]
Sea surface temperature [K].
Definition: mptrac.h:3420
float rwc[EX][EY][EP]
Cloud rain water content [kg/kg].
Definition: mptrac.h:3492
float o3c[EX][EY]
Total column ozone [DU].
Definition: mptrac.h:3462
float cape[EX][EY]
Convective available potential energy [J/kg].
Definition: mptrac.h:3456
float pct[EX][EY]
Cloud top pressure [hPa].
Definition: mptrac.h:3438
float shf[EX][EY]
Surface sensible heat flux [W/m^2].
Definition: mptrac.h:3414
float lwc[EX][EY][EP]
Cloud liquid water content [kg/kg].
Definition: mptrac.h:3489
float us[EX][EY]
Surface zonal wind [m/s].
Definition: mptrac.h:3402
float cc[EX][EY][EP]
Cloud cover [1].
Definition: mptrac.h:3501
float ts[EX][EY]
Surface temperature [K].
Definition: mptrac.h:3396
float ess[EX][EY]
Eastward turbulent surface stress [N/m^2].
Definition: mptrac.h:3408
float pcb[EX][EY]
Cloud bottom pressure [hPa].
Definition: mptrac.h:3441
float pel[EX][EY]
Pressure at equilibrium level (EL) [hPa].
Definition: mptrac.h:3453
float cin[EX][EY]
Convective inhibition [J/kg].
Definition: mptrac.h:3459
float plcl[EX][EY]
Pressure at lifted condensation level (LCL) [hPa].
Definition: mptrac.h:3447
float tt[EX][EY]
Tropopause temperature [K].
Definition: mptrac.h:3429
float pbl[EX][EY]
Boundary layer pressure [hPa].
Definition: mptrac.h:3423
float vs[EX][EY]
Surface meridional wind [m/s].
Definition: mptrac.h:3405
float lsm[EX][EY]
Land-sea mask [1].
Definition: mptrac.h:3417
float iwc[EX][EY][EP]
Cloud ice water content [kg/kg].
Definition: mptrac.h:3495
float h2ot[EX][EY]
Tropopause water vapor volume mixing ratio [ppv].
Definition: mptrac.h:3435
float pv[EX][EY][EP]
Potential vorticity [PVU].
Definition: mptrac.h:3480
float cl[EX][EY]
Total column cloud water [kg/m^2].
Definition: mptrac.h:3444
float nss[EX][EY]
Northward turbulent surface stress [N/m^2].
Definition: mptrac.h:3411
float plfc[EX][EY]
Pressure at level of free convection (LFC) [hPa].
Definition: mptrac.h:3450
float swc[EX][EY][EP]
Cloud snow water content [kg/kg].
Definition: mptrac.h:3498
Here is the call graph for this function:

◆ read_met_bin_2d()

void read_met_bin_2d ( FILE *  in,
const met_t met,
float  var[EX][EY],
const 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 6542 of file mptrac.c.

6546 {
6547
6548 float *help;
6549
6550 /* Allocate... */
6551 ALLOC(help, float,
6552 EX * EY);
6553
6554 /* Read uncompressed... */
6555 LOG(2, "Read 2-D variable: %s (uncompressed)", varname);
6556 FREAD(help, float,
6557 (size_t) (met->nx * met->ny),
6558 in);
6559
6560 /* Copy data... */
6561 for (int ix = 0; ix < met->nx; ix++)
6562 for (int iy = 0; iy < met->ny; iy++)
6563 var[ix][iy] = help[ARRAY_2D(ix, iy, met->ny)];
6564
6565 /* Free... */
6566 free(help);
6567}
#define ARRAY_2D(ix, iy, ny)
Macro for computing the linear index of a 2D array element.
Definition: mptrac.h:372

◆ read_met_bin_3d()

void read_met_bin_3d ( FILE *  in,
const ctl_t ctl,
const met_t met,
float  var[EX][EY][EP],
const char *  varname,
const float  bound_min,
const 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 6571 of file mptrac.c.

6578 {
6579
6580 float *help;
6581
6582 /* Allocate... */
6583 ALLOC(help, float,
6584 EX * EY * EP);
6585
6586 /* Read uncompressed data... */
6587 if (ctl->met_type == 1) {
6588 LOG(2, "Read 3-D variable: %s (uncompressed)", varname);
6589 FREAD(help, float,
6590 (size_t) (met->nx * met->ny * met->np),
6591 in);
6592 }
6593
6594 /* Read packed data... */
6595 else if (ctl->met_type == 2)
6596 compress_pck(varname, help, (size_t) (met->ny * met->nx),
6597 (size_t) met->np, 1, in);
6598
6599 /* Read zfp data... */
6600 else if (ctl->met_type == 3) {
6601#ifdef ZFP
6602 int precision;
6603 FREAD(&precision, int,
6604 1,
6605 in);
6606
6607 double tolerance;
6608 FREAD(&tolerance, double,
6609 1,
6610 in);
6611
6612 compress_zfp(varname, help, met->np, met->ny, met->nx, precision,
6613 tolerance, 1, in);
6614#else
6615 ERRMSG("MPTRAC was compiled without zfp compression!");
6616#endif
6617 }
6618
6619 /* Read zstd data... */
6620 else if (ctl->met_type == 4) {
6621#ifdef ZSTD
6622 compress_zstd(varname, help, (size_t) (met->np * met->ny * met->nx), 1,
6623 in);
6624#else
6625 ERRMSG("MPTRAC was compiled without zstd compression!");
6626#endif
6627 }
6628
6629 /* Read cmultiscale data... */
6630 else if (ctl->met_type == 5) {
6631#ifdef CMS
6632 compress_cms(ctl, varname, help, (size_t) met->nx, (size_t) met->ny,
6633 (size_t) met->np, 1, in);
6634#else
6635 ERRMSG("MPTRAC was compiled without cmultiscale compression!");
6636#endif
6637 }
6638
6639 /* Copy data... */
6640#pragma omp parallel for default(shared) collapse(2)
6641 for (int ix = 0; ix < met->nx; ix++)
6642 for (int iy = 0; iy < met->ny; iy++)
6643 for (int ip = 0; ip < met->np; ip++) {
6644 var[ix][iy][ip] = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
6645 if (var[ix][iy][ip] < bound_min)
6646 var[ix][iy][ip] = bound_min;
6647 else if (var[ix][iy][ip] > bound_max)
6648 var[ix][iy][ip] = bound_max;
6649 }
6650
6651 /* Free... */
6652 free(help);
6653}
void compress_pck(const char *varname, float *array, const size_t nxy, const size_t nz, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats.
Definition: mptrac.c:657
void compress_cms(const ctl_t *ctl, const char *varname, float *array, const size_t nx, const size_t ny, const size_t np, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm.
void compress_zfp(const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using the ZFP library.
void compress_zstd(const char *varname, float *array, const size_t n, const int decompress, FILE *inout)
Compresses or decompresses an array of floats using the Zstandard (ZSTD) library.
Here is the call graph for this function:

◆ read_met_cape()

void read_met_cape ( const ctl_t ctl,
const 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 6657 of file mptrac.c.

6660 {
6661
6662 /* Check parameters... */
6663 if (ctl->met_cape != 1)
6664 return;
6665
6666 /* Set timer... */
6667 SELECT_TIMER("READ_MET_CAPE", "METPROC", NVTX_READ);
6668 LOG(2, "Calculate CAPE...");
6669
6670 /* Vertical spacing (about 100 m)... */
6671 const double pfac = 1.01439, dz0 = RI / MA / G0 * log(pfac);
6672
6673 /* Loop over columns... */
6674#pragma omp parallel for default(shared) collapse(2)
6675 for (int ix = 0; ix < met->nx; ix++)
6676 for (int iy = 0; iy < met->ny; iy++) {
6677
6678 /* Get potential temperature and water vapor at lowest 50 hPa... */
6679 int n = 0;
6680 double h2o = 0, t, theta = 0;
6681 double pbot = MIN(met->ps[ix][iy], met->p[0]);
6682 double ptop = pbot - 50.;
6683 for (int ip = 0; ip < met->np; ip++) {
6684 if (met->p[ip] <= pbot) {
6685 theta += THETA(met->p[ip], met->t[ix][iy][ip]);
6686 h2o += met->h2o[ix][iy][ip];
6687 n++;
6688 }
6689 if (met->p[ip] < ptop && n > 0)
6690 break;
6691 }
6692 theta /= n;
6693 h2o /= n;
6694
6695 /* Cannot compute anything if water vapor is missing... */
6696 met->plcl[ix][iy] = NAN;
6697 met->plfc[ix][iy] = NAN;
6698 met->pel[ix][iy] = NAN;
6699 met->cape[ix][iy] = NAN;
6700 met->cin[ix][iy] = NAN;
6701 if (h2o <= 0)
6702 continue;
6703
6704 /* Find lifted condensation level (LCL)... */
6705 ptop = P(20.);
6706 pbot = met->ps[ix][iy];
6707 do {
6708 met->plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
6709 t = theta / pow(1000. / met->plcl[ix][iy], 0.286);
6710 if (RH(met->plcl[ix][iy], t, h2o) > 100.)
6711 ptop = met->plcl[ix][iy];
6712 else
6713 pbot = met->plcl[ix][iy];
6714 } while (pbot - ptop > 0.1);
6715
6716 /* Calculate CIN up to LCL... */
6718 double dcape, dz, h2o_env, t_env;
6719 double p = met->ps[ix][iy];
6720 met->cape[ix][iy] = met->cin[ix][iy] = 0;
6721 do {
6722 dz = dz0 * TVIRT(t, h2o);
6723 p /= pfac;
6724 t = theta / pow(1000. / p, 0.286);
6725 intpol_met_space_3d(met, met->t, p, met->lon[ix], met->lat[iy],
6726 &t_env, ci, cw, 1);
6727 intpol_met_space_3d(met, met->h2o, p, met->lon[ix], met->lat[iy],
6728 &h2o_env, ci, cw, 0);
6729 dcape = 1e3 * G0 * (TVIRT(t, h2o) - TVIRT(t_env, h2o_env)) /
6730 TVIRT(t_env, h2o_env) * dz;
6731 if (dcape < 0)
6732 met->cin[ix][iy] += fabsf((float) dcape);
6733 } while (p > met->plcl[ix][iy]);
6734
6735 /* Calculate level of free convection (LFC), equilibrium level (EL),
6736 and convective available potential energy (CAPE)... */
6737 dcape = 0;
6738 p = met->plcl[ix][iy];
6739 t = theta / pow(1000. / p, 0.286);
6740 ptop = 0.75 * clim_tropo(clim, met->time, met->lat[iy]);
6741 do {
6742 dz = dz0 * TVIRT(t, h2o);
6743 p /= pfac;
6744 t -= lapse_rate(t, h2o) * dz;
6745 double psat = PSAT(t);
6746 h2o = psat / (p - (1. - EPS) * psat);
6747 intpol_met_space_3d(met, met->t, p, met->lon[ix], met->lat[iy],
6748 &t_env, ci, cw, 1);
6749 intpol_met_space_3d(met, met->h2o, p, met->lon[ix], met->lat[iy],
6750 &h2o_env, ci, cw, 0);
6751 double dcape_old = dcape;
6752 dcape = 1e3 * G0 * (TVIRT(t, h2o) - TVIRT(t_env, h2o_env)) /
6753 TVIRT(t_env, h2o_env) * dz;
6754 if (dcape > 0) {
6755 met->cape[ix][iy] += (float) dcape;
6756 if (!isfinite(met->plfc[ix][iy]))
6757 met->plfc[ix][iy] = (float) p;
6758 } else if (dcape_old > 0)
6759 met->pel[ix][iy] = (float) p;
6760 if (dcape < 0 && !isfinite(met->plfc[ix][iy]))
6761 met->cin[ix][iy] += fabsf((float) dcape);
6762 } while (p > ptop);
6763
6764 /* Check results... */
6765 if (!isfinite(met->plfc[ix][iy]))
6766 met->cin[ix][iy] = NAN;
6767 }
6768}
double clim_tropo(const clim_t *clim, const double t, const double lat)
Calculates the tropopause pressure based on climatological data.
Definition: mptrac.c:200
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 6772 of file mptrac.c.

6773 {
6774
6775 /* Set timer... */
6776 SELECT_TIMER("READ_MET_CLOUD", "METPROC", NVTX_READ);
6777 LOG(2, "Calculate cloud data...");
6778
6779 /* Thresholds for cloud detection... */
6780 const double ccmin = 0.01, cwmin = 1e-6;
6781
6782 /* Loop over columns... */
6783#pragma omp parallel for default(shared) collapse(2)
6784 for (int ix = 0; ix < met->nx; ix++)
6785 for (int iy = 0; iy < met->ny; iy++) {
6786
6787 /* Init... */
6788 met->pct[ix][iy] = NAN;
6789 met->pcb[ix][iy] = NAN;
6790 met->cl[ix][iy] = 0;
6791
6792 /* Loop over pressure levels... */
6793 for (int ip = 0; ip < met->np - 1; ip++) {
6794
6795 /* Check pressure... */
6796 if (met->p[ip] > met->ps[ix][iy] || met->p[ip] < P(20.))
6797 continue;
6798
6799 /* Check ice water and liquid water content... */
6800 if (met->cc[ix][iy][ip] > ccmin
6801 && (met->iwc[ix][iy][ip] > cwmin
6802 || met->rwc[ix][iy][ip] > cwmin
6803 || met->lwc[ix][iy][ip] > cwmin
6804 || met->swc[ix][iy][ip] > cwmin)) {
6805
6806 /* Get cloud top pressure ... */
6807 met->pct[ix][iy]
6808 = (float) (0.5 * (met->p[ip] + (float) met->p[ip + 1]));
6809
6810 /* Get cloud bottom pressure ... */
6811 if (!isfinite(met->pcb[ix][iy]))
6812 met->pcb[ix][iy]
6813 = (float) (0.5 * (met->p[ip] + met->p[MAX(ip - 1, 0)]));
6814 }
6815
6816 /* Get cloud water... */
6817 met->cl[ix][iy] += (float)
6818 (0.5 * (met->lwc[ix][iy][ip] + met->lwc[ix][iy][ip + 1]
6819 + met->rwc[ix][iy][ip] + met->rwc[ix][iy][ip + 1]
6820 + met->iwc[ix][iy][ip] + met->iwc[ix][iy][ip + 1]
6821 + met->swc[ix][iy][ip] + met->swc[ix][iy][ip + 1])
6822 * 100. * (met->p[ip] - met->p[ip + 1]) / G0);
6823 }
6824 }
6825}

◆ read_met_detrend()

void read_met_detrend ( const 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 6829 of file mptrac.c.

6831 {
6832
6833 met_t *help;
6834
6835 /* Check parameters... */
6836 if (ctl->met_detrend <= 0)
6837 return;
6838
6839 /* Set timer... */
6840 SELECT_TIMER("READ_MET_DETREND", "METPROC", NVTX_READ);
6841 LOG(2, "Detrend meteo data...");
6842
6843 /* Allocate... */
6844 ALLOC(help, met_t, 1);
6845
6846 /* Calculate standard deviation... */
6847 const double sigma = ctl->met_detrend / 2.355;
6848 const double tssq = 2. * SQR(sigma);
6849
6850 /* Calculate box size in latitude... */
6851 int sy = (int) (3. * DY2DEG(sigma) / fabs(met->lat[1] - met->lat[0]));
6852 sy = MIN(MAX(1, sy), met->ny / 2);
6853
6854 /* Calculate background... */
6855#pragma omp parallel for default(shared) collapse(2)
6856 for (int ix = 0; ix < met->nx; ix++) {
6857 for (int iy = 0; iy < met->ny; iy++) {
6858
6859 /* Calculate Cartesian coordinates... */
6860 double x0[3];
6861 geo2cart(0.0, met->lon[ix], met->lat[iy], x0);
6862
6863 /* Calculate box size in longitude... */
6864 int sx =
6865 (int) (3. * DX2DEG(sigma, met->lat[iy]) /
6866 fabs(met->lon[1] - met->lon[0]));
6867 sx = MIN(MAX(1, sx), met->nx / 2);
6868
6869 /* Init... */
6870 float wsum = 0;
6871 for (int ip = 0; ip < met->np; ip++) {
6872 help->t[ix][iy][ip] = 0;
6873 help->u[ix][iy][ip] = 0;
6874 help->v[ix][iy][ip] = 0;
6875 help->w[ix][iy][ip] = 0;
6876 }
6877
6878 /* Loop over neighboring grid points... */
6879 for (int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
6880 int ix3 = ix2;
6881 if (ix3 < 0)
6882 ix3 += met->nx;
6883 else if (ix3 >= met->nx)
6884 ix3 -= met->nx;
6885 for (int iy2 = MAX(iy - sy, 0);
6886 iy2 <= MIN(iy + sy, met->ny - 1); iy2++) {
6887
6888 /* Calculate Cartesian coordinates... */
6889 double x1[3];
6890 geo2cart(0.0, met->lon[ix3], met->lat[iy2], x1);
6891
6892 /* Calculate weighting factor... */
6893 const float w = (float) exp(-DIST2(x0, x1) / tssq);
6894
6895 /* Add data... */
6896 wsum += w;
6897 for (int ip = 0; ip < met->np; ip++) {
6898 help->t[ix][iy][ip] += w * met->t[ix3][iy2][ip];
6899 help->u[ix][iy][ip] += w * met->u[ix3][iy2][ip];
6900 help->v[ix][iy][ip] += w * met->v[ix3][iy2][ip];
6901 help->w[ix][iy][ip] += w * met->w[ix3][iy2][ip];
6902 }
6903 }
6904 }
6905
6906 /* Normalize... */
6907 for (int ip = 0; ip < met->np; ip++) {
6908 help->t[ix][iy][ip] /= wsum;
6909 help->u[ix][iy][ip] /= wsum;
6910 help->v[ix][iy][ip] /= wsum;
6911 help->w[ix][iy][ip] /= wsum;
6912 }
6913 }
6914 }
6915
6916 /* Subtract background... */
6917#pragma omp parallel for default(shared) collapse(3)
6918 for (int ix = 0; ix < met->nx; ix++)
6919 for (int iy = 0; iy < met->ny; iy++)
6920 for (int ip = 0; ip < met->np; ip++) {
6921 met->t[ix][iy][ip] -= help->t[ix][iy][ip];
6922 met->u[ix][iy][ip] -= help->u[ix][iy][ip];
6923 met->v[ix][iy][ip] -= help->v[ix][iy][ip];
6924 met->w[ix][iy][ip] -= help->w[ix][iy][ip];
6925 }
6926
6927 /* Free... */
6928 free(help);
6929}
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:985
#define DIST2(a, b)
Calculate the squared Euclidean distance between two points in Cartesian coordinates.
Definition: mptrac.h:594
double met_detrend
FWHM of horizontal Gaussian used for detrending [km].
Definition: mptrac.h:2571
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 6933 of file mptrac.c.

6934 {
6935
6936 /* Set timer... */
6937 SELECT_TIMER("READ_MET_EXTRAPOLATE", "METPROC", NVTX_READ);
6938 LOG(2, "Extrapolate meteo data...");
6939
6940 /* Loop over columns... */
6941#pragma omp parallel for default(shared) collapse(2)
6942 for (int ix = 0; ix < met->nx; ix++)
6943 for (int iy = 0; iy < met->ny; iy++) {
6944
6945 /* Find lowest valid data point... */
6946 int ip0;
6947 for (ip0 = met->np - 1; ip0 >= 0; ip0--)
6948 if (!isfinite(met->t[ix][iy][ip0])
6949 || !isfinite(met->u[ix][iy][ip0])
6950 || !isfinite(met->v[ix][iy][ip0])
6951 || !isfinite(met->w[ix][iy][ip0]))
6952 break;
6953
6954 /* Extrapolate... */
6955 for (int ip = ip0; ip >= 0; ip--) {
6956 met->t[ix][iy][ip] = met->t[ix][iy][ip + 1];
6957 met->u[ix][iy][ip] = met->u[ix][iy][ip + 1];
6958 met->v[ix][iy][ip] = met->v[ix][iy][ip + 1];
6959 met->w[ix][iy][ip] = met->w[ix][iy][ip + 1];
6960 met->h2o[ix][iy][ip] = met->h2o[ix][iy][ip + 1];
6961 met->o3[ix][iy][ip] = met->o3[ix][iy][ip + 1];
6962 met->lwc[ix][iy][ip] = met->lwc[ix][iy][ip + 1];
6963 met->rwc[ix][iy][ip] = met->rwc[ix][iy][ip + 1];
6964 met->iwc[ix][iy][ip] = met->iwc[ix][iy][ip + 1];
6965 met->swc[ix][iy][ip] = met->swc[ix][iy][ip + 1];
6966 met->cc[ix][iy][ip] = met->cc[ix][iy][ip + 1];
6967 }
6968 }
6969}

◆ read_met_geopot()

void read_met_geopot ( const 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 6973 of file mptrac.c.

6975 {
6976
6977 float *help;
6978
6979 double logp[EP];
6980
6981 int dx = ctl->met_geopot_sx, dy = ctl->met_geopot_sy;
6982
6983 /* Set timer... */
6984 SELECT_TIMER("READ_MET_GEOPOT", "METPROC", NVTX_READ);
6985 LOG(2, "Calculate geopotential heights...");
6986
6987 /* Allocate... */
6988 ALLOC(help, float,
6989 EX * EY * EP);
6990
6991 /* Calculate log pressure... */
6992#pragma omp parallel for default(shared)
6993 for (int ip = 0; ip < met->np; ip++)
6994 logp[ip] = log(met->p[ip]);
6995
6996 /* Apply hydrostatic equation to calculate geopotential heights... */
6997#pragma omp parallel for default(shared) collapse(2)
6998 for (int ix = 0; ix < met->nx; ix++)
6999 for (int iy = 0; iy < met->ny; iy++) {
7000
7001 /* Get surface height and pressure... */
7002 const double zs = met->zs[ix][iy];
7003 const double lnps = log(met->ps[ix][iy]);
7004
7005 /* Get temperature and water vapor at the surface... */
7006 const int ip0 = locate_irr(met->p, met->np, met->ps[ix][iy]);
7007 const double ts = LIN(met->p[ip0], met->t[ix][iy][ip0], met->p[ip0 + 1],
7008 met->t[ix][iy][ip0 + 1], met->ps[ix][iy]);
7009 const double h2os =
7010 LIN(met->p[ip0], met->h2o[ix][iy][ip0], met->p[ip0 + 1],
7011 met->h2o[ix][iy][ip0 + 1], met->ps[ix][iy]);
7012
7013 /* Upper part of profile... */
7014 met->z[ix][iy][ip0 + 1]
7015 = (float) (zs +
7016 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
7017 met->t[ix][iy][ip0 + 1], met->h2o[ix][iy][ip0 + 1]));
7018 for (int ip = ip0 + 2; ip < met->np; ip++)
7019 met->z[ix][iy][ip]
7020 = (float) (met->z[ix][iy][ip - 1] +
7021 ZDIFF(logp[ip - 1], met->t[ix][iy][ip - 1],
7022 met->h2o[ix][iy][ip - 1], logp[ip],
7023 met->t[ix][iy][ip], met->h2o[ix][iy][ip]));
7024
7025 /* Lower part of profile... */
7026 met->z[ix][iy][ip0]
7027 = (float) (zs +
7028 ZDIFF(lnps, ts, h2os, logp[ip0],
7029 met->t[ix][iy][ip0], met->h2o[ix][iy][ip0]));
7030 for (int ip = ip0 - 1; ip >= 0; ip--)
7031 met->z[ix][iy][ip]
7032 = (float) (met->z[ix][iy][ip + 1] +
7033 ZDIFF(logp[ip + 1], met->t[ix][iy][ip + 1],
7034 met->h2o[ix][iy][ip + 1], logp[ip],
7035 met->t[ix][iy][ip], met->h2o[ix][iy][ip]));
7036 }
7037
7038 /* Check control parameters... */
7039 if (dx == 0 || dy == 0)
7040 return;
7041
7042 /* Default smoothing parameters... */
7043 if (dx < 0 || dy < 0) {
7044 if (fabs(met->lon[1] - met->lon[0]) < 0.5) {
7045 dx = 3;
7046 dy = 2;
7047 } else {
7048 dx = 6;
7049 dy = 4;
7050 }
7051 }
7052
7053 /* Calculate weights for smoothing... */
7054 float ws[dx + 1][dy + 1];
7055#pragma omp parallel for default(shared) collapse(2)
7056 for (int ix = 0; ix <= dx; ix++)
7057 for (int iy = 0; iy < dy; iy++)
7058 ws[ix][iy] = (1.0f - (float) ix / (float) dx)
7059 * (1.0f - (float) iy / (float) dy);
7060
7061 /* Copy data... */
7062#pragma omp parallel for default(shared) collapse(3)
7063 for (int ix = 0; ix < met->nx; ix++)
7064 for (int iy = 0; iy < met->ny; iy++)
7065 for (int ip = 0; ip < met->np; ip++)
7066 help[ARRAY_3D(ip, ix, met->nx, iy, met->ny)] = met->z[ix][iy][ip];
7067
7068 /* Horizontal smoothing... */
7069#pragma omp parallel for default(shared) collapse(3)
7070 for (int ip = 0; ip < met->np; ip++)
7071 for (int ix = 0; ix < met->nx; ix++)
7072 for (int iy = 0; iy < met->ny; iy++) {
7073 float res = 0, wsum = 0;
7074 int iy0 = MAX(iy - dy + 1, 0);
7075 int iy1 = MIN(iy + dy - 1, met->ny - 1);
7076 for (int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
7077 int ix3 = ix2;
7078 if (ix3 < 0)
7079 ix3 += met->nx;
7080 else if (ix3 >= met->nx)
7081 ix3 -= met->nx;
7082 for (int iy2 = iy0; iy2 <= iy1; ++iy2)
7083 if (isfinite(help[ARRAY_3D(ip, ix3, met->nx, iy2, met->ny)])) {
7084 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
7085 res += w * help[ARRAY_3D(ip, ix3, met->nx, iy2, met->ny)];
7086 wsum += w;
7087 }
7088 }
7089 if (wsum > 0)
7090 met->z[ix][iy][ip] = res / wsum;
7091 else
7092 met->z[ix][iy][ip] = NAN;
7093 }
7094
7095 /* Free... */
7096 free(help);
7097}
#define ZDIFF(lnp0, t0, h2o0, lnp1, t1, h2o1)
Calculate geopotential height difference.
Definition: mptrac.h:1772
Here is the call graph for this function:

◆ read_met_grid()

void read_met_grid ( const char *  filename,
const int  ncid,
const 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 7101 of file mptrac.c.

7105 {
7106
7107 char levname[LEN], tstr[10];
7108
7109 double rtime = 0, r, r2;
7110
7111 int varid, year2, mon2, day2, hour2, min2, sec2,
7112 year, mon, day, hour, min, sec;
7113
7114 size_t np;
7115
7116 /* Set timer... */
7117 SELECT_TIMER("READ_MET_GRID", "INPUT", NVTX_READ);
7118 LOG(2, "Read meteo grid information...");
7119
7120 /* MPTRAC meteo files... */
7121 if (ctl->met_clams == 0) {
7122
7123 /* Get time from filename... */
7124 met->time = time_from_filename(filename, 16);
7125
7126 /* Check time information from data file... */
7127 jsec2time(met->time, &year, &mon, &day, &hour, &min, &sec, &r);
7128 if (nc_inq_varid(ncid, "time", &varid) == NC_NOERR) {
7129 NC(nc_get_var_double(ncid, varid, &rtime));
7130 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
7131 WARN("Time information in meteo file does not match filename!");
7132 } else
7133 WARN("Time information in meteo file is missing!");
7134 }
7135
7136 /* CLaMS meteo files... */
7137 else {
7138
7139 /* Read time from file... */
7140 NC_GET_DOUBLE("time", &rtime, 0);
7141
7142 /* Get time from filename (considering the century)... */
7143 if (rtime < 0)
7144 sprintf(tstr, "19%.2s", &filename[strlen(filename) - 11]);
7145 else
7146 sprintf(tstr, "20%.2s", &filename[strlen(filename) - 11]);
7147 year = atoi(tstr);
7148 sprintf(tstr, "%.2s", &filename[strlen(filename) - 9]);
7149 mon = atoi(tstr);
7150 sprintf(tstr, "%.2s", &filename[strlen(filename) - 7]);
7151 day = atoi(tstr);
7152 sprintf(tstr, "%.2s", &filename[strlen(filename) - 5]);
7153 hour = atoi(tstr);
7154 time2jsec(year, mon, day, hour, 0, 0, 0, &met->time);
7155 }
7156
7157 /* Check time... */
7158 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
7159 || day < 1 || day > 31 || hour < 0 || hour > 23)
7160 ERRMSG("Cannot read time from filename!");
7161 jsec2time(met->time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
7162 LOG(2, "Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
7163 met->time, year2, mon2, day2, hour2, min2);
7164
7165 /* Get grid dimensions... */
7166 NC_INQ_DIM("lon", &met->nx, 2, EX);
7167 LOG(2, "Number of longitudes: %d", met->nx);
7168
7169 NC_INQ_DIM("lat", &met->ny, 2, EY);
7170 LOG(2, "Number of latitudes: %d", met->ny);
7171
7172 int dimid2;
7173 sprintf(levname, "lev");
7174 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
7175 sprintf(levname, "plev");
7176 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
7177 sprintf(levname, "hybrid");
7178
7179 NC_INQ_DIM(levname, &met->np, 1, EP);
7180 if (met->np == 1) {
7181 sprintf(levname, "lev_2");
7182 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR) {
7183 sprintf(levname, "plev");
7184 NC(nc_inq_dimid(ncid, levname, &dimid2));
7185 }
7186 NC(nc_inq_dimlen(ncid, dimid2, &np));
7187 met->np = (int) np;
7188 }
7189 LOG(2, "Number of levels: %d", met->np);
7190 if (met->np < 2 || met->np > EP)
7191 ERRMSG("Number of levels out of range!");
7192
7193 /* Read longitudes and latitudes... */
7194 NC_GET_DOUBLE("lon", met->lon, 1);
7195 LOG(2, "Longitudes: %g, %g ... %g deg",
7196 met->lon[0], met->lon[1], met->lon[met->nx - 1]);
7197 NC_GET_DOUBLE("lat", met->lat, 1);
7198 LOG(2, "Latitudes: %g, %g ... %g deg",
7199 met->lat[0], met->lat[1], met->lat[met->ny - 1]);
7200
7201 /* Read pressure levels... */
7202 if (ctl->met_np <= 0) {
7203 NC_GET_DOUBLE(levname, met->p, 1);
7204 for (int ip = 0; ip < met->np; ip++)
7205 met->p[ip] /= 100.;
7206 LOG(2, "Altitude levels: %g, %g ... %g km",
7207 Z(met->p[0]), Z(met->p[1]), Z(met->p[met->np - 1]));
7208 LOG(2, "Pressure levels: %g, %g ... %g hPa",
7209 met->p[0], met->p[1], met->p[met->np - 1]);
7210 }
7211
7212 /* Read hybrid levels... */
7213 if (strcasecmp(levname, "hybrid") == 0)
7214 NC_GET_DOUBLE("hybrid", met->hybrid, 1);
7215}
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:9060
double time_from_filename(const char *filename, const int offset)
Extracts and converts a timestamp from a filename to Julian seconds.
Definition: mptrac.c:9159
double hybrid[EP]
Model hybrid levels.
Definition: mptrac.h:3390
Here is the call graph for this function:

◆ read_met_levels()

void read_met_levels ( const int  ncid,
const 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 7219 of file mptrac.c.

7222 {
7223
7224 /* Set timer... */
7225 SELECT_TIMER("READ_MET_LEVELS", "INPUT", NVTX_READ);
7226 LOG(2, "Read level data...");
7227
7228 /* Read temperature... */
7229 if (!read_met_nc_3d(ncid, "t", "T", "temp", "TEMP", ctl, met, met->t, 1.0))
7230 ERRMSG("Cannot read temperature!");
7231
7232 /* Read horizontal wind and vertical velocity... */
7233 if (!read_met_nc_3d(ncid, "u", "U", NULL, NULL, ctl, met, met->u, 1.0))
7234 ERRMSG("Cannot read zonal wind!");
7235 if (!read_met_nc_3d(ncid, "v", "V", NULL, NULL, ctl, met, met->v, 1.0))
7236 ERRMSG("Cannot read meridional wind!");
7237 if (!read_met_nc_3d
7238 (ncid, "w", "W", "omega", "OMEGA", ctl, met, met->w, 0.01f))
7239 WARN("Cannot read vertical velocity!");
7240
7241 /* Read water vapor... */
7242 if (!ctl->met_relhum) {
7243 if (!read_met_nc_3d
7244 (ncid, "q", "Q", "sh", "SH", ctl, met, met->h2o, (float) (MA / MH2O)))
7245 WARN("Cannot read specific humidity!");
7246 } else {
7247 if (!read_met_nc_3d
7248 (ncid, "rh", "RH", NULL, NULL, ctl, met, met->h2o, 0.01f))
7249 WARN("Cannot read relative humidity!");
7250#pragma omp parallel for default(shared) collapse(2)
7251 for (int ix = 0; ix < met->nx; ix++)
7252 for (int iy = 0; iy < met->ny; iy++)
7253 for (int ip = 0; ip < met->np; ip++) {
7254 double pw = met->h2o[ix][iy][ip] * PSAT(met->t[ix][iy][ip]);
7255 met->h2o[ix][iy][ip] =
7256 (float) (pw / (met->p[ip] - (1.0 - EPS) * pw));
7257 }
7258 }
7259
7260 /* Read ozone... */
7261 if (!read_met_nc_3d
7262 (ncid, "o3", "O3", NULL, NULL, ctl, met, met->o3, (float) (MA / MO3)))
7263 WARN("Cannot read ozone data!");
7264
7265 /* Read cloud data... */
7266 if (!read_met_nc_3d
7267 (ncid, "clwc", "CLWC", NULL, NULL, ctl, met, met->lwc, 1.0))
7268 WARN("Cannot read cloud liquid water content!");
7269 if (!read_met_nc_3d
7270 (ncid, "crwc", "CRWC", NULL, NULL, ctl, met, met->rwc, 1.0))
7271 WARN("Cannot read cloud rain water content!");
7272 if (!read_met_nc_3d
7273 (ncid, "ciwc", "CIWC", NULL, NULL, ctl, met, met->iwc, 1.0))
7274 WARN("Cannot read cloud ice water content!");
7275 if (!read_met_nc_3d
7276 (ncid, "cswc", "CSWC", NULL, NULL, ctl, met, met->swc, 1.0))
7277 WARN("Cannot read cloud snow water content!");
7278 if (!read_met_nc_3d(ncid, "cc", "CC", NULL, NULL, ctl, met, met->cc, 1.0))
7279 WARN("Cannot read cloud cover!");
7280
7281 /* Read zeta and zeta_dot... */
7282 if (!read_met_nc_3d
7283 (ncid, "ZETA", "zeta", NULL, NULL, ctl, met, met->zetal, 1.0))
7284 WARN("Cannot read ZETA!");
7285 if (!read_met_nc_3d
7286 (ncid, "ZETA_DOT_TOT", "ZETA_DOT_clr", "zeta_dot_clr",
7287 NULL, ctl, met, met->zeta_dotl, 0.00001157407f))
7288 WARN("Cannot read ZETA_DOT!");
7289
7290 /* Store velocities on model levels... */
7291 if (ctl->met_vert_coord != 0) {
7292 for (int ix = 0; ix < met->nx; ix++)
7293 for (int iy = 0; iy < met->ny; iy++)
7294 for (int ip = 0; ip < met->np; ip++) {
7295 met->ul[ix][iy][ip] = met->u[ix][iy][ip];
7296 met->vl[ix][iy][ip] = met->v[ix][iy][ip];
7297 met->wl[ix][iy][ip] = met->w[ix][iy][ip];
7298 }
7299
7300 /* Save number of model levels... */
7301 met->npl = met->np;
7302 }
7303
7304 /* Read pressure on model levels... */
7305 if (ctl->met_np > 0 || ctl->met_vert_coord != 0) {
7306
7307 /* Read 3-D pressure field... */
7308 if (ctl->met_vert_coord == 1) {
7309 if (!read_met_nc_3d
7310 (ncid, "pl", "PL", "pressure", "PRESSURE", ctl, met, met->pl,
7311 0.01f))
7312 if (!read_met_nc_3d
7313 (ncid, "press", "PRESS", NULL, NULL, ctl, met, met->pl, 1.0))
7314 ERRMSG("Cannot read pressure on model levels!");
7315 }
7316
7317 /* Calculate pressure from a and b coefficients... */
7318 else {
7319
7320 /* Read a and b coefficients... */
7321 int varid;
7322 double hyam[EP], hybm[EP];
7323 NC_GET_DOUBLE("hyam", hyam, 1);
7324 NC_GET_DOUBLE("hybm", hybm, 1);
7325
7326 /* Calculate pressure... */
7327 for (int ix = 0; ix < met->nx; ix++)
7328 for (int iy = 0; iy < met->ny; iy++)
7329 for (int ip = 0; ip < met->np; ip++)
7330 met->pl[ix][iy][ip] =
7331 (float) (hyam[ip] / 100. + hybm[ip] * met->ps[ix][iy]);
7332 }
7333
7334 /* Check ordering of pressure levels... */
7335 for (int ix = 0; ix < met->nx; ix++)
7336 for (int iy = 0; iy < met->ny; iy++)
7337 for (int ip = 1; ip < met->np; ip++)
7338 if ((met->pl[ix][iy][0] > met->pl[ix][iy][1]
7339 && met->pl[ix][iy][ip - 1] <= met->pl[ix][iy][ip])
7340 || (met->pl[ix][iy][0] < met->pl[ix][iy][1]
7341 && met->pl[ix][iy][ip - 1] >= met->pl[ix][iy][ip]))
7342 ERRMSG("Pressure profiles are not monotonic!");
7343 }
7344
7345 /* Interpolate from model levels to pressure levels... */
7346 if (ctl->met_np > 0) {
7347
7348 /* Interpolate variables... */
7349 read_met_ml2pl(ctl, met, met->t, "T");
7350 read_met_ml2pl(ctl, met, met->u, "U");
7351 read_met_ml2pl(ctl, met, met->v, "V");
7352 read_met_ml2pl(ctl, met, met->w, "W");
7353 read_met_ml2pl(ctl, met, met->h2o, "H2O");
7354 read_met_ml2pl(ctl, met, met->o3, "O3");
7355 read_met_ml2pl(ctl, met, met->lwc, "LWC");
7356 read_met_ml2pl(ctl, met, met->rwc, "RWC");
7357 read_met_ml2pl(ctl, met, met->iwc, "IWC");
7358 read_met_ml2pl(ctl, met, met->swc, "SWC");
7359 read_met_ml2pl(ctl, met, met->cc, "CC");
7360
7361 /* Set new pressure levels... */
7362 met->np = ctl->met_np;
7363 for (int ip = 0; ip < met->np; ip++)
7364 met->p[ip] = ctl->met_p[ip];
7365 }
7366
7367 /* Check ordering of pressure levels... */
7368 for (int ip = 1; ip < met->np; ip++)
7369 if (met->p[ip - 1] < met->p[ip])
7370 ERRMSG("Pressure levels must be descending!");
7371}
void read_met_ml2pl(const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname)
Interpolates meteorological data to specified pressure levels.
Definition: mptrac.c:7375
int read_met_nc_3d(const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const ctl_t *ctl, const met_t *met, float dest[EX][EY][EP], const float scl)
Reads a 3-dimensional meteorological variable from a NetCDF file.
Definition: mptrac.c:7727
#define MH2O
Molar mass of water vapor [g/mol].
Definition: mptrac.h:202
#define MO3
Molar mass of ozone [g/mol].
Definition: mptrac.h:207
int met_vert_coord
Vertical coordinate of input meteo data (0=pressure-level, 1=model-level_pfield, 2=model-level_abcoef...
Definition: mptrac.h:2479
Here is the call graph for this function:

◆ read_met_ml2pl()

void read_met_ml2pl ( const ctl_t ctl,
const met_t met,
float  var[EX][EY][EP],
const 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 7375 of file mptrac.c.

7379 {
7380
7381 double aux[EP], p[EP];
7382
7383 /* Set timer... */
7384 SELECT_TIMER("READ_MET_ML2PL", "METPROC", NVTX_READ);
7385 LOG(2, "Interpolate meteo data to pressure levels: %s", varname);
7386
7387 /* Loop over columns... */
7388#pragma omp parallel for default(shared) private(aux,p) collapse(2)
7389 for (int ix = 0; ix < met->nx; ix++)
7390 for (int iy = 0; iy < met->ny; iy++) {
7391
7392 /* Copy pressure profile... */
7393 for (int ip = 0; ip < met->np; ip++)
7394 p[ip] = met->pl[ix][iy][ip];
7395
7396 /* Interpolate... */
7397 for (int ip = 0; ip < ctl->met_np; ip++) {
7398 double pt = ctl->met_p[ip];
7399 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
7400 pt = p[0];
7401 else if ((pt > p[met->np - 1] && p[1] > p[0])
7402 || (pt < p[met->np - 1] && p[1] < p[0]))
7403 pt = p[met->np - 1];
7404 int ip2 = locate_irr(p, met->np, pt);
7405 aux[ip] = LIN(p[ip2], var[ix][iy][ip2],
7406 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
7407 }
7408
7409 /* Copy data... */
7410 for (int ip = 0; ip < ctl->met_np; ip++)
7411 var[ix][iy][ip] = (float) aux[ip];
7412 }
7413}
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 7417 of file mptrac.c.

7418 {
7419
7420 /* Set timer... */
7421 SELECT_TIMER("READ_MET_MONOTONIZE", "METPROC", NVTX_READ);
7422 LOG(2, "Make zeta profiles monotone...");
7423
7424 /* Create monotone zeta profiles... */
7425#pragma omp parallel for default(shared) collapse(2)
7426 for (int i = 0; i < met->nx; i++)
7427 for (int j = 0; j < met->ny; j++) {
7428 int k = 1;
7429
7430 while (k < met->npl) { /* Check if there is an inversion at level k... */
7431 if ((met->zetal[i][j][k - 1] >= met->zetal[i][j][k])) {
7432 /* Find the upper level k+l over the inversion... */
7433 int l = 0;
7434 do {
7435 l++;
7436 }
7437 while ((met->zetal[i][j][k - 1] >=
7438 met->zetal[i][j][k + l]) & (k + l < met->npl));
7439
7440 /* Interpolate linear between the top and bottom
7441 of the inversion... */
7442 float s =
7443 (float) (met->zetal[i][j][k + l] - met->zetal[i][j][k - 1])
7444 / (float) (met->hybrid[k + l] - met->hybrid[k - 1]);
7445
7446 for (int m = k; m < k + l; m++) {
7447 float d = (float) (met->hybrid[m] - met->hybrid[k - 1]);
7448 met->zetal[i][j][m] = s * d + met->zetal[i][j][k - 1];
7449 }
7450
7451 /* Search for more inversions above the last inversion ... */
7452 k = k + l;
7453 } else {
7454 k++;
7455 }
7456 }
7457 }
7458
7459 /* Create monotone pressure profiles... */
7460#pragma omp parallel for default(shared) collapse(2)
7461 for (int i = 0; i < met->nx; i++)
7462 for (int j = 0; j < met->ny; j++) {
7463 int k = 1;
7464
7465 while (k < met->npl) { /* Check if there is an inversion at level k... */
7466 if ((met->pl[i][j][k - 1] <= met->pl[i][j][k])) {
7467
7468 /* Find the upper level k+l over the inversion... */
7469 int l = 0;
7470 do {
7471 l++;
7472 }
7473 while ((met->pl[i][j][k - 1] <= met->pl[i][j][k + l]) & (k + l <
7474 met->npl));
7475
7476 /* Interpolate linear between the top and bottom
7477 of the inversion... */
7478 float s = (float) (met->pl[i][j][k + l] - met->pl[i][j][k - 1])
7479 / (float) (met->hybrid[k + l] - met->hybrid[k - 1]);
7480
7481 for (int m = k; m < k + l; m++) {
7482 float d = (float) (met->hybrid[m] - met->hybrid[k - 1]);
7483 met->pl[i][j][m] = s * d + met->pl[i][j][k - 1];
7484 }
7485
7486 /* Search for more inversions above the last inversion ... */
7487 k += l;
7488 } else {
7489 k++;
7490 }
7491 }
7492 }
7493}

◆ read_met_nc()

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

Reads meteorological data from a NetCDF file and processes it.

This function reads meteorological data from a NetCDF file specified by the filename parameter, using the NetCDF library. It reads grid, surface, and vertical level data, processes the data (including extrapolation, boundary conditions, and downsampling), and calculates various derived meteorological fields such as geopotential heights, potential vorticity, cloud properties, and convective available potential energy (CAPE).

Parameters
filenameA constant character pointer representing the name of the NetCDF file to read the meteorological data from.
ctlA pointer to a ctl_t structure, which contains control parameters for reading and processing the meteorological data.
climA pointer to a clim_t structure that holds climatological data, used in the calculation of derived properties such as CAPE and tropopause data.
metA pointer to a met_t structure that will store the meteorological data read and processed from the NetCDF file.
Returns
Returns 1 on success, or 0 if the file cannot be opened.
Note
  • The function opens the NetCDF file in read-only mode using nc_open and handles any errors during the file opening process.
  • The function reads grid data, vertical level data, and surface data from the file, and processes the data to calculate additional meteorological parameters.
  • If the file cannot be opened, the function logs a warning and returns 0.
  • It is important to ensure that the NetCDF file contains the expected structure for meteorological data (grid, levels, surface data).
Author
Lars Hoffmann

Definition at line 7497 of file mptrac.c.

7501 {
7502
7503 int ncid;
7504
7505 /* Open netCDF file... */
7506 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7507 WARN("Cannot open file!");
7508 return 0;
7509 }
7510
7511 /* Read coordinates of meteo data... */
7512 read_met_grid(filename, ncid, ctl, met);
7513
7514 /* Read surface data... */
7515 read_met_surface(ncid, ctl, met);
7516
7517 /* Read meteo data on vertical levels... */
7518 read_met_levels(ncid, ctl, met);
7519
7520 /* Extrapolate data for lower boundary... */
7522
7523 /* Fix polar winds... */
7525
7526 /* Create periodic boundary conditions... */
7527 read_met_periodic(met);
7528
7529 /* Downsampling... */
7530 read_met_sample(ctl, met);
7531
7532 /* Calculate geopotential heights... */
7533 read_met_geopot(ctl, met);
7534
7535 /* Calculate potential vorticity... */
7536 read_met_pv(met);
7537
7538 /* Calculate boundary layer data... */
7539 read_met_pbl(ctl, met);
7540
7541 /* Calculate tropopause data... */
7542 read_met_tropo(ctl, clim, met);
7543
7544 /* Calculate cloud properties... */
7545 read_met_cloud(met);
7546
7547 /* Calculate convective available potential energy... */
7548 read_met_cape(ctl, clim, met);
7549
7550 /* Calculate total column ozone... */
7551 read_met_ozone(met);
7552
7553 /* Detrending... */
7554 read_met_detrend(ctl, met);
7555
7556 /* Check meteo data and smooth zeta profiles ... */
7557 if (ctl->advect_vert_coord == 1)
7559
7560 /* Close file... */
7561 NC(nc_close(ncid));
7562
7563 /* Return success... */
7564 return 1;
7565}
void read_met_geopot(const ctl_t *ctl, met_t *met)
Calculates geopotential heights from meteorological data.
Definition: mptrac.c:6973
void read_met_extrapolate(met_t *met)
Extrapolates meteorological data.
Definition: mptrac.c:6933
void read_met_levels(const int ncid, const ctl_t *ctl, met_t *met)
Reads meteorological variables at different vertical levels from a NetCDF file.
Definition: mptrac.c:7219
void read_met_sample(const ctl_t *ctl, met_t *met)
Downsamples meteorological data based on specified parameters.
Definition: mptrac.c:8265
void read_met_cloud(met_t *met)
Calculates cloud-related variables for each grid point.
Definition: mptrac.c:6772
void read_met_pbl(const ctl_t *ctl, met_t *met)
Computes the planetary boundary layer (PBL) pressure based on meteorological data.
Definition: mptrac.c:7873
void read_met_detrend(const ctl_t *ctl, met_t *met)
Detrends meteorological data.
Definition: mptrac.c:6829
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
Definition: mptrac.c:8010
void read_met_grid(const char *filename, const int ncid, const ctl_t *ctl, met_t *met)
Reads meteorological grid information from a NetCDF file.
Definition: mptrac.c:7101
void read_met_monotonize(met_t *met)
Makes zeta and pressure profiles monotone.
Definition: mptrac.c:7417
void read_met_surface(const int ncid, const ctl_t *ctl, met_t *met)
Reads surface meteorological data from a netCDF file and stores it in the meteorological data structu...
Definition: mptrac.c:8437
void read_met_ozone(met_t *met)
Calculates the total column ozone from meteorological ozone data.
Definition: mptrac.c:8236
void read_met_pv(met_t *met)
Calculates potential vorticity (PV) from meteorological data.
Definition: mptrac.c:8130
void read_met_polar_winds(met_t *met)
Applies a fix for polar winds in meteorological data.
Definition: mptrac.c:8071
void read_met_cape(const ctl_t *ctl, const clim_t *clim, met_t *met)
Calculates Convective Available Potential Energy (CAPE) for each grid point.
Definition: mptrac.c:6657
Here is the call graph for this function:

◆ read_met_nc_2d()

int read_met_nc_2d ( const int  ncid,
const char *  varname,
const char *  varname2,
const char *  varname3,
const char *  varname4,
const char *  varname5,
const char *  varname6,
const ctl_t ctl,
const met_t met,
float  dest[EX][EY],
const float  scl,
const 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 7569 of file mptrac.c.

7581 {
7582
7583 char varsel[LEN];
7584
7585 float offset, scalfac;
7586
7587 int varid;
7588
7589 /* Check if variable exists... */
7590 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
7591 sprintf(varsel, "%s", varname);
7592 else if (varname2 != NULL
7593 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
7594 sprintf(varsel, "%s", varname2);
7595 else if (varname3 != NULL
7596 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
7597 sprintf(varsel, "%s", varname3);
7598 else if (varname4 != NULL
7599 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
7600 sprintf(varsel, "%s", varname4);
7601 else if (varname5 != NULL
7602 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
7603 sprintf(varsel, "%s", varname5);
7604 else if (varname6 != NULL
7605 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
7606 sprintf(varsel, "%s", varname6);
7607 else
7608 return 0;
7609
7610 /* Read packed data... */
7611 if (ctl->met_nc_scale
7612 && nc_get_att_float(ncid, varid, "add_offset", &offset) == NC_NOERR
7613 && nc_get_att_float(ncid, varid, "scale_factor",
7614 &scalfac) == NC_NOERR) {
7615
7616 /* Allocate... */
7617 short *help;
7618 ALLOC(help, short,
7619 EX * EY * EP);
7620
7621 /* Read fill value and missing value... */
7622 short fillval, missval;
7623 if (nc_get_att_short(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
7624 fillval = 0;
7625 if (nc_get_att_short(ncid, varid, "missing_value", &missval) != NC_NOERR)
7626 missval = 0;
7627
7628 /* Write info... */
7629 LOG(2, "Read 2-D variable: %s"
7630 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
7631 varsel, fillval, missval, scalfac, offset);
7632
7633 /* Read data... */
7634 NC(nc_get_var_short(ncid, varid, help));
7635
7636 /* Check meteo data layout... */
7637 if (ctl->met_convention != 0)
7638 ERRMSG("Meteo data layout not implemented for packed netCDF files!");
7639
7640 /* Copy and check data... */
7641#pragma omp parallel for default(shared) num_threads(12)
7642 for (int ix = 0; ix < met->nx; ix++)
7643 for (int iy = 0; iy < met->ny; iy++) {
7644 if (init)
7645 dest[ix][iy] = 0;
7646 const short aux = help[ARRAY_2D(iy, ix, met->nx)];
7647 if ((fillval == 0 || aux != fillval)
7648 && (missval == 0 || aux != missval)
7649 && fabsf(aux * scalfac + offset) < 1e14f)
7650 dest[ix][iy] += scl * (aux * scalfac + offset);
7651 else
7652 dest[ix][iy] = NAN;
7653 }
7654
7655 /* Free... */
7656 free(help);
7657 }
7658
7659 /* Unpacked data... */
7660 else {
7661
7662 /* Allocate... */
7663 float *help;
7664 ALLOC(help, float,
7665 EX * EY);
7666
7667 /* Read fill value and missing value... */
7668 float fillval, missval;
7669 if (nc_get_att_float(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
7670 fillval = 0;
7671 if (nc_get_att_float(ncid, varid, "missing_value", &missval) != NC_NOERR)
7672 missval = 0;
7673
7674 /* Write info... */
7675 LOG(2, "Read 2-D variable: %s (FILL = %g, MISS = %g)",
7676 varsel, fillval, missval);
7677
7678 /* Read data... */
7679 NC(nc_get_var_float(ncid, varid, help));
7680
7681 /* Check meteo data layout... */
7682 if (ctl->met_convention == 0) {
7683
7684 /* Copy and check data (ordering: lat, lon)... */
7685#pragma omp parallel for default(shared) num_threads(12)
7686 for (int ix = 0; ix < met->nx; ix++)
7687 for (int iy = 0; iy < met->ny; iy++) {
7688 if (init)
7689 dest[ix][iy] = 0;
7690 const float aux = help[ARRAY_2D(iy, ix, met->nx)];
7691 if ((fillval == 0 || aux != fillval)
7692 && (missval == 0 || aux != missval)
7693 && fabsf(aux) < 1e14f)
7694 dest[ix][iy] += scl * aux;
7695 else
7696 dest[ix][iy] = NAN;
7697 }
7698
7699 } else {
7700
7701 /* Copy and check data (ordering: lon, lat)... */
7702#pragma omp parallel for default(shared) num_threads(12)
7703 for (int iy = 0; iy < met->ny; iy++)
7704 for (int ix = 0; ix < met->nx; ix++) {
7705 if (init)
7706 dest[ix][iy] = 0;
7707 const float aux = help[ARRAY_2D(ix, iy, met->ny)];
7708 if ((fillval == 0 || aux != fillval)
7709 && (missval == 0 || aux != missval)
7710 && fabsf(aux) < 1e14f)
7711 dest[ix][iy] += scl * aux;
7712 else
7713 dest[ix][iy] = NAN;
7714 }
7715 }
7716
7717 /* Free... */
7718 free(help);
7719 }
7720
7721 /* Return... */
7722 return 1;
7723}
int met_nc_scale
Check netCDF scaling factors (0=no, 1=yes).
Definition: mptrac.h:2489
int met_convention
Meteo data layout (0=[lev, lat, lon], 1=[lon, lat, lev]).
Definition: mptrac.h:2475

◆ read_met_nc_3d()

int read_met_nc_3d ( const int  ncid,
const char *  varname,
const char *  varname2,
const char *  varname3,
const char *  varname4,
const ctl_t ctl,
const met_t met,
float  dest[EX][EY][EP],
const 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).
varname5An alternative name of the variable to read (in case varname4 is not found).
varname6An alternative name of the variable to read (in case varname5 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 7727 of file mptrac.c.

7736 {
7737
7738 char varsel[LEN];
7739
7740 float offset, scalfac;
7741
7742 int varid;
7743
7744 /* Check if variable exists... */
7745 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
7746 sprintf(varsel, "%s", varname);
7747 else if (varname2 != NULL
7748 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
7749 sprintf(varsel, "%s", varname2);
7750 else if (varname3 != NULL
7751 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
7752 sprintf(varsel, "%s", varname3);
7753 else if (varname4 != NULL
7754 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
7755 sprintf(varsel, "%s", varname4);
7756 else
7757 return 0;
7758
7759 /* Read packed data... */
7760 if (ctl->met_nc_scale
7761 && nc_get_att_float(ncid, varid, "add_offset", &offset) == NC_NOERR
7762 && nc_get_att_float(ncid, varid, "scale_factor",
7763 &scalfac) == NC_NOERR) {
7764
7765 /* Allocate... */
7766 short *help;
7767 ALLOC(help, short,
7768 EX * EY * EP);
7769
7770 /* Read fill value and missing value... */
7771 short fillval, missval;
7772 if (nc_get_att_short(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
7773 fillval = 0;
7774 if (nc_get_att_short(ncid, varid, "missing_value", &missval) != NC_NOERR)
7775 missval = 0;
7776
7777 /* Write info... */
7778 LOG(2, "Read 3-D variable: %s "
7779 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
7780 varsel, fillval, missval, scalfac, offset);
7781
7782 /* Read data... */
7783 NC(nc_get_var_short(ncid, varid, help));
7784
7785 /* Check meteo data layout... */
7786 if (ctl->met_convention != 0)
7787 ERRMSG("Meteo data layout not implemented for packed netCDF files!");
7788
7789 /* Copy and check data... */
7790#pragma omp parallel for default(shared) num_threads(12)
7791 for (int ix = 0; ix < met->nx; ix++)
7792 for (int iy = 0; iy < met->ny; iy++)
7793 for (int ip = 0; ip < met->np; ip++) {
7794 const short aux = help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)];
7795 if ((fillval == 0 || aux != fillval)
7796 && (missval == 0 || aux != missval)
7797 && fabsf(aux * scalfac + offset) < 1e14f)
7798 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
7799 else
7800 dest[ix][iy][ip] = NAN;
7801 }
7802
7803 /* Free... */
7804 free(help);
7805 }
7806
7807 /* Unpacked data... */
7808 else {
7809
7810 /* Allocate... */
7811 float *help;
7812 ALLOC(help, float,
7813 EX * EY * EP);
7814
7815 /* Read fill value and missing value... */
7816 float fillval, missval;
7817 if (nc_get_att_float(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
7818 fillval = 0;
7819 if (nc_get_att_float(ncid, varid, "missing_value", &missval) != NC_NOERR)
7820 missval = 0;
7821
7822 /* Write info... */
7823 LOG(2, "Read 3-D variable: %s (FILL = %g, MISS = %g)",
7824 varsel, fillval, missval);
7825
7826 /* Read data... */
7827 NC(nc_get_var_float(ncid, varid, help));
7828
7829 /* Check meteo data layout... */
7830 if (ctl->met_convention == 0) {
7831
7832 /* Copy and check data (ordering: lev, lat, lon)... */
7833#pragma omp parallel for default(shared) num_threads(12)
7834 for (int ix = 0; ix < met->nx; ix++)
7835 for (int iy = 0; iy < met->ny; iy++)
7836 for (int ip = 0; ip < met->np; ip++) {
7837 const float aux = help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)];
7838 if ((fillval == 0 || aux != fillval)
7839 && (missval == 0 || aux != missval)
7840 && fabsf(aux) < 1e14f)
7841 dest[ix][iy][ip] = scl * aux;
7842 else
7843 dest[ix][iy][ip] = NAN;
7844 }
7845
7846 } else {
7847
7848 /* Copy and check data (ordering: lon, lat, lev)... */
7849#pragma omp parallel for default(shared) num_threads(12)
7850 for (int ip = 0; ip < met->np; ip++)
7851 for (int iy = 0; iy < met->ny; iy++)
7852 for (int ix = 0; ix < met->nx; ix++) {
7853 const float aux = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
7854 if ((fillval == 0 || aux != fillval)
7855 && (missval == 0 || aux != missval)
7856 && fabsf(aux) < 1e14f)
7857 dest[ix][iy][ip] = scl * aux;
7858 else
7859 dest[ix][iy][ip] = NAN;
7860 }
7861 }
7862
7863 /* Free... */
7864 free(help);
7865 }
7866
7867 /* Return... */
7868 return 1;
7869}

◆ read_met_pbl()

void read_met_pbl ( const ctl_t ctl,
met_t met 
)

Computes the planetary boundary layer (PBL) pressure based on meteorological data.

This function determines the PBL pressure for each grid point using one of four methods: 0. Read PBL pressure from meteo data file.

  1. Read PBL heights from meteo data file and convert to pressure.
  2. Determine PBL pressure based on bulk Richardson number criterion.
  3. Determine PBL pressure Based on potential temperature difference. The calculated PBL height is constrained by user-defined minimum and maximum limits.
Parameters
[in]ctlPointer to the control structure (ctl_t), which contains parameters controlling the PBL calculation.
[in,out]metPointer to the meteorological data structure (met_t), which contains grid and atmospheric data. The met->pbl array is updated with the calculated PBL pressure.

Method 0 (Precomputed PBL pressure from file):

  • Read PBL pressure from meteo data file.

Method 1 (Precomputed PBL height from file):

  • Read PBL height from meteo data file.
  • Interpolates the PBL pressure using the geopotential heights from the meteo file.

Method 2 (Richardson number criterion):

  • Implements a method based on the bulk Richardson number (critical value: Ri = 0.25).
  • Iteratively evaluates vertical levels, calculating wind shear, and thermal gradients, until the Richardson number exceeds the critical threshold.
  • Interpolates between levels to find the precise height.

Method 3 (Potential temperature difference):

  • Computes the PBL height as the altitude where the potential temperature exceeds the surface value by 2 K.
  • Interpolates between levels to find the precise height.

Final Adjustments:

  • Ensures the PBL height respects user-defined minimum and maximum thresholds.
Note
Method 2 is a standard method for estimating PBL depths, but the current implementation seems to underestimate PBL depths compared to ECMWF PBL data or Method 3. Therefore, Method 3, is selected by default. If PBL heights are available from the meteo data files, it is recommended to select Method 1.
Author
Lars Hoffmann

Definition at line 7873 of file mptrac.c.

7875 {
7876
7877 /* Set timer... */
7878 SELECT_TIMER("READ_MET_PBL", "METPROC", NVTX_READ);
7879 LOG(2, "Calculate planetary boundary layer...");
7880
7881 /* Convert PBL height from meteo file to pressure... */
7882 if (ctl->met_pbl == 1) {
7883
7884 /* Loop over grid points... */
7885#pragma omp parallel for default(shared) collapse(2)
7886 for (int ix = 0; ix < met->nx; ix++)
7887 for (int iy = 0; iy < met->ny; iy++) {
7888
7889 /* Get pressure at top of PBL... */
7890 const float z = met->zs[ix][iy] + met->pbl[ix][iy];
7891 const int ip = locate_irr_float(met->z[ix][iy], met->np, z, 0);
7892 met->pbl[ix][iy] =
7893 (float) (LIN(met->z[ix][iy][ip], met->p[ip],
7894 met->z[ix][iy][ip + 1], met->p[ip + 1], z));
7895 }
7896 }
7897
7898 /* Determine PBL based on Richardson number... */
7899 else if (ctl->met_pbl == 2) {
7900
7901 /* Parameters used to estimate the height of the PBL
7902 (e.g., Vogelezang and Holtslag, 1996; Seidel et al., 2012)... */
7903 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
7904
7905 /* Loop over grid points... */
7906#pragma omp parallel for default(shared) collapse(2)
7907 for (int ix = 0; ix < met->nx; ix++)
7908 for (int iy = 0; iy < met->ny; iy++) {
7909
7910 /* Set bottom level of PBL... */
7911 const double pbl_bot = met->ps[ix][iy] * exp(-dz / H0);
7912
7913 /* Find lowest level near the bottom... */
7914 int ip;
7915 for (ip = 1; ip < met->np; ip++)
7916 if (met->p[ip] < pbl_bot)
7917 break;
7918
7919 /* Get near surface data... */
7920 const double h2os = LIN(met->p[ip - 1], met->h2o[ix][iy][ip - 1],
7921 met->p[ip], met->h2o[ix][iy][ip], pbl_bot);
7922 const double tvs = THETAVIRT(pbl_bot, met->ts[ix][iy], h2os);
7923
7924 /* Init... */
7925 double rib_old = 0;
7926
7927 /* Loop over levels... */
7928 for (; ip < met->np; ip++) {
7929
7930 /* Get squared horizontal wind speed... */
7931 double vh2 = SQR(met->u[ix][iy][ip] - met->us[ix][iy])
7932 + SQR(met->v[ix][iy][ip] - met->vs[ix][iy]);
7933 vh2 = MAX(vh2, SQR(umin));
7934
7935 /* Calculate bulk Richardson number... */
7936 const double rib =
7937 G0 * 1e3 * (met->z[ix][iy][ip] - met->zs[ix][iy]) / tvs
7938 * (THETAVIRT(met->p[ip], met->t[ix][iy][ip],
7939 met->h2o[ix][iy][ip]) - tvs) / vh2;
7940
7941 /* Check for critical value... */
7942 if (rib >= rib_crit) {
7943 met->pbl[ix][iy] = (float) (LIN(rib_old, met->p[ip - 1],
7944 rib, met->p[ip], rib_crit));
7945 if (met->pbl[ix][iy] > pbl_bot)
7946 met->pbl[ix][iy] = (float) pbl_bot;
7947 break;
7948 }
7949
7950 /* Save Richardson number... */
7951 rib_old = rib;
7952 }
7953 }
7954 }
7955
7956 /* Determine PBL based on potential temperature... */
7957 if (ctl->met_pbl == 3) {
7958
7959 /* Parameters used to estimate the height of the PBL
7960 (following HYSPLIT model)... */
7961 const double dtheta = 2.0, zmin = 0.1;
7962
7963 /* Loop over grid points... */
7964#pragma omp parallel for default(shared) collapse(2)
7965 for (int ix = 0; ix < met->nx; ix++)
7966 for (int iy = 0; iy < met->ny; iy++) {
7967
7968 /* Potential temperature at the surface... */
7969 const double theta0 = THETA(met->ps[ix][iy], met->ts[ix][iy]);
7970
7971 /* Find topmost level where theta exceeds surface value by 2 K... */
7972 int ip;
7973 for (ip = met->np - 2; ip > 0; ip--)
7974 if (met->p[ip] >= 300.)
7975 if (met->p[ip] > met->ps[ix][iy]
7976 || THETA(met->p[ip], met->t[ix][iy][ip]) <= theta0 + dtheta)
7977 break;
7978
7979 /* Interpolate... */
7980 met->pbl[ix][iy]
7981 = (float) (LIN(THETA(met->p[ip + 1], met->t[ix][iy][ip + 1]),
7982 met->p[ip + 1],
7983 THETA(met->p[ip], met->t[ix][iy][ip]),
7984 met->p[ip], theta0 + dtheta));
7985
7986 /* Check minimum value... */
7987 double pbl_min = met->ps[ix][iy] * exp(-zmin / H0);
7988 if (met->pbl[ix][iy] > pbl_min || met->p[ip] > met->ps[ix][iy])
7989 met->pbl[ix][iy] = (float) pbl_min;
7990 }
7991 }
7992
7993 /* Loop over grid points... */
7994#pragma omp parallel for default(shared) collapse(2)
7995 for (int ix = 0; ix < met->nx; ix++)
7996 for (int iy = 0; iy < met->ny; iy++) {
7997
7998 /* Check minimum value... */
7999 double pbl_min = met->ps[ix][iy] * exp(-ctl->met_pbl_min / H0);
8000 met->pbl[ix][iy] = MIN(met->pbl[ix][iy], (float) pbl_min);
8001
8002 /* Check maximum value... */
8003 double pbl_max = met->ps[ix][iy] * exp(-ctl->met_pbl_max / H0);
8004 met->pbl[ix][iy] = MAX(met->pbl[ix][iy], (float) pbl_max);
8005 }
8006}
Here is the call graph for this function:

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

8011 {
8012
8013 /* Set timer... */
8014 SELECT_TIMER("READ_MET_PERIODIC", "METPROC", NVTX_READ);
8015 LOG(2, "Apply periodic boundary conditions...");
8016
8017 /* Check longitudes... */
8018 if (!(fabs(met->lon[met->nx - 1] - met->lon[0]
8019 + met->lon[1] - met->lon[0] - 360) < 0.01))
8020 return;
8021
8022 /* Increase longitude counter... */
8023 if ((++met->nx) >= EX)
8024 ERRMSG("Cannot create periodic boundary conditions!");
8025
8026 /* Set longitude... */
8027 met->lon[met->nx - 1] = met->lon[met->nx - 2] + met->lon[1] - met->lon[0];
8028
8029 /* Loop over latitudes and pressure levels... */
8030#pragma omp parallel for default(shared)
8031 for (int iy = 0; iy < met->ny; iy++) {
8032 met->ps[met->nx - 1][iy] = met->ps[0][iy];
8033 met->zs[met->nx - 1][iy] = met->zs[0][iy];
8034 met->ts[met->nx - 1][iy] = met->ts[0][iy];
8035 met->us[met->nx - 1][iy] = met->us[0][iy];
8036 met->vs[met->nx - 1][iy] = met->vs[0][iy];
8037 met->ess[met->nx - 1][iy] = met->ess[0][iy];
8038 met->nss[met->nx - 1][iy] = met->nss[0][iy];
8039 met->shf[met->nx - 1][iy] = met->shf[0][iy];
8040 met->lsm[met->nx - 1][iy] = met->lsm[0][iy];
8041 met->sst[met->nx - 1][iy] = met->sst[0][iy];
8042 met->pbl[met->nx - 1][iy] = met->pbl[0][iy];
8043 met->cape[met->nx - 1][iy] = met->cape[0][iy];
8044 met->cin[met->nx - 1][iy] = met->cin[0][iy];
8045 for (int ip = 0; ip < met->np; ip++) {
8046 met->t[met->nx - 1][iy][ip] = met->t[0][iy][ip];
8047 met->u[met->nx - 1][iy][ip] = met->u[0][iy][ip];
8048 met->v[met->nx - 1][iy][ip] = met->v[0][iy][ip];
8049 met->w[met->nx - 1][iy][ip] = met->w[0][iy][ip];
8050 met->h2o[met->nx - 1][iy][ip] = met->h2o[0][iy][ip];
8051 met->o3[met->nx - 1][iy][ip] = met->o3[0][iy][ip];
8052 met->lwc[met->nx - 1][iy][ip] = met->lwc[0][iy][ip];
8053 met->rwc[met->nx - 1][iy][ip] = met->rwc[0][iy][ip];
8054 met->iwc[met->nx - 1][iy][ip] = met->iwc[0][iy][ip];
8055 met->swc[met->nx - 1][iy][ip] = met->swc[0][iy][ip];
8056 met->cc[met->nx - 1][iy][ip] = met->cc[0][iy][ip];
8057 }
8058 for (int ip = 0; ip < met->npl; ip++) {
8059 met->ul[met->nx - 1][iy][ip] = met->ul[0][iy][ip];
8060 met->vl[met->nx - 1][iy][ip] = met->vl[0][iy][ip];
8061 met->wl[met->nx - 1][iy][ip] = met->wl[0][iy][ip];
8062 met->pl[met->nx - 1][iy][ip] = met->pl[0][iy][ip];
8063 met->zetal[met->nx - 1][iy][ip] = met->zetal[0][iy][ip];
8064 met->zeta_dotl[met->nx - 1][iy][ip] = met->zeta_dotl[0][iy][ip];
8065 }
8066 }
8067}

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

8072 {
8073
8074 /* Set timer... */
8075 SELECT_TIMER("READ_MET_POLAR_WINDS", "METPROC", NVTX_READ);
8076 LOG(2, "Apply fix for polar winds...");
8077
8078 /* Check latitudes... */
8079 if (fabs(met->lat[0]) < 89.999 || fabs(met->lat[met->ny - 1]) < 89.999)
8080 return;
8081
8082 /* Loop over hemispheres... */
8083 for (int ihem = 0; ihem < 2; ihem++) {
8084
8085 /* Set latitude indices... */
8086 int i89 = 1, i90 = 0, sign = 1;
8087 if (ihem == 1) {
8088 i89 = met->ny - 2;
8089 i90 = met->ny - 1;
8090 }
8091 if (met->lat[i90] < 0)
8092 sign = -1;
8093
8094 /* Look-up table of cosinus and sinus... */
8095 double clon[EX], slon[EX];
8096#pragma omp parallel for default(shared)
8097 for (int ix = 0; ix < met->nx; ix++) {
8098 clon[ix] = cos(sign * DEG2RAD(met->lon[ix]));
8099 slon[ix] = sin(sign * DEG2RAD(met->lon[ix]));
8100 }
8101
8102 /* Loop over levels... */
8103#pragma omp parallel for default(shared)
8104 for (int ip = 0; ip < met->np; ip++) {
8105
8106 /* Transform 89 degree u and v winds into Cartesian coordinates and take the mean... */
8107 double vel89x = 0, vel89y = 0;
8108 for (int ix = 0; ix < met->nx; ix++) {
8109 vel89x +=
8110 (met->u[ix][i89][ip] * clon[ix] -
8111 met->v[ix][i89][ip] * slon[ix]) / met->nx;
8112 vel89y +=
8113 (met->u[ix][i89][ip] * slon[ix] +
8114 met->v[ix][i89][ip] * clon[ix]) / met->nx;
8115 }
8116
8117 /* Replace 90 degree winds by 89 degree mean... */
8118 for (int ix = 0; ix < met->nx; ix++) {
8119 met->u[ix][i90][ip]
8120 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
8121 met->v[ix][i90][ip]
8122 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
8123 }
8124 }
8125 }
8126}

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

8131 {
8132
8133 double pows[EP];
8134
8135 /* Set timer... */
8136 SELECT_TIMER("READ_MET_PV", "METPROC", NVTX_READ);
8137 LOG(2, "Calculate potential vorticity...");
8138
8139 /* Set powers... */
8140#pragma omp parallel for default(shared)
8141 for (int ip = 0; ip < met->np; ip++)
8142 pows[ip] = pow(1000. / met->p[ip], 0.286);
8143
8144 /* Loop over grid points... */
8145#pragma omp parallel for default(shared)
8146 for (int ix = 0; ix < met->nx; ix++) {
8147
8148 /* Set indices... */
8149 const int ix0 = MAX(ix - 1, 0);
8150 const int ix1 = MIN(ix + 1, met->nx - 1);
8151
8152 /* Loop over grid points... */
8153 for (int iy = 0; iy < met->ny; iy++) {
8154
8155 /* Set indices... */
8156 const int iy0 = MAX(iy - 1, 0);
8157 const int iy1 = MIN(iy + 1, met->ny - 1);
8158
8159 /* Set auxiliary variables... */
8160 const double latr = 0.5 * (met->lat[iy1] + met->lat[iy0]);
8161 const double dx = 1000. * DEG2DX(met->lon[ix1] - met->lon[ix0], latr);
8162 const double dy = 1000. * DEG2DY(met->lat[iy1] - met->lat[iy0]);
8163 const double c0 = cos(DEG2RAD(met->lat[iy0]));
8164 const double c1 = cos(DEG2RAD(met->lat[iy1]));
8165 const double cr = cos(DEG2RAD(latr));
8166 const double vort = 2 * 7.2921e-5 * sin(DEG2RAD(latr));
8167
8168 /* Loop over grid points... */
8169 for (int ip = 0; ip < met->np; ip++) {
8170
8171 /* Get gradients in longitude... */
8172 const double dtdx
8173 = (met->t[ix1][iy][ip] - met->t[ix0][iy][ip]) * pows[ip] / dx;
8174 const double dvdx = (met->v[ix1][iy][ip] - met->v[ix0][iy][ip]) / dx;
8175
8176 /* Get gradients in latitude... */
8177 const double dtdy
8178 = (met->t[ix][iy1][ip] - met->t[ix][iy0][ip]) * pows[ip] / dy;
8179 const double dudy
8180 = (met->u[ix][iy1][ip] * c1 - met->u[ix][iy0][ip] * c0) / dy;
8181
8182 /* Set indices... */
8183 const int ip0 = MAX(ip - 1, 0);
8184 const int ip1 = MIN(ip + 1, met->np - 1);
8185
8186 /* Get gradients in pressure... */
8187 double dtdp, dudp, dvdp;
8188 const double dp0 = 100. * (met->p[ip] - met->p[ip0]);
8189 const double dp1 = 100. * (met->p[ip1] - met->p[ip]);
8190 if (ip != ip0 && ip != ip1) {
8191 double denom = dp0 * dp1 * (dp0 + dp1);
8192 dtdp = (dp0 * dp0 * met->t[ix][iy][ip1] * pows[ip1]
8193 - dp1 * dp1 * met->t[ix][iy][ip0] * pows[ip0]
8194 + (dp1 * dp1 - dp0 * dp0) * met->t[ix][iy][ip] * pows[ip])
8195 / denom;
8196 dudp = (dp0 * dp0 * met->u[ix][iy][ip1]
8197 - dp1 * dp1 * met->u[ix][iy][ip0]
8198 + (dp1 * dp1 - dp0 * dp0) * met->u[ix][iy][ip])
8199 / denom;
8200 dvdp = (dp0 * dp0 * met->v[ix][iy][ip1]
8201 - dp1 * dp1 * met->v[ix][iy][ip0]
8202 + (dp1 * dp1 - dp0 * dp0) * met->v[ix][iy][ip])
8203 / denom;
8204 } else {
8205 const double denom = dp0 + dp1;
8206 dtdp =
8207 (met->t[ix][iy][ip1] * pows[ip1] -
8208 met->t[ix][iy][ip0] * pows[ip0]) / denom;
8209 dudp = (met->u[ix][iy][ip1] - met->u[ix][iy][ip0]) / denom;
8210 dvdp = (met->v[ix][iy][ip1] - met->v[ix][iy][ip0]) / denom;
8211 }
8212
8213 /* Calculate PV... */
8214 met->pv[ix][iy][ip] = (float)
8215 (1e6 * G0 *
8216 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
8217 }
8218 }
8219 }
8220
8221 /* Fix for polar regions... */
8222#pragma omp parallel for default(shared)
8223 for (int ix = 0; ix < met->nx; ix++)
8224 for (int ip = 0; ip < met->np; ip++) {
8225 met->pv[ix][0][ip]
8226 = met->pv[ix][1][ip]
8227 = met->pv[ix][2][ip];
8228 met->pv[ix][met->ny - 1][ip]
8229 = met->pv[ix][met->ny - 2][ip]
8230 = met->pv[ix][met->ny - 3][ip];
8231 }
8232}
#define DEG2DY(dlat)
Convert a latitude difference to a distance in the y-direction (north-south).
Definition: mptrac.h:461
#define DEG2DX(dlon, lat)
Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude.
Definition: mptrac.h:440

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

8237 {
8238
8239 /* Set timer... */
8240 SELECT_TIMER("READ_MET_OZONE", "METPROC", NVTX_READ);
8241 LOG(2, "Calculate total column ozone...");
8242
8243 /* Loop over columns... */
8244#pragma omp parallel for default(shared) collapse(2)
8245 for (int ix = 0; ix < met->nx; ix++)
8246 for (int iy = 0; iy < met->ny; iy++) {
8247
8248 /* Integrate... */
8249 double cd = 0;
8250 for (int ip = 1; ip < met->np; ip++)
8251 if (met->p[ip - 1] <= met->ps[ix][iy]) {
8252 const double vmr =
8253 0.5 * (met->o3[ix][iy][ip - 1] + met->o3[ix][iy][ip]);
8254 const double dp = met->p[ip - 1] - met->p[ip];
8255 cd += vmr * MO3 / MA * dp * 1e2 / G0;
8256 }
8257
8258 /* Convert to Dobson units... */
8259 met->o3c[ix][iy] = (float) (cd / 2.1415e-5);
8260 }
8261}

◆ read_met_sample()

void read_met_sample ( const 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 8265 of file mptrac.c.

8267 {
8268
8269 met_t *help;
8270
8271 /* Check parameters... */
8272 if (ctl->met_dp <= 1 && ctl->met_dx <= 1 && ctl->met_dy <= 1
8273 && ctl->met_sp <= 1 && ctl->met_sx <= 1 && ctl->met_sy <= 1)
8274 return;
8275
8276 /* Set timer... */
8277 SELECT_TIMER("READ_MET_SAMPLE", "METPROC", NVTX_READ);
8278 LOG(2, "Downsampling of meteo data...");
8279
8280 /* Allocate... */
8281 ALLOC(help, met_t, 1);
8282
8283 /* Copy data... */
8284 help->nx = met->nx;
8285 help->ny = met->ny;
8286 help->np = met->np;
8287 memcpy(help->lon, met->lon, sizeof(met->lon));
8288 memcpy(help->lat, met->lat, sizeof(met->lat));
8289 memcpy(help->p, met->p, sizeof(met->p));
8290
8291 /* Smoothing... */
8292 for (int ix = 0; ix < met->nx; ix += ctl->met_dx) {
8293 for (int iy = 0; iy < met->ny; iy += ctl->met_dy) {
8294 for (int ip = 0; ip < met->np; ip += ctl->met_dp) {
8295 help->ps[ix][iy] = 0;
8296 help->zs[ix][iy] = 0;
8297 help->ts[ix][iy] = 0;
8298 help->us[ix][iy] = 0;
8299 help->vs[ix][iy] = 0;
8300 help->ess[ix][iy] = 0;
8301 help->nss[ix][iy] = 0;
8302 help->shf[ix][iy] = 0;
8303 help->lsm[ix][iy] = 0;
8304 help->sst[ix][iy] = 0;
8305 help->pbl[ix][iy] = 0;
8306 help->cape[ix][iy] = 0;
8307 help->cin[ix][iy] = 0;
8308 help->t[ix][iy][ip] = 0;
8309 help->u[ix][iy][ip] = 0;
8310 help->v[ix][iy][ip] = 0;
8311 help->w[ix][iy][ip] = 0;
8312 help->h2o[ix][iy][ip] = 0;
8313 help->o3[ix][iy][ip] = 0;
8314 help->lwc[ix][iy][ip] = 0;
8315 help->rwc[ix][iy][ip] = 0;
8316 help->iwc[ix][iy][ip] = 0;
8317 help->swc[ix][iy][ip] = 0;
8318 help->cc[ix][iy][ip] = 0;
8319 float wsum = 0;
8320 for (int ix2 = ix - ctl->met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
8321 ix2++) {
8322 int ix3 = ix2;
8323 if (ix3 < 0)
8324 ix3 += met->nx;
8325 else if (ix3 >= met->nx)
8326 ix3 -= met->nx;
8327
8328 for (int iy2 = MAX(iy - ctl->met_sy + 1, 0);
8329 iy2 <= MIN(iy + ctl->met_sy - 1, met->ny - 1); iy2++)
8330 for (int ip2 = MAX(ip - ctl->met_sp + 1, 0);
8331 ip2 <= MIN(ip + ctl->met_sp - 1, met->np - 1); ip2++) {
8332 float w = (1.0f - (float) abs(ix - ix2) / (float) ctl->met_sx)
8333 * (1.0f - (float) abs(iy - iy2) / (float) ctl->met_sy)
8334 * (1.0f - (float) abs(ip - ip2) / (float) ctl->met_sp);
8335 help->ps[ix][iy] += w * met->ps[ix3][iy2];
8336 help->zs[ix][iy] += w * met->zs[ix3][iy2];
8337 help->ts[ix][iy] += w * met->ts[ix3][iy2];
8338 help->us[ix][iy] += w * met->us[ix3][iy2];
8339 help->vs[ix][iy] += w * met->vs[ix3][iy2];
8340 help->ess[ix][iy] += w * met->ess[ix3][iy2];
8341 help->nss[ix][iy] += w * met->nss[ix3][iy2];
8342 help->shf[ix][iy] += w * met->shf[ix3][iy2];
8343 help->lsm[ix][iy] += w * met->lsm[ix3][iy2];
8344 help->sst[ix][iy] += w * met->sst[ix3][iy2];
8345 help->pbl[ix][iy] += w * met->pbl[ix3][iy2];
8346 help->cape[ix][iy] += w * met->cape[ix3][iy2];
8347 help->cin[ix][iy] += w * met->cin[ix3][iy2];
8348 help->t[ix][iy][ip] += w * met->t[ix3][iy2][ip2];
8349 help->u[ix][iy][ip] += w * met->u[ix3][iy2][ip2];
8350 help->v[ix][iy][ip] += w * met->v[ix3][iy2][ip2];
8351 help->w[ix][iy][ip] += w * met->w[ix3][iy2][ip2];
8352 help->h2o[ix][iy][ip] += w * met->h2o[ix3][iy2][ip2];
8353 help->o3[ix][iy][ip] += w * met->o3[ix3][iy2][ip2];
8354 help->lwc[ix][iy][ip] += w * met->lwc[ix3][iy2][ip2];
8355 help->rwc[ix][iy][ip] += w * met->rwc[ix3][iy2][ip2];
8356 help->iwc[ix][iy][ip] += w * met->iwc[ix3][iy2][ip2];
8357 help->swc[ix][iy][ip] += w * met->swc[ix3][iy2][ip2];
8358 help->cc[ix][iy][ip] += w * met->cc[ix3][iy2][ip2];
8359 wsum += w;
8360 }
8361 }
8362 help->ps[ix][iy] /= wsum;
8363 help->zs[ix][iy] /= wsum;
8364 help->ts[ix][iy] /= wsum;
8365 help->us[ix][iy] /= wsum;
8366 help->vs[ix][iy] /= wsum;
8367 help->ess[ix][iy] /= wsum;
8368 help->nss[ix][iy] /= wsum;
8369 help->shf[ix][iy] /= wsum;
8370 help->lsm[ix][iy] /= wsum;
8371 help->sst[ix][iy] /= wsum;
8372 help->pbl[ix][iy] /= wsum;
8373 help->cape[ix][iy] /= wsum;
8374 help->cin[ix][iy] /= wsum;
8375 help->t[ix][iy][ip] /= wsum;
8376 help->u[ix][iy][ip] /= wsum;
8377 help->v[ix][iy][ip] /= wsum;
8378 help->w[ix][iy][ip] /= wsum;
8379 help->h2o[ix][iy][ip] /= wsum;
8380 help->o3[ix][iy][ip] /= wsum;
8381 help->lwc[ix][iy][ip] /= wsum;
8382 help->rwc[ix][iy][ip] /= wsum;
8383 help->iwc[ix][iy][ip] /= wsum;
8384 help->swc[ix][iy][ip] /= wsum;
8385 help->cc[ix][iy][ip] /= wsum;
8386 }
8387 }
8388 }
8389
8390 /* Downsampling... */
8391 met->nx = 0;
8392 for (int ix = 0; ix < help->nx; ix += ctl->met_dx) {
8393 met->lon[met->nx] = help->lon[ix];
8394 met->ny = 0;
8395 for (int iy = 0; iy < help->ny; iy += ctl->met_dy) {
8396 met->lat[met->ny] = help->lat[iy];
8397 met->ps[met->nx][met->ny] = help->ps[ix][iy];
8398 met->zs[met->nx][met->ny] = help->zs[ix][iy];
8399 met->ts[met->nx][met->ny] = help->ts[ix][iy];
8400 met->us[met->nx][met->ny] = help->us[ix][iy];
8401 met->vs[met->nx][met->ny] = help->vs[ix][iy];
8402 met->ess[met->nx][met->ny] = help->ess[ix][iy];
8403 met->nss[met->nx][met->ny] = help->nss[ix][iy];
8404 met->shf[met->nx][met->ny] = help->shf[ix][iy];
8405 met->lsm[met->nx][met->ny] = help->lsm[ix][iy];
8406 met->sst[met->nx][met->ny] = help->sst[ix][iy];
8407 met->pbl[met->nx][met->ny] = help->pbl[ix][iy];
8408 met->cape[met->nx][met->ny] = help->cape[ix][iy];
8409 met->cin[met->nx][met->ny] = help->cin[ix][iy];
8410 met->np = 0;
8411 for (int ip = 0; ip < help->np; ip += ctl->met_dp) {
8412 met->p[met->np] = help->p[ip];
8413 met->t[met->nx][met->ny][met->np] = help->t[ix][iy][ip];
8414 met->u[met->nx][met->ny][met->np] = help->u[ix][iy][ip];
8415 met->v[met->nx][met->ny][met->np] = help->v[ix][iy][ip];
8416 met->w[met->nx][met->ny][met->np] = help->w[ix][iy][ip];
8417 met->h2o[met->nx][met->ny][met->np] = help->h2o[ix][iy][ip];
8418 met->o3[met->nx][met->ny][met->np] = help->o3[ix][iy][ip];
8419 met->lwc[met->nx][met->ny][met->np] = help->lwc[ix][iy][ip];
8420 met->rwc[met->nx][met->ny][met->np] = help->rwc[ix][iy][ip];
8421 met->iwc[met->nx][met->ny][met->np] = help->iwc[ix][iy][ip];
8422 met->swc[met->nx][met->ny][met->np] = help->swc[ix][iy][ip];
8423 met->cc[met->nx][met->ny][met->np] = help->cc[ix][iy][ip];
8424 met->np++;
8425 }
8426 met->ny++;
8427 }
8428 met->nx++;
8429 }
8430
8431 /* Free... */
8432 free(help);
8433}
int met_dp
Stride for pressure levels.
Definition: mptrac.h:2559
int met_sy
Smoothing for latitudes.
Definition: mptrac.h:2565
int met_sx
Smoothing for longitudes.
Definition: mptrac.h:2562
int met_dx
Stride for longitudes.
Definition: mptrac.h:2553
int met_sp
Smoothing for pressure levels.
Definition: mptrac.h:2568
int met_dy
Stride for latitudes.
Definition: mptrac.h:2556

◆ read_met_surface()

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

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

8440 {
8441
8442 /* Set timer... */
8443 SELECT_TIMER("READ_MET_SURFACE", "INPUT", NVTX_READ);
8444 LOG(2, "Read surface data...");
8445
8446 /* Read surface pressure... */
8447 if (read_met_nc_2d
8448 (ncid, "lnsp", "LNSP", NULL, NULL, NULL, NULL, ctl, met, met->ps, 1.0f,
8449 1)) {
8450 for (int ix = 0; ix < met->nx; ix++)
8451 for (int iy = 0; iy < met->ny; iy++)
8452 met->ps[ix][iy] = (float) (exp(met->ps[ix][iy]) / 100.);
8453 } else
8454 if (!read_met_nc_2d
8455 (ncid, "ps", "PS", "sp", "SP", NULL, NULL, ctl, met, met->ps, 0.01f,
8456 1)) {
8457 WARN("Cannot not read surface pressure data (use lowest level)!");
8458 for (int ix = 0; ix < met->nx; ix++)
8459 for (int iy = 0; iy < met->ny; iy++)
8460 met->ps[ix][iy]
8461 = (ctl->met_np > 0 ? (float) ctl->met_p[0] : (float) met->p[0]);
8462 }
8463
8464 /* MPTRAC meteo data... */
8465 if (ctl->met_clams == 0) {
8466
8467 /* Read geopotential height at the surface... */
8468 if (!read_met_nc_2d
8469 (ncid, "z", "Z", NULL, NULL, NULL, NULL, ctl, met, met->zs,
8470 (float) (1. / (1000. * G0)), 1))
8471 if (!read_met_nc_2d
8472 (ncid, "zm", "ZM", NULL, NULL, NULL, NULL, ctl, met, met->zs,
8473 (float) (1. / 1000.), 1))
8474 WARN("Cannot read surface geopotential height!");
8475 }
8476
8477 /* CLaMS meteo data... */
8478 else {
8479
8480 /* Read geopotential height at the surface
8481 (use lowermost level of 3-D data field)... */
8482 float *help;
8483 ALLOC(help, float,
8484 EX * EY * EP);
8485 memcpy(help, met->pl, sizeof(met->pl));
8486 if (!read_met_nc_3d
8487 (ncid, "gph", "GPH", NULL, NULL, ctl, met, met->pl,
8488 (float) (1e-3 / G0)))
8489 ERRMSG("Cannot read geopotential height!");
8490 for (int ix = 0; ix < met->nx; ix++)
8491 for (int iy = 0; iy < met->ny; iy++)
8492 met->zs[ix][iy] = met->pl[ix][iy][0];
8493 memcpy(met->pl, help, sizeof(met->pl));
8494 free(help);
8495 }
8496
8497 /* Read temperature at the surface... */
8498 if (!read_met_nc_2d
8499 (ncid, "t2m", "T2M", "2t", "2T", "t2", "T2", ctl, met, met->ts, 1.0, 1))
8500 WARN("Cannot read surface temperature!");
8501
8502 /* Read zonal wind at the surface... */
8503 if (!read_met_nc_2d
8504 (ncid, "u10m", "U10M", "10u", "10U", "u10", "U10", ctl, met, met->us,
8505 1.0, 1))
8506 WARN("Cannot read surface zonal wind!");
8507
8508 /* Read meridional wind at the surface... */
8509 if (!read_met_nc_2d
8510 (ncid, "v10m", "V10M", "10v", "10V", "v10", "V10", ctl, met, met->vs,
8511 1.0, 1))
8512 WARN("Cannot read surface meridional wind!");
8513
8514 /* Read eastward turbulent surface stress... */
8515 if (!read_met_nc_2d
8516 (ncid, "iews", "IEWS", NULL, NULL, NULL, NULL, ctl, met, met->ess, 1.0,
8517 1))
8518 WARN("Cannot read eastward turbulent surface stress!");
8519
8520 /* Read northward turbulent surface stress... */
8521 if (!read_met_nc_2d
8522 (ncid, "inss", "INSS", NULL, NULL, NULL, NULL, ctl, met, met->nss, 1.0,
8523 1))
8524 WARN("Cannot read nothward turbulent surface stress!");
8525
8526 /* Read surface sensible heat flux... */
8527 if (!read_met_nc_2d
8528 (ncid, "ishf", "ISHF", NULL, NULL, NULL, NULL, ctl, met, met->shf, 1.0,
8529 1))
8530 WARN("Cannot read surface sensible heat flux!");
8531
8532 /* Read land-sea mask... */
8533 if (!read_met_nc_2d
8534 (ncid, "lsm", "LSM", NULL, NULL, NULL, NULL, ctl, met, met->lsm, 1.0,
8535 1))
8536 WARN("Cannot read land-sea mask!");
8537
8538 /* Read sea surface temperature... */
8539 if (!read_met_nc_2d
8540 (ncid, "sstk", "SSTK", "sst", "SST", NULL, NULL, ctl, met, met->sst,
8541 1.0, 1))
8542 WARN("Cannot read sea surface temperature!");
8543
8544 /* Read PBL... */
8545 if (ctl->met_pbl == 0)
8546 if (!read_met_nc_2d
8547 (ncid, "blp", "BLP", NULL, NULL, NULL, NULL, ctl, met, met->pbl,
8548 0.01f, 1))
8549 WARN("Cannot read planetary boundary layer pressure!");
8550 if (ctl->met_pbl == 1)
8551 if (!read_met_nc_2d
8552 (ncid, "blh", "BLH", NULL, NULL, NULL, NULL, ctl, met, met->pbl,
8553 0.001f, 1))
8554 WARN("Cannot read planetary boundary layer height!");
8555
8556 /* Read CAPE... */
8557 if (ctl->met_cape == 0)
8558 if (!read_met_nc_2d
8559 (ncid, "cape", "CAPE", NULL, NULL, NULL, NULL, ctl, met, met->cape,
8560 1.0, 1))
8561 WARN("Cannot read CAPE!");
8562
8563 /* Read CIN... */
8564 if (ctl->met_cape == 0)
8565 if (!read_met_nc_2d
8566 (ncid, "cin", "CIN", NULL, NULL, NULL, NULL, ctl, met, met->cin,
8567 1.0, 1))
8568 WARN("Cannot read convective inhibition!");
8569}
int read_met_nc_2d(const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const char *varname5, const char *varname6, const ctl_t *ctl, const met_t *met, float dest[EX][EY], const float scl, const int init)
Reads a 2-dimensional meteorological variable from a NetCDF file.
Definition: mptrac.c:7569
Here is the call graph for this function:

◆ read_met_tropo()

void read_met_tropo ( const ctl_t ctl,
const 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 8573 of file mptrac.c.

8576 {
8577
8578 double p2[200], pv[EP], pv2[200], t[EP], t2[200], th[EP],
8579 th2[200], z[EP], z2[200];
8580
8581 /* Set timer... */
8582 SELECT_TIMER("READ_MET_TROPO", "METPROC", NVTX_READ);
8583 LOG(2, "Calculate tropopause...");
8584
8585 /* Get altitude and pressure profiles... */
8586#pragma omp parallel for default(shared)
8587 for (int iz = 0; iz < met->np; iz++)
8588 z[iz] = Z(met->p[iz]);
8589#pragma omp parallel for default(shared)
8590 for (int iz = 0; iz <= 190; iz++) {
8591 z2[iz] = 4.5 + 0.1 * iz;
8592 p2[iz] = P(z2[iz]);
8593 }
8594
8595 /* Do not calculate tropopause... */
8596 if (ctl->met_tropo == 0)
8597#pragma omp parallel for default(shared) collapse(2)
8598 for (int ix = 0; ix < met->nx; ix++)
8599 for (int iy = 0; iy < met->ny; iy++)
8600 met->pt[ix][iy] = NAN;
8601
8602 /* Use tropopause climatology... */
8603 else if (ctl->met_tropo == 1) {
8604#pragma omp parallel for default(shared) collapse(2)
8605 for (int ix = 0; ix < met->nx; ix++)
8606 for (int iy = 0; iy < met->ny; iy++)
8607 met->pt[ix][iy] = (float) clim_tropo(clim, met->time, met->lat[iy]);
8608 }
8609
8610 /* Use cold point... */
8611 else if (ctl->met_tropo == 2) {
8612
8613 /* Loop over grid points... */
8614#pragma omp parallel for default(shared) private(t,t2) collapse(2)
8615 for (int ix = 0; ix < met->nx; ix++)
8616 for (int iy = 0; iy < met->ny; iy++) {
8617
8618 /* Interpolate temperature profile... */
8619 for (int iz = 0; iz < met->np; iz++)
8620 t[iz] = met->t[ix][iy][iz];
8621 spline(z, t, met->np, z2, t2, 171, ctl->met_tropo_spline);
8622
8623 /* Find minimum... */
8624 int iz = (int) gsl_stats_min_index(t2, 1, 171);
8625 if (iz > 0 && iz < 170)
8626 met->pt[ix][iy] = (float) p2[iz];
8627 else
8628 met->pt[ix][iy] = NAN;
8629 }
8630 }
8631
8632 /* Use WMO definition... */
8633 else if (ctl->met_tropo == 3 || ctl->met_tropo == 4) {
8634
8635 /* Loop over grid points... */
8636#pragma omp parallel for default(shared) private(t,t2) collapse(2)
8637 for (int ix = 0; ix < met->nx; ix++)
8638 for (int iy = 0; iy < met->ny; iy++) {
8639
8640 /* Interpolate temperature profile... */
8641 int iz;
8642 for (iz = 0; iz < met->np; iz++)
8643 t[iz] = met->t[ix][iy][iz];
8644 spline(z, t, met->np, z2, t2, 191, ctl->met_tropo_spline);
8645
8646 /* Find 1st tropopause... */
8647 met->pt[ix][iy] = NAN;
8648 for (iz = 0; iz <= 170; iz++) {
8649 int found = 1;
8650 for (int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
8651 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
8652 found = 0;
8653 break;
8654 }
8655 if (found) {
8656 if (iz > 0 && iz < 170)
8657 met->pt[ix][iy] = (float) p2[iz];
8658 break;
8659 }
8660 }
8661
8662 /* Find 2nd tropopause... */
8663 if (ctl->met_tropo == 4) {
8664 met->pt[ix][iy] = NAN;
8665 for (; iz <= 170; iz++) {
8666 int found = 1;
8667 for (int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
8668 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
8669 found = 0;
8670 break;
8671 }
8672 if (found)
8673 break;
8674 }
8675 for (; iz <= 170; iz++) {
8676 int found = 1;
8677 for (int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
8678 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
8679 found = 0;
8680 break;
8681 }
8682 if (found) {
8683 if (iz > 0 && iz < 170)
8684 met->pt[ix][iy] = (float) p2[iz];
8685 break;
8686 }
8687 }
8688 }
8689 }
8690 }
8691
8692 /* Use dynamical tropopause... */
8693 else if (ctl->met_tropo == 5) {
8694
8695 /* Loop over grid points... */
8696#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
8697 for (int ix = 0; ix < met->nx; ix++)
8698 for (int iy = 0; iy < met->ny; iy++) {
8699
8700 /* Interpolate potential vorticity profile... */
8701 for (int iz = 0; iz < met->np; iz++)
8702 pv[iz] = met->pv[ix][iy][iz];
8703 spline(z, pv, met->np, z2, pv2, 171, ctl->met_tropo_spline);
8704
8705 /* Interpolate potential temperature profile... */
8706 for (int iz = 0; iz < met->np; iz++)
8707 th[iz] = THETA(met->p[iz], met->t[ix][iy][iz]);
8708 spline(z, th, met->np, z2, th2, 171, ctl->met_tropo_spline);
8709
8710 /* Find dynamical tropopause... */
8711 met->pt[ix][iy] = NAN;
8712 for (int iz = 0; iz <= 170; iz++)
8713 if (fabs(pv2[iz]) >= ctl->met_tropo_pv
8714 || th2[iz] >= ctl->met_tropo_theta) {
8715 if (iz > 0 && iz < 170)
8716 met->pt[ix][iy] = (float) p2[iz];
8717 break;
8718 }
8719 }
8720 }
8721
8722 else
8723 ERRMSG("Cannot calculate tropopause!");
8724
8725 /* Interpolate temperature, geopotential height, and water vapor... */
8726#pragma omp parallel for default(shared) collapse(2)
8727 for (int ix = 0; ix < met->nx; ix++)
8728 for (int iy = 0; iy < met->ny; iy++) {
8729 double h2ot, tt, zt;
8731 intpol_met_space_3d(met, met->t, met->pt[ix][iy], met->lon[ix],
8732 met->lat[iy], &tt, ci, cw, 1);
8733 intpol_met_space_3d(met, met->z, met->pt[ix][iy], met->lon[ix],
8734 met->lat[iy], &zt, ci, cw, 0);
8735 intpol_met_space_3d(met, met->h2o, met->pt[ix][iy], met->lon[ix],
8736 met->lat[iy], &h2ot, ci, cw, 0);
8737 met->tt[ix][iy] = (float) tt;
8738 met->zt[ix][iy] = (float) zt;
8739 met->h2ot[ix][iy] = (float) h2ot;
8740 }
8741}
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:8951
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
Definition: mptrac.h:840
Here is the call graph for this function:

◆ read_obs()

void read_obs ( const char *  filename,
const 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 8745 of file mptrac.c.

8753 {
8754
8755 /* Write info... */
8756 LOG(1, "Read observation data: %s", filename);
8757
8758 /* Read data... */
8759 if (ctl->obs_type == 0)
8760 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
8761 else if (ctl->obs_type == 1)
8762 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
8763 else
8764 ERRMSG("Set OBS_TYPE to 0 or 1!");
8765
8766 /* Check time... */
8767 for (int i = 1; i < *nobs; i++)
8768 if (rt[i] < rt[i - 1])
8769 ERRMSG("Time must be ascending!");
8770
8771 /* Write info... */
8772 int n = *nobs;
8773 double mini, maxi;
8774 LOG(2, "Number of observations: %d", *nobs);
8775 gsl_stats_minmax(&mini, &maxi, rt, 1, (size_t) n);
8776 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
8777 gsl_stats_minmax(&mini, &maxi, rz, 1, (size_t) n);
8778 LOG(2, "Altitude range: %g ... %g km", mini, maxi);
8779 gsl_stats_minmax(&mini, &maxi, rlon, 1, (size_t) n);
8780 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
8781 gsl_stats_minmax(&mini, &maxi, rlat, 1, (size_t) n);
8782 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
8783 gsl_stats_minmax(&mini, &maxi, robs, 1, (size_t) n);
8784 LOG(2, "Observation range: %g ... %g", mini, maxi);
8785}
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:8789
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:8817
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 8789 of file mptrac.c.

8796 {
8797
8798 /* Open observation data file... */
8799 FILE *in;
8800 if (!(in = fopen(filename, "r")))
8801 ERRMSG("Cannot open file!");
8802
8803 /* Read observations... */
8804 char line[LEN];
8805 while (fgets(line, LEN, in))
8806 if (sscanf(line, "%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
8807 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
8808 if ((++(*nobs)) >= NOBS)
8809 ERRMSG("Too many observations!");
8810
8811 /* Close observation data file... */
8812 fclose(in);
8813}
#define NOBS
Maximum number of observation data points.
Definition: mptrac.h:281

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

8824 {
8825
8826 int ncid, varid;
8827
8828 /* Open netCDF file... */
8829 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
8830 ERRMSG("Cannot open file!");
8831
8832 /* Read the observations from the NetCDF file... */
8833 NC_INQ_DIM("nobs", nobs, 1, NOBS);
8834 NC_GET_DOUBLE("time", rt, 1);
8835 NC_GET_DOUBLE("alt", rz, 1);
8836 NC_GET_DOUBLE("lon", rlon, 1);
8837 NC_GET_DOUBLE("lat", rlat, 1);
8838 NC_GET_DOUBLE("obs", robs, 1);
8839
8840 /* Close file... */
8841 NC(nc_close(ncid));
8842}

◆ scan_ctl()

double scan_ctl ( const char *  filename,
int  argc,
char *  argv[],
const char *  varname,
const 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 8846 of file mptrac.c.

8853 {
8854
8855 FILE *in = NULL;
8856
8857 char fullname1[LEN], fullname2[LEN], rval[LEN];
8858
8859 int contain = 0, i;
8860
8861 /* Open file... */
8862 if (filename[strlen(filename) - 1] != '-')
8863 if (!(in = fopen(filename, "r")))
8864 ERRMSG("Cannot open file!");
8865
8866 /* Set full variable name... */
8867 if (arridx >= 0) {
8868 sprintf(fullname1, "%s[%d]", varname, arridx);
8869 sprintf(fullname2, "%s[*]", varname);
8870 } else {
8871 sprintf(fullname1, "%s", varname);
8872 sprintf(fullname2, "%s", varname);
8873 }
8874
8875 /* Read data... */
8876 if (in != NULL) {
8877 char dummy[LEN], line[LEN], rvarname[LEN];
8878 while (fgets(line, LEN, in)) {
8879 if (sscanf(line, "%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
8880 if (strcasecmp(rvarname, fullname1) == 0 ||
8881 strcasecmp(rvarname, fullname2) == 0) {
8882 contain = 1;
8883 break;
8884 }
8885 }
8886 }
8887 for (i = 1; i < argc - 1; i++)
8888 if (strcasecmp(argv[i], fullname1) == 0 ||
8889 strcasecmp(argv[i], fullname2) == 0) {
8890 sprintf(rval, "%s", argv[i + 1]);
8891 contain = 1;
8892 break;
8893 }
8894
8895 /* Close file... */
8896 if (in != NULL)
8897 fclose(in);
8898
8899 /* Check for missing variables... */
8900 if (!contain) {
8901 if (strlen(defvalue) > 0)
8902 sprintf(rval, "%s", defvalue);
8903 else
8904 ERRMSG("Missing variable %s!\n", fullname1);
8905 }
8906
8907 /* Write info... */
8908 LOG(1, "%s = %s", fullname1, rval);
8909
8910 /* Return values... */
8911 if (value != NULL)
8912 sprintf(value, "%s", rval);
8913 return atof(rval);
8914}

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

8922 {
8923
8924 /* Convert particle radius from microns to m... */
8925 const double rp_help = rp * 1e-6;
8926
8927 /* Density of dry air [kg / m^3]... */
8928 const double rho = RHO(p, T);
8929
8930 /* Dynamic viscosity of air [kg / (m s)]... */
8931 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
8932
8933 /* Thermal velocity of an air molecule [m / s]... */
8934 const double v = sqrt(8. * KB * T / (M_PI * 4.8096e-26));
8935
8936 /* Mean free path of an air molecule [m]... */
8937 const double lambda = 2. * eta / (rho * v);
8938
8939 /* Knudsen number for air (dimensionless)... */
8940 const double K = lambda / rp_help;
8941
8942 /* Cunningham slip-flow correction (dimensionless)... */
8943 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
8944
8945 /* Sedimentation velocity [m / s]... */
8946 return 2. * SQR(rp_help) * (rhop - rho) * G0 / (9. * eta) * G;
8947}
#define KB
Boltzmann constant [kg m^2/(K s^2)].
Definition: mptrac.h:192

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

8958 {
8959
8960 /* Cubic spline interpolation... */
8961 if (method == 1) {
8962
8963 /* Allocate... */
8964 gsl_interp_accel *acc = gsl_interp_accel_alloc();
8965 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (size_t) n);
8966
8967 /* Interpolate profile... */
8968 gsl_spline_init(s, x, y, (size_t) n);
8969 for (int i = 0; i < n2; i++)
8970 if (x2[i] <= x[0])
8971 y2[i] = y[0];
8972 else if (x2[i] >= x[n - 1])
8973 y2[i] = y[n - 1];
8974 else
8975 y2[i] = gsl_spline_eval(s, x2[i], acc);
8976
8977 /* Free... */
8978 gsl_spline_free(s);
8979 gsl_interp_accel_free(acc);
8980 }
8981
8982 /* Linear interpolation... */
8983 else {
8984 for (int i = 0; i < n2; i++)
8985 if (x2[i] <= x[0])
8986 y2[i] = y[0];
8987 else if (x2[i] >= x[n - 1])
8988 y2[i] = y[n - 1];
8989 else {
8990 int idx = locate_irr(x, n, x2[i]);
8991 y2[i] = LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
8992 }
8993 }
8994}
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 8998 of file mptrac.c.

9000 {
9001
9002 if (n <= 0)
9003 return 0;
9004
9005 float mean = 0, var = 0;
9006
9007 for (int i = 0; i < n; ++i) {
9008 mean += data[i];
9009 var += SQR(data[i]);
9010 }
9011
9012 var = var / (float) n - SQR(mean / (float) n);
9013
9014 return (var > 0 ? sqrtf(var) : 0);
9015}

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

9022 {
9023
9024 /* Number of days and fraction with respect to 2000-01-01T12:00Z... */
9025 const double D = sec / 86400 - 0.5;
9026
9027 /* Geocentric apparent ecliptic longitude [rad]... */
9028 const double g = DEG2RAD(357.529 + 0.98560028 * D);
9029 const double q = 280.459 + 0.98564736 * D;
9030 const double L = DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
9031
9032 /* Mean obliquity of the ecliptic [rad]... */
9033 const double e = DEG2RAD(23.439 - 0.00000036 * D);
9034
9035 /* Declination [rad]... */
9036 const double sindec = sin(e) * sin(L);
9037
9038 /* Right ascension [rad]... */
9039 const double ra = atan2(cos(e) * sin(L), cos(L));
9040
9041 /* Greenwich Mean Sidereal Time [h]... */
9042 const double GMST = 18.697374558 + 24.06570982441908 * D;
9043
9044 /* Local Sidereal Time [h]... */
9045 const double LST = GMST + lon / 15;
9046
9047 /* Hour angle [rad]... */
9048 const double h = LST / 12 * M_PI - ra;
9049
9050 /* Convert latitude... */
9051 const double lat_help = DEG2RAD(lat);
9052
9053 /* Return solar zenith angle [rad]... */
9054 return acos(sin(lat_help) * sindec +
9055 cos(lat_help) * sqrt(1 - SQR(sindec)) * cos(h));
9056}

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

9068 {
9069
9070 struct tm t0, t1;
9071
9072 t0.tm_year = 100;
9073 t0.tm_mon = 0;
9074 t0.tm_mday = 1;
9075 t0.tm_hour = 0;
9076 t0.tm_min = 0;
9077 t0.tm_sec = 0;
9078
9079 t1.tm_year = year - 1900;
9080 t1.tm_mon = mon - 1;
9081 t1.tm_mday = day;
9082 t1.tm_hour = hour;
9083 t1.tm_min = min;
9084 t1.tm_sec = sec;
9085
9086 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
9087}

◆ timer()

void timer ( const char *  name,
const char *  group,
const 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 9091 of file mptrac.c.

9094 {
9095
9096 static char names[NTIMER][100], groups[NTIMER][100];
9097
9098 static double rt_name[NTIMER], rt_group[NTIMER],
9099 rt_min[NTIMER], rt_max[NTIMER], dt, t0, t1;
9100
9101 static int iname = -1, igroup = -1, nname, ngroup, ct_name[NTIMER];
9102
9103 /* Get time... */
9104 t1 = omp_get_wtime();
9105 dt = t1 - t0;
9106
9107 /* Add elapsed time to current timers... */
9108 if (iname >= 0) {
9109 rt_name[iname] += dt;
9110 rt_min[iname] = (ct_name[iname] <= 0 ? dt : MIN(rt_min[iname], dt));
9111 rt_max[iname] = (ct_name[iname] <= 0 ? dt : MAX(rt_max[iname], dt));
9112 ct_name[iname]++;
9113 }
9114 if (igroup >= 0)
9115 rt_group[igroup] += t1 - t0;
9116
9117 /* Report timers... */
9118 if (output) {
9119 for (int i = 0; i < nname; i++)
9120 LOG(1, "TIMER_%s = %.3f s (min= %g s, mean= %g s,"
9121 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
9122 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
9123 for (int i = 0; i < ngroup; i++)
9124 LOG(1, "TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
9125 double total = 0.0;
9126 for (int i = 0; i < nname; i++)
9127 total += rt_name[i];
9128 LOG(1, "TIMER_TOTAL = %.3f s", total);
9129 }
9130
9131 /* Identify IDs of next timer... */
9132 for (iname = 0; iname < nname; iname++)
9133 if (strcasecmp(name, names[iname]) == 0)
9134 break;
9135 for (igroup = 0; igroup < ngroup; igroup++)
9136 if (strcasecmp(group, groups[igroup]) == 0)
9137 break;
9138
9139 /* Check whether this is a new timer... */
9140 if (iname >= nname) {
9141 sprintf(names[iname], "%s", name);
9142 if ((++nname) >= NTIMER)
9143 ERRMSG("Too many timers!");
9144 }
9145
9146 /* Check whether this is a new group... */
9147 if (igroup >= ngroup) {
9148 sprintf(groups[igroup], "%s", group);
9149 if ((++ngroup) >= NTIMER)
9150 ERRMSG("Too many groups!");
9151 }
9152
9153 /* Save starting time... */
9154 t0 = t1;
9155}
#define NTIMER
Maximum number of timers.
Definition: mptrac.h:1948

◆ time_from_filename()

double time_from_filename ( const char *  filename,
const 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 9159 of file mptrac.c.

9161 {
9162
9163 char tstr[10];
9164
9165 double t;
9166
9167 /* Get time from filename... */
9168 int len = (int) strlen(filename);
9169 sprintf(tstr, "%.4s", &filename[len - offset]);
9170 int year = atoi(tstr);
9171 sprintf(tstr, "%.2s", &filename[len - offset + 5]);
9172 int mon = atoi(tstr);
9173 sprintf(tstr, "%.2s", &filename[len - offset + 8]);
9174 int day = atoi(tstr);
9175 sprintf(tstr, "%.2s", &filename[len - offset + 11]);
9176 int hour = atoi(tstr);
9177 sprintf(tstr, "%.2s", &filename[len - offset + 14]);
9178 int min = atoi(tstr);
9179
9180 /* Check time... */
9181 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
9182 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
9183 ERRMSG("Cannot read time from filename!");
9184
9185 /* Convert time to Julian seconds... */
9186 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
9187
9188 /* Return time... */
9189 return t;
9190}
Here is the call graph for this function:

◆ tropo_weight()

double tropo_weight ( const clim_t clim,
const atm_t atm,
const int  ip 
)

Computes a weighting factor based on tropopause pressure.

This function calculates a weighting factor for a given pressure value in relation to the tropopause pressure. The weighting factor is determined as follows:

  • Returns 1 if the pressure is greater than a calculated upper limit.
  • Returns 0 if the pressure is less than a calculated lower limit.
  • Linearly interpolates between 1 and 0 within the range defined by the upper and lower limits.
Parameters
[in]climPointer to the climatology data structure.
[in]atmPointer to the atmospheric data structure.
[in]ipIndex of the pressure value to evaluate within the atmospheric data.
Returns
Weighting factor (double) in the range [0, 1].
Author
Lars Hoffmann

Definition at line 9194 of file mptrac.c.

9197 {
9198
9199 /* Get tropopause pressure... */
9200 const double pt = clim_tropo(clim, atm->time[ip], atm->lat[ip]);
9201
9202 /* Get pressure range... */
9203 const double p1 = pt * 0.866877899;
9204 const double p0 = pt / 0.866877899;
9205
9206 /* Get weighting factor... */
9207 if (atm->p[ip] > p0)
9208 return 1;
9209 else if (atm->p[ip] < p1)
9210 return 0;
9211 else
9212 return LIN(p0, 1.0, p1, 0.0, atm->p[ip]);
9213}
Here is the call graph for this function:

◆ write_atm_asc()

void write_atm_asc ( const char *  filename,
const ctl_t ctl,
const atm_t atm,
const 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 9217 of file mptrac.c.

9221 {
9222
9223 FILE *out;
9224
9225 /* Set time interval for output... */
9226 const double t0 = t - 0.5 * ctl->dt_mod;
9227 const double t1 = t + 0.5 * ctl->dt_mod;
9228
9229 /* Check if gnuplot output is requested... */
9230 if (ctl->atm_gpfile[0] != '-') {
9231
9232 /* Create gnuplot pipe... */
9233 if (!(out = popen("gnuplot", "w")))
9234 ERRMSG("Cannot create pipe to gnuplot!");
9235
9236 /* Set plot filename... */
9237 fprintf(out, "set out \"%s.png\"\n", filename);
9238
9239 /* Set time string... */
9240 double r;
9241 int year, mon, day, hour, min, sec;
9242 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
9243 fprintf(out, "timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
9244 year, mon, day, hour, min);
9245
9246 /* Dump gnuplot file to pipe... */
9247 FILE *in;
9248 if (!(in = fopen(ctl->atm_gpfile, "r")))
9249 ERRMSG("Cannot open file!");
9250 char line[LEN];
9251 while (fgets(line, LEN, in))
9252 fprintf(out, "%s", line);
9253 fclose(in);
9254 }
9255
9256 else {
9257
9258 /* Create file... */
9259 if (!(out = fopen(filename, "w")))
9260 ERRMSG("Cannot create file!");
9261 }
9262
9263 /* Write header... */
9264 fprintf(out,
9265 "# $1 = time [s]\n"
9266 "# $2 = altitude [km]\n"
9267 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
9268 for (int iq = 0; iq < ctl->nq; iq++)
9269 fprintf(out, "# $%i = %s [%s]\n", iq + 5, ctl->qnt_name[iq],
9270 ctl->qnt_unit[iq]);
9271 fprintf(out, "\n");
9272
9273 /* Write data... */
9274 for (int ip = 0; ip < atm->np; ip += ctl->atm_stride) {
9275
9276 /* Check time... */
9277 if (ctl->atm_filter == 2 && (atm->time[ip] < t0 || atm->time[ip] > t1))
9278 continue;
9279
9280 /* Write output... */
9281 fprintf(out, "%.2f %g %g %g", atm->time[ip], Z(atm->p[ip]),
9282 atm->lon[ip], atm->lat[ip]);
9283 for (int iq = 0; iq < ctl->nq; iq++) {
9284 fprintf(out, " ");
9285 if (ctl->atm_filter == 1 && (atm->time[ip] < t0 || atm->time[ip] > t1))
9286 fprintf(out, ctl->qnt_format[iq], NAN);
9287 else
9288 fprintf(out, ctl->qnt_format[iq], atm->q[iq][ip]);
9289 }
9290 fprintf(out, "\n");
9291 }
9292
9293 /* Close file... */
9294 fclose(out);
9295}
Here is the call graph for this function:

◆ write_atm_bin()

void write_atm_bin ( const char *  filename,
const ctl_t ctl,
const 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 9299 of file mptrac.c.

9302 {
9303
9304 FILE *out;
9305
9306 /* Create file... */
9307 if (!(out = fopen(filename, "w")))
9308 ERRMSG("Cannot create file!");
9309
9310 /* Write version of binary data... */
9311 int version = 100;
9312 FWRITE(&version, int,
9313 1,
9314 out);
9315
9316 /* Write data... */
9317 FWRITE(&atm->np, int,
9318 1,
9319 out);
9320 FWRITE(atm->time, double,
9321 (size_t) atm->np,
9322 out);
9323 FWRITE(atm->p, double,
9324 (size_t) atm->np,
9325 out);
9326 FWRITE(atm->lon, double,
9327 (size_t) atm->np,
9328 out);
9329 FWRITE(atm->lat, double,
9330 (size_t) atm->np,
9331 out);
9332 for (int iq = 0; iq < ctl->nq; iq++)
9333 FWRITE(atm->q[iq], double,
9334 (size_t) atm->np,
9335 out);
9336
9337 /* Write final flag... */
9338 int final = 999;
9339 FWRITE(&final, int,
9340 1,
9341 out);
9342
9343 /* Close file... */
9344 fclose(out);
9345}

◆ write_atm_clams()

void write_atm_clams ( const char *  filename,
const ctl_t ctl,
const 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 9349 of file mptrac.c.

9352 {
9353
9354 int tid, pid, ncid, varid;
9355 size_t start[2], count[2];
9356
9357 /* Create file... */
9358 nc_create(filename, NC_NETCDF4, &ncid);
9359
9360 /* Define dimensions... */
9361 NC(nc_def_dim(ncid, "time", 1, &tid));
9362 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
9363
9364 /* Define variables and their attributes... */
9365 int dim_ids[2] = { tid, pid };
9366 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
9367 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
9368 NC_DEF_VAR("LAT", NC_DOUBLE, 1, &pid, "Latitude", "deg",
9369 ctl->atm_nc_level, 0);
9370 NC_DEF_VAR("LON", NC_DOUBLE, 1, &pid, "Longitude", "deg",
9371 ctl->atm_nc_level, 0);
9372 NC_DEF_VAR("PRESS", NC_DOUBLE, 1, &pid, "Pressure", "hPa",
9373 ctl->atm_nc_level, 0);
9374 NC_DEF_VAR("ZETA", NC_DOUBLE, 1, &pid, "Zeta", "K", ctl->atm_nc_level, 0);
9375 for (int iq = 0; iq < ctl->nq; iq++)
9376 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
9377 ctl->qnt_name[iq], ctl->qnt_unit[iq],
9378 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
9379
9380 /* Define global attributes... */
9381 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
9382 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
9383
9384 /* End definitions... */
9385 NC(nc_enddef(ncid));
9386
9387 /* Write data... */
9388 NC_PUT_DOUBLE("time", atm->time, 0);
9389 NC_PUT_DOUBLE("LAT", atm->lat, 0);
9390 NC_PUT_DOUBLE("LON", atm->lon, 0);
9391 NC_PUT_DOUBLE("PRESS", atm->p, 0);
9392 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 0);
9393 for (int iq = 0; iq < ctl->nq; iq++)
9394 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
9395
9396 /* Close file... */
9397 NC(nc_close(ncid));
9398}
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
Definition: mptrac.h:1212
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units, level, quant)
Define a NetCDF variable with attributes.
Definition: mptrac.h:1045
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
Write double precision data to a NetCDF variable.
Definition: mptrac.h:1126

◆ write_atm_clams_traj()

void write_atm_clams_traj ( const char *  dirname,
const ctl_t ctl,
const atm_t atm,
const 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 9402 of file mptrac.c.

9406 {
9407
9408 /* Global Counter... */
9409 static size_t out_cnt = 0;
9410
9411 double r, r_start, r_stop;
9412 int year, mon, day, hour, min, sec;
9413 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
9414 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
9415 char filename_out[2 * LEN] = "traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
9416
9417 int ncid, varid, tid, pid, cid;
9418 int dim_ids[2];
9419
9420 /* time, nparc */
9421 size_t start[2];
9422 size_t count[2];
9423
9424 /* Determine start and stop times of calculation... */
9425 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
9426 jsec2time(ctl->t_start, &year_start, &mon_start, &day_start, &hour_start,
9427 &min_start, &sec_start, &r_start);
9428 jsec2time(ctl->t_stop, &year_stop, &mon_stop, &day_stop, &hour_stop,
9429 &min_stop, &sec_stop, &r_stop);
9430
9431 sprintf(filename_out, "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc",
9432 dirname,
9433 year_start % 100, mon_start, day_start, hour_start,
9434 year_stop % 100, mon_stop, day_stop, hour_stop);
9435 LOG(1, "Write traj file: %s", filename_out);
9436
9437 /* Define hyperslap for the traj_file... */
9438 start[0] = out_cnt;
9439 start[1] = 0;
9440 count[0] = 1;
9441 count[1] = (size_t) atm->np;
9442
9443 /* Create the file at the first timestep... */
9444 if (out_cnt == 0) {
9445
9446 /* Create file... */
9447 nc_create(filename_out, NC_NETCDF4, &ncid);
9448
9449 /* Define dimensions... */
9450 NC(nc_def_dim(ncid, "time", NC_UNLIMITED, &tid));
9451 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
9452 NC(nc_def_dim(ncid, "TMDT", 7, &cid));
9453 dim_ids[0] = tid;
9454 dim_ids[1] = pid;
9455
9456 /* Define variables and their attributes... */
9457 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
9458 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
9459 NC_DEF_VAR("LAT", NC_DOUBLE, 2, dim_ids, "Latitude", "deg",
9460 ctl->atm_nc_level, 0);
9461 NC_DEF_VAR("LON", NC_DOUBLE, 2, dim_ids, "Longitude", "deg",
9462 ctl->atm_nc_level, 0);
9463 NC_DEF_VAR("PRESS", NC_DOUBLE, 2, dim_ids, "Pressure", "hPa",
9464 ctl->atm_nc_level, 0);
9465 NC_DEF_VAR("ZETA", NC_DOUBLE, 2, dim_ids, "Zeta", "K",
9466 ctl->atm_nc_level, 0);
9467 for (int iq = 0; iq < ctl->nq; iq++)
9468 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
9469 ctl->qnt_name[iq], ctl->qnt_unit[iq],
9470 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
9471
9472 /* Define global attributes... */
9473 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
9474 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
9475
9476 /* End definitions... */
9477 NC(nc_enddef(ncid));
9478 NC(nc_close(ncid));
9479 }
9480
9481 /* Increment global counter to change hyperslap... */
9482 out_cnt++;
9483
9484 /* Open file... */
9485 NC(nc_open(filename_out, NC_WRITE, &ncid));
9486
9487 /* Write data... */
9488 NC_PUT_DOUBLE("time", atm->time, 1);
9489 NC_PUT_DOUBLE("LAT", atm->lat, 1);
9490 NC_PUT_DOUBLE("LON", atm->lon, 1);
9491 NC_PUT_DOUBLE("PRESS", atm->p, 1);
9492 if (ctl->advect_vert_coord == 1) {
9493 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta], 1);
9494 } else if (ctl->qnt_zeta >= 0) {
9495 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 1);
9496 }
9497 for (int iq = 0; iq < ctl->nq; iq++)
9498 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 1);
9499
9500 /* Close file... */
9501 NC(nc_close(ncid));
9502
9503 /* At the last time step create the init_fix_YYYYMMDDHH file... */
9504 if ((year == year_stop) && (mon == mon_stop)
9505 && (day == day_stop) && (hour == hour_stop)) {
9506
9507 /* Set filename... */
9508 char filename_init[2 * LEN] = "./init_fix_YYYYMMDDHH.nc";
9509 sprintf(filename_init, "%s/init_fix_%02d%02d%02d%02d.nc",
9510 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
9511 LOG(1, "Write init file: %s", filename_init);
9512
9513 /* Create file... */
9514 nc_create(filename_init, NC_NETCDF4, &ncid);
9515
9516 /* Define dimensions... */
9517 NC(nc_def_dim(ncid, "time", 1, &tid));
9518 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
9519 dim_ids[0] = tid;
9520 dim_ids[1] = pid;
9521
9522 /* Define variables and their attributes... */
9523 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
9524 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
9525 NC_DEF_VAR("LAT", NC_DOUBLE, 1, &pid, "Latitude", "deg",
9526 ctl->atm_nc_level, 0);
9527 NC_DEF_VAR("LON", NC_DOUBLE, 1, &pid, "Longitude", "deg",
9528 ctl->atm_nc_level, 0);
9529 NC_DEF_VAR("PRESS", NC_DOUBLE, 1, &pid, "Pressure", "hPa",
9530 ctl->atm_nc_level, 0);
9531 NC_DEF_VAR("ZETA", NC_DOUBLE, 1, &pid, "Zeta", "K", ctl->atm_nc_level, 0);
9532 for (int iq = 0; iq < ctl->nq; iq++)
9533 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
9534 ctl->qnt_name[iq], ctl->qnt_unit[iq],
9535 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
9536
9537 /* Define global attributes... */
9538 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
9539 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
9540
9541 /* End definitions... */
9542 NC(nc_enddef(ncid));
9543
9544 /* Write data... */
9545 NC_PUT_DOUBLE("time", atm->time, 0);
9546 NC_PUT_DOUBLE("LAT", atm->lat, 0);
9547 NC_PUT_DOUBLE("LON", atm->lon, 0);
9548 NC_PUT_DOUBLE("PRESS", atm->p, 0);
9549 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 0);
9550 for (int iq = 0; iq < ctl->nq; iq++)
9551 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
9552
9553 /* Close file... */
9554 NC(nc_close(ncid));
9555 }
9556}
Here is the call graph for this function:

◆ write_atm_nc()

void write_atm_nc ( const char *  filename,
const ctl_t ctl,
const 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 9560 of file mptrac.c.

9563 {
9564
9565 int ncid, obsid, varid;
9566
9567 size_t start[2], count[2];
9568
9569 /* Create file... */
9570 NC(nc_create(filename, NC_NETCDF4, &ncid));
9571
9572 /* Define dimensions... */
9573 NC(nc_def_dim(ncid, "obs", (size_t) atm->np, &obsid));
9574
9575 /* Define variables and their attributes... */
9576 NC_DEF_VAR("time", NC_DOUBLE, 1, &obsid, "time",
9577 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
9578 NC_DEF_VAR("press", NC_DOUBLE, 1, &obsid, "pressure", "hPa",
9579 ctl->atm_nc_level, 0);
9580 NC_DEF_VAR("lon", NC_DOUBLE, 1, &obsid, "longitude", "degrees_east",
9581 ctl->atm_nc_level, 0);
9582 NC_DEF_VAR("lat", NC_DOUBLE, 1, &obsid, "latitude", "degrees_north",
9583 ctl->atm_nc_level, 0);
9584 for (int iq = 0; iq < ctl->nq; iq++)
9585 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 1, &obsid,
9586 ctl->qnt_longname[iq], ctl->qnt_unit[iq],
9587 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
9588
9589 /* Define global attributes... */
9590 NC_PUT_ATT_GLOBAL("featureType", "point");
9591
9592 /* End definitions... */
9593 NC(nc_enddef(ncid));
9594
9595 /* Write data... */
9596 NC_PUT_DOUBLE("time", atm->time, 0);
9597 NC_PUT_DOUBLE("press", atm->p, 0);
9598 NC_PUT_DOUBLE("lon", atm->lon, 0);
9599 NC_PUT_DOUBLE("lat", atm->lat, 0);
9600 for (int iq = 0; iq < ctl->nq; iq++)
9601 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
9602
9603 /* Close file... */
9604 NC(nc_close(ncid));
9605}

◆ write_csi()

void write_csi ( const char *  filename,
const ctl_t ctl,
const atm_t atm,
const 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 9609 of file mptrac.c.

9613 {
9614
9615 static FILE *out;
9616
9617 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
9618 *area, dlon, dlat, dz, x[NCSI], y[NCSI], obsstdn[NCSI], kz[EP], kw[EP];
9619
9620 static int *obscount, ct, cx, cy, cz, ip, ix, iy, iz, n, nobs, nk;
9621
9622 /* Set timer... */
9623 SELECT_TIMER("WRITE_CSI", "OUTPUT", NVTX_WRITE);
9624
9625 /* Init... */
9626 if (t == ctl->t_start) {
9627
9628 /* Check quantity index for mass... */
9629 if (ctl->qnt_m < 0)
9630 ERRMSG("Need quantity mass!");
9631
9632 /* Allocate... */
9633 ALLOC(area, double,
9634 ctl->csi_ny);
9635 ALLOC(rt, double,
9636 NOBS);
9637 ALLOC(rz, double,
9638 NOBS);
9639 ALLOC(rlon, double,
9640 NOBS);
9641 ALLOC(rlat, double,
9642 NOBS);
9643 ALLOC(robs, double,
9644 NOBS);
9645
9646 /* Read observation data... */
9647 read_obs(ctl->csi_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
9648
9649 /* Read kernel data... */
9650 if (ctl->csi_kernel[0] != '-')
9651 read_kernel(ctl->csi_kernel, kz, kw, &nk);
9652
9653 /* Create new file... */
9654 LOG(1, "Write CSI data: %s", filename);
9655 if (!(out = fopen(filename, "w")))
9656 ERRMSG("Cannot create file!");
9657
9658 /* Write header... */
9659 fprintf(out,
9660 "# $1 = time [s]\n"
9661 "# $2 = number of hits (cx)\n"
9662 "# $3 = number of misses (cy)\n"
9663 "# $4 = number of false alarms (cz)\n"
9664 "# $5 = number of observations (cx + cy)\n"
9665 "# $6 = number of forecasts (cx + cz)\n"
9666 "# $7 = bias (ratio of forecasts and observations) [%%]\n"
9667 "# $8 = probability of detection (POD) [%%]\n"
9668 "# $9 = false alarm rate (FAR) [%%]\n"
9669 "# $10 = critical success index (CSI) [%%]\n");
9670 fprintf(out,
9671 "# $11 = hits associated with random chance\n"
9672 "# $12 = equitable threat score (ETS) [%%]\n"
9673 "# $13 = Pearson linear correlation coefficient\n"
9674 "# $14 = Spearman rank-order correlation coefficient\n"
9675 "# $15 = column density mean error (F - O) [kg/m^2]\n"
9676 "# $16 = column density root mean square error (RMSE) [kg/m^2]\n"
9677 "# $17 = column density mean absolute error [kg/m^2]\n"
9678 "# $18 = log-likelihood function\n"
9679 "# $19 = number of data points\n\n");
9680
9681 /* Set grid box size... */
9682 dz = (ctl->csi_z1 - ctl->csi_z0) / ctl->csi_nz;
9683 dlon = (ctl->csi_lon1 - ctl->csi_lon0) / ctl->csi_nx;
9684 dlat = (ctl->csi_lat1 - ctl->csi_lat0) / ctl->csi_ny;
9685
9686 /* Set horizontal coordinates... */
9687 for (iy = 0; iy < ctl->csi_ny; iy++) {
9688 const double lat = ctl->csi_lat0 + dlat * (iy + 0.5);
9689 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat));
9690 }
9691 }
9692
9693 /* Set time interval... */
9694 const double t0 = t - 0.5 * ctl->dt_mod;
9695 const double t1 = t + 0.5 * ctl->dt_mod;
9696
9697 /* Allocate... */
9698 ALLOC(modmean, double,
9699 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
9700 ALLOC(obsmean, double,
9701 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
9702 ALLOC(obscount, int,
9703 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
9704 ALLOC(obsstd, double,
9705 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
9706
9707 /* Loop over observations... */
9708 for (int i = 0; i < nobs; i++) {
9709
9710 /* Check time... */
9711 if (rt[i] < t0)
9712 continue;
9713 else if (rt[i] >= t1)
9714 break;
9715
9716 /* Check observation data... */
9717 if (!isfinite(robs[i]))
9718 continue;
9719
9720 /* Calculate indices... */
9721 ix = (int) ((rlon[i] - ctl->csi_lon0) / dlon);
9722 iy = (int) ((rlat[i] - ctl->csi_lat0) / dlat);
9723 iz = (int) ((rz[i] - ctl->csi_z0) / dz);
9724
9725 /* Check indices... */
9726 if (ix < 0 || ix >= ctl->csi_nx ||
9727 iy < 0 || iy >= ctl->csi_ny || iz < 0 || iz >= ctl->csi_nz)
9728 continue;
9729
9730 /* Get mean observation index... */
9731 int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
9732 obsmean[idx] += robs[i];
9733 obsstd[idx] += SQR(robs[i]);
9734 obscount[idx]++;
9735 }
9736
9737 /* Analyze model data... */
9738 for (ip = 0; ip < atm->np; ip++) {
9739
9740 /* Check time... */
9741 if (atm->time[ip] < t0 || atm->time[ip] > t1)
9742 continue;
9743
9744 /* Get indices... */
9745 ix = (int) ((atm->lon[ip] - ctl->csi_lon0) / dlon);
9746 iy = (int) ((atm->lat[ip] - ctl->csi_lat0) / dlat);
9747 iz = (int) ((Z(atm->p[ip]) - ctl->csi_z0) / dz);
9748
9749 /* Check indices... */
9750 if (ix < 0 || ix >= ctl->csi_nx ||
9751 iy < 0 || iy >= ctl->csi_ny || iz < 0 || iz >= ctl->csi_nz)
9752 continue;
9753
9754 /* Get total mass in grid cell... */
9755 int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
9756 modmean[idx] += kernel_weight(kz, kw, nk, atm->p[ip])
9757 * atm->q[ctl->qnt_m][ip];
9758 }
9759
9760 /* Analyze all grid cells... */
9761 for (ix = 0; ix < ctl->csi_nx; ix++)
9762 for (iy = 0; iy < ctl->csi_ny; iy++)
9763 for (iz = 0; iz < ctl->csi_nz; iz++) {
9764
9765 /* Calculate mean observation index... */
9766 int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
9767 if (obscount[idx] > 0) {
9768 obsmean[idx] /= obscount[idx];
9769 obsstd[idx] -= SQR(obsmean[idx]);
9770 obsstd[idx] = sqrt(obsstd[idx]);
9771 }
9772
9773 /* Calculate column density... */
9774 if (modmean[idx] > 0)
9775 modmean[idx] /= (1e6 * area[iy]);
9776
9777 /* Calculate CSI... */
9778 if (obscount[idx] > 0) {
9779 ct++;
9780 if (obsmean[idx] >= ctl->csi_obsmin &&
9781 modmean[idx] >= ctl->csi_modmin)
9782 cx++;
9783 else if (obsmean[idx] >= ctl->csi_obsmin &&
9784 modmean[idx] < ctl->csi_modmin)
9785 cy++;
9786 else if (obsmean[idx] < ctl->csi_obsmin &&
9787 modmean[idx] >= ctl->csi_modmin)
9788 cz++;
9789 }
9790
9791 /* Save data for other verification statistics... */
9792 if (obscount[idx] > 0
9793 && (obsmean[idx] >= ctl->csi_obsmin
9794 || modmean[idx] >= ctl->csi_modmin)) {
9795 x[n] = modmean[idx];
9796 y[n] = obsmean[idx];
9797 if (modmean[idx] >= ctl->csi_modmin)
9798 obsstdn[n] = obsstd[idx];
9799 if ((++n) >= NCSI)
9800 ERRMSG("Too many data points to calculate statistics!");
9801 }
9802 }
9803
9804 /* Write output... */
9805 if (fmod(t, ctl->csi_dt_out) == 0) {
9806
9807 /* Calculate verification statistics
9808 (https://www.cawcr.gov.au/projects/verification/) ... */
9809 static double work[2 * NCSI], work2[2 * NCSI];;
9810 const int n_obs = cx + cy;
9811 const int n_for = cx + cz;
9812 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
9813 const double pod = (n_obs > 0) ? (100. * cx) / n_obs : NAN;
9814 const double far = (n_for > 0) ? (100. * cz) / n_for : NAN;
9815 const double csi =
9816 (cx + cy + cz > 0) ? (100. * cx) / (cx + cy + cz) : NAN;
9817 const double cx_rd = (ct > 0) ? (1. * n_obs * n_for) / ct : NAN;
9818 const double ets = (cx + cy + cz - cx_rd > 0) ?
9819 (100. * (cx - cx_rd)) / (cx + cy + cz - cx_rd) : NAN;
9820 const double rho_p =
9821 (n > 0) ? gsl_stats_correlation(x, 1, y, 1, (size_t) n) : NAN;
9822 const double rho_s =
9823 (n > 0) ? gsl_stats_spearman(x, 1, y, 1, (size_t) n, work) : NAN;
9824 for (int i = 0; i < n; i++) {
9825 work[i] = x[i] - y[i];
9826 work2[i] = (obsstdn[i] != 0) ? (x[i] - y[i]) / obsstdn[i] : 0;
9827 }
9828 const double mean = (n > 0) ? gsl_stats_mean(work, 1, (size_t) n) : NAN;
9829 const double rmse =
9830 (n > 0) ? gsl_stats_sd_with_fixed_mean(work, 1, (size_t) n,
9831 0.0) : NAN;
9832 const double absdev =
9833 (n > 0) ? gsl_stats_absdev_m(work, 1, (size_t) n, 0.0) : NAN;
9834 const double loglikelihood =
9835 (n > 0) ? gsl_stats_tss(work2, 1, (size_t) n) * (-0.5) : GSL_NAN;
9836
9837 /* Write... */
9838 fprintf(out,
9839 "%.2f %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n", t,
9840 cx, cy, cz, n_obs, n_for, bias, pod, far, csi, cx_rd, ets, rho_p,
9841 rho_s, mean, rmse, absdev, loglikelihood, n);
9842
9843 /* Set counters to zero... */
9844 n = ct = cx = cy = cz = 0;
9845 }
9846
9847 /* Free... */
9848 free(modmean);
9849 free(obsmean);
9850 free(obscount);
9851 free(obsstd);
9852
9853 /* Finalize... */
9854 if (t == ctl->t_stop) {
9855
9856 /* Close output file... */
9857 fclose(out);
9858
9859 /* Free... */
9860 free(area);
9861 free(rt);
9862 free(rz);
9863 free(rlon);
9864 free(rlat);
9865 free(robs);
9866 }
9867}
void read_obs(const char *filename, const 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:8745
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:6353
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:1716
#define NCSI
Maximum number of data points for CSI calculation.
Definition: mptrac.h:256
Here is the call graph for this function:

◆ write_ens()

void write_ens ( const char *  filename,
const ctl_t ctl,
const atm_t atm,
const 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 9871 of file mptrac.c.

9875 {
9876
9877 static FILE *out;
9878
9879 static double dummy, lat, lon, qm[NQ][NENS], qs[NQ][NENS], xm[NENS][3],
9880 x[3], zm[NENS];
9881
9882 static int n[NENS];
9883
9884 /* Set timer... */
9885 SELECT_TIMER("WRITE_ENS", "OUTPUT", NVTX_WRITE);
9886
9887 /* Check quantities... */
9888 if (ctl->qnt_ens < 0)
9889 ERRMSG("Missing ensemble IDs!");
9890
9891 /* Set time interval... */
9892 const double t0 = t - 0.5 * ctl->dt_mod;
9893 const double t1 = t + 0.5 * ctl->dt_mod;
9894
9895 /* Init... */
9896 for (int i = 0; i < NENS; i++) {
9897 for (int iq = 0; iq < ctl->nq; iq++)
9898 qm[iq][i] = qs[iq][i] = 0;
9899 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
9900 n[i] = 0;
9901 }
9902
9903 /* Loop over air parcels... */
9904 for (int ip = 0; ip < atm->np; ip++) {
9905
9906 /* Check time... */
9907 if (atm->time[ip] < t0 || atm->time[ip] > t1)
9908 continue;
9909
9910 /* Check ensemble ID... */
9911 if (atm->q[ctl->qnt_ens][ip] < 0 || atm->q[ctl->qnt_ens][ip] >= NENS)
9912 ERRMSG("Ensemble ID is out of range!");
9913
9914 /* Get means... */
9915 geo2cart(0, atm->lon[ip], atm->lat[ip], x);
9916 for (int iq = 0; iq < ctl->nq; iq++) {
9917 qm[iq][ctl->qnt_ens] += atm->q[iq][ip];
9918 qs[iq][ctl->qnt_ens] += SQR(atm->q[iq][ip]);
9919 }
9920 xm[ctl->qnt_ens][0] += x[0];
9921 xm[ctl->qnt_ens][1] += x[1];
9922 xm[ctl->qnt_ens][2] += x[2];
9923 zm[ctl->qnt_ens] += Z(atm->p[ip]);
9924 n[ctl->qnt_ens]++;
9925 }
9926
9927 /* Create file... */
9928 LOG(1, "Write ensemble data: %s", filename);
9929 if (!(out = fopen(filename, "w")))
9930 ERRMSG("Cannot create file!");
9931
9932 /* Write header... */
9933 fprintf(out,
9934 "# $1 = time [s]\n"
9935 "# $2 = altitude [km]\n"
9936 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
9937 for (int iq = 0; iq < ctl->nq; iq++)
9938 fprintf(out, "# $%d = %s (mean) [%s]\n", 5 + iq,
9939 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
9940 for (int iq = 0; iq < ctl->nq; iq++)
9941 fprintf(out, "# $%d = %s (sigma) [%s]\n", 5 + ctl->nq + iq,
9942 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
9943 fprintf(out, "# $%d = number of members\n\n", 5 + 2 * ctl->nq);
9944
9945 /* Write data... */
9946 for (int i = 0; i < NENS; i++)
9947 if (n[i] > 0) {
9948 cart2geo(xm[i], &dummy, &lon, &lat);
9949 fprintf(out, "%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
9950 for (int iq = 0; iq < ctl->nq; iq++) {
9951 fprintf(out, " ");
9952 fprintf(out, ctl->qnt_format[iq], qm[iq][i] / n[i]);
9953 }
9954 for (int iq = 0; iq < ctl->nq; iq++) {
9955 fprintf(out, " ");
9956 double var = qs[iq][i] / n[i] - SQR(qm[iq][i] / n[i]);
9957 fprintf(out, ctl->qnt_format[iq], (var > 0 ? sqrt(var) : 0));
9958 }
9959 fprintf(out, " %d\n", n[i]);
9960 }
9961
9962 /* Close file... */
9963 fclose(out);
9964}
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:276
Here is the call graph for this function:

◆ write_grid()

void write_grid ( const char *  filename,
const ctl_t ctl,
met_t met0,
met_t met1,
const atm_t atm,
const 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 9968 of file mptrac.c.

9974 {
9975
9976 static double kz[EP], kw[EP];
9977
9978 static int nk;
9979
9980 double *cd, *mean[NQ], *sigma[NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
9981
9982 int *ixs, *iys, *izs, *np;
9983
9984 /* Set timer... */
9985 SELECT_TIMER("WRITE_GRID", "OUTPUT", NVTX_WRITE);
9986
9987 /* Write info... */
9988 LOG(1, "Write grid data: %s", filename);
9989
9990 /* Init... */
9991 if (t == ctl->t_start) {
9992
9993 /* Read kernel data... */
9994 if (ctl->grid_kernel[0] != '-')
9995 read_kernel(ctl->grid_kernel, kz, kw, &nk);
9996 }
9997
9998 /* Allocate... */
9999 ALLOC(cd, double,
10000 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10001 for (int iq = 0; iq < ctl->nq; iq++) {
10002 ALLOC(mean[iq], double,
10003 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10004 ALLOC(sigma[iq], double,
10005 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10006 }
10007 ALLOC(vmr_impl, double,
10008 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10009 ALLOC(z, double,
10010 ctl->grid_nz);
10011 ALLOC(lon, double,
10012 ctl->grid_nx);
10013 ALLOC(lat, double,
10014 ctl->grid_ny);
10015 ALLOC(area, double,
10016 ctl->grid_ny);
10017 ALLOC(press, double,
10018 ctl->grid_nz);
10019 ALLOC(np, int,
10020 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10021 ALLOC(ixs, int,
10022 atm->np);
10023 ALLOC(iys, int,
10024 atm->np);
10025 ALLOC(izs, int,
10026 atm->np);
10027
10028 /* Set grid box size... */
10029 const double dz = (ctl->grid_z1 - ctl->grid_z0) / ctl->grid_nz;
10030 const double dlon = (ctl->grid_lon1 - ctl->grid_lon0) / ctl->grid_nx;
10031 const double dlat = (ctl->grid_lat1 - ctl->grid_lat0) / ctl->grid_ny;
10032
10033 /* Set vertical coordinates... */
10034#pragma omp parallel for default(shared)
10035 for (int iz = 0; iz < ctl->grid_nz; iz++) {
10036 z[iz] = ctl->grid_z0 + dz * (iz + 0.5);
10037 press[iz] = P(z[iz]);
10038 }
10039
10040 /* Set horizontal coordinates... */
10041 for (int ix = 0; ix < ctl->grid_nx; ix++)
10042 lon[ix] = ctl->grid_lon0 + dlon * (ix + 0.5);
10043#pragma omp parallel for default(shared)
10044 for (int iy = 0; iy < ctl->grid_ny; iy++) {
10045 lat[iy] = ctl->grid_lat0 + dlat * (iy + 0.5);
10046 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
10047 }
10048
10049 /* Set time interval for output... */
10050 const double t0 = t - 0.5 * ctl->dt_mod;
10051 const double t1 = t + 0.5 * ctl->dt_mod;
10052
10053 /* Get grid box indices... */
10054#pragma omp parallel for default(shared)
10055 for (int ip = 0; ip < atm->np; ip++) {
10056 ixs[ip] = (int) ((atm->lon[ip] - ctl->grid_lon0) / dlon);
10057 iys[ip] = (int) ((atm->lat[ip] - ctl->grid_lat0) / dlat);
10058 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->grid_z0) / dz);
10059 if (atm->time[ip] < t0 || atm->time[ip] > t1
10060 || ixs[ip] < 0 || ixs[ip] >= ctl->grid_nx
10061 || iys[ip] < 0 || iys[ip] >= ctl->grid_ny
10062 || izs[ip] < 0 || izs[ip] >= ctl->grid_nz)
10063 izs[ip] = -1;
10064 }
10065
10066 /* Average data... */
10067 for (int ip = 0; ip < atm->np; ip++)
10068 if (izs[ip] >= 0) {
10069 int idx =
10070 ARRAY_3D(ixs[ip], iys[ip], ctl->grid_ny, izs[ip], ctl->grid_nz);
10071 double kernel = kernel_weight(kz, kw, nk, atm->p[ip]);
10072 np[idx]++;
10073 for (int iq = 0; iq < ctl->nq; iq++) {
10074 mean[iq][idx] += kernel * atm->q[iq][ip];
10075 sigma[iq][idx] += SQR(kernel * atm->q[iq][ip]);
10076 }
10077 }
10078
10079 /* Calculate column density and volume mixing ratio... */
10080#pragma omp parallel for default(shared)
10081 for (int ix = 0; ix < ctl->grid_nx; ix++)
10082 for (int iy = 0; iy < ctl->grid_ny; iy++)
10083 for (int iz = 0; iz < ctl->grid_nz; iz++) {
10084
10085 /* Get grid index... */
10086 int idx = ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz);
10087
10088 /* Calculate column density... */
10089 cd[idx] = NAN;
10090 if (ctl->qnt_m >= 0)
10091 cd[idx] = mean[ctl->qnt_m][idx] / (1e6 * area[iy]);
10092
10093 /* Calculate volume mixing ratio (implicit)... */
10094 vmr_impl[idx] = NAN;
10095 if (ctl->qnt_m >= 0 && ctl->molmass > 0 && met0 != NULL
10096 && met1 != NULL) {
10097 vmr_impl[idx] = 0;
10098 if (mean[ctl->qnt_m][idx] > 0) {
10099
10100 /* Get temperature... */
10101 double temp;
10103 intpol_met_time_3d(met0, met0->t, met1, met1->t, t, press[iz],
10104 lon[ix], lat[iy], &temp, ci, cw, 1);
10105
10106 /* Calculate volume mixing ratio... */
10107 vmr_impl[idx] =
10108 MA / ctl->molmass * cd[idx] / (RHO(press[iz], temp) * dz * 1e3);
10109 }
10110 }
10111
10112 /* Calculate mean... */
10113 if (np[idx] > 0)
10114 for (int iq = 0; iq < ctl->nq; iq++) {
10115 mean[iq][idx] /= np[idx];
10116 double var = sigma[iq][idx] / np[idx] - SQR(mean[iq][idx]);
10117 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
10118 } else
10119 for (int iq = 0; iq < ctl->nq; iq++) {
10120 mean[iq][idx] = NAN;
10121 sigma[iq][idx] = NAN;
10122 }
10123 }
10124
10125 /* Write ASCII data... */
10126 if (ctl->grid_type == 0)
10127 write_grid_asc(filename, ctl, cd, mean, sigma, vmr_impl,
10128 t, z, lon, lat, area, dz, np);
10129
10130 /* Write netCDF data... */
10131 else if (ctl->grid_type == 1)
10132 write_grid_nc(filename, ctl, cd, mean, sigma, vmr_impl,
10133 t, z, lon, lat, area, dz, np);
10134
10135 /* Error message... */
10136 else
10137 ERRMSG("Grid data format GRID_TYPE unknown!");
10138
10139 /* Free... */
10140 free(cd);
10141 for (int iq = 0; iq < ctl->nq; iq++) {
10142 free(mean[iq]);
10143 free(sigma[iq]);
10144 }
10145 free(vmr_impl);
10146 free(z);
10147 free(lon);
10148 free(lat);
10149 free(area);
10150 free(press);
10151 free(np);
10152 free(ixs);
10153 free(iys);
10154 free(izs);
10155}
void write_grid_asc(const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
Writes grid data to an ASCII file.
Definition: mptrac.c:10159
void write_grid_nc(const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
Writes grid data to a NetCDF file.
Definition: mptrac.c:10263
Here is the call graph for this function:

◆ write_grid_asc()

void write_grid_asc ( const char *  filename,
const ctl_t ctl,
const double *  cd,
double *  mean[NQ],
double *  sigma[NQ],
const double *  vmr_impl,
const double  t,
const double *  z,
const double *  lon,
const double *  lat,
const double *  area,
const double  dz,
const 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 10159 of file mptrac.c.

10172 {
10173
10174 FILE *out;
10175
10176 /* Check if gnuplot output is requested... */
10177 if (ctl->grid_gpfile[0] != '-') {
10178
10179 /* Create gnuplot pipe... */
10180 if (!(out = popen("gnuplot", "w")))
10181 ERRMSG("Cannot create pipe to gnuplot!");
10182
10183 /* Set plot filename... */
10184 fprintf(out, "set out \"%s.png\"\n", filename);
10185
10186 /* Set time string... */
10187 double r;
10188 int year, mon, day, hour, min, sec;
10189 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
10190 fprintf(out, "timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
10191 year, mon, day, hour, min);
10192
10193 /* Dump gnuplot file to pipe... */
10194 FILE *in;
10195 char line[LEN];
10196 if (!(in = fopen(ctl->grid_gpfile, "r")))
10197 ERRMSG("Cannot open file!");
10198 while (fgets(line, LEN, in))
10199 fprintf(out, "%s", line);
10200 fclose(in);
10201 }
10202
10203 else {
10204
10205 /* Create file... */
10206 if (!(out = fopen(filename, "w")))
10207 ERRMSG("Cannot create file!");
10208 }
10209
10210 /* Write header... */
10211 fprintf(out,
10212 "# $1 = time [s]\n"
10213 "# $2 = altitude [km]\n"
10214 "# $3 = longitude [deg]\n"
10215 "# $4 = latitude [deg]\n"
10216 "# $5 = surface area [km^2]\n"
10217 "# $6 = layer depth [km]\n"
10218 "# $7 = column density (implicit) [kg/m^2]\n"
10219 "# $8 = volume mixing ratio (implicit) [ppv]\n"
10220 "# $9 = number of particles [1]\n");
10221 for (int iq = 0; iq < ctl->nq; iq++)
10222 fprintf(out, "# $%i = %s (mean) [%s]\n", 10 + iq, ctl->qnt_name[iq],
10223 ctl->qnt_unit[iq]);
10224 if (ctl->grid_stddev)
10225 for (int iq = 0; iq < ctl->nq; iq++)
10226 fprintf(out, "# $%i = %s (stddev) [%s]\n", 10 + ctl->nq + iq,
10227 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
10228 fprintf(out, "\n");
10229
10230 /* Write data... */
10231 for (int ix = 0; ix < ctl->grid_nx; ix++) {
10232 if (ix > 0 && ctl->grid_ny > 1 && !ctl->grid_sparse)
10233 fprintf(out, "\n");
10234 for (int iy = 0; iy < ctl->grid_ny; iy++) {
10235 if (iy > 0 && ctl->grid_nz > 1 && !ctl->grid_sparse)
10236 fprintf(out, "\n");
10237 for (int iz = 0; iz < ctl->grid_nz; iz++) {
10238 int idx = ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz);
10239 if (!ctl->grid_sparse || vmr_impl[idx] > 0) {
10240 fprintf(out, "%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
10241 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
10242 for (int iq = 0; iq < ctl->nq; iq++) {
10243 fprintf(out, " ");
10244 fprintf(out, ctl->qnt_format[iq], mean[iq][idx]);
10245 }
10246 if (ctl->grid_stddev)
10247 for (int iq = 0; iq < ctl->nq; iq++) {
10248 fprintf(out, " ");
10249 fprintf(out, ctl->qnt_format[iq], sigma[iq][idx]);
10250 }
10251 fprintf(out, "\n");
10252 }
10253 }
10254 }
10255 }
10256
10257 /* Close file... */
10258 fclose(out);
10259}
Here is the call graph for this function:

◆ write_grid_nc()

void write_grid_nc ( const char *  filename,
const ctl_t ctl,
const double *  cd,
double *  mean[NQ],
double *  sigma[NQ],
const double *  vmr_impl,
const double  t,
const double *  z,
const double *  lon,
const double *  lat,
const double *  area,
const double  dz,
const 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 10263 of file mptrac.c.

10276 {
10277
10278 char longname[2 * LEN], varname[2 * LEN];
10279
10280 double *help;
10281
10282 int *help2, ncid, dimid[10], varid;
10283
10284 size_t start[2], count[2];
10285
10286 /* Allocate... */
10287 ALLOC(help, double,
10288 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10289 ALLOC(help2, int,
10290 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10291
10292 /* Create file... */
10293 NC(nc_create(filename, NC_NETCDF4, &ncid));
10294
10295 /* Define dimensions... */
10296 NC(nc_def_dim(ncid, "time", 1, &dimid[0]));
10297 NC(nc_def_dim(ncid, "z", (size_t) ctl->grid_nz, &dimid[1]));
10298 NC(nc_def_dim(ncid, "lat", (size_t) ctl->grid_ny, &dimid[2]));
10299 NC(nc_def_dim(ncid, "lon", (size_t) ctl->grid_nx, &dimid[3]));
10300 NC(nc_def_dim(ncid, "dz", 1, &dimid[4]));
10301
10302 /* Define variables and their attributes... */
10303 NC_DEF_VAR("time", NC_DOUBLE, 1, &dimid[0], "time",
10304 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
10305 NC_DEF_VAR("z", NC_DOUBLE, 1, &dimid[1], "altitude", "km", 0, 0);
10306 NC_DEF_VAR("lat", NC_DOUBLE, 1, &dimid[2], "latitude", "degrees_north", 0,
10307 0);
10308 NC_DEF_VAR("lon", NC_DOUBLE, 1, &dimid[3], "longitude", "degrees_east", 0,
10309 0);
10310 NC_DEF_VAR("dz", NC_DOUBLE, 1, &dimid[1], "layer depth", "km", 0, 0);
10311 NC_DEF_VAR("area", NC_DOUBLE, 1, &dimid[2], "surface area", "km**2", 0, 0);
10312
10313 NC_DEF_VAR("cd", NC_FLOAT, 4, dimid, "column density", "kg m**-2",
10314 ctl->grid_nc_level, 0);
10315 NC_DEF_VAR("vmr_impl", NC_FLOAT, 4, dimid, "volume mixing ratio (implicit)",
10316 "ppv", ctl->grid_nc_level, 0);
10317 NC_DEF_VAR("np", NC_INT, 4, dimid, "number of particles", "1", 0, 0);
10318 for (int iq = 0; iq < ctl->nq; iq++) {
10319 sprintf(varname, "%s_mean", ctl->qnt_name[iq]);
10320 sprintf(longname, "%s (mean)", ctl->qnt_longname[iq]);
10321 NC_DEF_VAR(varname, NC_DOUBLE, 4, dimid, longname, ctl->qnt_unit[iq],
10322 ctl->grid_nc_level, ctl->grid_nc_quant[iq]);
10323 if (ctl->grid_stddev) {
10324 sprintf(varname, "%s_stddev", ctl->qnt_name[iq]);
10325 sprintf(longname, "%s (stddev)", ctl->qnt_longname[iq]);
10326 NC_DEF_VAR(varname, NC_DOUBLE, 4, dimid, longname, ctl->qnt_unit[iq],
10327 ctl->grid_nc_level, ctl->grid_nc_quant[iq]);
10328 }
10329 }
10330 /* End definitions... */
10331 NC(nc_enddef(ncid));
10332
10333 /* Write data... */
10334 NC_PUT_DOUBLE("time", &t, 0);
10335 NC_PUT_DOUBLE("lon", lon, 0);
10336 NC_PUT_DOUBLE("lat", lat, 0);
10337 NC_PUT_DOUBLE("z", z, 0);
10338 NC_PUT_DOUBLE("area", area, 0);
10339 NC_PUT_DOUBLE("dz", &dz, 0);
10340
10341 for (int ix = 0; ix < ctl->grid_nx; ix++)
10342 for (int iy = 0; iy < ctl->grid_ny; iy++)
10343 for (int iz = 0; iz < ctl->grid_nz; iz++)
10344 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
10345 cd[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
10346 NC_PUT_DOUBLE("cd", help, 0);
10347
10348 for (int ix = 0; ix < ctl->grid_nx; ix++)
10349 for (int iy = 0; iy < ctl->grid_ny; iy++)
10350 for (int iz = 0; iz < ctl->grid_nz; iz++)
10351 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
10352 vmr_impl[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
10353 NC_PUT_DOUBLE("vmr_impl", help, 0);
10354
10355 for (int ix = 0; ix < ctl->grid_nx; ix++)
10356 for (int iy = 0; iy < ctl->grid_ny; iy++)
10357 for (int iz = 0; iz < ctl->grid_nz; iz++)
10358 help2[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
10359 np[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
10360 NC_PUT_INT("np", help2, 0);
10361
10362 for (int iq = 0; iq < ctl->nq; iq++) {
10363 sprintf(varname, "%s_mean", ctl->qnt_name[iq]);
10364 for (int ix = 0; ix < ctl->grid_nx; ix++)
10365 for (int iy = 0; iy < ctl->grid_ny; iy++)
10366 for (int iz = 0; iz < ctl->grid_nz; iz++)
10367 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
10368 mean[iq][ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
10369 NC_PUT_DOUBLE(varname, help, 0);
10370 }
10371
10372 if (ctl->grid_stddev)
10373 for (int iq = 0; iq < ctl->nq; iq++) {
10374 sprintf(varname, "%s_stddev", ctl->qnt_name[iq]);
10375 for (int ix = 0; ix < ctl->grid_nx; ix++)
10376 for (int iy = 0; iy < ctl->grid_ny; iy++)
10377 for (int iz = 0; iz < ctl->grid_nz; iz++)
10378 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
10379 sigma[iq][ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
10380 NC_PUT_DOUBLE(varname, help, 0);
10381 }
10382
10383 /* Close file... */
10384 NC(nc_close(ncid));
10385
10386 /* Free... */
10387 free(help);
10388 free(help2);
10389}
#define NC_PUT_INT(varname, ptr, hyperslab)
Write integer data to a NetCDF variable.
Definition: mptrac.h:1173

◆ write_met_bin()

void write_met_bin ( const char *  filename,
const ctl_t ctl,
met_t met 
)

Writes meteorological data in binary format to a specified file.

This function writes meteorological data from the met_t structure to a binary file. The data includes grid and surface data, as well as multi-level data such as temperature, velocity components, and atmospheric properties. The compression options for multi-level data (ZFP) are controlled via the ctl_t structure. The function supports multiple variables, such as surface pressure, temperature, wind components, and cloud properties.

Parameters
filenameA constant character pointer representing the name of the file to write the binary data to.
ctlA pointer to a ctl_t structure, which holds control parameters including the type of meteorological data, compression settings, and grid dimensions.
metA pointer to a met_t structure that contains the meteorological data to be written to the binary file.
Note
  • The function creates a new file to write the data. If the file cannot be created, an error is generated.
  • The type of meteorological data (ctl->met_type) and the version of the binary format are written at the beginning of the file.
  • Grid data such as longitude, latitude, pressure levels, and time are written to the file.
  • Surface data (e.g., pressure, temperature, wind components) are written using the write_met_bin_2d helper function.
  • Multi-level (3D) data such as geopotential height, temperature, and wind velocity are written using the write_met_bin_3d function with optional ZFP compression settings.
Author
Lars Hoffmann

Definition at line 10393 of file mptrac.c.

10396 {
10397
10398 /* Create file... */
10399 FILE *out;
10400 if (!(out = fopen(filename, "w")))
10401 ERRMSG("Cannot create file!");
10402
10403 /* Write type of binary data... */
10404 FWRITE(&ctl->met_type, int,
10405 1,
10406 out);
10407
10408 /* Write version of binary data... */
10409 int version = 103;
10410 FWRITE(&version, int,
10411 1,
10412 out);
10413
10414 /* Write grid data... */
10415 FWRITE(&met->time, double,
10416 1,
10417 out);
10418 FWRITE(&met->nx, int,
10419 1,
10420 out);
10421 FWRITE(&met->ny, int,
10422 1,
10423 out);
10424 FWRITE(&met->np, int,
10425 1,
10426 out);
10427 FWRITE(met->lon, double,
10428 (size_t) met->nx,
10429 out);
10430 FWRITE(met->lat, double,
10431 (size_t) met->ny,
10432 out);
10433 FWRITE(met->p, double,
10434 (size_t) met->np,
10435 out);
10436
10437 /* Write surface data... */
10438 write_met_bin_2d(out, met, met->ps, "PS");
10439 write_met_bin_2d(out, met, met->ts, "TS");
10440 write_met_bin_2d(out, met, met->zs, "ZS");
10441 write_met_bin_2d(out, met, met->us, "US");
10442 write_met_bin_2d(out, met, met->vs, "VS");
10443 write_met_bin_2d(out, met, met->ess, "ESS");
10444 write_met_bin_2d(out, met, met->nss, "NSS");
10445 write_met_bin_2d(out, met, met->shf, "SHF");
10446 write_met_bin_2d(out, met, met->lsm, "LSM");
10447 write_met_bin_2d(out, met, met->sst, "SST");
10448 write_met_bin_2d(out, met, met->pbl, "PBL");
10449 write_met_bin_2d(out, met, met->pt, "PT");
10450 write_met_bin_2d(out, met, met->tt, "TT");
10451 write_met_bin_2d(out, met, met->zt, "ZT");
10452 write_met_bin_2d(out, met, met->h2ot, "H2OT");
10453 write_met_bin_2d(out, met, met->pct, "PCT");
10454 write_met_bin_2d(out, met, met->pcb, "PCB");
10455 write_met_bin_2d(out, met, met->cl, "CL");
10456 write_met_bin_2d(out, met, met->plcl, "PLCL");
10457 write_met_bin_2d(out, met, met->plfc, "PLFC");
10458 write_met_bin_2d(out, met, met->pel, "PEL");
10459 write_met_bin_2d(out, met, met->cape, "CAPE");
10460 write_met_bin_2d(out, met, met->cin, "CIN");
10461 write_met_bin_2d(out, met, met->o3c, "O3C");
10462
10463 /* Write level data... */
10464 write_met_bin_3d(out, ctl, met, met->z, "Z",
10465 (ctl->met_zfp_tol_z <= 0 ? ctl->met_zfp_prec : 0),
10466 ctl->met_zfp_tol_z);
10467 write_met_bin_3d(out, ctl, met, met->t, "T",
10468 (ctl->met_zfp_tol_t <= 0 ? ctl->met_zfp_prec : 0),
10469 ctl->met_zfp_tol_t);
10470 write_met_bin_3d(out, ctl, met, met->u, "U", ctl->met_zfp_prec, 0);
10471 write_met_bin_3d(out, ctl, met, met->v, "V", ctl->met_zfp_prec, 0);
10472 write_met_bin_3d(out, ctl, met, met->w, "W", ctl->met_zfp_prec, 0);
10473 write_met_bin_3d(out, ctl, met, met->pv, "PV", ctl->met_zfp_prec, 0);
10474 write_met_bin_3d(out, ctl, met, met->h2o, "H2O", ctl->met_zfp_prec, 0);
10475 write_met_bin_3d(out, ctl, met, met->o3, "O3", ctl->met_zfp_prec, 0);
10476 write_met_bin_3d(out, ctl, met, met->lwc, "LWC", ctl->met_zfp_prec, 0);
10477 write_met_bin_3d(out, ctl, met, met->rwc, "RWC", ctl->met_zfp_prec, 0);
10478 write_met_bin_3d(out, ctl, met, met->iwc, "IWC", ctl->met_zfp_prec, 0);
10479 write_met_bin_3d(out, ctl, met, met->swc, "SWC", ctl->met_zfp_prec, 0);
10480 write_met_bin_3d(out, ctl, met, met->cc, "CC", ctl->met_zfp_prec, 0);
10481
10482 /* Write final flag... */
10483 int final = 999;
10484 FWRITE(&final, int,
10485 1,
10486 out);
10487
10488 /* Close file... */
10489 fclose(out);
10490}
void write_met_bin_3d(FILE *out, const ctl_t *ctl, met_t *met, float var[EX][EY][EP], const char *varname, const int precision, const double tolerance)
Writes a 3-dimensional meteorological variable to a binary file.
Definition: mptrac.c:10523
void write_met_bin_2d(FILE *out, met_t *met, float var[EX][EY], const char *varname)
Writes a 2-dimensional meteorological variable to a binary file.
Definition: mptrac.c:10494
int met_zfp_prec
ZFP compression precision for all variables, except z and T.
Definition: mptrac.h:2498
double met_zfp_tol_t
ZFP compression tolerance for temperature.
Definition: mptrac.h:2501
double met_zfp_tol_z
ZFP compression tolerance for geopotential height.
Definition: mptrac.h:2504
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],
const 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 10494 of file mptrac.c.

10498 {
10499
10500 float *help;
10501
10502 /* Allocate... */
10503 ALLOC(help, float,
10504 EX * EY);
10505
10506 /* Copy data... */
10507 for (int ix = 0; ix < met->nx; ix++)
10508 for (int iy = 0; iy < met->ny; iy++)
10509 help[ARRAY_2D(ix, iy, met->ny)] = var[ix][iy];
10510
10511 /* Write uncompressed data... */
10512 LOG(2, "Write 2-D variable: %s (uncompressed)", varname);
10513 FWRITE(help, float,
10514 (size_t) (met->nx * met->ny),
10515 out);
10516
10517 /* Free... */
10518 free(help);
10519}

◆ write_met_bin_3d()

void write_met_bin_3d ( FILE *  out,
const ctl_t ctl,
met_t met,
float  var[EX][EY][EP],
const char *  varname,
const int  precision,
const 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 10523 of file mptrac.c.

10530 {
10531
10532 float *help;
10533
10534 /* Allocate... */
10535 ALLOC(help, float,
10536 EX * EY * EP);
10537
10538 /* Copy data... */
10539#pragma omp parallel for default(shared) collapse(2)
10540 for (int ix = 0; ix < met->nx; ix++)
10541 for (int iy = 0; iy < met->ny; iy++)
10542 for (int ip = 0; ip < met->np; ip++)
10543 help[ARRAY_3D(ix, iy, met->ny, ip, met->np)] = var[ix][iy][ip];
10544
10545 /* Write uncompressed data... */
10546 if (ctl->met_type == 1) {
10547 LOG(2, "Write 3-D variable: %s (uncompressed)", varname);
10548 FWRITE(help, float,
10549 (size_t) (met->nx * met->ny * met->np),
10550 out);
10551 }
10552
10553 /* Write packed data... */
10554 else if (ctl->met_type == 2)
10555 compress_pck(varname, help, (size_t) (met->ny * met->nx),
10556 (size_t) met->np, 0, out);
10557
10558 /* Write zfp data... */
10559#ifdef ZFP
10560 else if (ctl->met_type == 3) {
10561 FWRITE(&precision, int,
10562 1,
10563 out);
10564 FWRITE(&tolerance, double,
10565 1,
10566 out);
10567 compress_zfp(varname, help, met->np, met->ny, met->nx, precision,
10568 tolerance, 0, out);
10569 }
10570#endif
10571
10572 /* Write zstd data... */
10573#ifdef ZSTD
10574 else if (ctl->met_type == 4)
10575 compress_zstd(varname, help, (size_t) (met->np * met->ny * met->nx), 0,
10576 out);
10577#endif
10578
10579 /* Write cmultiscale data... */
10580#ifdef CMS
10581 else if (ctl->met_type == 5) {
10582 compress_cms(ctl, varname, help, (size_t) met->nx, (size_t) met->ny,
10583 (size_t) met->np, 0, out);
10584 }
10585#endif
10586
10587 /* Unknown method... */
10588 else {
10589 ERRMSG("MET_TYPE not supported!");
10590 LOG(3, "%d %g", precision, tolerance);
10591 }
10592
10593 /* Free... */
10594 free(help);
10595}
Here is the call graph for this function:

◆ write_met_nc()

void write_met_nc ( const char *  filename,
const ctl_t ctl,
met_t met 
)

Writes meteorological data to a NetCDF file.

This function creates and writes meteorological data to a NetCDF file in the NetCDF-4 format. It defines the required dimensions, grid, surface variables, and level data within the NetCDF structure and writes the corresponding values from the met_t structure. The function uses helper functions to write 2D surface and 3D level data.

Parameters
filenameA constant character pointer representing the name of the NetCDF file to create and write the data to.
ctlA pointer to a ctl_t structure that contains control parameters, such as the NetCDF level and quantization settings.
metA pointer to a met_t structure that contains the meteorological data to be written to the NetCDF file.
Note
  • The function uses the NetCDF-4 format for efficient data storage.
  • It defines the grid dimensions (time, longitude, latitude, pressure levels) and adds global attributes like units and descriptions for each variable.
  • The surface variables include surface pressure, geopotential, 2-meter temperature, and wind components, which are defined on a 2D grid (latitude × longitude).
  • The level variables, such as temperature, wind velocities, and cloud properties, are defined on a 3D grid (pressure level × latitude × longitude).
Author
Lars Hoffmann

Definition at line 10599 of file mptrac.c.

10602 {
10603
10604 /* Create file... */
10605 int ncid, varid;
10606 size_t start[4], count[4];
10607 nc_create(filename, NC_NETCDF4, &ncid);
10608
10609 /* Define dimensions... */
10610 int tid, lonid, latid, levid;
10611 NC(nc_def_dim(ncid, "time", 1, &tid));
10612 NC(nc_def_dim(ncid, "lon", (size_t) met->nx, &lonid));
10613 NC(nc_def_dim(ncid, "lat", (size_t) met->ny, &latid));
10614 NC(nc_def_dim(ncid, "lev", (size_t) met->np, &levid));
10615
10616 /* Define grid... */
10617 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "time",
10618 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
10619 NC_DEF_VAR("lon", NC_DOUBLE, 1, &lonid, "longitude", "degrees_east", 0, 0);
10620 NC_DEF_VAR("lat", NC_DOUBLE, 1, &latid, "latitude", "degrees_north", 0, 0);
10621 NC_DEF_VAR("lev", NC_DOUBLE, 1, &levid, "pressure", "Pa", 0, 0);
10622
10623 /* Define surface variables... */
10624 int dimid2[2] = { latid, lonid };
10625 NC_DEF_VAR("sp", NC_FLOAT, 2, dimid2, "Surface pressure", "Pa",
10626 ctl->met_nc_level, 0);
10627 NC_DEF_VAR("z", NC_FLOAT, 2, dimid2, "Geopotential", "m**2 s**-2",
10628 ctl->met_nc_level, 0);
10629 NC_DEF_VAR("t2m", NC_FLOAT, 2, dimid2, "2 metre temperature", "K",
10630 ctl->met_nc_level, 0);
10631 NC_DEF_VAR("u10m", NC_FLOAT, 2, dimid2, "10 metre U wind component",
10632 "m s**-1", ctl->met_nc_level, 0);
10633 NC_DEF_VAR("v10m", NC_FLOAT, 2, dimid2, "10 metre V wind component",
10634 "m s**-1", ctl->met_nc_level, 0);
10635 NC_DEF_VAR("iews", NC_FLOAT, 2, dimid2,
10636 "Instantaneous eastward turbulent surface stress", "N m**-2",
10637 ctl->met_nc_level, 0);
10638 NC_DEF_VAR("inss", NC_FLOAT, 2, dimid2,
10639 "Instantaneous northward turbulent surface stress", "N m**-2",
10640 ctl->met_nc_level, 0);
10641 NC_DEF_VAR("ishf", NC_FLOAT, 2, dimid2,
10642 "Instantaneous surface sensible heat flux", "W m**-1",
10643 ctl->met_nc_level, 0);
10644 NC_DEF_VAR("lsm", NC_FLOAT, 2, dimid2, "Land/sea mask", "-",
10645 ctl->met_nc_level, 0);
10646 NC_DEF_VAR("sstk", NC_FLOAT, 2, dimid2, "Sea surface temperature", "K",
10647 ctl->met_nc_level, 0);
10648 NC_DEF_VAR("blp", NC_FLOAT, 2, dimid2, "Boundary layer pressure", "Pa",
10649 ctl->met_nc_level, 0);
10650 NC_DEF_VAR("pt", NC_FLOAT, 2, dimid2, "Tropopause pressure", "Pa",
10651 ctl->met_nc_level, 0);
10652 NC_DEF_VAR("tt", NC_FLOAT, 2, dimid2, "Tropopause temperature", "K",
10653 ctl->met_nc_level, 0);
10654 NC_DEF_VAR("zt", NC_FLOAT, 2, dimid2, "Tropopause height", "m",
10655 ctl->met_nc_level, 0);
10656 NC_DEF_VAR("h2ot", NC_FLOAT, 2, dimid2, "Tropopause water vapor", "ppv",
10657 ctl->met_nc_level, 0);
10658 NC_DEF_VAR("pct", NC_FLOAT, 2, dimid2, "Cloud top pressure", "Pa",
10659 ctl->met_nc_level, 0);
10660 NC_DEF_VAR("pcb", NC_FLOAT, 2, dimid2, "Cloud bottom pressure", "Pa",
10661 ctl->met_nc_level, 0);
10662 NC_DEF_VAR("cl", NC_FLOAT, 2, dimid2, "Total column cloud water", "kg m**2",
10663 ctl->met_nc_level, 0);
10664 NC_DEF_VAR("plcl", NC_FLOAT, 2, dimid2,
10665 "Pressure at lifted condensation level (LCL)", "Pa",
10666 ctl->met_nc_level, 0);
10667 NC_DEF_VAR("plfc", NC_FLOAT, 2, dimid2,
10668 "Pressure at level of free convection (LFC)", "Pa",
10669 ctl->met_nc_level, 0);
10670 NC_DEF_VAR("pel", NC_FLOAT, 2, dimid2, "Pressure at equilibrium level (EL)",
10671 "Pa", ctl->met_nc_level, 0);
10672 NC_DEF_VAR("cape", NC_FLOAT, 2, dimid2,
10673 "Convective available potential energy", "J kg**-1",
10674 ctl->met_nc_level, 0);
10675 NC_DEF_VAR("cin", NC_FLOAT, 2, dimid2, "Convective inhibition", "J kg**-1",
10676 ctl->met_nc_level, 0);
10677 NC_DEF_VAR("o3c", NC_FLOAT, 2, dimid2, "Total column ozone", "DU",
10678 ctl->met_nc_level, 0);
10679
10680 /* Define level data... */
10681 int dimid3[3] = { levid, latid, lonid };
10682 NC_DEF_VAR("t", NC_FLOAT, 3, dimid3, "Temperature", "K",
10683 ctl->met_nc_level, ctl->met_nc_quant);
10684 NC_DEF_VAR("u", NC_FLOAT, 3, dimid3, "U velocity", "m s**-1",
10685 ctl->met_nc_level, ctl->met_nc_quant);
10686 NC_DEF_VAR("v", NC_FLOAT, 3, dimid3, "V velocity", "m s**-1",
10687 ctl->met_nc_level, ctl->met_nc_quant);
10688 NC_DEF_VAR("w", NC_FLOAT, 3, dimid3, "Vertical velocity", "Pa s**-1",
10689 ctl->met_nc_level, ctl->met_nc_quant);
10690 NC_DEF_VAR("q", NC_FLOAT, 3, dimid3, "Specific humidity", "kg kg**-1",
10691 ctl->met_nc_level, ctl->met_nc_quant);
10692 NC_DEF_VAR("o3", NC_FLOAT, 3, dimid3, "Ozone mass mixing ratio",
10693 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
10694 NC_DEF_VAR("clwc", NC_FLOAT, 3, dimid3, "Cloud liquid water content",
10695 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
10696 NC_DEF_VAR("crwc", NC_FLOAT, 3, dimid3, "Cloud rain water content",
10697 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
10698 NC_DEF_VAR("ciwc", NC_FLOAT, 3, dimid3, "Cloud ice water content",
10699 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
10700 NC_DEF_VAR("cswc", NC_FLOAT, 3, dimid3, "Cloud snow water content",
10701 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
10702 NC_DEF_VAR("cc", NC_FLOAT, 3, dimid3, "Cloud cover", "-",
10703 ctl->met_nc_level, ctl->met_nc_quant);
10704
10705 /* End definitions... */
10706 NC(nc_enddef(ncid));
10707
10708 /* Write grid data... */
10709 NC_PUT_DOUBLE("time", &met->time, 0);
10710 NC_PUT_DOUBLE("lon", met->lon, 0);
10711 NC_PUT_DOUBLE("lat", met->lat, 0);
10712 double phelp[EP];
10713 for (int ip = 0; ip < met->np; ip++)
10714 phelp[ip] = 100. * met->p[ip];
10715 NC_PUT_DOUBLE("lev", phelp, 0);
10716
10717 /* Write surface data... */
10718 write_met_nc_2d(ncid, "sp", met, met->ps, 100.0f);
10719 write_met_nc_2d(ncid, "z", met, met->zs, (float) (1000. * G0));
10720 write_met_nc_2d(ncid, "t2m", met, met->ts, 1.0f);
10721 write_met_nc_2d(ncid, "u10m", met, met->us, 1.0f);
10722 write_met_nc_2d(ncid, "v10m", met, met->vs, 1.0f);
10723 write_met_nc_2d(ncid, "iews", met, met->ess, 1.0f);
10724 write_met_nc_2d(ncid, "inss", met, met->nss, 1.0f);
10725 write_met_nc_2d(ncid, "ishf", met, met->shf, 1.0f);
10726 write_met_nc_2d(ncid, "lsm", met, met->lsm, 1.0f);
10727 write_met_nc_2d(ncid, "sstk", met, met->sst, 1.0f);
10728 write_met_nc_2d(ncid, "blp", met, met->pbl, 100.0f);
10729 write_met_nc_2d(ncid, "pt", met, met->pt, 100.0f);
10730 write_met_nc_2d(ncid, "tt", met, met->tt, 1.0f);
10731 write_met_nc_2d(ncid, "zt", met, met->zt, 1000.0f);
10732 write_met_nc_2d(ncid, "h2ot", met, met->h2ot, 1.0f);
10733 write_met_nc_2d(ncid, "pct", met, met->pct, 100.0f);
10734 write_met_nc_2d(ncid, "pcb", met, met->pcb, 100.0f);
10735 write_met_nc_2d(ncid, "cl", met, met->cl, 1.0f);
10736 write_met_nc_2d(ncid, "plcl", met, met->plcl, 100.0f);
10737 write_met_nc_2d(ncid, "plfc", met, met->plfc, 100.0f);
10738 write_met_nc_2d(ncid, "pel", met, met->pel, 100.0f);
10739 write_met_nc_2d(ncid, "cape", met, met->cape, 1.0f);
10740 write_met_nc_2d(ncid, "cin", met, met->cin, 1.0f);
10741 write_met_nc_2d(ncid, "o3c", met, met->o3c, 1.0f);
10742
10743 /* Write level data... */
10744 write_met_nc_3d(ncid, "t", met, met->t, 1.0f);
10745 write_met_nc_3d(ncid, "u", met, met->u, 1.0f);
10746 write_met_nc_3d(ncid, "v", met, met->v, 1.0f);
10747 write_met_nc_3d(ncid, "w", met, met->w, 100.0f);
10748 write_met_nc_3d(ncid, "q", met, met->h2o, (float) (MH2O / MA));
10749 write_met_nc_3d(ncid, "o3", met, met->o3, (float) (MO3 / MA));
10750 write_met_nc_3d(ncid, "clwc", met, met->lwc, 1.0f);
10751 write_met_nc_3d(ncid, "crwc", met, met->rwc, 1.0f);
10752 write_met_nc_3d(ncid, "ciwc", met, met->iwc, 1.0f);
10753 write_met_nc_3d(ncid, "cswc", met, met->swc, 1.0f);
10754 write_met_nc_3d(ncid, "cc", met, met->cc, 1.0f);
10755
10756 /* Close file... */
10757 NC(nc_close(ncid));
10758}
void write_met_nc_2d(const int ncid, const char *varname, met_t *met, float var[EX][EY], const float scl)
Writes a 2D meteorological variable to a NetCDF file.
Definition: mptrac.c:10762
void write_met_nc_3d(const int ncid, const char *varname, met_t *met, float var[EX][EY][EP], const float scl)
Writes a 3D meteorological variable to a NetCDF file.
Definition: mptrac.c:10791
int met_nc_quant
Number of digits for quantization of netCDF meteo files (0=off).
Definition: mptrac.h:2495
int met_nc_level
zlib compression level of netCDF meteo files (0=off).
Definition: mptrac.h:2492
Here is the call graph for this function:

◆ write_met_nc_2d()

void write_met_nc_2d ( const int  ncid,
const char *  varname,
met_t met,
float  var[EX][EY],
const float  scl 
)

Writes a 2D meteorological variable to a NetCDF file.

This function writes a 2D meteorological variable, stored in the array var, to a NetCDF file with the specified variable name. The data is scaled by a factor scl before being written. The function handles memory allocation for the data copy, scaling, and freeing the allocated memory after writing the data to the NetCDF file.

Parameters
ncidThe NetCDF file ID. This is an integer that identifies the NetCDF file where the data will be written. It is assumed that this file has already been opened for writing.
varnameA pointer to a string containing the name of the variable in the NetCDF file where the data will be stored.
metA pointer to a structure of type met_t that contains metadata about the meteorological field, including the dimensions nx (number of points in x-direction) and ny (number of points in y-direction).
varA 2D array of dimensions EX x EY containing the meteorological data to be written. The data is provided in the format var[ix][iy], where ix is the index in the x-direction and iy is the index in the y-direction.
sclA scaling factor applied to each element in the var array before writing to the NetCDF file.
Returns
void This function does not return any value.
Author
Lars Hoffmann

Definition at line 10762 of file mptrac.c.

10767 {
10768
10769 int varid;
10770 size_t start[4], count[4];
10771
10772 /* Allocate... */
10773 float *help;
10774 ALLOC(help, float,
10775 EX * EY);
10776
10777 /* Copy data... */
10778 for (int ix = 0; ix < met->nx; ix++)
10779 for (int iy = 0; iy < met->ny; iy++)
10780 help[ARRAY_2D(iy, ix, met->nx)] = scl * var[ix][iy];
10781
10782 /* Write data... */
10783 NC_PUT_FLOAT(varname, help, 0);
10784
10785 /* Free... */
10786 free(help);
10787}
#define NC_PUT_FLOAT(varname, ptr, hyperslab)
Write a float array to a NetCDF file.
Definition: mptrac.h:1150

◆ write_met_nc_3d()

void write_met_nc_3d ( const int  ncid,
const char *  varname,
met_t met,
float  var[EX][EY][EP],
const float  scl 
)

Writes a 3D meteorological variable to a NetCDF file.

This function writes a 3D meteorological variable, stored in the array var, to a NetCDF file with the specified variable name. The data is scaled by a factor scl before being written. The function handles memory allocation for the data copy, scaling, and freeing the allocated memory after writing the data to the NetCDF file.

Parameters
ncidThe NetCDF file ID. This is an integer that identifies the NetCDF file where the data will be written. It is assumed that this file has already been opened for writing.
varnameA pointer to a string containing the name of the variable in the NetCDF file where the data will be stored.
metA pointer to a structure of type met_t that contains metadata about the meteorological field, including the dimensions nx (number of points in the x-direction), ny (number of points in the y-direction), and np (number of points in the third dimension, e.g., pressure levels).
varA 3D array of dimensions EX x EY x EP containing the meteorological data to be written. The data is provided in the format var[ix][iy][ip], where ix is the index in the x-direction, iy is the index in the y-direction, and ip is the index in the third dimension (e.g., vertical levels).
sclA scaling factor applied to each element in the var array before writing to the NetCDF file.
Returns
void This function does not return any value.
Author
Lars Hoffmann

Definition at line 10791 of file mptrac.c.

10796 {
10797
10798 int varid;
10799 size_t start[4], count[4];
10800
10801 /* Allocate... */
10802 float *help;
10803 ALLOC(help, float,
10804 EX * EY * EP);
10805
10806 /* Copy data... */
10807 for (int ix = 0; ix < met->nx; ix++)
10808 for (int iy = 0; iy < met->ny; iy++)
10809 for (int ip = 0; ip < met->np; ip++)
10810 help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)] = scl * var[ix][iy][ip];
10811
10812 /* Write data... */
10813 NC_PUT_FLOAT(varname, help, 0);
10814
10815 /* Free... */
10816 free(help);
10817}

◆ write_prof()

void write_prof ( const char *  filename,
const ctl_t ctl,
met_t met0,
met_t met1,
const atm_t atm,
const 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 10821 of file mptrac.c.

10827 {
10828
10829 static FILE *out;
10830
10831 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
10832 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
10833
10834 static int nobs, *obscount, ip, okay;
10835
10836 /* Set timer... */
10837 SELECT_TIMER("WRITE_PROF", "OUTPUT", NVTX_WRITE);
10838
10839 /* Init... */
10840 if (t == ctl->t_start) {
10841
10842 /* Check quantity index for mass... */
10843 if (ctl->qnt_m < 0)
10844 ERRMSG("Need quantity mass!");
10845
10846 /* Check molar mass... */
10847 if (ctl->molmass <= 0)
10848 ERRMSG("Specify molar mass!");
10849
10850 /* Allocate... */
10851 ALLOC(lon, double,
10852 ctl->prof_nx);
10853 ALLOC(lat, double,
10854 ctl->prof_ny);
10855 ALLOC(area, double,
10856 ctl->prof_ny);
10857 ALLOC(z, double,
10858 ctl->prof_nz);
10859 ALLOC(press, double,
10860 ctl->prof_nz);
10861 ALLOC(rt, double,
10862 NOBS);
10863 ALLOC(rz, double,
10864 NOBS);
10865 ALLOC(rlon, double,
10866 NOBS);
10867 ALLOC(rlat, double,
10868 NOBS);
10869 ALLOC(robs, double,
10870 NOBS);
10871
10872 /* Read observation data... */
10873 read_obs(ctl->prof_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
10874
10875 /* Create new output file... */
10876 LOG(1, "Write profile data: %s", filename);
10877 if (!(out = fopen(filename, "w")))
10878 ERRMSG("Cannot create file!");
10879
10880 /* Write header... */
10881 fprintf(out,
10882 "# $1 = time [s]\n"
10883 "# $2 = altitude [km]\n"
10884 "# $3 = longitude [deg]\n"
10885 "# $4 = latitude [deg]\n"
10886 "# $5 = pressure [hPa]\n"
10887 "# $6 = temperature [K]\n"
10888 "# $7 = volume mixing ratio [ppv]\n"
10889 "# $8 = H2O volume mixing ratio [ppv]\n"
10890 "# $9 = O3 volume mixing ratio [ppv]\n"
10891 "# $10 = observed BT index [K]\n"
10892 "# $11 = number of observations\n");
10893
10894 /* Set grid box size... */
10895 dz = (ctl->prof_z1 - ctl->prof_z0) / ctl->prof_nz;
10896 dlon = (ctl->prof_lon1 - ctl->prof_lon0) / ctl->prof_nx;
10897 dlat = (ctl->prof_lat1 - ctl->prof_lat0) / ctl->prof_ny;
10898
10899 /* Set vertical coordinates... */
10900 for (int iz = 0; iz < ctl->prof_nz; iz++) {
10901 z[iz] = ctl->prof_z0 + dz * (iz + 0.5);
10902 press[iz] = P(z[iz]);
10903 }
10904
10905 /* Set horizontal coordinates... */
10906 for (int ix = 0; ix < ctl->prof_nx; ix++)
10907 lon[ix] = ctl->prof_lon0 + dlon * (ix + 0.5);
10908 for (int iy = 0; iy < ctl->prof_ny; iy++) {
10909 lat[iy] = ctl->prof_lat0 + dlat * (iy + 0.5);
10910 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
10911 }
10912 }
10913
10914 /* Set time interval... */
10915 const double t0 = t - 0.5 * ctl->dt_mod;
10916 const double t1 = t + 0.5 * ctl->dt_mod;
10917
10918 /* Allocate... */
10919 ALLOC(mass, double,
10920 ctl->prof_nx * ctl->prof_ny * ctl->prof_nz);
10921 ALLOC(obsmean, double,
10922 ctl->prof_nx * ctl->prof_ny);
10923 ALLOC(obscount, int,
10924 ctl->prof_nx * ctl->prof_ny);
10925
10926 /* Loop over observations... */
10927 for (int i = 0; i < nobs; i++) {
10928
10929 /* Check time... */
10930 if (rt[i] < t0)
10931 continue;
10932 else if (rt[i] >= t1)
10933 break;
10934
10935 /* Check observation data... */
10936 if (!isfinite(robs[i]))
10937 continue;
10938
10939 /* Calculate indices... */
10940 int ix = (int) ((rlon[i] - ctl->prof_lon0) / dlon);
10941 int iy = (int) ((rlat[i] - ctl->prof_lat0) / dlat);
10942
10943 /* Check indices... */
10944 if (ix < 0 || ix >= ctl->prof_nx || iy < 0 || iy >= ctl->prof_ny)
10945 continue;
10946
10947 /* Get mean observation index... */
10948 int idx = ARRAY_2D(ix, iy, ctl->prof_ny);
10949 obsmean[idx] += robs[i];
10950 obscount[idx]++;
10951 }
10952
10953 /* Analyze model data... */
10954 for (ip = 0; ip < atm->np; ip++) {
10955
10956 /* Check time... */
10957 if (atm->time[ip] < t0 || atm->time[ip] > t1)
10958 continue;
10959
10960 /* Get indices... */
10961 int ix = (int) ((atm->lon[ip] - ctl->prof_lon0) / dlon);
10962 int iy = (int) ((atm->lat[ip] - ctl->prof_lat0) / dlat);
10963 int iz = (int) ((Z(atm->p[ip]) - ctl->prof_z0) / dz);
10964
10965 /* Check indices... */
10966 if (ix < 0 || ix >= ctl->prof_nx ||
10967 iy < 0 || iy >= ctl->prof_ny || iz < 0 || iz >= ctl->prof_nz)
10968 continue;
10969
10970 /* Get total mass in grid cell... */
10971 int idx = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
10972 mass[idx] += atm->q[ctl->qnt_m][ip];
10973 }
10974
10975 /* Extract profiles... */
10976 for (int ix = 0; ix < ctl->prof_nx; ix++)
10977 for (int iy = 0; iy < ctl->prof_ny; iy++) {
10978 int idx2 = ARRAY_2D(ix, iy, ctl->prof_ny);
10979 if (obscount[idx2] > 0) {
10980
10981 /* Check profile... */
10982 okay = 0;
10983 for (int iz = 0; iz < ctl->prof_nz; iz++) {
10984 int idx3 = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
10985 if (mass[idx3] > 0) {
10986 okay = 1;
10987 break;
10988 }
10989 }
10990 if (!okay)
10991 continue;
10992
10993 /* Write output... */
10994 fprintf(out, "\n");
10995
10996 /* Loop over altitudes... */
10997 for (int iz = 0; iz < ctl->prof_nz; iz++) {
10998
10999 /* Get temperature, water vapor, and ozone... */
11001 intpol_met_time_3d(met0, met0->t, met1, met1->t, t, press[iz],
11002 lon[ix], lat[iy], &temp, ci, cw, 1);
11003 intpol_met_time_3d(met0, met0->h2o, met1, met1->h2o, t, press[iz],
11004 lon[ix], lat[iy], &h2o, ci, cw, 0);
11005 intpol_met_time_3d(met0, met0->o3, met1, met1->o3, t, press[iz],
11006 lon[ix], lat[iy], &o3, ci, cw, 0);
11007
11008 /* Calculate volume mixing ratio... */
11009 const int idx3 = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
11010 vmr = MA / ctl->molmass * mass[idx3]
11011 / (RHO(press[iz], temp) * area[iy] * dz * 1e9);
11012
11013 /* Write output... */
11014 fprintf(out, "%.2f %g %g %g %g %g %g %g %g %g %d\n",
11015 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
11016 obsmean[idx2] / obscount[idx2], obscount[idx2]);
11017 }
11018 }
11019 }
11020
11021 /* Free... */
11022 free(mass);
11023 free(obsmean);
11024 free(obscount);
11025
11026 /* Finalize... */
11027 if (t == ctl->t_stop) {
11028
11029 /* Close output file... */
11030 fclose(out);
11031
11032 /* Free... */
11033 free(lon);
11034 free(lat);
11035 free(area);
11036 free(z);
11037 free(press);
11038 free(rt);
11039 free(rz);
11040 free(rlon);
11041 free(rlat);
11042 free(robs);
11043 }
11044}
Here is the call graph for this function:

◆ write_sample()

void write_sample ( const char *  filename,
const ctl_t ctl,
met_t met0,
met_t met1,
const atm_t atm,
const 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 11048 of file mptrac.c.

11054 {
11055
11056 static FILE *out;
11057
11058 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[EP],
11059 kw[EP];
11060
11061 static int nobs, nk;
11062
11063 /* Set timer... */
11064 SELECT_TIMER("WRITE_SAMPLE", "OUTPUT", NVTX_WRITE);
11065
11066 /* Init... */
11067 if (t == ctl->t_start) {
11068
11069 /* Allocate... */
11070 ALLOC(rt, double,
11071 NOBS);
11072 ALLOC(rz, double,
11073 NOBS);
11074 ALLOC(rlon, double,
11075 NOBS);
11076 ALLOC(rlat, double,
11077 NOBS);
11078 ALLOC(robs, double,
11079 NOBS);
11080
11081 /* Read observation data... */
11082 read_obs(ctl->sample_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
11083
11084 /* Read kernel data... */
11085 if (ctl->sample_kernel[0] != '-')
11086 read_kernel(ctl->sample_kernel, kz, kw, &nk);
11087
11088 /* Create output file... */
11089 LOG(1, "Write sample data: %s", filename);
11090 if (!(out = fopen(filename, "w")))
11091 ERRMSG("Cannot create file!");
11092
11093 /* Write header... */
11094 fprintf(out,
11095 "# $1 = time [s]\n"
11096 "# $2 = altitude [km]\n"
11097 "# $3 = longitude [deg]\n"
11098 "# $4 = latitude [deg]\n"
11099 "# $5 = surface area [km^2]\n"
11100 "# $6 = layer depth [km]\n"
11101 "# $7 = number of particles [1]\n"
11102 "# $8 = column density [kg/m^2]\n"
11103 "# $9 = volume mixing ratio [ppv]\n"
11104 "# $10 = observed BT index [K]\n\n");
11105
11106 /* Set latitude range, squared radius, and area... */
11107 dlat = DY2DEG(ctl->sample_dx);
11108 rmax2 = SQR(ctl->sample_dx);
11109 area = M_PI * rmax2;
11110 }
11111
11112 /* Set time interval for output... */
11113 const double t0 = t - 0.5 * ctl->dt_mod;
11114 const double t1 = t + 0.5 * ctl->dt_mod;
11115
11116 /* Loop over observations... */
11117 for (int i = 0; i < nobs; i++) {
11118
11119 /* Check time... */
11120 if (rt[i] < t0)
11121 continue;
11122 else if (rt[i] >= t1)
11123 break;
11124
11125 /* Calculate Cartesian coordinates... */
11126 double x0[3];
11127 geo2cart(0, rlon[i], rlat[i], x0);
11128
11129 /* Set pressure range... */
11130 const double rp = P(rz[i]);
11131 const double ptop = P(rz[i] + ctl->sample_dz);
11132 const double pbot = P(rz[i] - ctl->sample_dz);
11133
11134 /* Init... */
11135 double mass = 0;
11136 int np = 0;
11137
11138 /* Loop over air parcels... */
11139 //#pragma omp parallel for default(shared) reduction(+:mass,np)
11140 for (int ip = 0; ip < atm->np; ip++) {
11141
11142 /* Check time... */
11143 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11144 continue;
11145
11146 /* Check latitude... */
11147 if (fabs(rlat[i] - atm->lat[ip]) > dlat)
11148 continue;
11149
11150 /* Check horizontal distance... */
11151 double x1[3];
11152 geo2cart(0, atm->lon[ip], atm->lat[ip], x1);
11153 if (DIST2(x0, x1) > rmax2)
11154 continue;
11155
11156 /* Check pressure... */
11157 if (ctl->sample_dz > 0)
11158 if (atm->p[ip] > pbot || atm->p[ip] < ptop)
11159 continue;
11160
11161 /* Add mass... */
11162 if (ctl->qnt_m >= 0)
11163 mass +=
11164 kernel_weight(kz, kw, nk, atm->p[ip]) * atm->q[ctl->qnt_m][ip];
11165 np++;
11166 }
11167
11168 /* Calculate column density... */
11169 const double cd = mass / (1e6 * area);
11170
11171 /* Calculate volume mixing ratio... */
11172 double vmr = 0;
11173 if (ctl->molmass > 0 && ctl->sample_dz > 0) {
11174 if (mass > 0) {
11175
11176 /* Get temperature... */
11177 double temp;
11179 intpol_met_time_3d(met0, met0->t, met1, met1->t, rt[i], rp,
11180 rlon[i], rlat[i], &temp, ci, cw, 1);
11181
11182 /* Calculate volume mixing ratio... */
11183 vmr = MA / ctl->molmass * cd / (RHO(rp, temp) * ctl->sample_dz * 1e3);
11184 }
11185 } else
11186 vmr = NAN;
11187
11188 /* Write output... */
11189 fprintf(out, "%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
11190 rlon[i], rlat[i], area, ctl->sample_dz, np, cd, vmr, robs[i]);
11191 }
11192
11193 /* Finalize...... */
11194 if (t == ctl->t_stop) {
11195
11196 /* Close output file... */
11197 fclose(out);
11198
11199 /* Free... */
11200 free(rt);
11201 free(rz);
11202 free(rlon);
11203 free(rlat);
11204 free(robs);
11205 }
11206}
Here is the call graph for this function:

◆ write_station()

void write_station ( const char *  filename,
const ctl_t ctl,
atm_t atm,
const 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 11210 of file mptrac.c.

11214 {
11215
11216 static FILE *out;
11217
11218 static double rmax2, x0[3], x1[3];
11219
11220 /* Set timer... */
11221 SELECT_TIMER("WRITE_STATION", "OUTPUT", NVTX_WRITE);
11222
11223 /* Init... */
11224 if (t == ctl->t_start) {
11225
11226 /* Write info... */
11227 LOG(1, "Write station data: %s", filename);
11228
11229 /* Create new file... */
11230 if (!(out = fopen(filename, "w")))
11231 ERRMSG("Cannot create file!");
11232
11233 /* Write header... */
11234 fprintf(out,
11235 "# $1 = time [s]\n"
11236 "# $2 = altitude [km]\n"
11237 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11238 for (int iq = 0; iq < ctl->nq; iq++)
11239 fprintf(out, "# $%i = %s [%s]\n", (iq + 5),
11240 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
11241 fprintf(out, "\n");
11242
11243 /* Set geolocation and search radius... */
11244 geo2cart(0, ctl->stat_lon, ctl->stat_lat, x0);
11245 rmax2 = SQR(ctl->stat_r);
11246 }
11247
11248 /* Set time interval for output... */
11249 const double t0 = t - 0.5 * ctl->dt_mod;
11250 const double t1 = t + 0.5 * ctl->dt_mod;
11251
11252 /* Loop over air parcels... */
11253 for (int ip = 0; ip < atm->np; ip++) {
11254
11255 /* Check time... */
11256 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11257 continue;
11258
11259 /* Check time range for station output... */
11260 if (atm->time[ip] < ctl->stat_t0 || atm->time[ip] > ctl->stat_t1)
11261 continue;
11262
11263 /* Check station flag... */
11264 if (ctl->qnt_stat >= 0)
11265 if ((int) atm->q[ctl->qnt_stat][ip])
11266 continue;
11267
11268 /* Get Cartesian coordinates... */
11269 geo2cart(0, atm->lon[ip], atm->lat[ip], x1);
11270
11271 /* Check horizontal distance... */
11272 if (DIST2(x0, x1) > rmax2)
11273 continue;
11274
11275 /* Set station flag... */
11276 if (ctl->qnt_stat >= 0)
11277 atm->q[ctl->qnt_stat][ip] = 1;
11278
11279 /* Write data... */
11280 fprintf(out, "%.2f %g %g %g",
11281 atm->time[ip], Z(atm->p[ip]), atm->lon[ip], atm->lat[ip]);
11282 for (int iq = 0; iq < ctl->nq; iq++) {
11283 fprintf(out, " ");
11284 fprintf(out, ctl->qnt_format[iq], atm->q[iq][ip]);
11285 }
11286 fprintf(out, "\n");
11287 }
11288
11289 /* Close file... */
11290 if (t == ctl->t_stop)
11291 fclose(out);
11292}
Here is the call graph for this function:

◆ write_vtk()

void write_vtk ( const char *  filename,
const ctl_t ctl,
const atm_t atm,
const 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 11296 of file mptrac.c.

11300 {
11301
11302 FILE *out;
11303
11304 /* Set timer... */
11305 SELECT_TIMER("WRITE_VTK", "OUTPUT", NVTX_WRITE);
11306
11307 /* Write info... */
11308 LOG(1, "Write VTK data: %s", filename);
11309
11310 /* Set time interval for output... */
11311 const double t0 = t - 0.5 * ctl->dt_mod;
11312 const double t1 = t + 0.5 * ctl->dt_mod;
11313
11314 /* Create file... */
11315 if (!(out = fopen(filename, "w")))
11316 ERRMSG("Cannot create file!");
11317
11318 /* Count data points... */
11319 int np = 0;
11320 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
11321 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11322 continue;
11323 np++;
11324 }
11325
11326 /* Write header... */
11327 fprintf(out,
11328 "# vtk DataFile Version 3.0\n"
11329 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
11330
11331 /* Write point coordinates... */
11332 fprintf(out, "POINTS %d float\n", np);
11333 if (ctl->vtk_sphere) {
11334 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
11335 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11336 continue;
11337 const double radius = (RE + Z(atm->p[ip]) * ctl->vtk_scale
11338 + ctl->vtk_offset) / RE;
11339 const double coslat = cos(DEG2RAD(atm->lat[ip]));
11340 const double x = radius * coslat * cos(DEG2RAD(atm->lon[ip]));
11341 const double y = radius * coslat * sin(DEG2RAD(atm->lon[ip]));
11342 const double z = radius * sin(DEG2RAD(atm->lat[ip]));
11343 fprintf(out, "%g %g %g\n", x, y, z);
11344 }
11345 } else
11346 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
11347 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11348 continue;
11349 fprintf(out, "%g %g %g\n", atm->lon[ip], atm->lat[ip],
11350 Z(atm->p[ip]) * ctl->vtk_scale + ctl->vtk_offset);
11351 }
11352
11353 /* Write point data... */
11354 fprintf(out, "POINT_DATA %d\n", np);
11355 for (int iq = 0; iq < ctl->nq; iq++) {
11356 fprintf(out, "SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
11357 ctl->qnt_name[iq]);
11358 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
11359 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11360 continue;
11361 fprintf(out, "%g\n", atm->q[iq][ip]);
11362 }
11363 }
11364
11365 /* Close file... */
11366 fclose(out);
11367}