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 ECC(cmd)
 Execute a ECCODES command and check for errors. More...
 
#define ECC_READ_2D(variable, target, scaling_factor, found_flag)
 Writes 2-D data from a grib message into the met struct. More...
 
#define ECC_READ_3D(variable, level, target, scaling_factor, found_flag)
 Writes 3D data from a grib message into the met struct. 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, const int level, FILE *inout)
 Compresses or decompresses a float array using Zstandard (ZSTD). 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_check_lon_lat (const double *lons, const int nlon, const double *lats, const int nlat, const double lon, const double lat, double *lon2, double *lat2)
 Adjusts longitude and latitude to ensure they fall within valid bounds. 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)
 Advances particle positions using different advection schemes. 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_grid_ens (const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double tt)
 Processes atmospheric ensemble chemical data on a defined 3D grid. 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_mixing_help_ens (const ctl_t *ctl, const clim_t *clim, atm_t *atm, const int *ixs, const int *iys, const int *izs, const int qnt_idx)
 Applies ensemble-based interparcel mixing for a given tracer 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 atmospheric data from a CLAMS NetCDF file. 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...
 
int read_met_grib (const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met)
 Reads global meteorological information from a grib file. 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)
 Reads meteorological variables at different vertical levels from a grib file. More...
 
void read_met_monotonize (const ctl_t *ctl, 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)
 Reads surface meteorological data from a grib file and stores it 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_csi_ens (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes ensemble-based Critical Success Index (CSI) and other verification statistics to an output 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 172 of file mptrac.h.

◆ CPD

#define CPD   1003.5

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

Definition at line 177 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 182 of file mptrac.h.

◆ G0

#define G0   9.80665

Standard gravity [m/s^2].

Definition at line 187 of file mptrac.h.

◆ H0

#define H0   7.0

Scale height [km].

Definition at line 192 of file mptrac.h.

◆ LV

#define LV   2501000.

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

Definition at line 197 of file mptrac.h.

◆ KARMAN

#define KARMAN   0.40

Karman's constant.

Definition at line 202 of file mptrac.h.

◆ KB

#define KB   1.3806504e-23

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

Definition at line 207 of file mptrac.h.

◆ MA

#define MA   28.9644

Molar mass of dry air [g/mol].

Definition at line 212 of file mptrac.h.

◆ MH2O

#define MH2O   18.01528

Molar mass of water vapor [g/mol].

Definition at line 217 of file mptrac.h.

◆ MO3

#define MO3   48.00

Molar mass of ozone [g/mol].

Definition at line 222 of file mptrac.h.

◆ P0

#define P0   1013.25

Standard pressure [hPa].

Definition at line 227 of file mptrac.h.

◆ RA

#define RA   (1e3 * RI / MA)

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

Definition at line 232 of file mptrac.h.

◆ RE

#define RE   6367.421

Mean radius of Earth [km].

Definition at line 237 of file mptrac.h.

◆ RI

#define RI   8.3144598

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

Definition at line 242 of file mptrac.h.

◆ T0

#define T0   273.15

Standard temperature [K].

Definition at line 247 of file mptrac.h.

◆ LEN

#define LEN   5000

Maximum length of ASCII data lines.

Definition at line 256 of file mptrac.h.

◆ NP

#define NP   10000000

Maximum number of atmospheric data points.

Definition at line 261 of file mptrac.h.

◆ NQ

#define NQ   15

Maximum number of quantities per data point.

Definition at line 266 of file mptrac.h.

◆ NCSI

#define NCSI   1000000

Maximum number of data points for CSI calculation.

Definition at line 271 of file mptrac.h.

◆ EP

#define EP   140

Maximum number of pressure levels for meteo data.

Definition at line 276 of file mptrac.h.

◆ EX

#define EX   1202

Maximum number of longitudes for meteo data.

Definition at line 281 of file mptrac.h.

◆ EY

#define EY   602

Maximum number of latitudes for meteo data.

Definition at line 286 of file mptrac.h.

◆ NENS

#define NENS   2000

Maximum number of data points for ensemble analysis.

Definition at line 291 of file mptrac.h.

◆ NOBS

#define NOBS   10000000

Maximum number of observation data points.

Definition at line 296 of file mptrac.h.

◆ NTHREADS

#define NTHREADS   512

Maximum number of OpenMP threads.

Definition at line 301 of file mptrac.h.

◆ CY

#define CY   250

Maximum number of latitudes for climatological data.

Definition at line 306 of file mptrac.h.

◆ CO3

#define CO3   30

Maximum number of total column ozone data for climatological data.

Definition at line 311 of file mptrac.h.

◆ CP

#define CP   70

Maximum number of pressure levels for climatological data.

Definition at line 316 of file mptrac.h.

◆ CSZA

#define CSZA   50

Maximum number of solar zenith angles for climatological data.

Definition at line 321 of file mptrac.h.

◆ CT

#define CT   12

Maximum number of time steps for climatological data.

Definition at line 326 of file mptrac.h.

◆ CTS

#define CTS   1000

Maximum number of data points of climatological time series.

Definition at line 331 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 364 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 387 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 406 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 431 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 455 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 476 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 493 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 518 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:237
#define DEG2RAD(deg)
Converts degrees to radians.
Definition: mptrac.h:493

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 540 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 558 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 577 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 593 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 609 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 625 of file mptrac.h.

◆ ECC

#define ECC (   cmd)
Value:
{ \
int ecc_result=(cmd); \
if(ecc_result!=0) \
ERRMSG("ECCODES error: %s", codes_get_error_message(ecc_result)); \
}

Execute a ECCODES command and check for errors.

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

Parameters
cmdECCODES command to execute.
Author
Nils Nobre Wittwer

Definition at line 639 of file mptrac.h.

◆ ECC_READ_2D

#define ECC_READ_2D (   variable,
  target,
  scaling_factor,
  found_flag 
)
Value:
{ \
if( strcmp(short_name,variable)==0){ \
for (int ix = 0; ix < met->nx; ix++) { \
for (int iy = 0; iy < met->ny; iy++) { \
target[ix][iy] = (float)(values[iy * met->nx + ix]*scaling_factor); \
} \
} \
found_flag =1; \
} \
}

Writes 2-D data from a grib message into the met struct.

This Macro writes 2-D data from an one dimensional grib message into the corresponding 2-D variable in the met struct.

Parameters
variableName of the current meterological variable
targetPointer to the 2-D array in the met struct where the data will be stored.
scaling_factorScaling factor to apply to the data.
found_flagFlag to store, that the variable was found in the grib message.
Author
Nils Nobre Wittwer

Definition at line 658 of file mptrac.h.

◆ ECC_READ_3D

#define ECC_READ_3D (   variable,
  level,
  target,
  scaling_factor,
  found_flag 
)
Value:
{ \
if( strcmp(short_name,variable)==0){ \
for (int ix = 0; ix < met->nx; ix++) { \
for (int iy = 0; iy < met->ny; iy++) { \
target[ix][iy][level] = (float) (values[iy * met->nx + ix]*scaling_factor); \
} \
} \
found_flag +=1; \
} \
}

Writes 3D data from a grib message into the met struct.

This Macro writes 3D data from an one dimensional grib message into the corresponding 3D variable in the met struct.

Parameters
variableName of the current meterological variable.
targetPointer to the 3D array in the met struct where the data will be stored.
scaling_factorScaling factor to apply to the data.
found_flagCounter to store, how many messages countaining data for this variable have been read.
Author
Nils Nobre Wittwer

Definition at line 682 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 709 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 727 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 747 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 762 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:1616

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 776 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:1562

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 793 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 812 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 866 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:232
#define G0
Standard gravity [m/s^2].
Definition: mptrac.h:187

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 920 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 939 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 966 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 980 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 1067 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 1082 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 1096 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:256

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 1125 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:1951

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 1155 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 1183 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 1206 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 1230 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 1253 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 1275 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 1292 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 1312 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 1327 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 1354 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 1384 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 1408 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 1432 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 1459 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 1476 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 1506 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 1536 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 1561 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 1580 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 1603 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 1624 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 1637 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 1651 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:1459
#define T0
Standard temperature [K].
Definition: mptrac.h:247

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 1675 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 1700 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 1724 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 1753 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:1984

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 1774 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 1799 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 1821 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:1799
#define MA
Molar mass of dry air [g/mol].
Definition: mptrac.h:212
#define RI
Ideal gas constant [J/(mol K)].
Definition: mptrac.h:242

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 1852 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:1724

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

◆ LOGLEV

#define LOGLEV   2

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

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

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 1914 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 1951 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 1984 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 2019 of file mptrac.h.

◆ NTIMER

#define NTIMER   100

Maximum number of timers.

Definition at line 2028 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 2043 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 2064 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 2083 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 2098 of file mptrac.h.

◆ NVTX_PUSH

#define NVTX_PUSH (   range_title,
  range_color 
)    {}

Definition at line 2190 of file mptrac.h.

◆ NVTX_POP

#define NVTX_POP   {}

Definition at line 2191 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:1327
#define RAD2DEG(rad)
Converts radians to degrees.
Definition: mptrac.h:1476

◆ 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:10007
clim_zm_t oh
OH zonal means.
Definition: mptrac.h:3430
double oh_chem_beta
Beta parameter for diurnal variablity of OH.
Definition: mptrac.h:2940
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:3386
int np
Number of pressure levels.
Definition: mptrac.h:3383
double vmr[CT][CP][CY]
Volume mixing ratio [ppv].
Definition: mptrac.h:3395
int ntime
Number of timesteps.
Definition: mptrac.h:3377
int nlat
Number of latitudes.
Definition: mptrac.h:3380
double lat[CY]
Latitude [deg].
Definition: mptrac.h:3389
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:2091
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:2027
#define LIN(x0, y0, x1, y1, x)
Linear interpolation.
Definition: mptrac.h:939
#define MAX(a, b)
Macro to determine the maximum of two values.
Definition: mptrac.h:966
int nsza
Number of solar zenith angles.
Definition: mptrac.h:3304
double sza[CSZA]
Solar zenith angle [rad].
Definition: mptrac.h:3313
double p[CP]
Pressure [hPa].
Definition: mptrac.h:3310
double o3c[CO3]
Total column ozone [DU].
Definition: mptrac.h:3316
int np
Number of pressure levels.
Definition: mptrac.h:3301
int no3c
Number of total ozone columns.
Definition: mptrac.h:3307
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:709
int tropo_ntime
Number of tropopause timesteps.
Definition: mptrac.h:3409
double tropo_lat[73]
Tropopause latitudes [deg].
Definition: mptrac.h:3418
int tropo_nlat
Number of tropopause latitudes.
Definition: mptrac.h:3412
double tropo[12][73]
Tropopause pressure values [hPa].
Definition: mptrac.h:3421
double tropo_time[12]
Tropopause time steps [s].
Definition: mptrac.h:3415
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:1067
#define Z(p)
Convert pressure to altitude.
Definition: mptrac.h:1821
#define LOG(level,...)
Print a log message with a specified logging level.
Definition: mptrac.h:1914

◆ 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:3363
double time[CTS]
Time [s].
Definition: mptrac.h:3360
int ntime
Number of timesteps.
Definition: mptrac.h:3357
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:3392
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 706 of file mptrac.c.

712 {
713
714 double min[EP], max[EP], off[EP], scl[EP];
715
716 unsigned short *sarray;
717
718 /* Allocate... */
719 ALLOC(sarray, unsigned short,
720 nxy * nz);
721
722 /* Read compressed stream and decompress array... */
723 if (decompress) {
724
725 /* Write info... */
726 LOG(2, "Read 3-D variable: %s (pck, RATIO= %g)",
727 varname, (double) sizeof(float) / (double) sizeof(unsigned short));
728
729 /* Read data... */
730 FREAD(&scl, double,
731 nz,
732 inout);
733 FREAD(&off, double,
734 nz,
735 inout);
736 FREAD(sarray, unsigned short,
737 nxy * nz,
738 inout);
739
740 /* Convert to float... */
741#pragma omp parallel for default(shared)
742 for (size_t ixy = 0; ixy < nxy; ixy++)
743 for (size_t iz = 0; iz < nz; iz++)
744 array[ixy * nz + iz]
745 = (float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
746 }
747
748 /* Compress array and output compressed stream... */
749 else {
750
751 /* Write info... */
752 LOG(2, "Write 3-D variable: %s (pck, RATIO= %g)",
753 varname, (double) sizeof(float) / (double) sizeof(unsigned short));
754
755 /* Get range... */
756 for (size_t iz = 0; iz < nz; iz++) {
757 min[iz] = array[iz];
758 max[iz] = array[iz];
759 }
760 for (size_t ixy = 1; ixy < nxy; ixy++)
761 for (size_t iz = 0; iz < nz; iz++) {
762 if (array[ixy * nz + iz] < min[iz])
763 min[iz] = array[ixy * nz + iz];
764 if (array[ixy * nz + iz] > max[iz])
765 max[iz] = array[ixy * nz + iz];
766 }
767
768 /* Get offset and scaling factor... */
769 for (size_t iz = 0; iz < nz; iz++) {
770 scl[iz] = (max[iz] - min[iz]) / 65533.;
771 off[iz] = min[iz];
772 }
773
774 /* Convert to short... */
775#pragma omp parallel for default(shared)
776 for (size_t ixy = 0; ixy < nxy; ixy++)
777 for (size_t iz = 0; iz < nz; iz++)
778 if (scl[iz] != 0)
779 sarray[ixy * nz + iz] = (unsigned short)
780 ((array[ixy * nz + iz] - off[iz]) / scl[iz] + .5);
781 else
782 sarray[ixy * nz + iz] = 0;
783
784 /* Write data... */
785 FWRITE(&scl, double,
786 nz,
787 inout);
788 FWRITE(&off, double,
789 nz,
790 inout);
791 FWRITE(sarray, unsigned short,
792 nxy * nz,
793 inout);
794 }
795
796 /* Free... */
797 free(sarray);
798}
#define FWRITE(ptr, type, size, out)
Write data from memory to a file stream.
Definition: mptrac.h:747
#define FREAD(ptr, type, size, in)
Read data from a file stream and store it in memory.
Definition: mptrac.h:727
#define ALLOC(ptr, type, n)
Allocate memory for a pointer with error handling.
Definition: mptrac.h:364
#define EP
Maximum number of pressure levels for meteo data.
Definition: mptrac.h:276

◆ 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,
const int  level,
FILE *  inout 
)

Compresses or decompresses a float array using Zstandard (ZSTD).

This function either compresses a given float array and writes the result to a file, or reads compressed data from a file and decompresses it into the array.

Parameters
[in]varnameName of the variable, used for logging.
[in,out]arrayPointer to the float array to compress or to fill with decompressed data.
[in]nNumber of float elements in the array.
[in]decompressIf non-zero, perform decompression; otherwise, perform compression.
[in]levelCompression level (-5 to 22). Use 0 for the Zstd default.
[in,out]inoutFile pointer for input/output. Used for reading or writing compressed data.
Note
This function uses ZSTD's simple one-shot compression API (ZSTD_compress), which does not support multithreaded compression.
Warning
The function allocates temporary memory for the compressed buffer and frees it internally. Ensure array has sufficient space for uncompressed data.
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 942 of file mptrac.c.

946 {
947
948 const int
949 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
950 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
951
952 /* Get day of year... */
953 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
954 *doy = d0l[mon - 1] + day - 1;
955 else
956 *doy = d0[mon - 1] + day - 1;
957}

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

965 {
966
967 const int
968 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
969 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
970
971 int i;
972
973 /* Get month and day... */
974 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
975 for (i = 11; i > 0; i--)
976 if (d0l[i] <= doy)
977 break;
978 *mon = i + 1;
979 *day = doy - d0l[i] + 1;
980 } else {
981 for (i = 11; i > 0; i--)
982 if (d0[i] <= doy)
983 break;
984 *mon = i + 1;
985 *day = doy - d0[i] + 1;
986 }
987}

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

994 {
995
996 double data[2 * EX];
997
998 /* Check size... */
999 if (n > EX)
1000 ERRMSG("Too many data points!");
1001
1002 /* Allocate... */
1003 gsl_fft_complex_wavetable *wavetable =
1004 gsl_fft_complex_wavetable_alloc((size_t) n);
1005 gsl_fft_complex_workspace *workspace =
1006 gsl_fft_complex_workspace_alloc((size_t) n);
1007
1008 /* Set data (real, complex)... */
1009 for (int i = 0; i < n; i++) {
1010 data[2 * i] = fcReal[i];
1011 data[2 * i + 1] = fcImag[i];
1012 }
1013
1014 /* Calculate FFT... */
1015 gsl_fft_complex_forward(data, 1, (size_t) n, wavetable, workspace);
1016
1017 /* Copy data... */
1018 for (int i = 0; i < n; i++) {
1019 fcReal[i] = data[2 * i];
1020 fcImag[i] = data[2 * i + 1];
1021 }
1022
1023 /* Free... */
1024 gsl_fft_complex_wavetable_free(wavetable);
1025 gsl_fft_complex_workspace_free(workspace);
1026}
#define EX
Maximum number of longitudes for meteo data.
Definition: mptrac.h:281

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

1034 {
1035
1036 const double radius = z + RE;
1037 const double latrad = DEG2RAD(lat);
1038 const double lonrad = DEG2RAD(lon);
1039 const double coslat = cos(latrad);
1040
1041 x[0] = radius * coslat * cos(lonrad);
1042 x[1] = radius * coslat * sin(lonrad);
1043 x[2] = radius * sin(latrad);
1044}

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

1054 {
1055
1056 char repl[LEN];
1057
1058 double t6, r;
1059
1060 int year, mon, day, hour, min, sec;
1061
1062 /* Round time to fixed intervals... */
1063 if (direct == -1)
1064 t6 = floor(t / dt_met) * dt_met;
1065 else
1066 t6 = ceil(t / dt_met) * dt_met;
1067
1068 /* Decode time... */
1069 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
1070
1071 /* Set filename of MPTRAC meteo files... */
1072 if (ctl->met_clams == 0) {
1073 if (ctl->met_type == 0)
1074 sprintf(filename, "%s_YYYY_MM_DD_HH.nc", metbase);
1075 else if (ctl->met_type == 1)
1076 sprintf(filename, "%s_YYYY_MM_DD_HH.bin", metbase);
1077 else if (ctl->met_type == 2)
1078 sprintf(filename, "%s_YYYY_MM_DD_HH.pck", metbase);
1079 else if (ctl->met_type == 3)
1080 sprintf(filename, "%s_YYYY_MM_DD_HH.zfp", metbase);
1081 else if (ctl->met_type == 4)
1082 sprintf(filename, "%s_YYYY_MM_DD_HH.zstd", metbase);
1083 else if (ctl->met_type == 5)
1084 sprintf(filename, "%s_YYYY_MM_DD_HH.cms", metbase);
1085 sprintf(repl, "%d", year);
1086 get_met_replace(filename, "YYYY", repl);
1087 sprintf(repl, "%02d", mon);
1088 get_met_replace(filename, "MM", repl);
1089 sprintf(repl, "%02d", day);
1090 get_met_replace(filename, "DD", repl);
1091 sprintf(repl, "%02d", hour);
1092 get_met_replace(filename, "HH", repl);
1093 }
1094
1095 /* Set filename of CLaMS meteo files... */
1096 else {
1097 sprintf(filename, "%s_YYMMDDHH.nc", metbase);
1098 sprintf(repl, "%d", year);
1099 get_met_replace(filename, "YYYY", repl);
1100 sprintf(repl, "%02d", year % 100);
1101 get_met_replace(filename, "YY", repl);
1102 sprintf(repl, "%02d", mon);
1103 get_met_replace(filename, "MM", repl);
1104 sprintf(repl, "%02d", day);
1105 get_met_replace(filename, "DD", repl);
1106 sprintf(repl, "%02d", hour);
1107 get_met_replace(filename, "HH", repl);
1108 }
1109}
void get_met_replace(char *orig, char *search, char *repl)
Replaces occurrences of a substring in a string with another substring.
Definition: mptrac.c:1113
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:1740
int met_clams
Read MPTRAC or CLaMS meteo data (0=MPTRAC, 1=CLaMS).
Definition: mptrac.h:2566
int met_type
Type of meteo data files (0=netCDF, 1=binary, 2=pck, 3=zfp, 4=zstd, 5=cms).
Definition: mptrac.h:2563
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 1113 of file mptrac.c.

1116 {
1117
1118 char buffer[LEN];
1119
1120 /* Iterate... */
1121 for (int i = 0; i < 3; i++) {
1122
1123 /* Replace sub-string... */
1124 char *ch;
1125 if (!(ch = strstr(orig, search)))
1126 return;
1127 strncpy(buffer, orig, (size_t) (ch - orig));
1128 buffer[ch - orig] = 0;
1129 sprintf(buffer + (ch - orig), "%s%s", repl, ch + strlen(search));
1130 orig[0] = 0;
1131 strcpy(orig, buffer);
1132 }
1133}

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

1152 {
1153
1155
1156 ctl->met_tropo = met_tropo;
1157 read_met_tropo(ctl, clim, met);
1158#pragma omp parallel for default(shared) private(ci,cw)
1159 for (int ix = 0; ix < nx; ix++)
1160 for (int iy = 0; iy < ny; iy++) {
1161 intpol_met_space_2d(met, met->pt, lons[ix], lats[iy],
1162 &pt[iy * nx + ix], ci, cw, 1);
1163 intpol_met_space_2d(met, met->ps, lons[ix], lats[iy],
1164 &ps[iy * nx + ix], ci, cw, 0);
1165 intpol_met_space_2d(met, met->zs, lons[ix], lats[iy],
1166 &zs[iy * nx + ix], ci, cw, 0);
1167 intpol_met_space_3d(met, met->z, pt[iy * nx + ix], lons[ix],
1168 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
1169 intpol_met_space_3d(met, met->t, pt[iy * nx + ix], lons[ix],
1170 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
1171 intpol_met_space_3d(met, met->h2o, pt[iy * nx + ix], lons[ix],
1172 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
1173 intpol_met_space_3d(met, met->o3, pt[iy * nx + ix], lons[ix],
1174 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
1175 }
1176}
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:1504
void read_met_tropo(const ctl_t *ctl, const clim_t *clim, met_t *met)
Reads surface meteorological data from a grib file and stores it in the meteorological data structure...
Definition: mptrac.c:9561
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:1379
#define INTPOL_INIT
Initialize arrays for interpolation.
Definition: mptrac.h:762
int met_tropo
Tropopause definition (0=none, 1=clim, 2=cold point, 3=WMO_1st, 4=WMO_2nd, 5=dynamical).
Definition: mptrac.h:2700
float h2o[EX][EY][EP]
Water vapor volume mixing ratio [1].
Definition: mptrac.h:3585
float ps[EX][EY]
Surface pressure [hPa].
Definition: mptrac.h:3495
float zs[EX][EY]
Surface geopotential height [km].
Definition: mptrac.h:3501
float o3[EX][EY][EP]
Ozone volume mixing ratio [1].
Definition: mptrac.h:3588
float t[EX][EY][EP]
Temperature [K].
Definition: mptrac.h:3570
float pt[EX][EY]
Tropopause pressure [hPa].
Definition: mptrac.h:3528
float z[EX][EY][EP]
Geopotential height [km].
Definition: mptrac.h:3567
Here is the call graph for this function:

◆ intpol_check_lon_lat()

void intpol_check_lon_lat ( const double *  lons,
const int  nlon,
const double *  lats,
const int  nlat,
const double  lon,
const double  lat,
double *  lon2,
double *  lat2 
)

Adjusts longitude and latitude to ensure they fall within valid bounds.

This function checks and modifies the given longitude and latitude values to fit within the specified longitude and latitude arrays. The longitude is wrapped within a 360-degree range, and the latitude is clamped within the valid range defined by the latitude array.

Parameters
[in]lonsPointer to an array of valid longitude values.
[in]nlonNumber of elements in the longitude array.
[in]latsPointer to an array of valid latitude values.
[in]nlatNumber of elements in the latitude array.
[in]lonInput longitude to be checked and adjusted.
[in]latInput latitude to be checked and adjusted.
[out]lon2Pointer to the adjusted longitude.
[out]lat2Pointer to the adjusted latitude.
Author
Lars Hoffmann

Definition at line 1180 of file mptrac.c.

1188 {
1189
1190 /* Check longitude... */
1191 *lon2 = FMOD(lon, 360.);
1192 if (*lon2 < lons[0])
1193 *lon2 += 360;
1194 else if (*lon2 > lons[nlon - 1])
1195 *lon2 -= 360;
1196
1197 /* Check latitude... */
1198 *lat2 = lat;
1199 if (lats[0] < lats[nlat - 1])
1200 *lat2 = MIN(MAX(*lat2, lats[0]), lats[nlat - 1]);
1201 else
1202 *lat2 = MIN(MAX(*lat2, lats[nlat - 1]), lats[0]);
1203}

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

1221 {
1222
1223 if (init) {
1224
1225 /* Check longitude and latitude... */
1226 double lon2, lat2;
1227 intpol_check_lon_lat(met0->lon, met0->nx, met0->lat, met0->ny, lon, lat,
1228 &lon2, &lat2);
1229
1230 /* Get horizontal indizes... */
1231 ci[0] = locate_irr(met0->lon, met0->nx, lon2);
1232 ci[1] = locate_irr(met0->lat, met0->ny, lat2);
1233
1234 /* Locate the vertical indizes for each edge of the column... */
1235 int ind[2][4];
1236 locate_vert(heights0, met0->npl, ci[0], ci[1], height, ind[0]);
1237 locate_vert(heights1, met1->npl, ci[0], ci[1], height, ind[1]);
1238
1239 /* Find minimum and maximum indizes... */
1240 ci[2] = ind[0][0];
1241 int k_max = ind[0][0];
1242 for (int i = 0; i < 2; i++)
1243 for (int j = 0; j < 4; j++) {
1244 if (ci[2] > ind[i][j])
1245 ci[2] = ind[i][j];
1246 if (k_max < ind[i][j])
1247 k_max = ind[i][j];
1248 }
1249
1250 /* Get weighting factors for time, longitude and latitude... */
1251 cw[3] = (ts - met0->time) / (met1->time - met0->time);
1252 cw[0] = (lon2 - met0->lon[ci[0]]) /
1253 (met0->lon[ci[0] + 1] - met0->lon[ci[0]]);
1254 cw[1] = (lat2 - met0->lat[ci[1]]) /
1255 (met0->lat[ci[1] + 1] - met0->lat[ci[1]]);
1256
1257 /* Interpolate in time at the lowest level... */
1258 double height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
1259 - heights0[ci[0]][ci[1]][ci[2]])
1260 + heights0[ci[0]][ci[1]][ci[2]];
1261 double height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
1262 - heights0[ci[0]][ci[1] + 1][ci[2]])
1263 + heights0[ci[0]][ci[1] + 1][ci[2]];
1264 double height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
1265 - heights0[ci[0] + 1][ci[1]][ci[2]])
1266 + heights0[ci[0] + 1][ci[1]][ci[2]];
1267 double height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
1268 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
1269 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
1270
1271 /* Interpolate in latitude direction... */
1272 double height0 = cw[1] * (height01 - height00) + height00;
1273 double height1 = cw[1] * (height11 - height10) + height10;
1274
1275 /* Interpolate in longitude direction... */
1276 double height_bot = cw[0] * (height1 - height0) + height0;
1277
1278 /* Interpolate in time at the upper level... */
1279 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
1280 - heights0[ci[0]][ci[1]][ci[2] + 1])
1281 + heights0[ci[0]][ci[1]][ci[2] + 1];
1282 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
1283 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
1284 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
1285 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
1286 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
1287 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
1288 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1289 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1290 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1291
1292 /* Interpolate in latitude direction... */
1293 height0 = cw[1] * (height01 - height00) + height00;
1294 height1 = cw[1] * (height11 - height10) + height10;
1295
1296 /* Interpolate in longitude direction... */
1297 double height_top = cw[0] * (height1 - height0) + height0;
1298
1299 /* Search at higher levels if height is not in box... */
1300 while (((heights0[0][0][0] > heights0[0][0][1]) &&
1301 ((height_bot <= height) || (height_top > height))
1302 && (height_bot >= height) && (ci[2] < k_max))
1303 ||
1304 ((heights0[0][0][0] < heights0[0][0][1]) &&
1305 ((height_bot >= height) || (height_top < height))
1306 && (height_bot <= height) && (ci[2] < k_max))
1307 ) {
1308
1309 ci[2]++;
1310 height_bot = height_top;
1311
1312 /* Interpolate in time at the next level... */
1313 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
1314 - heights0[ci[0]][ci[1]][ci[2] + 1])
1315 + heights0[ci[0]][ci[1]][ci[2] + 1];
1316 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
1317 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
1318 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
1319 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
1320 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
1321 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
1322 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1323 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1324 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1325
1326 /* Interpolate in latitude direction... */
1327 height0 = cw[1] * (height01 - height00) + height00;
1328 height1 = cw[1] * (height11 - height10) + height10;
1329
1330 /* Interpolate in longitude direction... */
1331 height_top = cw[0] * (height1 - height0) + height0;
1332 }
1333
1334 /* Get vertical weighting factors... */
1335 cw[2] = (height - height_bot)
1336 / (height_top - height_bot);
1337 }
1338
1339 /* Calculate the needed array values... */
1340 double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
1341 - array0[ci[0]][ci[1]][ci[2]])
1342 + array0[ci[0]][ci[1]][ci[2]];
1343 double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
1344 - array0[ci[0] + 1][ci[1]][ci[2]])
1345 + array0[ci[0] + 1][ci[1]][ci[2]];
1346 double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
1347 - array0[ci[0]][ci[1] + 1][ci[2]])
1348 + array0[ci[0]][ci[1] + 1][ci[2]];
1349 double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
1350 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
1351 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
1352 double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
1353 - array0[ci[0]][ci[1]][ci[2] + 1])
1354 + array0[ci[0]][ci[1]][ci[2] + 1];
1355 double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
1356 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
1357 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
1358 double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
1359 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
1360 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
1361 double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1362 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1363 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1364
1365 double array00 = cw[0] * (array100 - array000) + array000;
1366 double array10 = cw[0] * (array110 - array010) + array010;
1367 double array01 = cw[0] * (array101 - array001) + array001;
1368 double array11 = cw[0] * (array111 - array011) + array011;
1369
1370 double aux0 = cw[1] * (array10 - array00) + array00;
1371 double aux1 = cw[1] * (array11 - array01) + array01;
1372
1373 /* Interpolate vertically... */
1374 *var = cw[2] * (aux1 - aux0) + aux0;
1375}
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:2110
void intpol_check_lon_lat(const double *lons, const int nlon, const double *lats, const int nlat, const double lon, const double lat, double *lon2, double *lat2)
Adjusts longitude and latitude to ensure they fall within valid bounds.
Definition: mptrac.c:1180
int nx
Number of longitudes.
Definition: mptrac.h:3471
int ny
Number of latitudes.
Definition: mptrac.h:3474
double lon[EX]
Longitude [deg].
Definition: mptrac.h:3483
int npl
Number of model levels.
Definition: mptrac.h:3480
double time
Time [s].
Definition: mptrac.h:3468
double lat[EY]
Latitude [deg].
Definition: mptrac.h:3486
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 1379 of file mptrac.c.

1388 {
1389
1390 /* Initialize interpolation... */
1391 if (init) {
1392
1393 /* Check longitude and latitude... */
1394 double lon2, lat2;
1395 intpol_check_lon_lat(met->lon, met->nx, met->lat, met->ny, lon, lat,
1396 &lon2, &lat2);
1397
1398 /* Get interpolation indices... */
1399 ci[0] = locate_irr(met->p, met->np, p);
1400 ci[1] = locate_reg(met->lon, met->nx, lon2);
1401 ci[2] = locate_irr(met->lat, met->ny, lat2);
1402
1403 /* Get interpolation weights... */
1404 cw[0] = (met->p[ci[0] + 1] - p)
1405 / (met->p[ci[0] + 1] - met->p[ci[0]]);
1406 cw[1] = (met->lon[ci[1] + 1] - lon2)
1407 / (met->lon[ci[1] + 1] - met->lon[ci[1]]);
1408 cw[2] = (met->lat[ci[2] + 1] - lat2)
1409 / (met->lat[ci[2] + 1] - met->lat[ci[2]]);
1410 }
1411
1412 /* Interpolate vertically... */
1413 double aux00 =
1414 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
1415 + array[ci[1]][ci[2]][ci[0] + 1];
1416 double aux01 =
1417 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
1418 array[ci[1]][ci[2] + 1][ci[0] + 1])
1419 + array[ci[1]][ci[2] + 1][ci[0] + 1];
1420 double aux10 =
1421 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
1422 array[ci[1] + 1][ci[2]][ci[0] + 1])
1423 + array[ci[1] + 1][ci[2]][ci[0] + 1];
1424 double aux11 =
1425 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
1426 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
1427 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
1428
1429 /* Interpolate horizontally... */
1430 aux00 = cw[2] * (aux00 - aux01) + aux01;
1431 aux11 = cw[2] * (aux10 - aux11) + aux11;
1432 *var = cw[1] * (aux00 - aux11) + aux11;
1433}
int np
Number of pressure levels.
Definition: mptrac.h:3477
double p[EP]
Pressure levels [hPa].
Definition: mptrac.h:3489
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 1437 of file mptrac.c.

1444 {
1445
1446 /* Check longitude and latitude... */
1447 double lon2, lat2;
1448 intpol_check_lon_lat(met->lon, met->nx, met->lat, met->ny, lon, lat, &lon2,
1449 &lat2);
1450
1451 /* Get horizontal indices... */
1452 const int ix = locate_reg(met->lon, met->nx, lon2);
1453 const int iy = locate_irr(met->lat, met->ny, lat2);
1454
1455 /* Interpolate vertically... */
1456 int iz = locate_irr_float(zs[ix][iy], met->npl, z, 0);
1457 double aux00;
1458 if (z >= zs[ix][iy][iz + 1])
1459 aux00 = array[ix][iy][iz + 1];
1460 else if (z <= zs[ix][iy][iz])
1461 aux00 = array[ix][iy][iz];
1462 else
1463 aux00 = LIN(zs[ix][iy][iz], array[ix][iy][iz],
1464 zs[ix][iy][iz + 1], array[ix][iy][iz + 1], z);
1465
1466 iz = locate_irr_float(zs[ix][iy + 1], met->npl, z, iz);
1467 double aux01;
1468 if (z >= zs[ix][iy + 1][iz + 1])
1469 aux01 = array[ix][iy + 1][iz + 1];
1470 else if (z <= zs[ix][iy + 1][iz])
1471 aux01 = array[ix][iy + 1][iz];
1472 else
1473 aux01 = LIN(zs[ix][iy + 1][iz], array[ix][iy + 1][iz],
1474 zs[ix][iy + 1][iz + 1], array[ix][iy + 1][iz + 1], z);
1475
1476 iz = locate_irr_float(zs[ix + 1][iy], met->npl, z, iz);
1477 double aux10;
1478 if (z >= zs[ix + 1][iy][iz + 1])
1479 aux10 = array[ix + 1][iy][iz + 1];
1480 else if (z <= zs[ix + 1][iy][iz])
1481 aux10 = array[ix + 1][iy][iz];
1482 else
1483 aux10 = LIN(zs[ix + 1][iy][iz], array[ix + 1][iy][iz],
1484 zs[ix + 1][iy][iz + 1], array[ix + 1][iy][iz + 1], z);
1485
1486 iz = locate_irr_float(zs[ix + 1][iy + 1], met->npl, z, iz);
1487 double aux11;
1488 if (z >= zs[ix + 1][iy + 1][iz + 1])
1489 aux11 = array[ix + 1][iy + 1][iz + 1];
1490 else if (z <= zs[ix + 1][iy + 1][iz])
1491 aux11 = array[ix + 1][iy + 1][iz];
1492 else
1493 aux11 = LIN(zs[ix + 1][iy + 1][iz], array[ix + 1][iy + 1][iz],
1494 zs[ix + 1][iy + 1][iz + 1], array[ix + 1][iy + 1][iz + 1], z);
1495
1496 /* Interpolate horizontally... */
1497 double aux0 = LIN(met->lat[iy], aux00, met->lat[iy + 1], aux01, lat2);
1498 double aux1 = LIN(met->lat[iy], aux10, met->lat[iy + 1], aux11, lat2);
1499 *var = LIN(met->lon[ix], aux0, met->lon[ix + 1], aux1, lon2);
1500}
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:2057
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 1504 of file mptrac.c.

1512 {
1513
1514 /* Initialize interpolation... */
1515 if (init) {
1516
1517 /* Check longitude and latitude... */
1518 double lon2, lat2;
1519 intpol_check_lon_lat(met->lon, met->nx, met->lat, met->ny, lon, lat,
1520 &lon2, &lat2);
1521
1522 /* Get interpolation indices... */
1523 ci[1] = locate_reg(met->lon, met->nx, lon2);
1524 ci[2] = locate_irr(met->lat, met->ny, lat2);
1525
1526 /* Get interpolation weights... */
1527 cw[1] = (met->lon[ci[1] + 1] - lon2)
1528 / (met->lon[ci[1] + 1] - met->lon[ci[1]]);
1529 cw[2] = (met->lat[ci[2] + 1] - lat2)
1530 / (met->lat[ci[2] + 1] - met->lat[ci[2]]);
1531 }
1532
1533 /* Set variables... */
1534 double aux00 = array[ci[1]][ci[2]];
1535 double aux01 = array[ci[1]][ci[2] + 1];
1536 double aux10 = array[ci[1] + 1][ci[2]];
1537 double aux11 = array[ci[1] + 1][ci[2] + 1];
1538
1539 /* Interpolate horizontally... */
1540 if (isfinite(aux00) && isfinite(aux01)
1541 && isfinite(aux10) && isfinite(aux11)) {
1542 aux00 = cw[2] * (aux00 - aux01) + aux01;
1543 aux11 = cw[2] * (aux10 - aux11) + aux11;
1544 *var = cw[1] * (aux00 - aux11) + aux11;
1545 } else {
1546 if (cw[2] < 0.5) {
1547 if (cw[1] < 0.5)
1548 *var = aux11;
1549 else
1550 *var = aux01;
1551 } else {
1552 if (cw[1] < 0.5)
1553 *var = aux10;
1554 else
1555 *var = aux00;
1556 }
1557 }
1558}
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 1562 of file mptrac.c.

1574 {
1575
1576 double var0, var1;
1577
1578 /* Spatial interpolation... */
1579 intpol_met_space_3d(met0, array0, p, lon, lat, &var0, ci, cw, init);
1580 intpol_met_space_3d(met1, array1, p, lon, lat, &var1, ci, cw, 0);
1581
1582 /* Get weighting factor... */
1583 const double wt = (met1->time - ts) / (met1->time - met0->time);
1584
1585 /* Interpolate... */
1586 *var = wt * (var0 - var1) + var1;
1587}
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 1591 of file mptrac.c.

1602 {
1603
1604 double var0, var1;
1605
1606 /* Spatial interpolation... */
1607 intpol_met_space_3d_ml(met0, zs0, array0, p, lon, lat, &var0);
1608 intpol_met_space_3d_ml(met1, zs1, array1, p, lon, lat, &var1);
1609
1610 /* Interpolate... */
1611 *var = LIN(met0->time, var0, met1->time, var1, ts);
1612}
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:1437
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 1616 of file mptrac.c.

1627 {
1628
1629 double var0, var1;
1630
1631 /* Spatial interpolation... */
1632 intpol_met_space_2d(met0, array0, lon, lat, &var0, ci, cw, init);
1633 intpol_met_space_2d(met1, array1, lon, lat, &var1, ci, cw, 0);
1634
1635 /* Get weighting factor... */
1636 const double wt = (met1->time - ts) / (met1->time - met0->time);
1637
1638 /* Interpolate... */
1639 if (isfinite(var0) && isfinite(var1))
1640 *var = wt * (var0 - var1) + var1;
1641 else if (wt < 0.5)
1642 *var = var1;
1643 else
1644 *var = var0;
1645}
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 1649 of file mptrac.c.

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

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

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

1777 {
1778
1779 /* Check number of data points... */
1780 if (nk < 2)
1781 return 1.0;
1782
1783 /* Get altitude... */
1784 const double z = Z(p);
1785
1786 /* Get weighting factor... */
1787 if (z < kz[0])
1788 return kw[0];
1789 else if (z > kz[nk - 1])
1790 return kw[nk - 1];
1791 else {
1792 int idx = locate_irr(kz, nk, z);
1793 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
1794 }
1795}
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 1799 of file mptrac.c.

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

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

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

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

2030 {
2031
2032 int ilo = 0;
2033 int ihi = n - 1;
2034 int i = (ihi + ilo) >> 1;
2035
2036 if (xx[i] < xx[i + 1])
2037 while (ihi > ilo + 1) {
2038 i = (ihi + ilo) >> 1;
2039 if (xx[i] > x)
2040 ihi = i;
2041 else
2042 ilo = i;
2043 } else
2044 while (ihi > ilo + 1) {
2045 i = (ihi + ilo) >> 1;
2046 if (xx[i] <= x)
2047 ihi = i;
2048 else
2049 ilo = i;
2050 }
2051
2052 return ilo;
2053}

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

2061 {
2062
2063 int ilo = 0;
2064 int ihi = n - 1;
2065 int i = (ihi + ilo) >> 1;
2066
2067 if (x >= xx[ig] && x < xx[ig + 1])
2068 return ig;
2069
2070 if (xx[i] < xx[i + 1])
2071 while (ihi > ilo + 1) {
2072 i = (ihi + ilo) >> 1;
2073 if (xx[i] > x)
2074 ihi = i;
2075 else
2076 ilo = i;
2077 } else
2078 while (ihi > ilo + 1) {
2079 i = (ihi + ilo) >> 1;
2080 if (xx[i] <= x)
2081 ihi = i;
2082 else
2083 ilo = i;
2084 }
2085
2086 return ilo;
2087}

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

2094 {
2095
2096 /* Calculate index... */
2097 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2098
2099 /* Check range... */
2100 if (i < 0)
2101 return 0;
2102 else if (i > n - 2)
2103 return n - 2;
2104 else
2105 return i;
2106}

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

2116 {
2117
2118 ind[0] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind],
2119 np, height_ap, 0);
2120 ind[1] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind],
2121 np, height_ap, ind[0]);
2122 ind[2] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind + 1],
2123 np, height_ap, ind[1]);
2124 ind[3] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind + 1],
2125 np, height_ap, ind[2]);
2126}
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 
)

Advances particle positions using different advection schemes.

This function updates the positions of atmospheric particles using different advection schemes based on vertical velocity formulations (omega or zetadot). The advection is performed over a number of integration nodes, using meteorological data interpolated in time and space.

Parameters
[in]ctlPointer to the control structure containing configuration settings.
[in]cachePointer to the cache structure storing precomputed time step values.
[in]met0Pointer to the meteorological data structure at the initial time.
[in]met1Pointer to the meteorological data structure at the next time step.
[in,out]atmPointer to the atmospheric data structure containing particle states.
  • If ctl->advect_vert_coord is 0 or 2, the function uses omega vertical velocity.
  • If ctl->advect_vert_coord is 1, the function uses zetadot vertical velocity.
  • The function interpolates meteorological data either on pressure levels or model levels.
  • The advection scheme supports different integration methods (e.g., two-stage, four-stage).
  • The function updates longitude, latitude, and pressure (or zeta) for each particle.
  • Special handling is applied to ensure zeta values remain non-negative.
Authors
Lars Hoffmann
Jan Clemens

Definition at line 2130 of file mptrac.c.

2135 {
2136
2137 /* Set timer... */
2138 SELECT_TIMER("MODULE_ADVECT", "PHYSICS", NVTX_GPU);
2139
2140 /* Use omega vertical velocity... */
2141 if (ctl->advect_vert_coord == 0 || ctl->advect_vert_coord == 2) {
2142
2143 /* Loop over particles... */
2144 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2145
2146 /* Init... */
2148 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
2149 x[3] = { 0, 0, 0 };
2150
2151 /* Loop over integration nodes... */
2152 for (int i = 0; i < ctl->advect; i++) {
2153
2154 /* Set position... */
2155 if (i == 0) {
2156 dts = 0.0;
2157 x[0] = atm->lon[ip];
2158 x[1] = atm->lat[ip];
2159 x[2] = atm->p[ip];
2160 } else {
2161 dts = (i == 3 ? 1.0 : 0.5) * cache->dt[ip];
2162 x[0] = atm->lon[ip] + DX2DEG(dts * u[i - 1] / 1000., atm->lat[ip]);
2163 x[1] = atm->lat[ip] + DY2DEG(dts * v[i - 1] / 1000.);
2164 x[2] = atm->p[ip] + dts * w[i - 1];
2165 }
2166 const double tm = atm->time[ip] + dts;
2167
2168 /* Interpolate meteo data on pressure levels... */
2169 if (ctl->advect_vert_coord == 0) {
2170 intpol_met_time_3d(met0, met0->u, met1, met1->u,
2171 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2172 intpol_met_time_3d(met0, met0->v, met1, met1->v,
2173 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2174 intpol_met_time_3d(met0, met0->w, met1, met1->w,
2175 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
2176 }
2177
2178 /* Interpolate meteo data on model levels... */
2179 else {
2180 intpol_met_time_3d_ml(met0, met0->pl, met0->ul,
2181 met1, met1->pl, met1->ul,
2182 tm, x[2], x[0], x[1], &u[i]);
2183 intpol_met_time_3d_ml(met0, met0->pl, met0->vl,
2184 met1, met1->pl, met1->vl,
2185 tm, x[2], x[0], x[1], &v[i]);
2186 intpol_met_time_3d_ml(met0, met0->pl, met0->wl,
2187 met1, met1->pl, met1->wl,
2188 tm, x[2], x[0], x[1], &w[i]);
2189 }
2190
2191 /* Get mean wind... */
2192 double k = 1.0;
2193 if (ctl->advect == 2)
2194 k = (i == 0 ? 0.0 : 1.0);
2195 else if (ctl->advect == 4)
2196 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2197 um += k * u[i];
2198 vm += k * v[i];
2199 wm += k * w[i];
2200 }
2201
2202 /* Set new position... */
2203 atm->time[ip] += cache->dt[ip];
2204 atm->lon[ip] += DX2DEG(cache->dt[ip] * um / 1000.,
2205 (ctl->advect == 2 ? x[1] : atm->lat[ip]));
2206 atm->lat[ip] += DY2DEG(cache->dt[ip] * vm / 1000.);
2207 atm->p[ip] += cache->dt[ip] * wm;
2208 }
2209 }
2210
2211 /* Use zetadot vertical velocity... */
2212 else if (ctl->advect_vert_coord == 1) {
2213
2214 /* Loop over particles... */
2215 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2216
2217 /* Convert pressure to zeta... */
2219 intpol_met_4d_coord(met0, met0->pl, met0->zetal, met1,
2220 met1->pl, met1->zetal, atm->time[ip], atm->p[ip],
2221 atm->lon[ip], atm->lat[ip],
2222 &atm->q[ctl->qnt_zeta][ip], ci, cw, 1);
2223
2224 /* Init... */
2225 double dts, u[4], um = 0, v[4], vm = 0, zeta_dot[4],
2226 zeta_dotm = 0, x[3] = { 0, 0, 0 };
2227
2228 /* Loop over integration nodes... */
2229 for (int i = 0; i < ctl->advect; i++) {
2230
2231 /* Set position... */
2232 if (i == 0) {
2233 dts = 0.0;
2234 x[0] = atm->lon[ip];
2235 x[1] = atm->lat[ip];
2236 x[2] = atm->q[ctl->qnt_zeta][ip];
2237 } else {
2238 dts = (i == 3 ? 1.0 : 0.5) * cache->dt[ip];
2239 x[0] = atm->lon[ip] + DX2DEG(dts * u[i - 1] / 1000., atm->lat[ip]);
2240 x[1] = atm->lat[ip] + DY2DEG(dts * v[i - 1] / 1000.);
2241 x[2] = atm->q[ctl->qnt_zeta][ip] + dts * zeta_dot[i - 1];
2242 }
2243 const double tm = atm->time[ip] + dts;
2244
2245 /* Interpolate meteo data... */
2246 intpol_met_4d_coord(met0, met0->zetal, met0->ul, met1, met1->zetal,
2247 met1->ul, tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2248 intpol_met_4d_coord(met0, met0->zetal, met0->vl, met1, met1->zetal,
2249 met1->vl, tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2250 intpol_met_4d_coord(met0, met0->zetal, met0->zeta_dotl, met1,
2251 met1->zetal, met1->zeta_dotl, tm, x[2], x[0],
2252 x[1], &zeta_dot[i], ci, cw, 0);
2253
2254 /* Get mean wind... */
2255 double k = 1.0;
2256 if (ctl->advect == 2)
2257 k = (i == 0 ? 0.0 : 1.0);
2258 else if (ctl->advect == 4)
2259 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2260 um += k * u[i];
2261 vm += k * v[i];
2262 zeta_dotm += k * zeta_dot[i];
2263 }
2264
2265 /* Set new position... */
2266 atm->time[ip] += cache->dt[ip];
2267 atm->lon[ip] += DX2DEG(cache->dt[ip] * um / 1000.,
2268 (ctl->advect == 2 ? x[1] : atm->lat[ip]));
2269 atm->lat[ip] += DY2DEG(cache->dt[ip] * vm / 1000.);
2270 atm->q[ctl->qnt_zeta][ip] += cache->dt[ip] * zeta_dotm;
2271
2272 /* Convert zeta to pressure... */
2273 intpol_met_4d_coord(met0, met0->zetal, met0->pl, met1, met1->zetal,
2274 met1->pl, atm->time[ip],
2275 atm->q[ctl->qnt_zeta][ip], atm->lon[ip],
2276 atm->lat[ip], &atm->p[ip], ci, cw, 1);
2277 }
2278 }
2279}
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:1207
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:1562
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:1591
#define PARTICLE_LOOP(ip0, ip1, check_dt,...)
Loop over particle indices with OpenACC acceleration.
Definition: mptrac.h:1354
#define DX2DEG(dx, lat)
Convert a distance in kilometers to degrees longitude at a given latitude.
Definition: mptrac.h:540
#define SELECT_TIMER(id, group, color)
Select and start a timer with specific attributes.
Definition: mptrac.h:2064
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
Definition: mptrac.h:558
double time[NP]
Time [s].
Definition: mptrac.h:3244
double lat[NP]
Latitude [deg].
Definition: mptrac.h:3253
double lon[NP]
Longitude [deg].
Definition: mptrac.h:3250
int np
Number of air parcels.
Definition: mptrac.h:3241
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
Definition: mptrac.h:3256
double p[NP]
Pressure [hPa].
Definition: mptrac.h:3247
double dt[NP]
Timesteps [s].
Definition: mptrac.h:3287
int advect
Advection scheme (0=off, 1=Euler, 2=midpoint, 4=Runge-Kutta).
Definition: mptrac.h:2735
int qnt_zeta
Quantity array index for zeta vertical coordinate.
Definition: mptrac.h:2452
int advect_vert_coord
Vertical velocity of air parcels (0=omega_on_plev, 1=zetadot_on_mlev, 2=omega_on_mlev).
Definition: mptrac.h:2739
float zeta_dotl[EX][EY][EP]
Vertical velocity on model levels [K/s].
Definition: mptrac.h:3621
float w[EX][EY][EP]
Vertical velocity [hPa/s].
Definition: mptrac.h:3579
float wl[EX][EY][EP]
Vertical velocity on model levels [hPa/s].
Definition: mptrac.h:3615
float vl[EX][EY][EP]
Meridional wind on model levels [m/s].
Definition: mptrac.h:3612
float u[EX][EY][EP]
Zonal wind [m/s].
Definition: mptrac.h:3573
float ul[EX][EY][EP]
Zonal wind on model levels [m/s].
Definition: mptrac.h:3609
float v[EX][EY][EP]
Meridional wind [m/s].
Definition: mptrac.h:3576
float pl[EX][EY][EP]
Pressure on model levels [hPa].
Definition: mptrac.h:3606
float zetal[EX][EY][EP]
Zeta on model levels [K].
Definition: mptrac.h:3618
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 2283 of file mptrac.c.

2288 {
2289
2290 /* Check parameters... */
2291 if (ctl->advect_vert_coord != 1)
2292 return;
2293
2294 /* Set timer... */
2295 SELECT_TIMER("MODULE_ADVECT_INIT", "PHYSICS", NVTX_GPU);
2296
2297 /* Loop over particles... */
2298 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,met0,met1,atm)") {
2299
2300 /* Initialize pressure consistent with zeta... */
2302 intpol_met_4d_coord(met0, met0->zetal, met0->pl, met1, met1->zetal,
2303 met1->pl, atm->time[ip], atm->q[ctl->qnt_zeta][ip],
2304 atm->lon[ip], atm->lat[ip], &atm->p[ip], ci, cw, 1);
2305 }
2306}
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 2310 of file mptrac.c.

2316 {
2317
2318 /* Set timer... */
2319 SELECT_TIMER("MODULE_BOUND_COND", "PHYSICS", NVTX_GPU);
2320
2321 /* Check quantity flags... */
2322 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0 && ctl->qnt_Cccl4
2323 && ctl->qnt_Cccl3f < 0 && ctl->qnt_Cccl2f2 < 0
2324 && ctl->qnt_Cn2o < 0 && ctl->qnt_Csf6 < 0 && ctl->qnt_aoa < 0)
2325 return;
2326
2327 /* Loop over particles... */
2328 PARTICLE_LOOP(0, atm->np, 1,
2329 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2330
2331 /* Check latitude and pressure range... */
2332 if (atm->lat[ip] < ctl->bound_lat0 || atm->lat[ip] > ctl->bound_lat1
2333 || atm->p[ip] > ctl->bound_p0 || atm->p[ip] < ctl->bound_p1)
2334 continue;
2335
2336 /* Check surface layer... */
2337 if (ctl->bound_dps > 0 || ctl->bound_dzs > 0
2338 || ctl->bound_zetas > 0 || ctl->bound_pbl) {
2339
2340 /* Get surface pressure... */
2341 double ps;
2343 INTPOL_2D(ps, 1);
2344
2345 /* Check pressure... */
2346 if (ctl->bound_dps > 0 && atm->p[ip] < ps - ctl->bound_dps)
2347 continue;
2348
2349 /* Check height... */
2350 if (ctl->bound_dzs > 0 && Z(atm->p[ip]) > Z(ps) + ctl->bound_dzs)
2351 continue;
2352
2353 /* Check zeta range... */
2354 if (ctl->bound_zetas > 0) {
2355 double t;
2356 INTPOL_3D(t, 1);
2357 if (ZETA(ps, atm->p[ip], t) > ctl->bound_zetas)
2358 continue;
2359 }
2360
2361 /* Check planetary boundary layer... */
2362 if (ctl->bound_pbl) {
2363 double pbl;
2364 INTPOL_2D(pbl, 0);
2365 if (atm->p[ip] < pbl)
2366 continue;
2367 }
2368 }
2369
2370 /* Set mass and volume mixing ratio... */
2371 if (ctl->qnt_m >= 0 && ctl->bound_mass >= 0)
2372 atm->q[ctl->qnt_m][ip] =
2373 ctl->bound_mass + ctl->bound_mass_trend * atm->time[ip];
2374 if (ctl->qnt_vmr >= 0 && ctl->bound_vmr >= 0)
2375 atm->q[ctl->qnt_vmr][ip] =
2376 ctl->bound_vmr + ctl->bound_vmr_trend * atm->time[ip];
2377
2378 /* Set CFC-10 volume mixing ratio... */
2379 if (ctl->qnt_Cccl4 >= 0 && ctl->clim_ccl4_timeseries[0] != '-')
2380 atm->q[ctl->qnt_Cccl4][ip] = clim_ts(&clim->ccl4, atm->time[ip]);
2381
2382 /* Set CFC-11 volume mixing ratio... */
2383 if (ctl->qnt_Cccl3f >= 0 && ctl->clim_ccl3f_timeseries[0] != '-')
2384 atm->q[ctl->qnt_Cccl3f][ip] = clim_ts(&clim->ccl3f, atm->time[ip]);
2385
2386 /* Set CFC-12 volume mixing ratio... */
2387 if (ctl->qnt_Cccl2f2 >= 0 && ctl->clim_ccl2f2_timeseries[0] != '-')
2388 atm->q[ctl->qnt_Cccl2f2][ip] = clim_ts(&clim->ccl2f2, atm->time[ip]);
2389
2390 /* Set N2O volume mixing ratio... */
2391 if (ctl->qnt_Cn2o >= 0 && ctl->clim_n2o_timeseries[0] != '-')
2392 atm->q[ctl->qnt_Cn2o][ip] = clim_ts(&clim->n2o, atm->time[ip]);
2393
2394 /* Set SF6 volume mixing ratio... */
2395 if (ctl->qnt_Csf6 >= 0 && ctl->clim_sf6_timeseries[0] != '-')
2396 atm->q[ctl->qnt_Csf6][ip] = clim_ts(&clim->sf6, atm->time[ip]);
2397
2398 /* Set age of air... */
2399 if (ctl->qnt_aoa >= 0)
2400 atm->q[ctl->qnt_aoa][ip] = atm->time[ip];
2401 }
2402}
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:793
#define ZETA(ps, p, t)
Computes the value of the zeta vertical coordinate.
Definition: mptrac.h:1871
#define INTPOL_2D(var, init)
Perform 2D interpolation for a meteorological variable.
Definition: mptrac.h:776
clim_ts_t ccl2f2
CFC-12 time series.
Definition: mptrac.h:3448
clim_ts_t sf6
SF6 time series.
Definition: mptrac.h:3454
clim_ts_t ccl4
CFC-10 time series.
Definition: mptrac.h:3442
clim_ts_t ccl3f
CFC-11 time series.
Definition: mptrac.h:3445
clim_ts_t n2o
N2O time series.
Definition: mptrac.h:3451
int qnt_Cccl2f2
Quantity array index for CFC-12 volume mixing ratio (chemistry code).
Definition: mptrac.h:2521
int qnt_m
Quantity array index for mass.
Definition: mptrac.h:2269
int qnt_aoa
Quantity array index for age of air.
Definition: mptrac.h:2530
char clim_n2o_timeseries[LEN]
Filename of N2O time series.
Definition: mptrac.h:2865
double bound_dzs
Boundary conditions surface layer depth [km].
Definition: mptrac.h:2814
int qnt_Cccl4
Quantity array index for CFC-10 volume mixing ratio (chemistry code).
Definition: mptrac.h:2515
double bound_mass
Boundary conditions mass per particle [kg].
Definition: mptrac.h:2787
int qnt_vmr
Quantity array index for volume mixing ratio.
Definition: mptrac.h:2272
double bound_lat1
Boundary conditions maximum longitude [deg].
Definition: mptrac.h:2802
int bound_pbl
Boundary conditions planetary boundary layer (0=no, 1=yes).
Definition: mptrac.h:2820
double bound_p1
Boundary conditions top pressure [hPa].
Definition: mptrac.h:2808
double bound_vmr
Boundary conditions volume mixing ratio [ppv].
Definition: mptrac.h:2793
double bound_lat0
Boundary conditions minimum longitude [deg].
Definition: mptrac.h:2799
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
Definition: mptrac.h:2796
int qnt_Cn2o
Quantity array index for N2O volume mixing ratio (chemistry code).
Definition: mptrac.h:2524
int qnt_Cccl3f
Quantity array index for CFC-11 volume mixing ratio (chemistry code).
Definition: mptrac.h:2518
int qnt_Csf6
Quantity array index for SF6 volume mixing ratio (chemistry code).
Definition: mptrac.h:2527
double bound_dps
Boundary conditions surface layer depth [hPa].
Definition: mptrac.h:2811
double bound_mass_trend
Boundary conditions mass per particle trend [kg/s].
Definition: mptrac.h:2790
double bound_p0
Boundary conditions bottom pressure [hPa].
Definition: mptrac.h:2805
char clim_ccl4_timeseries[LEN]
Filename of CFC-10 time series.
Definition: mptrac.h:2856
char clim_sf6_timeseries[LEN]
Filename of SF6 time series.
Definition: mptrac.h:2868
char clim_ccl3f_timeseries[LEN]
Filename of CFC-11 time series.
Definition: mptrac.h:2859
char clim_ccl2f2_timeseries[LEN]
Filename of CFC-12 time series.
Definition: mptrac.h:2862
double bound_zetas
Boundary conditions surface layer zeta [K].
Definition: mptrac.h:2817
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 2406 of file mptrac.c.

2411 {
2412
2413 /* Check quantities... */
2414 if (ctl->qnt_m < 0 || ctl->qnt_Cx < 0)
2415 return;
2416 if (ctl->molmass <= 0)
2417 ERRMSG("Molar mass is not defined!");
2418
2419 /* Set timer... */
2420 SELECT_TIMER("MODULE_CHEM_GRID", "PHYSICS", NVTX_GPU);
2421
2422 /* Allocate... */
2423 const int np = atm->np;
2424 const int nz = ctl->chemgrid_nz;
2425 const int nx = ctl->chemgrid_nx;
2426 const int ny = ctl->chemgrid_ny;
2427 const int ngrid = nx * ny * nz;
2428
2429 double *restrict const z = (double *) malloc((size_t) nz * sizeof(double));
2430 double *restrict const press =
2431 (double *) malloc((size_t) nz * sizeof(double));
2432 double *restrict const mass =
2433 (double *) calloc((size_t) ngrid, sizeof(double));
2434 double *restrict const area =
2435 (double *) malloc((size_t) ny * sizeof(double));
2436 double *restrict const lon =
2437 (double *) malloc((size_t) nx * sizeof(double));
2438 double *restrict const lat =
2439 (double *) malloc((size_t) ny * sizeof(double));
2440
2441 int *restrict const ixs = (int *) malloc((size_t) np * sizeof(int));
2442 int *restrict const iys = (int *) malloc((size_t) np * sizeof(int));
2443 int *restrict const izs = (int *) malloc((size_t) np * sizeof(int));
2444
2445 /* Set grid box size... */
2446 const double dz = (ctl->chemgrid_z1 - ctl->chemgrid_z0) / nz;
2447 const double dlon = (ctl->chemgrid_lon1 - ctl->chemgrid_lon0) / nx;
2448 const double dlat = (ctl->chemgrid_lat1 - ctl->chemgrid_lat0) / ny;
2449
2450 /* Set vertical coordinates... */
2451#ifdef _OPENACC
2452#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])
2453#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
2454#pragma acc parallel loop independent gang vector
2455#else
2456#pragma omp parallel for default(shared)
2457#endif
2458 for (int iz = 0; iz < nz; iz++) {
2459 z[iz] = ctl->chemgrid_z0 + dz * (iz + 0.5);
2460 press[iz] = P(z[iz]);
2461 }
2462
2463 /* Set time interval for output... */
2464 const double t0 = tt - 0.5 * ctl->dt_mod;
2465 const double t1 = tt + 0.5 * ctl->dt_mod;
2466
2467 /* Get indices... */
2468#ifdef _OPENACC
2469#pragma acc parallel loop independent gang vector
2470#else
2471#pragma omp parallel for default(shared)
2472#endif
2473 for (int ip = 0; ip < np; ip++) {
2474 ixs[ip] = (int) ((atm->lon[ip] - ctl->chemgrid_lon0) / dlon);
2475 iys[ip] = (int) ((atm->lat[ip] - ctl->chemgrid_lat0) / dlat);
2476 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->chemgrid_z0) / dz);
2477 if (atm->time[ip] < t0 || atm->time[ip] > t1
2478 || ixs[ip] < 0 || ixs[ip] >= nx
2479 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
2480 izs[ip] = -1;
2481 }
2482
2483 /* Set horizontal coordinates... */
2484#ifdef _OPENACC
2485#pragma acc parallel loop independent gang vector
2486#else
2487#pragma omp parallel for default(shared)
2488#endif
2489 for (int ix = 0; ix < nx; ix++)
2490 lon[ix] = ctl->chemgrid_lon0 + dlon * (ix + 0.5);
2491#ifdef _OPENACC
2492#pragma acc parallel loop independent gang vector
2493#else
2494#pragma omp parallel for default(shared)
2495#endif
2496 for (int iy = 0; iy < ny; iy++) {
2497 lat[iy] = ctl->chemgrid_lat0 + dlat * (iy + 0.5);
2498 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
2499 }
2500
2501 /* Get mass per grid box... */
2502#ifdef _OPENACC
2503#pragma acc parallel loop independent gang vector
2504#endif
2505 for (int ip = 0; ip < np; ip++)
2506 if (izs[ip] >= 0)
2507#ifdef _OPENACC
2508#pragma acc atomic update
2509#endif
2510 mass[ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz)]
2511 += atm->q[ctl->qnt_m][ip];
2512
2513 /* Assign grid data to air parcels ... */
2514#ifdef _OPENACC
2515#pragma acc parallel loop independent gang vector
2516#else
2517#pragma omp parallel for default(shared)
2518#endif
2519 for (int ip = 0; ip < np; ip++)
2520 if (izs[ip] >= 0) {
2521
2522 /* Interpolate temperature... */
2523 double temp;
2525 intpol_met_time_3d(met0, met0->t, met1, met1->t, tt, press[izs[ip]],
2526 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
2527
2528 /* Set mass... */
2529 const double m = mass[ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz)];
2530
2531 /* Calculate volume mixing ratio... */
2532 atm->q[ctl->qnt_Cx][ip] = MA / ctl->molmass * m
2533 / (RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
2534 }
2535#ifdef _OPENACC
2536#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
2537#endif
2538
2539 /* Free... */
2540 free(mass);
2541 free(lon);
2542 free(lat);
2543 free(area);
2544 free(z);
2545 free(press);
2546 free(ixs);
2547 free(iys);
2548 free(izs);
2549}
#define ARRAY_3D(ix, iy, ny, iz, nz)
Compute the linear index of a 3D array element.
Definition: mptrac.h:406
#define P(z)
Compute pressure at given altitude.
Definition: mptrac.h:1384
#define RHO(p, t)
Compute density of air.
Definition: mptrac.h:1561
double molmass
Molar mass [g/mol].
Definition: mptrac.h:2826
double chemgrid_z1
Upper altitude of chemistry grid [km].
Definition: mptrac.h:2913
double chemgrid_z0
Lower altitude of chemistry grid [km].
Definition: mptrac.h:2910
double chemgrid_lat0
Lower latitude of chemistry grid [deg].
Definition: mptrac.h:2928
double chemgrid_lat1
Upper latitude of chemistry grid [deg].
Definition: mptrac.h:2931
double chemgrid_lon0
Lower longitude of chemistry grid [deg].
Definition: mptrac.h:2919
double chemgrid_lon1
Upper longitude of chemistry grid [deg].
Definition: mptrac.h:2922
double dt_mod
Time step of simulation [s].
Definition: mptrac.h:2542
int chemgrid_nz
Number of altitudes of chemistry grid.
Definition: mptrac.h:2907
int chemgrid_nx
Number of longitudes of chemistry grid.
Definition: mptrac.h:2916
int chemgrid_ny
Number of latitudes of chemistry grid.
Definition: mptrac.h:2925
int qnt_Cx
Quantity array index for trace species x volume mixing ratio (chemistry code).
Definition: mptrac.h:2485
Here is the call graph for this function:

◆ module_chem_grid_ens()

void module_chem_grid_ens ( const ctl_t ctl,
met_t met0,
met_t met1,
atm_t atm,
const double  tt 
)

Processes atmospheric ensemble chemical data on a defined 3D grid.

This function aggregates and interpolates mass and mixing ratio data for atmospheric parcels over a 3D spatial grid, for multiple ensemble members. It computes grid-based statistics and updates each air parcel with the appropriate chemical quantities (e.g., mass and concentration).

Parameters
ctlPointer to the model control structure containing grid and configuration parameters.
met0Pointer to the meteorological dataset at the beginning of the interpolation time window.
met1Pointer to the meteorological dataset at the end of the interpolation time window.
atmPointer to the structure containing atmospheric parcel data, including positions and properties.
ttSimulation time (in seconds) for which the chemical grid is evaluated.

The function performs the following main tasks:

  • Checks configuration and model parameters for validity.
  • Allocates and initializes memory for spatial grid properties (altitude, pressure, area, etc.).
  • Maps air parcel positions to 3D grid indices (longitude, latitude, height).
  • Aggregates mass into grid cells for each ensemble.
  • Interpolates meteorological data (e.g., temperature) at each parcel's position.
  • Computes volume mixing ratios using the interpolated data and grid cell properties.
  • Updates each air parcel with the computed chemical quantity.

Parallelization is supported via OpenMP or OpenACC (depending on compilation).

Note
  • Memory allocation is done dynamically within the function and freed before exit.
  • The function uses macros and helper functions like P(), Z(), RHO(), ARRAY_3D(), and intpol_met_time_3d() for calculations and interpolation.
  • Requires ensemble quantity indices (qnt_ens, qnt_m, and qnt_Cx) to be set in ctl.
Warning
If molar mass is not set (molmass <= 0), the function will issue an error and exit.
Authors
Mingzhao Liu

Definition at line 2553 of file mptrac.c.

2558 {
2559
2560 /* Check quantities... */
2561 if (ctl->qnt_m < 0 || ctl->qnt_Cx < 0)
2562 return;
2563 if (ctl->molmass <= 0)
2564 ERRMSG("Molar mass is not defined!");
2565
2566 /* Set timer... */
2567 SELECT_TIMER("MODULE_CHEM_GRID_ENS", "PHYSICS", NVTX_GPU);
2568
2569 /* Allocate... */
2570 const int np = atm->np;
2571 const int nz = ctl->chemgrid_nz;
2572 const int nx = ctl->chemgrid_nx;
2573 const int ny = ctl->chemgrid_ny;
2574 const int ngrid = nx * ny * nz;
2575
2576 double *restrict const z = (double *) malloc((size_t) nz * sizeof(double));
2577 double *restrict const press =
2578 (double *) malloc((size_t) nz * sizeof(double));
2579 double *restrict const mass =
2580 (double *) calloc((size_t) ngrid * (size_t) ctl->nens, sizeof(double));
2581 double *restrict const area =
2582 (double *) malloc((size_t) ny * sizeof(double));
2583 double *restrict const lon =
2584 (double *) malloc((size_t) nx * sizeof(double));
2585 double *restrict const lat =
2586 (double *) malloc((size_t) ny * sizeof(double));
2587
2588 int *restrict const ixs = (int *) malloc((size_t) np * sizeof(int));
2589 int *restrict const iys = (int *) malloc((size_t) np * sizeof(int));
2590 int *restrict const izs = (int *) malloc((size_t) np * sizeof(int));
2591
2592 /* Set grid box size... */
2593 const double dz = (ctl->chemgrid_z1 - ctl->chemgrid_z0) / nz;
2594 const double dlon = (ctl->chemgrid_lon1 - ctl->chemgrid_lon0) / nx;
2595 const double dlat = (ctl->chemgrid_lat1 - ctl->chemgrid_lat0) / ny;
2596
2597 /* Set vertical coordinates... */
2598#ifdef _OPENACC
2599#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])
2600#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
2601#pragma acc parallel loop independent gang vector
2602#else
2603#pragma omp parallel for default(shared)
2604#endif
2605 for (int iz = 0; iz < nz; iz++) {
2606 z[iz] = ctl->chemgrid_z0 + dz * (iz + 0.5);
2607 press[iz] = P(z[iz]);
2608 }
2609
2610 /* Set time interval for output... */
2611 const double t0 = tt - 0.5 * ctl->dt_mod;
2612 const double t1 = tt + 0.5 * ctl->dt_mod;
2613
2614 /* Get indices... */
2615#ifdef _OPENACC
2616#pragma acc parallel loop independent gang vector
2617#else
2618#pragma omp parallel for default(shared)
2619#endif
2620 for (int ip = 0; ip < np; ip++) {
2621 ixs[ip] = (int) ((atm->lon[ip] - ctl->chemgrid_lon0) / dlon);
2622 iys[ip] = (int) ((atm->lat[ip] - ctl->chemgrid_lat0) / dlat);
2623 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->chemgrid_z0) / dz);
2624 if (atm->time[ip] < t0 || atm->time[ip] > t1
2625 || ixs[ip] < 0 || ixs[ip] >= nx
2626 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
2627 izs[ip] = -1;
2628 }
2629
2630 /* Set horizontal coordinates... */
2631#ifdef _OPENACC
2632#pragma acc parallel loop independent gang vector
2633#else
2634#pragma omp parallel for default(shared)
2635#endif
2636 for (int ix = 0; ix < nx; ix++)
2637 lon[ix] = ctl->chemgrid_lon0 + dlon * (ix + 0.5);
2638#ifdef _OPENACC
2639#pragma acc parallel loop independent gang vector
2640#else
2641#pragma omp parallel for default(shared)
2642#endif
2643 for (int iy = 0; iy < ny; iy++) {
2644 lat[iy] = ctl->chemgrid_lat0 + dlat * (iy + 0.5);
2645 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
2646 }
2647
2648 /* Get mass per grid box per ensemble... */
2649#ifdef _OPENACC
2650#pragma acc parallel loop independent gang vector
2651#endif
2652 for (int ip = 0; ip < np; ip++)
2653 if (izs[ip] >= 0) {
2654 const int ens = (int) atm->q[ctl->qnt_ens][ip];
2655#ifdef _OPENACC
2656#pragma acc atomic update
2657#endif
2658 mass[ens * ngrid + ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz)]
2659 += atm->q[ctl->qnt_m][ip];
2660 }
2661
2662 /* Assign grid data to air parcels ... */
2663#ifdef _OPENACC
2664#pragma acc parallel loop independent gang vector
2665#else
2666#pragma omp parallel for default(shared)
2667#endif
2668 for (int ip = 0; ip < np; ip++)
2669 if (izs[ip] >= 0) {
2670
2671 /* Interpolate temperature... */
2672 double temp;
2674 intpol_met_time_3d(met0, met0->t, met1, met1->t, tt, press[izs[ip]],
2675 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
2676
2677 /* Set mass per ensemble... */
2678 int ens = (int) atm->q[ctl->qnt_ens][ip];
2679 const double m =
2680 mass[ens * ngrid + ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz)];
2681
2682 /* Calculate volume mixing ratio... */
2683 atm->q[ctl->qnt_Cx][ip] = MA / ctl->molmass * m
2684 / (RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
2685 }
2686#ifdef _OPENACC
2687#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
2688#endif
2689
2690 /* Free... */
2691 free(mass);
2692 free(lon);
2693 free(lat);
2694 free(area);
2695 free(z);
2696 free(press);
2697 free(ixs);
2698 free(iys);
2699 free(izs);
2700}
int nens
Number of ensembles.
Definition: mptrac.h:3040
int qnt_ens
Quantity array index for ensemble IDs.
Definition: mptrac.h:2263
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 2704 of file mptrac.c.

2710 {
2711
2712 /* Set timer... */
2713 SELECT_TIMER("MODULE_CHEM_INIT", "PHYSICS", NVTX_GPU);
2714
2715 /* Loop over particles... */
2716 PARTICLE_LOOP(0, atm->np, 0,
2717 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2718
2719 /* Set H2O and O3 using meteo data... */
2721 if (ctl->qnt_Ch2o >= 0) {
2722 double h2o;
2723 INTPOL_3D(h2o, 1);
2724 SET_ATM(qnt_Ch2o, h2o);
2725 }
2726 if (ctl->qnt_Co3 >= 0) {
2727 double o3;
2728 INTPOL_3D(o3, 1);
2729 SET_ATM(qnt_Co3, o3);
2730 }
2731
2732 /* Set radical species... */
2733 SET_ATM(qnt_Coh, clim_oh(ctl, clim, atm->time[ip],
2734 atm->lon[ip], atm->lat[ip], atm->p[ip]));
2735 SET_ATM(qnt_Cho2, clim_zm(&clim->ho2, atm->time[ip],
2736 atm->lat[ip], atm->p[ip]));
2737 SET_ATM(qnt_Ch2o2, clim_zm(&clim->h2o2, atm->time[ip],
2738 atm->lat[ip], atm->p[ip]));
2739 SET_ATM(qnt_Co1d, clim_zm(&clim->o1d, atm->time[ip],
2740 atm->lat[ip], atm->p[ip]));
2741 }
2742}
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:1580
clim_zm_t ho2
HO2 zonal means.
Definition: mptrac.h:3436
clim_zm_t o1d
O(1D) zonal means.
Definition: mptrac.h:3439
clim_zm_t h2o2
H2O2 zonal means.
Definition: mptrac.h:3433
int qnt_Ch2o
Quantity array index for H2O volume mixing ratio (chemistry code).
Definition: mptrac.h:2488
int qnt_Co3
Quantity array index for O3 volume mixing ratio (chemistry code).
Definition: mptrac.h:2491
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 2746 of file mptrac.c.

2751 {
2752
2753 /* Set timer... */
2754 SELECT_TIMER("MODULE_CONVECTION", "PHYSICS", NVTX_GPU);
2755
2756 /* Create random numbers... */
2757 module_rng(ctl, cache->rs, (size_t) atm->np, 0);
2758
2759 /* Loop over particles... */
2760 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2761
2762 /* Interpolate CAPE... */
2763 double ps;
2765 INTPOL_2D(ps, 1);
2766
2767 /* Initialize pressure range for vertical mixing... */
2768 double pbot = ps, ptop = ps;
2769
2770 /* Mixing in the PBL... */
2771 if (ctl->conv_mix_pbl) {
2772
2773 /* Interpolate PBL... */
2774 double pbl;
2775 INTPOL_2D(pbl, 0);
2776
2777 /* Set pressure range... */
2778 ptop = pbl - ctl->conv_pbl_trans * (ps - pbl);
2779 }
2780
2781 /* Convective mixing... */
2782 if (ctl->conv_cape >= 0) {
2783
2784 /* Interpolate CAPE, CIN, and equilibrium level... */
2785 double cape, cin, pel;
2786 INTPOL_2D(cape, 0);
2787 INTPOL_2D(cin, 0);
2788 INTPOL_2D(pel, 0);
2789
2790 /* Set pressure range... */
2791 if (isfinite(cape) && cape >= ctl->conv_cape
2792 && (ctl->conv_cin <= 0 || (isfinite(cin) && cin >= ctl->conv_cin)))
2793 ptop = GSL_MIN(ptop, pel);
2794 }
2795
2796 /* Apply vertical mixing... */
2797 if (ptop != pbot && atm->p[ip] >= ptop) {
2798
2799 /* Get density range... */
2800 double tbot, ttop;
2801 intpol_met_time_3d(met0, met0->t, met1, met1->t, atm->time[ip],
2802 pbot, atm->lon[ip], atm->lat[ip], &tbot, ci, cw, 1);
2803 intpol_met_time_3d(met0, met0->t, met1, met1->t, atm->time[ip], ptop,
2804 atm->lon[ip], atm->lat[ip], &ttop, ci, cw, 1);
2805 const double rhobot = pbot / tbot;
2806 const double rhotop = ptop / ttop;
2807
2808 /* Get new density... */
2809 const double rho = rhobot + (rhotop - rhobot) * cache->rs[ip];
2810
2811 /* Get pressure... */
2812 atm->p[ip] = LIN(rhobot, pbot, rhotop, ptop, rho);
2813 }
2814 }
2815}
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:4022
double rs[3 *NP+1]
Random numbers.
Definition: mptrac.h:3284
double conv_cape
CAPE threshold for convection module [J/kg].
Definition: mptrac.h:2778
double conv_pbl_trans
Depth of PBL transition layer (fraction of PBL depth).
Definition: mptrac.h:2775
int conv_mix_pbl
Vertical mixing in the PBL (0=off, 1=on).
Definition: mptrac.h:2772
double conv_cin
CIN threshold for convection module [J/kg].
Definition: mptrac.h:2781
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 2819 of file mptrac.c.

2823 {
2824
2825 /* Set timer... */
2826 SELECT_TIMER("MODULE_DECAY", "PHYSICS", NVTX_GPU);
2827
2828 /* Check quantity flags... */
2829 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
2830 ERRMSG("Module needs quantity mass or volume mixing ratio!");
2831
2832 /* Loop over particles... */
2833 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,clim,atm)") {
2834
2835 /* Get weighting factor... */
2836 const double w = tropo_weight(clim, atm, ip);
2837
2838 /* Set lifetime... */
2839 const double tdec = w * ctl->tdec_trop + (1 - w) * ctl->tdec_strat;
2840
2841 /* Calculate exponential decay... */
2842 const double aux = exp(-cache->dt[ip] / tdec);
2843 if (ctl->qnt_m >= 0) {
2844 if (ctl->qnt_mloss_decay >= 0)
2845 atm->q[ctl->qnt_mloss_decay][ip]
2846 += atm->q[ctl->qnt_m][ip] * (1 - aux);
2847 atm->q[ctl->qnt_m][ip] *= aux;
2848 if (ctl->qnt_loss_rate >= 0)
2849 atm->q[ctl->qnt_loss_rate][ip] += 1. / tdec;
2850 }
2851 if (ctl->qnt_vmr >= 0)
2852 atm->q[ctl->qnt_vmr][ip] *= aux;
2853 }
2854}
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:10182
int qnt_loss_rate
Quantity array index for total loss rate.
Definition: mptrac.h:2428
int qnt_mloss_decay
Quantity array index for total mass loss due to exponential decay.
Definition: mptrac.h:2425
double tdec_strat
Life time of particles in the stratosphere [s].
Definition: mptrac.h:2832
double tdec_trop
Life time of particles in the troposphere [s].
Definition: mptrac.h:2829
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 2858 of file mptrac.c.

2863 {
2864
2865 /* Set timer... */
2866 SELECT_TIMER("MODULE_DIFF_MESO", "PHYSICS", NVTX_GPU);
2867
2868 /* Create random numbers... */
2869 module_rng(ctl, cache->rs, 3 * (size_t) atm->np, 1);
2870
2871 /* Loop over particles... */
2872 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2873
2874 /* Get indices... */
2875 const int ix = locate_reg(met0->lon, met0->nx, atm->lon[ip]);
2876 const int iy = locate_irr(met0->lat, met0->ny, atm->lat[ip]);
2877 const int iz = locate_irr(met0->p, met0->np, atm->p[ip]);
2878
2879 /* Get standard deviations of local wind data... */
2880 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
2881 for (int i = 0; i < 2; i++)
2882 for (int j = 0; j < 2; j++)
2883 for (int k = 0; k < 2; k++) {
2884 umean += met0->u[ix + i][iy + j][iz + k];
2885 usig += SQR(met0->u[ix + i][iy + j][iz + k]);
2886 vmean += met0->v[ix + i][iy + j][iz + k];
2887 vsig += SQR(met0->v[ix + i][iy + j][iz + k]);
2888 wmean += met0->w[ix + i][iy + j][iz + k];
2889 wsig += SQR(met0->w[ix + i][iy + j][iz + k]);
2890
2891 umean += met1->u[ix + i][iy + j][iz + k];
2892 usig += SQR(met1->u[ix + i][iy + j][iz + k]);
2893 vmean += met1->v[ix + i][iy + j][iz + k];
2894 vsig += SQR(met1->v[ix + i][iy + j][iz + k]);
2895 wmean += met1->w[ix + i][iy + j][iz + k];
2896 wsig += SQR(met1->w[ix + i][iy + j][iz + k]);
2897 }
2898 usig = usig / 16.f - SQR(umean / 16.f);
2899 usig = (usig > 0 ? sqrtf(usig) : 0);
2900 vsig = vsig / 16.f - SQR(vmean / 16.f);
2901 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
2902 wsig = wsig / 16.f - SQR(wmean / 16.f);
2903 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
2904
2905 /* Set temporal correlations for mesoscale fluctuations... */
2906 const double r = 1 - 2 * fabs(cache->dt[ip]) / ctl->dt_met;
2907 const double r2 = sqrt(1 - r * r);
2908
2909 /* Calculate horizontal mesoscale wind fluctuations... */
2910 if (ctl->turb_mesox > 0) {
2911 cache->uvwp[ip][0] =
2912 (float) (r * cache->uvwp[ip][0] +
2913 r2 * cache->rs[3 * ip] * ctl->turb_mesox * usig);
2914 atm->lon[ip] +=
2915 DX2DEG(cache->uvwp[ip][0] * cache->dt[ip] / 1000., atm->lat[ip]);
2916
2917 cache->uvwp[ip][1] =
2918 (float) (r * cache->uvwp[ip][1] +
2919 r2 * cache->rs[3 * ip + 1] * ctl->turb_mesox * vsig);
2920 atm->lat[ip] += DY2DEG(cache->uvwp[ip][1] * cache->dt[ip] / 1000.);
2921 }
2922
2923 /* Calculate vertical mesoscale wind fluctuations... */
2924 if (ctl->turb_mesoz > 0) {
2925 cache->uvwp[ip][2] =
2926 (float) (r * cache->uvwp[ip][2] +
2927 r2 * cache->rs[3 * ip + 2] * ctl->turb_mesoz * wsig);
2928 atm->p[ip] += cache->uvwp[ip][2] * cache->dt[ip];
2929 }
2930 }
2931}
float uvwp[NP][3]
Wind perturbations [m/s].
Definition: mptrac.h:3281
double turb_mesoz
Vertical scaling factor for mesoscale wind fluctuations.
Definition: mptrac.h:2769
double dt_met
Time step of meteo data [s].
Definition: mptrac.h:2552
double turb_mesox
Horizontal scaling factor for mesoscale wind fluctuations.
Definition: mptrac.h:2766
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 2935 of file mptrac.c.

2940 {
2941
2942 /* Set timer... */
2943 SELECT_TIMER("MODULE_DIFF_PBL", "PHYSICS", NVTX_GPU);
2944
2945 /* Create random numbers... */
2946 module_rng(ctl, cache->rs, 3 * (size_t) atm->np, 1);
2947
2948 /* Loop over particles... */
2949 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2950
2951 double dsigw_dz = 0.0, sig_u = 0.25, sig_w = 0.1,
2952 tau_u = 300., tau_w = 100.;
2953
2954 /* Get surface and PBL pressure... */
2955 double pbl, ps;
2957 INTPOL_2D(ps, 1);
2958 INTPOL_2D(pbl, 0);
2959
2960 /* Boundary layer... */
2961 if (atm->p[ip] >= pbl) {
2962
2963 /* Calculate heights... */
2964 const double p = MIN(atm->p[ip], ps);
2965 const double zs = Z(ps);
2966 const double z = 1e3 * (Z(p) - zs);
2967 const double zi = 1e3 * (Z(pbl) - zs);
2968 const double zratio = z / zi;
2969
2970 /* Calculate friction velocity... */
2971 double ess, nss, h2o, t;
2972 INTPOL_2D(ess, 0);
2973 INTPOL_2D(nss, 0);
2974 INTPOL_3D(t, 1);
2975 INTPOL_3D(h2o, 0);
2976 const double rho = RHO(p, TVIRT(t, h2o));
2977 const double tau = sqrt(SQR(ess) + SQR(nss));
2978 const double ustar = sqrt(tau / rho);
2979
2980 /* Get surface sensible heat flux... */
2981 double shf;
2982 INTPOL_2D(shf, 1);
2983
2984 /* Stable or neutral conditions... */
2985 if (shf <= 0) {
2986
2987 /* Calcalute turbulent velocity variances... */
2988 sig_u = 1e-2 + 2.0 * ustar * (1.0 - zratio);
2989 sig_w = 1e-2 + 1.3 * ustar * (1.0 - zratio);
2990
2991 /* Calculate derivative dsig_w/dz... */
2992 dsigw_dz = -1.3 * ustar / zi;
2993
2994 /* Calcalute Lagrangian timescales... */
2995 tau_u = 0.07 * zi / sig_u * sqrt(zratio);
2996 tau_w = 0.1 * zi / sig_w * pow(zratio, 0.8);
2997 }
2998
2999 /* Unstable conditions... */
3000 else {
3001
3002 /* Convective velocity... */
3003 const double wstar =
3004 pow(G0 / THETAVIRT(p, t, h2o) * shf / (rho * CPD) * zi, 1. / 3.);
3005
3006 /* Calcalute turbulent velocity variances... */
3007 sig_u = 1e-2
3008 + sqrt(0.4 * SQR(wstar) + (5.0 - 4.0 * zratio) * SQR(ustar));
3009 sig_w = 1e-2 + sqrt(1.2 * SQR(wstar) * (1.0 - 0.9 * zratio)
3010 * pow(zratio, 2.0 / 3.0)
3011 + (1.8 - 1.4 * zratio) * SQR(ustar));
3012
3013 /* Calculate derivative dsig_w/dz... */
3014 dsigw_dz = 0.5 / sig_w / zi * (-1.4 * SQR(ustar) + SQR(wstar)
3015 * (0.8 *
3016 pow(MAX(zratio, 1e-3), -1.0 / 3.0)
3017 - 1.8 * pow(zratio, 2.0 / 3.0)));
3018
3019 /* Calcalute Lagrangian timescales... */
3020 const double C0 = 3.0; // TODO: typically 3...6, NAME model uses 3?
3021 const double eps =
3022 (1.5 - 1.2 * pow(zratio, 1.0 / 3.0)) * SQR(wstar) * wstar / zi
3023 + SQR(ustar) * ustar * (1.0 - 0.8 * zratio) / (KARMAN * z);
3024 tau_u = 2 * SQR(sig_u) / (C0 * eps);
3025 tau_w = 2 * SQR(sig_w) / (C0 * eps);
3026 }
3027 }
3028
3029 /* Set minimum values... */
3030 sig_u = MAX(sig_u, 0.25);
3031 sig_w = MAX(sig_w, 0.1);
3032 tau_u = MAX(tau_u, 300.);
3033 tau_w = MAX(tau_w, 100.);
3034
3035 /* Update perturbations... */
3036 const double ru = exp(-fabs(cache->dt[ip]) / tau_u);
3037 const double ru2 = sqrt(1.0 - SQR(ru));
3038 cache->uvwp[ip][0]
3039 = (float) (cache->uvwp[ip][0] * ru + ru2 * cache->rs[3 * ip]);
3040 cache->uvwp[ip][1]
3041 = (float) (cache->uvwp[ip][1] * ru + ru2 * cache->rs[3 * ip + 1]);
3042
3043 const double rw = exp(-fabs(cache->dt[ip]) / tau_w);
3044 const double rw2 = sqrt(1.0 - SQR(rw));
3045 cache->uvwp[ip][2]
3046 = (float) (cache->uvwp[ip][2] * rw + rw2 * cache->rs[3 * ip + 2]
3047 + sig_w * dsigw_dz * cache->dt[ip]); // TODO: check approx for density correction?
3048
3049 /* Calculate new air parcel position... */
3050 atm->lon[ip] +=
3051 DX2DEG(cache->uvwp[ip][0] * cache->dt[ip] / 1000., atm->lat[ip]);
3052 atm->lat[ip] += DY2DEG(cache->uvwp[ip][1] * cache->dt[ip] / 1000.);
3053 atm->p[ip] +=
3054 DZ2DP(cache->uvwp[ip][2] * cache->dt[ip] / 1000., atm->p[ip]);
3055 }
3056}
#define KARMAN
Karman's constant.
Definition: mptrac.h:202
#define THETAVIRT(p, t, h2o)
Compute virtual potential temperature.
Definition: mptrac.h:1753
#define DZ2DP(dz, p)
Convert a change in altitude to a change in pressure.
Definition: mptrac.h:577
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 3060 of file mptrac.c.

3066 {
3067
3068 /* Set timer... */
3069 SELECT_TIMER("MODULE_DIFF_TURB", "PHYSICS", NVTX_GPU);
3070
3071 /* Create random numbers... */
3072 module_rng(ctl, cache->rs, 3 * (size_t) atm->np, 1);
3073
3074 /* Loop over particles... */
3075 PARTICLE_LOOP(0, atm->np, 1,
3076 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3077
3078 /* Get PBL and surface pressure... */
3079 double pbl, ps;
3081 INTPOL_2D(pbl, 1);
3082 INTPOL_2D(ps, 0);
3083
3084 /* Get weighting factors... */
3085 const double wpbl = pbl_weight(ctl, atm, ip, pbl, ps);
3086 const double wtrop = tropo_weight(clim, atm, ip) * (1.0 - wpbl);
3087 const double wstrat = 1.0 - wpbl - wtrop;
3088
3089 /* Set diffusivity... */
3090 const double dx = wpbl * ctl->turb_dx_pbl + wtrop * ctl->turb_dx_trop
3091 + wstrat * ctl->turb_dx_strat;
3092 const double dz = wpbl * ctl->turb_dz_pbl + wtrop * ctl->turb_dz_trop
3093 + wstrat * ctl->turb_dz_strat;
3094
3095 /* Horizontal turbulent diffusion... */
3096 if (dx > 0) {
3097 const double sigma = sqrt(2.0 * dx * fabs(cache->dt[ip])) / 1000.;
3098 atm->lon[ip] += DX2DEG(cache->rs[3 * ip] * sigma, atm->lat[ip]);
3099 atm->lat[ip] += DY2DEG(cache->rs[3 * ip + 1] * sigma);
3100 }
3101
3102 /* Vertical turbulent diffusion... */
3103 if (dz > 0) {
3104 const double sigma = sqrt(2.0 * dz * fabs(cache->dt[ip])) / 1000.;
3105 atm->p[ip] += DZ2DP(cache->rs[3 * ip + 2] * sigma, atm->p[ip]);
3106 }
3107 }
3108}
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:6245
double turb_dz_trop
Vertical turbulent diffusion coefficient (troposphere) [m^2/s].
Definition: mptrac.h:2760
double turb_dx_strat
Horizontal turbulent diffusion coefficient (stratosphere) [m^2/s].
Definition: mptrac.h:2754
double turb_dx_trop
Horizontal turbulent diffusion coefficient (troposphere) [m^2/s].
Definition: mptrac.h:2751
double turb_dx_pbl
Horizontal turbulent diffusion coefficient (PBL) [m^2/s].
Definition: mptrac.h:2748
double turb_dz_strat
Vertical turbulent diffusion coefficient (stratosphere) [m^2/s].
Definition: mptrac.h:2763
double turb_dz_pbl
Vertical turbulent diffusion coefficient (PBL) [m^2/s].
Definition: mptrac.h:2757
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 3112 of file mptrac.c.

3117 {
3118
3119 /* Set timer... */
3120 SELECT_TIMER("MODULE_DRY_DEPO", "PHYSICS", NVTX_GPU);
3121
3122 /* Check quantity flags... */
3123 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
3124 ERRMSG("Module needs quantity mass or volume mixing ratio!");
3125
3126 /* Loop over particles... */
3127 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
3128
3129 /* Get surface pressure... */
3130 double ps;
3132 INTPOL_2D(ps, 1);
3133
3134 /* Check whether particle is above the surface layer... */
3135 if (atm->p[ip] < ps - ctl->dry_depo_dp)
3136 continue;
3137
3138 /* Set depth of surface layer... */
3139 const double dz = 1000. * (Z(ps - ctl->dry_depo_dp) - Z(ps));
3140
3141 /* Calculate sedimentation velocity for particles... */
3142 double v_dep;
3143 if (ctl->qnt_rp > 0 && ctl->qnt_rhop > 0) {
3144
3145 /* Get temperature... */
3146 double t;
3147 INTPOL_3D(t, 1);
3148
3149 /* Set deposition velocity... */
3150 v_dep = sedi(atm->p[ip], t, atm->q[ctl->qnt_rp][ip],
3151 atm->q[ctl->qnt_rhop][ip]);
3152 }
3153
3154 /* Use explicit sedimentation velocity for gases... */
3155 else
3156 v_dep = ctl->dry_depo_vdep;
3157
3158 /* Calculate loss of mass based on deposition velocity... */
3159 const double aux = exp(-cache->dt[ip] * v_dep / dz);
3160 if (ctl->qnt_m >= 0) {
3161 if (ctl->qnt_mloss_dry >= 0)
3162 atm->q[ctl->qnt_mloss_dry][ip]
3163 += atm->q[ctl->qnt_m][ip] * (1 - aux);
3164 atm->q[ctl->qnt_m][ip] *= aux;
3165 if (ctl->qnt_loss_rate >= 0)
3166 atm->q[ctl->qnt_loss_rate][ip] += v_dep / dz;
3167 }
3168 if (ctl->qnt_vmr >= 0)
3169 atm->q[ctl->qnt_vmr][ip] *= aux;
3170 }
3171}
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:9906
int qnt_rhop
Quantity array index for particle density.
Definition: mptrac.h:2278
int qnt_rp
Quantity array index for particle radius.
Definition: mptrac.h:2275
double dry_depo_dp
Dry deposition surface layer [hPa].
Definition: mptrac.h:2985
int qnt_mloss_dry
Quantity array index for total mass loss due to dry deposition.
Definition: mptrac.h:2422
double dry_depo_vdep
Dry deposition velocity [m/s].
Definition: mptrac.h:2988
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 3175 of file mptrac.c.

3181 {
3182
3183 /* Set timer... */
3184 SELECT_TIMER("MODULE_H2O2_CHEM", "PHYSICS", NVTX_GPU);
3185
3186 /* Check quantity flags... */
3187 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
3188 ERRMSG("Module needs quantity mass or volume mixing ratio!");
3189
3190 /* Parameter of SO2 correction... */
3191 const double a = 3.12541941e-06;
3192 const double b = -5.72532259e-01;
3193 const double low = pow(1. / a, 1. / b);
3194
3195 /* Loop over particles... */
3196 PARTICLE_LOOP(0, atm->np, 1,
3197 "acc data present(ctl,cache,ctl,met0,met1,atm)") {
3198
3199 /* Check whether particle is inside cloud... */
3200 double lwc, rwc;
3202 INTPOL_3D(lwc, 1);
3203 INTPOL_3D(rwc, 0);
3204 if (!(lwc > 0 || rwc > 0))
3205 continue;
3206
3207 /* Get temperature... */
3208 double t;
3209 INTPOL_3D(t, 0);
3210
3211 /* Get molecular density... */
3212 const double M = MOLEC_DENS(atm->p[ip], t);
3213
3214 /* Reaction rate (Berglen et al., 2004)... */
3215 const double k = 9.1e7 * exp(-29700. / RI * (1. / t - 1. / 298.15)); /* (Maass, 1999), unit: M^(-2) */
3216
3217 /* Henry constant of SO2... */
3218 const double H_SO2 =
3219 1.3e-2 * exp(2900. * (1. / t - 1. / 298.15)) * RI * t;
3220 const double K_1S = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15)); /* unit: mol/L */
3221
3222 /* Henry constant of H2O2... */
3223 const double H_h2o2 =
3224 8.3e2 * exp(7600. * (1. / t - 1. / 298.15)) * RI * t;
3225
3226 /* Correction factor for high SO2 concentration
3227 (if qnt_Cx is defined, the correction is switched on)... */
3228 double cor = 1.0;
3229 if (ctl->qnt_Cx >= 0)
3230 cor = atm->q[ctl->qnt_Cx][ip] >
3231 low ? a * pow(atm->q[ctl->qnt_Cx][ip], b) : 1;
3232
3233 const double h2o2 = H_h2o2
3234 * clim_zm(&clim->h2o2, atm->time[ip], atm->lat[ip], atm->p[ip])
3235 * M * cor * 1000. / AVO; /* unit: mol/L */
3236
3237 /* Volume water content in cloud [m^3 m^(-3)]... */
3238 const double rho_air = atm->p[ip] / (RI * t) * MA / 10.;
3239 const double CWC = (lwc + rwc) * rho_air / 1e3;
3240
3241 /* Calculate exponential decay (Rolph et al., 1992)... */
3242 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
3243 const double aux = exp(-cache->dt[ip] * rate_coef);
3244 if (ctl->qnt_m >= 0) {
3245 if (ctl->qnt_mloss_h2o2 >= 0)
3246 atm->q[ctl->qnt_mloss_h2o2][ip] += atm->q[ctl->qnt_m][ip] * (1 - aux);
3247 atm->q[ctl->qnt_m][ip] *= aux;
3248 if (ctl->qnt_loss_rate >= 0)
3249 atm->q[ctl->qnt_loss_rate][ip] += rate_coef;
3250 }
3251 if (ctl->qnt_vmr >= 0)
3252 atm->q[ctl->qnt_vmr][ip] *= aux;
3253 }
3254}
#define AVO
Avogadro constant [1/mol].
Definition: mptrac.h:172
#define MOLEC_DENS(p, t)
Calculate the density of a gas molecule.
Definition: mptrac.h:1082
int qnt_mloss_h2o2
Quantity array index for total mass loss due to H2O2 chemistry.
Definition: mptrac.h:2413
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 3258 of file mptrac.c.

3263 {
3264
3265 double t;
3266
3267 /* Set timer... */
3268 SELECT_TIMER("MODULE_ISOSURF_INIT", "PHYSICS", NVTX_GPU);
3269
3270 /* Save pressure... */
3271 if (ctl->isosurf == 1) {
3272 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,atm)") {
3273 cache->iso_var[ip] = atm->p[ip];
3274 }
3275 }
3276
3277 /* Save density... */
3278 else if (ctl->isosurf == 2) {
3279 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,met0,met1,atm)") {
3281 INTPOL_3D(t, 1);
3282 cache->iso_var[ip] = atm->p[ip] / t;
3283 }
3284 }
3285
3286 /* Save potential temperature... */
3287 else if (ctl->isosurf == 3) {
3288 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,met0,met1,atm)") {
3290 INTPOL_3D(t, 1);
3291 cache->iso_var[ip] = THETA(atm->p[ip], t);
3292 }
3293 }
3294
3295 /* Read balloon pressure data... */
3296 else if (ctl->isosurf == 4) {
3297
3298 /* Write info... */
3299 LOG(1, "Read balloon pressure data: %s", ctl->balloon);
3300
3301 /* Open file... */
3302 FILE *in;
3303 if (!(in = fopen(ctl->balloon, "r")))
3304 ERRMSG("Cannot open file!");
3305
3306 /* Read pressure time series... */
3307 char line[LEN];
3308 while (fgets(line, LEN, in))
3309 if (sscanf(line, "%lg %lg", &(cache->iso_ts[cache->iso_n]),
3310 &(cache->iso_ps[cache->iso_n])) == 2)
3311 if ((++cache->iso_n) > NP)
3312 ERRMSG("Too many data points!");
3313
3314 /* Check number of points... */
3315 if (cache->iso_n < 1)
3316 ERRMSG("Could not read any data!");
3317
3318 /* Close file... */
3319 fclose(in);
3320
3321 /* Update of cache data on device... */
3322 mptrac_update_device(NULL, cache, NULL, NULL, NULL, NULL);
3323 }
3324}
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:5912
double iso_ts[NP]
Isosurface balloon time [s].
Definition: mptrac.h:3275
int iso_n
Isosurface balloon number of data points.
Definition: mptrac.h:3278
double iso_ps[NP]
Isosurface balloon pressure [hPa].
Definition: mptrac.h:3272
double iso_var[NP]
Isosurface variables.
Definition: mptrac.h:3269
char balloon[LEN]
Balloon position filename.
Definition: mptrac.h:2732
int isosurf
Isosurface parameter (0=none, 1=pressure, 2=density, 3=theta, 4=balloon).
Definition: mptrac.h:2729
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 3328 of file mptrac.c.

3333 {
3334
3335 /* Set timer... */
3336 SELECT_TIMER("MODULE_ISOSURF", "PHYSICS", NVTX_GPU);
3337
3338 /* Loop over particles... */
3339 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,cache,met0,met1,atm)") {
3340
3341 /* Init... */
3342 double t;
3344
3345 /* Restore pressure... */
3346 if (ctl->isosurf == 1)
3347 atm->p[ip] = cache->iso_var[ip];
3348
3349 /* Restore density... */
3350 else if (ctl->isosurf == 2) {
3351 INTPOL_3D(t, 1);
3352 atm->p[ip] = cache->iso_var[ip] * t;
3353 }
3354
3355 /* Restore potential temperature... */
3356 else if (ctl->isosurf == 3) {
3357 INTPOL_3D(t, 1);
3358 atm->p[ip] = 1000. * pow(cache->iso_var[ip] / t, -1. / 0.286);
3359 }
3360
3361 /* Interpolate pressure... */
3362 else if (ctl->isosurf == 4) {
3363 if (atm->time[ip] <= cache->iso_ts[0])
3364 atm->p[ip] = cache->iso_ps[0];
3365 else if (atm->time[ip] >= cache->iso_ts[cache->iso_n - 1])
3366 atm->p[ip] = cache->iso_ps[cache->iso_n - 1];
3367 else {
3368 int idx = locate_irr(cache->iso_ts, cache->iso_n, atm->time[ip]);
3369 atm->p[ip] = LIN(cache->iso_ts[idx], cache->iso_ps[idx],
3370 cache->iso_ts[idx + 1], cache->iso_ps[idx + 1],
3371 atm->time[ip]);
3372 }
3373 }
3374 }
3375}
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 3433 of file mptrac.c.

3439 {
3440
3441 /* Set timer... */
3442 SELECT_TIMER("MODULE_METEO", "PHYSICS", NVTX_GPU);
3443
3444 /* Check quantity flags... */
3445 if (ctl->qnt_tsts >= 0)
3446 if (ctl->qnt_tice < 0 || ctl->qnt_tnat < 0)
3447 ERRMSG("Need T_ice and T_NAT to calculate T_STS!");
3448
3449 /* Loop over particles... */
3450 PARTICLE_LOOP(0, atm->np, 0,
3451 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3452
3453 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
3454 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
3455 o3, lwc, rwc, iwc, swc, cc, z, zt;
3456
3457 /* Interpolate meteo data... */
3459 INTPOL_TIME_ALL(atm->time[ip], atm->p[ip], atm->lon[ip], atm->lat[ip]);
3460
3461 /* Set quantities... */
3462 SET_ATM(qnt_ps, ps);
3463 SET_ATM(qnt_ts, ts);
3464 SET_ATM(qnt_zs, zs);
3465 SET_ATM(qnt_us, us);
3466 SET_ATM(qnt_vs, vs);
3467 SET_ATM(qnt_ess, ess);
3468 SET_ATM(qnt_nss, nss);
3469 SET_ATM(qnt_shf, shf);
3470 SET_ATM(qnt_lsm, lsm);
3471 SET_ATM(qnt_sst, sst);
3472 SET_ATM(qnt_pbl, pbl);
3473 SET_ATM(qnt_pt, pt);
3474 SET_ATM(qnt_tt, tt);
3475 SET_ATM(qnt_zt, zt);
3476 SET_ATM(qnt_h2ot, h2ot);
3477 SET_ATM(qnt_zg, z);
3478 SET_ATM(qnt_p, atm->p[ip]);
3479 SET_ATM(qnt_t, t);
3480 SET_ATM(qnt_rho, RHO(atm->p[ip], t));
3481 SET_ATM(qnt_u, u);
3482 SET_ATM(qnt_v, v);
3483 SET_ATM(qnt_w, w);
3484 SET_ATM(qnt_h2o, h2o);
3485 SET_ATM(qnt_o3, o3);
3486 SET_ATM(qnt_lwc, lwc);
3487 SET_ATM(qnt_rwc, rwc);
3488 SET_ATM(qnt_iwc, iwc);
3489 SET_ATM(qnt_swc, swc);
3490 SET_ATM(qnt_cc, cc);
3491 SET_ATM(qnt_pct, pct);
3492 SET_ATM(qnt_pcb, pcb);
3493 SET_ATM(qnt_cl, cl);
3494 SET_ATM(qnt_plcl, plcl);
3495 SET_ATM(qnt_plfc, plfc);
3496 SET_ATM(qnt_pel, pel);
3497 SET_ATM(qnt_cape, cape);
3498 SET_ATM(qnt_cin, cin);
3499 SET_ATM(qnt_o3c, o3c);
3500 SET_ATM(qnt_hno3,
3501 clim_zm(&clim->hno3, atm->time[ip], atm->lat[ip], atm->p[ip]));
3502 SET_ATM(qnt_oh, clim_oh(ctl, clim, atm->time[ip],
3503 atm->lon[ip], atm->lat[ip], atm->p[ip]));
3504 SET_ATM(qnt_h2o2, clim_zm(&clim->h2o2, atm->time[ip],
3505 atm->lat[ip], atm->p[ip]));
3506 SET_ATM(qnt_ho2, clim_zm(&clim->ho2, atm->time[ip],
3507 atm->lat[ip], atm->p[ip]));
3508 SET_ATM(qnt_o1d, clim_zm(&clim->o1d, atm->time[ip],
3509 atm->lat[ip], atm->p[ip]));
3510 SET_ATM(qnt_vh, sqrt(u * u + v * v));
3511 SET_ATM(qnt_vz, -1e3 * H0 / atm->p[ip] * w);
3512 SET_ATM(qnt_psat, PSAT(t));
3513 SET_ATM(qnt_psice, PSICE(t));
3514 SET_ATM(qnt_pw, PW(atm->p[ip], h2o));
3515 SET_ATM(qnt_sh, SH(h2o));
3516 SET_ATM(qnt_rh, RH(atm->p[ip], t, h2o));
3517 SET_ATM(qnt_rhice, RHICE(atm->p[ip], t, h2o));
3518 SET_ATM(qnt_theta, THETA(atm->p[ip], t));
3519 SET_ATM(qnt_zeta, atm->q[ctl->qnt_zeta][ip]);
3520 SET_ATM(qnt_zeta_d, ZETA(ps, atm->p[ip], t));
3521 SET_ATM(qnt_tvirt, TVIRT(t, h2o));
3522 SET_ATM(qnt_lapse, lapse_rate(t, h2o));
3523 SET_ATM(qnt_pv, pv);
3524 SET_ATM(qnt_tdew, TDEW(atm->p[ip], h2o));
3525 SET_ATM(qnt_tice, TICE(atm->p[ip], h2o));
3526 SET_ATM(qnt_tnat,
3527 nat_temperature(atm->p[ip], h2o,
3528 clim_zm(&clim->hno3, atm->time[ip],
3529 atm->lat[ip], atm->p[ip])));
3530 SET_ATM(qnt_tsts,
3531 0.5 * (atm->q[ctl->qnt_tice][ip] + atm->q[ctl->qnt_tnat][ip]));
3532 }
3533}
double nat_temperature(const double p, const double h2o, const double hno3)
Calculates the nitric acid trihydrate (NAT) temperature.
Definition: mptrac.c:6221
double lapse_rate(const double t, const double h2o)
Calculates the moist adiabatic lapse rate in Kelvin per kilometer.
Definition: mptrac.c:1799
#define H0
Scale height [km].
Definition: mptrac.h:192
#define PSICE(t)
Compute saturation pressure over ice (WMO, 2018).
Definition: mptrac.h:1432
#define TICE(p, h2o)
Calculate frost point temperature (WMO, 2018).
Definition: mptrac.h:1700
#define RHICE(p, t, h2o)
Compute relative humidity over ice.
Definition: mptrac.h:1536
#define INTPOL_TIME_ALL(time, p, lon, lat)
Interpolate multiple meteorological variables in time.
Definition: mptrac.h:866
#define RH(p, t, h2o)
Compute relative humidity over water.
Definition: mptrac.h:1506
#define TDEW(p, h2o)
Calculate dew point temperature.
Definition: mptrac.h:1675
#define PSAT(t)
Compute saturation pressure over water.
Definition: mptrac.h:1408
clim_zm_t hno3
HNO3 zonal means.
Definition: mptrac.h:3427
int qnt_tnat
Quantity array index for T_NAT.
Definition: mptrac.h:2482
int qnt_tice
Quantity array index for T_ice.
Definition: mptrac.h:2476
int qnt_tsts
Quantity array index for T_STS.
Definition: mptrac.h:2479
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 3537 of file mptrac.c.

3541 {
3542
3543 /* Set timer... */
3544 SELECT_TIMER("MODULE_MIXING", "PHYSICS", NVTX_GPU);
3545
3546 /* Allocate... */
3547 const int np = atm->np;
3548 int *restrict const ixs = (int *) malloc((size_t) np * sizeof(int));
3549 int *restrict const iys = (int *) malloc((size_t) np * sizeof(int));
3550 int *restrict const izs = (int *) malloc((size_t) np * sizeof(int));
3551
3552 /* Set grid box size... */
3553 const double dz = (ctl->mixing_z1 - ctl->mixing_z0) / ctl->mixing_nz;
3554 const double dlon = (ctl->mixing_lon1 - ctl->mixing_lon0) / ctl->mixing_nx;
3555 const double dlat = (ctl->mixing_lat1 - ctl->mixing_lat0) / ctl->mixing_ny;
3556
3557 /* Set time interval... */
3558 const double t0 = t - 0.5 * ctl->dt_mod;
3559 const double t1 = t + 0.5 * ctl->dt_mod;
3560
3561 /* Get indices... */
3562#ifdef _OPENACC
3563#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
3564#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
3565#pragma acc parallel loop independent gang vector
3566#else
3567#pragma omp parallel for default(shared)
3568#endif
3569 for (int ip = 0; ip < np; ip++) {
3570 ixs[ip] = (int) ((atm->lon[ip] - ctl->mixing_lon0) / dlon);
3571 iys[ip] = (int) ((atm->lat[ip] - ctl->mixing_lat0) / dlat);
3572 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->mixing_z0) / dz);
3573 if (atm->time[ip] < t0 || atm->time[ip] > t1
3574 || ixs[ip] < 0 || ixs[ip] >= ctl->mixing_nx
3575 || iys[ip] < 0 || iys[ip] >= ctl->mixing_ny
3576 || izs[ip] < 0 || izs[ip] >= ctl->mixing_nz)
3577 izs[ip] = -1;
3578 }
3579
3580 /* Calculate interparcel mixing... */
3581 if (ctl->nens > 0) {
3582 if (ctl->qnt_m >= 0)
3583 module_mixing_help_ens(ctl, clim, atm, ixs, iys, izs, ctl->qnt_m);
3584 if (ctl->qnt_vmr >= 0)
3585 module_mixing_help_ens(ctl, clim, atm, ixs, iys, izs, ctl->qnt_vmr);
3586 if (ctl->qnt_Ch2o >= 0)
3587 module_mixing_help_ens(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Ch2o);
3588 if (ctl->qnt_Co3 >= 0)
3589 module_mixing_help_ens(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Co3);
3590 if (ctl->qnt_Cco >= 0)
3591 module_mixing_help_ens(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cco);
3592 if (ctl->qnt_Coh >= 0)
3593 module_mixing_help_ens(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Coh);
3594 if (ctl->qnt_Ch >= 0)
3595 module_mixing_help_ens(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Ch);
3596 if (ctl->qnt_Cho2 >= 0)
3597 module_mixing_help_ens(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cho2);
3598 if (ctl->qnt_Ch2o2 >= 0)
3599 module_mixing_help_ens(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Ch2o2);
3600 if (ctl->qnt_Co1d >= 0)
3601 module_mixing_help_ens(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Co1d);
3602 if (ctl->qnt_Co3p >= 0)
3603 module_mixing_help_ens(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Co3p);
3604 if (ctl->qnt_Cccl4 >= 0)
3605 module_mixing_help_ens(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cccl4);
3606 if (ctl->qnt_Cccl3f >= 0)
3607 module_mixing_help_ens(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cccl3f);
3608 if (ctl->qnt_Cccl2f2 >= 0)
3609 module_mixing_help_ens(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cccl2f2);
3610 if (ctl->qnt_Cn2o >= 0)
3611 module_mixing_help_ens(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cn2o);
3612 if (ctl->qnt_Csf6 >= 0)
3613 module_mixing_help_ens(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Csf6);
3614 if (ctl->qnt_aoa >= 0)
3615 module_mixing_help_ens(ctl, clim, atm, ixs, iys, izs, ctl->qnt_aoa);
3616 } else {
3617 if (ctl->qnt_m >= 0)
3618 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_m);
3619 if (ctl->qnt_vmr >= 0)
3620 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_vmr);
3621 if (ctl->qnt_Ch2o >= 0)
3622 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Ch2o);
3623 if (ctl->qnt_Co3 >= 0)
3624 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Co3);
3625 if (ctl->qnt_Cco >= 0)
3626 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cco);
3627 if (ctl->qnt_Coh >= 0)
3628 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Coh);
3629 if (ctl->qnt_Ch >= 0)
3630 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Ch);
3631 if (ctl->qnt_Cho2 >= 0)
3632 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cho2);
3633 if (ctl->qnt_Ch2o2 >= 0)
3634 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Ch2o2);
3635 if (ctl->qnt_Co1d >= 0)
3636 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Co1d);
3637 if (ctl->qnt_Co3p >= 0)
3638 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Co3p);
3639 if (ctl->qnt_Cccl4 >= 0)
3640 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cccl4);
3641 if (ctl->qnt_Cccl3f >= 0)
3642 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cccl3f);
3643 if (ctl->qnt_Cccl2f2 >= 0)
3644 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cccl2f2);
3645 if (ctl->qnt_Cn2o >= 0)
3646 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cn2o);
3647 if (ctl->qnt_Csf6 >= 0)
3648 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Csf6);
3649 if (ctl->qnt_aoa >= 0)
3650 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_aoa);
3651 }
3652
3653 /* Free... */
3654#ifdef _OPENACC
3655#pragma acc exit data delete(ixs,iys,izs)
3656#endif
3657 free(ixs);
3658 free(iys);
3659 free(izs);
3660}
void module_mixing_help_ens(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const int *ixs, const int *iys, const int *izs, const int qnt_idx)
Applies ensemble-based interparcel mixing for a given tracer quantity.
Definition: mptrac.c:3758
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:3664
int qnt_Coh
Quantity array index for OH volume mixing ratio (chemistry code).
Definition: mptrac.h:2497
int mixing_nx
Number of longitudes of mixing grid.
Definition: mptrac.h:2889
double mixing_z1
Upper altitude of mixing grid [km].
Definition: mptrac.h:2886
int qnt_Co1d
Quantity array index for O(1D) volume mixing ratio (chemistry code).
Definition: mptrac.h:2509
double mixing_z0
Lower altitude of mixing grid [km].
Definition: mptrac.h:2883
int qnt_Cco
Quantity array index for CO volume mixing ratio (chemistry code).
Definition: mptrac.h:2494
int mixing_ny
Number of latitudes of mixing grid.
Definition: mptrac.h:2898
int qnt_Ch
Quantity array index for H volume mixing ratio (chemistry code).
Definition: mptrac.h:2500
double mixing_lat0
Lower latitude of mixing grid [deg].
Definition: mptrac.h:2901
int qnt_Cho2
Quantity array index for HO2 volume mixing ratio (chemistry code).
Definition: mptrac.h:2503
int mixing_nz
Number of altitudes of mixing grid.
Definition: mptrac.h:2880
double mixing_lon0
Lower longitude of mixing grid [deg].
Definition: mptrac.h:2892
double mixing_lat1
Upper latitude of mixing grid [deg].
Definition: mptrac.h:2904
int qnt_Co3p
Quantity array index for O(3P) volume mixing ratio (chemistry code).
Definition: mptrac.h:2512
int qnt_Ch2o2
Quantity array index for H2O2 volume mixing ratio (chemistry code).
Definition: mptrac.h:2506
double mixing_lon1
Upper longitude of mixing grid [deg].
Definition: mptrac.h:2895
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 3664 of file mptrac.c.

3671 {
3672
3673 /* Allocate... */
3674 const int np = atm->np;
3675 const int ngrid = ctl->mixing_nx * ctl->mixing_ny * ctl->mixing_nz;
3676 double *restrict const cmean =
3677 (double *) malloc((size_t) ngrid * sizeof(double));
3678 int *restrict const count = (int *) malloc((size_t) ngrid * sizeof(int));
3679
3680 /* Init... */
3681#ifdef _OPENACC
3682#pragma acc enter data create(cmean[0:ngrid],count[0:ngrid])
3683#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
3684#pragma acc parallel loop independent gang vector
3685#else
3686#ifdef __NVCOMPILER
3687#pragma novector
3688#endif
3689#pragma omp parallel for
3690#endif
3691 for (int i = 0; i < ngrid; i++) {
3692 count[i] = 0;
3693 cmean[i] = 0;
3694 }
3695
3696 /* Loop over particles... */
3697#ifdef _OPENACC
3698#pragma acc parallel loop independent gang vector
3699#endif
3700 for (int ip = 0; ip < np; ip++)
3701 if (izs[ip] >= 0) {
3702 const int idx = ARRAY_3D
3703 (ixs[ip], iys[ip], ctl->mixing_ny, izs[ip], ctl->mixing_nz);
3704#ifdef _OPENACC
3705#pragma acc atomic update
3706#endif
3707 cmean[idx] += atm->q[qnt_idx][ip];
3708#ifdef _OPENACC
3709#pragma acc atomic update
3710#endif
3711 count[idx]++;
3712 }
3713#ifdef _OPENACC
3714#pragma acc parallel loop independent gang vector
3715#else
3716#ifdef __NVCOMPILER
3717#pragma novector
3718#endif
3719#pragma omp parallel for
3720#endif
3721 for (int i = 0; i < ngrid; i++)
3722 if (count[i] > 0)
3723 cmean[i] /= count[i];
3724
3725 /* Calculate interparcel mixing... */
3726#ifdef _OPENACC
3727#pragma acc parallel loop independent gang vector
3728#else
3729#pragma omp parallel for
3730#endif
3731 for (int ip = 0; ip < np; ip++)
3732 if (izs[ip] >= 0) {
3733
3734 /* Set mixing parameter... */
3735 double mixparam = 1.0;
3736 if (ctl->mixing_trop < 1 || ctl->mixing_strat < 1) {
3737 double w = tropo_weight(clim, atm, ip);
3738 mixparam = w * ctl->mixing_trop + (1 - w) * ctl->mixing_strat;
3739 }
3740
3741 /* Adjust quantity... */
3742 atm->q[qnt_idx][ip] +=
3743 (cmean
3744 [ARRAY_3D(ixs[ip], iys[ip], ctl->mixing_ny, izs[ip], ctl->mixing_nz)]
3745 - atm->q[qnt_idx][ip]) * mixparam;
3746 }
3747
3748 /* Free... */
3749#ifdef _OPENACC
3750#pragma acc exit data delete(cmean,count)
3751#endif
3752 free(cmean);
3753 free(count);
3754}
double mixing_trop
Interparcel exchange parameter for mixing in the troposphere.
Definition: mptrac.h:2874
double mixing_strat
Interparcel exchange parameter for mixing in the stratosphere.
Definition: mptrac.h:2877
Here is the call graph for this function:

◆ module_mixing_help_ens()

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

Applies ensemble-based interparcel mixing for a given tracer quantity.

This function calculates local grid-cell averages of a specified tracer quantity (qnt_idx) across ensemble members, and then applies a mixing adjustment to each atmospheric parcel based on the difference between its value and the mean within its grid cell.

Parameters
ctlPointer to the model control structure, containing mixing configuration and grid dimensions.
climPointer to climatological data used to determine tropospheric weighting, if applicable.
atmPointer to the structure containing atmospheric parcel data, including tracer fields.
ixsArray of X-indices mapping parcels to grid cells in the horizontal (longitude) direction.
iysArray of Y-indices mapping parcels to grid cells in the horizontal (latitude) direction.
izsArray of Z-indices mapping parcels to vertical levels; negative values indicate invalid/masked parcels.
qnt_idxIndex of the tracer quantity in the atm->q array to be mixed.

The function performs the following steps:

  • Initializes temporary arrays for computing ensemble-mean tracer concentrations and parcel counts.
  • Loops over all parcels to accumulate tracer values and counts into their corresponding grid cells.
  • Computes the ensemble mean of the tracer for each populated grid cell.
  • Applies a linear relaxation of parcel tracer values toward the ensemble mean using a mixing parameter. The mixing strength can vary between troposphere and stratosphere, depending on ctl->mixing_trop and ctl->mixing_strat. If those values are < 1, a weighted average based on the parcel's vertical position (via tropo_weight()) is used.
Note
  • Memory is dynamically allocated and freed within the function.
  • The grid is assumed to be 3D (nx × ny × nz), and calculations are performed per ensemble member.
  • Parallelization is supported through OpenMP or OpenACC for improved performance.
Warning
Parcels with izs[ip] < 0 are excluded from processing.
Authors
Mingzhao Liu

Definition at line 3758 of file mptrac.c.

3765 {
3766
3767 /* Allocate... */
3768 const int np = atm->np;
3769 const int ngrid = ctl->mixing_nx * ctl->mixing_ny * ctl->mixing_nz;
3770 double *restrict const cmean =
3771 (double *) malloc((size_t) ngrid * (size_t) ctl->nens * sizeof(double));
3772 int *restrict const count =
3773 (int *) malloc((size_t) ngrid * (size_t) ctl->nens * sizeof(int));
3774
3775 /* Init... */
3776#ifdef _OPENACC
3777#pragma acc enter data create(cmean[0:ngrid],count[0:ngrid])
3778#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
3779#pragma acc parallel loop independent gang vector
3780#else
3781#ifdef __NVCOMPILER
3782#pragma novector
3783#endif
3784#pragma omp parallel for
3785#endif
3786 for (int i = 0; i < ngrid * ctl->nens; i++) {
3787 count[i] = 0;
3788 cmean[i] = 0;
3789 }
3790
3791 /* Loop over particles... */
3792#ifdef _OPENACC
3793#pragma acc parallel loop independent gang vector
3794#endif
3795 for (int ip = 0; ip < np; ip++)
3796 if (izs[ip] >= 0) {
3797 const int ens = (int) atm->q[ctl->qnt_ens][ip];
3798 const int idx = ens * ngrid + ARRAY_3D
3799 (ixs[ip], iys[ip], ctl->mixing_ny, izs[ip], ctl->mixing_nz);
3800#ifdef _OPENACC
3801#pragma acc atomic update
3802#endif
3803 cmean[idx] += atm->q[qnt_idx][ip];
3804#ifdef _OPENACC
3805#pragma acc atomic update
3806#endif
3807 count[idx]++;
3808 }
3809#ifdef _OPENACC
3810#pragma acc parallel loop independent gang vector
3811#else
3812#ifdef __NVCOMPILER
3813#pragma novector
3814#endif
3815#pragma omp parallel for
3816#endif
3817 for (int i = 0; i < ngrid * ctl->nens; i++)
3818 if (count[i] > 0)
3819 cmean[i] /= count[i];
3820
3821 /* Calculate interparcel mixing... */
3822#ifdef _OPENACC
3823#pragma acc parallel loop independent gang vector
3824#else
3825#pragma omp parallel for
3826#endif
3827 for (int ip = 0; ip < np; ip++)
3828 if (izs[ip] >= 0) {
3829
3830 int ens = (int) atm->q[ctl->qnt_ens][ip];
3831 /* Set mixing parameter... */
3832 double mixparam = 1.0;
3833 if (ctl->mixing_trop < 1 || ctl->mixing_strat < 1) {
3834 double w = tropo_weight(clim, atm, ip);
3835 mixparam = w * ctl->mixing_trop + (1 - w) * ctl->mixing_strat;
3836 }
3837
3838 /* Adjust quantity... */
3839 atm->q[qnt_idx][ip] +=
3840 (cmean
3841 [ens * ngrid +
3842 ARRAY_3D(ixs[ip], iys[ip], ctl->mixing_ny, izs[ip], ctl->mixing_nz)]
3843 - atm->q[qnt_idx][ip]) * mixparam;
3844 }
3845
3846 /* Free... */
3847#ifdef _OPENACC
3848#pragma acc exit data delete(cmean,count)
3849#endif
3850 free(cmean);
3851 free(count);
3852}
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 3856 of file mptrac.c.

3862 {
3863
3864 /* Set timer... */
3865 SELECT_TIMER("MODULE_OH_CHEM", "PHYSICS", NVTX_GPU);
3866
3867 /* Check quantity flags... */
3868 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
3869 ERRMSG("Module needs quantity mass or volume mixing ratio!");
3870
3871 /* Parameter of SO2 correction... */
3872 const double a = 4.71572206e-08;
3873 const double b = -8.28782867e-01;
3874 const double low = pow(1. / a, 1. / b);
3875
3876 /* Loop over particles... */
3877 PARTICLE_LOOP(0, atm->np, 1,
3878 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3879
3880 /* Get temperature... */
3881 double t;
3883 INTPOL_3D(t, 1);
3884
3885 /* Calculate molecular density... */
3886 const double M = MOLEC_DENS(atm->p[ip], t);
3887
3888 /* Use constant reaction rate... */
3889 double k = NAN;
3890 if (ctl->oh_chem_reaction == 1)
3891 k = ctl->oh_chem[0];
3892
3893 /* Calculate bimolecular reaction rate... */
3894 else if (ctl->oh_chem_reaction == 2)
3895 k = ctl->oh_chem[0] * exp(-ctl->oh_chem[1] / t);
3896
3897 /* Calculate termolecular reaction rate... */
3898 if (ctl->oh_chem_reaction == 3) {
3899
3900 /* Calculate rate coefficient for X + OH + M -> XOH + M
3901 (JPL Publication 19-05) ... */
3902 const double k0 =
3903 ctl->oh_chem[0] * (ctl->oh_chem[1] !=
3904 0 ? pow(298. / t, ctl->oh_chem[1]) : 1.);
3905 const double ki =
3906 ctl->oh_chem[2] * (ctl->oh_chem[3] !=
3907 0 ? pow(298. / t, ctl->oh_chem[3]) : 1.);
3908 const double c = log10(k0 * M / ki);
3909 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
3910 }
3911
3912 /* Correction factor for high SO2 concentration
3913 (if qnt_Cx is defined, the correction is switched on)... */
3914 double cor = 1;
3915 if (ctl->qnt_Cx >= 0)
3916 cor =
3917 atm->q[ctl->qnt_Cx][ip] >
3918 low ? a * pow(atm->q[ctl->qnt_Cx][ip], b) : 1;
3919
3920 /* Calculate exponential decay... */
3921 const double rate_coef =
3922 k * clim_oh(ctl, clim, atm->time[ip], atm->lon[ip],
3923 atm->lat[ip], atm->p[ip]) * M * cor;
3924 const double aux = exp(-cache->dt[ip] * rate_coef);
3925 if (ctl->qnt_m >= 0) {
3926 if (ctl->qnt_mloss_oh >= 0)
3927 atm->q[ctl->qnt_mloss_oh][ip]
3928 += atm->q[ctl->qnt_m][ip] * (1 - aux);
3929 atm->q[ctl->qnt_m][ip] *= aux;
3930 if (ctl->qnt_loss_rate >= 0)
3931 atm->q[ctl->qnt_loss_rate][ip] += rate_coef;
3932 }
3933 if (ctl->qnt_vmr >= 0)
3934 atm->q[ctl->qnt_vmr][ip] *= aux;
3935 }
3936}
double oh_chem[4]
Coefficients for OH reaction rate (A, E/R or k0, n, kinf, m).
Definition: mptrac.h:2937
int oh_chem_reaction
Reaction type for OH chemistry (0=none, 2=bimolecular, 3=termolecular).
Definition: mptrac.h:2934
int qnt_mloss_oh
Quantity array index for total mass loss due to OH chemistry.
Definition: mptrac.h:2410
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 3940 of file mptrac.c.

3944 {
3945
3946 /* Set timer... */
3947 SELECT_TIMER("MODULE_POSITION", "PHYSICS", NVTX_GPU);
3948
3949 /* Loop over particles... */
3950 PARTICLE_LOOP(0, atm->np, 1, "acc data present(cache,met0,met1,atm)") {
3951
3952 /* Init... */
3953 double ps;
3955
3956 /* Calculate modulo... */
3957 atm->lon[ip] = FMOD(atm->lon[ip], 360.);
3958 atm->lat[ip] = FMOD(atm->lat[ip], 360.);
3959
3960 /* Check latitude... */
3961 while (atm->lat[ip] < -90 || atm->lat[ip] > 90) {
3962 if (atm->lat[ip] > 90) {
3963 atm->lat[ip] = 180 - atm->lat[ip];
3964 atm->lon[ip] += 180;
3965 }
3966 if (atm->lat[ip] < -90) {
3967 atm->lat[ip] = -180 - atm->lat[ip];
3968 atm->lon[ip] += 180;
3969 }
3970 }
3971
3972 /* Check longitude... */
3973 while (atm->lon[ip] < -180)
3974 atm->lon[ip] += 360;
3975 while (atm->lon[ip] >= 180)
3976 atm->lon[ip] -= 360;
3977
3978 /* Check pressure... */
3979 if (atm->p[ip] < met0->p[met0->np - 1]) {
3980 atm->p[ip] = met0->p[met0->np - 1];
3981 } else if (atm->p[ip] > 300.) {
3982 INTPOL_2D(ps, 1);
3983 if (atm->p[ip] > ps)
3984 atm->p[ip] = ps;
3985 }
3986 }
3987}

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

3992 {
3993
3994 /* Initialize GSL random number generators... */
3995 gsl_rng_env_setup();
3996 if (omp_get_max_threads() > NTHREADS)
3997 ERRMSG("Too many threads!");
3998 for (int i = 0; i < NTHREADS; i++) {
3999 rng[i] = gsl_rng_alloc(gsl_rng_default);
4000 gsl_rng_set(rng[i], gsl_rng_default_seed
4001 + (long unsigned) (ntask * NTHREADS + i));
4002 }
4003
4004 /* Initialize cuRAND random number generators... */
4005#ifdef CURAND
4006 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
4007 CURAND_STATUS_SUCCESS)
4008 ERRMSG("Cannot create random number generator!");
4009 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
4010 CURAND_STATUS_SUCCESS)
4011 ERRMSG("Cannot set seed for random number generator!");
4012 if (curandSetStream
4013 (rng_curand,
4014 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
4015 CURAND_STATUS_SUCCESS)
4016 ERRMSG("Cannot set stream for random number generator!");
4017#endif
4018}
#define NTHREADS
Maximum number of OpenMP threads.
Definition: mptrac.h:301

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

4026 {
4027
4028 /* Use GSL random number generators... */
4029 if (ctl->rng_type == 0) {
4030
4031 /* Uniform distribution... */
4032 if (method == 0) {
4033#pragma omp parallel for default(shared)
4034 for (size_t i = 0; i < n; ++i)
4035 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
4036 }
4037
4038 /* Normal distribution... */
4039 else if (method == 1) {
4040#pragma omp parallel for default(shared)
4041 for (size_t i = 0; i < n; ++i)
4042 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
4043 }
4044
4045 /* Update of random numbers on device... */
4046#ifdef _OPENACC
4047 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
4048#pragma acc update device(rs[:n])
4049#endif
4050 }
4051
4052 /* Use Squares random number generator (Widynski, 2022)... */
4053 else if (ctl->rng_type == 1) {
4054
4055 /* Set key (don't change this!)... */
4056 const uint64_t key = 0xc8e4fd154ce32f6d;
4057
4058 /* Uniform distribution... */
4059#ifdef _OPENACC
4060#pragma acc data present(rs)
4061#pragma acc parallel loop independent gang vector
4062#else
4063#pragma omp parallel for default(shared)
4064#endif
4065 for (size_t i = 0; i < n + 1; ++i) {
4066 uint64_t r, t, x, y, z;
4067 y = x = (rng_ctr + i) * key;
4068 z = y + key;
4069 x = x * x + y;
4070 x = (x >> 32) | (x << 32);
4071 x = x * x + z;
4072 x = (x >> 32) | (x << 32);
4073 x = x * x + y;
4074 x = (x >> 32) | (x << 32);
4075 t = x = x * x + z;
4076 x = (x >> 32) | (x << 32);
4077 r = t ^ ((x * x + y) >> 32);
4078 rs[i] = (double) r / (double) UINT64_MAX;
4079 }
4080 rng_ctr += n + 1;
4081
4082 /* Normal distribution... */
4083 if (method == 1) {
4084#ifdef _OPENACC
4085#pragma acc parallel loop independent gang vector
4086#else
4087#pragma omp parallel for default(shared)
4088#endif
4089 for (size_t i = 0; i < n; i += 2) {
4090 const double r = sqrt(-2.0 * log(rs[i]));
4091 const double phi = 2.0 * M_PI * rs[i + 1];
4092 rs[i] = r * cosf((float) phi);
4093 rs[i + 1] = r * sinf((float) phi);
4094 }
4095 }
4096 }
4097
4098 /* Use cuRAND random number generators... */
4099 else if (ctl->rng_type == 2) {
4100#ifdef CURAND
4101#pragma acc host_data use_device(rs)
4102 {
4103
4104 /* Uniform distribution... */
4105 if (method == 0) {
4106 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
4107 CURAND_STATUS_SUCCESS)
4108 ERRMSG("Cannot create random numbers!");
4109 }
4110
4111 /* Normal distribution... */
4112 else if (method == 1) {
4113 if (curandGenerateNormalDouble
4114 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
4115 1.0) != CURAND_STATUS_SUCCESS)
4116 ERRMSG("Cannot create random numbers!");
4117 }
4118 }
4119#else
4120 ERRMSG("MPTRAC was compiled without cuRAND!");
4121#endif
4122 }
4123}
int rng_type
Random number generator (0=GSL, 1=Squares, 2=cuRAND).
Definition: mptrac.h:2742

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

4132 {
4133
4134 /* Set timer... */
4135 SELECT_TIMER("MODULE_SEDI", "PHYSICS", NVTX_GPU);
4136
4137 /* Loop over particles... */
4138 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
4139
4140 /* Get temperature... */
4141 double t;
4143 INTPOL_3D(t, 1);
4144
4145 /* Sedimentation velocity... */
4146 const double v_s = sedi(atm->p[ip], t, atm->q[ctl->qnt_rp][ip],
4147 atm->q[ctl->qnt_rhop][ip]);
4148
4149 /* Calculate pressure change... */
4150 atm->p[ip] += DZ2DP(v_s * cache->dt[ip] / 1000., atm->p[ip]);
4151 }
4152}
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 4156 of file mptrac.c.

4159 {
4160
4161 /* Set timer... */
4162 SELECT_TIMER("MODULE_SORT", "PHYSICS", NVTX_GPU);
4163
4164 /* Allocate... */
4165 const int np = atm->np;
4166 double *restrict const a = (double *) malloc((size_t) np * sizeof(double));
4167 int *restrict const p = (int *) malloc((size_t) np * sizeof(int));
4168
4169#ifdef _OPENACC
4170#pragma acc enter data create(a[0:np],p[0:np])
4171#pragma acc data present(ctl,met0,atm,a,p)
4172#endif
4173
4174 /* Get box index... */
4175#ifdef _OPENACC
4176#pragma acc parallel loop independent gang vector
4177#else
4178#pragma omp parallel for default(shared)
4179#endif
4180 for (int ip = 0; ip < np; ip++) {
4181 a[ip] =
4182 (double) ((locate_reg(met0->lon, met0->nx, atm->lon[ip]) * met0->ny +
4183 locate_irr(met0->lat, met0->ny, atm->lat[ip]))
4184 * met0->np + locate_irr(met0->p, met0->np, atm->p[ip]));
4185 p[ip] = ip;
4186 }
4187
4188 /* Sorting... */
4189#ifdef _OPENACC
4190#pragma acc host_data use_device(a,p)
4191#endif
4192#ifdef THRUST
4193 thrustSortWrapper(a, np, p);
4194#else
4195 ERRMSG("MPTRAC was compiled without Thrust library!");
4196#endif
4197
4198 /* Sort data... */
4199 module_sort_help(atm->time, p, np);
4200 module_sort_help(atm->p, p, np);
4201 module_sort_help(atm->lon, p, np);
4202 module_sort_help(atm->lat, p, np);
4203 for (int iq = 0; iq < ctl->nq; iq++)
4204 module_sort_help(atm->q[iq], p, np);
4205
4206 /* Free... */
4207#ifdef _OPENACC
4208#pragma acc exit data delete(a,p)
4209#endif
4210 free(a);
4211 free(p);
4212}
void module_sort_help(double *a, const int *p, const int np)
Reorder an array based on a given permutation.
Definition: mptrac.c:4216
void thrustSortWrapper(double *__restrict__ c, int n, int *__restrict__ index)
Wrapper to Thrust sorting function.
int nq
Number of quantities.
Definition: mptrac.h:2245
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 4216 of file mptrac.c.

4219 {
4220
4221 /* Allocate... */
4222 double *restrict const help =
4223 (double *) malloc((size_t) np * sizeof(double));
4224
4225 /* Reordering of array... */
4226#ifdef _OPENACC
4227#pragma acc enter data create(help[0:np])
4228#pragma acc data present(a,p,help)
4229#pragma acc parallel loop independent gang vector
4230#else
4231#pragma omp parallel for default(shared)
4232#endif
4233 for (int ip = 0; ip < np; ip++)
4234 help[ip] = a[p[ip]];
4235#ifdef _OPENACC
4236#pragma acc parallel loop independent gang vector
4237#else
4238#pragma omp parallel for default(shared)
4239#endif
4240 for (int ip = 0; ip < np; ip++)
4241 a[ip] = help[ip];
4242
4243 /* Free... */
4244#ifdef _OPENACC
4245#pragma acc exit data delete(help)
4246#endif
4247 free(help);
4248}

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

4257 {
4258
4259 /* Set timer... */
4260 SELECT_TIMER("MODULE_TIMESTEPS", "PHYSICS", NVTX_GPU);
4261
4262 const double latmin = gsl_stats_min(met0->lat, 1, (size_t) met0->ny),
4263 latmax = gsl_stats_max(met0->lat, 1, (size_t) met0->ny);
4264
4265 const int local =
4266 (fabs(met0->lon[met0->nx - 1] - met0->lon[0] - 360.0) >= 0.01);
4267
4268 /* Loop over particles... */
4269 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,cache,met0,atm)") {
4270
4271 /* Set time step for each air parcel... */
4272 if ((ctl->direction * (atm->time[ip] - ctl->t_start) >= 0
4273 && ctl->direction * (atm->time[ip] - ctl->t_stop) <= 0
4274 && ctl->direction * (atm->time[ip] - t) < 0))
4275 cache->dt[ip] = t - atm->time[ip];
4276 else
4277 cache->dt[ip] = 0.0;
4278
4279 /* Check horizontal boundaries of local meteo data... */
4280 if (local && (atm->lon[ip] <= met0->lon[0]
4281 || atm->lon[ip] >= met0->lon[met0->nx - 1]
4282 || atm->lat[ip] <= latmin || atm->lat[ip] >= latmax))
4283 cache->dt[ip] = 0.0;
4284 }
4285}
int direction
Direction flag (1=forward calculation, -1=backward calculation).
Definition: mptrac.h:2533
double t_stop
Stop time of simulation [s].
Definition: mptrac.h:2539
double t_start
Start time of simulation [s].
Definition: mptrac.h:2536

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

4291 {
4292
4293 /* Set timer... */
4294 SELECT_TIMER("MODULE_TIMESTEPS_INIT", "PHYSICS", NVTX_GPU);
4295
4296 /* Set start time... */
4297 if (ctl->direction == 1) {
4298 ctl->t_start = gsl_stats_min(atm->time, 1, (size_t) atm->np);
4299 if (ctl->t_stop > 1e99)
4300 ctl->t_stop = gsl_stats_max(atm->time, 1, (size_t) atm->np);
4301 } else {
4302 ctl->t_start = gsl_stats_max(atm->time, 1, (size_t) atm->np);
4303 if (ctl->t_stop > 1e99)
4304 ctl->t_stop = gsl_stats_min(atm->time, 1, (size_t) atm->np);
4305 }
4306
4307 /* Check time interval... */
4308 if (ctl->direction * (ctl->t_stop - ctl->t_start) <= 0)
4309 ERRMSG("Nothing to do! Check T_STOP and DIRECTION!");
4310
4311 /* Round start time... */
4312 if (ctl->direction == 1)
4313 ctl->t_start = floor(ctl->t_start / ctl->dt_mod) * ctl->dt_mod;
4314 else
4315 ctl->t_start = ceil(ctl->t_start / ctl->dt_mod) * ctl->dt_mod;
4316}

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

4326 {
4327
4328 /* Set timer... */
4329 SELECT_TIMER("MODULE_TRACER_CHEM", "PHYSICS", NVTX_GPU);
4330
4331 /* Loop over particles... */
4332 PARTICLE_LOOP(0, atm->np, 1,
4333 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4334
4335 /* Get temperature... */
4336 double t;
4338 INTPOL_3D(t, 1);
4339
4340 /* Get molecular density... */
4341 const double M = MOLEC_DENS(atm->p[ip], t);
4342
4343 /* Get total column ozone... */
4344 double o3c;
4345 INTPOL_2D(o3c, 1);
4346
4347 /* Get solar zenith angle... */
4348 const double sza = sza_calc(atm->time[ip], atm->lon[ip], atm->lat[ip]);
4349
4350 /* Get O(1D) volume mixing ratio... */
4351 const double o1d =
4352 clim_zm(&clim->o1d, atm->time[ip], atm->lat[ip], atm->p[ip]);
4353
4354 /* Reactions for CFC-10... */
4355 if (ctl->qnt_Cccl4 >= 0) {
4356 const double K_o1d = ARRHENIUS(3.30e-10, 0, t) * o1d * M;
4357 const double K_hv = clim_photo(clim->photo.ccl4, &(clim->photo),
4358 atm->p[ip], sza, o3c);
4359 atm->q[ctl->qnt_Cccl4][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4360 }
4361
4362 /* Reactions for CFC-11... */
4363 if (ctl->qnt_Cccl3f >= 0) {
4364 const double K_o1d = ARRHENIUS(2.30e-10, 0, t) * o1d * M;
4365 const double K_hv = clim_photo(clim->photo.ccl3f, &(clim->photo),
4366 atm->p[ip], sza, o3c);
4367 atm->q[ctl->qnt_Cccl3f][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4368 }
4369
4370 /* Reactions for CFC-12... */
4371 if (ctl->qnt_Cccl2f2 >= 0) {
4372 const double K_o1d = ARRHENIUS(1.40e-10, -25, t) * o1d * M;
4373 const double K_hv = clim_photo(clim->photo.ccl2f2, &(clim->photo),
4374 atm->p[ip], sza, o3c);
4375 atm->q[ctl->qnt_Cccl2f2][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4376 }
4377
4378 /* Reactions for N2O... */
4379 if (ctl->qnt_Cn2o >= 0) {
4380 const double K_o1d = ARRHENIUS(1.19e-10, -20, t) * o1d * M;
4381 const double K_hv = clim_photo(clim->photo.n2o, &(clim->photo),
4382 atm->p[ip], sza, o3c);
4383 atm->q[ctl->qnt_Cn2o][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4384 }
4385 }
4386}
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:431
double ccl2f2[CP][CSZA][CO3]
CCl2F2 photolysis rate [1/s].
Definition: mptrac.h:3328
double ccl3f[CP][CSZA][CO3]
CCl3F photolysis rate [1/s].
Definition: mptrac.h:3325
double n2o[CP][CSZA][CO3]
N2O photolysis rate [1/s].
Definition: mptrac.h:3319
double ccl4[CP][CSZA][CO3]
CCl4 photolysis rate [1/s].
Definition: mptrac.h:3322
clim_photo_t photo
Photolysis rates.
Definition: mptrac.h:3424
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 4390 of file mptrac.c.

4395 {
4396
4397 /* Set timer... */
4398 SELECT_TIMER("MODULE_WET_DEPO", "PHYSICS", NVTX_GPU);
4399
4400 /* Check quantity flags... */
4401 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
4402 ERRMSG("Module needs quantity mass or volume mixing ratio!");
4403
4404 /* Loop over particles... */
4405 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
4406
4407 /* Check whether particle is below cloud top... */
4408 double pct;
4410 INTPOL_2D(pct, 1);
4411 if (!isfinite(pct) || atm->p[ip] <= pct)
4412 continue;
4413
4414 /* Get cloud bottom pressure... */
4415 double pcb;
4416 INTPOL_2D(pcb, 0);
4417
4418 /* Estimate precipitation rate (Pisso et al., 2019)... */
4419 double cl;
4420 INTPOL_2D(cl, 0);
4421 const double Is =
4422 pow(1. / ctl->wet_depo_pre[0] * cl, 1. / ctl->wet_depo_pre[1]);
4423 if (Is < 0.01)
4424 continue;
4425
4426 /* Check whether particle is inside or below cloud... */
4427 double lwc, rwc, iwc, swc;
4428 INTPOL_3D(lwc, 1);
4429 INTPOL_3D(rwc, 0);
4430 INTPOL_3D(iwc, 0);
4431 INTPOL_3D(swc, 0);
4432 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
4433
4434 /* Get temperature... */
4435 double t;
4436 INTPOL_3D(t, 0);
4437
4438 /* Calculate in-cloud scavenging coefficient... */
4439 double lambda = 0;
4440 if (inside) {
4441
4442 /* Calculate retention factor... */
4443 double eta;
4444 if (t > 273.15)
4445 eta = 1;
4446 else if (t <= 238.15)
4447 eta = ctl->wet_depo_ic_ret_ratio;
4448 else
4449 eta = LIN(273.15, 1, 238.15, ctl->wet_depo_ic_ret_ratio, t);
4450
4451 /* Use exponential dependency for particles (Bakels et al., 2024)... */
4452 if (ctl->wet_depo_ic_a > 0)
4453 lambda = ctl->wet_depo_ic_a * pow(Is, ctl->wet_depo_ic_b) * eta;
4454
4455 /* Use Henry's law for gases... */
4456 else if (ctl->wet_depo_ic_h[0] > 0) {
4457
4458 /* Get Henry's constant (Burkholder et al., 2019; Sander, 2023)... */
4459 double h = ctl->wet_depo_ic_h[0]
4460 * exp(ctl->wet_depo_ic_h[1] * (1. / t - 1. / 298.15));
4461
4462 /* Use effective Henry's constant for SO2
4463 (Berglen, 2004; Simpson, 2012)... */
4464 if (ctl->wet_depo_so2_ph > 0) {
4465 const double H_ion = pow(10., -ctl->wet_depo_so2_ph);
4466 const double K_1 = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
4467 const double K_2 = 6e-8 * exp(1.12e3 * (1. / t - 1. / 298.15));
4468 h *= (1. + K_1 / H_ion + K_1 * K_2 / SQR(H_ion));
4469 }
4470
4471 /* Estimate depth of cloud layer... */
4472 const double dz = 1e3 * (Z(pct) - Z(pcb));
4473
4474 /* Calculate scavenging coefficient... */
4475 lambda = h * RI * t * Is / 3.6e6 / dz * eta;
4476 }
4477 }
4478
4479 /* Calculate below-cloud scavenging coefficient... */
4480 else {
4481
4482 /* Calculate retention factor... */
4483 double eta;
4484 if (t > 270)
4485 eta = 1;
4486 else
4487 eta = ctl->wet_depo_bc_ret_ratio;
4488
4489 /* Use exponential dependency for particles (Bakels et al., 2024)... */
4490 if (ctl->wet_depo_bc_a > 0)
4491 lambda = ctl->wet_depo_bc_a * pow(Is, ctl->wet_depo_bc_b) * eta;
4492
4493 /* Use Henry's law for gases... */
4494 else if (ctl->wet_depo_bc_h[0] > 0) {
4495
4496 /* Get Henry's constant (Burkholder et al., 2019; Sander, 2023)... */
4497 const double h = ctl->wet_depo_bc_h[0]
4498 * exp(ctl->wet_depo_bc_h[1] * (1. / t - 1. / 298.15));
4499
4500 /* Estimate depth of cloud layer... */
4501 const double dz = 1e3 * (Z(pct) - Z(pcb));
4502
4503 /* Calculate scavenging coefficient... */
4504 lambda = h * RI * t * Is / 3.6e6 / dz * eta;
4505 }
4506 }
4507
4508 /* Calculate exponential decay of mass... */
4509 const double aux = exp(-cache->dt[ip] * lambda);
4510 if (ctl->qnt_m >= 0) {
4511 if (ctl->qnt_mloss_wet >= 0)
4512 atm->q[ctl->qnt_mloss_wet][ip]
4513 += atm->q[ctl->qnt_m][ip] * (1 - aux);
4514 atm->q[ctl->qnt_m][ip] *= aux;
4515 if (ctl->qnt_loss_rate >= 0)
4516 atm->q[ctl->qnt_loss_rate][ip] += lambda;
4517 }
4518 if (ctl->qnt_vmr >= 0)
4519 atm->q[ctl->qnt_vmr][ip] *= aux;
4520 }
4521}
double wet_depo_ic_a
Coefficient A for wet deposition in cloud (exponential form).
Definition: mptrac.h:2964
double wet_depo_bc_a
Coefficient A for wet deposition below cloud (exponential form).
Definition: mptrac.h:2958
int qnt_mloss_wet
Quantity array index for total mass loss due to wet deposition.
Definition: mptrac.h:2419
double wet_depo_so2_ph
pH value used to calculate effective Henry constant of SO2.
Definition: mptrac.h:2976
double wet_depo_pre[2]
Coefficients for precipitation calculation.
Definition: mptrac.h:2955
double wet_depo_bc_h[2]
Coefficients for wet deposition below cloud (Henry's law: Hb, Cb).
Definition: mptrac.h:2973
double wet_depo_bc_ret_ratio
Coefficients for wet deposition below cloud: retention ratio.
Definition: mptrac.h:2982
double wet_depo_ic_h[2]
Coefficients for wet deposition in cloud (Henry's law: Hb, Cb).
Definition: mptrac.h:2970
double wet_depo_ic_ret_ratio
Coefficients for wet deposition in cloud: retention ratio.
Definition: mptrac.h:2979
double wet_depo_ic_b
Coefficient B for wet deposition in cloud (exponential form).
Definition: mptrac.h:2967
double wet_depo_bc_b
Coefficient B for wet deposition below cloud (exponential form).
Definition: mptrac.h:2961

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

4531 {
4532
4533 /* Initialize GPU... */
4534#ifdef _OPENACC
4535 SELECT_TIMER("ACC_INIT", "INIT", NVTX_GPU);
4536 int rank = 0;
4537#ifdef MPI
4538 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
4539#endif
4540 if (acc_get_num_devices(acc_device_nvidia) <= 0)
4541 ERRMSG("Not running on a GPU device!");
4542 acc_set_device_num(rank % acc_get_num_devices(acc_device_nvidia),
4543 acc_device_nvidia);
4544 acc_device_t device_type = acc_get_device_type();
4545 acc_init(device_type);
4546#endif
4547
4548 /* Allocate... */
4549 SELECT_TIMER("ALLOC", "MEMORY", NVTX_CPU);
4550 ALLOC(*ctl, ctl_t, 1);
4551 ALLOC(*cache, cache_t, 1);
4552 ALLOC(*clim, clim_t, 1);
4553 ALLOC(*met0, met_t, 1);
4554 ALLOC(*met1, met_t, 1);
4555 ALLOC(*atm, atm_t, 1);
4556
4557 /* Create data region on GPU... */
4558#ifdef _OPENACC
4559 SELECT_TIMER("CREATE_DATA_REGION", "MEMORY", NVTX_GPU);
4560 ctl_t *ctlup = *ctl;
4561 cache_t *cacheup = *cache;
4562 clim_t *climup = *clim;
4563 met_t *met0up = *met0;
4564 met_t *met1up = *met1;
4565 atm_t *atmup = *atm;
4566#pragma acc enter data create(ctlup[:1],cacheup[:1],climup[:1],met0up[:1],met1up[:1],atmup[:1])
4567#endif
4568}
Air parcel data.
Definition: mptrac.h:3238
Cache data structure.
Definition: mptrac.h:3266
Climatological data.
Definition: mptrac.h:3406
Control parameters.
Definition: mptrac.h:2238
Meteo data structure.
Definition: mptrac.h:3465

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

4578 {
4579
4580 /* Delete data region on GPU... */
4581#ifdef _OPENACC
4582 SELECT_TIMER("DELETE_DATA_REGION", "MEMORY", NVTX_GPU);
4583#pragma acc exit data delete (ctl,cache,clim,met0,met1,atm)
4584#endif
4585
4586 /* Free... */
4587 SELECT_TIMER("FREE", "MEMORY", NVTX_CPU);
4588 free(atm);
4589 free(ctl);
4590 free(cache);
4591 free(clim);
4592 free(met0);
4593 free(met1);
4594}

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

4603 {
4604
4605 static int init;
4606
4607 met_t *mets;
4608
4609 char cachefile[LEN], cmd[2 * LEN], filename[LEN];
4610
4611 /* Set timer... */
4612 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4613
4614 /* Init... */
4615 if (t == ctl->t_start || !init) {
4616 init = 1;
4617
4618 /* Read meteo data... */
4619 get_met_help(ctl, t + (ctl->direction == -1 ? -1 : 0), -1,
4620 ctl->metbase, ctl->dt_met, filename);
4621 if (!mptrac_read_met(filename, ctl, clim, *met0))
4622 ERRMSG("Cannot open file!");
4623
4624 get_met_help(ctl, t + (ctl->direction == 1 ? 1 : 0), 1,
4625 ctl->metbase, ctl->dt_met, filename);
4626 if (!mptrac_read_met(filename, ctl, clim, *met1))
4627 ERRMSG("Cannot open file!");
4628
4629 /* Update GPU... */
4630 mptrac_update_device(NULL, NULL, NULL, met0, met1, NULL);
4631 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4632
4633 /* Caching... */
4634 if (ctl->met_cache && t != ctl->t_stop) {
4635 get_met_help(ctl, t + 1.1 * ctl->dt_met * ctl->direction,
4636 ctl->direction, ctl->metbase, ctl->dt_met, cachefile);
4637 sprintf(cmd, "cat %s > /dev/null &", cachefile);
4638 LOG(1, "Caching: %s", cachefile);
4639 if (system(cmd) != 0)
4640 WARN("Caching command failed!");
4641 }
4642 }
4643
4644 /* Read new data for forward trajectories... */
4645 if (t > (*met1)->time) {
4646
4647 /* Pointer swap... */
4648 mets = *met1;
4649 *met1 = *met0;
4650 *met0 = mets;
4651
4652 /* Read new meteo data... */
4653 get_met_help(ctl, t, 1, ctl->metbase, ctl->dt_met, filename);
4654 if (!mptrac_read_met(filename, ctl, clim, *met1))
4655 ERRMSG("Cannot open file!");
4656
4657 /* Update GPU... */
4658 mptrac_update_device(NULL, NULL, NULL, NULL, met1, NULL);
4659 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4660
4661 /* Caching... */
4662 if (ctl->met_cache && t != ctl->t_stop) {
4663 get_met_help(ctl, t + ctl->dt_met, 1, ctl->metbase, ctl->dt_met,
4664 cachefile);
4665 sprintf(cmd, "cat %s > /dev/null &", cachefile);
4666 LOG(1, "Caching: %s", cachefile);
4667 if (system(cmd) != 0)
4668 WARN("Caching command failed!");
4669 }
4670 }
4671
4672 /* Read new data for backward trajectories... */
4673 if (t < (*met0)->time) {
4674
4675 /* Pointer swap... */
4676 mets = *met1;
4677 *met1 = *met0;
4678 *met0 = mets;
4679
4680 /* Read new meteo data... */
4681 get_met_help(ctl, t, -1, ctl->metbase, ctl->dt_met, filename);
4682 if (!mptrac_read_met(filename, ctl, clim, *met0))
4683 ERRMSG("Cannot open file!");
4684
4685 /* Update GPU... */
4686 mptrac_update_device(NULL, NULL, NULL, met0, NULL, NULL);
4687 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4688
4689 /* Caching... */
4690 if (ctl->met_cache && t != ctl->t_stop) {
4691 get_met_help(ctl, t - ctl->dt_met, -1, ctl->metbase, ctl->dt_met,
4692 cachefile);
4693 sprintf(cmd, "cat %s > /dev/null &", cachefile);
4694 LOG(1, "Caching: %s", cachefile);
4695 if (system(cmd) != 0)
4696 WARN("Caching command failed!");
4697 }
4698 }
4699
4700 /* Check that grids are consistent... */
4701 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
4702 if ((*met0)->nx != (*met1)->nx
4703 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
4704 ERRMSG("Meteo grid dimensions do not match!");
4705 for (int ix = 0; ix < (*met0)->nx; ix++)
4706 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
4707 ERRMSG("Meteo grid longitudes do not match!");
4708 for (int iy = 0; iy < (*met0)->ny; iy++)
4709 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
4710 ERRMSG("Meteo grid latitudes do not match!");
4711 for (int ip = 0; ip < (*met0)->np; ip++)
4712 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
4713 ERRMSG("Meteo grid pressure levels do not match!");
4714 }
4715}
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:5709
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:1048
int met_cache
Preload meteo data into disk cache (0=no, 1=yes).
Definition: mptrac.h:2715
char metbase[LEN]
Basename for meteo data.
Definition: mptrac.h:2549
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 4719 of file mptrac.c.

4724 {
4725
4726 /* Initialize timesteps... */
4727 module_timesteps_init(ctl, atm);
4728
4729 /* Initialize random number generator... */
4730 module_rng_init(ntask);
4731
4732 /* Update GPU memory... */
4733 mptrac_update_device(ctl, cache, clim, NULL, NULL, atm);
4734}
void module_timesteps_init(ctl_t *ctl, const atm_t *atm)
Initialize start time and time interval for time-stepping.
Definition: mptrac.c:4289
void module_rng_init(const int ntask)
Initialize random number generators for parallel tasks.
Definition: mptrac.c:3991
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 4738 of file mptrac.c.

4741 {
4742
4743 int result;
4744
4745 /* Set timer... */
4746 SELECT_TIMER("READ_ATM", "INPUT", NVTX_READ);
4747
4748 /* Init... */
4749 atm->np = 0;
4750
4751 /* Write info... */
4752 LOG(1, "Read atmospheric data: %s", filename);
4753
4754 /* Read ASCII data... */
4755 if (ctl->atm_type == 0)
4756 result = read_atm_asc(filename, ctl, atm);
4757
4758 /* Read binary data... */
4759 else if (ctl->atm_type == 1)
4760 result = read_atm_bin(filename, ctl, atm);
4761
4762 /* Read netCDF data... */
4763 else if (ctl->atm_type == 2)
4764 result = read_atm_nc(filename, ctl, atm);
4765
4766 /* Read CLaMS data... */
4767 else if (ctl->atm_type == 3 || ctl->atm_type == 4)
4768 result = read_atm_clams(filename, ctl, atm);
4769
4770 /* Error... */
4771 else
4772 ERRMSG("Atmospheric data type not supported!");
4773
4774 /* Check result... */
4775 if (result != 1)
4776 return 0;
4777
4778 /* Check number of air parcels... */
4779 if (atm->np < 1)
4780 ERRMSG("Can not read any data!");
4781
4782 /* Write info... */
4783 double mini, maxi;
4784 LOG(2, "Number of particles: %d", atm->np);
4785 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
4786 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
4787 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
4788 LOG(2, "Altitude range: %g ... %g km", Z(maxi), Z(mini));
4789 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
4790 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
4791 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
4792 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
4793 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
4794 for (int iq = 0; iq < ctl->nq; iq++) {
4795 char msg[5 * LEN];
4796 sprintf(msg, "Quantity %s range: %s ... %s %s",
4797 ctl->qnt_name[iq], ctl->qnt_format[iq],
4798 ctl->qnt_format[iq], ctl->qnt_unit[iq]);
4799 gsl_stats_minmax(&mini, &maxi, atm->q[iq], 1, (size_t) atm->np);
4800 LOG(2, msg, mini, maxi);
4801 }
4802
4803 /* Return success... */
4804 return 1;
4805}
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:6421
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:6309
int read_atm_clams(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads atmospheric data from a CLAMS NetCDF file.
Definition: mptrac.c:6365
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:6267
char qnt_format[NQ][LEN]
Quantity output format.
Definition: mptrac.h:2257
int atm_type
Type of atmospheric data files (0=ASCII, 1=binary, 2=netCDF, 3=CLaMS_traj, 4=CLaMS_pos).
Definition: mptrac.h:3017
char qnt_unit[NQ][LEN]
Quantity units.
Definition: mptrac.h:2254
char qnt_name[NQ][LEN]
Quantity names.
Definition: mptrac.h:2248
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 4809 of file mptrac.c.

4811 {
4812
4813 /* Set timer... */
4814 SELECT_TIMER("READ_CLIM", "INPUT", NVTX_READ);
4815
4816 /* Init tropopause climatology... */
4817 clim_tropo_init(clim);
4818
4819 /* Read photolysis rates... */
4820 if (ctl->clim_photo[0] != '-')
4821 read_clim_photo(ctl->clim_photo, &clim->photo);
4822
4823 /* Read HNO3 climatology... */
4824 if (ctl->clim_hno3_filename[0] != '-')
4825 read_clim_zm(ctl->clim_hno3_filename, "HNO3", &clim->hno3);
4826
4827 /* Read OH climatology... */
4828 if (ctl->clim_oh_filename[0] != '-') {
4829 read_clim_zm(ctl->clim_oh_filename, "OH", &clim->oh);
4830 if (ctl->oh_chem_beta > 0)
4831 clim_oh_diurnal_correction(ctl, clim);
4832 }
4833
4834 /* Read H2O2 climatology... */
4835 if (ctl->clim_h2o2_filename[0] != '-')
4836 read_clim_zm(ctl->clim_h2o2_filename, "H2O2", &clim->h2o2);
4837
4838 /* Read HO2 climatology... */
4839 if (ctl->clim_ho2_filename[0] != '-')
4840 read_clim_zm(ctl->clim_ho2_filename, "HO2", &clim->ho2);
4841
4842 /* Read O(1D) climatology... */
4843 if (ctl->clim_o1d_filename[0] != '-')
4844 read_clim_zm(ctl->clim_o1d_filename, "O1D", &clim->o1d);
4845
4846 /* Read CFC-10 time series... */
4847 if (ctl->clim_ccl4_timeseries[0] != '-')
4849
4850 /* Read CFC-11 time series... */
4851 if (ctl->clim_ccl3f_timeseries[0] != '-')
4853
4854 /* Read CFC-12 time series... */
4855 if (ctl->clim_ccl2f2_timeseries[0] != '-')
4857
4858 /* Read N2O time series... */
4859 if (ctl->clim_n2o_timeseries[0] != '-')
4860 read_clim_ts(ctl->clim_n2o_timeseries, &clim->n2o);
4861
4862 /* Read SF6 time series... */
4863 if (ctl->clim_sf6_timeseries[0] != '-')
4864 read_clim_ts(ctl->clim_sf6_timeseries, &clim->sf6);
4865}
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:6454
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:6573
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:6627
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:2847
char clim_o1d_filename[LEN]
Filename of O(1D) climatology.
Definition: mptrac.h:2850
char clim_photo[LEN]
Filename of photolysis rates climatology.
Definition: mptrac.h:2835
char clim_h2o2_filename[LEN]
Filename of H2O2 climatology.
Definition: mptrac.h:2844
char clim_oh_filename[LEN]
Filename of OH climatology.
Definition: mptrac.h:2841
char clim_hno3_filename[LEN]
Filename of HNO3 climatology.
Definition: mptrac.h:2838
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 4869 of file mptrac.c.

4873 {
4874
4875 /* Set timer... */
4876 SELECT_TIMER("READ_CTL", "INPUT", NVTX_READ);
4877
4878 /* Write info... */
4879 LOG(1, "\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
4880 "(executable: %s | version: %s | compiled: %s, %s)\n",
4881 argv[0], VERSION, __DATE__, __TIME__);
4882
4883 /* Initialize quantity indices... */
4884 ctl->qnt_idx = -1;
4885 ctl->qnt_ens = -1;
4886 ctl->qnt_stat = -1;
4887 ctl->qnt_m = -1;
4888 ctl->qnt_vmr = -1;
4889 ctl->qnt_rp = -1;
4890 ctl->qnt_rhop = -1;
4891 ctl->qnt_ps = -1;
4892 ctl->qnt_ts = -1;
4893 ctl->qnt_zs = -1;
4894 ctl->qnt_us = -1;
4895 ctl->qnt_vs = -1;
4896 ctl->qnt_ess = -1;
4897 ctl->qnt_nss = -1;
4898 ctl->qnt_shf = -1;
4899 ctl->qnt_lsm = -1;
4900 ctl->qnt_sst = -1;
4901 ctl->qnt_pbl = -1;
4902 ctl->qnt_pt = -1;
4903 ctl->qnt_tt = -1;
4904 ctl->qnt_zt = -1;
4905 ctl->qnt_h2ot = -1;
4906 ctl->qnt_zg = -1;
4907 ctl->qnt_p = -1;
4908 ctl->qnt_t = -1;
4909 ctl->qnt_rho = -1;
4910 ctl->qnt_u = -1;
4911 ctl->qnt_v = -1;
4912 ctl->qnt_w = -1;
4913 ctl->qnt_h2o = -1;
4914 ctl->qnt_o3 = -1;
4915 ctl->qnt_lwc = -1;
4916 ctl->qnt_rwc = -1;
4917 ctl->qnt_iwc = -1;
4918 ctl->qnt_swc = -1;
4919 ctl->qnt_cc = -1;
4920 ctl->qnt_pct = -1;
4921 ctl->qnt_pcb = -1;
4922 ctl->qnt_cl = -1;
4923 ctl->qnt_plcl = -1;
4924 ctl->qnt_plfc = -1;
4925 ctl->qnt_pel = -1;
4926 ctl->qnt_cape = -1;
4927 ctl->qnt_cin = -1;
4928 ctl->qnt_o3c = -1;
4929 ctl->qnt_hno3 = -1;
4930 ctl->qnt_oh = -1;
4931 ctl->qnt_h2o2 = -1;
4932 ctl->qnt_ho2 = -1;
4933 ctl->qnt_o1d = -1;
4934 ctl->qnt_mloss_oh = -1;
4935 ctl->qnt_mloss_h2o2 = -1;
4936 ctl->qnt_mloss_kpp = -1;
4937 ctl->qnt_mloss_wet = -1;
4938 ctl->qnt_mloss_dry = -1;
4939 ctl->qnt_mloss_decay = -1;
4940 ctl->qnt_loss_rate = -1;
4941 ctl->qnt_psat = -1;
4942 ctl->qnt_psice = -1;
4943 ctl->qnt_pw = -1;
4944 ctl->qnt_sh = -1;
4945 ctl->qnt_rh = -1;
4946 ctl->qnt_rhice = -1;
4947 ctl->qnt_theta = -1;
4948 ctl->qnt_zeta = -1;
4949 ctl->qnt_zeta_d = -1;
4950 ctl->qnt_tvirt = -1;
4951 ctl->qnt_lapse = -1;
4952 ctl->qnt_vh = -1;
4953 ctl->qnt_vz = -1;
4954 ctl->qnt_pv = -1;
4955 ctl->qnt_tdew = -1;
4956 ctl->qnt_tice = -1;
4957 ctl->qnt_tsts = -1;
4958 ctl->qnt_tnat = -1;
4959 ctl->qnt_Cx = -1;
4960 ctl->qnt_Ch2o = -1;
4961 ctl->qnt_Co3 = -1;
4962 ctl->qnt_Cco = -1;
4963 ctl->qnt_Coh = -1;
4964 ctl->qnt_Ch = -1;
4965 ctl->qnt_Cho2 = -1;
4966 ctl->qnt_Ch2o2 = -1;
4967 ctl->qnt_Co1d = -1;
4968 ctl->qnt_Co3p = -1;
4969 ctl->qnt_Cccl4 = -1;
4970 ctl->qnt_Cccl3f = -1;
4971 ctl->qnt_Cccl2f2 = -1;
4972 ctl->qnt_Cn2o = -1;
4973 ctl->qnt_Csf6 = -1;
4974 ctl->qnt_aoa = -1;
4975
4976 /* Read quantities... */
4977 ctl->nq = (int) scan_ctl(filename, argc, argv, "NQ", -1, "0", NULL);
4978 if (ctl->nq > NQ)
4979 ERRMSG("Too many quantities!");
4980 for (int iq = 0; iq < ctl->nq; iq++) {
4981
4982 /* Read quantity name and format... */
4983 scan_ctl(filename, argc, argv, "QNT_NAME", iq, "", ctl->qnt_name[iq]);
4984 scan_ctl(filename, argc, argv, "QNT_LONGNAME", iq, ctl->qnt_name[iq],
4985 ctl->qnt_longname[iq]);
4986 scan_ctl(filename, argc, argv, "QNT_FORMAT", iq, "%g",
4987 ctl->qnt_format[iq]);
4988 if (strcasecmp(ctl->qnt_name[iq], "aoa") == 0)
4989 sprintf(ctl->qnt_format[iq], "%%.2f");
4990
4991 /* Try to identify quantity... */
4992 SET_QNT(qnt_idx, "idx", "particle index", "-")
4993 SET_QNT(qnt_ens, "ens", "ensemble index", "-")
4994 SET_QNT(qnt_stat, "stat", "station flag", "-")
4995 SET_QNT(qnt_m, "m", "mass", "kg")
4996 SET_QNT(qnt_vmr, "vmr", "volume mixing ratio", "ppv")
4997 SET_QNT(qnt_rp, "rp", "particle radius", "microns")
4998 SET_QNT(qnt_rhop, "rhop", "particle density", "kg/m^3")
4999 SET_QNT(qnt_ps, "ps", "surface pressure", "hPa")
5000 SET_QNT(qnt_ts, "ts", "surface temperature", "K")
5001 SET_QNT(qnt_zs, "zs", "surface height", "km")
5002 SET_QNT(qnt_us, "us", "surface zonal wind", "m/s")
5003 SET_QNT(qnt_vs, "vs", "surface meridional wind", "m/s")
5004 SET_QNT(qnt_ess, "ess", "eastward turbulent surface stress", "N/m^2")
5005 SET_QNT(qnt_nss, "nss", "northward turbulent surface stress", "N/m^2")
5006 SET_QNT(qnt_shf, "shf", "surface sensible heat flux", "W/m^2")
5007 SET_QNT(qnt_lsm, "lsm", "land-sea mask", "1")
5008 SET_QNT(qnt_sst, "sst", "sea surface temperature", "K")
5009 SET_QNT(qnt_pbl, "pbl", "planetary boundary layer", "hPa")
5010 SET_QNT(qnt_pt, "pt", "tropopause pressure", "hPa")
5011 SET_QNT(qnt_tt, "tt", "tropopause temperature", "K")
5012 SET_QNT(qnt_zt, "zt", "tropopause geopotential height", "km")
5013 SET_QNT(qnt_h2ot, "h2ot", "tropopause water vapor", "ppv")
5014 SET_QNT(qnt_zg, "zg", "geopotential height", "km")
5015 SET_QNT(qnt_p, "p", "pressure", "hPa")
5016 SET_QNT(qnt_t, "t", "temperature", "K")
5017 SET_QNT(qnt_rho, "rho", "air density", "kg/m^3")
5018 SET_QNT(qnt_u, "u", "zonal wind", "m/s")
5019 SET_QNT(qnt_v, "v", "meridional wind", "m/s")
5020 SET_QNT(qnt_w, "w", "vertical velocity", "hPa/s")
5021 SET_QNT(qnt_h2o, "h2o", "water vapor", "ppv")
5022 SET_QNT(qnt_o3, "o3", "ozone", "ppv")
5023 SET_QNT(qnt_lwc, "lwc", "cloud liquid water content", "kg/kg")
5024 SET_QNT(qnt_rwc, "rwc", "cloud rain water content", "kg/kg")
5025 SET_QNT(qnt_iwc, "iwc", "cloud ice water content", "kg/kg")
5026 SET_QNT(qnt_swc, "swc", "cloud snow water content", "kg/kg")
5027 SET_QNT(qnt_cc, "cc", "cloud cover", "1")
5028 SET_QNT(qnt_pct, "pct", "cloud top pressure", "hPa")
5029 SET_QNT(qnt_pcb, "pcb", "cloud bottom pressure", "hPa")
5030 SET_QNT(qnt_cl, "cl", "total column cloud water", "kg/m^2")
5031 SET_QNT(qnt_plcl, "plcl", "lifted condensation level", "hPa")
5032 SET_QNT(qnt_plfc, "plfc", "level of free convection", "hPa")
5033 SET_QNT(qnt_pel, "pel", "equilibrium level", "hPa")
5034 SET_QNT(qnt_cape, "cape", "convective available potential energy",
5035 "J/kg")
5036 SET_QNT(qnt_cin, "cin", "convective inhibition", "J/kg")
5037 SET_QNT(qnt_o3c, "o3c", "total column ozone", "DU")
5038 SET_QNT(qnt_hno3, "hno3", "nitric acid", "ppv")
5039 SET_QNT(qnt_oh, "oh", "hydroxyl radical", "ppv")
5040 SET_QNT(qnt_h2o2, "h2o2", "hydrogen peroxide", "ppv")
5041 SET_QNT(qnt_ho2, "ho2", "hydroperoxyl radical", "ppv")
5042 SET_QNT(qnt_o1d, "o1d", "atomic oxygen", "ppv")
5043 SET_QNT(qnt_mloss_oh, "mloss_oh", "mass loss due to OH chemistry", "kg")
5044 SET_QNT(qnt_mloss_h2o2, "mloss_h2o2",
5045 "mass loss due to H2O2 chemistry", "kg")
5046 SET_QNT(qnt_mloss_kpp, "mloss_kpp", "mass loss due to kpp chemistry",
5047 "kg")
5048 SET_QNT(qnt_mloss_wet, "mloss_wet", "mass loss due to wet deposition",
5049 "kg")
5050 SET_QNT(qnt_mloss_dry, "mloss_dry", "mass loss due to dry deposition",
5051 "kg")
5052 SET_QNT(qnt_mloss_decay, "mloss_decay",
5053 "mass loss due to exponential decay", "kg")
5054 SET_QNT(qnt_loss_rate, "loss_rate", "total loss rate", "s^-1")
5055 SET_QNT(qnt_psat, "psat", "saturation pressure over water", "hPa")
5056 SET_QNT(qnt_psice, "psice", "saturation pressure over ice", "hPa")
5057 SET_QNT(qnt_pw, "pw", "partial water vapor pressure", "hPa")
5058 SET_QNT(qnt_sh, "sh", "specific humidity", "kg/kg")
5059 SET_QNT(qnt_rh, "rh", "relative humidity", "%%")
5060 SET_QNT(qnt_rhice, "rhice", "relative humidity over ice", "%%")
5061 SET_QNT(qnt_theta, "theta", "potential temperature", "K")
5062 SET_QNT(qnt_zeta, "zeta", "zeta coordinate", "K")
5063 SET_QNT(qnt_zeta_d, "zeta_d", "diagnosed zeta coordinate", "K")
5064 SET_QNT(qnt_tvirt, "tvirt", "virtual temperature", "K")
5065 SET_QNT(qnt_lapse, "lapse", "temperature lapse rate", "K/km")
5066 SET_QNT(qnt_vh, "vh", "horizontal velocity", "m/s")
5067 SET_QNT(qnt_vz, "vz", "vertical velocity", "m/s")
5068 SET_QNT(qnt_pv, "pv", "potential vorticity", "PVU")
5069 SET_QNT(qnt_tdew, "tdew", "dew point temperature", "K")
5070 SET_QNT(qnt_tice, "tice", "frost point temperature", "K")
5071 SET_QNT(qnt_tsts, "tsts", "STS existence temperature", "K")
5072 SET_QNT(qnt_tnat, "tnat", "NAT existence temperature", "K")
5073 SET_QNT(qnt_Cx, "Cx", "Trace species x volume mixing ratio", "ppv")
5074 SET_QNT(qnt_Ch2o, "Ch2o", "H2O volume mixing ratio", "ppv")
5075 SET_QNT(qnt_Co3, "Co3", "O3 volume mixing ratio", "ppv")
5076 SET_QNT(qnt_Cco, "Cco", "CO volume mixing ratio", "ppv")
5077 SET_QNT(qnt_Coh, "Coh", "HO volume mixing ratio", "ppv")
5078 SET_QNT(qnt_Ch, "Ch", "H radical volume mixing ratio", "ppv")
5079 SET_QNT(qnt_Cho2, "Cho2", "HO2 volume mixing ratio", "ppv")
5080 SET_QNT(qnt_Ch2o2, "Ch2o2", "H2O2 volume mixing ratio", "ppv")
5081 SET_QNT(qnt_Co1d, "Co1d", "O(1D) volume mixing ratio", "ppv")
5082 SET_QNT(qnt_Co3p, "Co3p", "O(3P) radical volume mixing ratio", "ppv")
5083 SET_QNT(qnt_Cccl4, "Cccl4", "CCl4 (CFC-10) volume mixing ratio", "ppv")
5084 SET_QNT(qnt_Cccl3f, "Cccl3f", "CCl3F (CFC-11) volume mixing ratio",
5085 "ppv")
5086 SET_QNT(qnt_Cccl2f2, "Cccl2f2", "CCl2F2 (CFC-12) volume mixing ratio",
5087 "ppv")
5088 SET_QNT(qnt_Cn2o, "Cn2o", "N2O volume mixing ratio", "ppv")
5089 SET_QNT(qnt_Csf6, "Csf6", "SF6 volume mixing ratio", "ppv")
5090 SET_QNT(qnt_aoa, "aoa", "age of air", "s")
5091 scan_ctl(filename, argc, argv, "QNT_UNIT", iq, "", ctl->qnt_unit[iq]);
5092 }
5093
5094 /* Vertical coordinates and velocities... */
5095 ctl->advect_vert_coord =
5096 (int) scan_ctl(filename, argc, argv, "ADVECT_VERT_COORD", -1, "0", NULL);
5097 if (ctl->advect_vert_coord < 0 || ctl->advect_vert_coord > 2)
5098 ERRMSG("Set ADVECT_VERT_COORD to 0, 1, or 2!");
5099 ctl->met_vert_coord =
5100 (int) scan_ctl(filename, argc, argv, "MET_VERT_COORD", -1, "0", NULL);
5101 if (ctl->met_vert_coord < 0 || ctl->met_vert_coord > 4)
5102 ERRMSG("Set MET_VERT_COORD to 0, 1, 2, 3, or 4!");
5103 if (ctl->advect_vert_coord == 1 && ctl->qnt_zeta < 0)
5104 ERRMSG("Please add zeta to your quantities for diabatic calculations!");
5105 if (ctl->advect_vert_coord == 2 && ctl->met_vert_coord == 0)
5106 ERRMSG
5107 ("Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
5108
5109 /* Time steps of simulation... */
5110 ctl->direction =
5111 (int) scan_ctl(filename, argc, argv, "DIRECTION", -1, "1", NULL);
5112 if (ctl->direction != -1 && ctl->direction != 1)
5113 ERRMSG("Set DIRECTION to -1 or 1!");
5114 ctl->t_stop = scan_ctl(filename, argc, argv, "T_STOP", -1, "1e100", NULL);
5115 ctl->dt_mod = scan_ctl(filename, argc, argv, "DT_MOD", -1, "180", NULL);
5116
5117 /* Meteo data... */
5118 scan_ctl(filename, argc, argv, "METBASE", -1, "-", ctl->metbase);
5119 ctl->dt_met = scan_ctl(filename, argc, argv, "DT_MET", -1, "3600", NULL);
5120 ctl->met_convention =
5121 (int) scan_ctl(filename, argc, argv, "MET_CONVENTION", -1, "0", NULL);
5122 ctl->met_type =
5123 (int) scan_ctl(filename, argc, argv, "MET_TYPE", -1, "0", NULL);
5124 if (ctl->advect_vert_coord == 1 && ctl->met_type != 0)
5125 ERRMSG
5126 ("Please use meteo files in netcdf format for diabatic calculations.");
5127 ctl->met_clams =
5128 (int) scan_ctl(filename, argc, argv, "MET_CLAMS", -1, "0", NULL);
5129 ctl->met_nc_scale =
5130 (int) scan_ctl(filename, argc, argv, "MET_NC_SCALE", -1, "1", NULL);
5131 ctl->met_nc_level =
5132 (int) scan_ctl(filename, argc, argv, "MET_NC_LEVEL", -1, "0", NULL);
5133 ctl->met_nc_quant =
5134 (int) scan_ctl(filename, argc, argv, "MET_NC_QUANT", -1, "0", NULL);
5135 ctl->met_zstd_level =
5136 (int) scan_ctl(filename, argc, argv, "MET_ZSTD_LEVEL", -1, "0", NULL);
5137 ctl->met_zfp_prec =
5138 (int) scan_ctl(filename, argc, argv, "MET_ZFP_PREC", -1, "8", NULL);
5139 ctl->met_zfp_tol_t =
5140 scan_ctl(filename, argc, argv, "MET_ZFP_TOL_T", -1, "5.0", NULL);
5141 ctl->met_zfp_tol_z =
5142 scan_ctl(filename, argc, argv, "MET_ZFP_TOL_Z", -1, "0.5", NULL);
5143 ctl->met_cms_batch =
5144 (int) scan_ctl(filename, argc, argv, "MET_CMS_BATCH", -1, "-1", NULL);
5145 ctl->met_cms_zstd =
5146 (int) scan_ctl(filename, argc, argv, "MET_CMS_ZSTD", -1, "1", NULL);
5147 ctl->met_cms_heur =
5148 (int) scan_ctl(filename, argc, argv, "MET_CMS_HEUR", -1, "1", NULL);
5149 ctl->met_cms_eps_z =
5150 scan_ctl(filename, argc, argv, "MET_CMS_EPS_Z", -1, "1.0", NULL);
5151 ctl->met_cms_eps_t =
5152 scan_ctl(filename, argc, argv, "MET_CMS_EPS_T", -1, "0.05", NULL);
5153 ctl->met_cms_eps_u =
5154 scan_ctl(filename, argc, argv, "MET_CMS_EPS_U", -1, "0.05", NULL);
5155 ctl->met_cms_eps_v =
5156 scan_ctl(filename, argc, argv, "MET_CMS_EPS_V", -1, "0.05", NULL);
5157 ctl->met_cms_eps_w =
5158 scan_ctl(filename, argc, argv, "MET_CMS_EPS_W", -1, "1.0", NULL);
5159 ctl->met_cms_eps_pv =
5160 scan_ctl(filename, argc, argv, "MET_CMS_EPS_PV", -1, "1.0", NULL);
5161 ctl->met_cms_eps_h2o =
5162 scan_ctl(filename, argc, argv, "MET_CMS_EPS_H2O", -1, "1.0", NULL);
5163 ctl->met_cms_eps_o3 =
5164 scan_ctl(filename, argc, argv, "MET_CMS_EPS_O3", -1, "1.0", NULL);
5165 ctl->met_cms_eps_lwc =
5166 scan_ctl(filename, argc, argv, "MET_CMS_EPS_LWC", -1, "1.0", NULL);
5167 ctl->met_cms_eps_rwc =
5168 scan_ctl(filename, argc, argv, "MET_CMS_EPS_RWC", -1, "1.0", NULL);
5169 ctl->met_cms_eps_iwc =
5170 scan_ctl(filename, argc, argv, "MET_CMS_EPS_IWC", -1, "1.0", NULL);
5171 ctl->met_cms_eps_swc =
5172 scan_ctl(filename, argc, argv, "MET_CMS_EPS_SWC", -1, "1.0", NULL);
5173 ctl->met_cms_eps_cc =
5174 scan_ctl(filename, argc, argv, "MET_CMS_EPS_CC", -1, "1.0", NULL);
5175 ctl->met_dx = (int) scan_ctl(filename, argc, argv, "MET_DX", -1, "1", NULL);
5176 ctl->met_dy = (int) scan_ctl(filename, argc, argv, "MET_DY", -1, "1", NULL);
5177 ctl->met_dp = (int) scan_ctl(filename, argc, argv, "MET_DP", -1, "1", NULL);
5178 if (ctl->met_dx < 1 || ctl->met_dy < 1 || ctl->met_dp < 1)
5179 ERRMSG("MET_DX, MET_DY, and MET_DP need to be greater than zero!");
5180 ctl->met_sx = (int) scan_ctl(filename, argc, argv, "MET_SX", -1, "1", NULL);
5181 ctl->met_sy = (int) scan_ctl(filename, argc, argv, "MET_SY", -1, "1", NULL);
5182 ctl->met_sp = (int) scan_ctl(filename, argc, argv, "MET_SP", -1, "1", NULL);
5183 if (ctl->met_sx < 1 || ctl->met_sy < 1 || ctl->met_sp < 1)
5184 ERRMSG("MET_SX, MET_SY, and MET_SP need to be greater than zero!");
5185 ctl->met_detrend =
5186 scan_ctl(filename, argc, argv, "MET_DETREND", -1, "-999", NULL);
5187 ctl->met_np = (int) scan_ctl(filename, argc, argv, "MET_NP", -1, "0", NULL);
5188 if (ctl->met_np > EP)
5189 ERRMSG("Too many pressure levels!");
5190 ctl->met_press_level_def =
5191 (int) scan_ctl(filename, argc, argv, "MET_PRESS_LEVEL_DEF", -1, "-1",
5192 NULL);
5193 if (ctl->met_press_level_def >= 0) {
5194 level_definitions(ctl);
5195 } else {
5196 if (ctl->met_np > 0) {
5197 for (int ip = 0; ip < ctl->met_np; ip++)
5198 ctl->met_p[ip] =
5199 scan_ctl(filename, argc, argv, "MET_P", ip, "", NULL);
5200 }
5201 }
5202 ctl->met_nlev =
5203 (int) scan_ctl(filename, argc, argv, "MET_NLEV", -1, "0", NULL);
5204 if (ctl->met_nlev > EP)
5205 ERRMSG("Too many model levels!");
5206 for (int ip = 0; ip < ctl->met_nlev; ip++) {
5207 ctl->met_lev_hyam[ip] =
5208 scan_ctl(filename, argc, argv, "MET_LEV_HYAM", ip, "", NULL);
5209 ctl->met_lev_hybm[ip] =
5210 scan_ctl(filename, argc, argv, "MET_LEV_HYBM", ip, "", NULL);
5211 }
5212 ctl->met_geopot_sx =
5213 (int) scan_ctl(filename, argc, argv, "MET_GEOPOT_SX", -1, "-1", NULL);
5214 ctl->met_geopot_sy =
5215 (int) scan_ctl(filename, argc, argv, "MET_GEOPOT_SY", -1, "-1", NULL);
5216 ctl->met_relhum =
5217 (int) scan_ctl(filename, argc, argv, "MET_RELHUM", -1, "0", NULL);
5218 ctl->met_cape =
5219 (int) scan_ctl(filename, argc, argv, "MET_CAPE", -1, "1", NULL);
5220 if (ctl->met_cape < 0 || ctl->met_cape > 1)
5221 ERRMSG("Set MET_CAPE to 0 or 1!");
5222 ctl->met_pbl =
5223 (int) scan_ctl(filename, argc, argv, "MET_PBL", -1, "3", NULL);
5224 if (ctl->met_pbl < 0 || ctl->met_pbl > 3)
5225 ERRMSG("Set MET_PBL to 0 ... 3!");
5226 ctl->met_pbl_min =
5227 scan_ctl(filename, argc, argv, "MET_PBL_MIN", -1, "0.1", NULL);
5228 ctl->met_pbl_max =
5229 scan_ctl(filename, argc, argv, "MET_PBL_MAX", -1, "5.0", NULL);
5230 ctl->met_tropo =
5231 (int) scan_ctl(filename, argc, argv, "MET_TROPO", -1, "3", NULL);
5232 if (ctl->met_tropo < 0 || ctl->met_tropo > 5)
5233 ERRMSG("Set MET_TROPO to 0 ... 5!");
5234 ctl->met_tropo_pv =
5235 scan_ctl(filename, argc, argv, "MET_TROPO_PV", -1, "3.5", NULL);
5236 ctl->met_tropo_theta =
5237 scan_ctl(filename, argc, argv, "MET_TROPO_THETA", -1, "380", NULL);
5238 ctl->met_tropo_spline =
5239 (int) scan_ctl(filename, argc, argv, "MET_TROPO_SPLINE", -1, "1", NULL);
5240 ctl->met_dt_out =
5241 scan_ctl(filename, argc, argv, "MET_DT_OUT", -1, "0.1", NULL);
5242 ctl->met_cache =
5243 (int) scan_ctl(filename, argc, argv, "MET_CACHE", -1, "0", NULL);
5244 ctl->met_mpi_share =
5245 (int) scan_ctl(filename, argc, argv, "MET_MPI_SHARE", -1, "0", NULL);
5246
5247 /* Sorting... */
5248 ctl->sort_dt = scan_ctl(filename, argc, argv, "SORT_DT", -1, "-999", NULL);
5249
5250 /* Isosurface parameters... */
5251 ctl->isosurf =
5252 (int) scan_ctl(filename, argc, argv, "ISOSURF", -1, "0", NULL);
5253 scan_ctl(filename, argc, argv, "BALLOON", -1, "-", ctl->balloon);
5254
5255 /* Random number generator... */
5256 ctl->rng_type =
5257 (int) scan_ctl(filename, argc, argv, "RNG_TYPE", -1, "1", NULL);
5258 if (ctl->rng_type < 0 || ctl->rng_type > 2)
5259 ERRMSG("Set RNG_TYPE to 0, 1, or 2!");
5260
5261 /* Advection parameters... */
5262 ctl->advect = (int) scan_ctl(filename, argc, argv, "ADVECT", -1, "2", NULL);
5263 if (!
5264 (ctl->advect == 0 || ctl->advect == 1 || ctl->advect == 2
5265 || ctl->advect == 4))
5266 ERRMSG("Set ADVECT to 0, 1, 2, or 4!");
5267
5268 /* Diffusion parameters... */
5269 ctl->diffusion
5270 = (int) scan_ctl(filename, argc, argv, "DIFFUSION", -1, "0", NULL);
5271 if (ctl->diffusion < 0 || ctl->diffusion > 2)
5272 ERRMSG("Set DIFFUSION to 0, 1 or 2!");
5273 ctl->turb_dx_pbl =
5274 scan_ctl(filename, argc, argv, "TURB_DX_PBL", -1, "50", NULL);
5275 ctl->turb_dx_trop =
5276 scan_ctl(filename, argc, argv, "TURB_DX_TROP", -1, "50", NULL);
5277 ctl->turb_dx_strat =
5278 scan_ctl(filename, argc, argv, "TURB_DX_STRAT", -1, "0", NULL);
5279 ctl->turb_dz_pbl =
5280 scan_ctl(filename, argc, argv, "TURB_DZ_PBL", -1, "0", NULL);
5281 ctl->turb_dz_trop =
5282 scan_ctl(filename, argc, argv, "TURB_DZ_TROP", -1, "0", NULL);
5283 ctl->turb_dz_strat =
5284 scan_ctl(filename, argc, argv, "TURB_DZ_STRAT", -1, "0.1", NULL);
5285 ctl->turb_mesox =
5286 scan_ctl(filename, argc, argv, "TURB_MESOX", -1, "0.16", NULL);
5287 ctl->turb_mesoz =
5288 scan_ctl(filename, argc, argv, "TURB_MESOZ", -1, "0.16", NULL);
5289
5290 /* Convection... */
5291 ctl->conv_mix_pbl
5292 = (int) scan_ctl(filename, argc, argv, "CONV_MIX_PBL", -1, "0", NULL);
5293 ctl->conv_pbl_trans
5294 = scan_ctl(filename, argc, argv, "CONV_PBL_TRANS", -1, "0", NULL);
5295 ctl->conv_cape
5296 = scan_ctl(filename, argc, argv, "CONV_CAPE", -1, "-999", NULL);
5297 ctl->conv_cin
5298 = scan_ctl(filename, argc, argv, "CONV_CIN", -1, "-999", NULL);
5299 ctl->conv_dt = scan_ctl(filename, argc, argv, "CONV_DT", -1, "-999", NULL);
5300
5301 /* Boundary conditions... */
5302 ctl->bound_mass =
5303 scan_ctl(filename, argc, argv, "BOUND_MASS", -1, "-999", NULL);
5304 ctl->bound_mass_trend =
5305 scan_ctl(filename, argc, argv, "BOUND_MASS_TREND", -1, "0", NULL);
5306 ctl->bound_vmr =
5307 scan_ctl(filename, argc, argv, "BOUND_VMR", -1, "-999", NULL);
5308 ctl->bound_vmr_trend =
5309 scan_ctl(filename, argc, argv, "BOUND_VMR_TREND", -1, "0", NULL);
5310 ctl->bound_lat0 =
5311 scan_ctl(filename, argc, argv, "BOUND_LAT0", -1, "-999", NULL);
5312 ctl->bound_lat1 =
5313 scan_ctl(filename, argc, argv, "BOUND_LAT1", -1, "-999", NULL);
5314 ctl->bound_p0 =
5315 scan_ctl(filename, argc, argv, "BOUND_P0", -1, "-999", NULL);
5316 ctl->bound_p1 =
5317 scan_ctl(filename, argc, argv, "BOUND_P1", -1, "-999", NULL);
5318 ctl->bound_dps =
5319 scan_ctl(filename, argc, argv, "BOUND_DPS", -1, "-999", NULL);
5320 ctl->bound_dzs =
5321 scan_ctl(filename, argc, argv, "BOUND_DZS", -1, "-999", NULL);
5322 ctl->bound_zetas =
5323 scan_ctl(filename, argc, argv, "BOUND_ZETAS", -1, "-999", NULL);
5324 ctl->bound_pbl =
5325 (int) scan_ctl(filename, argc, argv, "BOUND_PBL", -1, "0", NULL);
5326
5327 /* Species parameters... */
5328 scan_ctl(filename, argc, argv, "SPECIES", -1, "-", ctl->species);
5329 if (strcasecmp(ctl->species, "CF2Cl2") == 0) {
5330 ctl->molmass = 120.907;
5331 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 3e-5;
5332 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3500.0;
5333 } else if (strcasecmp(ctl->species, "CFCl3") == 0) {
5334 ctl->molmass = 137.359;
5335 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.1e-4;
5336 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3300.0;
5337 } else if (strcasecmp(ctl->species, "CH4") == 0) {
5338 ctl->molmass = 16.043;
5339 ctl->oh_chem_reaction = 2;
5340 ctl->oh_chem[0] = 2.45e-12;
5341 ctl->oh_chem[1] = 1775;
5342 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.4e-5;
5343 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1600.0;
5344 } else if (strcasecmp(ctl->species, "CO") == 0) {
5345 ctl->molmass = 28.01;
5346 ctl->oh_chem_reaction = 3;
5347 ctl->oh_chem[0] = 6.9e-33;
5348 ctl->oh_chem[1] = 2.1;
5349 ctl->oh_chem[2] = 1.1e-12;
5350 ctl->oh_chem[3] = -1.3;
5351 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 9.7e-6;
5352 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1300.0;
5353 } else if (strcasecmp(ctl->species, "CO2") == 0) {
5354 ctl->molmass = 44.009;
5355 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 3.3e-4;
5356 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2400.0;
5357 } else if (strcasecmp(ctl->species, "H2O") == 0) {
5358 ctl->molmass = 18.01528;
5359 } else if (strcasecmp(ctl->species, "N2O") == 0) {
5360 ctl->molmass = 44.013;
5361 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.4e-4;
5362 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2600.;
5363 } else if (strcasecmp(ctl->species, "NH3") == 0) {
5364 ctl->molmass = 17.031;
5365 ctl->oh_chem_reaction = 2;
5366 ctl->oh_chem[0] = 1.7e-12;
5367 ctl->oh_chem[1] = 710;
5368 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 5.9e-1;
5369 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 4200.0;
5370 } else if (strcasecmp(ctl->species, "HNO3") == 0) {
5371 ctl->molmass = 63.012;
5372 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.1e3;
5373 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 8700.0;
5374 } else if (strcasecmp(ctl->species, "NO") == 0) {
5375 ctl->molmass = 30.006;
5376 ctl->oh_chem_reaction = 3;
5377 ctl->oh_chem[0] = 7.1e-31;
5378 ctl->oh_chem[1] = 2.6;
5379 ctl->oh_chem[2] = 3.6e-11;
5380 ctl->oh_chem[3] = 0.1;
5381 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.9e-5;
5382 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1600.0;
5383 } else if (strcasecmp(ctl->species, "NO2") == 0) {
5384 ctl->molmass = 46.005;
5385 ctl->oh_chem_reaction = 3;
5386 ctl->oh_chem[0] = 1.8e-30;
5387 ctl->oh_chem[1] = 3.0;
5388 ctl->oh_chem[2] = 2.8e-11;
5389 ctl->oh_chem[3] = 0.0;
5390 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.2e-4;
5391 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2400.0;
5392 } else if (strcasecmp(ctl->species, "O3") == 0) {
5393 ctl->molmass = 47.997;
5394 ctl->oh_chem_reaction = 2;
5395 ctl->oh_chem[0] = 1.7e-12;
5396 ctl->oh_chem[1] = 940;
5397 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1e-4;
5398 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2800.0;
5399 } else if (strcasecmp(ctl->species, "SF6") == 0) {
5400 ctl->molmass = 146.048;
5401 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.4e-6;
5402 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3100.0;
5403 } else if (strcasecmp(ctl->species, "SO2") == 0) {
5404 ctl->molmass = 64.066;
5405 ctl->oh_chem_reaction = 3;
5406 ctl->oh_chem[0] = 2.9e-31;
5407 ctl->oh_chem[1] = 4.1;
5408 ctl->oh_chem[2] = 1.7e-12;
5409 ctl->oh_chem[3] = -0.2;
5410 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.3e-2;
5411 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2900.0;
5412 }
5413
5414 /* Molar mass... */
5415 char defstr[LEN];
5416 sprintf(defstr, "%g", ctl->molmass);
5417 ctl->molmass = scan_ctl(filename, argc, argv, "MOLMASS", -1, defstr, NULL);
5418
5419 /* OH chemistry... */
5420 sprintf(defstr, "%d", ctl->oh_chem_reaction);
5421 ctl->oh_chem_reaction =
5422 (int) scan_ctl(filename, argc, argv, "OH_CHEM_REACTION", -1, defstr,
5423 NULL);
5424 for (int ip = 0; ip < 4; ip++) {
5425 sprintf(defstr, "%g", ctl->oh_chem[ip]);
5426 ctl->oh_chem[ip] =
5427 scan_ctl(filename, argc, argv, "OH_CHEM", ip, defstr, NULL);
5428 }
5429 ctl->oh_chem_beta =
5430 scan_ctl(filename, argc, argv, "OH_CHEM_BETA", -1, "0", NULL);
5431
5432 /* H2O2 chemistry... */
5433 ctl->h2o2_chem_reaction =
5434 (int) scan_ctl(filename, argc, argv, "H2O2_CHEM_REACTION", -1, "0", NULL);
5435
5436 /* KPP chemistry... */
5437 ctl->kpp_chem =
5438 (int) scan_ctl(filename, argc, argv, "KPP_CHEM", -1, "0", NULL);
5439 ctl->dt_kpp = scan_ctl(filename, argc, argv, "DT_KPP", -1, "1800", NULL);
5440
5441 /* First order tracer chemistry... */
5442 ctl->tracer_chem =
5443 (int) scan_ctl(filename, argc, argv, "TRACER_CHEM", -1, "0", NULL);
5444
5445 /* Wet deposition... */
5446 for (int ip = 0; ip < 2; ip++) {
5447 sprintf(defstr, "%g", ctl->wet_depo_ic_h[ip]);
5448 ctl->wet_depo_ic_h[ip] =
5449 scan_ctl(filename, argc, argv, "WET_DEPO_IC_H", ip, defstr, NULL);
5450 }
5451 for (int ip = 0; ip < 1; ip++) {
5452 sprintf(defstr, "%g", ctl->wet_depo_bc_h[ip]);
5453 ctl->wet_depo_bc_h[ip] =
5454 scan_ctl(filename, argc, argv, "WET_DEPO_BC_H", ip, defstr, NULL);
5455 }
5456 ctl->wet_depo_so2_ph =
5457 scan_ctl(filename, argc, argv, "WET_DEPO_SO2_PH", -1, "0", NULL);
5458 ctl->wet_depo_ic_a =
5459 scan_ctl(filename, argc, argv, "WET_DEPO_IC_A", -1, "0", NULL);
5460 ctl->wet_depo_ic_b =
5461 scan_ctl(filename, argc, argv, "WET_DEPO_IC_B", -1, "0", NULL);
5462 ctl->wet_depo_bc_a =
5463 scan_ctl(filename, argc, argv, "WET_DEPO_BC_A", -1, "0", NULL);
5464 ctl->wet_depo_bc_b =
5465 scan_ctl(filename, argc, argv, "WET_DEPO_BC_B", -1, "0", NULL);
5466 ctl->wet_depo_pre[0] =
5467 scan_ctl(filename, argc, argv, "WET_DEPO_PRE", 0, "0.5", NULL);
5468 ctl->wet_depo_pre[1] =
5469 scan_ctl(filename, argc, argv, "WET_DEPO_PRE", 1, "0.36", NULL);
5471 scan_ctl(filename, argc, argv, "WET_DEPO_IC_RET_RATIO", -1, "1", NULL);
5473 scan_ctl(filename, argc, argv, "WET_DEPO_BC_RET_RATIO", -1, "1", NULL);
5474
5475 /* Dry deposition... */
5476 ctl->dry_depo_vdep =
5477 scan_ctl(filename, argc, argv, "DRY_DEPO_VDEP", -1, "0", NULL);
5478 ctl->dry_depo_dp =
5479 scan_ctl(filename, argc, argv, "DRY_DEPO_DP", -1, "30", NULL);
5480
5481 /* Climatological data... */
5482 scan_ctl(filename, argc, argv, "CLIM_PHOTO", -1,
5483 "../../data/clams_photolysis_rates.nc", ctl->clim_photo);
5484 scan_ctl(filename, argc, argv, "CLIM_HNO3_FILENAME", -1,
5485 "../../data/gozcards_HNO3.nc", ctl->clim_hno3_filename);
5486 scan_ctl(filename, argc, argv, "CLIM_OH_FILENAME", -1,
5487 "../../data/clams_radical_species_vmr.nc", ctl->clim_oh_filename);
5488 scan_ctl(filename, argc, argv, "CLIM_H2O2_FILENAME", -1,
5489 "../../data/cams_H2O2.nc", ctl->clim_h2o2_filename);
5490 scan_ctl(filename, argc, argv, "CLIM_HO2_FILENAME", -1,
5491 "../../data/clams_radical_species_vmr.nc", ctl->clim_ho2_filename);
5492 scan_ctl(filename, argc, argv, "CLIM_O1D_FILENAME", -1,
5493 "../../data/clams_radical_species_vmr.nc", ctl->clim_o1d_filename);
5494 scan_ctl(filename, argc, argv, "CLIM_CCL4_TIMESERIES", -1,
5495 "../../data/noaa_gml_ccl4.tab", ctl->clim_ccl4_timeseries);
5496 scan_ctl(filename, argc, argv, "CLIM_CCL3F_TIMESERIES", -1,
5497 "../../data/noaa_gml_cfc11.tab", ctl->clim_ccl3f_timeseries);
5498 scan_ctl(filename, argc, argv, "CLIM_CCL2F2_TIMESERIES", -1,
5499 "../../data/noaa_gml_cfc12.tab", ctl->clim_ccl2f2_timeseries);
5500 scan_ctl(filename, argc, argv, "CLIM_N2O_TIMESERIES", -1,
5501 "../../data/noaa_gml_n2o.tab", ctl->clim_n2o_timeseries);
5502 scan_ctl(filename, argc, argv, "CLIM_SF6_TIMESERIES", -1,
5503 "../../data/noaa_gml_sf6.tab", ctl->clim_sf6_timeseries);
5504
5505 /* Mixing... */
5506 ctl->mixing_dt =
5507 scan_ctl(filename, argc, argv, "MIXING_DT", -1, "3600.", NULL);
5508 ctl->mixing_trop =
5509 scan_ctl(filename, argc, argv, "MIXING_TROP", -1, "-999", NULL);
5510 ctl->mixing_strat =
5511 scan_ctl(filename, argc, argv, "MIXING_STRAT", -1, "-999", NULL);
5512 ctl->mixing_z0 =
5513 scan_ctl(filename, argc, argv, "MIXING_Z0", -1, "-5", NULL);
5514 ctl->mixing_z1 =
5515 scan_ctl(filename, argc, argv, "MIXING_Z1", -1, "85", NULL);
5516 ctl->mixing_nz =
5517 (int) scan_ctl(filename, argc, argv, "MIXING_NZ", -1, "90", NULL);
5518 ctl->mixing_lon0 =
5519 scan_ctl(filename, argc, argv, "MIXING_LON0", -1, "-180", NULL);
5520 ctl->mixing_lon1 =
5521 scan_ctl(filename, argc, argv, "MIXING_LON1", -1, "180", NULL);
5522 ctl->mixing_nx =
5523 (int) scan_ctl(filename, argc, argv, "MIXING_NX", -1, "360", NULL);
5524 ctl->mixing_lat0 =
5525 scan_ctl(filename, argc, argv, "MIXING_LAT0", -1, "-90", NULL);
5526 ctl->mixing_lat1 =
5527 scan_ctl(filename, argc, argv, "MIXING_LAT1", -1, "90", NULL);
5528 ctl->mixing_ny =
5529 (int) scan_ctl(filename, argc, argv, "MIXING_NY", -1, "180", NULL);
5530
5531 /* Chemistry grid... */
5532 ctl->chemgrid_z0 =
5533 scan_ctl(filename, argc, argv, "CHEMGRID_Z0", -1, "-5", NULL);
5534 ctl->chemgrid_z1 =
5535 scan_ctl(filename, argc, argv, "CHEMGRID_Z1", -1, "85", NULL);
5536 ctl->chemgrid_nz =
5537 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NZ", -1, "90", NULL);
5538 ctl->chemgrid_lon0 =
5539 scan_ctl(filename, argc, argv, "CHEMGRID_LON0", -1, "-180", NULL);
5540 ctl->chemgrid_lon1 =
5541 scan_ctl(filename, argc, argv, "CHEMGRID_LON1", -1, "180", NULL);
5542 ctl->chemgrid_nx =
5543 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NX", -1, "360", NULL);
5544 ctl->chemgrid_lat0 =
5545 scan_ctl(filename, argc, argv, "CHEMGRID_LAT0", -1, "-90", NULL);
5546 ctl->chemgrid_lat1 =
5547 scan_ctl(filename, argc, argv, "CHEMGRID_LAT1", -1, "90", NULL);
5548 ctl->chemgrid_ny =
5549 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NY", -1, "180", NULL);
5550
5551 /* Exponential decay... */
5552 ctl->tdec_trop = scan_ctl(filename, argc, argv, "TDEC_TROP", -1, "0", NULL);
5553 ctl->tdec_strat =
5554 scan_ctl(filename, argc, argv, "TDEC_STRAT", -1, "0", NULL);
5555
5556 /* PSC analysis... */
5557 ctl->psc_h2o = scan_ctl(filename, argc, argv, "PSC_H2O", -1, "4e-6", NULL);
5558 ctl->psc_hno3 =
5559 scan_ctl(filename, argc, argv, "PSC_HNO3", -1, "9e-9", NULL);
5560
5561 /* Output of atmospheric data... */
5562 scan_ctl(filename, argc, argv, "ATM_BASENAME", -1, "-", ctl->atm_basename);
5563 scan_ctl(filename, argc, argv, "ATM_GPFILE", -1, "-", ctl->atm_gpfile);
5564 ctl->atm_dt_out =
5565 scan_ctl(filename, argc, argv, "ATM_DT_OUT", -1, "86400", NULL);
5566 ctl->atm_filter =
5567 (int) scan_ctl(filename, argc, argv, "ATM_FILTER", -1, "0", NULL);
5568 ctl->atm_stride =
5569 (int) scan_ctl(filename, argc, argv, "ATM_STRIDE", -1, "1", NULL);
5570 ctl->atm_type =
5571 (int) scan_ctl(filename, argc, argv, "ATM_TYPE", -1, "0", NULL);
5572 ctl->atm_type_out =
5573 (int) scan_ctl(filename, argc, argv, "ATM_TYPE_OUT", -1, "-1", NULL);
5574 if (ctl->atm_type_out == -1)
5575 ctl->atm_type_out = ctl->atm_type;
5576 ctl->atm_nc_level =
5577 (int) scan_ctl(filename, argc, argv, "ATM_NC_LEVEL", -1, "0", NULL);
5578 for (int iq = 0; iq < ctl->nq; iq++)
5579 ctl->atm_nc_quant[iq] =
5580 (int) scan_ctl(filename, argc, argv, "ATM_NC_QUANT", iq, "0", NULL);
5581 ctl->obs_type =
5582 (int) scan_ctl(filename, argc, argv, "OBS_TYPE", -1, "0", NULL);
5583
5584 /* Output of CSI data... */
5585 scan_ctl(filename, argc, argv, "CSI_BASENAME", -1, "-", ctl->csi_basename);
5586 scan_ctl(filename, argc, argv, "CSI_ENS_BASENAME", -1, "-",
5587 ctl->csi_ens_basename);
5588 ctl->nens = (int) scan_ctl(filename, argc, argv, "NENS", -1, "0", NULL);
5589 scan_ctl(filename, argc, argv, "CSI_KERNEL", -1, "-", ctl->csi_kernel);
5590 ctl->csi_dt_out =
5591 scan_ctl(filename, argc, argv, "CSI_DT_OUT", -1, "86400", NULL);
5592 scan_ctl(filename, argc, argv, "CSI_OBSFILE", -1, "-", ctl->csi_obsfile);
5593 ctl->csi_obsmin =
5594 scan_ctl(filename, argc, argv, "CSI_OBSMIN", -1, "0", NULL);
5595 ctl->csi_modmin =
5596 scan_ctl(filename, argc, argv, "CSI_MODMIN", -1, "0", NULL);
5597 ctl->csi_z0 = scan_ctl(filename, argc, argv, "CSI_Z0", -1, "-5", NULL);
5598 ctl->csi_z1 = scan_ctl(filename, argc, argv, "CSI_Z1", -1, "85", NULL);
5599 ctl->csi_nz = (int) scan_ctl(filename, argc, argv, "CSI_NZ", -1, "1", NULL);
5600 ctl->csi_lon0 =
5601 scan_ctl(filename, argc, argv, "CSI_LON0", -1, "-180", NULL);
5602 ctl->csi_lon1 = scan_ctl(filename, argc, argv, "CSI_LON1", -1, "180", NULL);
5603 ctl->csi_nx =
5604 (int) scan_ctl(filename, argc, argv, "CSI_NX", -1, "360", NULL);
5605 ctl->csi_lat0 = scan_ctl(filename, argc, argv, "CSI_LAT0", -1, "-90", NULL);
5606 ctl->csi_lat1 = scan_ctl(filename, argc, argv, "CSI_LAT1", -1, "90", NULL);
5607 ctl->csi_ny =
5608 (int) scan_ctl(filename, argc, argv, "CSI_NY", -1, "180", NULL);
5609
5610 /* Output of ensemble data... */
5611 scan_ctl(filename, argc, argv, "ENS_BASENAME", -1, "-", ctl->ens_basename);
5612 ctl->ens_dt_out =
5613 scan_ctl(filename, argc, argv, "ENS_DT_OUT", -1, "86400", NULL);
5614
5615 /* Output of grid data... */
5616 scan_ctl(filename, argc, argv, "GRID_BASENAME", -1, "-",
5617 ctl->grid_basename);
5618 scan_ctl(filename, argc, argv, "GRID_KERNEL", -1, "-", ctl->grid_kernel);
5619 scan_ctl(filename, argc, argv, "GRID_GPFILE", -1, "-", ctl->grid_gpfile);
5620 ctl->grid_dt_out =
5621 scan_ctl(filename, argc, argv, "GRID_DT_OUT", -1, "86400", NULL);
5622 ctl->grid_sparse =
5623 (int) scan_ctl(filename, argc, argv, "GRID_SPARSE", -1, "0", NULL);
5624 ctl->grid_nc_level =
5625 (int) scan_ctl(filename, argc, argv, "GRID_NC_LEVEL", -1, "0", NULL);
5626 for (int iq = 0; iq < ctl->nq; iq++)
5627 ctl->grid_nc_quant[iq] =
5628 (int) scan_ctl(filename, argc, argv, "GRID_NC_QUANT", iq, "0", NULL);
5629 ctl->grid_stddev =
5630 (int) scan_ctl(filename, argc, argv, "GRID_STDDEV", -1, "0", NULL);
5631 ctl->grid_z0 = scan_ctl(filename, argc, argv, "GRID_Z0", -1, "-5", NULL);
5632 ctl->grid_z1 = scan_ctl(filename, argc, argv, "GRID_Z1", -1, "85", NULL);
5633 ctl->grid_nz =
5634 (int) scan_ctl(filename, argc, argv, "GRID_NZ", -1, "1", NULL);
5635 ctl->grid_lon0 =
5636 scan_ctl(filename, argc, argv, "GRID_LON0", -1, "-180", NULL);
5637 ctl->grid_lon1 =
5638 scan_ctl(filename, argc, argv, "GRID_LON1", -1, "180", NULL);
5639 ctl->grid_nx =
5640 (int) scan_ctl(filename, argc, argv, "GRID_NX", -1, "360", NULL);
5641 ctl->grid_lat0 =
5642 scan_ctl(filename, argc, argv, "GRID_LAT0", -1, "-90", NULL);
5643 ctl->grid_lat1 =
5644 scan_ctl(filename, argc, argv, "GRID_LAT1", -1, "90", NULL);
5645 ctl->grid_ny =
5646 (int) scan_ctl(filename, argc, argv, "GRID_NY", -1, "180", NULL);
5647 ctl->grid_type =
5648 (int) scan_ctl(filename, argc, argv, "GRID_TYPE", -1, "0", NULL);
5649
5650 /* Output of profile data... */
5651 scan_ctl(filename, argc, argv, "PROF_BASENAME", -1, "-",
5652 ctl->prof_basename);
5653 scan_ctl(filename, argc, argv, "PROF_OBSFILE", -1, "-", ctl->prof_obsfile);
5654 ctl->prof_z0 = scan_ctl(filename, argc, argv, "PROF_Z0", -1, "0", NULL);
5655 ctl->prof_z1 = scan_ctl(filename, argc, argv, "PROF_Z1", -1, "60", NULL);
5656 ctl->prof_nz =
5657 (int) scan_ctl(filename, argc, argv, "PROF_NZ", -1, "60", NULL);
5658 ctl->prof_lon0 =
5659 scan_ctl(filename, argc, argv, "PROF_LON0", -1, "-180", NULL);
5660 ctl->prof_lon1 =
5661 scan_ctl(filename, argc, argv, "PROF_LON1", -1, "180", NULL);
5662 ctl->prof_nx =
5663 (int) scan_ctl(filename, argc, argv, "PROF_NX", -1, "360", NULL);
5664 ctl->prof_lat0 =
5665 scan_ctl(filename, argc, argv, "PROF_LAT0", -1, "-90", NULL);
5666 ctl->prof_lat1 =
5667 scan_ctl(filename, argc, argv, "PROF_LAT1", -1, "90", NULL);
5668 ctl->prof_ny =
5669 (int) scan_ctl(filename, argc, argv, "PROF_NY", -1, "180", NULL);
5670
5671 /* Output of sample data... */
5672 scan_ctl(filename, argc, argv, "SAMPLE_BASENAME", -1, "-",
5673 ctl->sample_basename);
5674 scan_ctl(filename, argc, argv, "SAMPLE_KERNEL", -1, "-",
5675 ctl->sample_kernel);
5676 scan_ctl(filename, argc, argv, "SAMPLE_OBSFILE", -1, "-",
5677 ctl->sample_obsfile);
5678 ctl->sample_dx =
5679 scan_ctl(filename, argc, argv, "SAMPLE_DX", -1, "50", NULL);
5680 ctl->sample_dz =
5681 scan_ctl(filename, argc, argv, "SAMPLE_DZ", -1, "-999", NULL);
5682
5683 /* Output of station data... */
5684 scan_ctl(filename, argc, argv, "STAT_BASENAME", -1, "-",
5685 ctl->stat_basename);
5686 ctl->stat_lon = scan_ctl(filename, argc, argv, "STAT_LON", -1, "0", NULL);
5687 ctl->stat_lat = scan_ctl(filename, argc, argv, "STAT_LAT", -1, "0", NULL);
5688 ctl->stat_r = scan_ctl(filename, argc, argv, "STAT_R", -1, "50", NULL);
5689 ctl->stat_t0 =
5690 scan_ctl(filename, argc, argv, "STAT_T0", -1, "-1e100", NULL);
5691 ctl->stat_t1 = scan_ctl(filename, argc, argv, "STAT_T1", -1, "1e100", NULL);
5692
5693 /* Output of VTK data... */
5694 scan_ctl(filename, argc, argv, "VTK_BASENAME", -1, "-", ctl->vtk_basename);
5695 ctl->vtk_dt_out =
5696 scan_ctl(filename, argc, argv, "VTK_DT_OUT", -1, "86400", NULL);
5697 ctl->vtk_stride =
5698 (int) scan_ctl(filename, argc, argv, "VTK_STRIDE", -1, "1", NULL);
5699 ctl->vtk_scale =
5700 scan_ctl(filename, argc, argv, "VTK_SCALE", -1, "1.0", NULL);
5701 ctl->vtk_offset =
5702 scan_ctl(filename, argc, argv, "VTK_OFFSET", -1, "0.0", NULL);
5703 ctl->vtk_sphere =
5704 (int) scan_ctl(filename, argc, argv, "VTK_SPHERE", -1, "0", NULL);
5705}
void level_definitions(ctl_t *ctl)
Defines pressure levels for meteorological data.
Definition: mptrac.c:1817
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:9834
#define NQ
Maximum number of quantities per data point.
Definition: mptrac.h:266
#define SET_QNT(qnt, name, longname, unit)
Set atmospheric quantity index.
Definition: mptrac.h:1603
double grid_z0
Lower altitude of gridded data [km].
Definition: mptrac.h:3118
int qnt_o3
Quantity array index for ozone volume mixing ratio.
Definition: mptrac.h:2350
double csi_lat1
Upper latitude of gridded CSI data [deg].
Definition: mptrac.h:3082
char csi_obsfile[LEN]
Observation data file for CSI analysis.
Definition: mptrac.h:3049
int qnt_pel
Quantity array index for pressure at equilibrium level (EL).
Definition: mptrac.h:2383
int csi_nz
Number of altitudes of gridded CSI data.
Definition: mptrac.h:3058
int qnt_p
Quantity array index for pressure.
Definition: mptrac.h:2329
char atm_gpfile[LEN]
Gnuplot file for atmospheric data.
Definition: mptrac.h:3004
int qnt_swc
Quantity array index for cloud snow water content.
Definition: mptrac.h:2362
double csi_obsmin
Minimum observation index to trigger detection.
Definition: mptrac.h:3052
int qnt_pcb
Quantity array index for cloud bottom pressure.
Definition: mptrac.h:2371
double csi_lon1
Upper longitude of gridded CSI data [deg].
Definition: mptrac.h:3073
int qnt_u
Quantity array index for zonal wind.
Definition: mptrac.h:2338
double stat_lon
Longitude of station [deg].
Definition: mptrac.h:3196
double sort_dt
Time step for sorting of particle data [s].
Definition: mptrac.h:2725
double stat_r
Search radius around station [km].
Definition: mptrac.h:3202
int csi_ny
Number of latitudes of gridded CSI data.
Definition: mptrac.h:3076
int vtk_sphere
Spherical projection for VTK data (0=no, 1=yes).
Definition: mptrac.h:3226
double met_pbl_min
Minimum depth of planetary boundary layer [km].
Definition: mptrac.h:2693
int qnt_iwc
Quantity array index for cloud ice water content.
Definition: mptrac.h:2359
int qnt_pw
Quantity array index for partial water vapor pressure.
Definition: mptrac.h:2437
char prof_basename[LEN]
Basename for profile output file.
Definition: mptrac.h:3145
double grid_z1
Upper altitude of gridded data [km].
Definition: mptrac.h:3121
double met_dt_out
Time step for sampling of meteo data along trajectories [s].
Definition: mptrac.h:2712
int qnt_h2o2
Quantity array index for H2O2 volume mixing ratio (climatology).
Definition: mptrac.h:2401
int qnt_vh
Quantity array index for horizontal wind.
Definition: mptrac.h:2464
char species[LEN]
Species.
Definition: mptrac.h:2823
int csi_nx
Number of longitudes of gridded CSI data.
Definition: mptrac.h:3067
double csi_lat0
Lower latitude of gridded CSI data [deg].
Definition: mptrac.h:3079
int met_pbl
Planetary boundary layer data (0=file, 1=z2p, 2=Richardson, 3=theta).
Definition: mptrac.h:2690
int qnt_lwc
Quantity array index for cloud liquid water content.
Definition: mptrac.h:2353
int grid_nc_level
zlib compression level of netCDF grid data files (0=off).
Definition: mptrac.h:3106
int grid_nx
Number of longitudes of gridded data.
Definition: mptrac.h:3124
double grid_lat0
Lower latitude of gridded data [deg].
Definition: mptrac.h:3136
int qnt_ts
Quantity array index for surface temperature.
Definition: mptrac.h:2284
int qnt_plfc
Quantity array index for pressure at level of free convection (LCF).
Definition: mptrac.h:2380
double grid_lon0
Lower longitude of gridded data [deg].
Definition: mptrac.h:3127
int qnt_o1d
Quantity array index for O(1D) volume mixing ratio (climatology).
Definition: mptrac.h:2407
int met_tropo_spline
Tropopause interpolation method (0=linear, 1=spline).
Definition: mptrac.h:2709
char sample_kernel[LEN]
Kernel data file for sample output.
Definition: mptrac.h:3181
int qnt_tvirt
Quantity array index for virtual temperature.
Definition: mptrac.h:2458
int met_geopot_sy
Latitudinal smoothing of geopotential heights.
Definition: mptrac.h:2681
char grid_gpfile[LEN]
Gnuplot file for gridded data.
Definition: mptrac.h:3097
int qnt_lsm
Quantity array index for land-sea mask.
Definition: mptrac.h:2305
int qnt_theta
Quantity array index for potential temperature.
Definition: mptrac.h:2449
double stat_t1
Stop time for station output [s].
Definition: mptrac.h:3208
char csi_kernel[LEN]
Kernel data file for CSI output.
Definition: mptrac.h:3043
int grid_type
Type of grid data files (0=ASCII, 1=netCDF).
Definition: mptrac.h:3142
double csi_lon0
Lower longitude of gridded CSI data [deg].
Definition: mptrac.h:3070
int qnt_pbl
Quantity array index for boundary layer pressure.
Definition: mptrac.h:2311
int grid_stddev
Include standard deviations in grid output (0=no, 1=yes).
Definition: mptrac.h:3112
int qnt_psice
Quantity array index for saturation pressure over ice.
Definition: mptrac.h:2434
int met_geopot_sx
Longitudinal smoothing of geopotential heights.
Definition: mptrac.h:2678
int qnt_ps
Quantity array index for surface pressure.
Definition: mptrac.h:2281
char prof_obsfile[LEN]
Observation data file for profile output.
Definition: mptrac.h:3148
int qnt_zs
Quantity array index for surface geopotential height.
Definition: mptrac.h:2287
int prof_nz
Number of altitudes of gridded profile data.
Definition: mptrac.h:3151
double csi_dt_out
Time step for CSI output [s].
Definition: mptrac.h:3046
int met_cape
Convective available potential energy data (0=file, 1=calculate).
Definition: mptrac.h:2687
double csi_modmin
Minimum column density to trigger detection [kg/m^2].
Definition: mptrac.h:3055
char grid_kernel[LEN]
Kernel data file for grid output.
Definition: mptrac.h:3094
double prof_z0
Lower altitude of gridded profile data [km].
Definition: mptrac.h:3154
int qnt_w
Quantity array index for vertical velocity.
Definition: mptrac.h:2344
double met_tropo_pv
Dynamical tropopause potential vorticity threshold [PVU].
Definition: mptrac.h:2703
int prof_nx
Number of longitudes of gridded profile data.
Definition: mptrac.h:3160
int qnt_stat
Quantity array index for station flag.
Definition: mptrac.h:2266
int met_mpi_share
Use MPI to share meteo (0=no, 1=yes).
Definition: mptrac.h:2718
int qnt_vz
Quantity array index for vertical velocity.
Definition: mptrac.h:2467
int qnt_ho2
Quantity array index for HO2 volume mixing ratio (climatology).
Definition: mptrac.h:2404
double csi_z1
Upper altitude of gridded CSI data [km].
Definition: mptrac.h:3064
double stat_t0
Start time for station output [s].
Definition: mptrac.h:3205
int atm_type_out
Type of atmospheric data files for output (-1=same as ATM_TYPE, 0=ASCII, 1=binary,...
Definition: mptrac.h:3022
int met_nlev
Number of meteo data model levels.
Definition: mptrac.h:2669
double dt_kpp
Time step for KPP chemistry [s].
Definition: mptrac.h:2949
char csi_basename[LEN]
Basename of CSI data files.
Definition: mptrac.h:3034
int qnt_shf
Quantity array index for surface sensible heat flux.
Definition: mptrac.h:2302
int qnt_vs
Quantity array index for surface meridional wind.
Definition: mptrac.h:2293
double vtk_dt_out
Time step for VTK data output [s].
Definition: mptrac.h:3214
double conv_dt
Time interval for convection module [s].
Definition: mptrac.h:2784
char sample_obsfile[LEN]
Observation data file for sample output.
Definition: mptrac.h:3184
int qnt_hno3
Quantity array index for HNO3 volume mixing ratio (climatology).
Definition: mptrac.h:2395
char grid_basename[LEN]
Basename of grid data files.
Definition: mptrac.h:3091
int qnt_h2ot
Quantity array index for tropopause water vapor volume mixing ratio.
Definition: mptrac.h:2323
int qnt_rh
Quantity array index for relative humidity over water.
Definition: mptrac.h:2443
double met_pbl_max
Maximum depth of planetary boundary layer [km].
Definition: mptrac.h:2696
int qnt_zeta_d
Quantity array index for diagnosed zeta vertical coordinate.
Definition: mptrac.h:2455
int tracer_chem
Switch for first order tracer chemistry module (0=off, 1=on).
Definition: mptrac.h:2952
int diffusion
Diffusion scheme (0=off, 1=fixed-K, 2=PBL).
Definition: mptrac.h:2745
int qnt_zg
Quantity array index for geopotential height.
Definition: mptrac.h:2326
double vtk_offset
Vertical offset for VTK data [km].
Definition: mptrac.h:3223
int qnt_v
Quantity array index for meridional wind.
Definition: mptrac.h:2341
int qnt_oh
Quantity array index for OH volume mixing ratio (climatology).
Definition: mptrac.h:2398
int qnt_h2o
Quantity array index for water vapor volume mixing ratio.
Definition: mptrac.h:2347
int prof_ny
Number of latitudes of gridded profile data.
Definition: mptrac.h:3169
int qnt_rhice
Quantity array index for relative humidity over ice.
Definition: mptrac.h:2446
int qnt_rho
Quantity array index for density of air.
Definition: mptrac.h:2335
double sample_dz
Layer depth for sample output [km].
Definition: mptrac.h:3190
int obs_type
Type of observation data files (0=ASCII, 1=netCDF).
Definition: mptrac.h:3031
int grid_nc_quant[NQ]
Number of digits for quantization of netCDF grid data files (0=off).
Definition: mptrac.h:3109
int qnt_us
Quantity array index for surface zonal wind.
Definition: mptrac.h:2290
double grid_lon1
Upper longitude of gridded data [deg].
Definition: mptrac.h:3130
char atm_basename[LEN]
Basename of atmospheric data files.
Definition: mptrac.h:3001
int qnt_pt
Quantity array index for tropopause pressure.
Definition: mptrac.h:2314
int qnt_cl
Quantity array index for total column cloud water.
Definition: mptrac.h:2374
double prof_z1
Upper altitude of gridded profile data [km].
Definition: mptrac.h:3157
double met_lev_hyam[EP]
Meteo data model level a coefficients.
Definition: mptrac.h:2672
int qnt_t
Quantity array index for temperature.
Definition: mptrac.h:2332
int atm_filter
Time filter for atmospheric data output (0=none, 1=missval, 2=remove).
Definition: mptrac.h:3010
int kpp_chem
Switch for KPP chemistry module (0=off, 1=on).
Definition: mptrac.h:2946
char ens_basename[LEN]
Basename of ensemble data file.
Definition: mptrac.h:3085
double csi_z0
Lower altitude of gridded CSI data [km].
Definition: mptrac.h:3061
int qnt_lapse
Quantity array index for lapse rate.
Definition: mptrac.h:2461
double stat_lat
Latitude of station [deg].
Definition: mptrac.h:3199
int grid_ny
Number of latitudes of gridded data.
Definition: mptrac.h:3133
int qnt_cape
Quantity array index for convective available potential energy (CAPE).
Definition: mptrac.h:2386
int qnt_o3c
Quantity array index for total column ozone.
Definition: mptrac.h:2392
int grid_nz
Number of altitudes of gridded data.
Definition: mptrac.h:3115
int qnt_nss
Quantity array index for northward turbulent surface stress.
Definition: mptrac.h:2299
double ens_dt_out
Time step for ensemble output [s].
Definition: mptrac.h:3088
char sample_basename[LEN]
Basename of sample data file.
Definition: mptrac.h:3178
int atm_stride
Particle index stride for atmospheric data files.
Definition: mptrac.h:3013
int met_relhum
Try to read relative humidity (0=no, 1=yes).
Definition: mptrac.h:2684
double atm_dt_out
Time step for atmospheric data output [s].
Definition: mptrac.h:3007
double prof_lat1
Upper latitude of gridded profile data [deg].
Definition: mptrac.h:3175
double psc_h2o
H2O volume mixing ratio for PSC analysis.
Definition: mptrac.h:2991
double prof_lon0
Lower longitude of gridded profile data [deg].
Definition: mptrac.h:3163
int qnt_pct
Quantity array index for cloud top pressure.
Definition: mptrac.h:2368
int qnt_mloss_kpp
Quantity array index for total mass loss due to KPP chemistry.
Definition: mptrac.h:2416
int qnt_psat
Quantity array index for saturation pressure over water.
Definition: mptrac.h:2431
double met_lev_hybm[EP]
Meteo data model level b coefficients.
Definition: mptrac.h:2675
double prof_lat0
Lower latitude of gridded profile data [deg].
Definition: mptrac.h:3172
int qnt_cin
Quantity array index for convective inhibition (CIN).
Definition: mptrac.h:2389
double psc_hno3
HNO3 volume mixing ratio for PSC analysis.
Definition: mptrac.h:2994
double prof_lon1
Upper longitude of gridded profile data [deg].
Definition: mptrac.h:3166
int h2o2_chem_reaction
Reaction type for H2O2 chemistry (0=none, 1=SO2).
Definition: mptrac.h:2943
int atm_nc_quant[NQ]
Number of digits for quantization of netCDF atmospheric data files (0=off).
Definition: mptrac.h:3028
int grid_sparse
Sparse output in grid data files (0=no, 1=yes).
Definition: mptrac.h:3103
char vtk_basename[LEN]
Basename of VTK data files.
Definition: mptrac.h:3211
int qnt_tt
Quantity array index for tropopause temperature.
Definition: mptrac.h:2317
double mixing_dt
Time interval for mixing [s].
Definition: mptrac.h:2871
double vtk_scale
Vertical scaling factor for VTK data.
Definition: mptrac.h:3220
int qnt_pv
Quantity array index for potential vorticity.
Definition: mptrac.h:2470
int qnt_sst
Quantity array index for sea surface temperature.
Definition: mptrac.h:2308
int atm_nc_level
zlib compression level of netCDF atmospheric data files (0=off).
Definition: mptrac.h:3025
int qnt_sh
Quantity array index for specific humidity.
Definition: mptrac.h:2440
char csi_ens_basename[LEN]
Basename of CSI ensemble data files.
Definition: mptrac.h:3037
int qnt_ess
Quantity array index for eastward turbulent surface stress.
Definition: mptrac.h:2296
int qnt_idx
Quantity array index for air parcel IDs.
Definition: mptrac.h:2260
double met_tropo_theta
Dynamical tropopause potential temperature threshold [K].
Definition: mptrac.h:2706
int qnt_rwc
Quantity array index for cloud rain water content.
Definition: mptrac.h:2356
char qnt_longname[NQ][LEN]
Quantity long names.
Definition: mptrac.h:2251
double sample_dx
Horizontal radius for sample output [km].
Definition: mptrac.h:3187
int vtk_stride
Particle index stride for VTK data.
Definition: mptrac.h:3217
char stat_basename[LEN]
Basename of station data file.
Definition: mptrac.h:3193
double grid_lat1
Upper latitude of gridded data [deg].
Definition: mptrac.h:3139
int qnt_zt
Quantity array index for tropopause geopotential height.
Definition: mptrac.h:2320
int qnt_cc
Quantity array index for cloud cover.
Definition: mptrac.h:2365
int qnt_plcl
Quantity array index for pressure at lifted condensation level (LCL).
Definition: mptrac.h:2377
double grid_dt_out
Time step for gridded data output [s].
Definition: mptrac.h:3100
int qnt_tdew
Quantity array index for dew point temperature.
Definition: mptrac.h:2473
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 5709 of file mptrac.c.

5713 {
5714
5715 /* Write info... */
5716 LOG(1, "Read meteo data: %s", filename);
5717
5718 /* Set rank... */
5719 int rank = 0;
5720#ifdef MPI
5721 if (ctl->met_mpi_share)
5722 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5723#endif
5724
5725 /* Check rank... */
5726 if (!ctl->met_mpi_share || rank == 0) {
5727
5728 /* Read netCDF data... */
5729 if (ctl->met_type == 0) {
5730 if (read_met_nc(filename, ctl, clim, met) != 1)
5731 return 0;
5732 }
5733
5734 /* Read binary data... */
5735 else if (ctl->met_type >= 1 && ctl->met_type <= 5) {
5736 if (read_met_bin(filename, ctl, met) != 1)
5737 return 0;
5738 }
5739#ifdef ECCODES
5740 /* Read grib data... */
5741 else if (ctl->met_type == 6) {
5742 if (read_met_grib(filename, ctl, clim, met) != 1)
5743 return 0;
5744 }
5745#endif
5746
5747 /* Not implemented... */
5748 else
5749 ERRMSG("MET_TYPE not implemented!");
5750 }
5751
5752 /* Broadcast data via MPI... */
5753#ifdef MPI
5754 if (ctl->met_mpi_share) {
5755
5756 /* Set timer... */
5757 SELECT_TIMER("READ_MET_MPI_BCAST", "COMM", NVTX_SEND);
5758 LOG(2, "Broadcast data on rank %d...", rank);
5759
5760 /* Broadcast... */
5761 broadcast_large_data(met, sizeof(met_t));
5762 }
5763#endif
5764
5765 /* Return success... */
5766 return 1;
5767}
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:8397
int read_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a binary file.
Definition: mptrac.c:6767
int read_met_grib(const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met)
Reads global meteorological information from a grib file.
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 5771 of file mptrac.c.

5778 {
5779
5780 /* Initialize modules... */
5781 if (t == ctl->t_start) {
5782
5783 /* Initialize isosurface data... */
5784 if (ctl->isosurf >= 1 && ctl->isosurf <= 4)
5785 module_isosurf_init(ctl, cache, *met0, *met1, atm);
5786
5787 /* Initialize advection... */
5788 module_advect_init(ctl, cache, *met0, *met1, atm);
5789
5790 /* Initialize chemistry... */
5791 module_chem_init(ctl, cache, clim, *met0, *met1, atm);
5792 }
5793
5794 /* Set time steps of air parcels... */
5795 module_timesteps(ctl, cache, *met0, atm, t);
5796
5797 /* Sort particles... */
5798 if (ctl->sort_dt > 0 && fmod(t, ctl->sort_dt) == 0)
5799 module_sort(ctl, *met0, atm);
5800
5801 /* Check positions (initial)... */
5802 module_position(cache, *met0, *met1, atm);
5803
5804 /* Advection... */
5805 if (ctl->advect > 0)
5806 module_advect(ctl, cache, *met0, *met1, atm);
5807
5808 /* Turbulent diffusion... */
5809 if (ctl->diffusion == 1
5810 && (ctl->turb_dx_pbl > 0 || ctl->turb_dz_pbl > 0
5811 || ctl->turb_dx_trop > 0 || ctl->turb_dz_trop > 0
5812 || ctl->turb_dx_strat > 0 || ctl->turb_dz_strat > 0))
5813 module_diff_turb(ctl, cache, clim, *met0, *met1, atm);
5814
5815 /* Mesoscale diffusion... */
5816 if (ctl->diffusion == 1 && (ctl->turb_mesox > 0 || ctl->turb_mesoz > 0))
5817 module_diff_meso(ctl, cache, *met0, *met1, atm);
5818
5819 /* Diffusion... */
5820 if (ctl->diffusion == 2)
5821 module_diff_pbl(ctl, cache, *met0, *met1, atm);
5822
5823 /* Convection... */
5824 if ((ctl->conv_mix_pbl || ctl->conv_cape >= 0)
5825 && (ctl->conv_dt <= 0 || fmod(t, ctl->conv_dt) == 0))
5826 module_convection(ctl, cache, *met0, *met1, atm);
5827
5828 /* Sedimentation... */
5829 if (ctl->qnt_rp >= 0 && ctl->qnt_rhop >= 0)
5830 module_sedi(ctl, cache, *met0, *met1, atm);
5831
5832 /* Isosurface... */
5833 if (ctl->isosurf >= 1 && ctl->isosurf <= 4)
5834 module_isosurf(ctl, cache, *met0, *met1, atm);
5835
5836 /* Check positions (final)... */
5837 module_position(cache, *met0, *met1, atm);
5838
5839 /* Interpolate meteo data... */
5840 if (ctl->met_dt_out > 0
5841 && (ctl->met_dt_out < ctl->dt_mod || fmod(t, ctl->met_dt_out) == 0))
5842 module_meteo(ctl, cache, clim, *met0, *met1, atm);
5843
5844 /* Check boundary conditions (initial)... */
5845 if ((ctl->bound_lat0 < ctl->bound_lat1)
5846 && (ctl->bound_p0 > ctl->bound_p1))
5847 module_bound_cond(ctl, cache, clim, *met0, *met1, atm);
5848
5849 /* Initialize quantity of total loss rate... */
5850 if (ctl->qnt_loss_rate >= 0) {
5851 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,atm)") {
5852 atm->q[ctl->qnt_loss_rate][ip] = 0;
5853 }
5854 }
5855
5856 /* Decay of particle mass... */
5857 if (ctl->tdec_trop > 0 && ctl->tdec_strat > 0)
5858 module_decay(ctl, cache, clim, atm);
5859
5860 /* Interparcel mixing... */
5861 if (ctl->mixing_trop >= 0 && ctl->mixing_strat >= 0
5862 && (ctl->mixing_dt <= 0 || fmod(t, ctl->mixing_dt) == 0))
5863 module_mixing(ctl, clim, atm, t);
5864
5865 /* Calculate the tracer vmr in the chemistry grid... */
5866 if (ctl->oh_chem_reaction != 0 || ctl->h2o2_chem_reaction != 0
5867 || (ctl->kpp_chem && fmod(t, ctl->dt_kpp) == 0)) {
5868 if (ctl->nens > 0)
5869 module_chem_grid_ens(ctl, *met0, *met1, atm, t);
5870 else
5871 module_chem_grid(ctl, *met0, *met1, atm, t);
5872 }
5873
5874 /* OH chemistry... */
5875 if (ctl->oh_chem_reaction != 0)
5876 module_oh_chem(ctl, cache, clim, *met0, *met1, atm);
5877
5878 /* H2O2 chemistry (for SO2 aqueous phase oxidation)... */
5879 if (ctl->h2o2_chem_reaction != 0)
5880 module_h2o2_chem(ctl, cache, clim, *met0, *met1, atm);
5881
5882 /* First-order tracer chemistry... */
5883 if (ctl->tracer_chem)
5884 module_tracer_chem(ctl, cache, clim, *met0, *met1, atm);
5885
5886 /* KPP chemistry... */
5887 if (ctl->kpp_chem && fmod(t, ctl->dt_kpp) == 0) {
5888#ifdef KPP
5889 module_kpp_chem(ctl, cache, clim, *met0, *met1, atm);
5890#else
5891 ERRMSG("Code was compiled without KPP!");
5892#endif
5893 }
5894
5895 /* Wet deposition... */
5896 if ((ctl->wet_depo_ic_a > 0 || ctl->wet_depo_ic_h[0] > 0)
5897 && (ctl->wet_depo_bc_a > 0 || ctl->wet_depo_bc_h[0] > 0))
5898 module_wet_depo(ctl, cache, *met0, *met1, atm);
5899
5900 /* Dry deposition... */
5901 if (ctl->dry_depo_vdep > 0)
5902 module_dry_depo(ctl, cache, *met0, *met1, atm);
5903
5904 /* Check boundary conditions (final)... */
5905 if ((ctl->bound_lat0 < ctl->bound_lat1)
5906 && (ctl->bound_p0 > ctl->bound_p1))
5907 module_bound_cond(ctl, cache, clim, *met0, *met1, atm);
5908}
void module_advect(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Advances particle positions using different advection schemes.
Definition: mptrac.c:2130
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:4252
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:3433
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:2819
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:2704
void module_chem_grid_ens(const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double tt)
Processes atmospheric ensemble chemical data on a defined 3D grid.
Definition: mptrac.c:2553
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:3537
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:3258
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:4390
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:2406
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:4127
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:2746
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:2310
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:2283
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:3940
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:2858
void module_sort(const ctl_t *ctl, met_t *met0, atm_t *atm)
Sort particles according to box index.
Definition: mptrac.c:4156
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:3060
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:4320
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:3175
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:2935
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:3328
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:3856
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:3112
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 6024 of file mptrac.c.

6028 {
6029
6030 /* Set timer... */
6031 SELECT_TIMER("WRITE_ATM", "OUTPUT", NVTX_WRITE);
6032
6033 /* Write info... */
6034 LOG(1, "Write atmospheric data: %s", filename);
6035
6036 /* Write ASCII data... */
6037 if (ctl->atm_type_out == 0)
6038 write_atm_asc(filename, ctl, atm, t);
6039
6040 /* Write binary data... */
6041 else if (ctl->atm_type_out == 1)
6042 write_atm_bin(filename, ctl, atm);
6043
6044 /* Write netCDF data... */
6045 else if (ctl->atm_type_out == 2)
6046 write_atm_nc(filename, ctl, atm);
6047
6048 /* Write CLaMS trajectory data... */
6049 else if (ctl->atm_type_out == 3)
6050 write_atm_clams_traj(filename, ctl, atm, t);
6051
6052 /* Write CLaMS pos data... */
6053 else if (ctl->atm_type_out == 4)
6054 write_atm_clams(filename, ctl, atm);
6055
6056 /* Error... */
6057 else
6058 ERRMSG("Atmospheric data type not supported!");
6059
6060 /* Write info... */
6061 double mini, maxi;
6062 LOG(2, "Number of particles: %d", atm->np);
6063 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
6064 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
6065 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
6066 LOG(2, "Altitude range: %g ... %g km", Z(maxi), Z(mini));
6067 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
6068 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
6069 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
6070 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
6071 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
6072 for (int iq = 0; iq < ctl->nq; iq++) {
6073 char msg[5 * LEN];
6074 sprintf(msg, "Quantity %s range: %s ... %s %s",
6075 ctl->qnt_name[iq], ctl->qnt_format[iq],
6076 ctl->qnt_format[iq], ctl->qnt_unit[iq]);
6077 gsl_stats_minmax(&mini, &maxi, atm->q[iq], 1, (size_t) atm->np);
6078 LOG(2, msg, mini, maxi);
6079 }
6080}
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:10390
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:10205
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:10337
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:10287
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:10548
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 6084 of file mptrac.c.

6087 {
6088
6089 /* Set timer... */
6090 SELECT_TIMER("WRITE_MET", "OUTPUT", NVTX_WRITE);
6091
6092 /* Write info... */
6093 LOG(1, "Write meteo data: %s", filename);
6094
6095 /* Check compression flags... */
6096#ifndef ZFP
6097 if (ctl->met_type == 3)
6098 ERRMSG("MPTRAC was compiled without zfp compression!");
6099#endif
6100#ifndef ZSTD
6101 if (ctl->met_type == 4)
6102 ERRMSG("MPTRAC was compiled without zstd compression!");
6103#endif
6104#ifndef CMS
6105 if (ctl->met_type == 5)
6106 ERRMSG("MPTRAC was compiled without cmultiscale compression!");
6107#endif
6108
6109 /* Write netCDF data... */
6110 if (ctl->met_type == 0)
6111 write_met_nc(filename, ctl, met);
6112
6113 /* Write binary data... */
6114 else if (ctl->met_type >= 1 && ctl->met_type <= 5)
6115 write_met_bin(filename, ctl, met);
6116
6117 /* Not implemented... */
6118 else
6119 ERRMSG("MET_TYPE not implemented!");
6120}
void write_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a NetCDF file.
Definition: mptrac.c:11884
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:11678
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 6124 of file mptrac.c.

6130 {
6131
6132 char ext[10], filename[2 * LEN];
6133
6134 double r;
6135
6136 int year, mon, day, hour, min, sec;
6137
6138 /* Get time... */
6139 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
6140
6141 /* Update host... */
6142 if ((ctl->atm_basename[0] != '-' && fmod(t, ctl->atm_dt_out) == 0)
6143 || (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0)
6144 || (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0)
6145 || ctl->csi_basename[0] != '-' || ctl->prof_basename[0] != '-'
6146 || ctl->sample_basename[0] != '-' || ctl->stat_basename[0] != '-'
6147 || (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0))
6148 mptrac_update_host(NULL, NULL, NULL, NULL, NULL, atm);
6149
6150 /* Write atmospheric data... */
6151 if (ctl->atm_basename[0] != '-' &&
6152 (fmod(t, ctl->atm_dt_out) == 0 || t == ctl->t_stop)) {
6153 if (ctl->atm_type_out == 0)
6154 sprintf(ext, "tab");
6155 else if (ctl->atm_type_out == 1)
6156 sprintf(ext, "bin");
6157 else if (ctl->atm_type_out == 2)
6158 sprintf(ext, "nc");
6159 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6160 dirname, ctl->atm_basename, year, mon, day, hour, min, ext);
6161 mptrac_write_atm(filename, ctl, atm, t);
6162 }
6163
6164 /* Write gridded data... */
6165 if (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0) {
6166 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6167 dirname, ctl->grid_basename, year, mon, day, hour, min,
6168 ctl->grid_type == 0 ? "tab" : "nc");
6169 write_grid(filename, ctl, met0, met1, atm, t);
6170 }
6171
6172 /* Write CSI data... */
6173 if (ctl->csi_basename[0] != '-') {
6174 sprintf(filename, "%s/%s.tab", dirname, ctl->csi_basename);
6175 write_csi(filename, ctl, atm, t);
6176 }
6177
6178 /* Write CSI ensemble data... */
6179 if (ctl->csi_ens_basename[0] != '-') {
6180 sprintf(filename, "%s/%s.tab", dirname, ctl->csi_ens_basename);
6181 write_csi_ens(filename, ctl, atm, t);
6182 }
6183
6184 /* Write ensemble data... */
6185 if (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0) {
6186 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
6187 dirname, ctl->ens_basename, year, mon, day, hour, min);
6188 write_ens(filename, ctl, atm, t);
6189 }
6190
6191 /* Write profile data... */
6192 if (ctl->prof_basename[0] != '-') {
6193 sprintf(filename, "%s/%s.tab", dirname, ctl->prof_basename);
6194 write_prof(filename, ctl, met0, met1, atm, t);
6195 }
6196
6197 /* Write sample data... */
6198 if (ctl->sample_basename[0] != '-') {
6199 sprintf(filename, "%s/%s.tab", dirname, ctl->sample_basename);
6200 write_sample(filename, ctl, met0, met1, atm, t);
6201 }
6202
6203 /* Write station data... */
6204 if (ctl->stat_basename[0] != '-') {
6205 sprintf(filename, "%s/%s.tab", dirname, ctl->stat_basename);
6206 write_station(filename, ctl, atm, t);
6207 }
6208
6209 /* Write VTK data... */
6210 if (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0) {
6211 static int nvtk;
6212 if (t == ctl->t_start)
6213 nvtk = 0;
6214 sprintf(filename, "%s/%s_%05d.vtk", dirname, ctl->vtk_basename, ++nvtk);
6215 write_vtk(filename, ctl, atm, t);
6216 }
6217}
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:6024
void write_csi_ens(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes ensemble-based Critical Success Index (CSI) and other verification statistics to an output fil...
Definition: mptrac.c:10859
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:11156
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:12107
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:5968
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:12496
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:12582
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:12334
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:11253
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:10597
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 5912 of file mptrac.c.

5918 {
5919
5920 /* Update GPU... */
5921 if (ctl != NULL) {
5922#ifdef _OPENACC
5923 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5924#pragma acc update device(ctl[:1])
5925#endif
5926 }
5927
5928 if (cache != NULL) {
5929#ifdef _OPENACC
5930 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5931#pragma acc update device(cache[:1])
5932#endif
5933 }
5934
5935 if (clim != NULL) {
5936#ifdef _OPENACC
5937 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5938#pragma acc update device(clim[:1])
5939#endif
5940 }
5941
5942 if (met0 != NULL) {
5943#ifdef _OPENACC
5944 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5945 met_t *met0up = *met0;
5946#pragma acc update device(met0up[:1])
5947#endif
5948 }
5949
5950 if (met1 != NULL) {
5951#ifdef _OPENACC
5952 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5953 met_t *met1up = *met1;
5954#pragma acc update device(met1up[:1])
5955#endif
5956 }
5957
5958 if (atm != NULL) {
5959#ifdef _OPENACC
5960 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5961#pragma acc update device(atm[:1])
5962#endif
5963 }
5964}

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

5974 {
5975
5976 /* Update GPU... */
5977 if (ctl != NULL) {
5978#ifdef _OPENACC
5979 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5980#pragma acc update host(ctl[:1])
5981#endif
5982 }
5983
5984 if (cache != NULL) {
5985#ifdef _OPENACC
5986 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5987#pragma acc update host(cache[:1])
5988#endif
5989 }
5990
5991 if (clim != NULL) {
5992#ifdef _OPENACC
5993 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5994#pragma acc update host(clim[:1])
5995#endif
5996 }
5997
5998 if (met0 != NULL) {
5999#ifdef _OPENACC
6000 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
6001 met_t *met0up = *met0;
6002#pragma acc update host(met0up[:1])
6003#endif
6004 }
6005
6006 if (met1 != NULL) {
6007#ifdef _OPENACC
6008 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
6009 met_t *met1up = *met1;
6010#pragma acc update host(met1up[:1])
6011#endif
6012 }
6013
6014 if (atm != NULL) {
6015#ifdef _OPENACC
6016 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
6017#pragma acc update host(atm[:1])
6018#endif
6019 }
6020}

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

6224 {
6225
6226 /* Check water vapor volume mixing ratio... */
6227 const double h2o_help = MAX(h2o, 0.1e-6);
6228
6229 /* Calculate T_NAT... */
6230 const double p_hno3 = hno3 * p / 1.333224;
6231 const double p_h2o = h2o_help * p / 1.333224;
6232 const double a = 0.009179 - 0.00088 * log10(p_h2o);
6233 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
6234 const double c = -11397.0 / a;
6235 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
6236 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
6237 if (x2 > 0)
6238 tnat = x2;
6239
6240 return tnat;
6241}

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

6250 {
6251
6252 /* Get pressure range... */
6253 const double p1 = pbl - ctl->conv_pbl_trans * (ps - pbl);
6254 const double p0 = pbl;
6255
6256 /* Get weighting factor... */
6257 if (atm->p[ip] > p0)
6258 return 1;
6259 else if (atm->p[ip] < p1)
6260 return 0;
6261 else
6262 return LIN(p0, 1.0, p1, 0.0, atm->p[ip]);
6263}

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

6270 {
6271
6272 /* Open file... */
6273 FILE *in;
6274 if (!(in = fopen(filename, "r"))) {
6275 WARN("Cannot open file!");
6276 return 0;
6277 }
6278
6279 /* Read line... */
6280 char line[LEN];
6281 while (fgets(line, LEN, in)) {
6282
6283 /* Read data... */
6284 char *tok;
6285 TOK(line, tok, "%lg", atm->time[atm->np]);
6286 TOK(NULL, tok, "%lg", atm->p[atm->np]);
6287 TOK(NULL, tok, "%lg", atm->lon[atm->np]);
6288 TOK(NULL, tok, "%lg", atm->lat[atm->np]);
6289 for (int iq = 0; iq < ctl->nq; iq++)
6290 TOK(NULL, tok, "%lg", atm->q[iq][atm->np]);
6291
6292 /* Convert altitude to pressure... */
6293 atm->p[atm->np] = P(atm->p[atm->np]);
6294
6295 /* Increment data point counter... */
6296 if ((++atm->np) > NP)
6297 ERRMSG("Too many data points!");
6298 }
6299
6300 /* Close file... */
6301 fclose(in);
6302
6303 /* Return success... */
6304 return 1;
6305}
#define TOK(line, tok, format, var)
Get string tokens.
Definition: mptrac.h:1774

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

6312 {
6313
6314 /* Open file... */
6315 FILE *in;
6316 if (!(in = fopen(filename, "r")))
6317 return 0;
6318
6319 /* Check version of binary data... */
6320 int version;
6321 FREAD(&version, int,
6322 1,
6323 in);
6324 if (version != 100)
6325 ERRMSG("Wrong version of binary data!");
6326
6327 /* Read data... */
6328 FREAD(&atm->np, int,
6329 1,
6330 in);
6331 FREAD(atm->time, double,
6332 (size_t) atm->np,
6333 in);
6334 FREAD(atm->p, double,
6335 (size_t) atm->np,
6336 in);
6337 FREAD(atm->lon, double,
6338 (size_t) atm->np,
6339 in);
6340 FREAD(atm->lat, double,
6341 (size_t) atm->np,
6342 in);
6343 for (int iq = 0; iq < ctl->nq; iq++)
6344 FREAD(atm->q[iq], double,
6345 (size_t) atm->np,
6346 in);
6347
6348 /* Read final flag... */
6349 int final;
6350 FREAD(&final, int,
6351 1,
6352 in);
6353 if (final != 999)
6354 ERRMSG("Error while reading binary data!");
6355
6356 /* Close file... */
6357 fclose(in);
6358
6359 /* Return success... */
6360 return 1;
6361}

◆ read_atm_clams()

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

Reads atmospheric data from a CLAMS NetCDF file.

This function opens a NetCDF file, reads various atmospheric parameters, and stores them in the provided atm_t structure. It handles both zeta and pressure coordinate systems depending on the control settings.

Parameters
[in]filenamePath to the NetCDF file containing atmospheric data.
[in]ctlPointer to the control structure containing configuration settings.
[out]atmPointer to the atmospheric data structure where the data will be stored.
Returns
Returns 1 on success, 0 on failure.
  • Opens the NetCDF file in read-only mode.
  • Retrieves the number of particles (NPARTS).
  • Reads initial time (TIME_INIT) or falls back to time if unavailable.
  • Depending on ctl->advect_vert_coord, reads ZETA and optionally PRESS, or reads PRESS_INIT with fallback to PRESS.
  • Reads longitude (LON) and latitude (LAT).
  • Closes the NetCDF file before returning.
Author
Jan Clemens

Definition at line 6365 of file mptrac.c.

6368 {
6369
6370 int ncid, varid;
6371
6372 /* Open file... */
6373 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6374 return 0;
6375
6376 /* Get dimensions... */
6377 NC_INQ_DIM("NPARTS", &atm->np, 1, NP);
6378
6379 /* Get time... */
6380 if (nc_inq_varid(ncid, "TIME_INIT", &varid) == NC_NOERR) {
6381 NC(nc_get_var_double(ncid, varid, atm->time));
6382 } else {
6383 WARN("TIME_INIT not found use time instead!");
6384 double time_init;
6385 NC_GET_DOUBLE("time", &time_init, 1);
6386 for (int ip = 0; ip < atm->np; ip++) {
6387 atm->time[ip] = time_init;
6388 }
6389 }
6390
6391 /* Read zeta coordinate, pressure is optional... */
6392 if (ctl->advect_vert_coord == 1) {
6393 NC_GET_DOUBLE("ZETA", atm->q[ctl->qnt_zeta], 1);
6394 NC_GET_DOUBLE("PRESS", atm->p, 0);
6395 }
6396
6397 /* Read pressure, zeta coordinate is optional... */
6398 else {
6399 if (nc_inq_varid(ncid, "PRESS_INIT", &varid) == NC_NOERR) {
6400 NC(nc_get_var_double(ncid, varid, atm->p));
6401 } else {
6402 WARN("PRESS_INIT not found use PRESS instead!");
6403 nc_inq_varid(ncid, "PRESS", &varid);
6404 NC(nc_get_var_double(ncid, varid, atm->p));
6405 }
6406 }
6407
6408 /* Read longitude and latitude... */
6409 NC_GET_DOUBLE("LON", atm->lon, 1);
6410 NC_GET_DOUBLE("LAT", atm->lat, 1);
6411
6412 /* Close file... */
6413 NC(nc_close(ncid));
6414
6415 /* Return success... */
6416 return 1;
6417}
#define NC(cmd)
Execute a NetCDF command and check for errors.
Definition: mptrac.h:1096
#define NC_INQ_DIM(dimname, ptr, min, max)
Inquire the length of a dimension in a NetCDF file.
Definition: mptrac.h:1183
#define NC_GET_DOUBLE(varname, ptr, force)
Retrieve a double-precision variable from a NetCDF file.
Definition: mptrac.h:1155

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

6424 {
6425
6426 int ncid, varid;
6427
6428 /* Open file... */
6429 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6430 return 0;
6431
6432 /* Get dimensions... */
6433 NC_INQ_DIM("obs", &atm->np, 1, NP);
6434
6435 /* Read geolocations... */
6436 NC_GET_DOUBLE("time", atm->time, 1);
6437 NC_GET_DOUBLE("press", atm->p, 1);
6438 NC_GET_DOUBLE("lon", atm->lon, 1);
6439 NC_GET_DOUBLE("lat", atm->lat, 1);
6440
6441 /* Read variables... */
6442 for (int iq = 0; iq < ctl->nq; iq++)
6443 NC_GET_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
6444
6445 /* Close file... */
6446 NC(nc_close(ncid));
6447
6448 /* Return success... */
6449 return 1;
6450}

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

6456 {
6457
6458 int ncid, varid;
6459
6460 /* Write info... */
6461 LOG(1, "Read photolysis rates: %s", filename);
6462
6463 /* Open netCDF file... */
6464 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
6465 WARN("Photolysis rate data are missing!");
6466 return;
6467 }
6468
6469 /* Read pressure data... */
6470 NC_INQ_DIM("press", &photo->np, 2, CP);
6471 NC_GET_DOUBLE("press", photo->p, 1);
6472 if (photo->p[0] < photo->p[1])
6473 ERRMSG("Pressure data are not descending!");
6474
6475 /* Read total column ozone data... */
6476 NC_INQ_DIM("total_o3col", &photo->no3c, 2, CO3);
6477 NC_GET_DOUBLE("total_o3col", photo->o3c, 1);
6478 if (photo->o3c[0] > photo->o3c[1])
6479 ERRMSG("Total column ozone data are not ascending!");
6480
6481 /* Read solar zenith angle data... */
6482 NC_INQ_DIM("sza", &photo->nsza, 2, CSZA);
6483 NC_GET_DOUBLE("sza", photo->sza, 1);
6484 if (photo->sza[0] > photo->sza[1])
6485 ERRMSG("Solar zenith angle data are not ascending!");
6486
6487 /* Read data... */
6488 read_clim_photo_help(ncid, "J_N2O", photo, photo->n2o);
6489 read_clim_photo_help(ncid, "J_CCl4", photo, photo->ccl4);
6490 read_clim_photo_help(ncid, "J_CFC-11", photo, photo->ccl3f);
6491 read_clim_photo_help(ncid, "J_CFC-12", photo, photo->ccl2f2);
6492 read_clim_photo_help(ncid, "J_O2", photo, photo->o2);
6493 read_clim_photo_help(ncid, "J_O3b", photo, photo->o3_1);
6494 read_clim_photo_help(ncid, "J_O3a", photo, photo->o3_2);
6495 read_clim_photo_help(ncid, "J_H2O2", photo, photo->h2o2);
6496 read_clim_photo_help(ncid, "J_H2O", photo, photo->h2o);
6497
6498 /* Close netCDF file... */
6499 NC(nc_close(ncid));
6500
6501 /* Write info... */
6502 LOG(2, "Number of pressure levels: %d", photo->np);
6503 LOG(2, "Altitude levels: %g, %g ... %g km",
6504 Z(photo->p[0]), Z(photo->p[1]), Z(photo->p[photo->np - 1]));
6505 LOG(2, "Pressure levels: %g, %g ... %g hPa",
6506 photo->p[0], photo->p[1], photo->p[photo->np - 1]);
6507 LOG(2, "Number of solar zenith angles: %d", photo->nsza);
6508 LOG(2, "Solar zenith angles: %g, %g ... %g deg",
6509 RAD2DEG(photo->sza[0]), RAD2DEG(photo->sza[1]),
6510 RAD2DEG(photo->sza[photo->nsza - 1]));
6511 LOG(2, "Number of total column ozone values: %d", photo->no3c);
6512 LOG(2, "Total column ozone: %g, %g ... %g DU",
6513 photo->o3c[0], photo->o3c[1], photo->o3c[photo->no3c - 1]);
6514 LOG(2, "N2O photolysis rate: %g, %g ... %g s**-1",
6515 photo->n2o[0][0][0], photo->n2o[1][0][0],
6516 photo->n2o[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6517 LOG(2, "CCl4 photolysis rate: %g, %g ... %g s**-1",
6518 photo->ccl4[0][0][0], photo->ccl4[1][0][0],
6519 photo->ccl4[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6520 LOG(2, "CFC-11 photolysis rate: %g, %g ... %g s**-1",
6521 photo->ccl3f[0][0][0], photo->ccl3f[1][0][0],
6522 photo->ccl3f[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6523 LOG(2, "CFC-12 photolysis rate: %g, %g ... %g s**-1",
6524 photo->ccl2f2[0][0][0], photo->ccl2f2[1][0][0],
6525 photo->ccl2f2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6526 LOG(2, "O2 photolysis rate: %g, %g ... %g s**-1",
6527 photo->o2[0][0][0], photo->o2[1][0][0],
6528 photo->o2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6529 LOG(2, "O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
6530 photo->o3_1[0][0][0], photo->o3_1[1][0][0],
6531 photo->o3_1[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6532 LOG(2, "O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
6533 photo->o3_2[0][0][0], photo->o3_2[1][0][0],
6534 photo->o3_2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6535 LOG(2, "H2O2 photolysis rate: %g, %g ... %g s**-1",
6536 photo->h2o2[0][0][0], photo->h2o2[1][0][0],
6537 photo->h2o2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6538 LOG(2, "H2O photolysis rate: %g, %g ... %g s**-1",
6539 photo->h2o[0][0][0], photo->h2o[1][0][0],
6540 photo->h2o[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6541}
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:6545
#define CP
Maximum number of pressure levels for climatological data.
Definition: mptrac.h:316
#define CO3
Maximum number of total column ozone data for climatological data.
Definition: mptrac.h:311
#define CSZA
Maximum number of solar zenith angles for climatological data.
Definition: mptrac.h:321
double o3_1[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O1d + O2) [1/s].
Definition: mptrac.h:3334
double o2[CP][CSZA][CO3]
O2 photolysis rate [1/s].
Definition: mptrac.h:3331
double h2o2[CP][CSZA][CO3]
H2O2 photolysis rate [1/s].
Definition: mptrac.h:3340
double h2o[CP][CSZA][CO3]
H2O photolysis rate [1/s].
Definition: mptrac.h:3343
double o3_2[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O3p + O2) [1/s].
Definition: mptrac.h:3337
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 6545 of file mptrac.c.

6549 {
6550
6551 /* Allocate... */
6552 double *help;
6553 ALLOC(help, double,
6554 photo->np * photo->nsza * photo->no3c);
6555
6556 /* Read varible... */
6557 int varid;
6558 NC_GET_DOUBLE(varname, help, 1);
6559
6560 /* Copy data... */
6561 for (int ip = 0; ip < photo->np; ip++)
6562 for (int is = 0; is < photo->nsza; is++)
6563 for (int io = 0; io < photo->no3c; io++)
6564 var[ip][is][io] =
6565 help[ARRAY_3D(ip, is, photo->nsza, io, photo->no3c)];
6566
6567 /* Free... */
6568 free(help);
6569}

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

6575 {
6576
6577 /* Write info... */
6578 LOG(1, "Read climatological time series: %s", filename);
6579
6580 /* Open file... */
6581 FILE *in;
6582 if (!(in = fopen(filename, "r"))) {
6583 WARN("Cannot open file!");
6584 return 0;
6585 }
6586
6587 /* Read data... */
6588 char line[LEN];
6589 int nh = 0;
6590 while (fgets(line, LEN, in))
6591 if (sscanf(line, "%lg %lg", &ts->time[nh], &ts->vmr[nh]) == 2) {
6592
6593 /* Convert years to seconds... */
6594 ts->time[nh] = (ts->time[nh] - 2000.0) * 365.25 * 86400.;
6595
6596 /* Check data... */
6597 if (nh > 0 && ts->time[nh] <= ts->time[nh - 1])
6598 ERRMSG("Time series must be ascending!");
6599
6600 /* Count time steps... */
6601 if ((++nh) >= CTS)
6602 ERRMSG("Too many data points!");
6603 }
6604
6605 /* Close file... */
6606 fclose(in);
6607
6608 /* Check number of data points... */
6609 ts->ntime = nh;
6610 if (nh < 2)
6611 ERRMSG("Not enough data points!");
6612
6613 /* Write info... */
6614 LOG(2, "Number of time steps: %d", ts->ntime);
6615 LOG(2, "Time steps: %.2f, %.2f ... %.2f s", ts->time[0], ts->time[1],
6616 ts->time[nh - 1]);
6617 LOG(2, "Volume mixing ratio range: %g ... %g ppv",
6618 gsl_stats_min(ts->vmr, 1, (size_t) nh), gsl_stats_max(ts->vmr, 1,
6619 (size_t) nh));
6620
6621 /* Exit success... */
6622 return 1;
6623}
#define CTS
Maximum number of data points of climatological time series.
Definition: mptrac.h:331

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

6630 {
6631
6632 int ncid, varid, it, iy, iz, iz2, nt;
6633
6634 double *help, varmin = 1e99, varmax = -1e99;
6635
6636 /* Write info... */
6637 LOG(1, "Read %s data: %s", varname, filename);
6638
6639 /* Open netCDF file... */
6640 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
6641 WARN("%s climatology data are missing!", varname);
6642 return;
6643 }
6644
6645 /* Read pressure data... */
6646 NC_INQ_DIM("press", &zm->np, 2, CP);
6647 NC_GET_DOUBLE("press", zm->p, 1);
6648 if (zm->p[0] < zm->p[1])
6649 ERRMSG("Pressure data are not descending!");
6650
6651 /* Read latitudes... */
6652 NC_INQ_DIM("lat", &zm->nlat, 2, CY);
6653 NC_GET_DOUBLE("lat", zm->lat, 1);
6654 if (zm->lat[0] > zm->lat[1])
6655 ERRMSG("Latitude data are not ascending!");
6656
6657 /* Set time data (for monthly means)... */
6658 zm->ntime = 12;
6659 zm->time[0] = 1209600.00;
6660 zm->time[1] = 3888000.00;
6661 zm->time[2] = 6393600.00;
6662 zm->time[3] = 9072000.00;
6663 zm->time[4] = 11664000.00;
6664 zm->time[5] = 14342400.00;
6665 zm->time[6] = 16934400.00;
6666 zm->time[7] = 19612800.00;
6667 zm->time[8] = 22291200.00;
6668 zm->time[9] = 24883200.00;
6669 zm->time[10] = 27561600.00;
6670 zm->time[11] = 30153600.00;
6671
6672 /* Check number of timesteps... */
6673 NC_INQ_DIM("time", &nt, 12, 12);
6674
6675 /* Read data... */
6676 ALLOC(help, double,
6677 zm->nlat * zm->np * zm->ntime);
6678 NC_GET_DOUBLE(varname, help, 1);
6679 for (it = 0; it < zm->ntime; it++)
6680 for (iz = 0; iz < zm->np; iz++)
6681 for (iy = 0; iy < zm->nlat; iy++)
6682 zm->vmr[it][iz][iy] = help[ARRAY_3D(it, iz, zm->np, iy, zm->nlat)];
6683 free(help);
6684
6685 /* Fix data gaps... */
6686 for (it = 0; it < zm->ntime; it++)
6687 for (iy = 0; iy < zm->nlat; iy++)
6688 for (iz = 0; iz < zm->np; iz++) {
6689 if (zm->vmr[it][iz][iy] < 0) {
6690 for (iz2 = 0; iz2 < zm->np; iz2++)
6691 if (zm->vmr[it][iz2][iy] >= 0) {
6692 zm->vmr[it][iz][iy] = zm->vmr[it][iz2][iy];
6693 break;
6694 }
6695 for (iz2 = zm->np - 1; iz2 >= 0; iz2--)
6696 if (zm->vmr[it][iz2][iy] >= 0) {
6697 zm->vmr[it][iz][iy] = zm->vmr[it][iz2][iy];
6698 break;
6699 }
6700 }
6701 varmin = MIN(varmin, zm->vmr[it][iz][iy]);
6702 varmax = MAX(varmax, zm->vmr[it][iz][iy]);
6703 }
6704
6705 /* Close netCDF file... */
6706 NC(nc_close(ncid));
6707
6708 /* Write info... */
6709 LOG(2, "Number of time steps: %d", zm->ntime);
6710 LOG(2, "Time steps: %.2f, %.2f ... %.2f s",
6711 zm->time[0], zm->time[1], zm->time[zm->ntime - 1]);
6712 LOG(2, "Number of pressure levels: %d", zm->np);
6713 LOG(2, "Altitude levels: %g, %g ... %g km",
6714 Z(zm->p[0]), Z(zm->p[1]), Z(zm->p[zm->np - 1]));
6715 LOG(2, "Pressure levels: %g, %g ... %g hPa", zm->p[0],
6716 zm->p[1], zm->p[zm->np - 1]);
6717 LOG(2, "Number of latitudes: %d", zm->nlat);
6718 LOG(2, "Latitudes: %g, %g ... %g deg",
6719 zm->lat[0], zm->lat[1], zm->lat[zm->nlat - 1]);
6720 LOG(2, "%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
6721 varmax);
6722}
#define CY
Maximum number of latitudes for climatological data.
Definition: mptrac.h:306

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

6730 {
6731
6732 /* Write info... */
6733 LOG(1, "Read kernel function: %s", filename);
6734
6735 /* Open file... */
6736 FILE *in;
6737 if (!(in = fopen(filename, "r")))
6738 ERRMSG("Cannot open file!");
6739
6740 /* Read data... */
6741 char line[LEN];
6742 int n = 0;
6743 while (fgets(line, LEN, in))
6744 if (sscanf(line, "%lg %lg", &kz[n], &kw[n]) == 2) {
6745 if (n > 0 && kz[n] < kz[n - 1])
6746 ERRMSG("Height levels must be ascending!");
6747 if ((++n) >= EP)
6748 ERRMSG("Too many height levels!");
6749 }
6750
6751 /* Close file... */
6752 fclose(in);
6753
6754 /* Check number of data points... */
6755 *nk = n;
6756 if (n < 2)
6757 ERRMSG("Not enough height levels!");
6758
6759 /* Normalize kernel function... */
6760 const double kmax = gsl_stats_max(kw, 1, (size_t) n);
6761 for (int iz = 0; iz < n; iz++)
6762 kw[iz] /= kmax;
6763}

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

6770 {
6771
6772 FILE *in;
6773
6774 double r;
6775
6776 int year, mon, day, hour, min, sec;
6777
6778 /* Set timer... */
6779 SELECT_TIMER("READ_MET_BIN", "INPUT", NVTX_READ);
6780
6781 /* Open file... */
6782 if (!(in = fopen(filename, "r"))) {
6783 WARN("Cannot open file!");
6784 return 0;
6785 }
6786
6787 /* Check type of binary data... */
6788 int met_type;
6789 FREAD(&met_type, int,
6790 1,
6791 in);
6792 if (met_type != ctl->met_type)
6793 ERRMSG("Wrong MET_TYPE of binary data!");
6794
6795 /* Check version of binary data... */
6796 int version;
6797 FREAD(&version, int,
6798 1,
6799 in);
6800 if (version != 103)
6801 ERRMSG("Wrong version of binary data!");
6802
6803 /* Read time... */
6804 FREAD(&met->time, double,
6805 1,
6806 in);
6807 jsec2time(met->time, &year, &mon, &day, &hour, &min, &sec, &r);
6808 LOG(2, "Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
6809 met->time, year, mon, day, hour, min);
6810 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
6811 || day < 1 || day > 31 || hour < 0 || hour > 23)
6812 ERRMSG("Error while reading time!");
6813
6814 /* Read dimensions... */
6815 FREAD(&met->nx, int,
6816 1,
6817 in);
6818 LOG(2, "Number of longitudes: %d", met->nx);
6819 if (met->nx < 2 || met->nx > EX)
6820 ERRMSG("Number of longitudes out of range!");
6821
6822 FREAD(&met->ny, int,
6823 1,
6824 in);
6825 LOG(2, "Number of latitudes: %d", met->ny);
6826 if (met->ny < 2 || met->ny > EY)
6827 ERRMSG("Number of latitudes out of range!");
6828
6829 FREAD(&met->np, int,
6830 1,
6831 in);
6832 LOG(2, "Number of levels: %d", met->np);
6833 if (met->np < 2 || met->np > EP)
6834 ERRMSG("Number of levels out of range!");
6835
6836 /* Read grid... */
6837 FREAD(met->lon, double,
6838 (size_t) met->nx,
6839 in);
6840 LOG(2, "Longitudes: %g, %g ... %g deg",
6841 met->lon[0], met->lon[1], met->lon[met->nx - 1]);
6842
6843 FREAD(met->lat, double,
6844 (size_t) met->ny,
6845 in);
6846 LOG(2, "Latitudes: %g, %g ... %g deg",
6847 met->lat[0], met->lat[1], met->lat[met->ny - 1]);
6848
6849 FREAD(met->p, double,
6850 (size_t) met->np,
6851 in);
6852 LOG(2, "Altitude levels: %g, %g ... %g km",
6853 Z(met->p[0]), Z(met->p[1]), Z(met->p[met->np - 1]));
6854 LOG(2, "Pressure levels: %g, %g ... %g hPa",
6855 met->p[0], met->p[1], met->p[met->np - 1]);
6856
6857 /* Read surface data... */
6858 read_met_bin_2d(in, met, met->ps, "PS");
6859 read_met_bin_2d(in, met, met->ts, "TS");
6860 read_met_bin_2d(in, met, met->zs, "ZS");
6861 read_met_bin_2d(in, met, met->us, "US");
6862 read_met_bin_2d(in, met, met->vs, "VS");
6863 read_met_bin_2d(in, met, met->ess, "ESS");
6864 read_met_bin_2d(in, met, met->nss, "NSS");
6865 read_met_bin_2d(in, met, met->shf, "SHF");
6866 read_met_bin_2d(in, met, met->lsm, "LSM");
6867 read_met_bin_2d(in, met, met->sst, "SST");
6868 read_met_bin_2d(in, met, met->pbl, "PBL");
6869 read_met_bin_2d(in, met, met->pt, "PT");
6870 read_met_bin_2d(in, met, met->tt, "TT");
6871 read_met_bin_2d(in, met, met->zt, "ZT");
6872 read_met_bin_2d(in, met, met->h2ot, "H2OT");
6873 read_met_bin_2d(in, met, met->pct, "PCT");
6874 read_met_bin_2d(in, met, met->pcb, "PCB");
6875 read_met_bin_2d(in, met, met->cl, "CL");
6876 read_met_bin_2d(in, met, met->plcl, "PLCL");
6877 read_met_bin_2d(in, met, met->plfc, "PLFC");
6878 read_met_bin_2d(in, met, met->pel, "PEL");
6879 read_met_bin_2d(in, met, met->cape, "CAPE");
6880 read_met_bin_2d(in, met, met->cin, "CIN");
6881 read_met_bin_2d(in, met, met->o3c, "O3C");
6882
6883 /* Read level data... */
6884 read_met_bin_3d(in, ctl, met, met->z, "Z", -1e34f, 1e34f);
6885 read_met_bin_3d(in, ctl, met, met->t, "T", 0, 1e34f);
6886 read_met_bin_3d(in, ctl, met, met->u, "U", -1e34f, 1e34f);
6887 read_met_bin_3d(in, ctl, met, met->v, "V", -1e34f, 1e34f);
6888 read_met_bin_3d(in, ctl, met, met->w, "W", -1e34f, 1e34f);
6889 read_met_bin_3d(in, ctl, met, met->pv, "PV", -1e34f, 1e34f);
6890 read_met_bin_3d(in, ctl, met, met->h2o, "H2O", 0, 1e34f);
6891 read_met_bin_3d(in, ctl, met, met->o3, "O3", 0, 1e34f);
6892 read_met_bin_3d(in, ctl, met, met->lwc, "LWC", 0, 1e34f);
6893 read_met_bin_3d(in, ctl, met, met->rwc, "RWC", 0, 1e34f);
6894 read_met_bin_3d(in, ctl, met, met->iwc, "IWC", 0, 1e34f);
6895 read_met_bin_3d(in, ctl, met, met->swc, "SWC", 0, 1e34f);
6896 read_met_bin_3d(in, ctl, met, met->cc, "CC", 0, 1);
6897
6898 /* Read final flag... */
6899 int final;
6900 FREAD(&final, int,
6901 1,
6902 in);
6903 if (final != 999)
6904 ERRMSG("Error while reading binary data!");
6905
6906 /* Close file... */
6907 fclose(in);
6908
6909 /* Return success... */
6910 return 1;
6911}
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:6915
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:6944
#define EY
Maximum number of latitudes for meteo data.
Definition: mptrac.h:286
float zt[EX][EY]
Tropopause geopotential height [km].
Definition: mptrac.h:3534
float sst[EX][EY]
Sea surface temperature [K].
Definition: mptrac.h:3522
float rwc[EX][EY][EP]
Cloud rain water content [kg/kg].
Definition: mptrac.h:3594
float o3c[EX][EY]
Total column ozone [DU].
Definition: mptrac.h:3564
float cape[EX][EY]
Convective available potential energy [J/kg].
Definition: mptrac.h:3558
float pct[EX][EY]
Cloud top pressure [hPa].
Definition: mptrac.h:3540
float shf[EX][EY]
Surface sensible heat flux [W/m^2].
Definition: mptrac.h:3516
float lwc[EX][EY][EP]
Cloud liquid water content [kg/kg].
Definition: mptrac.h:3591
float us[EX][EY]
Surface zonal wind [m/s].
Definition: mptrac.h:3504
float cc[EX][EY][EP]
Cloud cover [1].
Definition: mptrac.h:3603
float ts[EX][EY]
Surface temperature [K].
Definition: mptrac.h:3498
float ess[EX][EY]
Eastward turbulent surface stress [N/m^2].
Definition: mptrac.h:3510
float pcb[EX][EY]
Cloud bottom pressure [hPa].
Definition: mptrac.h:3543
float pel[EX][EY]
Pressure at equilibrium level (EL) [hPa].
Definition: mptrac.h:3555
float cin[EX][EY]
Convective inhibition [J/kg].
Definition: mptrac.h:3561
float plcl[EX][EY]
Pressure at lifted condensation level (LCL) [hPa].
Definition: mptrac.h:3549
float tt[EX][EY]
Tropopause temperature [K].
Definition: mptrac.h:3531
float pbl[EX][EY]
Boundary layer pressure [hPa].
Definition: mptrac.h:3525
float vs[EX][EY]
Surface meridional wind [m/s].
Definition: mptrac.h:3507
float lsm[EX][EY]
Land-sea mask [1].
Definition: mptrac.h:3519
float iwc[EX][EY][EP]
Cloud ice water content [kg/kg].
Definition: mptrac.h:3597
float h2ot[EX][EY]
Tropopause water vapor volume mixing ratio [ppv].
Definition: mptrac.h:3537
float pv[EX][EY][EP]
Potential vorticity [PVU].
Definition: mptrac.h:3582
float cl[EX][EY]
Total column cloud water [kg/m^2].
Definition: mptrac.h:3546
float nss[EX][EY]
Northward turbulent surface stress [N/m^2].
Definition: mptrac.h:3513
float plfc[EX][EY]
Pressure at level of free convection (LFC) [hPa].
Definition: mptrac.h:3552
float swc[EX][EY][EP]
Cloud snow water content [kg/kg].
Definition: mptrac.h:3600
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 6915 of file mptrac.c.

6919 {
6920
6921 float *help;
6922
6923 /* Allocate... */
6924 ALLOC(help, float,
6925 EX * EY);
6926
6927 /* Read uncompressed... */
6928 LOG(2, "Read 2-D variable: %s (uncompressed)", varname);
6929 FREAD(help, float,
6930 (size_t) (met->nx * met->ny),
6931 in);
6932
6933 /* Copy data... */
6934 for (int ix = 0; ix < met->nx; ix++)
6935 for (int iy = 0; iy < met->ny; iy++)
6936 var[ix][iy] = help[ARRAY_2D(ix, iy, met->ny)];
6937
6938 /* Free... */
6939 free(help);
6940}
#define ARRAY_2D(ix, iy, ny)
Macro for computing the linear index of a 2D array element.
Definition: mptrac.h:387

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

6951 {
6952
6953 float *help;
6954
6955 /* Allocate... */
6956 ALLOC(help, float,
6957 EX * EY * EP);
6958
6959 /* Read uncompressed data... */
6960 if (ctl->met_type == 1) {
6961 LOG(2, "Read 3-D variable: %s (uncompressed)", varname);
6962 FREAD(help, float,
6963 (size_t) (met->nx * met->ny * met->np),
6964 in);
6965 }
6966
6967 /* Read packed data... */
6968 else if (ctl->met_type == 2)
6969 compress_pck(varname, help, (size_t) (met->ny * met->nx),
6970 (size_t) met->np, 1, in);
6971
6972 /* Read zfp data... */
6973 else if (ctl->met_type == 3) {
6974#ifdef ZFP
6975 int precision;
6976 FREAD(&precision, int,
6977 1,
6978 in);
6979
6980 double tolerance;
6981 FREAD(&tolerance, double,
6982 1,
6983 in);
6984
6985 compress_zfp(varname, help, met->np, met->ny, met->nx, precision,
6986 tolerance, 1, in);
6987#else
6988 ERRMSG("MPTRAC was compiled without zfp compression!");
6989#endif
6990 }
6991
6992 /* Read zstd data... */
6993 else if (ctl->met_type == 4) {
6994#ifdef ZSTD
6995 compress_zstd(varname, help, (size_t) (met->np * met->ny * met->nx), 1,
6996 ctl->met_zstd_level, in);
6997#else
6998 ERRMSG("MPTRAC was compiled without zstd compression!");
6999#endif
7000 }
7001
7002 /* Read cmultiscale data... */
7003 else if (ctl->met_type == 5) {
7004#ifdef CMS
7005 compress_cms(ctl, varname, help, (size_t) met->nx, (size_t) met->ny,
7006 (size_t) met->np, 1, in);
7007#else
7008 ERRMSG("MPTRAC was compiled without cmultiscale compression!");
7009#endif
7010 }
7011
7012 /* Copy data... */
7013#pragma omp parallel for default(shared) collapse(2)
7014 for (int ix = 0; ix < met->nx; ix++)
7015 for (int iy = 0; iy < met->ny; iy++)
7016 for (int ip = 0; ip < met->np; ip++) {
7017 var[ix][iy][ip] = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
7018 if (var[ix][iy][ip] < bound_min)
7019 var[ix][iy][ip] = bound_min;
7020 else if (var[ix][iy][ip] > bound_max)
7021 var[ix][iy][ip] = bound_max;
7022 }
7023
7024 /* Free... */
7025 free(help);
7026}
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:706
void compress_zstd(const char *varname, float *array, const size_t n, const int decompress, const int level, FILE *inout)
Compresses or decompresses a float array using Zstandard (ZSTD).
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.
int met_zstd_level
ZSTD compression level (from -5 to 22).
Definition: mptrac.h:2578
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 7030 of file mptrac.c.

7033 {
7034
7035 /* Check parameters... */
7036 if (ctl->met_cape != 1)
7037 return;
7038
7039 /* Set timer... */
7040 SELECT_TIMER("READ_MET_CAPE", "METPROC", NVTX_READ);
7041 LOG(2, "Calculate CAPE...");
7042
7043 /* Vertical spacing (about 100 m)... */
7044 const double pfac = 1.01439, dz0 = RI / MA / G0 * log(pfac);
7045
7046 /* Loop over columns... */
7047#pragma omp parallel for default(shared) collapse(2)
7048 for (int ix = 0; ix < met->nx; ix++)
7049 for (int iy = 0; iy < met->ny; iy++) {
7050
7051 /* Get potential temperature and water vapor at lowest 50 hPa... */
7052 int n = 0;
7053 double h2o = 0, t, theta = 0;
7054 double pbot = MIN(met->ps[ix][iy], met->p[0]);
7055 double ptop = pbot - 50.;
7056 for (int ip = 0; ip < met->np; ip++) {
7057 if (met->p[ip] <= pbot) {
7058 theta += THETA(met->p[ip], met->t[ix][iy][ip]);
7059 h2o += met->h2o[ix][iy][ip];
7060 n++;
7061 }
7062 if (met->p[ip] < ptop && n > 0)
7063 break;
7064 }
7065 theta /= n;
7066 h2o /= n;
7067
7068 /* Cannot compute anything if water vapor is missing... */
7069 met->plcl[ix][iy] = NAN;
7070 met->plfc[ix][iy] = NAN;
7071 met->pel[ix][iy] = NAN;
7072 met->cape[ix][iy] = NAN;
7073 met->cin[ix][iy] = NAN;
7074 if (h2o <= 0)
7075 continue;
7076
7077 /* Find lifted condensation level (LCL)... */
7078 ptop = P(20.);
7079 pbot = met->ps[ix][iy];
7080 do {
7081 met->plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
7082 t = theta / pow(1000. / met->plcl[ix][iy], 0.286);
7083 if (RH(met->plcl[ix][iy], t, h2o) > 100.)
7084 ptop = met->plcl[ix][iy];
7085 else
7086 pbot = met->plcl[ix][iy];
7087 } while (pbot - ptop > 0.1);
7088
7089 /* Calculate CIN up to LCL... */
7091 double dcape, dz, h2o_env, t_env;
7092 double p = met->ps[ix][iy];
7093 met->cape[ix][iy] = met->cin[ix][iy] = 0;
7094 do {
7095 dz = dz0 * TVIRT(t, h2o);
7096 p /= pfac;
7097 t = theta / pow(1000. / p, 0.286);
7098 intpol_met_space_3d(met, met->t, p, met->lon[ix], met->lat[iy],
7099 &t_env, ci, cw, 1);
7100 intpol_met_space_3d(met, met->h2o, p, met->lon[ix], met->lat[iy],
7101 &h2o_env, ci, cw, 0);
7102 dcape = 1e3 * G0 * (TVIRT(t, h2o) - TVIRT(t_env, h2o_env)) /
7103 TVIRT(t_env, h2o_env) * dz;
7104 if (dcape < 0)
7105 met->cin[ix][iy] += fabsf((float) dcape);
7106 } while (p > met->plcl[ix][iy]);
7107
7108 /* Calculate level of free convection (LFC), equilibrium level (EL),
7109 and convective available potential energy (CAPE)... */
7110 dcape = 0;
7111 p = met->plcl[ix][iy];
7112 t = theta / pow(1000. / p, 0.286);
7113 ptop = 0.75 * clim_tropo(clim, met->time, met->lat[iy]);
7114 do {
7115 dz = dz0 * TVIRT(t, h2o);
7116 p /= pfac;
7117 t -= lapse_rate(t, h2o) * dz;
7118 double psat = PSAT(t);
7119 h2o = psat / (p - (1. - EPS) * psat);
7120 intpol_met_space_3d(met, met->t, p, met->lon[ix], met->lat[iy],
7121 &t_env, ci, cw, 1);
7122 intpol_met_space_3d(met, met->h2o, p, met->lon[ix], met->lat[iy],
7123 &h2o_env, ci, cw, 0);
7124 double dcape_old = dcape;
7125 dcape = 1e3 * G0 * (TVIRT(t, h2o) - TVIRT(t_env, h2o_env)) /
7126 TVIRT(t_env, h2o_env) * dz;
7127 if (dcape > 0) {
7128 met->cape[ix][iy] += (float) dcape;
7129 if (!isfinite(met->plfc[ix][iy]))
7130 met->plfc[ix][iy] = (float) p;
7131 } else if (dcape_old > 0)
7132 met->pel[ix][iy] = (float) p;
7133 if (dcape < 0 && !isfinite(met->plfc[ix][iy]))
7134 met->cin[ix][iy] += fabsf((float) dcape);
7135 } while (p > ptop);
7136
7137 /* Check results... */
7138 if (!isfinite(met->plfc[ix][iy]))
7139 met->cin[ix][iy] = NAN;
7140 }
7141}
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 7145 of file mptrac.c.

7146 {
7147
7148 /* Set timer... */
7149 SELECT_TIMER("READ_MET_CLOUD", "METPROC", NVTX_READ);
7150 LOG(2, "Calculate cloud data...");
7151
7152 /* Thresholds for cloud detection... */
7153 const double ccmin = 0.01, cwmin = 1e-6;
7154
7155 /* Loop over columns... */
7156#pragma omp parallel for default(shared) collapse(2)
7157 for (int ix = 0; ix < met->nx; ix++)
7158 for (int iy = 0; iy < met->ny; iy++) {
7159
7160 /* Init... */
7161 met->pct[ix][iy] = NAN;
7162 met->pcb[ix][iy] = NAN;
7163 met->cl[ix][iy] = 0;
7164
7165 /* Loop over pressure levels... */
7166 for (int ip = 0; ip < met->np - 1; ip++) {
7167
7168 /* Check pressure... */
7169 if (met->p[ip] > met->ps[ix][iy] || met->p[ip] < P(20.))
7170 continue;
7171
7172 /* Check ice water and liquid water content... */
7173 if (met->cc[ix][iy][ip] > ccmin
7174 && (met->lwc[ix][iy][ip] > cwmin
7175 || met->rwc[ix][iy][ip] > cwmin
7176 || met->iwc[ix][iy][ip] > cwmin
7177 || met->swc[ix][iy][ip] > cwmin)) {
7178
7179 /* Get cloud top pressure ... */
7180 met->pct[ix][iy]
7181 = (float) (0.5 * (met->p[ip] + (float) met->p[ip + 1]));
7182
7183 /* Get cloud bottom pressure ... */
7184 if (!isfinite(met->pcb[ix][iy]))
7185 met->pcb[ix][iy]
7186 = (float) (0.5 * (met->p[ip] + met->p[MAX(ip - 1, 0)]));
7187 }
7188
7189 /* Get cloud water... */
7190 met->cl[ix][iy] += (float)
7191 (0.5 * (met->lwc[ix][iy][ip] + met->lwc[ix][iy][ip + 1]
7192 + met->rwc[ix][iy][ip] + met->rwc[ix][iy][ip + 1]
7193 + met->iwc[ix][iy][ip] + met->iwc[ix][iy][ip + 1]
7194 + met->swc[ix][iy][ip] + met->swc[ix][iy][ip + 1])
7195 * 100. * (met->p[ip] - met->p[ip + 1]) / G0);
7196 }
7197 }
7198}

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

7204 {
7205
7206 met_t *help;
7207
7208 /* Check parameters... */
7209 if (ctl->met_detrend <= 0)
7210 return;
7211
7212 /* Set timer... */
7213 SELECT_TIMER("READ_MET_DETREND", "METPROC", NVTX_READ);
7214 LOG(2, "Detrend meteo data...");
7215
7216 /* Allocate... */
7217 ALLOC(help, met_t, 1);
7218
7219 /* Calculate standard deviation... */
7220 const double sigma = ctl->met_detrend / 2.355;
7221 const double tssq = 2. * SQR(sigma);
7222
7223 /* Calculate box size in latitude... */
7224 int sy = (int) (3. * DY2DEG(sigma) / fabs(met->lat[1] - met->lat[0]));
7225 sy = MIN(MAX(1, sy), met->ny / 2);
7226
7227 /* Calculate background... */
7228#pragma omp parallel for default(shared) collapse(2)
7229 for (int ix = 0; ix < met->nx; ix++) {
7230 for (int iy = 0; iy < met->ny; iy++) {
7231
7232 /* Calculate Cartesian coordinates... */
7233 double x0[3];
7234 geo2cart(0.0, met->lon[ix], met->lat[iy], x0);
7235
7236 /* Calculate box size in longitude... */
7237 int sx =
7238 (int) (3. * DX2DEG(sigma, met->lat[iy]) /
7239 fabs(met->lon[1] - met->lon[0]));
7240 sx = MIN(MAX(1, sx), met->nx / 2);
7241
7242 /* Init... */
7243 float wsum = 0;
7244 for (int ip = 0; ip < met->np; ip++) {
7245 help->t[ix][iy][ip] = 0;
7246 help->u[ix][iy][ip] = 0;
7247 help->v[ix][iy][ip] = 0;
7248 help->w[ix][iy][ip] = 0;
7249 }
7250
7251 /* Loop over neighboring grid points... */
7252 for (int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
7253 int ix3 = ix2;
7254 if (ix3 < 0)
7255 ix3 += met->nx;
7256 else if (ix3 >= met->nx)
7257 ix3 -= met->nx;
7258 for (int iy2 = MAX(iy - sy, 0);
7259 iy2 <= MIN(iy + sy, met->ny - 1); iy2++) {
7260
7261 /* Calculate Cartesian coordinates... */
7262 double x1[3];
7263 geo2cart(0.0, met->lon[ix3], met->lat[iy2], x1);
7264
7265 /* Calculate weighting factor... */
7266 const float w = (float) exp(-DIST2(x0, x1) / tssq);
7267
7268 /* Add data... */
7269 wsum += w;
7270 for (int ip = 0; ip < met->np; ip++) {
7271 help->t[ix][iy][ip] += w * met->t[ix3][iy2][ip];
7272 help->u[ix][iy][ip] += w * met->u[ix3][iy2][ip];
7273 help->v[ix][iy][ip] += w * met->v[ix3][iy2][ip];
7274 help->w[ix][iy][ip] += w * met->w[ix3][iy2][ip];
7275 }
7276 }
7277 }
7278
7279 /* Normalize... */
7280 for (int ip = 0; ip < met->np; ip++) {
7281 help->t[ix][iy][ip] /= wsum;
7282 help->u[ix][iy][ip] /= wsum;
7283 help->v[ix][iy][ip] /= wsum;
7284 help->w[ix][iy][ip] /= wsum;
7285 }
7286 }
7287 }
7288
7289 /* Subtract background... */
7290#pragma omp parallel for default(shared) collapse(3)
7291 for (int ix = 0; ix < met->nx; ix++)
7292 for (int iy = 0; iy < met->ny; iy++)
7293 for (int ip = 0; ip < met->np; ip++) {
7294 met->t[ix][iy][ip] -= help->t[ix][iy][ip];
7295 met->u[ix][iy][ip] -= help->u[ix][iy][ip];
7296 met->v[ix][iy][ip] -= help->v[ix][iy][ip];
7297 met->w[ix][iy][ip] -= help->w[ix][iy][ip];
7298 }
7299
7300 /* Free... */
7301 free(help);
7302}
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:1030
#define DIST2(a, b)
Calculate the squared Euclidean distance between two points in Cartesian coordinates.
Definition: mptrac.h:609
double met_detrend
FWHM of horizontal Gaussian used for detrending [km].
Definition: mptrac.h:2657
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 7306 of file mptrac.c.

7307 {
7308
7309 /* Set timer... */
7310 SELECT_TIMER("READ_MET_EXTRAPOLATE", "METPROC", NVTX_READ);
7311 LOG(2, "Extrapolate meteo data...");
7312
7313 /* Loop over columns... */
7314#pragma omp parallel for default(shared) collapse(2)
7315 for (int ix = 0; ix < met->nx; ix++)
7316 for (int iy = 0; iy < met->ny; iy++) {
7317
7318 /* Find lowest valid data point... */
7319 int ip0;
7320 for (ip0 = met->np - 1; ip0 >= 0; ip0--)
7321 if (!isfinite(met->t[ix][iy][ip0])
7322 || !isfinite(met->u[ix][iy][ip0])
7323 || !isfinite(met->v[ix][iy][ip0])
7324 || !isfinite(met->w[ix][iy][ip0]))
7325 break;
7326
7327 /* Extrapolate... */
7328 for (int ip = ip0; ip >= 0; ip--) {
7329 met->t[ix][iy][ip] = met->t[ix][iy][ip + 1];
7330 met->u[ix][iy][ip] = met->u[ix][iy][ip + 1];
7331 met->v[ix][iy][ip] = met->v[ix][iy][ip + 1];
7332 met->w[ix][iy][ip] = met->w[ix][iy][ip + 1];
7333 met->h2o[ix][iy][ip] = met->h2o[ix][iy][ip + 1];
7334 met->o3[ix][iy][ip] = met->o3[ix][iy][ip + 1];
7335 met->lwc[ix][iy][ip] = met->lwc[ix][iy][ip + 1];
7336 met->rwc[ix][iy][ip] = met->rwc[ix][iy][ip + 1];
7337 met->iwc[ix][iy][ip] = met->iwc[ix][iy][ip + 1];
7338 met->swc[ix][iy][ip] = met->swc[ix][iy][ip + 1];
7339 met->cc[ix][iy][ip] = met->cc[ix][iy][ip + 1];
7340 }
7341 }
7342}

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

7348 {
7349
7350 float *help;
7351
7352 double logp[EP];
7353
7354 int dx = ctl->met_geopot_sx, dy = ctl->met_geopot_sy;
7355
7356 /* Set timer... */
7357 SELECT_TIMER("READ_MET_GEOPOT", "METPROC", NVTX_READ);
7358 LOG(2, "Calculate geopotential heights...");
7359
7360 /* Allocate... */
7361 ALLOC(help, float,
7362 EX * EY * EP);
7363
7364 /* Calculate log pressure... */
7365#pragma omp parallel for default(shared)
7366 for (int ip = 0; ip < met->np; ip++)
7367 logp[ip] = log(met->p[ip]);
7368
7369 /* Apply hydrostatic equation to calculate geopotential heights... */
7370#pragma omp parallel for default(shared) collapse(2)
7371 for (int ix = 0; ix < met->nx; ix++)
7372 for (int iy = 0; iy < met->ny; iy++) {
7373
7374 /* Get surface height and pressure... */
7375 const double zs = met->zs[ix][iy];
7376 const double lnps = log(met->ps[ix][iy]);
7377
7378 /* Get temperature and water vapor at the surface... */
7379 const int ip0 = locate_irr(met->p, met->np, met->ps[ix][iy]);
7380 const double ts = LIN(met->p[ip0], met->t[ix][iy][ip0], met->p[ip0 + 1],
7381 met->t[ix][iy][ip0 + 1], met->ps[ix][iy]);
7382 const double h2os =
7383 LIN(met->p[ip0], met->h2o[ix][iy][ip0], met->p[ip0 + 1],
7384 met->h2o[ix][iy][ip0 + 1], met->ps[ix][iy]);
7385
7386 /* Upper part of profile... */
7387 met->z[ix][iy][ip0 + 1]
7388 = (float) (zs +
7389 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
7390 met->t[ix][iy][ip0 + 1], met->h2o[ix][iy][ip0 + 1]));
7391 for (int ip = ip0 + 2; ip < met->np; ip++)
7392 met->z[ix][iy][ip]
7393 = (float) (met->z[ix][iy][ip - 1] +
7394 ZDIFF(logp[ip - 1], met->t[ix][iy][ip - 1],
7395 met->h2o[ix][iy][ip - 1], logp[ip],
7396 met->t[ix][iy][ip], met->h2o[ix][iy][ip]));
7397
7398 /* Lower part of profile... */
7399 met->z[ix][iy][ip0]
7400 = (float) (zs +
7401 ZDIFF(lnps, ts, h2os, logp[ip0],
7402 met->t[ix][iy][ip0], met->h2o[ix][iy][ip0]));
7403 for (int ip = ip0 - 1; ip >= 0; ip--)
7404 met->z[ix][iy][ip]
7405 = (float) (met->z[ix][iy][ip + 1] +
7406 ZDIFF(logp[ip + 1], met->t[ix][iy][ip + 1],
7407 met->h2o[ix][iy][ip + 1], logp[ip],
7408 met->t[ix][iy][ip], met->h2o[ix][iy][ip]));
7409 }
7410
7411 /* Check control parameters... */
7412 if (dx == 0 || dy == 0)
7413 return;
7414
7415 /* Default smoothing parameters... */
7416 if (dx < 0 || dy < 0) {
7417 if (fabs(met->lon[1] - met->lon[0]) < 0.5) {
7418 dx = 3;
7419 dy = 2;
7420 } else {
7421 dx = 6;
7422 dy = 4;
7423 }
7424 }
7425
7426 /* Calculate weights for smoothing... */
7427 float ws[dx + 1][dy + 1];
7428#pragma omp parallel for default(shared) collapse(2)
7429 for (int ix = 0; ix <= dx; ix++)
7430 for (int iy = 0; iy < dy; iy++)
7431 ws[ix][iy] = (1.0f - (float) ix / (float) dx)
7432 * (1.0f - (float) iy / (float) dy);
7433
7434 /* Copy data... */
7435#pragma omp parallel for default(shared) collapse(3)
7436 for (int ix = 0; ix < met->nx; ix++)
7437 for (int iy = 0; iy < met->ny; iy++)
7438 for (int ip = 0; ip < met->np; ip++)
7439 help[ARRAY_3D(ip, ix, met->nx, iy, met->ny)] = met->z[ix][iy][ip];
7440
7441 /* Horizontal smoothing... */
7442#pragma omp parallel for default(shared) collapse(3)
7443 for (int ip = 0; ip < met->np; ip++)
7444 for (int ix = 0; ix < met->nx; ix++)
7445 for (int iy = 0; iy < met->ny; iy++) {
7446 float res = 0, wsum = 0;
7447 int iy0 = MAX(iy - dy + 1, 0);
7448 int iy1 = MIN(iy + dy - 1, met->ny - 1);
7449 for (int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
7450 int ix3 = ix2;
7451 if (ix3 < 0)
7452 ix3 += met->nx;
7453 else if (ix3 >= met->nx)
7454 ix3 -= met->nx;
7455 for (int iy2 = iy0; iy2 <= iy1; ++iy2)
7456 if (isfinite(help[ARRAY_3D(ip, ix3, met->nx, iy2, met->ny)])) {
7457 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
7458 res += w * help[ARRAY_3D(ip, ix3, met->nx, iy2, met->ny)];
7459 wsum += w;
7460 }
7461 }
7462 if (wsum > 0)
7463 met->z[ix][iy][ip] = res / wsum;
7464 else
7465 met->z[ix][iy][ip] = NAN;
7466 }
7467
7468 /* Free... */
7469 free(help);
7470}
#define ZDIFF(lnp0, t0, h2o0, lnp1, t1, h2o1)
Calculate geopotential height difference.
Definition: mptrac.h:1852
Here is the call graph for this function:

◆ read_met_grib()

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

Reads global meteorological information from a grib file.

This function reads meteorological grid information from a grib file, including time and spatial dimensions. The function computes the latitude and longitude grid based on the provided boundaries and icnrement values.

Parameters
handlesA pointer to an array of codes_handle pointers representing the grib messages.
count_handlesThe total number of grib messages in the handles array.
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 the data file.
  • Retrieves grid dimensions (longitude, latitude, and vertical levels) from the grib file.
  • Reads longitudes and latitudes boundaries and increments from the grib file and computes the grid.
  • Logs the retrieved grid information for verification and debugging purposes.
Authors
Nils Nobre Wittwer

Reads meteorological data from a grib file and processes it.

This function reads meteorological data from a grib file specified by the filename parameter, using the ECCODES library. It reads grid, surface, and vertical level data, processes the data 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 grib files to read the meteorological data from. The sf or ml suffixes indicating surface or multi-level data should be replaced with XX.
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 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.
Author
Nils Nobre Wittwer

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

7478 {
7479
7480 char levname[LEN], tstr[10];
7481
7482 double rtime = 0, r, r2;
7483
7484 int varid, year2, mon2, day2, hour2, min2, sec2,
7485 year, mon, day, hour, min, sec;
7486
7487 size_t np;
7488
7489 /* Set timer... */
7490 SELECT_TIMER("READ_MET_GRID", "INPUT", NVTX_READ);
7491 LOG(2, "Read meteo grid information...");
7492
7493 /* MPTRAC meteo files... */
7494 if (ctl->met_clams == 0) {
7495
7496 /* Get time from filename... */
7497 met->time = time_from_filename(filename, 16);
7498
7499 /* Check time information from data file... */
7500 jsec2time(met->time, &year, &mon, &day, &hour, &min, &sec, &r);
7501 if (nc_inq_varid(ncid, "time", &varid) == NC_NOERR) {
7502 NC(nc_get_var_double(ncid, varid, &rtime));
7503 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
7504 WARN("Time information in meteo file does not match filename!");
7505 } else
7506 WARN("Time information in meteo file is missing!");
7507 }
7508
7509 /* CLaMS meteo files... */
7510 else {
7511
7512 /* Read time from file... */
7513 NC_GET_DOUBLE("time", &rtime, 0);
7514
7515 /* Get time from filename (considering the century)... */
7516 if (rtime < 0)
7517 sprintf(tstr, "19%.2s", &filename[strlen(filename) - 11]);
7518 else
7519 sprintf(tstr, "20%.2s", &filename[strlen(filename) - 11]);
7520 year = atoi(tstr);
7521 sprintf(tstr, "%.2s", &filename[strlen(filename) - 9]);
7522 mon = atoi(tstr);
7523 sprintf(tstr, "%.2s", &filename[strlen(filename) - 7]);
7524 day = atoi(tstr);
7525 sprintf(tstr, "%.2s", &filename[strlen(filename) - 5]);
7526 hour = atoi(tstr);
7527 time2jsec(year, mon, day, hour, 0, 0, 0, &met->time);
7528 }
7529
7530 /* Check time... */
7531 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
7532 || day < 1 || day > 31 || hour < 0 || hour > 23)
7533 ERRMSG("Cannot read time from filename!");
7534 jsec2time(met->time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
7535 LOG(2, "Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
7536 met->time, year2, mon2, day2, hour2, min2);
7537
7538 /* Get grid dimensions... */
7539 NC_INQ_DIM("lon", &met->nx, 2, EX);
7540 LOG(2, "Number of longitudes: %d", met->nx);
7541
7542 NC_INQ_DIM("lat", &met->ny, 2, EY);
7543 LOG(2, "Number of latitudes: %d", met->ny);
7544
7545 int dimid2;
7546 sprintf(levname, "lev");
7547 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
7548 sprintf(levname, "plev");
7549 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
7550 sprintf(levname, "hybrid");
7551 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
7552 sprintf(levname, "hybrid_level");
7553
7554 NC_INQ_DIM(levname, &met->np, 1, EP);
7555 if (met->np == 1) {
7556 sprintf(levname, "lev_2");
7557 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR) {
7558 sprintf(levname, "plev");
7559 NC(nc_inq_dimid(ncid, levname, &dimid2));
7560 }
7561 NC(nc_inq_dimlen(ncid, dimid2, &np));
7562 met->np = (int) np;
7563 }
7564 LOG(2, "Number of levels: %d", met->np);
7565 if (met->np < 2 || met->np > EP)
7566 ERRMSG("Number of levels out of range!");
7567
7568 /* Read longitudes and latitudes... */
7569 NC_GET_DOUBLE("lon", met->lon, 1);
7570 LOG(2, "Longitudes: %g, %g ... %g deg",
7571 met->lon[0], met->lon[1], met->lon[met->nx - 1]);
7572 NC_GET_DOUBLE("lat", met->lat, 1);
7573 LOG(2, "Latitudes: %g, %g ... %g deg",
7574 met->lat[0], met->lat[1], met->lat[met->ny - 1]);
7575
7576 /* Check grid spacing... */
7577 for (int ix = 2; ix < met->nx; ix++)
7578 if (fabs
7579 (fabs(met->lon[ix] - met->lon[ix - 1]) -
7580 fabs(met->lon[1] - met->lon[0])) > 0.001)
7581 ERRMSG("No regular grid spacing in longitudes!");
7582 for (int iy = 2; iy < met->ny; iy++)
7583 if (fabs
7584 (fabs(met->lat[iy] - met->lat[iy - 1]) -
7585 fabs(met->lat[1] - met->lat[0])) > 0.001) {
7586 WARN("No regular grid spacing in latitudes!");
7587 break;
7588 }
7589
7590 /* Read pressure levels... */
7591 if (ctl->met_np <= 0) {
7592 NC_GET_DOUBLE(levname, met->p, 1);
7593 for (int ip = 0; ip < met->np; ip++)
7594 met->p[ip] /= 100.;
7595 LOG(2, "Altitude levels: %g, %g ... %g km",
7596 Z(met->p[0]), Z(met->p[1]), Z(met->p[met->np - 1]));
7597 LOG(2, "Pressure levels: %g, %g ... %g hPa",
7598 met->p[0], met->p[1], met->p[met->np - 1]);
7599 }
7600
7601 /* Read hybrid levels... */
7602 if (strcasecmp(levname, "hybrid") == 0)
7603 NC_GET_DOUBLE("hybrid", met->hybrid, 1);
7604}
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:10048
double time_from_filename(const char *filename, const int offset)
Extracts and converts a timestamp from a filename to Julian seconds.
Definition: mptrac.c:10147
double hybrid[EP]
Model hybrid levels.
Definition: mptrac.h:3492
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 7725 of file mptrac.c.

7728 {
7729
7730 /* Set timer... */
7731 SELECT_TIMER("READ_MET_LEVELS", "INPUT", NVTX_READ);
7732 LOG(2, "Read level data...");
7733
7734 /* Read temperature... */
7735 if (!read_met_nc_3d(ncid, "t", "T", "temp", "TEMP", ctl, met, met->t, 1.0))
7736 ERRMSG("Cannot read temperature!");
7737
7738 /* Read horizontal wind and vertical velocity... */
7739 if (!read_met_nc_3d(ncid, "u", "U", NULL, NULL, ctl, met, met->u, 1.0))
7740 ERRMSG("Cannot read zonal wind!");
7741 if (!read_met_nc_3d(ncid, "v", "V", NULL, NULL, ctl, met, met->v, 1.0))
7742 ERRMSG("Cannot read meridional wind!");
7743 if (!read_met_nc_3d
7744 (ncid, "w", "W", "omega", "OMEGA", ctl, met, met->w, 0.01f))
7745 WARN("Cannot read vertical velocity!");
7746
7747 /* Read water vapor... */
7748 if (!ctl->met_relhum) {
7749 if (!read_met_nc_3d
7750 (ncid, "q", "Q", "sh", "SH", ctl, met, met->h2o, (float) (MA / MH2O)))
7751 WARN("Cannot read specific humidity!");
7752 } else {
7753 if (!read_met_nc_3d
7754 (ncid, "rh", "RH", NULL, NULL, ctl, met, met->h2o, 0.01f))
7755 WARN("Cannot read relative humidity!");
7756#pragma omp parallel for default(shared) collapse(2)
7757 for (int ix = 0; ix < met->nx; ix++)
7758 for (int iy = 0; iy < met->ny; iy++)
7759 for (int ip = 0; ip < met->np; ip++) {
7760 double pw = met->h2o[ix][iy][ip] * PSAT(met->t[ix][iy][ip]);
7761 met->h2o[ix][iy][ip] =
7762 (float) (pw / (met->p[ip] - (1.0 - EPS) * pw));
7763 }
7764 }
7765
7766 /* Read ozone... */
7767 if (!read_met_nc_3d
7768 (ncid, "o3", "O3", NULL, NULL, ctl, met, met->o3, (float) (MA / MO3)))
7769 WARN("Cannot read ozone data!");
7770
7771 /* Read cloud data... */
7772 if (!read_met_nc_3d
7773 (ncid, "clwc", "CLWC", NULL, NULL, ctl, met, met->lwc, 1.0))
7774 WARN("Cannot read cloud liquid water content!");
7775 if (!read_met_nc_3d
7776 (ncid, "crwc", "CRWC", NULL, NULL, ctl, met, met->rwc, 1.0))
7777 WARN("Cannot read cloud rain water content!");
7778 if (!read_met_nc_3d
7779 (ncid, "ciwc", "CIWC", NULL, NULL, ctl, met, met->iwc, 1.0))
7780 WARN("Cannot read cloud ice water content!");
7781 if (!read_met_nc_3d
7782 (ncid, "cswc", "CSWC", NULL, NULL, ctl, met, met->swc, 1.0))
7783 WARN("Cannot read cloud snow water content!");
7784 if (!read_met_nc_3d(ncid, "cc", "CC", NULL, NULL, ctl, met, met->cc, 1.0))
7785 WARN("Cannot read cloud cover!");
7786
7787 /* Read zeta and zeta_dot... */
7788 if (!read_met_nc_3d
7789 (ncid, "ZETA", "zeta", NULL, NULL, ctl, met, met->zetal, 1.0))
7790 WARN("Cannot read ZETA!");
7791 if (!read_met_nc_3d
7792 (ncid, "ZETA_DOT_TOT", "ZETA_DOT_clr", "zeta_dot_clr",
7793 NULL, ctl, met, met->zeta_dotl, 0.00001157407f))
7794 WARN("Cannot read ZETA_DOT!");
7795
7796 /* Store velocities on model levels... */
7797 if (ctl->met_vert_coord != 0) {
7798 for (int ix = 0; ix < met->nx; ix++)
7799 for (int iy = 0; iy < met->ny; iy++)
7800 for (int ip = 0; ip < met->np; ip++) {
7801 met->ul[ix][iy][ip] = met->u[ix][iy][ip];
7802 met->vl[ix][iy][ip] = met->v[ix][iy][ip];
7803 met->wl[ix][iy][ip] = met->w[ix][iy][ip];
7804 }
7805
7806 /* Save number of model levels... */
7807 met->npl = met->np;
7808 }
7809
7810 /* Get pressure on model levels... */
7811 if (ctl->met_np > 0 || ctl->met_vert_coord != 0) {
7812
7813 /* Read 3-D pressure field... */
7814 if (ctl->met_vert_coord == 1) {
7815 if (!read_met_nc_3d
7816 (ncid, "pl", "PL", "pressure", "PRESSURE", ctl, met, met->pl,
7817 0.01f))
7818 if (!read_met_nc_3d
7819 (ncid, "press", "PRESS", NULL, NULL, ctl, met, met->pl, 1.0))
7820 ERRMSG("Cannot read pressure on model levels!");
7821 }
7822
7823 /* Use a and b coefficients for full levels... */
7824 else if (ctl->met_vert_coord == 2 || ctl->met_vert_coord == 3) {
7825
7826 /* Grid level coefficients... */
7827 double hyam[EP], hybm[EP];
7828
7829 /* Read coefficients from file... */
7830 if (ctl->met_vert_coord == 2) {
7831 int varid;
7832 if (nc_inq_varid(ncid, "hyam", &varid) == NC_NOERR
7833 && nc_inq_varid(ncid, "hybm", &varid) == NC_NOERR) {
7834 NC_GET_DOUBLE("hyam", hyam, 1);
7835 NC_GET_DOUBLE("hybm", hybm, 1);
7836 } else if (nc_inq_varid(ncid, "a_hybrid_level", &varid) == NC_NOERR
7837 && nc_inq_varid(ncid, "b_hybrid_level",
7838 &varid) == NC_NOERR) {
7839 NC_GET_DOUBLE("a_hybrid_level", hyam, 1);
7840 NC_GET_DOUBLE("b_hybrid_level", hybm, 1);
7841 } else
7842 ERRMSG("Cannot read a and b level coefficients from netCDF file!");
7843 }
7844
7845 /* Use control parameters... */
7846 else if (ctl->met_vert_coord == 3) {
7847
7848 /* Check number of levels... */
7849 if (met->np != ctl->met_nlev)
7850 ERRMSG("Mismatch in number of model levels!");
7851
7852 /* Copy parameters... */
7853 for (int ip = 0; ip < met->np; ip++) {
7854 hyam[ip] = ctl->met_lev_hyam[ip];
7855 hybm[ip] = ctl->met_lev_hybm[ip];
7856 }
7857 }
7858
7859 /* Calculate pressure... */
7860 for (int ix = 0; ix < met->nx; ix++)
7861 for (int iy = 0; iy < met->ny; iy++)
7862 for (int ip = 0; ip < met->np; ip++)
7863 met->pl[ix][iy][ip] =
7864 (float) (hyam[ip] / 100. + hybm[ip] * met->ps[ix][iy]);
7865 }
7866
7867 /* Use a and b coefficients for half levels... */
7868 else if (ctl->met_vert_coord == 4) {
7869
7870 /* Grid level coefficients... */
7871 double hyam[EP], hybm[EP];
7872
7873 /* Use control parameters... */
7874 for (int ip = 0; ip < met->np + 1; ip++) {
7875 hyam[ip] = ctl->met_lev_hyam[ip];
7876 hybm[ip] = ctl->met_lev_hybm[ip];
7877 }
7878
7879 /* Check number of levels... */
7880 if (met->np + 1 != ctl->met_nlev)
7881 ERRMSG("Mismatch in number of model levels!");
7882
7883 /* Calculate pressure... */
7884#pragma omp parallel for default(shared) collapse(2)
7885 for (int ix = 0; ix < met->nx; ix++)
7886 for (int iy = 0; iy < met->ny; iy++)
7887 for (int ip = 0; ip < met->np; ip++) {
7888 double p0 = hyam[ip] / 100. + hybm[ip] * met->ps[ix][iy];
7889 double p1 = hyam[ip + 1] / 100. + hybm[ip + 1] * met->ps[ix][iy];
7890 met->pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
7891 }
7892 }
7893
7894 /* Check ordering of pressure levels... */
7895 for (int ix = 0; ix < met->nx; ix++)
7896 for (int iy = 0; iy < met->ny; iy++)
7897 for (int ip = 1; ip < met->np; ip++)
7898 if ((met->pl[ix][iy][0] > met->pl[ix][iy][1]
7899 && met->pl[ix][iy][ip - 1] <= met->pl[ix][iy][ip])
7900 || (met->pl[ix][iy][0] < met->pl[ix][iy][1]
7901 && met->pl[ix][iy][ip - 1] >= met->pl[ix][iy][ip]))
7902 ERRMSG("Pressure profiles are not monotonic!");
7903 }
7904
7905 /* Interpolate from model levels to pressure levels... */
7906 if (ctl->met_np > 0) {
7907
7908 /* Check pressure on model levels... */
7909 if (met->pl[0][0][0] <= 0)
7910 ERRMSG("Pressure on model levels is missing, check MET_VERT_COORD!");
7911
7912 /* Interpolate variables... */
7913 read_met_ml2pl(ctl, met, met->t, "T");
7914 read_met_ml2pl(ctl, met, met->u, "U");
7915 read_met_ml2pl(ctl, met, met->v, "V");
7916 read_met_ml2pl(ctl, met, met->w, "W");
7917 read_met_ml2pl(ctl, met, met->h2o, "H2O");
7918 read_met_ml2pl(ctl, met, met->o3, "O3");
7919 read_met_ml2pl(ctl, met, met->lwc, "LWC");
7920 read_met_ml2pl(ctl, met, met->rwc, "RWC");
7921 read_met_ml2pl(ctl, met, met->iwc, "IWC");
7922 read_met_ml2pl(ctl, met, met->swc, "SWC");
7923 read_met_ml2pl(ctl, met, met->cc, "CC");
7924
7925 /* Set new pressure levels... */
7926 met->np = ctl->met_np;
7927 for (int ip = 0; ip < met->np; ip++)
7928 met->p[ip] = ctl->met_p[ip];
7929 }
7930
7931 /* Check ordering of pressure levels... */
7932 for (int ip = 1; ip < met->np; ip++)
7933 if (met->p[ip - 1] < met->p[ip])
7934 ERRMSG("Pressure levels must be descending!");
7935}
void read_met_ml2pl(const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname)
Reads meteorological variables at different vertical levels from a grib file.
Definition: mptrac.c:8118
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:8626
#define MH2O
Molar mass of water vapor [g/mol].
Definition: mptrac.h:217
#define MO3
Molar mass of ozone [g/mol].
Definition: mptrac.h:222
int met_vert_coord
Vertical coordinate of input meteo data (0=plev, 1=mlev_p_file, 2=mlev_ab_file, 3=mlev_ab_full,...
Definition: mptrac.h:2559
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 
)

Reads meteorological variables at different vertical levels from a grib 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 grib file.

Parameters
handlesA pointer to an array of codes_handle pointers representing the grib messages.
num_messagesThe total number of grib messages in the handles array.
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 grib file.
  • Checks the ordering of pressure levels to ensure they are in descending order.
Authors
Nils Nobre Wittwer

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

8122 {
8123
8124 double aux[EP], p[EP];
8125
8126 /* Set timer... */
8127 SELECT_TIMER("READ_MET_ML2PL", "METPROC", NVTX_READ);
8128 LOG(2, "Interpolate meteo data to pressure levels: %s", varname);
8129
8130 /* Loop over columns... */
8131#pragma omp parallel for default(shared) private(aux,p) collapse(2)
8132 for (int ix = 0; ix < met->nx; ix++)
8133 for (int iy = 0; iy < met->ny; iy++) {
8134
8135 /* Copy pressure profile... */
8136 for (int ip = 0; ip < met->np; ip++)
8137 p[ip] = met->pl[ix][iy][ip];
8138
8139 /* Interpolate... */
8140 for (int ip = 0; ip < ctl->met_np; ip++) {
8141 double pt = ctl->met_p[ip];
8142 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
8143 pt = p[0];
8144 else if ((pt > p[met->np - 1] && p[1] > p[0])
8145 || (pt < p[met->np - 1] && p[1] < p[0]))
8146 pt = p[met->np - 1];
8147 int ip2 = locate_irr(p, met->np, pt);
8148 aux[ip] = LIN(p[ip2], var[ix][iy][ip2],
8149 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
8150 }
8151
8152 /* Copy data... */
8153 for (int ip = 0; ip < ctl->met_np; ip++)
8154 var[ix][iy][ip] = (float) aux[ip];
8155 }
8156}
Here is the call graph for this function:

◆ read_met_monotonize()

void read_met_monotonize ( const ctl_t ctl,
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
ctlA pointer to a control parameter structure.
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 8160 of file mptrac.c.

8162 {
8163
8164 /* Check parameters... */
8165 if (ctl->advect_vert_coord != 1)
8166 return;
8167
8168 /* Set timer... */
8169 SELECT_TIMER("READ_MET_MONOTONIZE", "METPROC", NVTX_READ);
8170 LOG(2, "Make zeta profiles monotone...");
8171
8172 /* Create monotone zeta profiles... */
8173#pragma omp parallel for default(shared) collapse(2)
8174 for (int i = 0; i < met->nx; i++)
8175 for (int j = 0; j < met->ny; j++) {
8176 int k = 1;
8177
8178 while (k < met->npl) { /* Check if there is an inversion at level k... */
8179 if ((met->zetal[i][j][k - 1] >= met->zetal[i][j][k])) {
8180 /* Find the upper level k+l over the inversion... */
8181 int l = 0;
8182 do {
8183 l++;
8184 }
8185 while ((met->zetal[i][j][k - 1] >=
8186 met->zetal[i][j][k + l]) & (k + l < met->npl));
8187
8188 /* Interpolate linear between the top and bottom
8189 of the inversion... */
8190 float s =
8191 (float) (met->zetal[i][j][k + l] - met->zetal[i][j][k - 1])
8192 / (float) (met->hybrid[k + l] - met->hybrid[k - 1]);
8193
8194 for (int m = k; m < k + l; m++) {
8195 float d = (float) (met->hybrid[m] - met->hybrid[k - 1]);
8196 met->zetal[i][j][m] = s * d + met->zetal[i][j][k - 1];
8197 }
8198
8199 /* Search for more inversions above the last inversion ... */
8200 k = k + l;
8201 } else {
8202 k++;
8203 }
8204 }
8205 }
8206
8207 /* Create monotone pressure profiles... */
8208#pragma omp parallel for default(shared) collapse(2)
8209 for (int i = 0; i < met->nx; i++)
8210 for (int j = 0; j < met->ny; j++) {
8211 int k = 1;
8212
8213 while (k < met->npl) { /* Check if there is an inversion at level k... */
8214 if ((met->pl[i][j][k - 1] <= met->pl[i][j][k])) {
8215
8216 /* Find the upper level k+l over the inversion... */
8217 int l = 0;
8218 do {
8219 l++;
8220 }
8221 while ((met->pl[i][j][k - 1] <= met->pl[i][j][k + l]) & (k + l <
8222 met->npl));
8223
8224 /* Interpolate linear between the top and bottom
8225 of the inversion... */
8226 float s = (float) (met->pl[i][j][k + l] - met->pl[i][j][k - 1])
8227 / (float) (met->hybrid[k + l] - met->hybrid[k - 1]);
8228
8229 for (int m = k; m < k + l; m++) {
8230 float d = (float) (met->hybrid[m] - met->hybrid[k - 1]);
8231 met->pl[i][j][m] = s * d + met->pl[i][j][k - 1];
8232 }
8233
8234 /* Search for more inversions above the last inversion ... */
8235 k += l;
8236 } else {
8237 k++;
8238 }
8239 }
8240 }
8241}

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

8401 {
8402
8403 int ncid;
8404
8405 /* Open netCDF file... */
8406 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
8407 WARN("Cannot open file!");
8408 return 0;
8409 }
8410
8411 /* Read coordinates of meteo data... */
8412 read_met_grid(filename, ncid, ctl, met);
8413
8414 /* Read surface data... */
8415 read_met_surface(ncid, ctl, met);
8416
8417 /* Read meteo data on vertical levels... */
8418 read_met_levels(ncid, ctl, met);
8419
8420 /* Extrapolate data for lower boundary... */
8422
8423 /* Fix polar winds... */
8425
8426 /* Create periodic boundary conditions... */
8427 read_met_periodic(met);
8428
8429 /* Downsampling... */
8430 read_met_sample(ctl, met);
8431
8432 /* Calculate geopotential heights... */
8433 read_met_geopot(ctl, met);
8434
8435 /* Calculate potential vorticity... */
8436 read_met_pv(met);
8437
8438 /* Calculate boundary layer data... */
8439 read_met_pbl(ctl, met);
8440
8441 /* Calculate tropopause data... */
8442 read_met_tropo(ctl, clim, met);
8443
8444 /* Calculate cloud properties... */
8445 read_met_cloud(met);
8446
8447 /* Calculate convective available potential energy... */
8448 read_met_cape(ctl, clim, met);
8449
8450 /* Calculate total column ozone... */
8451 read_met_ozone(met);
8452
8453 /* Detrending... */
8454 read_met_detrend(ctl, met);
8455
8456 /* Check meteo data and smooth zeta profiles ... */
8457 read_met_monotonize(ctl, met);
8458
8459 /* Close file... */
8460 NC(nc_close(ncid));
8461
8462 /* Return success... */
8463 return 1;
8464}
void read_met_geopot(const ctl_t *ctl, met_t *met)
Calculates geopotential heights from meteorological data.
Definition: mptrac.c:7346
void read_met_extrapolate(met_t *met)
Extrapolates meteorological data.
Definition: mptrac.c:7306
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:7725
void read_met_sample(const ctl_t *ctl, met_t *met)
Downsamples meteorological data based on specified parameters.
Definition: mptrac.c:9164
void read_met_cloud(met_t *met)
Calculates cloud-related variables for each grid point.
Definition: mptrac.c:7145
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:8772
void read_met_detrend(const ctl_t *ctl, met_t *met)
Detrends meteorological data.
Definition: mptrac.c:7202
void read_met_monotonize(const ctl_t *ctl, met_t *met)
Makes zeta and pressure profiles monotone.
Definition: mptrac.c:8160
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
Definition: mptrac.c:8909
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:7474
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:9336
void read_met_ozone(met_t *met)
Calculates the total column ozone from meteorological ozone data.
Definition: mptrac.c:9135
void read_met_pv(met_t *met)
Calculates potential vorticity (PV) from meteorological data.
Definition: mptrac.c:9029
void read_met_polar_winds(met_t *met)
Applies a fix for polar winds in meteorological data.
Definition: mptrac.c:8970
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:7030
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 8468 of file mptrac.c.

8480 {
8481
8482 char varsel[LEN];
8483
8484 float offset, scalfac;
8485
8486 int varid;
8487
8488 /* Check if variable exists... */
8489 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
8490 sprintf(varsel, "%s", varname);
8491 else if (varname2 != NULL
8492 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
8493 sprintf(varsel, "%s", varname2);
8494 else if (varname3 != NULL
8495 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
8496 sprintf(varsel, "%s", varname3);
8497 else if (varname4 != NULL
8498 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
8499 sprintf(varsel, "%s", varname4);
8500 else if (varname5 != NULL
8501 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
8502 sprintf(varsel, "%s", varname5);
8503 else if (varname6 != NULL
8504 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
8505 sprintf(varsel, "%s", varname6);
8506 else
8507 return 0;
8508
8509 /* Read packed data... */
8510 if (ctl->met_nc_scale
8511 && nc_get_att_float(ncid, varid, "add_offset", &offset) == NC_NOERR
8512 && nc_get_att_float(ncid, varid, "scale_factor",
8513 &scalfac) == NC_NOERR) {
8514
8515 /* Allocate... */
8516 short *help;
8517 ALLOC(help, short,
8518 EX * EY * EP);
8519
8520 /* Read fill value and missing value... */
8521 short fillval, missval;
8522 if (nc_get_att_short(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
8523 fillval = 0;
8524 if (nc_get_att_short(ncid, varid, "missing_value", &missval) != NC_NOERR)
8525 missval = 0;
8526
8527 /* Write info... */
8528 LOG(2, "Read 2-D variable: %s"
8529 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
8530 varsel, fillval, missval, scalfac, offset);
8531
8532 /* Read data... */
8533 NC(nc_get_var_short(ncid, varid, help));
8534
8535 /* Check meteo data layout... */
8536 if (ctl->met_convention != 0)
8537 ERRMSG("Meteo data layout not implemented for packed netCDF files!");
8538
8539 /* Copy and check data... */
8540#pragma omp parallel for default(shared) num_threads(12)
8541 for (int ix = 0; ix < met->nx; ix++)
8542 for (int iy = 0; iy < met->ny; iy++) {
8543 if (init)
8544 dest[ix][iy] = 0;
8545 const short aux = help[ARRAY_2D(iy, ix, met->nx)];
8546 if ((fillval == 0 || aux != fillval)
8547 && (missval == 0 || aux != missval)
8548 && fabsf(aux * scalfac + offset) < 1e14f)
8549 dest[ix][iy] += scl * (aux * scalfac + offset);
8550 else
8551 dest[ix][iy] = NAN;
8552 }
8553
8554 /* Free... */
8555 free(help);
8556 }
8557
8558 /* Unpacked data... */
8559 else {
8560
8561 /* Allocate... */
8562 float *help;
8563 ALLOC(help, float,
8564 EX * EY);
8565
8566 /* Read fill value and missing value... */
8567 float fillval, missval;
8568 if (nc_get_att_float(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
8569 fillval = 0;
8570 if (nc_get_att_float(ncid, varid, "missing_value", &missval) != NC_NOERR)
8571 missval = 0;
8572
8573 /* Write info... */
8574 LOG(2, "Read 2-D variable: %s (FILL = %g, MISS = %g)",
8575 varsel, fillval, missval);
8576
8577 /* Read data... */
8578 NC(nc_get_var_float(ncid, varid, help));
8579
8580 /* Check meteo data layout... */
8581 if (ctl->met_convention == 0) {
8582
8583 /* Copy and check data (ordering: lat, lon)... */
8584#pragma omp parallel for default(shared) num_threads(12)
8585 for (int ix = 0; ix < met->nx; ix++)
8586 for (int iy = 0; iy < met->ny; iy++) {
8587 if (init)
8588 dest[ix][iy] = 0;
8589 const float aux = help[ARRAY_2D(iy, ix, met->nx)];
8590 if ((fillval == 0 || aux != fillval)
8591 && (missval == 0 || aux != missval)
8592 && fabsf(aux) < 1e14f)
8593 dest[ix][iy] += scl * aux;
8594 else
8595 dest[ix][iy] = NAN;
8596 }
8597
8598 } else {
8599
8600 /* Copy and check data (ordering: lon, lat)... */
8601#pragma omp parallel for default(shared) num_threads(12)
8602 for (int iy = 0; iy < met->ny; iy++)
8603 for (int ix = 0; ix < met->nx; ix++) {
8604 if (init)
8605 dest[ix][iy] = 0;
8606 const float aux = help[ARRAY_2D(ix, iy, met->ny)];
8607 if ((fillval == 0 || aux != fillval)
8608 && (missval == 0 || aux != missval)
8609 && fabsf(aux) < 1e14f)
8610 dest[ix][iy] += scl * aux;
8611 else
8612 dest[ix][iy] = NAN;
8613 }
8614 }
8615
8616 /* Free... */
8617 free(help);
8618 }
8619
8620 /* Return... */
8621 return 1;
8622}
int met_nc_scale
Check netCDF scaling factors (0=no, 1=yes).
Definition: mptrac.h:2569
int met_convention
Meteo data layout (0=[lev, lat, lon], 1=[lon, lat, lev]).
Definition: mptrac.h:2555

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

8635 {
8636
8637 char varsel[LEN];
8638
8639 float offset, scalfac;
8640
8641 int varid;
8642
8643 /* Check if variable exists... */
8644 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
8645 sprintf(varsel, "%s", varname);
8646 else if (varname2 != NULL
8647 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
8648 sprintf(varsel, "%s", varname2);
8649 else if (varname3 != NULL
8650 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
8651 sprintf(varsel, "%s", varname3);
8652 else if (varname4 != NULL
8653 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
8654 sprintf(varsel, "%s", varname4);
8655 else
8656 return 0;
8657
8658 /* Read packed data... */
8659 if (ctl->met_nc_scale
8660 && nc_get_att_float(ncid, varid, "add_offset", &offset) == NC_NOERR
8661 && nc_get_att_float(ncid, varid, "scale_factor",
8662 &scalfac) == NC_NOERR) {
8663
8664 /* Allocate... */
8665 short *help;
8666 ALLOC(help, short,
8667 EX * EY * EP);
8668
8669 /* Read fill value and missing value... */
8670 short fillval, missval;
8671 if (nc_get_att_short(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
8672 fillval = 0;
8673 if (nc_get_att_short(ncid, varid, "missing_value", &missval) != NC_NOERR)
8674 missval = 0;
8675
8676 /* Write info... */
8677 LOG(2, "Read 3-D variable: %s "
8678 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
8679 varsel, fillval, missval, scalfac, offset);
8680
8681 /* Read data... */
8682 NC(nc_get_var_short(ncid, varid, help));
8683
8684 /* Check meteo data layout... */
8685 if (ctl->met_convention != 0)
8686 ERRMSG("Meteo data layout not implemented for packed netCDF files!");
8687
8688 /* Copy and check data... */
8689#pragma omp parallel for default(shared) num_threads(12)
8690 for (int ix = 0; ix < met->nx; ix++)
8691 for (int iy = 0; iy < met->ny; iy++)
8692 for (int ip = 0; ip < met->np; ip++) {
8693 const short aux = help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)];
8694 if ((fillval == 0 || aux != fillval)
8695 && (missval == 0 || aux != missval)
8696 && fabsf(aux * scalfac + offset) < 1e14f)
8697 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
8698 else
8699 dest[ix][iy][ip] = NAN;
8700 }
8701
8702 /* Free... */
8703 free(help);
8704 }
8705
8706 /* Unpacked data... */
8707 else {
8708
8709 /* Allocate... */
8710 float *help;
8711 ALLOC(help, float,
8712 EX * EY * EP);
8713
8714 /* Read fill value and missing value... */
8715 float fillval, missval;
8716 if (nc_get_att_float(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
8717 fillval = 0;
8718 if (nc_get_att_float(ncid, varid, "missing_value", &missval) != NC_NOERR)
8719 missval = 0;
8720
8721 /* Write info... */
8722 LOG(2, "Read 3-D variable: %s (FILL = %g, MISS = %g)",
8723 varsel, fillval, missval);
8724
8725 /* Read data... */
8726 NC(nc_get_var_float(ncid, varid, help));
8727
8728 /* Check meteo data layout... */
8729 if (ctl->met_convention == 0) {
8730
8731 /* Copy and check data (ordering: lev, lat, lon)... */
8732#pragma omp parallel for default(shared) num_threads(12)
8733 for (int ix = 0; ix < met->nx; ix++)
8734 for (int iy = 0; iy < met->ny; iy++)
8735 for (int ip = 0; ip < met->np; ip++) {
8736 const float aux = help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)];
8737 if ((fillval == 0 || aux != fillval)
8738 && (missval == 0 || aux != missval)
8739 && fabsf(aux) < 1e14f)
8740 dest[ix][iy][ip] = scl * aux;
8741 else
8742 dest[ix][iy][ip] = NAN;
8743 }
8744
8745 } else {
8746
8747 /* Copy and check data (ordering: lon, lat, lev)... */
8748#pragma omp parallel for default(shared) num_threads(12)
8749 for (int ip = 0; ip < met->np; ip++)
8750 for (int iy = 0; iy < met->ny; iy++)
8751 for (int ix = 0; ix < met->nx; ix++) {
8752 const float aux = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
8753 if ((fillval == 0 || aux != fillval)
8754 && (missval == 0 || aux != missval)
8755 && fabsf(aux) < 1e14f)
8756 dest[ix][iy][ip] = scl * aux;
8757 else
8758 dest[ix][iy][ip] = NAN;
8759 }
8760 }
8761
8762 /* Free... */
8763 free(help);
8764 }
8765
8766 /* Return... */
8767 return 1;
8768}

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

8774 {
8775
8776 /* Set timer... */
8777 SELECT_TIMER("READ_MET_PBL", "METPROC", NVTX_READ);
8778 LOG(2, "Calculate planetary boundary layer...");
8779
8780 /* Convert PBL height from meteo file to pressure... */
8781 if (ctl->met_pbl == 1) {
8782
8783 /* Loop over grid points... */
8784#pragma omp parallel for default(shared) collapse(2)
8785 for (int ix = 0; ix < met->nx; ix++)
8786 for (int iy = 0; iy < met->ny; iy++) {
8787
8788 /* Get pressure at top of PBL... */
8789 const float z = met->zs[ix][iy] + met->pbl[ix][iy];
8790 const int ip = locate_irr_float(met->z[ix][iy], met->np, z, 0);
8791 met->pbl[ix][iy] =
8792 (float) (LIN(met->z[ix][iy][ip], met->p[ip],
8793 met->z[ix][iy][ip + 1], met->p[ip + 1], z));
8794 }
8795 }
8796
8797 /* Determine PBL based on Richardson number... */
8798 else if (ctl->met_pbl == 2) {
8799
8800 /* Parameters used to estimate the height of the PBL
8801 (e.g., Vogelezang and Holtslag, 1996; Seidel et al., 2012)... */
8802 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
8803
8804 /* Loop over grid points... */
8805#pragma omp parallel for default(shared) collapse(2)
8806 for (int ix = 0; ix < met->nx; ix++)
8807 for (int iy = 0; iy < met->ny; iy++) {
8808
8809 /* Set bottom level of PBL... */
8810 const double pbl_bot = met->ps[ix][iy] * exp(-dz / H0);
8811
8812 /* Find lowest level near the bottom... */
8813 int ip;
8814 for (ip = 1; ip < met->np; ip++)
8815 if (met->p[ip] < pbl_bot)
8816 break;
8817
8818 /* Get near surface data... */
8819 const double h2os = LIN(met->p[ip - 1], met->h2o[ix][iy][ip - 1],
8820 met->p[ip], met->h2o[ix][iy][ip], pbl_bot);
8821 const double tvs = THETAVIRT(pbl_bot, met->ts[ix][iy], h2os);
8822
8823 /* Init... */
8824 double rib_old = 0;
8825
8826 /* Loop over levels... */
8827 for (; ip < met->np; ip++) {
8828
8829 /* Get squared horizontal wind speed... */
8830 double vh2 = SQR(met->u[ix][iy][ip] - met->us[ix][iy])
8831 + SQR(met->v[ix][iy][ip] - met->vs[ix][iy]);
8832 vh2 = MAX(vh2, SQR(umin));
8833
8834 /* Calculate bulk Richardson number... */
8835 const double rib =
8836 G0 * 1e3 * (met->z[ix][iy][ip] - met->zs[ix][iy]) / tvs
8837 * (THETAVIRT(met->p[ip], met->t[ix][iy][ip],
8838 met->h2o[ix][iy][ip]) - tvs) / vh2;
8839
8840 /* Check for critical value... */
8841 if (rib >= rib_crit) {
8842 met->pbl[ix][iy] = (float) (LIN(rib_old, met->p[ip - 1],
8843 rib, met->p[ip], rib_crit));
8844 if (met->pbl[ix][iy] > pbl_bot)
8845 met->pbl[ix][iy] = (float) pbl_bot;
8846 break;
8847 }
8848
8849 /* Save Richardson number... */
8850 rib_old = rib;
8851 }
8852 }
8853 }
8854
8855 /* Determine PBL based on potential temperature... */
8856 if (ctl->met_pbl == 3) {
8857
8858 /* Parameters used to estimate the height of the PBL
8859 (following HYSPLIT model)... */
8860 const double dtheta = 2.0, zmin = 0.1;
8861
8862 /* Loop over grid points... */
8863#pragma omp parallel for default(shared) collapse(2)
8864 for (int ix = 0; ix < met->nx; ix++)
8865 for (int iy = 0; iy < met->ny; iy++) {
8866
8867 /* Potential temperature at the surface... */
8868 const double theta0 = THETA(met->ps[ix][iy], met->ts[ix][iy]);
8869
8870 /* Find topmost level where theta exceeds surface value by 2 K... */
8871 int ip;
8872 for (ip = met->np - 2; ip > 0; ip--)
8873 if (met->p[ip] >= 300.)
8874 if (met->p[ip] > met->ps[ix][iy]
8875 || THETA(met->p[ip], met->t[ix][iy][ip]) <= theta0 + dtheta)
8876 break;
8877
8878 /* Interpolate... */
8879 met->pbl[ix][iy]
8880 = (float) (LIN(THETA(met->p[ip + 1], met->t[ix][iy][ip + 1]),
8881 met->p[ip + 1],
8882 THETA(met->p[ip], met->t[ix][iy][ip]),
8883 met->p[ip], theta0 + dtheta));
8884
8885 /* Check minimum value... */
8886 double pbl_min = met->ps[ix][iy] * exp(-zmin / H0);
8887 if (met->pbl[ix][iy] > pbl_min || met->p[ip] > met->ps[ix][iy])
8888 met->pbl[ix][iy] = (float) pbl_min;
8889 }
8890 }
8891
8892 /* Loop over grid points... */
8893#pragma omp parallel for default(shared) collapse(2)
8894 for (int ix = 0; ix < met->nx; ix++)
8895 for (int iy = 0; iy < met->ny; iy++) {
8896
8897 /* Check minimum value... */
8898 double pbl_min = met->ps[ix][iy] * exp(-ctl->met_pbl_min / H0);
8899 met->pbl[ix][iy] = MIN(met->pbl[ix][iy], (float) pbl_min);
8900
8901 /* Check maximum value... */
8902 double pbl_max = met->ps[ix][iy] * exp(-ctl->met_pbl_max / H0);
8903 met->pbl[ix][iy] = MAX(met->pbl[ix][iy], (float) pbl_max);
8904 }
8905}
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 8909 of file mptrac.c.

8910 {
8911
8912 /* Set timer... */
8913 SELECT_TIMER("READ_MET_PERIODIC", "METPROC", NVTX_READ);
8914 LOG(2, "Apply periodic boundary conditions...");
8915
8916 /* Check longitudes... */
8917 if (!(fabs(met->lon[met->nx - 1] - met->lon[0]
8918 + met->lon[1] - met->lon[0] - 360) < 0.01))
8919 return;
8920
8921 /* Increase longitude counter... */
8922 if ((++met->nx) >= EX)
8923 ERRMSG("Cannot create periodic boundary conditions!");
8924
8925 /* Set longitude... */
8926 met->lon[met->nx - 1] = met->lon[met->nx - 2] + met->lon[1] - met->lon[0];
8927
8928 /* Loop over latitudes and pressure levels... */
8929#pragma omp parallel for default(shared)
8930 for (int iy = 0; iy < met->ny; iy++) {
8931 met->ps[met->nx - 1][iy] = met->ps[0][iy];
8932 met->zs[met->nx - 1][iy] = met->zs[0][iy];
8933 met->ts[met->nx - 1][iy] = met->ts[0][iy];
8934 met->us[met->nx - 1][iy] = met->us[0][iy];
8935 met->vs[met->nx - 1][iy] = met->vs[0][iy];
8936 met->ess[met->nx - 1][iy] = met->ess[0][iy];
8937 met->nss[met->nx - 1][iy] = met->nss[0][iy];
8938 met->shf[met->nx - 1][iy] = met->shf[0][iy];
8939 met->lsm[met->nx - 1][iy] = met->lsm[0][iy];
8940 met->sst[met->nx - 1][iy] = met->sst[0][iy];
8941 met->pbl[met->nx - 1][iy] = met->pbl[0][iy];
8942 met->cape[met->nx - 1][iy] = met->cape[0][iy];
8943 met->cin[met->nx - 1][iy] = met->cin[0][iy];
8944 for (int ip = 0; ip < met->np; ip++) {
8945 met->t[met->nx - 1][iy][ip] = met->t[0][iy][ip];
8946 met->u[met->nx - 1][iy][ip] = met->u[0][iy][ip];
8947 met->v[met->nx - 1][iy][ip] = met->v[0][iy][ip];
8948 met->w[met->nx - 1][iy][ip] = met->w[0][iy][ip];
8949 met->h2o[met->nx - 1][iy][ip] = met->h2o[0][iy][ip];
8950 met->o3[met->nx - 1][iy][ip] = met->o3[0][iy][ip];
8951 met->lwc[met->nx - 1][iy][ip] = met->lwc[0][iy][ip];
8952 met->rwc[met->nx - 1][iy][ip] = met->rwc[0][iy][ip];
8953 met->iwc[met->nx - 1][iy][ip] = met->iwc[0][iy][ip];
8954 met->swc[met->nx - 1][iy][ip] = met->swc[0][iy][ip];
8955 met->cc[met->nx - 1][iy][ip] = met->cc[0][iy][ip];
8956 }
8957 for (int ip = 0; ip < met->npl; ip++) {
8958 met->ul[met->nx - 1][iy][ip] = met->ul[0][iy][ip];
8959 met->vl[met->nx - 1][iy][ip] = met->vl[0][iy][ip];
8960 met->wl[met->nx - 1][iy][ip] = met->wl[0][iy][ip];
8961 met->pl[met->nx - 1][iy][ip] = met->pl[0][iy][ip];
8962 met->zetal[met->nx - 1][iy][ip] = met->zetal[0][iy][ip];
8963 met->zeta_dotl[met->nx - 1][iy][ip] = met->zeta_dotl[0][iy][ip];
8964 }
8965 }
8966}

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

8971 {
8972
8973 /* Set timer... */
8974 SELECT_TIMER("READ_MET_POLAR_WINDS", "METPROC", NVTX_READ);
8975 LOG(2, "Apply fix for polar winds...");
8976
8977 /* Check latitudes... */
8978 if (fabs(met->lat[0]) < 89.999 || fabs(met->lat[met->ny - 1]) < 89.999)
8979 return;
8980
8981 /* Loop over hemispheres... */
8982 for (int ihem = 0; ihem < 2; ihem++) {
8983
8984 /* Set latitude indices... */
8985 int i89 = 1, i90 = 0, sign = 1;
8986 if (ihem == 1) {
8987 i89 = met->ny - 2;
8988 i90 = met->ny - 1;
8989 }
8990 if (met->lat[i90] < 0)
8991 sign = -1;
8992
8993 /* Look-up table of cosinus and sinus... */
8994 double clon[EX], slon[EX];
8995#pragma omp parallel for default(shared)
8996 for (int ix = 0; ix < met->nx; ix++) {
8997 clon[ix] = cos(sign * DEG2RAD(met->lon[ix]));
8998 slon[ix] = sin(sign * DEG2RAD(met->lon[ix]));
8999 }
9000
9001 /* Loop over levels... */
9002#pragma omp parallel for default(shared)
9003 for (int ip = 0; ip < met->np; ip++) {
9004
9005 /* Transform 89 degree u and v winds into Cartesian coordinates and take the mean... */
9006 double vel89x = 0, vel89y = 0;
9007 for (int ix = 0; ix < met->nx; ix++) {
9008 vel89x +=
9009 (met->u[ix][i89][ip] * clon[ix] -
9010 met->v[ix][i89][ip] * slon[ix]) / met->nx;
9011 vel89y +=
9012 (met->u[ix][i89][ip] * slon[ix] +
9013 met->v[ix][i89][ip] * clon[ix]) / met->nx;
9014 }
9015
9016 /* Replace 90 degree winds by 89 degree mean... */
9017 for (int ix = 0; ix < met->nx; ix++) {
9018 met->u[ix][i90][ip]
9019 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
9020 met->v[ix][i90][ip]
9021 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
9022 }
9023 }
9024 }
9025}

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

9030 {
9031
9032 double pows[EP];
9033
9034 /* Set timer... */
9035 SELECT_TIMER("READ_MET_PV", "METPROC", NVTX_READ);
9036 LOG(2, "Calculate potential vorticity...");
9037
9038 /* Set powers... */
9039#pragma omp parallel for default(shared)
9040 for (int ip = 0; ip < met->np; ip++)
9041 pows[ip] = pow(1000. / met->p[ip], 0.286);
9042
9043 /* Loop over grid points... */
9044#pragma omp parallel for default(shared)
9045 for (int ix = 0; ix < met->nx; ix++) {
9046
9047 /* Set indices... */
9048 const int ix0 = MAX(ix - 1, 0);
9049 const int ix1 = MIN(ix + 1, met->nx - 1);
9050
9051 /* Loop over grid points... */
9052 for (int iy = 0; iy < met->ny; iy++) {
9053
9054 /* Set indices... */
9055 const int iy0 = MAX(iy - 1, 0);
9056 const int iy1 = MIN(iy + 1, met->ny - 1);
9057
9058 /* Set auxiliary variables... */
9059 const double latr = 0.5 * (met->lat[iy1] + met->lat[iy0]);
9060 const double dx = 1000. * DEG2DX(met->lon[ix1] - met->lon[ix0], latr);
9061 const double dy = 1000. * DEG2DY(met->lat[iy1] - met->lat[iy0]);
9062 const double c0 = cos(DEG2RAD(met->lat[iy0]));
9063 const double c1 = cos(DEG2RAD(met->lat[iy1]));
9064 const double cr = cos(DEG2RAD(latr));
9065 const double vort = 2 * 7.2921e-5 * sin(DEG2RAD(latr));
9066
9067 /* Loop over grid points... */
9068 for (int ip = 0; ip < met->np; ip++) {
9069
9070 /* Get gradients in longitude... */
9071 const double dtdx
9072 = (met->t[ix1][iy][ip] - met->t[ix0][iy][ip]) * pows[ip] / dx;
9073 const double dvdx = (met->v[ix1][iy][ip] - met->v[ix0][iy][ip]) / dx;
9074
9075 /* Get gradients in latitude... */
9076 const double dtdy
9077 = (met->t[ix][iy1][ip] - met->t[ix][iy0][ip]) * pows[ip] / dy;
9078 const double dudy
9079 = (met->u[ix][iy1][ip] * c1 - met->u[ix][iy0][ip] * c0) / dy;
9080
9081 /* Set indices... */
9082 const int ip0 = MAX(ip - 1, 0);
9083 const int ip1 = MIN(ip + 1, met->np - 1);
9084
9085 /* Get gradients in pressure... */
9086 double dtdp, dudp, dvdp;
9087 const double dp0 = 100. * (met->p[ip] - met->p[ip0]);
9088 const double dp1 = 100. * (met->p[ip1] - met->p[ip]);
9089 if (ip != ip0 && ip != ip1) {
9090 double denom = dp0 * dp1 * (dp0 + dp1);
9091 dtdp = (dp0 * dp0 * met->t[ix][iy][ip1] * pows[ip1]
9092 - dp1 * dp1 * met->t[ix][iy][ip0] * pows[ip0]
9093 + (dp1 * dp1 - dp0 * dp0) * met->t[ix][iy][ip] * pows[ip])
9094 / denom;
9095 dudp = (dp0 * dp0 * met->u[ix][iy][ip1]
9096 - dp1 * dp1 * met->u[ix][iy][ip0]
9097 + (dp1 * dp1 - dp0 * dp0) * met->u[ix][iy][ip])
9098 / denom;
9099 dvdp = (dp0 * dp0 * met->v[ix][iy][ip1]
9100 - dp1 * dp1 * met->v[ix][iy][ip0]
9101 + (dp1 * dp1 - dp0 * dp0) * met->v[ix][iy][ip])
9102 / denom;
9103 } else {
9104 const double denom = dp0 + dp1;
9105 dtdp =
9106 (met->t[ix][iy][ip1] * pows[ip1] -
9107 met->t[ix][iy][ip0] * pows[ip0]) / denom;
9108 dudp = (met->u[ix][iy][ip1] - met->u[ix][iy][ip0]) / denom;
9109 dvdp = (met->v[ix][iy][ip1] - met->v[ix][iy][ip0]) / denom;
9110 }
9111
9112 /* Calculate PV... */
9113 met->pv[ix][iy][ip] = (float)
9114 (1e6 * G0 *
9115 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
9116 }
9117 }
9118 }
9119
9120 /* Fix for polar regions... */
9121#pragma omp parallel for default(shared)
9122 for (int ix = 0; ix < met->nx; ix++)
9123 for (int ip = 0; ip < met->np; ip++) {
9124 met->pv[ix][0][ip]
9125 = met->pv[ix][1][ip]
9126 = met->pv[ix][2][ip];
9127 met->pv[ix][met->ny - 1][ip]
9128 = met->pv[ix][met->ny - 2][ip]
9129 = met->pv[ix][met->ny - 3][ip];
9130 }
9131}
#define DEG2DY(dlat)
Convert a latitude difference to a distance in the y-direction (north-south).
Definition: mptrac.h:476
#define DEG2DX(dlon, lat)
Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude.
Definition: mptrac.h:455

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

9136 {
9137
9138 /* Set timer... */
9139 SELECT_TIMER("READ_MET_OZONE", "METPROC", NVTX_READ);
9140 LOG(2, "Calculate total column ozone...");
9141
9142 /* Loop over columns... */
9143#pragma omp parallel for default(shared) collapse(2)
9144 for (int ix = 0; ix < met->nx; ix++)
9145 for (int iy = 0; iy < met->ny; iy++) {
9146
9147 /* Integrate... */
9148 double cd = 0;
9149 for (int ip = 1; ip < met->np; ip++)
9150 if (met->p[ip - 1] <= met->ps[ix][iy]) {
9151 const double vmr =
9152 0.5 * (met->o3[ix][iy][ip - 1] + met->o3[ix][iy][ip]);
9153 const double dp = met->p[ip - 1] - met->p[ip];
9154 cd += vmr * MO3 / MA * dp * 1e2 / G0;
9155 }
9156
9157 /* Convert to Dobson units... */
9158 met->o3c[ix][iy] = (float) (cd / 2.1415e-5);
9159 }
9160}

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

9166 {
9167
9168 met_t *help;
9169
9170 /* Check parameters... */
9171 if (ctl->met_dp <= 1 && ctl->met_dx <= 1 && ctl->met_dy <= 1
9172 && ctl->met_sp <= 1 && ctl->met_sx <= 1 && ctl->met_sy <= 1)
9173 return;
9174
9175 /* Set timer... */
9176 SELECT_TIMER("READ_MET_SAMPLE", "METPROC", NVTX_READ);
9177 LOG(2, "Downsampling of meteo data...");
9178
9179 /* Allocate... */
9180 ALLOC(help, met_t, 1);
9181
9182 /* Copy data... */
9183 help->nx = met->nx;
9184 help->ny = met->ny;
9185 help->np = met->np;
9186 memcpy(help->lon, met->lon, sizeof(met->lon));
9187 memcpy(help->lat, met->lat, sizeof(met->lat));
9188 memcpy(help->p, met->p, sizeof(met->p));
9189
9190 /* Smoothing... */
9191 for (int ix = 0; ix < met->nx; ix += ctl->met_dx) {
9192 for (int iy = 0; iy < met->ny; iy += ctl->met_dy) {
9193 for (int ip = 0; ip < met->np; ip += ctl->met_dp) {
9194 help->ps[ix][iy] = 0;
9195 help->zs[ix][iy] = 0;
9196 help->ts[ix][iy] = 0;
9197 help->us[ix][iy] = 0;
9198 help->vs[ix][iy] = 0;
9199 help->ess[ix][iy] = 0;
9200 help->nss[ix][iy] = 0;
9201 help->shf[ix][iy] = 0;
9202 help->lsm[ix][iy] = 0;
9203 help->sst[ix][iy] = 0;
9204 help->pbl[ix][iy] = 0;
9205 help->cape[ix][iy] = 0;
9206 help->cin[ix][iy] = 0;
9207 help->t[ix][iy][ip] = 0;
9208 help->u[ix][iy][ip] = 0;
9209 help->v[ix][iy][ip] = 0;
9210 help->w[ix][iy][ip] = 0;
9211 help->h2o[ix][iy][ip] = 0;
9212 help->o3[ix][iy][ip] = 0;
9213 help->lwc[ix][iy][ip] = 0;
9214 help->rwc[ix][iy][ip] = 0;
9215 help->iwc[ix][iy][ip] = 0;
9216 help->swc[ix][iy][ip] = 0;
9217 help->cc[ix][iy][ip] = 0;
9218 float wsum = 0;
9219 for (int ix2 = ix - ctl->met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
9220 ix2++) {
9221 int ix3 = ix2;
9222 if (ix3 < 0)
9223 ix3 += met->nx;
9224 else if (ix3 >= met->nx)
9225 ix3 -= met->nx;
9226
9227 for (int iy2 = MAX(iy - ctl->met_sy + 1, 0);
9228 iy2 <= MIN(iy + ctl->met_sy - 1, met->ny - 1); iy2++)
9229 for (int ip2 = MAX(ip - ctl->met_sp + 1, 0);
9230 ip2 <= MIN(ip + ctl->met_sp - 1, met->np - 1); ip2++) {
9231 float w = (1.0f - (float) abs(ix - ix2) / (float) ctl->met_sx)
9232 * (1.0f - (float) abs(iy - iy2) / (float) ctl->met_sy)
9233 * (1.0f - (float) abs(ip - ip2) / (float) ctl->met_sp);
9234 help->ps[ix][iy] += w * met->ps[ix3][iy2];
9235 help->zs[ix][iy] += w * met->zs[ix3][iy2];
9236 help->ts[ix][iy] += w * met->ts[ix3][iy2];
9237 help->us[ix][iy] += w * met->us[ix3][iy2];
9238 help->vs[ix][iy] += w * met->vs[ix3][iy2];
9239 help->ess[ix][iy] += w * met->ess[ix3][iy2];
9240 help->nss[ix][iy] += w * met->nss[ix3][iy2];
9241 help->shf[ix][iy] += w * met->shf[ix3][iy2];
9242 help->lsm[ix][iy] += w * met->lsm[ix3][iy2];
9243 help->sst[ix][iy] += w * met->sst[ix3][iy2];
9244 help->pbl[ix][iy] += w * met->pbl[ix3][iy2];
9245 help->cape[ix][iy] += w * met->cape[ix3][iy2];
9246 help->cin[ix][iy] += w * met->cin[ix3][iy2];
9247 help->t[ix][iy][ip] += w * met->t[ix3][iy2][ip2];
9248 help->u[ix][iy][ip] += w * met->u[ix3][iy2][ip2];
9249 help->v[ix][iy][ip] += w * met->v[ix3][iy2][ip2];
9250 help->w[ix][iy][ip] += w * met->w[ix3][iy2][ip2];
9251 help->h2o[ix][iy][ip] += w * met->h2o[ix3][iy2][ip2];
9252 help->o3[ix][iy][ip] += w * met->o3[ix3][iy2][ip2];
9253 help->lwc[ix][iy][ip] += w * met->lwc[ix3][iy2][ip2];
9254 help->rwc[ix][iy][ip] += w * met->rwc[ix3][iy2][ip2];
9255 help->iwc[ix][iy][ip] += w * met->iwc[ix3][iy2][ip2];
9256 help->swc[ix][iy][ip] += w * met->swc[ix3][iy2][ip2];
9257 help->cc[ix][iy][ip] += w * met->cc[ix3][iy2][ip2];
9258 wsum += w;
9259 }
9260 }
9261 help->ps[ix][iy] /= wsum;
9262 help->zs[ix][iy] /= wsum;
9263 help->ts[ix][iy] /= wsum;
9264 help->us[ix][iy] /= wsum;
9265 help->vs[ix][iy] /= wsum;
9266 help->ess[ix][iy] /= wsum;
9267 help->nss[ix][iy] /= wsum;
9268 help->shf[ix][iy] /= wsum;
9269 help->lsm[ix][iy] /= wsum;
9270 help->sst[ix][iy] /= wsum;
9271 help->pbl[ix][iy] /= wsum;
9272 help->cape[ix][iy] /= wsum;
9273 help->cin[ix][iy] /= wsum;
9274 help->t[ix][iy][ip] /= wsum;
9275 help->u[ix][iy][ip] /= wsum;
9276 help->v[ix][iy][ip] /= wsum;
9277 help->w[ix][iy][ip] /= wsum;
9278 help->h2o[ix][iy][ip] /= wsum;
9279 help->o3[ix][iy][ip] /= wsum;
9280 help->lwc[ix][iy][ip] /= wsum;
9281 help->rwc[ix][iy][ip] /= wsum;
9282 help->iwc[ix][iy][ip] /= wsum;
9283 help->swc[ix][iy][ip] /= wsum;
9284 help->cc[ix][iy][ip] /= wsum;
9285 }
9286 }
9287 }
9288
9289 /* Downsampling... */
9290 met->nx = 0;
9291 for (int ix = 0; ix < help->nx; ix += ctl->met_dx) {
9292 met->lon[met->nx] = help->lon[ix];
9293 met->ny = 0;
9294 for (int iy = 0; iy < help->ny; iy += ctl->met_dy) {
9295 met->lat[met->ny] = help->lat[iy];
9296 met->ps[met->nx][met->ny] = help->ps[ix][iy];
9297 met->zs[met->nx][met->ny] = help->zs[ix][iy];
9298 met->ts[met->nx][met->ny] = help->ts[ix][iy];
9299 met->us[met->nx][met->ny] = help->us[ix][iy];
9300 met->vs[met->nx][met->ny] = help->vs[ix][iy];
9301 met->ess[met->nx][met->ny] = help->ess[ix][iy];
9302 met->nss[met->nx][met->ny] = help->nss[ix][iy];
9303 met->shf[met->nx][met->ny] = help->shf[ix][iy];
9304 met->lsm[met->nx][met->ny] = help->lsm[ix][iy];
9305 met->sst[met->nx][met->ny] = help->sst[ix][iy];
9306 met->pbl[met->nx][met->ny] = help->pbl[ix][iy];
9307 met->cape[met->nx][met->ny] = help->cape[ix][iy];
9308 met->cin[met->nx][met->ny] = help->cin[ix][iy];
9309 met->np = 0;
9310 for (int ip = 0; ip < help->np; ip += ctl->met_dp) {
9311 met->p[met->np] = help->p[ip];
9312 met->t[met->nx][met->ny][met->np] = help->t[ix][iy][ip];
9313 met->u[met->nx][met->ny][met->np] = help->u[ix][iy][ip];
9314 met->v[met->nx][met->ny][met->np] = help->v[ix][iy][ip];
9315 met->w[met->nx][met->ny][met->np] = help->w[ix][iy][ip];
9316 met->h2o[met->nx][met->ny][met->np] = help->h2o[ix][iy][ip];
9317 met->o3[met->nx][met->ny][met->np] = help->o3[ix][iy][ip];
9318 met->lwc[met->nx][met->ny][met->np] = help->lwc[ix][iy][ip];
9319 met->rwc[met->nx][met->ny][met->np] = help->rwc[ix][iy][ip];
9320 met->iwc[met->nx][met->ny][met->np] = help->iwc[ix][iy][ip];
9321 met->swc[met->nx][met->ny][met->np] = help->swc[ix][iy][ip];
9322 met->cc[met->nx][met->ny][met->np] = help->cc[ix][iy][ip];
9323 met->np++;
9324 }
9325 met->ny++;
9326 }
9327 met->nx++;
9328 }
9329
9330 /* Free... */
9331 free(help);
9332}
int met_dp
Stride for pressure levels.
Definition: mptrac.h:2645
int met_sy
Smoothing for latitudes.
Definition: mptrac.h:2651
int met_sx
Smoothing for longitudes.
Definition: mptrac.h:2648
int met_dx
Stride for longitudes.
Definition: mptrac.h:2639
int met_sp
Smoothing for pressure levels.
Definition: mptrac.h:2654
int met_dy
Stride for latitudes.
Definition: mptrac.h:2642

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

9339 {
9340
9341 /* Set timer... */
9342 SELECT_TIMER("READ_MET_SURFACE", "INPUT", NVTX_READ);
9343 LOG(2, "Read surface data...");
9344
9345 /* Read surface pressure... */
9346 if (read_met_nc_2d
9347 (ncid, "lnsp", "LNSP", NULL, NULL, NULL, NULL, ctl, met, met->ps,
9348 1.0f, 1)) {
9349 for (int ix = 0; ix < met->nx; ix++)
9350 for (int iy = 0; iy < met->ny; iy++)
9351 met->ps[ix][iy] = (float) (exp(met->ps[ix][iy]) / 100.);
9352 } else
9353 if (!read_met_nc_2d
9354 (ncid, "ps", "PS", "sp", "SP", NULL, NULL, ctl, met, met->ps, 0.01f,
9355 1)) {
9356 WARN("Cannot not read surface pressure data (use lowest level)!");
9357 for (int ix = 0; ix < met->nx; ix++)
9358 for (int iy = 0; iy < met->ny; iy++)
9359 met->ps[ix][iy]
9360 = (ctl->met_np > 0 ? (float) ctl->met_p[0] : (float) met->p[0]);
9361 }
9362
9363 /* MPTRAC meteo data... */
9364 if (ctl->met_clams == 0) {
9365
9366 /* Read geopotential height at the surface... */
9367 if (!read_met_nc_2d
9368 (ncid, "z", "Z", NULL, NULL, NULL, NULL, ctl, met, met->zs,
9369 (float) (1. / (1000. * G0)), 1))
9370 if (!read_met_nc_2d
9371 (ncid, "zm", "ZM", NULL, NULL, NULL, NULL, ctl, met, met->zs,
9372 (float) (1. / 1000.), 1))
9373 WARN("Cannot read surface geopotential height!");
9374 }
9375
9376 /* CLaMS meteo data... */
9377 else {
9378
9379 /* Read geopotential height at the surface
9380 (use lowermost level of 3-D data field)... */
9381 float *help;
9382 ALLOC(help, float,
9383 EX * EY * EP);
9384 memcpy(help, met->pl, sizeof(met->pl));
9385 if (!read_met_nc_3d
9386 (ncid, "gph", "GPH", NULL, NULL, ctl, met, met->pl,
9387 (float) (1e-3 / G0)))
9388 ERRMSG("Cannot read geopotential height!");
9389 for (int ix = 0; ix < met->nx; ix++)
9390 for (int iy = 0; iy < met->ny; iy++)
9391 met->zs[ix][iy] = met->pl[ix][iy][0];
9392 memcpy(met->pl, help, sizeof(met->pl));
9393 free(help);
9394 }
9395
9396 /* Read temperature at the surface... */
9397 if (!read_met_nc_2d
9398 (ncid, "t2m", "T2M", "2t", "2T", "t2", "T2", ctl, met, met->ts, 1.0, 1))
9399 WARN("Cannot read surface temperature!");
9400
9401 /* Read zonal wind at the surface... */
9402 if (!read_met_nc_2d
9403 (ncid, "u10m", "U10M", "10u", "10U", "u10", "U10", ctl, met, met->us,
9404 1.0, 1))
9405 WARN("Cannot read surface zonal wind!");
9406
9407 /* Read meridional wind at the surface... */
9408 if (!read_met_nc_2d
9409 (ncid, "v10m", "V10M", "10v", "10V", "v10", "V10", ctl, met, met->vs,
9410 1.0, 1))
9411 WARN("Cannot read surface meridional wind!");
9412
9413 /* Read eastward turbulent surface stress... */
9414 if (!read_met_nc_2d
9415 (ncid, "iews", "IEWS", NULL, NULL, NULL, NULL, ctl, met, met->ess,
9416 1.0, 1))
9417 WARN("Cannot read eastward turbulent surface stress!");
9418
9419 /* Read northward turbulent surface stress... */
9420 if (!read_met_nc_2d
9421 (ncid, "inss", "INSS", NULL, NULL, NULL, NULL, ctl, met, met->nss,
9422 1.0, 1))
9423 WARN("Cannot read nothward turbulent surface stress!");
9424
9425 /* Read surface sensible heat flux... */
9426 if (!read_met_nc_2d
9427 (ncid, "ishf", "ISHF", NULL, NULL, NULL, NULL, ctl, met, met->shf,
9428 1.0, 1))
9429 WARN("Cannot read surface sensible heat flux!");
9430
9431 /* Read land-sea mask... */
9432 if (!read_met_nc_2d
9433 (ncid, "lsm", "LSM", NULL, NULL, NULL, NULL, ctl, met, met->lsm, 1.0,
9434 1))
9435 WARN("Cannot read land-sea mask!");
9436
9437 /* Read sea surface temperature... */
9438 if (!read_met_nc_2d
9439 (ncid, "sstk", "SSTK", "sst", "SST", NULL, NULL, ctl, met, met->sst,
9440 1.0, 1))
9441 WARN("Cannot read sea surface temperature!");
9442
9443 /* Read PBL... */
9444 if (ctl->met_pbl == 0)
9445 if (!read_met_nc_2d
9446 (ncid, "blp", "BLP", NULL, NULL, NULL, NULL, ctl, met, met->pbl,
9447 0.01f, 1))
9448 WARN("Cannot read planetary boundary layer pressure!");
9449 if (ctl->met_pbl == 1)
9450 if (!read_met_nc_2d
9451 (ncid, "blh", "BLH", NULL, NULL, NULL, NULL, ctl, met, met->pbl,
9452 0.001f, 1))
9453 WARN("Cannot read planetary boundary layer height!");
9454
9455 /* Read CAPE... */
9456 if (ctl->met_cape == 0)
9457 if (!read_met_nc_2d
9458 (ncid, "cape", "CAPE", NULL, NULL, NULL, NULL, ctl, met, met->cape,
9459 1.0, 1))
9460 WARN("Cannot read CAPE!");
9461
9462 /* Read CIN... */
9463 if (ctl->met_cape == 0)
9464 if (!read_met_nc_2d
9465 (ncid, "cin", "CIN", NULL, NULL, NULL, NULL, ctl, met, met->cin,
9466 1.0, 1))
9467 WARN("Cannot read convective inhibition!");
9468}
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:8468
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 
)

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

This function reads various surface meteorological variables from a grib 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
handlesA pointer to an array of codes_handle pointers representing the grib messages.
num_messagesThe total number of grib messages in the handles array.
ctlA pointer to a structure containing control parameters.
metA pointer to a structure to store meteorological data.

The function performs the following steps:

  • Sets a timer for performance monitoring.
  • Reads surface meteorological data based on the configuration:
  • Reads surface pressure from "lnsp", "ps", or "sp" variables.
  • Converts surface pressure to Pa.
  • 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.
Authors
Nils Nobre Wittwer

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

9564 {
9565
9566 double p2[200], pv[EP], pv2[200], t[EP], t2[200], th[EP],
9567 th2[200], z[EP], z2[200];
9568
9569 /* Set timer... */
9570 SELECT_TIMER("READ_MET_TROPO", "METPROC", NVTX_READ);
9571 LOG(2, "Calculate tropopause...");
9572
9573 /* Get altitude and pressure profiles... */
9574#pragma omp parallel for default(shared)
9575 for (int iz = 0; iz < met->np; iz++)
9576 z[iz] = Z(met->p[iz]);
9577#pragma omp parallel for default(shared)
9578 for (int iz = 0; iz <= 190; iz++) {
9579 z2[iz] = 4.5 + 0.1 * iz;
9580 p2[iz] = P(z2[iz]);
9581 }
9582
9583 /* Do not calculate tropopause... */
9584 if (ctl->met_tropo == 0)
9585#pragma omp parallel for default(shared) collapse(2)
9586 for (int ix = 0; ix < met->nx; ix++)
9587 for (int iy = 0; iy < met->ny; iy++)
9588 met->pt[ix][iy] = NAN;
9589
9590 /* Use tropopause climatology... */
9591 else if (ctl->met_tropo == 1) {
9592#pragma omp parallel for default(shared) collapse(2)
9593 for (int ix = 0; ix < met->nx; ix++)
9594 for (int iy = 0; iy < met->ny; iy++)
9595 met->pt[ix][iy] = (float) clim_tropo(clim, met->time, met->lat[iy]);
9596 }
9597
9598 /* Use cold point... */
9599 else if (ctl->met_tropo == 2) {
9600
9601 /* Loop over grid points... */
9602#pragma omp parallel for default(shared) private(t,t2) collapse(2)
9603 for (int ix = 0; ix < met->nx; ix++)
9604 for (int iy = 0; iy < met->ny; iy++) {
9605
9606 /* Interpolate temperature profile... */
9607 for (int iz = 0; iz < met->np; iz++)
9608 t[iz] = met->t[ix][iy][iz];
9609 spline(z, t, met->np, z2, t2, 171, ctl->met_tropo_spline);
9610
9611 /* Find minimum... */
9612 int iz = (int) gsl_stats_min_index(t2, 1, 171);
9613 if (iz > 0 && iz < 170)
9614 met->pt[ix][iy] = (float) p2[iz];
9615 else
9616 met->pt[ix][iy] = NAN;
9617 }
9618 }
9619
9620 /* Use WMO definition... */
9621 else if (ctl->met_tropo == 3 || ctl->met_tropo == 4) {
9622
9623 /* Loop over grid points... */
9624#pragma omp parallel for default(shared) private(t,t2) collapse(2)
9625 for (int ix = 0; ix < met->nx; ix++)
9626 for (int iy = 0; iy < met->ny; iy++) {
9627
9628 /* Interpolate temperature profile... */
9629 int iz;
9630 for (iz = 0; iz < met->np; iz++)
9631 t[iz] = met->t[ix][iy][iz];
9632 spline(z, t, met->np, z2, t2, 191, ctl->met_tropo_spline);
9633
9634 /* Find 1st tropopause... */
9635 met->pt[ix][iy] = NAN;
9636 for (iz = 0; iz <= 170; iz++) {
9637 int found = 1;
9638 for (int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
9639 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
9640 found = 0;
9641 break;
9642 }
9643 if (found) {
9644 if (iz > 0 && iz < 170)
9645 met->pt[ix][iy] = (float) p2[iz];
9646 break;
9647 }
9648 }
9649
9650 /* Find 2nd tropopause... */
9651 if (ctl->met_tropo == 4) {
9652 met->pt[ix][iy] = NAN;
9653 for (; iz <= 170; iz++) {
9654 int found = 1;
9655 for (int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
9656 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
9657 found = 0;
9658 break;
9659 }
9660 if (found)
9661 break;
9662 }
9663 for (; iz <= 170; iz++) {
9664 int found = 1;
9665 for (int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
9666 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
9667 found = 0;
9668 break;
9669 }
9670 if (found) {
9671 if (iz > 0 && iz < 170)
9672 met->pt[ix][iy] = (float) p2[iz];
9673 break;
9674 }
9675 }
9676 }
9677 }
9678 }
9679
9680 /* Use dynamical tropopause... */
9681 else if (ctl->met_tropo == 5) {
9682
9683 /* Loop over grid points... */
9684#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
9685 for (int ix = 0; ix < met->nx; ix++)
9686 for (int iy = 0; iy < met->ny; iy++) {
9687
9688 /* Interpolate potential vorticity profile... */
9689 for (int iz = 0; iz < met->np; iz++)
9690 pv[iz] = met->pv[ix][iy][iz];
9691 spline(z, pv, met->np, z2, pv2, 171, ctl->met_tropo_spline);
9692
9693 /* Interpolate potential temperature profile... */
9694 for (int iz = 0; iz < met->np; iz++)
9695 th[iz] = THETA(met->p[iz], met->t[ix][iy][iz]);
9696 spline(z, th, met->np, z2, th2, 171, ctl->met_tropo_spline);
9697
9698 /* Find dynamical tropopause... */
9699 met->pt[ix][iy] = NAN;
9700 for (int iz = 0; iz <= 170; iz++)
9701 if (fabs(pv2[iz]) >= ctl->met_tropo_pv
9702 || th2[iz] >= ctl->met_tropo_theta) {
9703 if (iz > 0 && iz < 170)
9704 met->pt[ix][iy] = (float) p2[iz];
9705 break;
9706 }
9707 }
9708 }
9709
9710 else
9711 ERRMSG("Cannot calculate tropopause!");
9712
9713 /* Interpolate temperature, geopotential height, and water vapor... */
9714#pragma omp parallel for default(shared) collapse(2)
9715 for (int ix = 0; ix < met->nx; ix++)
9716 for (int iy = 0; iy < met->ny; iy++) {
9717 double h2ot, tt, zt;
9719 intpol_met_space_3d(met, met->t, met->pt[ix][iy], met->lon[ix],
9720 met->lat[iy], &tt, ci, cw, 1);
9721 intpol_met_space_3d(met, met->z, met->pt[ix][iy], met->lon[ix],
9722 met->lat[iy], &zt, ci, cw, 0);
9723 intpol_met_space_3d(met, met->h2o, met->pt[ix][iy], met->lon[ix],
9724 met->lat[iy], &h2ot, ci, cw, 0);
9725 met->tt[ix][iy] = (float) tt;
9726 met->zt[ix][iy] = (float) zt;
9727 met->h2ot[ix][iy] = (float) h2ot;
9728 }
9729}
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:9939
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
Definition: mptrac.h:920
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 9733 of file mptrac.c.

9741 {
9742
9743 /* Write info... */
9744 LOG(1, "Read observation data: %s", filename);
9745
9746 /* Read data... */
9747 if (ctl->obs_type == 0)
9748 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
9749 else if (ctl->obs_type == 1)
9750 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
9751 else
9752 ERRMSG("Set OBS_TYPE to 0 or 1!");
9753
9754 /* Check time... */
9755 for (int i = 1; i < *nobs; i++)
9756 if (rt[i] < rt[i - 1])
9757 ERRMSG("Time must be ascending!");
9758
9759 /* Write info... */
9760 int n = *nobs;
9761 double mini, maxi;
9762 LOG(2, "Number of observations: %d", *nobs);
9763 gsl_stats_minmax(&mini, &maxi, rt, 1, (size_t) n);
9764 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
9765 gsl_stats_minmax(&mini, &maxi, rz, 1, (size_t) n);
9766 LOG(2, "Altitude range: %g ... %g km", mini, maxi);
9767 gsl_stats_minmax(&mini, &maxi, rlon, 1, (size_t) n);
9768 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
9769 gsl_stats_minmax(&mini, &maxi, rlat, 1, (size_t) n);
9770 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
9771 gsl_stats_minmax(&mini, &maxi, robs, 1, (size_t) n);
9772 LOG(2, "Observation range: %g ... %g", mini, maxi);
9773}
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:9777
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:9805
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 9777 of file mptrac.c.

9784 {
9785
9786 /* Open observation data file... */
9787 FILE *in;
9788 if (!(in = fopen(filename, "r")))
9789 ERRMSG("Cannot open file!");
9790
9791 /* Read observations... */
9792 char line[LEN];
9793 while (fgets(line, LEN, in))
9794 if (sscanf(line, "%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
9795 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
9796 if ((++(*nobs)) >= NOBS)
9797 ERRMSG("Too many observations!");
9798
9799 /* Close observation data file... */
9800 fclose(in);
9801}
#define NOBS
Maximum number of observation data points.
Definition: mptrac.h:296

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

9812 {
9813
9814 int ncid, varid;
9815
9816 /* Open netCDF file... */
9817 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
9818 ERRMSG("Cannot open file!");
9819
9820 /* Read the observations from the NetCDF file... */
9821 NC_INQ_DIM("nobs", nobs, 1, NOBS);
9822 NC_GET_DOUBLE("time", rt, 1);
9823 NC_GET_DOUBLE("alt", rz, 1);
9824 NC_GET_DOUBLE("lon", rlon, 1);
9825 NC_GET_DOUBLE("lat", rlat, 1);
9826 NC_GET_DOUBLE("obs", robs, 1);
9827
9828 /* Close file... */
9829 NC(nc_close(ncid));
9830}

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

9841 {
9842
9843 FILE *in = NULL;
9844
9845 char fullname1[LEN], fullname2[LEN], rval[LEN];
9846
9847 int contain = 0, i;
9848
9849 /* Open file... */
9850 if (filename[strlen(filename) - 1] != '-')
9851 if (!(in = fopen(filename, "r")))
9852 ERRMSG("Cannot open file!");
9853
9854 /* Set full variable name... */
9855 if (arridx >= 0) {
9856 sprintf(fullname1, "%s[%d]", varname, arridx);
9857 sprintf(fullname2, "%s[*]", varname);
9858 } else {
9859 sprintf(fullname1, "%s", varname);
9860 sprintf(fullname2, "%s", varname);
9861 }
9862
9863 /* Read data... */
9864 if (in != NULL) {
9865 char dummy[LEN], line[LEN], rvarname[LEN];
9866 while (fgets(line, LEN, in)) {
9867 if (sscanf(line, "%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
9868 if (strcasecmp(rvarname, fullname1) == 0 ||
9869 strcasecmp(rvarname, fullname2) == 0) {
9870 contain = 1;
9871 break;
9872 }
9873 }
9874 }
9875 for (i = 1; i < argc - 1; i++)
9876 if (strcasecmp(argv[i], fullname1) == 0 ||
9877 strcasecmp(argv[i], fullname2) == 0) {
9878 sprintf(rval, "%s", argv[i + 1]);
9879 contain = 1;
9880 break;
9881 }
9882
9883 /* Close file... */
9884 if (in != NULL)
9885 fclose(in);
9886
9887 /* Check for missing variables... */
9888 if (!contain) {
9889 if (strlen(defvalue) > 0)
9890 sprintf(rval, "%s", defvalue);
9891 else
9892 ERRMSG("Missing variable %s!\n", fullname1);
9893 }
9894
9895 /* Write info... */
9896 LOG(1, "%s = %s", fullname1, rval);
9897
9898 /* Return values... */
9899 if (value != NULL)
9900 sprintf(value, "%s", rval);
9901 return atof(rval);
9902}

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

9910 {
9911
9912 /* Convert particle radius from microns to m... */
9913 const double rp_help = rp * 1e-6;
9914
9915 /* Density of dry air [kg / m^3]... */
9916 const double rho = RHO(p, T);
9917
9918 /* Dynamic viscosity of air [kg / (m s)]... */
9919 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
9920
9921 /* Thermal velocity of an air molecule [m / s]... */
9922 const double v = sqrt(8. * KB * T / (M_PI * 4.8096e-26));
9923
9924 /* Mean free path of an air molecule [m]... */
9925 const double lambda = 2. * eta / (rho * v);
9926
9927 /* Knudsen number for air (dimensionless)... */
9928 const double K = lambda / rp_help;
9929
9930 /* Cunningham slip-flow correction (dimensionless)... */
9931 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
9932
9933 /* Sedimentation velocity [m / s]... */
9934 return 2. * SQR(rp_help) * (rhop - rho) * G0 / (9. * eta) * G;
9935}
#define KB
Boltzmann constant [kg m^2/(K s^2)].
Definition: mptrac.h:207

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

9946 {
9947
9948 /* Cubic spline interpolation... */
9949 if (method == 1) {
9950
9951 /* Allocate... */
9952 gsl_interp_accel *acc = gsl_interp_accel_alloc();
9953 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (size_t) n);
9954
9955 /* Interpolate profile... */
9956 gsl_spline_init(s, x, y, (size_t) n);
9957 for (int i = 0; i < n2; i++)
9958 if (x2[i] <= x[0])
9959 y2[i] = y[0];
9960 else if (x2[i] >= x[n - 1])
9961 y2[i] = y[n - 1];
9962 else
9963 y2[i] = gsl_spline_eval(s, x2[i], acc);
9964
9965 /* Free... */
9966 gsl_spline_free(s);
9967 gsl_interp_accel_free(acc);
9968 }
9969
9970 /* Linear interpolation... */
9971 else {
9972 for (int i = 0; i < n2; i++)
9973 if (x2[i] <= x[0])
9974 y2[i] = y[0];
9975 else if (x2[i] >= x[n - 1])
9976 y2[i] = y[n - 1];
9977 else {
9978 int idx = locate_irr(x, n, x2[i]);
9979 y2[i] = LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
9980 }
9981 }
9982}
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 9986 of file mptrac.c.

9988 {
9989
9990 if (n <= 0)
9991 return 0;
9992
9993 float mean = 0, var = 0;
9994
9995 for (int i = 0; i < n; ++i) {
9996 mean += data[i];
9997 var += SQR(data[i]);
9998 }
9999
10000 var = var / (float) n - SQR(mean / (float) n);
10001
10002 return (var > 0 ? sqrtf(var) : 0);
10003}

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

10010 {
10011
10012 /* Number of days and fraction with respect to 2000-01-01T12:00Z... */
10013 const double D = sec / 86400 - 0.5;
10014
10015 /* Geocentric apparent ecliptic longitude [rad]... */
10016 const double g = DEG2RAD(357.529 + 0.98560028 * D);
10017 const double q = 280.459 + 0.98564736 * D;
10018 const double L = DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
10019
10020 /* Mean obliquity of the ecliptic [rad]... */
10021 const double e = DEG2RAD(23.439 - 0.00000036 * D);
10022
10023 /* Declination [rad]... */
10024 const double sindec = sin(e) * sin(L);
10025
10026 /* Right ascension [rad]... */
10027 const double ra = atan2(cos(e) * sin(L), cos(L));
10028
10029 /* Greenwich Mean Sidereal Time [h]... */
10030 const double GMST = 18.697374558 + 24.06570982441908 * D;
10031
10032 /* Local Sidereal Time [h]... */
10033 const double LST = GMST + lon / 15;
10034
10035 /* Hour angle [rad]... */
10036 const double h = LST / 12 * M_PI - ra;
10037
10038 /* Convert latitude... */
10039 const double lat_help = DEG2RAD(lat);
10040
10041 /* Return solar zenith angle [rad]... */
10042 return acos(sin(lat_help) * sindec +
10043 cos(lat_help) * sqrt(1 - SQR(sindec)) * cos(h));
10044}

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

10056 {
10057
10058 struct tm t0, t1;
10059
10060 t0.tm_year = 100;
10061 t0.tm_mon = 0;
10062 t0.tm_mday = 1;
10063 t0.tm_hour = 0;
10064 t0.tm_min = 0;
10065 t0.tm_sec = 0;
10066
10067 t1.tm_year = year - 1900;
10068 t1.tm_mon = mon - 1;
10069 t1.tm_mday = day;
10070 t1.tm_hour = hour;
10071 t1.tm_min = min;
10072 t1.tm_sec = sec;
10073
10074 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
10075}

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

10082 {
10083
10084 static char names[NTIMER][100], groups[NTIMER][100];
10085
10086 static double rt_name[NTIMER], rt_group[NTIMER],
10087 rt_min[NTIMER], rt_max[NTIMER], dt, t0, t1;
10088
10089 static int iname = -1, igroup = -1, nname, ngroup, ct_name[NTIMER];
10090
10091 /* Get time... */
10092 t1 = omp_get_wtime();
10093 dt = t1 - t0;
10094
10095 /* Add elapsed time to current timers... */
10096 if (iname >= 0) {
10097 rt_name[iname] += dt;
10098 rt_min[iname] = (ct_name[iname] <= 0 ? dt : MIN(rt_min[iname], dt));
10099 rt_max[iname] = (ct_name[iname] <= 0 ? dt : MAX(rt_max[iname], dt));
10100 ct_name[iname]++;
10101 }
10102 if (igroup >= 0)
10103 rt_group[igroup] += t1 - t0;
10104
10105 /* Report timers... */
10106 if (output) {
10107 for (int i = 0; i < nname; i++)
10108 LOG(1, "TIMER_%s = %.3f s (min= %g s, mean= %g s,"
10109 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
10110 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
10111 for (int i = 0; i < ngroup; i++)
10112 LOG(1, "TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
10113 double total = 0.0;
10114 for (int i = 0; i < nname; i++)
10115 total += rt_name[i];
10116 LOG(1, "TIMER_TOTAL = %.3f s", total);
10117 }
10118
10119 /* Identify IDs of next timer... */
10120 for (iname = 0; iname < nname; iname++)
10121 if (strcasecmp(name, names[iname]) == 0)
10122 break;
10123 for (igroup = 0; igroup < ngroup; igroup++)
10124 if (strcasecmp(group, groups[igroup]) == 0)
10125 break;
10126
10127 /* Check whether this is a new timer... */
10128 if (iname >= nname) {
10129 sprintf(names[iname], "%s", name);
10130 if ((++nname) >= NTIMER)
10131 ERRMSG("Too many timers!");
10132 }
10133
10134 /* Check whether this is a new group... */
10135 if (igroup >= ngroup) {
10136 sprintf(groups[igroup], "%s", group);
10137 if ((++ngroup) >= NTIMER)
10138 ERRMSG("Too many groups!");
10139 }
10140
10141 /* Save starting time... */
10142 t0 = t1;
10143}
#define NTIMER
Maximum number of timers.
Definition: mptrac.h:2028

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

10149 {
10150
10151 char tstr[10];
10152
10153 double t;
10154
10155 /* Get time from filename... */
10156 int len = (int) strlen(filename);
10157 sprintf(tstr, "%.4s", &filename[len - offset]);
10158 int year = atoi(tstr);
10159 sprintf(tstr, "%.2s", &filename[len - offset + 5]);
10160 int mon = atoi(tstr);
10161 sprintf(tstr, "%.2s", &filename[len - offset + 8]);
10162 int day = atoi(tstr);
10163 sprintf(tstr, "%.2s", &filename[len - offset + 11]);
10164 int hour = atoi(tstr);
10165 sprintf(tstr, "%.2s", &filename[len - offset + 14]);
10166 int min = atoi(tstr);
10167
10168 /* Check time... */
10169 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
10170 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
10171 ERRMSG("Cannot read time from filename!");
10172
10173 /* Convert time to Julian seconds... */
10174 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
10175
10176 /* Return time... */
10177 return t;
10178}
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 10182 of file mptrac.c.

10185 {
10186
10187 /* Get tropopause pressure... */
10188 const double pt = clim_tropo(clim, atm->time[ip], atm->lat[ip]);
10189
10190 /* Get pressure range... */
10191 const double p1 = pt * 0.866877899;
10192 const double p0 = pt / 0.866877899;
10193
10194 /* Get weighting factor... */
10195 if (atm->p[ip] > p0)
10196 return 1;
10197 else if (atm->p[ip] < p1)
10198 return 0;
10199 else
10200 return LIN(p0, 1.0, p1, 0.0, atm->p[ip]);
10201}
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 10205 of file mptrac.c.

10209 {
10210
10211 FILE *out;
10212
10213 /* Set time interval for output... */
10214 const double t0 = t - 0.5 * ctl->dt_mod;
10215 const double t1 = t + 0.5 * ctl->dt_mod;
10216
10217 /* Check if gnuplot output is requested... */
10218 if (ctl->atm_gpfile[0] != '-') {
10219
10220 /* Create gnuplot pipe... */
10221 if (!(out = popen("gnuplot", "w")))
10222 ERRMSG("Cannot create pipe to gnuplot!");
10223
10224 /* Set plot filename... */
10225 fprintf(out, "set out \"%s.png\"\n", filename);
10226
10227 /* Set time string... */
10228 double r;
10229 int year, mon, day, hour, min, sec;
10230 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
10231 fprintf(out, "timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
10232 year, mon, day, hour, min);
10233
10234 /* Dump gnuplot file to pipe... */
10235 FILE *in;
10236 if (!(in = fopen(ctl->atm_gpfile, "r")))
10237 ERRMSG("Cannot open file!");
10238 char line[LEN];
10239 while (fgets(line, LEN, in))
10240 fprintf(out, "%s", line);
10241 fclose(in);
10242 }
10243
10244 else {
10245
10246 /* Create file... */
10247 if (!(out = fopen(filename, "w")))
10248 ERRMSG("Cannot create file!");
10249 }
10250
10251 /* Write header... */
10252 fprintf(out,
10253 "# $1 = time [s]\n"
10254 "# $2 = altitude [km]\n"
10255 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
10256 for (int iq = 0; iq < ctl->nq; iq++)
10257 fprintf(out, "# $%i = %s [%s]\n", iq + 5, ctl->qnt_name[iq],
10258 ctl->qnt_unit[iq]);
10259 fprintf(out, "\n");
10260
10261 /* Write data... */
10262 for (int ip = 0; ip < atm->np; ip += ctl->atm_stride) {
10263
10264 /* Check time... */
10265 if (ctl->atm_filter == 2 && (atm->time[ip] < t0 || atm->time[ip] > t1))
10266 continue;
10267
10268 /* Write output... */
10269 fprintf(out, "%.2f %g %g %g", atm->time[ip], Z(atm->p[ip]),
10270 atm->lon[ip], atm->lat[ip]);
10271 for (int iq = 0; iq < ctl->nq; iq++) {
10272 fprintf(out, " ");
10273 if (ctl->atm_filter == 1 && (atm->time[ip] < t0 || atm->time[ip] > t1))
10274 fprintf(out, ctl->qnt_format[iq], NAN);
10275 else
10276 fprintf(out, ctl->qnt_format[iq], atm->q[iq][ip]);
10277 }
10278 fprintf(out, "\n");
10279 }
10280
10281 /* Close file... */
10282 fclose(out);
10283}
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 10287 of file mptrac.c.

10290 {
10291
10292 FILE *out;
10293
10294 /* Create file... */
10295 if (!(out = fopen(filename, "w")))
10296 ERRMSG("Cannot create file!");
10297
10298 /* Write version of binary data... */
10299 int version = 100;
10300 FWRITE(&version, int,
10301 1,
10302 out);
10303
10304 /* Write data... */
10305 FWRITE(&atm->np, int,
10306 1,
10307 out);
10308 FWRITE(atm->time, double,
10309 (size_t) atm->np,
10310 out);
10311 FWRITE(atm->p, double,
10312 (size_t) atm->np,
10313 out);
10314 FWRITE(atm->lon, double,
10315 (size_t) atm->np,
10316 out);
10317 FWRITE(atm->lat, double,
10318 (size_t) atm->np,
10319 out);
10320 for (int iq = 0; iq < ctl->nq; iq++)
10321 FWRITE(atm->q[iq], double,
10322 (size_t) atm->np,
10323 out);
10324
10325 /* Write final flag... */
10326 int final = 999;
10327 FWRITE(&final, int,
10328 1,
10329 out);
10330
10331 /* Close file... */
10332 fclose(out);
10333}

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

10340 {
10341
10342 int tid, pid, ncid, varid;
10343 size_t start[2], count[2];
10344
10345 /* Create file... */
10346 nc_create(filename, NC_NETCDF4, &ncid);
10347
10348 /* Define dimensions... */
10349 NC(nc_def_dim(ncid, "time", 1, &tid));
10350 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
10351
10352 /* Define variables and their attributes... */
10353 int dim_ids[2] = { tid, pid };
10354 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
10355 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
10356 NC_DEF_VAR("LAT", NC_DOUBLE, 1, &pid, "Latitude", "deg",
10357 ctl->atm_nc_level, 0);
10358 NC_DEF_VAR("LON", NC_DOUBLE, 1, &pid, "Longitude", "deg",
10359 ctl->atm_nc_level, 0);
10360 NC_DEF_VAR("PRESS", NC_DOUBLE, 1, &pid, "Pressure", "hPa",
10361 ctl->atm_nc_level, 0);
10362 NC_DEF_VAR("ZETA", NC_DOUBLE, 1, &pid, "Zeta", "K", ctl->atm_nc_level, 0);
10363 for (int iq = 0; iq < ctl->nq; iq++)
10364 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
10365 ctl->qnt_name[iq], ctl->qnt_unit[iq],
10366 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
10367
10368 /* Define global attributes... */
10369 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
10370 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
10371
10372 /* End definitions... */
10373 NC(nc_enddef(ncid));
10374
10375 /* Write data... */
10376 NC_PUT_DOUBLE("time", atm->time, 0);
10377 NC_PUT_DOUBLE("LAT", atm->lat, 0);
10378 NC_PUT_DOUBLE("LON", atm->lon, 0);
10379 NC_PUT_DOUBLE("PRESS", atm->p, 0);
10380 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 0);
10381 for (int iq = 0; iq < ctl->nq; iq++)
10382 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
10383
10384 /* Close file... */
10385 NC(nc_close(ncid));
10386}
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
Definition: mptrac.h:1292
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units, level, quant)
Define a NetCDF variable with attributes.
Definition: mptrac.h:1125
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
Write double precision data to a NetCDF variable.
Definition: mptrac.h:1206

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

10394 {
10395
10396 /* Global Counter... */
10397 static size_t out_cnt = 0;
10398
10399 double r, r_start, r_stop;
10400 int year, mon, day, hour, min, sec;
10401 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
10402 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
10403 char filename_out[2 * LEN] = "traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
10404
10405 int ncid, varid, tid, pid, cid;
10406 int dim_ids[2];
10407
10408 /* time, nparc */
10409 size_t start[2];
10410 size_t count[2];
10411
10412 /* Determine start and stop times of calculation... */
10413 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
10414 jsec2time(ctl->t_start, &year_start, &mon_start, &day_start, &hour_start,
10415 &min_start, &sec_start, &r_start);
10416 jsec2time(ctl->t_stop, &year_stop, &mon_stop, &day_stop, &hour_stop,
10417 &min_stop, &sec_stop, &r_stop);
10418
10419 sprintf(filename_out,
10420 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
10421 year_start % 100, mon_start, day_start, hour_start,
10422 year_stop % 100, mon_stop, day_stop, hour_stop);
10423 LOG(1, "Write traj file: %s", filename_out);
10424
10425 /* Define hyperslap for the traj_file... */
10426 start[0] = out_cnt;
10427 start[1] = 0;
10428 count[0] = 1;
10429 count[1] = (size_t) atm->np;
10430
10431 /* Create the file at the first timestep... */
10432 if (out_cnt == 0) {
10433
10434 /* Create file... */
10435 nc_create(filename_out, NC_NETCDF4, &ncid);
10436
10437 /* Define dimensions... */
10438 NC(nc_def_dim(ncid, "time", NC_UNLIMITED, &tid));
10439 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
10440 NC(nc_def_dim(ncid, "TMDT", 7, &cid));
10441 dim_ids[0] = tid;
10442 dim_ids[1] = pid;
10443
10444 /* Define variables and their attributes... */
10445 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
10446 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
10447 NC_DEF_VAR("LAT", NC_DOUBLE, 2, dim_ids, "Latitude", "deg",
10448 ctl->atm_nc_level, 0);
10449 NC_DEF_VAR("LON", NC_DOUBLE, 2, dim_ids, "Longitude", "deg",
10450 ctl->atm_nc_level, 0);
10451 NC_DEF_VAR("PRESS", NC_DOUBLE, 2, dim_ids, "Pressure", "hPa",
10452 ctl->atm_nc_level, 0);
10453 NC_DEF_VAR("ZETA", NC_DOUBLE, 2, dim_ids, "Zeta", "K",
10454 ctl->atm_nc_level, 0);
10455 for (int iq = 0; iq < ctl->nq; iq++)
10456 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
10457 ctl->qnt_name[iq], ctl->qnt_unit[iq],
10458 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
10459
10460 /* Define global attributes... */
10461 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
10462 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
10463
10464 /* End definitions... */
10465 NC(nc_enddef(ncid));
10466 NC(nc_close(ncid));
10467 }
10468
10469 /* Increment global counter to change hyperslap... */
10470 out_cnt++;
10471
10472 /* Open file... */
10473 NC(nc_open(filename_out, NC_WRITE, &ncid));
10474
10475 /* Write data... */
10476 NC_PUT_DOUBLE("time", atm->time, 1);
10477 NC_PUT_DOUBLE("LAT", atm->lat, 1);
10478 NC_PUT_DOUBLE("LON", atm->lon, 1);
10479 NC_PUT_DOUBLE("PRESS", atm->p, 1);
10480 if (ctl->advect_vert_coord == 1) {
10481 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta], 1);
10482 } else if (ctl->qnt_zeta >= 0) {
10483 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 1);
10484 }
10485 for (int iq = 0; iq < ctl->nq; iq++)
10486 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 1);
10487
10488 /* Close file... */
10489 NC(nc_close(ncid));
10490
10491 /* At the last time step create the init_fix_YYYYMMDDHH file... */
10492 if ((year == year_stop) && (mon == mon_stop)
10493 && (day == day_stop) && (hour == hour_stop)) {
10494
10495 /* Set filename... */
10496 char filename_init[2 * LEN] = "./init_fix_YYYYMMDDHH.nc";
10497 sprintf(filename_init, "%s/init_fix_%02d%02d%02d%02d.nc",
10498 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
10499 LOG(1, "Write init file: %s", filename_init);
10500
10501 /* Create file... */
10502 nc_create(filename_init, NC_NETCDF4, &ncid);
10503
10504 /* Define dimensions... */
10505 NC(nc_def_dim(ncid, "time", 1, &tid));
10506 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
10507 dim_ids[0] = tid;
10508 dim_ids[1] = pid;
10509
10510 /* Define variables and their attributes... */
10511 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
10512 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
10513 NC_DEF_VAR("LAT", NC_DOUBLE, 1, &pid, "Latitude", "deg",
10514 ctl->atm_nc_level, 0);
10515 NC_DEF_VAR("LON", NC_DOUBLE, 1, &pid, "Longitude", "deg",
10516 ctl->atm_nc_level, 0);
10517 NC_DEF_VAR("PRESS", NC_DOUBLE, 1, &pid, "Pressure", "hPa",
10518 ctl->atm_nc_level, 0);
10519 NC_DEF_VAR("ZETA", NC_DOUBLE, 1, &pid, "Zeta", "K", ctl->atm_nc_level, 0);
10520 for (int iq = 0; iq < ctl->nq; iq++)
10521 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
10522 ctl->qnt_name[iq], ctl->qnt_unit[iq],
10523 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
10524
10525 /* Define global attributes... */
10526 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
10527 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
10528
10529 /* End definitions... */
10530 NC(nc_enddef(ncid));
10531
10532 /* Write data... */
10533 NC_PUT_DOUBLE("time", atm->time, 0);
10534 NC_PUT_DOUBLE("LAT", atm->lat, 0);
10535 NC_PUT_DOUBLE("LON", atm->lon, 0);
10536 NC_PUT_DOUBLE("PRESS", atm->p, 0);
10537 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 0);
10538 for (int iq = 0; iq < ctl->nq; iq++)
10539 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
10540
10541 /* Close file... */
10542 NC(nc_close(ncid));
10543 }
10544}
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 10548 of file mptrac.c.

10551 {
10552
10553 int ncid, obsid, varid;
10554
10555 size_t start[2], count[2];
10556
10557 /* Create file... */
10558 NC(nc_create(filename, NC_NETCDF4, &ncid));
10559
10560 /* Define dimensions... */
10561 NC(nc_def_dim(ncid, "obs", (size_t) atm->np, &obsid));
10562
10563 /* Define variables and their attributes... */
10564 NC_DEF_VAR("time", NC_DOUBLE, 1, &obsid, "time",
10565 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
10566 NC_DEF_VAR("press", NC_DOUBLE, 1, &obsid, "pressure", "hPa",
10567 ctl->atm_nc_level, 0);
10568 NC_DEF_VAR("lon", NC_DOUBLE, 1, &obsid, "longitude", "degrees_east",
10569 ctl->atm_nc_level, 0);
10570 NC_DEF_VAR("lat", NC_DOUBLE, 1, &obsid, "latitude", "degrees_north",
10571 ctl->atm_nc_level, 0);
10572 for (int iq = 0; iq < ctl->nq; iq++)
10573 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 1, &obsid,
10574 ctl->qnt_longname[iq], ctl->qnt_unit[iq],
10575 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
10576
10577 /* Define global attributes... */
10578 NC_PUT_ATT_GLOBAL("featureType", "point");
10579
10580 /* End definitions... */
10581 NC(nc_enddef(ncid));
10582
10583 /* Write data... */
10584 NC_PUT_DOUBLE("time", atm->time, 0);
10585 NC_PUT_DOUBLE("press", atm->p, 0);
10586 NC_PUT_DOUBLE("lon", atm->lon, 0);
10587 NC_PUT_DOUBLE("lat", atm->lat, 0);
10588 for (int iq = 0; iq < ctl->nq; iq++)
10589 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
10590
10591 /* Close file... */
10592 NC(nc_close(ncid));
10593}

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

10601 {
10602
10603 static FILE *out;
10604
10605 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
10606 *area, dlon, dlat, dz, x[NCSI], y[NCSI], obsstdn[NCSI], kz[EP], kw[EP];
10607
10608 static int *obscount, ct, cx, cy, cz, ip, ix, iy, iz, n, nobs, nk;
10609
10610 /* Set timer... */
10611 SELECT_TIMER("WRITE_CSI", "OUTPUT", NVTX_WRITE);
10612
10613 /* Init... */
10614 if (t == ctl->t_start) {
10615
10616 /* Check quantity index for mass... */
10617 if (ctl->qnt_m < 0)
10618 ERRMSG("Need quantity mass!");
10619
10620 /* Allocate... */
10621 ALLOC(area, double,
10622 ctl->csi_ny);
10623 ALLOC(rt, double,
10624 NOBS);
10625 ALLOC(rz, double,
10626 NOBS);
10627 ALLOC(rlon, double,
10628 NOBS);
10629 ALLOC(rlat, double,
10630 NOBS);
10631 ALLOC(robs, double,
10632 NOBS);
10633
10634 /* Read observation data... */
10635 read_obs(ctl->csi_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
10636
10637 /* Read kernel data... */
10638 if (ctl->csi_kernel[0] != '-')
10639 read_kernel(ctl->csi_kernel, kz, kw, &nk);
10640
10641 /* Create new file... */
10642 LOG(1, "Write CSI data: %s", filename);
10643 if (!(out = fopen(filename, "w")))
10644 ERRMSG("Cannot create file!");
10645
10646 /* Write header... */
10647 fprintf(out,
10648 "# $1 = time [s]\n"
10649 "# $2 = number of hits (cx)\n"
10650 "# $3 = number of misses (cy)\n"
10651 "# $4 = number of false alarms (cz)\n"
10652 "# $5 = number of observations (cx + cy)\n"
10653 "# $6 = number of forecasts (cx + cz)\n"
10654 "# $7 = bias (ratio of forecasts and observations) [%%]\n"
10655 "# $8 = probability of detection (POD) [%%]\n"
10656 "# $9 = false alarm rate (FAR) [%%]\n"
10657 "# $10 = critical success index (CSI) [%%]\n");
10658 fprintf(out,
10659 "# $11 = hits associated with random chance\n"
10660 "# $12 = equitable threat score (ETS) [%%]\n"
10661 "# $13 = Pearson linear correlation coefficient\n"
10662 "# $14 = Spearman rank-order correlation coefficient\n"
10663 "# $15 = column density mean error (F - O) [kg/m^2]\n"
10664 "# $16 = column density root mean square error (RMSE) [kg/m^2]\n"
10665 "# $17 = column density mean absolute error [kg/m^2]\n"
10666 "# $18 = log-likelihood function\n"
10667 "# $19 = number of data points\n\n");
10668
10669 /* Set grid box size... */
10670 dz = (ctl->csi_z1 - ctl->csi_z0) / ctl->csi_nz;
10671 dlon = (ctl->csi_lon1 - ctl->csi_lon0) / ctl->csi_nx;
10672 dlat = (ctl->csi_lat1 - ctl->csi_lat0) / ctl->csi_ny;
10673
10674 /* Set horizontal coordinates... */
10675 for (iy = 0; iy < ctl->csi_ny; iy++) {
10676 const double lat = ctl->csi_lat0 + dlat * (iy + 0.5);
10677 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat));
10678 }
10679 }
10680
10681 /* Set time interval... */
10682 const double t0 = t - 0.5 * ctl->dt_mod;
10683 const double t1 = t + 0.5 * ctl->dt_mod;
10684
10685 /* Allocate... */
10686 ALLOC(modmean, double,
10687 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
10688 ALLOC(obsmean, double,
10689 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
10690 ALLOC(obscount, int,
10691 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
10692 ALLOC(obsstd, double,
10693 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
10694
10695 /* Loop over observations... */
10696 for (int i = 0; i < nobs; i++) {
10697
10698 /* Check time... */
10699 if (rt[i] < t0)
10700 continue;
10701 else if (rt[i] >= t1)
10702 break;
10703
10704 /* Check observation data... */
10705 if (!isfinite(robs[i]))
10706 continue;
10707
10708 /* Calculate indices... */
10709 ix = (int) ((rlon[i] - ctl->csi_lon0) / dlon);
10710 iy = (int) ((rlat[i] - ctl->csi_lat0) / dlat);
10711 iz = (int) ((rz[i] - ctl->csi_z0) / dz);
10712
10713 /* Check indices... */
10714 if (ix < 0 || ix >= ctl->csi_nx ||
10715 iy < 0 || iy >= ctl->csi_ny || iz < 0 || iz >= ctl->csi_nz)
10716 continue;
10717
10718 /* Get mean observation index... */
10719 int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
10720 obsmean[idx] += robs[i];
10721 obsstd[idx] += SQR(robs[i]);
10722 obscount[idx]++;
10723 }
10724
10725 /* Analyze model data... */
10726 for (ip = 0; ip < atm->np; ip++) {
10727
10728 /* Check time... */
10729 if (atm->time[ip] < t0 || atm->time[ip] > t1)
10730 continue;
10731
10732 /* Get indices... */
10733 ix = (int) ((atm->lon[ip] - ctl->csi_lon0) / dlon);
10734 iy = (int) ((atm->lat[ip] - ctl->csi_lat0) / dlat);
10735 iz = (int) ((Z(atm->p[ip]) - ctl->csi_z0) / dz);
10736
10737 /* Check indices... */
10738 if (ix < 0 || ix >= ctl->csi_nx ||
10739 iy < 0 || iy >= ctl->csi_ny || iz < 0 || iz >= ctl->csi_nz)
10740 continue;
10741
10742 /* Get total mass in grid cell... */
10743 int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
10744 modmean[idx] += kernel_weight(kz, kw, nk, atm->p[ip])
10745 * atm->q[ctl->qnt_m][ip];
10746 }
10747
10748 /* Analyze all grid cells... */
10749 for (ix = 0; ix < ctl->csi_nx; ix++)
10750 for (iy = 0; iy < ctl->csi_ny; iy++)
10751 for (iz = 0; iz < ctl->csi_nz; iz++) {
10752
10753 /* Calculate mean observation index... */
10754 int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
10755 if (obscount[idx] > 0) {
10756 obsmean[idx] /= obscount[idx];
10757 obsstd[idx] -= SQR(obsmean[idx]);
10758 obsstd[idx] = sqrt(obsstd[idx]);
10759 }
10760
10761 /* Calculate column density... */
10762 if (modmean[idx] > 0)
10763 modmean[idx] /= (1e6 * area[iy]);
10764
10765 /* Calculate CSI... */
10766 if (obscount[idx] > 0) {
10767 ct++;
10768 if (obsmean[idx] >= ctl->csi_obsmin &&
10769 modmean[idx] >= ctl->csi_modmin)
10770 cx++;
10771 else if (obsmean[idx] >= ctl->csi_obsmin &&
10772 modmean[idx] < ctl->csi_modmin)
10773 cy++;
10774 else if (obsmean[idx] < ctl->csi_obsmin &&
10775 modmean[idx] >= ctl->csi_modmin)
10776 cz++;
10777 }
10778
10779 /* Save data for other verification statistics... */
10780 if (obscount[idx] > 0
10781 && (obsmean[idx] >= ctl->csi_obsmin
10782 || modmean[idx] >= ctl->csi_modmin)) {
10783 x[n] = modmean[idx];
10784 y[n] = obsmean[idx];
10785 if (modmean[idx] >= ctl->csi_modmin)
10786 obsstdn[n] = obsstd[idx];
10787 if ((++n) >= NCSI)
10788 ERRMSG("Too many data points to calculate statistics!");
10789 }
10790 }
10791
10792 /* Write output... */
10793 if (fmod(t, ctl->csi_dt_out) == 0) {
10794
10795 /* Calculate verification statistics
10796 (https://www.cawcr.gov.au/projects/verification/) ... */
10797 static double work[2 * NCSI], work2[2 * NCSI];;
10798 const int n_obs = cx + cy;
10799 const int n_for = cx + cz;
10800 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
10801 const double pod = (n_obs > 0) ? (100. * cx) / n_obs : NAN;
10802 const double far = (n_for > 0) ? (100. * cz) / n_for : NAN;
10803 const double csi =
10804 (cx + cy + cz > 0) ? (100. * cx) / (cx + cy + cz) : NAN;
10805 const double cx_rd = (ct > 0) ? (1. * n_obs * n_for) / ct : NAN;
10806 const double ets = (cx + cy + cz - cx_rd > 0) ?
10807 (100. * (cx - cx_rd)) / (cx + cy + cz - cx_rd) : NAN;
10808 const double rho_p =
10809 (n > 0) ? gsl_stats_correlation(x, 1, y, 1, (size_t) n) : NAN;
10810 const double rho_s =
10811 (n > 0) ? gsl_stats_spearman(x, 1, y, 1, (size_t) n, work) : NAN;
10812 for (int i = 0; i < n; i++) {
10813 work[i] = x[i] - y[i];
10814 work2[i] = (obsstdn[i] != 0) ? (x[i] - y[i]) / obsstdn[i] : 0;
10815 }
10816 const double mean = (n > 0) ? gsl_stats_mean(work, 1, (size_t) n) : NAN;
10817 const double rmse =
10818 (n > 0) ? gsl_stats_sd_with_fixed_mean(work, 1, (size_t) n,
10819 0.0) : NAN;
10820 const double absdev =
10821 (n > 0) ? gsl_stats_absdev_m(work, 1, (size_t) n, 0.0) : NAN;
10822 const double loglikelihood =
10823 (n > 0) ? gsl_stats_tss(work2, 1, (size_t) n) * (-0.5) : GSL_NAN;
10824
10825 /* Write... */
10826 fprintf(out,
10827 "%.2f %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
10828 t, cx, cy, cz, n_obs, n_for, bias, pod, far, csi, cx_rd, ets,
10829 rho_p, rho_s, mean, rmse, absdev, loglikelihood, n);
10830
10831 /* Set counters to zero... */
10832 n = ct = cx = cy = cz = 0;
10833 }
10834
10835 /* Free... */
10836 free(modmean);
10837 free(obsmean);
10838 free(obscount);
10839 free(obsstd);
10840
10841 /* Finalize... */
10842 if (t == ctl->t_stop) {
10843
10844 /* Close output file... */
10845 fclose(out);
10846
10847 /* Free... */
10848 free(area);
10849 free(rt);
10850 free(rz);
10851 free(rlon);
10852 free(rlat);
10853 free(robs);
10854 }
10855}
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:9733
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:6726
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:1773
#define NCSI
Maximum number of data points for CSI calculation.
Definition: mptrac.h:271
Here is the call graph for this function:

◆ write_csi_ens()

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

Writes ensemble-based Critical Success Index (CSI) and other verification statistics to an output file.

This function computes and writes various statistical verification metrics that assess the performance of ensemble forecasts compared to observations. The output includes, for each ensemble member:

  • Critical Success Index (CSI)
  • Equitable Threat Score (ETS)
  • Bias (forecast/observation ratio)
  • Probability of Detection (POD)
  • False Alarm Rate (FAR)
  • Correlation coefficients (Pearson, Spearman)
  • Error metrics (mean error, RMSE, mean absolute error)
  • Log-likelihood of the normalized errors

On the first invocation (when t == ctl->t_start), the function loads observation data and kernel weights, allocates necessary arrays, and creates a new output file with a descriptive header. On the final call (when t == ctl->t_stop), the function closes the file and frees all persistent memory.

Output is written at time steps divisible by ctl->csi_dt_out.

Parameters
[in]filenamePath to the output file where statistics will be written.
[in]ctlPointer to control structure containing configuration, ensemble settings, and spatial/time grid info.
[in]atmPointer to atmospheric data structure holding model output.
[in]tCurrent simulation/model time.
Note
This function maintains internal static buffers and handles memory management across time steps. It validates input configuration and will terminate with an error message if required quantities are missing or if limits (e.g., number of ensembles or data points) are exceeded.
Exceptions
Ifrequired quantities (mass or ensemble IDs) are undefined, if ensemble IDs are out of bounds, or if the output file cannot be created.
Author
Mingzhao Liu

Definition at line 10859 of file mptrac.c.

10863 {
10864
10865 static FILE *out;
10866
10867 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
10868 *area, dlon, dlat, dz, x[NCSI], y[NCSI], obsstdn[NCSI], kz[EP], kw[EP];
10869
10870 static int *obscount, ct[NENS], cx[NENS], cy[NENS], cz[NENS], ip, ix, iy,
10871 iz, n[NENS], nobs, nk;
10872
10873 /* Set timer... */
10874 SELECT_TIMER("WRITE_CSI_ENS", "OUTPUT", NVTX_WRITE);
10875
10876 /* Check quantity index for mass... */
10877 if (ctl->qnt_m < 0)
10878 ERRMSG("Need quantity mass!");
10879
10880 /* Check ensemble IDs... */
10881 if (ctl->qnt_ens < 0)
10882 ERRMSG("Missing ensemble IDs!");
10883
10884 if (ctl->nens > NENS)
10885 ERRMSG("Too much ensembles!")
10886 /* Init... */
10887 if (t == ctl->t_start) {
10888 /* Allocate... */
10889 ALLOC(area, double,
10890 ctl->csi_ny);
10891 ALLOC(rt, double,
10892 NOBS);
10893 ALLOC(rz, double,
10894 NOBS);
10895 ALLOC(rlon, double,
10896 NOBS);
10897 ALLOC(rlat, double,
10898 NOBS);
10899 ALLOC(robs, double,
10900 NOBS);
10901
10902 /* Read observation data... */
10903 read_obs(ctl->csi_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
10904
10905 /* Read kernel data... */
10906 if (ctl->csi_kernel[0] != '-')
10907 read_kernel(ctl->csi_kernel, kz, kw, &nk);
10908
10909 /* Create new file... */
10910 LOG(1, "Write CSI ensemble data: %s", filename);
10911 if (!(out = fopen(filename, "w")))
10912 ERRMSG("Cannot create file!");
10913
10914 /* Write header... */
10915 fprintf(out,
10916 "# $1 = time [s]\n"
10917 "# $2 = ensemble ID\n"
10918 "# $3 = number of hits (cx)\n"
10919 "# $4 = number of misses (cy)\n"
10920 "# $5 = number of false alarms (cz)\n"
10921 "# $6 = number of observations (cx + cy)\n"
10922 "# $7 = number of forecasts (cx + cz)\n"
10923 "# $8 = bias (ratio of forecasts and observations) [%%]\n"
10924 "# $9 = probability of detection (POD) [%%]\n"
10925 "# $10 = false alarm rate (FAR) [%%]\n"
10926 "# $11 = critical success index (CSI) [%%]\n"
10927 "# $12 = hits associated with random chance\n"
10928 "# $13 = equitable threat score (ETS) [%%]\n"
10929 "# $14 = Pearson linear correlation coefficient\n"
10930 "# $15 = Spearman rank-order correlation coefficient\n"
10931 "# $16 = column density mean error (F - O) [kg/m^2]\n"
10932 "# $17 = column density root mean square error (RMSE) [kg/m^2]\n"
10933 "# $18 = column density mean absolute error [kg/m^2]\n"
10934 "# $19 = log-likelihood function\n"
10935 "# $20 = number of data points\n\n");
10936
10937 /* Set grid box size... */
10938 dz = (ctl->csi_z1 - ctl->csi_z0) / ctl->csi_nz;
10939 dlon = (ctl->csi_lon1 - ctl->csi_lon0) / ctl->csi_nx;
10940 dlat = (ctl->csi_lat1 - ctl->csi_lat0) / ctl->csi_ny;
10941
10942 /* Set horizontal coordinates... */
10943 for (iy = 0; iy < ctl->csi_ny; iy++) {
10944 const double lat = ctl->csi_lat0 + dlat * (iy + 0.5);
10945 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat));
10946 }
10947 }
10948
10949 /* Set time interval... */
10950 const double t0 = t - 0.5 * ctl->dt_mod;
10951 const double t1 = t + 0.5 * ctl->dt_mod;
10952
10953 /* Allocate per-ensemble arrays... */
10954 ALLOC(modmean, double,
10955 ctl->nens * ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
10956
10957 ALLOC(obsmean, double,
10958 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
10959 ALLOC(obscount, int,
10960 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
10961 ALLOC(obsstd, double,
10962 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
10963
10964 /* Initialize ensemble counters... */
10965 for (int i = 0; i < ctl->nens; i++) {
10966 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
10967 }
10968
10969 /* Loop over observations... */
10970 int grid_size = ctl->csi_nx * ctl->csi_ny * ctl->csi_nz;
10971 for (int i = 0; i < nobs; i++) {
10972 /* Check time... */
10973 if (rt[i] < t0)
10974 continue;
10975 else if (rt[i] >= t1)
10976 break;
10977
10978 /* Check observation data... */
10979 if (!isfinite(robs[i]))
10980 continue;
10981
10982 /* Calculate indices... */
10983 ix = (int) ((rlon[i] - ctl->csi_lon0) / dlon);
10984 iy = (int) ((rlat[i] - ctl->csi_lat0) / dlat);
10985 iz = (int) ((rz[i] - ctl->csi_z0) / dz);
10986
10987 /* Check indices... */
10988 if (ix < 0 || ix >= ctl->csi_nx ||
10989 iy < 0 || iy >= ctl->csi_ny || iz < 0 || iz >= ctl->csi_nz)
10990 continue;
10991
10992 /* Get mean observation index... */
10993 int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
10994 obsmean[idx] += robs[i];
10995 obsstd[idx] += SQR(robs[i]);
10996 obscount[idx]++;
10997 }
10998
10999 /* Analyze model data per ensemble... */
11000 for (ip = 0; ip < atm->np; ip++) {
11001 /* Check time... */
11002 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11003 continue;
11004
11005 /* Check ensemble ID... */
11006 int ens = (int) atm->q[ctl->qnt_ens][ip];
11007 if (ens < 0 || ens > ctl->nens)
11008 ERRMSG("Ensemble ID is out of range!");
11009
11010 /* Get indices... */
11011 ix = (int) ((atm->lon[ip] - ctl->csi_lon0) / dlon);
11012 iy = (int) ((atm->lat[ip] - ctl->csi_lat0) / dlat);
11013 iz = (int) ((Z(atm->p[ip]) - ctl->csi_z0) / dz);
11014
11015 /* Check indices... */
11016 if (ix < 0 || ix >= ctl->csi_nx ||
11017 iy < 0 || iy >= ctl->csi_ny || iz < 0 || iz >= ctl->csi_nz)
11018 continue;
11019
11020 /* Get total mass in grid cell per ensemble... */
11021 int idx =
11022 ens * grid_size + ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
11023 modmean[idx] += kernel_weight(kz, kw, nk, atm->p[ip])
11024 * atm->q[ctl->qnt_m][ip];
11025 }
11026
11027 /* Analyze all grid cells... */
11028 for (ix = 0; ix < ctl->csi_nx; ix++)
11029 for (iy = 0; iy < ctl->csi_ny; iy++)
11030 for (iz = 0; iz < ctl->csi_nz; iz++) {
11031 /* Calculate mean observation index... */
11032 int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
11033 if (obscount[idx] > 0) {
11034 obsmean[idx] /= obscount[idx];
11035 obsstd[idx] -= SQR(obsmean[idx]);
11036 obsstd[idx] = sqrt(obsstd[idx]);
11037 }
11038
11039 /* Calculate column density per ensemble... */
11040 for (int i = 0; i < ctl->nens; i++) {
11041 int mod_idx =
11042 i * grid_size + ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
11043 if (modmean[mod_idx] > 0)
11044 modmean[mod_idx] /= (1e6 * area[iy]);
11045 }
11046
11047 /* Calculate CSI per ensemble... */
11048 if (obscount[idx] > 0) {
11049 for (int i = 0; i < ctl->nens; i++) {
11050 ct[i]++;
11051 int mod_idx = i * grid_size + ARRAY_3D(ix, iy, ctl->csi_ny, iz,
11052 ctl->csi_nz);
11053 if (obsmean[idx] >= ctl->csi_obsmin
11054 && modmean[mod_idx] >= ctl->csi_modmin)
11055 cx[i]++;
11056 else if (obsmean[idx] >= ctl->csi_obsmin &&
11057 modmean[mod_idx] < ctl->csi_modmin)
11058 cy[i]++;
11059 else if (obsmean[idx] < ctl->csi_obsmin &&
11060 modmean[mod_idx] >= ctl->csi_modmin)
11061 cz[i]++;
11062 }
11063 }
11064
11065 /* Save data for other verification statistics... */
11066 for (int i = 0; i < ctl->nens; i++) {
11067 if (obscount[idx] > 0
11068 && (obsmean[idx] >= ctl->csi_obsmin
11069 || modmean[i * grid_size + idx] >= ctl->csi_modmin)) {
11070 int mod_idx = i * grid_size + ARRAY_3D(ix, iy, ctl->csi_ny, iz,
11071 ctl->csi_nz);
11072 x[n[i]] = modmean[mod_idx];
11073 y[n[i]] = obsmean[idx];
11074 if (modmean[mod_idx] >= ctl->csi_modmin)
11075 obsstdn[n[i]] = obsstd[idx];
11076 if ((++n[i]) >= NCSI)
11077 ERRMSG("Too many data points to calculate statistics!");
11078 }
11079 }
11080 }
11081
11082 /* Write output... */
11083 if (fmod(t, ctl->csi_dt_out) == 0) {
11084 for (int i = 0; i < ctl->nens; i++) {
11085 if (n[i] > 0) {
11086 /* Calculate verification statistics... */
11087 static double work[2 * NCSI], work2[2 * NCSI];
11088 const int n_obs = cx[i] + cy[i];
11089 const int n_for = cx[i] + cz[i];
11090 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
11091 const double pod = (n_obs > 0) ? (100. * cx[i]) / n_obs : NAN;
11092 const double far = (n_for > 0) ? (100. * cz[i]) / n_for : NAN;
11093 const double csi =
11094 (cx[i] + cy[i] + cz[i] >
11095 0) ? (100. * cx[i]) / (cx[i] + cy[i] + cz[i]) : NAN;
11096 const double cx_rd = (ct[i] > 0) ? (1. * n_obs * n_for) / ct[i] : NAN;
11097 const double ets =
11098 (cx[i] + cy[i] + cz[i] - cx_rd >
11099 0) ? (100. * (cx[i] - cx_rd)) / (cx[i] + cy[i] + cz[i] -
11100 cx_rd) : NAN;
11101 const double rho_p = (n[i] > 0) ? gsl_stats_correlation(x, 1, y, 1,
11102 (size_t) n[i])
11103 : NAN;
11104 const double rho_s =
11105 (n[i] > 0) ? gsl_stats_spearman(x, 1, y, 1, (size_t) n[i],
11106 work) : NAN;
11107 for (int j = 0; j < n[i]; j++) {
11108 work[j] = x[j] - y[j];
11109 work2[j] = (obsstdn[j] != 0) ? (x[j] - y[j]) / obsstdn[j] : 0;
11110 }
11111 const double mean =
11112 (n[i] > 0) ? gsl_stats_mean(work, 1, (size_t) n[i]) : NAN;
11113 const double rmse =
11114 (n[i] > 0) ? gsl_stats_sd_with_fixed_mean(work, 1, (size_t) n[i],
11115 0.0) : NAN;
11116 const double absdev =
11117 (n[i] > 0) ? gsl_stats_absdev_m(work, 1, (size_t) n[i],
11118 0.0) : NAN;
11119 const double loglikelihood = (n[i] > 0) ? gsl_stats_tss(work2, 1,
11120 (size_t) n[i])
11121 * (-0.5) : GSL_NAN;
11122
11123 /* Write... */
11124 fprintf(out,
11125 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
11126 t, i, cx[i], cy[i], cz[i], n_obs, n_for, bias, pod, far,
11127 csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
11128 loglikelihood, n[i]);
11129 }
11130 }
11131 }
11132
11133 /* Free... */
11134 free(modmean);
11135 free(obsmean);
11136 free(obscount);
11137 free(obsstd);
11138
11139 /* Finalize... */
11140 if (t == ctl->t_stop) {
11141 /* Close output file... */
11142 fclose(out);
11143
11144 /* Free... */
11145 free(area);
11146 free(rt);
11147 free(rz);
11148 free(rlon);
11149 free(rlat);
11150 free(robs);
11151 }
11152}
#define NENS
Maximum number of data points for ensemble analysis.
Definition: mptrac.h:291
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 11156 of file mptrac.c.

11160 {
11161
11162 static FILE *out;
11163
11164 static double dummy, lat, lon, qm[NQ][NENS], qs[NQ][NENS], xm[NENS][3],
11165 x[3], zm[NENS];
11166
11167 static int n[NENS];
11168
11169 /* Set timer... */
11170 SELECT_TIMER("WRITE_ENS", "OUTPUT", NVTX_WRITE);
11171
11172 /* Check quantities... */
11173 if (ctl->qnt_ens < 0)
11174 ERRMSG("Missing ensemble IDs!");
11175
11176 /* Set time interval... */
11177 const double t0 = t - 0.5 * ctl->dt_mod;
11178 const double t1 = t + 0.5 * ctl->dt_mod;
11179
11180 /* Init... */
11181 for (int i = 0; i < NENS; i++) {
11182 for (int iq = 0; iq < ctl->nq; iq++)
11183 qm[iq][i] = qs[iq][i] = 0;
11184 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
11185 n[i] = 0;
11186 }
11187
11188 /* Loop over air parcels... */
11189 for (int ip = 0; ip < atm->np; ip++) {
11190
11191 /* Check time... */
11192 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11193 continue;
11194
11195 /* Check ensemble ID... */
11196 if (atm->q[ctl->qnt_ens][ip] < 0 || atm->q[ctl->qnt_ens][ip] >= NENS)
11197 ERRMSG("Ensemble ID is out of range!");
11198
11199 /* Get means... */
11200 geo2cart(0, atm->lon[ip], atm->lat[ip], x);
11201 for (int iq = 0; iq < ctl->nq; iq++) {
11202 qm[iq][ctl->qnt_ens] += atm->q[iq][ip];
11203 qs[iq][ctl->qnt_ens] += SQR(atm->q[iq][ip]);
11204 }
11205 xm[ctl->qnt_ens][0] += x[0];
11206 xm[ctl->qnt_ens][1] += x[1];
11207 xm[ctl->qnt_ens][2] += x[2];
11208 zm[ctl->qnt_ens] += Z(atm->p[ip]);
11209 n[ctl->qnt_ens]++;
11210 }
11211
11212 /* Create file... */
11213 LOG(1, "Write ensemble data: %s", filename);
11214 if (!(out = fopen(filename, "w")))
11215 ERRMSG("Cannot create file!");
11216
11217 /* Write header... */
11218 fprintf(out,
11219 "# $1 = time [s]\n"
11220 "# $2 = altitude [km]\n"
11221 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11222 for (int iq = 0; iq < ctl->nq; iq++)
11223 fprintf(out, "# $%d = %s (mean) [%s]\n", 5 + iq,
11224 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
11225 for (int iq = 0; iq < ctl->nq; iq++)
11226 fprintf(out, "# $%d = %s (sigma) [%s]\n", 5 + ctl->nq + iq,
11227 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
11228 fprintf(out, "# $%d = number of members\n\n", 5 + 2 * ctl->nq);
11229
11230 /* Write data... */
11231 for (int i = 0; i < NENS; i++)
11232 if (n[i] > 0) {
11233 cart2geo(xm[i], &dummy, &lon, &lat);
11234 fprintf(out, "%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
11235 for (int iq = 0; iq < ctl->nq; iq++) {
11236 fprintf(out, " ");
11237 fprintf(out, ctl->qnt_format[iq], qm[iq][i] / n[i]);
11238 }
11239 for (int iq = 0; iq < ctl->nq; iq++) {
11240 fprintf(out, " ");
11241 double var = qs[iq][i] / n[i] - SQR(qm[iq][i] / n[i]);
11242 fprintf(out, ctl->qnt_format[iq], (var > 0 ? sqrt(var) : 0));
11243 }
11244 fprintf(out, " %d\n", n[i]);
11245 }
11246
11247 /* Close file... */
11248 fclose(out);
11249}
void cart2geo(const double *x, double *z, double *lon, double *lat)
State variables of cuRAND random number generator.
Definition: mptrac.c:74
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 11253 of file mptrac.c.

11259 {
11260
11261 static double kz[EP], kw[EP];
11262
11263 static int nk;
11264
11265 double *cd, *mean[NQ], *sigma[NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
11266
11267 int *ixs, *iys, *izs, *np;
11268
11269 /* Set timer... */
11270 SELECT_TIMER("WRITE_GRID", "OUTPUT", NVTX_WRITE);
11271
11272 /* Write info... */
11273 LOG(1, "Write grid data: %s", filename);
11274
11275 /* Init... */
11276 if (t == ctl->t_start) {
11277
11278 /* Read kernel data... */
11279 if (ctl->grid_kernel[0] != '-')
11280 read_kernel(ctl->grid_kernel, kz, kw, &nk);
11281 }
11282
11283 /* Allocate... */
11284 ALLOC(cd, double,
11285 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
11286 for (int iq = 0; iq < ctl->nq; iq++) {
11287 ALLOC(mean[iq], double,
11288 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
11289 ALLOC(sigma[iq], double,
11290 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
11291 }
11292 ALLOC(vmr_impl, double,
11293 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
11294 ALLOC(z, double,
11295 ctl->grid_nz);
11296 ALLOC(lon, double,
11297 ctl->grid_nx);
11298 ALLOC(lat, double,
11299 ctl->grid_ny);
11300 ALLOC(area, double,
11301 ctl->grid_ny);
11302 ALLOC(press, double,
11303 ctl->grid_nz);
11304 ALLOC(np, int,
11305 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
11306 ALLOC(ixs, int,
11307 atm->np);
11308 ALLOC(iys, int,
11309 atm->np);
11310 ALLOC(izs, int,
11311 atm->np);
11312
11313 /* Set grid box size... */
11314 const double dz = (ctl->grid_z1 - ctl->grid_z0) / ctl->grid_nz;
11315 const double dlon = (ctl->grid_lon1 - ctl->grid_lon0) / ctl->grid_nx;
11316 const double dlat = (ctl->grid_lat1 - ctl->grid_lat0) / ctl->grid_ny;
11317
11318 /* Set vertical coordinates... */
11319#pragma omp parallel for default(shared)
11320 for (int iz = 0; iz < ctl->grid_nz; iz++) {
11321 z[iz] = ctl->grid_z0 + dz * (iz + 0.5);
11322 press[iz] = P(z[iz]);
11323 }
11324
11325 /* Set horizontal coordinates... */
11326 for (int ix = 0; ix < ctl->grid_nx; ix++)
11327 lon[ix] = ctl->grid_lon0 + dlon * (ix + 0.5);
11328#pragma omp parallel for default(shared)
11329 for (int iy = 0; iy < ctl->grid_ny; iy++) {
11330 lat[iy] = ctl->grid_lat0 + dlat * (iy + 0.5);
11331 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
11332 }
11333
11334 /* Set time interval for output... */
11335 const double t0 = t - 0.5 * ctl->dt_mod;
11336 const double t1 = t + 0.5 * ctl->dt_mod;
11337
11338 /* Get grid box indices... */
11339#pragma omp parallel for default(shared)
11340 for (int ip = 0; ip < atm->np; ip++) {
11341 ixs[ip] = (int) ((atm->lon[ip] - ctl->grid_lon0) / dlon);
11342 iys[ip] = (int) ((atm->lat[ip] - ctl->grid_lat0) / dlat);
11343 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->grid_z0) / dz);
11344 if (atm->time[ip] < t0 || atm->time[ip] > t1
11345 || ixs[ip] < 0 || ixs[ip] >= ctl->grid_nx
11346 || iys[ip] < 0 || iys[ip] >= ctl->grid_ny
11347 || izs[ip] < 0 || izs[ip] >= ctl->grid_nz)
11348 izs[ip] = -1;
11349 }
11350
11351 /* Average data... */
11352 for (int ip = 0; ip < atm->np; ip++)
11353 if (izs[ip] >= 0) {
11354 int idx =
11355 ARRAY_3D(ixs[ip], iys[ip], ctl->grid_ny, izs[ip], ctl->grid_nz);
11356 double kernel = kernel_weight(kz, kw, nk, atm->p[ip]);
11357 np[idx]++;
11358 for (int iq = 0; iq < ctl->nq; iq++) {
11359 mean[iq][idx] += kernel * atm->q[iq][ip];
11360 sigma[iq][idx] += SQR(kernel * atm->q[iq][ip]);
11361 }
11362 }
11363
11364 /* Calculate column density and volume mixing ratio... */
11365#pragma omp parallel for default(shared)
11366 for (int ix = 0; ix < ctl->grid_nx; ix++)
11367 for (int iy = 0; iy < ctl->grid_ny; iy++)
11368 for (int iz = 0; iz < ctl->grid_nz; iz++) {
11369
11370 /* Get grid index... */
11371 int idx = ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz);
11372
11373 /* Calculate column density... */
11374 cd[idx] = NAN;
11375 if (ctl->qnt_m >= 0)
11376 cd[idx] = mean[ctl->qnt_m][idx] / (1e6 * area[iy]);
11377
11378 /* Calculate volume mixing ratio (implicit)... */
11379 vmr_impl[idx] = NAN;
11380 if (ctl->qnt_m >= 0 && ctl->molmass > 0 && met0 != NULL
11381 && met1 != NULL) {
11382 vmr_impl[idx] = 0;
11383 if (mean[ctl->qnt_m][idx] > 0) {
11384
11385 /* Get temperature... */
11386 double temp;
11388 intpol_met_time_3d(met0, met0->t, met1, met1->t, t, press[iz],
11389 lon[ix], lat[iy], &temp, ci, cw, 1);
11390
11391 /* Calculate volume mixing ratio... */
11392 vmr_impl[idx] =
11393 MA / ctl->molmass * cd[idx] / (RHO(press[iz], temp) * dz * 1e3);
11394 }
11395 }
11396
11397 /* Calculate mean... */
11398 if (np[idx] > 0)
11399 for (int iq = 0; iq < ctl->nq; iq++) {
11400 mean[iq][idx] /= np[idx];
11401 double var = sigma[iq][idx] / np[idx] - SQR(mean[iq][idx]);
11402 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
11403 } else
11404 for (int iq = 0; iq < ctl->nq; iq++) {
11405 mean[iq][idx] = NAN;
11406 sigma[iq][idx] = NAN;
11407 }
11408 }
11409
11410 /* Write ASCII data... */
11411 if (ctl->grid_type == 0)
11412 write_grid_asc(filename, ctl, cd, mean, sigma, vmr_impl,
11413 t, z, lon, lat, area, dz, np);
11414
11415 /* Write netCDF data... */
11416 else if (ctl->grid_type == 1)
11417 write_grid_nc(filename, ctl, cd, mean, sigma, vmr_impl,
11418 t, z, lon, lat, area, dz, np);
11419
11420 /* Error message... */
11421 else
11422 ERRMSG("Grid data format GRID_TYPE unknown!");
11423
11424 /* Free... */
11425 free(cd);
11426 for (int iq = 0; iq < ctl->nq; iq++) {
11427 free(mean[iq]);
11428 free(sigma[iq]);
11429 }
11430 free(vmr_impl);
11431 free(z);
11432 free(lon);
11433 free(lat);
11434 free(area);
11435 free(press);
11436 free(np);
11437 free(ixs);
11438 free(iys);
11439 free(izs);
11440}
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:11444
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:11548
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 11444 of file mptrac.c.

11457 {
11458
11459 FILE *out;
11460
11461 /* Check if gnuplot output is requested... */
11462 if (ctl->grid_gpfile[0] != '-') {
11463
11464 /* Create gnuplot pipe... */
11465 if (!(out = popen("gnuplot", "w")))
11466 ERRMSG("Cannot create pipe to gnuplot!");
11467
11468 /* Set plot filename... */
11469 fprintf(out, "set out \"%s.png\"\n", filename);
11470
11471 /* Set time string... */
11472 double r;
11473 int year, mon, day, hour, min, sec;
11474 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11475 fprintf(out, "timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
11476 year, mon, day, hour, min);
11477
11478 /* Dump gnuplot file to pipe... */
11479 FILE *in;
11480 char line[LEN];
11481 if (!(in = fopen(ctl->grid_gpfile, "r")))
11482 ERRMSG("Cannot open file!");
11483 while (fgets(line, LEN, in))
11484 fprintf(out, "%s", line);
11485 fclose(in);
11486 }
11487
11488 else {
11489
11490 /* Create file... */
11491 if (!(out = fopen(filename, "w")))
11492 ERRMSG("Cannot create file!");
11493 }
11494
11495 /* Write header... */
11496 fprintf(out,
11497 "# $1 = time [s]\n"
11498 "# $2 = altitude [km]\n"
11499 "# $3 = longitude [deg]\n"
11500 "# $4 = latitude [deg]\n"
11501 "# $5 = surface area [km^2]\n"
11502 "# $6 = layer depth [km]\n"
11503 "# $7 = column density (implicit) [kg/m^2]\n"
11504 "# $8 = volume mixing ratio (implicit) [ppv]\n"
11505 "# $9 = number of particles [1]\n");
11506 for (int iq = 0; iq < ctl->nq; iq++)
11507 fprintf(out, "# $%i = %s (mean) [%s]\n", 10 + iq, ctl->qnt_name[iq],
11508 ctl->qnt_unit[iq]);
11509 if (ctl->grid_stddev)
11510 for (int iq = 0; iq < ctl->nq; iq++)
11511 fprintf(out, "# $%i = %s (stddev) [%s]\n", 10 + ctl->nq + iq,
11512 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
11513 fprintf(out, "\n");
11514
11515 /* Write data... */
11516 for (int ix = 0; ix < ctl->grid_nx; ix++) {
11517 if (ix > 0 && ctl->grid_ny > 1 && !ctl->grid_sparse)
11518 fprintf(out, "\n");
11519 for (int iy = 0; iy < ctl->grid_ny; iy++) {
11520 if (iy > 0 && ctl->grid_nz > 1 && !ctl->grid_sparse)
11521 fprintf(out, "\n");
11522 for (int iz = 0; iz < ctl->grid_nz; iz++) {
11523 int idx = ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz);
11524 if (!ctl->grid_sparse || vmr_impl[idx] > 0) {
11525 fprintf(out, "%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
11526 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
11527 for (int iq = 0; iq < ctl->nq; iq++) {
11528 fprintf(out, " ");
11529 fprintf(out, ctl->qnt_format[iq], mean[iq][idx]);
11530 }
11531 if (ctl->grid_stddev)
11532 for (int iq = 0; iq < ctl->nq; iq++) {
11533 fprintf(out, " ");
11534 fprintf(out, ctl->qnt_format[iq], sigma[iq][idx]);
11535 }
11536 fprintf(out, "\n");
11537 }
11538 }
11539 }
11540 }
11541
11542 /* Close file... */
11543 fclose(out);
11544}
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 11548 of file mptrac.c.

11561 {
11562
11563 char longname[2 * LEN], varname[2 * LEN];
11564
11565 double *help;
11566
11567 int *help2, ncid, dimid[10], varid;
11568
11569 size_t start[2], count[2];
11570
11571 /* Allocate... */
11572 ALLOC(help, double,
11573 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
11574 ALLOC(help2, int,
11575 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
11576
11577 /* Create file... */
11578 NC(nc_create(filename, NC_NETCDF4, &ncid));
11579
11580 /* Define dimensions... */
11581 NC(nc_def_dim(ncid, "time", 1, &dimid[0]));
11582 NC(nc_def_dim(ncid, "z", (size_t) ctl->grid_nz, &dimid[1]));
11583 NC(nc_def_dim(ncid, "lat", (size_t) ctl->grid_ny, &dimid[2]));
11584 NC(nc_def_dim(ncid, "lon", (size_t) ctl->grid_nx, &dimid[3]));
11585 NC(nc_def_dim(ncid, "dz", 1, &dimid[4]));
11586
11587 /* Define variables and their attributes... */
11588 NC_DEF_VAR("time", NC_DOUBLE, 1, &dimid[0], "time",
11589 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
11590 NC_DEF_VAR("z", NC_DOUBLE, 1, &dimid[1], "altitude", "km", 0, 0);
11591 NC_DEF_VAR("lat", NC_DOUBLE, 1, &dimid[2], "latitude", "degrees_north", 0,
11592 0);
11593 NC_DEF_VAR("lon", NC_DOUBLE, 1, &dimid[3], "longitude", "degrees_east", 0,
11594 0);
11595 NC_DEF_VAR("dz", NC_DOUBLE, 1, &dimid[1], "layer depth", "km", 0, 0);
11596 NC_DEF_VAR("area", NC_DOUBLE, 1, &dimid[2], "surface area", "km**2", 0, 0);
11597
11598 NC_DEF_VAR("cd", NC_FLOAT, 4, dimid, "column density", "kg m**-2",
11599 ctl->grid_nc_level, 0);
11600 NC_DEF_VAR("vmr_impl", NC_FLOAT, 4, dimid,
11601 "volume mixing ratio (implicit)", "ppv", ctl->grid_nc_level, 0);
11602 NC_DEF_VAR("np", NC_INT, 4, dimid, "number of particles", "1", 0, 0);
11603 for (int iq = 0; iq < ctl->nq; iq++) {
11604 sprintf(varname, "%s_mean", ctl->qnt_name[iq]);
11605 sprintf(longname, "%s (mean)", ctl->qnt_longname[iq]);
11606 NC_DEF_VAR(varname, NC_DOUBLE, 4, dimid, longname, ctl->qnt_unit[iq],
11607 ctl->grid_nc_level, ctl->grid_nc_quant[iq]);
11608 if (ctl->grid_stddev) {
11609 sprintf(varname, "%s_stddev", ctl->qnt_name[iq]);
11610 sprintf(longname, "%s (stddev)", ctl->qnt_longname[iq]);
11611 NC_DEF_VAR(varname, NC_DOUBLE, 4, dimid, longname, ctl->qnt_unit[iq],
11612 ctl->grid_nc_level, ctl->grid_nc_quant[iq]);
11613 }
11614 }
11615 /* End definitions... */
11616 NC(nc_enddef(ncid));
11617
11618 /* Write data... */
11619 NC_PUT_DOUBLE("time", &t, 0);
11620 NC_PUT_DOUBLE("lon", lon, 0);
11621 NC_PUT_DOUBLE("lat", lat, 0);
11622 NC_PUT_DOUBLE("z", z, 0);
11623 NC_PUT_DOUBLE("area", area, 0);
11624 NC_PUT_DOUBLE("dz", &dz, 0);
11625
11626 for (int ix = 0; ix < ctl->grid_nx; ix++)
11627 for (int iy = 0; iy < ctl->grid_ny; iy++)
11628 for (int iz = 0; iz < ctl->grid_nz; iz++)
11629 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
11630 cd[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
11631 NC_PUT_DOUBLE("cd", help, 0);
11632
11633 for (int ix = 0; ix < ctl->grid_nx; ix++)
11634 for (int iy = 0; iy < ctl->grid_ny; iy++)
11635 for (int iz = 0; iz < ctl->grid_nz; iz++)
11636 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
11637 vmr_impl[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
11638 NC_PUT_DOUBLE("vmr_impl", help, 0);
11639
11640 for (int ix = 0; ix < ctl->grid_nx; ix++)
11641 for (int iy = 0; iy < ctl->grid_ny; iy++)
11642 for (int iz = 0; iz < ctl->grid_nz; iz++)
11643 help2[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
11644 np[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
11645 NC_PUT_INT("np", help2, 0);
11646
11647 for (int iq = 0; iq < ctl->nq; iq++) {
11648 sprintf(varname, "%s_mean", ctl->qnt_name[iq]);
11649 for (int ix = 0; ix < ctl->grid_nx; ix++)
11650 for (int iy = 0; iy < ctl->grid_ny; iy++)
11651 for (int iz = 0; iz < ctl->grid_nz; iz++)
11652 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
11653 mean[iq][ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
11654 NC_PUT_DOUBLE(varname, help, 0);
11655 }
11656
11657 if (ctl->grid_stddev)
11658 for (int iq = 0; iq < ctl->nq; iq++) {
11659 sprintf(varname, "%s_stddev", ctl->qnt_name[iq]);
11660 for (int ix = 0; ix < ctl->grid_nx; ix++)
11661 for (int iy = 0; iy < ctl->grid_ny; iy++)
11662 for (int iz = 0; iz < ctl->grid_nz; iz++)
11663 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
11664 sigma[iq][ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
11665 NC_PUT_DOUBLE(varname, help, 0);
11666 }
11667
11668 /* Close file... */
11669 NC(nc_close(ncid));
11670
11671 /* Free... */
11672 free(help);
11673 free(help2);
11674}
#define NC_PUT_INT(varname, ptr, hyperslab)
Write integer data to a NetCDF variable.
Definition: mptrac.h:1253

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

11681 {
11682
11683 /* Create file... */
11684 FILE *out;
11685 if (!(out = fopen(filename, "w")))
11686 ERRMSG("Cannot create file!");
11687
11688 /* Write type of binary data... */
11689 FWRITE(&ctl->met_type, int,
11690 1,
11691 out);
11692
11693 /* Write version of binary data... */
11694 int version = 103;
11695 FWRITE(&version, int,
11696 1,
11697 out);
11698
11699 /* Write grid data... */
11700 FWRITE(&met->time, double,
11701 1,
11702 out);
11703 FWRITE(&met->nx, int,
11704 1,
11705 out);
11706 FWRITE(&met->ny, int,
11707 1,
11708 out);
11709 FWRITE(&met->np, int,
11710 1,
11711 out);
11712 FWRITE(met->lon, double,
11713 (size_t) met->nx,
11714 out);
11715 FWRITE(met->lat, double,
11716 (size_t) met->ny,
11717 out);
11718 FWRITE(met->p, double,
11719 (size_t) met->np,
11720 out);
11721
11722 /* Write surface data... */
11723 write_met_bin_2d(out, met, met->ps, "PS");
11724 write_met_bin_2d(out, met, met->ts, "TS");
11725 write_met_bin_2d(out, met, met->zs, "ZS");
11726 write_met_bin_2d(out, met, met->us, "US");
11727 write_met_bin_2d(out, met, met->vs, "VS");
11728 write_met_bin_2d(out, met, met->ess, "ESS");
11729 write_met_bin_2d(out, met, met->nss, "NSS");
11730 write_met_bin_2d(out, met, met->shf, "SHF");
11731 write_met_bin_2d(out, met, met->lsm, "LSM");
11732 write_met_bin_2d(out, met, met->sst, "SST");
11733 write_met_bin_2d(out, met, met->pbl, "PBL");
11734 write_met_bin_2d(out, met, met->pt, "PT");
11735 write_met_bin_2d(out, met, met->tt, "TT");
11736 write_met_bin_2d(out, met, met->zt, "ZT");
11737 write_met_bin_2d(out, met, met->h2ot, "H2OT");
11738 write_met_bin_2d(out, met, met->pct, "PCT");
11739 write_met_bin_2d(out, met, met->pcb, "PCB");
11740 write_met_bin_2d(out, met, met->cl, "CL");
11741 write_met_bin_2d(out, met, met->plcl, "PLCL");
11742 write_met_bin_2d(out, met, met->plfc, "PLFC");
11743 write_met_bin_2d(out, met, met->pel, "PEL");
11744 write_met_bin_2d(out, met, met->cape, "CAPE");
11745 write_met_bin_2d(out, met, met->cin, "CIN");
11746 write_met_bin_2d(out, met, met->o3c, "O3C");
11747
11748 /* Write level data... */
11749 write_met_bin_3d(out, ctl, met, met->z, "Z",
11750 (ctl->met_zfp_tol_z <= 0 ? ctl->met_zfp_prec : 0),
11751 ctl->met_zfp_tol_z);
11752 write_met_bin_3d(out, ctl, met, met->t, "T",
11753 (ctl->met_zfp_tol_t <= 0 ? ctl->met_zfp_prec : 0),
11754 ctl->met_zfp_tol_t);
11755 write_met_bin_3d(out, ctl, met, met->u, "U", ctl->met_zfp_prec, 0);
11756 write_met_bin_3d(out, ctl, met, met->v, "V", ctl->met_zfp_prec, 0);
11757 write_met_bin_3d(out, ctl, met, met->w, "W", ctl->met_zfp_prec, 0);
11758 write_met_bin_3d(out, ctl, met, met->pv, "PV", ctl->met_zfp_prec, 0);
11759 write_met_bin_3d(out, ctl, met, met->h2o, "H2O", ctl->met_zfp_prec, 0);
11760 write_met_bin_3d(out, ctl, met, met->o3, "O3", ctl->met_zfp_prec, 0);
11761 write_met_bin_3d(out, ctl, met, met->lwc, "LWC", ctl->met_zfp_prec, 0);
11762 write_met_bin_3d(out, ctl, met, met->rwc, "RWC", ctl->met_zfp_prec, 0);
11763 write_met_bin_3d(out, ctl, met, met->iwc, "IWC", ctl->met_zfp_prec, 0);
11764 write_met_bin_3d(out, ctl, met, met->swc, "SWC", ctl->met_zfp_prec, 0);
11765 write_met_bin_3d(out, ctl, met, met->cc, "CC", ctl->met_zfp_prec, 0);
11766
11767 /* Write final flag... */
11768 int final = 999;
11769 FWRITE(&final, int,
11770 1,
11771 out);
11772
11773 /* Close file... */
11774 fclose(out);
11775}
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:11808
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:11779
int met_zfp_prec
ZFP compression precision for all variables, except z and T.
Definition: mptrac.h:2581
double met_zfp_tol_t
ZFP compression tolerance for temperature.
Definition: mptrac.h:2584
double met_zfp_tol_z
ZFP compression tolerance for geopotential height.
Definition: mptrac.h:2587
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 11779 of file mptrac.c.

11783 {
11784
11785 float *help;
11786
11787 /* Allocate... */
11788 ALLOC(help, float,
11789 EX * EY);
11790
11791 /* Copy data... */
11792 for (int ix = 0; ix < met->nx; ix++)
11793 for (int iy = 0; iy < met->ny; iy++)
11794 help[ARRAY_2D(ix, iy, met->ny)] = var[ix][iy];
11795
11796 /* Write uncompressed data... */
11797 LOG(2, "Write 2-D variable: %s (uncompressed)", varname);
11798 FWRITE(help, float,
11799 (size_t) (met->nx * met->ny),
11800 out);
11801
11802 /* Free... */
11803 free(help);
11804}

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

11815 {
11816
11817 float *help;
11818
11819 /* Allocate... */
11820 ALLOC(help, float,
11821 EX * EY * EP);
11822
11823 /* Copy data... */
11824#pragma omp parallel for default(shared) collapse(2)
11825 for (int ix = 0; ix < met->nx; ix++)
11826 for (int iy = 0; iy < met->ny; iy++)
11827 for (int ip = 0; ip < met->np; ip++)
11828 help[ARRAY_3D(ix, iy, met->ny, ip, met->np)] = var[ix][iy][ip];
11829
11830 /* Write uncompressed data... */
11831 if (ctl->met_type == 1) {
11832 LOG(2, "Write 3-D variable: %s (uncompressed)", varname);
11833 FWRITE(help, float,
11834 (size_t) (met->nx * met->ny * met->np),
11835 out);
11836 }
11837
11838 /* Write packed data... */
11839 else if (ctl->met_type == 2)
11840 compress_pck(varname, help, (size_t) (met->ny * met->nx),
11841 (size_t) met->np, 0, out);
11842
11843 /* Write zfp data... */
11844#ifdef ZFP
11845 else if (ctl->met_type == 3) {
11846 FWRITE(&precision, int,
11847 1,
11848 out);
11849 FWRITE(&tolerance, double,
11850 1,
11851 out);
11852 compress_zfp(varname, help, met->np, met->ny, met->nx, precision,
11853 tolerance, 0, out);
11854 }
11855#endif
11856
11857 /* Write zstd data... */
11858#ifdef ZSTD
11859 else if (ctl->met_type == 4)
11860 compress_zstd(varname, help, (size_t) (met->np * met->ny * met->nx), 0,
11861 ctl->met_zstd_level, out);
11862#endif
11863
11864 /* Write cmultiscale data... */
11865#ifdef CMS
11866 else if (ctl->met_type == 5) {
11867 compress_cms(ctl, varname, help, (size_t) met->nx, (size_t) met->ny,
11868 (size_t) met->np, 0, out);
11869 }
11870#endif
11871
11872 /* Unknown method... */
11873 else {
11874 ERRMSG("MET_TYPE not supported!");
11875 LOG(3, "%d %g", precision, tolerance);
11876 }
11877
11878 /* Free... */
11879 free(help);
11880}
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 11884 of file mptrac.c.

11887 {
11888
11889 /* Create file... */
11890 int ncid, varid;
11891 size_t start[4], count[4];
11892 nc_create(filename, NC_NETCDF4, &ncid);
11893
11894 /* Define dimensions... */
11895 int tid, lonid, latid, levid;
11896 NC(nc_def_dim(ncid, "time", 1, &tid));
11897 NC(nc_def_dim(ncid, "lon", (size_t) met->nx, &lonid));
11898 NC(nc_def_dim(ncid, "lat", (size_t) met->ny, &latid));
11899 NC(nc_def_dim(ncid, "lev", (size_t) met->np, &levid));
11900
11901 /* Define grid... */
11902 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "time",
11903 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
11904 NC_DEF_VAR("lon", NC_DOUBLE, 1, &lonid, "longitude", "degrees_east", 0, 0);
11905 NC_DEF_VAR("lat", NC_DOUBLE, 1, &latid, "latitude", "degrees_north", 0, 0);
11906 NC_DEF_VAR("lev", NC_DOUBLE, 1, &levid, "pressure", "Pa", 0, 0);
11907
11908 /* Define surface variables... */
11909 int dimid2[2] = { latid, lonid };
11910 NC_DEF_VAR("sp", NC_FLOAT, 2, dimid2, "Surface pressure", "Pa",
11911 ctl->met_nc_level, 0);
11912 NC_DEF_VAR("z", NC_FLOAT, 2, dimid2, "Geopotential", "m**2 s**-2",
11913 ctl->met_nc_level, 0);
11914 NC_DEF_VAR("t2m", NC_FLOAT, 2, dimid2, "2 metre temperature", "K",
11915 ctl->met_nc_level, 0);
11916 NC_DEF_VAR("u10m", NC_FLOAT, 2, dimid2, "10 metre U wind component",
11917 "m s**-1", ctl->met_nc_level, 0);
11918 NC_DEF_VAR("v10m", NC_FLOAT, 2, dimid2, "10 metre V wind component",
11919 "m s**-1", ctl->met_nc_level, 0);
11920 NC_DEF_VAR("iews", NC_FLOAT, 2, dimid2,
11921 "Instantaneous eastward turbulent surface stress", "N m**-2",
11922 ctl->met_nc_level, 0);
11923 NC_DEF_VAR("inss", NC_FLOAT, 2, dimid2,
11924 "Instantaneous northward turbulent surface stress", "N m**-2",
11925 ctl->met_nc_level, 0);
11926 NC_DEF_VAR("ishf", NC_FLOAT, 2, dimid2,
11927 "Instantaneous surface sensible heat flux", "W m**-1",
11928 ctl->met_nc_level, 0);
11929 NC_DEF_VAR("lsm", NC_FLOAT, 2, dimid2, "Land/sea mask", "-",
11930 ctl->met_nc_level, 0);
11931 NC_DEF_VAR("sstk", NC_FLOAT, 2, dimid2, "Sea surface temperature", "K",
11932 ctl->met_nc_level, 0);
11933 NC_DEF_VAR("blp", NC_FLOAT, 2, dimid2, "Boundary layer pressure", "Pa",
11934 ctl->met_nc_level, 0);
11935 NC_DEF_VAR("pt", NC_FLOAT, 2, dimid2, "Tropopause pressure", "Pa",
11936 ctl->met_nc_level, 0);
11937 NC_DEF_VAR("tt", NC_FLOAT, 2, dimid2, "Tropopause temperature", "K",
11938 ctl->met_nc_level, 0);
11939 NC_DEF_VAR("zt", NC_FLOAT, 2, dimid2, "Tropopause height", "m",
11940 ctl->met_nc_level, 0);
11941 NC_DEF_VAR("h2ot", NC_FLOAT, 2, dimid2, "Tropopause water vapor", "ppv",
11942 ctl->met_nc_level, 0);
11943 NC_DEF_VAR("pct", NC_FLOAT, 2, dimid2, "Cloud top pressure", "Pa",
11944 ctl->met_nc_level, 0);
11945 NC_DEF_VAR("pcb", NC_FLOAT, 2, dimid2, "Cloud bottom pressure", "Pa",
11946 ctl->met_nc_level, 0);
11947 NC_DEF_VAR("cl", NC_FLOAT, 2, dimid2, "Total column cloud water",
11948 "kg m**2", ctl->met_nc_level, 0);
11949 NC_DEF_VAR("plcl", NC_FLOAT, 2, dimid2,
11950 "Pressure at lifted condensation level (LCL)", "Pa",
11951 ctl->met_nc_level, 0);
11952 NC_DEF_VAR("plfc", NC_FLOAT, 2, dimid2,
11953 "Pressure at level of free convection (LFC)", "Pa",
11954 ctl->met_nc_level, 0);
11955 NC_DEF_VAR("pel", NC_FLOAT, 2, dimid2,
11956 "Pressure at equilibrium level (EL)", "Pa", ctl->met_nc_level,
11957 0);
11958 NC_DEF_VAR("cape", NC_FLOAT, 2, dimid2,
11959 "Convective available potential energy", "J kg**-1",
11960 ctl->met_nc_level, 0);
11961 NC_DEF_VAR("cin", NC_FLOAT, 2, dimid2, "Convective inhibition",
11962 "J kg**-1", ctl->met_nc_level, 0);
11963 NC_DEF_VAR("o3c", NC_FLOAT, 2, dimid2, "Total column ozone", "DU",
11964 ctl->met_nc_level, 0);
11965
11966 /* Define level data... */
11967 int dimid3[3] = { levid, latid, lonid };
11968 NC_DEF_VAR("t", NC_FLOAT, 3, dimid3, "Temperature", "K",
11969 ctl->met_nc_level, ctl->met_nc_quant);
11970 NC_DEF_VAR("u", NC_FLOAT, 3, dimid3, "U velocity", "m s**-1",
11971 ctl->met_nc_level, ctl->met_nc_quant);
11972 NC_DEF_VAR("v", NC_FLOAT, 3, dimid3, "V velocity", "m s**-1",
11973 ctl->met_nc_level, ctl->met_nc_quant);
11974 NC_DEF_VAR("w", NC_FLOAT, 3, dimid3, "Vertical velocity", "Pa s**-1",
11975 ctl->met_nc_level, ctl->met_nc_quant);
11976 NC_DEF_VAR("q", NC_FLOAT, 3, dimid3, "Specific humidity", "kg kg**-1",
11977 ctl->met_nc_level, ctl->met_nc_quant);
11978 NC_DEF_VAR("o3", NC_FLOAT, 3, dimid3, "Ozone mass mixing ratio",
11979 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
11980 NC_DEF_VAR("clwc", NC_FLOAT, 3, dimid3, "Cloud liquid water content",
11981 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
11982 NC_DEF_VAR("crwc", NC_FLOAT, 3, dimid3, "Cloud rain water content",
11983 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
11984 NC_DEF_VAR("ciwc", NC_FLOAT, 3, dimid3, "Cloud ice water content",
11985 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
11986 NC_DEF_VAR("cswc", NC_FLOAT, 3, dimid3, "Cloud snow water content",
11987 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
11988 NC_DEF_VAR("cc", NC_FLOAT, 3, dimid3, "Cloud cover", "-",
11989 ctl->met_nc_level, ctl->met_nc_quant);
11990
11991 /* End definitions... */
11992 NC(nc_enddef(ncid));
11993
11994 /* Write grid data... */
11995 NC_PUT_DOUBLE("time", &met->time, 0);
11996 NC_PUT_DOUBLE("lon", met->lon, 0);
11997 NC_PUT_DOUBLE("lat", met->lat, 0);
11998 double phelp[EP];
11999 for (int ip = 0; ip < met->np; ip++)
12000 phelp[ip] = 100. * met->p[ip];
12001 NC_PUT_DOUBLE("lev", phelp, 0);
12002
12003 /* Write surface data... */
12004 write_met_nc_2d(ncid, "sp", met, met->ps, 100.0f);
12005 write_met_nc_2d(ncid, "z", met, met->zs, (float) (1000. * G0));
12006 write_met_nc_2d(ncid, "t2m", met, met->ts, 1.0f);
12007 write_met_nc_2d(ncid, "u10m", met, met->us, 1.0f);
12008 write_met_nc_2d(ncid, "v10m", met, met->vs, 1.0f);
12009 write_met_nc_2d(ncid, "iews", met, met->ess, 1.0f);
12010 write_met_nc_2d(ncid, "inss", met, met->nss, 1.0f);
12011 write_met_nc_2d(ncid, "ishf", met, met->shf, 1.0f);
12012 write_met_nc_2d(ncid, "lsm", met, met->lsm, 1.0f);
12013 write_met_nc_2d(ncid, "sstk", met, met->sst, 1.0f);
12014 write_met_nc_2d(ncid, "blp", met, met->pbl, 100.0f);
12015 write_met_nc_2d(ncid, "pt", met, met->pt, 100.0f);
12016 write_met_nc_2d(ncid, "tt", met, met->tt, 1.0f);
12017 write_met_nc_2d(ncid, "zt", met, met->zt, 1000.0f);
12018 write_met_nc_2d(ncid, "h2ot", met, met->h2ot, 1.0f);
12019 write_met_nc_2d(ncid, "pct", met, met->pct, 100.0f);
12020 write_met_nc_2d(ncid, "pcb", met, met->pcb, 100.0f);
12021 write_met_nc_2d(ncid, "cl", met, met->cl, 1.0f);
12022 write_met_nc_2d(ncid, "plcl", met, met->plcl, 100.0f);
12023 write_met_nc_2d(ncid, "plfc", met, met->plfc, 100.0f);
12024 write_met_nc_2d(ncid, "pel", met, met->pel, 100.0f);
12025 write_met_nc_2d(ncid, "cape", met, met->cape, 1.0f);
12026 write_met_nc_2d(ncid, "cin", met, met->cin, 1.0f);
12027 write_met_nc_2d(ncid, "o3c", met, met->o3c, 1.0f);
12028
12029 /* Write level data... */
12030 write_met_nc_3d(ncid, "t", met, met->t, 1.0f);
12031 write_met_nc_3d(ncid, "u", met, met->u, 1.0f);
12032 write_met_nc_3d(ncid, "v", met, met->v, 1.0f);
12033 write_met_nc_3d(ncid, "w", met, met->w, 100.0f);
12034 write_met_nc_3d(ncid, "q", met, met->h2o, (float) (MH2O / MA));
12035 write_met_nc_3d(ncid, "o3", met, met->o3, (float) (MO3 / MA));
12036 write_met_nc_3d(ncid, "clwc", met, met->lwc, 1.0f);
12037 write_met_nc_3d(ncid, "crwc", met, met->rwc, 1.0f);
12038 write_met_nc_3d(ncid, "ciwc", met, met->iwc, 1.0f);
12039 write_met_nc_3d(ncid, "cswc", met, met->swc, 1.0f);
12040 write_met_nc_3d(ncid, "cc", met, met->cc, 1.0f);
12041
12042 /* Close file... */
12043 NC(nc_close(ncid));
12044}
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:12048
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:12077
int met_nc_quant
Number of digits for quantization of netCDF meteo files (0=off).
Definition: mptrac.h:2575
int met_nc_level
zlib compression level of netCDF meteo files (0=off).
Definition: mptrac.h:2572
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 12048 of file mptrac.c.

12053 {
12054
12055 int varid;
12056 size_t start[4], count[4];
12057
12058 /* Allocate... */
12059 float *help;
12060 ALLOC(help, float,
12061 EX * EY);
12062
12063 /* Copy data... */
12064 for (int ix = 0; ix < met->nx; ix++)
12065 for (int iy = 0; iy < met->ny; iy++)
12066 help[ARRAY_2D(iy, ix, met->nx)] = scl * var[ix][iy];
12067
12068 /* Write data... */
12069 NC_PUT_FLOAT(varname, help, 0);
12070
12071 /* Free... */
12072 free(help);
12073}
#define NC_PUT_FLOAT(varname, ptr, hyperslab)
Write a float array to a NetCDF file.
Definition: mptrac.h:1230

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

12082 {
12083
12084 int varid;
12085 size_t start[4], count[4];
12086
12087 /* Allocate... */
12088 float *help;
12089 ALLOC(help, float,
12090 EX * EY * EP);
12091
12092 /* Copy data... */
12093 for (int ix = 0; ix < met->nx; ix++)
12094 for (int iy = 0; iy < met->ny; iy++)
12095 for (int ip = 0; ip < met->np; ip++)
12096 help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)] = scl * var[ix][iy][ip];
12097
12098 /* Write data... */
12099 NC_PUT_FLOAT(varname, help, 0);
12100
12101 /* Free... */
12102 free(help);
12103}

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

12113 {
12114
12115 static FILE *out;
12116
12117 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
12118 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
12119
12120 static int nobs, *obscount, ip, okay;
12121
12122 /* Set timer... */
12123 SELECT_TIMER("WRITE_PROF", "OUTPUT", NVTX_WRITE);
12124
12125 /* Init... */
12126 if (t == ctl->t_start) {
12127
12128 /* Check quantity index for mass... */
12129 if (ctl->qnt_m < 0)
12130 ERRMSG("Need quantity mass!");
12131
12132 /* Check molar mass... */
12133 if (ctl->molmass <= 0)
12134 ERRMSG("Specify molar mass!");
12135
12136 /* Allocate... */
12137 ALLOC(lon, double,
12138 ctl->prof_nx);
12139 ALLOC(lat, double,
12140 ctl->prof_ny);
12141 ALLOC(area, double,
12142 ctl->prof_ny);
12143 ALLOC(z, double,
12144 ctl->prof_nz);
12145 ALLOC(press, double,
12146 ctl->prof_nz);
12147 ALLOC(rt, double,
12148 NOBS);
12149 ALLOC(rz, double,
12150 NOBS);
12151 ALLOC(rlon, double,
12152 NOBS);
12153 ALLOC(rlat, double,
12154 NOBS);
12155 ALLOC(robs, double,
12156 NOBS);
12157
12158 /* Read observation data... */
12159 read_obs(ctl->prof_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
12160
12161 /* Create new output file... */
12162 LOG(1, "Write profile data: %s", filename);
12163 if (!(out = fopen(filename, "w")))
12164 ERRMSG("Cannot create file!");
12165
12166 /* Write header... */
12167 fprintf(out,
12168 "# $1 = time [s]\n"
12169 "# $2 = altitude [km]\n"
12170 "# $3 = longitude [deg]\n"
12171 "# $4 = latitude [deg]\n"
12172 "# $5 = pressure [hPa]\n"
12173 "# $6 = temperature [K]\n"
12174 "# $7 = volume mixing ratio [ppv]\n"
12175 "# $8 = H2O volume mixing ratio [ppv]\n"
12176 "# $9 = O3 volume mixing ratio [ppv]\n"
12177 "# $10 = observed BT index [K]\n"
12178 "# $11 = number of observations\n");
12179
12180 /* Set grid box size... */
12181 dz = (ctl->prof_z1 - ctl->prof_z0) / ctl->prof_nz;
12182 dlon = (ctl->prof_lon1 - ctl->prof_lon0) / ctl->prof_nx;
12183 dlat = (ctl->prof_lat1 - ctl->prof_lat0) / ctl->prof_ny;
12184
12185 /* Set vertical coordinates... */
12186 for (int iz = 0; iz < ctl->prof_nz; iz++) {
12187 z[iz] = ctl->prof_z0 + dz * (iz + 0.5);
12188 press[iz] = P(z[iz]);
12189 }
12190
12191 /* Set horizontal coordinates... */
12192 for (int ix = 0; ix < ctl->prof_nx; ix++)
12193 lon[ix] = ctl->prof_lon0 + dlon * (ix + 0.5);
12194 for (int iy = 0; iy < ctl->prof_ny; iy++) {
12195 lat[iy] = ctl->prof_lat0 + dlat * (iy + 0.5);
12196 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
12197 }
12198 }
12199
12200 /* Set time interval... */
12201 const double t0 = t - 0.5 * ctl->dt_mod;
12202 const double t1 = t + 0.5 * ctl->dt_mod;
12203
12204 /* Allocate... */
12205 ALLOC(mass, double,
12206 ctl->prof_nx * ctl->prof_ny * ctl->prof_nz);
12207 ALLOC(obsmean, double,
12208 ctl->prof_nx * ctl->prof_ny);
12209 ALLOC(obscount, int,
12210 ctl->prof_nx * ctl->prof_ny);
12211
12212 /* Loop over observations... */
12213 for (int i = 0; i < nobs; i++) {
12214
12215 /* Check time... */
12216 if (rt[i] < t0)
12217 continue;
12218 else if (rt[i] >= t1)
12219 break;
12220
12221 /* Check observation data... */
12222 if (!isfinite(robs[i]))
12223 continue;
12224
12225 /* Calculate indices... */
12226 int ix = (int) ((rlon[i] - ctl->prof_lon0) / dlon);
12227 int iy = (int) ((rlat[i] - ctl->prof_lat0) / dlat);
12228
12229 /* Check indices... */
12230 if (ix < 0 || ix >= ctl->prof_nx || iy < 0 || iy >= ctl->prof_ny)
12231 continue;
12232
12233 /* Get mean observation index... */
12234 int idx = ARRAY_2D(ix, iy, ctl->prof_ny);
12235 obsmean[idx] += robs[i];
12236 obscount[idx]++;
12237 }
12238
12239 /* Analyze model data... */
12240 for (ip = 0; ip < atm->np; ip++) {
12241
12242 /* Check time... */
12243 if (atm->time[ip] < t0 || atm->time[ip] > t1)
12244 continue;
12245
12246 /* Get indices... */
12247 int ix = (int) ((atm->lon[ip] - ctl->prof_lon0) / dlon);
12248 int iy = (int) ((atm->lat[ip] - ctl->prof_lat0) / dlat);
12249 int iz = (int) ((Z(atm->p[ip]) - ctl->prof_z0) / dz);
12250
12251 /* Check indices... */
12252 if (ix < 0 || ix >= ctl->prof_nx ||
12253 iy < 0 || iy >= ctl->prof_ny || iz < 0 || iz >= ctl->prof_nz)
12254 continue;
12255
12256 /* Get total mass in grid cell... */
12257 int idx = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
12258 mass[idx] += atm->q[ctl->qnt_m][ip];
12259 }
12260
12261 /* Extract profiles... */
12262 for (int ix = 0; ix < ctl->prof_nx; ix++)
12263 for (int iy = 0; iy < ctl->prof_ny; iy++) {
12264 int idx2 = ARRAY_2D(ix, iy, ctl->prof_ny);
12265 if (obscount[idx2] > 0) {
12266
12267 /* Check profile... */
12268 okay = 0;
12269 for (int iz = 0; iz < ctl->prof_nz; iz++) {
12270 int idx3 = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
12271 if (mass[idx3] > 0) {
12272 okay = 1;
12273 break;
12274 }
12275 }
12276 if (!okay)
12277 continue;
12278
12279 /* Write output... */
12280 fprintf(out, "\n");
12281
12282 /* Loop over altitudes... */
12283 for (int iz = 0; iz < ctl->prof_nz; iz++) {
12284
12285 /* Get temperature, water vapor, and ozone... */
12287 intpol_met_time_3d(met0, met0->t, met1, met1->t, t, press[iz],
12288 lon[ix], lat[iy], &temp, ci, cw, 1);
12289 intpol_met_time_3d(met0, met0->h2o, met1, met1->h2o, t, press[iz],
12290 lon[ix], lat[iy], &h2o, ci, cw, 0);
12291 intpol_met_time_3d(met0, met0->o3, met1, met1->o3, t, press[iz],
12292 lon[ix], lat[iy], &o3, ci, cw, 0);
12293
12294 /* Calculate volume mixing ratio... */
12295 const int idx3 = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
12296 vmr = MA / ctl->molmass * mass[idx3]
12297 / (RHO(press[iz], temp) * area[iy] * dz * 1e9);
12298
12299 /* Write output... */
12300 fprintf(out, "%.2f %g %g %g %g %g %g %g %g %g %d\n",
12301 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
12302 obsmean[idx2] / obscount[idx2], obscount[idx2]);
12303 }
12304 }
12305 }
12306
12307 /* Free... */
12308 free(mass);
12309 free(obsmean);
12310 free(obscount);
12311
12312 /* Finalize... */
12313 if (t == ctl->t_stop) {
12314
12315 /* Close output file... */
12316 fclose(out);
12317
12318 /* Free... */
12319 free(lon);
12320 free(lat);
12321 free(area);
12322 free(z);
12323 free(press);
12324 free(rt);
12325 free(rz);
12326 free(rlon);
12327 free(rlat);
12328 free(robs);
12329 }
12330}
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 12334 of file mptrac.c.

12340 {
12341
12342 static FILE *out;
12343
12344 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[EP],
12345 kw[EP];
12346
12347 static int nobs, nk;
12348
12349 /* Set timer... */
12350 SELECT_TIMER("WRITE_SAMPLE", "OUTPUT", NVTX_WRITE);
12351
12352 /* Init... */
12353 if (t == ctl->t_start) {
12354
12355 /* Allocate... */
12356 ALLOC(rt, double,
12357 NOBS);
12358 ALLOC(rz, double,
12359 NOBS);
12360 ALLOC(rlon, double,
12361 NOBS);
12362 ALLOC(rlat, double,
12363 NOBS);
12364 ALLOC(robs, double,
12365 NOBS);
12366
12367 /* Read observation data... */
12368 read_obs(ctl->sample_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
12369
12370 /* Read kernel data... */
12371 if (ctl->sample_kernel[0] != '-')
12372 read_kernel(ctl->sample_kernel, kz, kw, &nk);
12373
12374 /* Create output file... */
12375 LOG(1, "Write sample data: %s", filename);
12376 if (!(out = fopen(filename, "w")))
12377 ERRMSG("Cannot create file!");
12378
12379 /* Write header... */
12380 fprintf(out,
12381 "# $1 = time [s]\n"
12382 "# $2 = altitude [km]\n"
12383 "# $3 = longitude [deg]\n"
12384 "# $4 = latitude [deg]\n"
12385 "# $5 = surface area [km^2]\n"
12386 "# $6 = layer depth [km]\n"
12387 "# $7 = number of particles [1]\n"
12388 "# $8 = column density [kg/m^2]\n"
12389 "# $9 = volume mixing ratio [ppv]\n"
12390 "# $10 = observed BT index [K]\n\n");
12391
12392 /* Set latitude range, squared radius, and area... */
12393 dlat = DY2DEG(ctl->sample_dx);
12394 rmax2 = SQR(ctl->sample_dx);
12395 area = M_PI * rmax2;
12396 }
12397
12398 /* Set time interval for output... */
12399 const double t0 = t - 0.5 * ctl->dt_mod;
12400 const double t1 = t + 0.5 * ctl->dt_mod;
12401
12402 /* Loop over observations... */
12403 for (int i = 0; i < nobs; i++) {
12404
12405 /* Check time... */
12406 if (rt[i] < t0)
12407 continue;
12408 else if (rt[i] >= t1)
12409 break;
12410
12411 /* Calculate Cartesian coordinates... */
12412 double x0[3];
12413 geo2cart(0, rlon[i], rlat[i], x0);
12414
12415 /* Set pressure range... */
12416 const double rp = P(rz[i]);
12417 const double ptop = P(rz[i] + ctl->sample_dz);
12418 const double pbot = P(rz[i] - ctl->sample_dz);
12419
12420 /* Init... */
12421 double mass = 0;
12422 int np = 0;
12423
12424 /* Loop over air parcels... */
12425 //#pragma omp parallel for default(shared) reduction(+:mass,np)
12426 for (int ip = 0; ip < atm->np; ip++) {
12427
12428 /* Check time... */
12429 if (atm->time[ip] < t0 || atm->time[ip] > t1)
12430 continue;
12431
12432 /* Check latitude... */
12433 if (fabs(rlat[i] - atm->lat[ip]) > dlat)
12434 continue;
12435
12436 /* Check horizontal distance... */
12437 double x1[3];
12438 geo2cart(0, atm->lon[ip], atm->lat[ip], x1);
12439 if (DIST2(x0, x1) > rmax2)
12440 continue;
12441
12442 /* Check pressure... */
12443 if (ctl->sample_dz > 0)
12444 if (atm->p[ip] > pbot || atm->p[ip] < ptop)
12445 continue;
12446
12447 /* Add mass... */
12448 if (ctl->qnt_m >= 0)
12449 mass +=
12450 kernel_weight(kz, kw, nk, atm->p[ip]) * atm->q[ctl->qnt_m][ip];
12451 np++;
12452 }
12453
12454 /* Calculate column density... */
12455 const double cd = mass / (1e6 * area);
12456
12457 /* Calculate volume mixing ratio... */
12458 double vmr = 0;
12459 if (ctl->molmass > 0 && ctl->sample_dz > 0) {
12460 if (mass > 0) {
12461
12462 /* Get temperature... */
12463 double temp;
12465 intpol_met_time_3d(met0, met0->t, met1, met1->t, rt[i], rp,
12466 rlon[i], rlat[i], &temp, ci, cw, 1);
12467
12468 /* Calculate volume mixing ratio... */
12469 vmr = MA / ctl->molmass * cd / (RHO(rp, temp) * ctl->sample_dz * 1e3);
12470 }
12471 } else
12472 vmr = NAN;
12473
12474 /* Write output... */
12475 fprintf(out, "%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
12476 rlon[i], rlat[i], area, ctl->sample_dz, np, cd, vmr, robs[i]);
12477 }
12478
12479 /* Finalize...... */
12480 if (t == ctl->t_stop) {
12481
12482 /* Close output file... */
12483 fclose(out);
12484
12485 /* Free... */
12486 free(rt);
12487 free(rz);
12488 free(rlon);
12489 free(rlat);
12490 free(robs);
12491 }
12492}
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 12496 of file mptrac.c.

12500 {
12501
12502 static FILE *out;
12503
12504 static double rmax2, x0[3], x1[3];
12505
12506 /* Set timer... */
12507 SELECT_TIMER("WRITE_STATION", "OUTPUT", NVTX_WRITE);
12508
12509 /* Init... */
12510 if (t == ctl->t_start) {
12511
12512 /* Write info... */
12513 LOG(1, "Write station data: %s", filename);
12514
12515 /* Create new file... */
12516 if (!(out = fopen(filename, "w")))
12517 ERRMSG("Cannot create file!");
12518
12519 /* Write header... */
12520 fprintf(out,
12521 "# $1 = time [s]\n"
12522 "# $2 = altitude [km]\n"
12523 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
12524 for (int iq = 0; iq < ctl->nq; iq++)
12525 fprintf(out, "# $%i = %s [%s]\n", (iq + 5),
12526 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
12527 fprintf(out, "\n");
12528
12529 /* Set geolocation and search radius... */
12530 geo2cart(0, ctl->stat_lon, ctl->stat_lat, x0);
12531 rmax2 = SQR(ctl->stat_r);
12532 }
12533
12534 /* Set time interval for output... */
12535 const double t0 = t - 0.5 * ctl->dt_mod;
12536 const double t1 = t + 0.5 * ctl->dt_mod;
12537
12538 /* Loop over air parcels... */
12539 for (int ip = 0; ip < atm->np; ip++) {
12540
12541 /* Check time... */
12542 if (atm->time[ip] < t0 || atm->time[ip] > t1)
12543 continue;
12544
12545 /* Check time range for station output... */
12546 if (atm->time[ip] < ctl->stat_t0 || atm->time[ip] > ctl->stat_t1)
12547 continue;
12548
12549 /* Check station flag... */
12550 if (ctl->qnt_stat >= 0)
12551 if ((int) atm->q[ctl->qnt_stat][ip])
12552 continue;
12553
12554 /* Get Cartesian coordinates... */
12555 geo2cart(0, atm->lon[ip], atm->lat[ip], x1);
12556
12557 /* Check horizontal distance... */
12558 if (DIST2(x0, x1) > rmax2)
12559 continue;
12560
12561 /* Set station flag... */
12562 if (ctl->qnt_stat >= 0)
12563 atm->q[ctl->qnt_stat][ip] = 1;
12564
12565 /* Write data... */
12566 fprintf(out, "%.2f %g %g %g",
12567 atm->time[ip], Z(atm->p[ip]), atm->lon[ip], atm->lat[ip]);
12568 for (int iq = 0; iq < ctl->nq; iq++) {
12569 fprintf(out, " ");
12570 fprintf(out, ctl->qnt_format[iq], atm->q[iq][ip]);
12571 }
12572 fprintf(out, "\n");
12573 }
12574
12575 /* Close file... */
12576 if (t == ctl->t_stop)
12577 fclose(out);
12578}
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 12582 of file mptrac.c.

12586 {
12587
12588 FILE *out;
12589
12590 /* Set timer... */
12591 SELECT_TIMER("WRITE_VTK", "OUTPUT", NVTX_WRITE);
12592
12593 /* Write info... */
12594 LOG(1, "Write VTK data: %s", filename);
12595
12596 /* Set time interval for output... */
12597 const double t0 = t - 0.5 * ctl->dt_mod;
12598 const double t1 = t + 0.5 * ctl->dt_mod;
12599
12600 /* Create file... */
12601 if (!(out = fopen(filename, "w")))
12602 ERRMSG("Cannot create file!");
12603
12604 /* Count data points... */
12605 int np = 0;
12606 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
12607 if (atm->time[ip] < t0 || atm->time[ip] > t1)
12608 continue;
12609 np++;
12610 }
12611
12612 /* Write header... */
12613 fprintf(out,
12614 "# vtk DataFile Version 3.0\n"
12615 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
12616
12617 /* Write point coordinates... */
12618 fprintf(out, "POINTS %d float\n", np);
12619 if (ctl->vtk_sphere) {
12620 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
12621 if (atm->time[ip] < t0 || atm->time[ip] > t1)
12622 continue;
12623 const double radius = (RE + Z(atm->p[ip]) * ctl->vtk_scale
12624 + ctl->vtk_offset) / RE;
12625 const double coslat = cos(DEG2RAD(atm->lat[ip]));
12626 const double x = radius * coslat * cos(DEG2RAD(atm->lon[ip]));
12627 const double y = radius * coslat * sin(DEG2RAD(atm->lon[ip]));
12628 const double z = radius * sin(DEG2RAD(atm->lat[ip]));
12629 fprintf(out, "%g %g %g\n", x, y, z);
12630 }
12631 } else
12632 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
12633 if (atm->time[ip] < t0 || atm->time[ip] > t1)
12634 continue;
12635 fprintf(out, "%g %g %g\n", atm->lon[ip], atm->lat[ip],
12636 Z(atm->p[ip]) * ctl->vtk_scale + ctl->vtk_offset);
12637 }
12638
12639 /* Write point data... */
12640 fprintf(out, "POINT_DATA %d\n", np);
12641 for (int iq = 0; iq < ctl->nq; iq++) {
12642 fprintf(out, "SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
12643 ctl->qnt_name[iq]);
12644 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
12645 if (atm->time[ip] < t0 || atm->time[ip] > t1)
12646 continue;
12647 fprintf(out, "%g\n", atm->q[iq][ip]);
12648 }
12649 }
12650
12651 /* Close file... */
12652 fclose(out);
12653}