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

MPTRAC library declarations. More...

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

Go to the source code of this file.

Data Structures

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

Macros

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

Functions

void thrustSortWrapper (double *__restrict__ c, int n, int *__restrict__ index)
 Wrapper to Thrust sorting function. More...
 
void broadcast_large_data (void *data, size_t N)
 Broadcasts large data across all processes in an MPI communicator. More...
 
void cart2geo (const double *x, double *z, double *lon, double *lat)
 Converts Cartesian coordinates to geographic coordinates. More...
 
double clim_oh (const ctl_t *ctl, const clim_t *clim, const double t, const double lon, const double lat, const double p)
 Calculates the hydroxyl radical (OH) concentration from climatology data, with an optional diurnal correction based on solar zenith angle. More...
 
void clim_oh_diurnal_correction (const ctl_t *ctl, clim_t *clim)
 Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data. More...
 
double clim_photo (const double rate[CP][CSZA][CO3], const clim_photo_t *photo, const double p, const double sza, const double o3c)
 Calculates the photolysis rate for a given set of atmospheric conditions. More...
 
double clim_tropo (const clim_t *clim, const double t, const double lat)
 Calculates the tropopause pressure based on climatological data. More...
 
void clim_tropo_init (clim_t *clim)
 Initializes the tropopause data in the climatology structure. More...
 
double clim_ts (const clim_ts_t *ts, const double t)
 Interpolates a time series of climatological variables. More...
 
double clim_zm (const clim_zm_t *zm, const double t, const double lat, const double p)
 Interpolates monthly mean zonal mean climatological variables. More...
 
void compress_cms (const ctl_t *ctl, const char *varname, float *array, const size_t nx, const size_t ny, const size_t np, const int decompress, FILE *inout)
 Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm. More...
 
void compress_pck (const char *varname, float *array, const size_t nxy, const size_t nz, const int decompress, FILE *inout)
 Compresses or decompresses a 3D array of floats. More...
 
void compress_zfp (const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
 Compresses or decompresses a 3D array of floats using the ZFP library. More...
 
void compress_zstd (const char *varname, float *array, const size_t n, const int decompress, FILE *inout)
 Compresses or decompresses an array of floats using the Zstandard (ZSTD) library. More...
 
void day2doy (const int year, const int mon, const int day, int *doy)
 Get day of year from date. More...
 
void doy2day (const int year, const int doy, int *mon, int *day)
 Converts a given day of the year (DOY) to a date (month and day). More...
 
void fft_help (double *fcReal, double *fcImag, const int n)
 Computes the Fast Fourier Transform (FFT) of a complex sequence. More...
 
void geo2cart (const double z, const double lon, const double lat, double *x)
 Converts geographic coordinates (longitude, latitude, altitude) to Cartesian coordinates. More...
 
void get_met_help (const ctl_t *ctl, const double t, const int direct, const char *metbase, const double dt_met, char *filename)
 Generates a formatted filename for meteorological data files based on the input parameters. More...
 
void get_met_replace (char *orig, char *search, char *repl)
 Replaces occurrences of a substring in a string with another substring. More...
 
void get_tropo (const int met_tropo, ctl_t *ctl, clim_t *clim, met_t *met, const double *lons, const int nx, const double *lats, const int ny, double *pt, double *zt, double *tt, double *qt, double *o3t, double *ps, double *zs)
 Calculate tropopause data. More...
 
void intpol_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_init (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Initializes the chemistry modules by setting atmospheric composition. More...
 
void module_convection (const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Performs convective mixing of atmospheric particles. More...
 
void module_decay (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, atm_t *atm)
 Simulate exponential decay processes for atmospheric particles. More...
 
void module_diff_meso (const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Simulate mesoscale diffusion for atmospheric particles. More...
 
void module_diff_pbl (const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Computes particle diffusion within the planetary boundary layer (PBL). More...
 
void module_diff_turb (const ctl_t *ctl, cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Applies turbulent diffusion processes to atmospheric particles. More...
 
void module_dry_depo (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Simulate dry deposition of atmospheric particles. More...
 
void module_h2o2_chem (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Perform chemical reactions involving H2O2 within cloud particles. More...
 
void module_isosurf_init (const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Initialize the isosurface module based on atmospheric data. More...
 
void module_isosurf (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Apply the isosurface module to adjust atmospheric properties. More...
 
void module_kpp_chem (ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 KPP chemistry module. More...
 
void module_meteo (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Update atmospheric properties using meteorological data. More...
 
void module_mixing (const ctl_t *ctl, const clim_t *clim, atm_t *atm, const double t)
 Update atmospheric properties through interparcel mixing. More...
 
void module_mixing_help (const ctl_t *ctl, const clim_t *clim, atm_t *atm, const int *ixs, const int *iys, const int *izs, const int qnt_idx)
 Perform interparcel mixing for a specific quantity. More...
 
void module_oh_chem (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Perform hydroxyl chemistry calculations for atmospheric particles. More...
 
void module_position (const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Update the positions and pressure levels of atmospheric particles. More...
 
void module_rng_init (const int ntask)
 Initialize random number generators for parallel tasks. More...
 
void module_rng (const ctl_t *ctl, double *rs, const size_t n, const int method)
 Generate random numbers using various methods and distributions. More...
 
void module_sedi (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Simulate sedimentation of particles in the atmosphere. More...
 
void module_sort (const ctl_t *ctl, met_t *met0, atm_t *atm)
 Sort particles according to box index. More...
 
void module_sort_help (double *a, const int *p, const int np)
 Reorder an array based on a given permutation. More...
 
void module_timesteps (const ctl_t *ctl, cache_t *cache, met_t *met0, atm_t *atm, const double t)
 Calculate time steps for air parcels based on specified conditions. More...
 
void module_timesteps_init (ctl_t *ctl, const atm_t *atm)
 Initialize start time and time interval for time-stepping. More...
 
void module_tracer_chem (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Simulate chemical reactions involving long-lived atmospheric tracers. More...
 
void module_wet_depo (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Perform wet deposition calculations for air parcels. More...
 
void mptrac_alloc (ctl_t **ctl, cache_t **cache, clim_t **clim, met_t **met0, met_t **met1, atm_t **atm)
 Allocates and initializes memory resources for MPTRAC. More...
 
void mptrac_free (ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Frees memory resources allocated for MPTRAC. More...
 
void mptrac_get_met (ctl_t *ctl, clim_t *clim, const double t, met_t **met0, met_t **met1)
 Retrieves meteorological data for the specified time. More...
 
void mptrac_init (ctl_t *ctl, cache_t *cache, clim_t *clim, atm_t *atm, const int ntask)
 Initializes the MPTRAC model and its associated components. More...
 
int mptrac_read_atm (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads air parcel data from a specified file into the given atmospheric structure. More...
 
void mptrac_read_clim (const ctl_t *ctl, clim_t *clim)
 Reads various climatological data and populates the given climatology structure. More...
 
void mptrac_read_ctl (const char *filename, int argc, char *argv[], ctl_t *ctl)
 Reads control parameters from a configuration file and populates the given structure. More...
 
int mptrac_read_met (const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met)
 Reads meteorological data from a file, supporting multiple formats and MPI broadcasting. More...
 
void mptrac_run_timestep (ctl_t *ctl, cache_t *cache, clim_t *clim, met_t **met0, met_t **met1, atm_t *atm, double t)
 Executes a single timestep of the MPTRAC model simulation. More...
 
void mptrac_write_atm (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes air parcel data to a file in various formats. More...
 
void mptrac_write_met (const char *filename, const ctl_t *ctl, met_t *met)
 Writes meteorological data to a file, supporting multiple formats and compression options. More...
 
void mptrac_write_output (const char *dirname, const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double t)
 Writes various types of output data to files in a specified directory. More...
 
void mptrac_update_device (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
 Updates device memory for specified data structures. More...
 
void mptrac_update_host (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
 Updates host memory for specified data structures. More...
 
double nat_temperature (const double p, const double h2o, const double hno3)
 Calculates the nitric acid trihydrate (NAT) temperature. More...
 
double pbl_weight (const ctl_t *ctl, const atm_t *atm, const int ip, const double pbl, const double ps)
 Computes a weighting factor based on planetary boundary layer pressure. More...
 
int read_atm_asc (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads air parcel data from an ASCII file and populates the given atmospheric structure. More...
 
int read_atm_bin (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads air parcel data from a binary file and populates the given atmospheric structure. More...
 
int read_atm_clams (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads 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...
 
void read_met_grid (const char *filename, const int ncid, const ctl_t *ctl, met_t *met)
 Reads meteorological grid information from a NetCDF file. More...
 
void read_met_levels (const int ncid, const ctl_t *ctl, met_t *met)
 Reads meteorological variables at different vertical levels from a NetCDF file. More...
 
void read_met_ml2pl (const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname)
 Interpolates meteorological data to specified pressure levels. More...
 
void read_met_monotonize (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)
 Calculates the tropopause and related meteorological variables based on various methods and stores the results in the meteorological data structure. More...
 
void read_obs (const char *filename, const ctl_t *ctl, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
 Reads observation data from a file and stores it in arrays. More...
 
void read_obs_asc (const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
 Reads observation data from an ASCII file. More...
 
void read_obs_nc (const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
 Reads observation data from a NetCDF file. More...
 
double scan_ctl (const char *filename, int argc, char *argv[], const char *varname, const int arridx, const char *defvalue, char *value)
 Scans a control file or command-line arguments for a specified variable. More...
 
double sedi (const double p, const double T, const double rp, const double rhop)
 Calculates the sedimentation velocity of a particle in air. More...
 
void spline (const double *x, const double *y, const int n, const double *x2, double *y2, const int n2, const int method)
 Performs spline interpolation or linear interpolation. More...
 
float stddev (const float *data, const int n)
 Calculates the standard deviation of a set of data. More...
 
double sza_calc (const double sec, const double lon, const double lat)
 Calculates the solar zenith angle. More...
 
void time2jsec (const int year, const int mon, const int day, const int hour, const int min, const int sec, const double remain, double *jsec)
 Converts time components to seconds since January 1, 2000, 12:00:00 UTC. More...
 
void timer (const char *name, const char *group, const int output)
 Measures and reports elapsed time for named and grouped timers. More...
 
double time_from_filename (const char *filename, const int offset)
 Extracts and converts a timestamp from a filename to Julian seconds. More...
 
double tropo_weight (const clim_t *clim, const atm_t *atm, const int ip)
 Computes a weighting factor based on tropopause pressure. More...
 
void write_atm_asc (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes air parcel data to an ASCII file or gnuplot. More...
 
void write_atm_bin (const char *filename, const ctl_t *ctl, const atm_t *atm)
 Writes air parcel data to a binary file. More...
 
void write_atm_clams (const char *filename, const ctl_t *ctl, const atm_t *atm)
 Writes air parcel data to a NetCDF file in the CLaMS format. More...
 
void write_atm_clams_traj (const char *dirname, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes CLaMS trajectory data to a NetCDF file. More...
 
void write_atm_nc (const char *filename, const ctl_t *ctl, const atm_t *atm)
 Writes air parcel data to a NetCDF file. More...
 
void write_csi (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes Critical Success Index (CSI) data to a file. More...
 
void write_ens (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes ensemble data to a file. More...
 
void write_grid (const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
 Writes grid data to a file in ASCII or netCDF format. More...
 
void write_grid_asc (const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
 Writes grid data to an ASCII file. More...
 
void write_grid_nc (const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
 Writes grid data to a NetCDF file. More...
 
void write_met_bin (const char *filename, const ctl_t *ctl, met_t *met)
 Writes meteorological data in binary format to a specified file. More...
 
void write_met_bin_2d (FILE *out, met_t *met, float var[EX][EY], const char *varname)
 Writes a 2-dimensional meteorological variable to a binary file. More...
 
void write_met_bin_3d (FILE *out, const ctl_t *ctl, met_t *met, float var[EX][EY][EP], const char *varname, const int precision, const double tolerance)
 Writes a 3-dimensional meteorological variable to a binary file. More...
 
void write_met_nc (const char *filename, const ctl_t *ctl, met_t *met)
 Writes meteorological data to a NetCDF file. More...
 
void write_met_nc_2d (const int ncid, const char *varname, met_t *met, float var[EX][EY], const float scl)
 Writes a 2D meteorological variable to a NetCDF file. More...
 
void write_met_nc_3d (const int ncid, const char *varname, met_t *met, float var[EX][EY][EP], const float scl)
 Writes a 3D meteorological variable to a NetCDF file. More...
 
void write_prof (const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
 Writes profile data to a specified file. More...
 
void write_sample (const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
 Writes sample data to a specified file. More...
 
void write_station (const char *filename, const ctl_t *ctl, atm_t *atm, const double t)
 Writes station data to a specified file. More...
 
void write_vtk (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes VTK (Visualization Toolkit) data to a specified file. More...
 

Detailed Description

MPTRAC library declarations.

Definition in file mptrac.h.

Macro Definition Documentation

◆ AVO

#define AVO   6.02214076e23

Avogadro constant [1/mol].

Definition at line 157 of file mptrac.h.

◆ CPD

#define CPD   1003.5

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

Definition at line 162 of file mptrac.h.

◆ EPS

#define EPS   (MH2O / MA)

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

Definition at line 167 of file mptrac.h.

◆ G0

#define G0   9.80665

Standard gravity [m/s^2].

Definition at line 172 of file mptrac.h.

◆ H0

#define H0   7.0

Scale height [km].

Definition at line 177 of file mptrac.h.

◆ LV

#define LV   2501000.

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

Definition at line 182 of file mptrac.h.

◆ KARMAN

#define KARMAN   0.40

Karman's constant.

Definition at line 187 of file mptrac.h.

◆ KB

#define KB   1.3806504e-23

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

Definition at line 192 of file mptrac.h.

◆ MA

#define MA   28.9644

Molar mass of dry air [g/mol].

Definition at line 197 of file mptrac.h.

◆ MH2O

#define MH2O   18.01528

Molar mass of water vapor [g/mol].

Definition at line 202 of file mptrac.h.

◆ MO3

#define MO3   48.00

Molar mass of ozone [g/mol].

Definition at line 207 of file mptrac.h.

◆ P0

#define P0   1013.25

Standard pressure [hPa].

Definition at line 212 of file mptrac.h.

◆ RA

#define RA   (1e3 * RI / MA)

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

Definition at line 217 of file mptrac.h.

◆ RE

#define RE   6367.421

Mean radius of Earth [km].

Definition at line 222 of file mptrac.h.

◆ RI

#define RI   8.3144598

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

Definition at line 227 of file mptrac.h.

◆ T0

#define T0   273.15

Standard temperature [K].

Definition at line 232 of file mptrac.h.

◆ LEN

#define LEN   5000

Maximum length of ASCII data lines.

Definition at line 241 of file mptrac.h.

◆ NP

#define NP   10000000

Maximum number of atmospheric data points.

Definition at line 246 of file mptrac.h.

◆ NQ

#define NQ   15

Maximum number of quantities per data point.

Definition at line 251 of file mptrac.h.

◆ NCSI

#define NCSI   1000000

Maximum number of data points for CSI calculation.

Definition at line 256 of file mptrac.h.

◆ EP

#define EP   140

Maximum number of pressure levels for meteo data.

Definition at line 261 of file mptrac.h.

◆ EX

#define EX   1202

Maximum number of longitudes for meteo data.

Definition at line 266 of file mptrac.h.

◆ EY

#define EY   602

Maximum number of latitudes for meteo data.

Definition at line 271 of file mptrac.h.

◆ NENS

#define NENS   2000

Maximum number of data points for ensemble analysis.

Definition at line 276 of file mptrac.h.

◆ NOBS

#define NOBS   10000000

Maximum number of observation data points.

Definition at line 281 of file mptrac.h.

◆ NTHREADS

#define NTHREADS   512

Maximum number of OpenMP threads.

Definition at line 286 of file mptrac.h.

◆ CY

#define CY   250

Maximum number of latitudes for climatological data.

Definition at line 291 of file mptrac.h.

◆ CO3

#define CO3   30

Maximum number of total column ozone data for climatological data.

Definition at line 296 of file mptrac.h.

◆ CP

#define CP   70

Maximum number of pressure levels for climatological data.

Definition at line 301 of file mptrac.h.

◆ CSZA

#define CSZA   50

Maximum number of solar zenith angles for climatological data.

Definition at line 306 of file mptrac.h.

◆ CT

#define CT   12

Maximum number of time steps for climatological data.

Definition at line 311 of file mptrac.h.

◆ CTS

#define CTS   1000

Maximum number of data points of climatological time series.

Definition at line 316 of file mptrac.h.

◆ ALLOC

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

Allocate memory for a pointer with error handling.

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

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

Definition at line 349 of file mptrac.h.

◆ ARRAY_2D

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

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

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

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

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

Author
Lars Hoffmann

Definition at line 372 of file mptrac.h.

◆ ARRAY_3D

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

Compute the linear index of a 3D array element.

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

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

Definition at line 391 of file mptrac.h.

◆ ARRHENIUS

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

Calculate the Arrhenius rate constant.

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

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

where:

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

Definition at line 416 of file mptrac.h.

◆ DEG2DX

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

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

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

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

where:

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

Definition at line 440 of file mptrac.h.

◆ DEG2DY

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

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

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

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

where:

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

Definition at line 461 of file mptrac.h.

◆ DEG2RAD

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

Converts degrees to radians.

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

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

Definition at line 478 of file mptrac.h.

◆ DP2DZ

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

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

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

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

where:

  • dz is the change in height (altitude) in meters.
  • dp is the pressure difference in hPa.
  • H0 is a reference scale height in km.
  • p is the reference pressure in hPa.
Parameters
dpPressure difference in hPa.
pReference pressure in hPa.
Returns
Change in height (altitude) in kilometers corresponding to the given pressure difference.
Warning
Don't use this for large values of dp!
Author
Lars Hoffmann

Definition at line 503 of file mptrac.h.

◆ DX2DEG

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

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

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

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

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

Definition at line 525 of file mptrac.h.

◆ DY2DEG

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

Convert a distance in kilometers to degrees latitude.

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

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

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

Definition at line 543 of file mptrac.h.

◆ DZ2DP

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

Convert a change in altitude to a change in pressure.

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

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

Parameters
dzChange in altitude in kilometers.
pCurrent pressure in hPa.
Returns
Change in pressure in hPa.
Warning
Don't use this for large values of dz!
Author
Lars Hoffmann

Definition at line 562 of file mptrac.h.

◆ DIST

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

Calculate the distance between two points in Cartesian coordinates.

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

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

Definition at line 578 of file mptrac.h.

◆ DIST2

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

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

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

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

Definition at line 594 of file mptrac.h.

◆ DOTP

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

Calculate the dot product of two vectors.

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

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

Definition at line 610 of file mptrac.h.

◆ FMOD

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

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

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

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

Definition at line 629 of file mptrac.h.

◆ FREAD

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

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

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

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

Definition at line 647 of file mptrac.h.

◆ FWRITE

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

Write data from memory to a file stream.

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

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

Definition at line 667 of file mptrac.h.

◆ INTPOL_INIT

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

Initialize arrays for interpolation.

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

Author
Lars Hoffmann

Definition at line 682 of file mptrac.h.

◆ INTPOL_2D

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

Perform 2D interpolation for a meteorological variable.

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

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

Definition at line 696 of file mptrac.h.

◆ INTPOL_3D

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

Perform 3D interpolation for a meteorological variable.

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

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

Definition at line 713 of file mptrac.h.

◆ INTPOL_SPACE_ALL

#define INTPOL_SPACE_ALL (   p,
  lon,
  lat 
)

Interpolate multiple meteorological variables in space.

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

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

Definition at line 732 of file mptrac.h.

◆ INTPOL_TIME_ALL

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

Interpolate multiple meteorological variables in time.

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

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

Definition at line 786 of file mptrac.h.

◆ LAPSE

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

Calculate lapse rate.

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

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

Definition at line 840 of file mptrac.h.

◆ LIN

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

Linear interpolation.

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

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

Definition at line 859 of file mptrac.h.

◆ MAX

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

Macro to determine the maximum of two values.

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

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

Definition at line 886 of file mptrac.h.

◆ MET_HEADER

#define MET_HEADER

Write header for meteorological data file.

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

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

Definition at line 900 of file mptrac.h.

◆ MIN

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

Macro to determine the minimum of two values.

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

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

Definition at line 987 of file mptrac.h.

◆ MOLEC_DENS

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

Calculate the density of a gas molecule.

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

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

Definition at line 1002 of file mptrac.h.

◆ NC

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

Execute a NetCDF command and check for errors.

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

Parameters
cmdNetCDF command to execute.
Author
Lars Hoffmann

Definition at line 1016 of file mptrac.h.

◆ NC_DEF_VAR

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

Define a NetCDF variable with attributes.

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

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

Definition at line 1045 of file mptrac.h.

◆ NC_GET_DOUBLE

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

Retrieve a double-precision variable from a NetCDF file.

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

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

Definition at line 1075 of file mptrac.h.

◆ NC_INQ_DIM

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

Inquire the length of a dimension in a NetCDF file.

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

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

Definition at line 1103 of file mptrac.h.

◆ NC_PUT_DOUBLE

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

Write double precision data to a NetCDF variable.

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

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

Definition at line 1126 of file mptrac.h.

◆ NC_PUT_FLOAT

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

Write a float array to a NetCDF file.

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

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

Definition at line 1150 of file mptrac.h.

◆ NC_PUT_INT

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

Write integer data to a NetCDF variable.

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

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

Definition at line 1173 of file mptrac.h.

◆ NC_PUT_ATT

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

Add a text attribute to a NetCDF variable.

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

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

Definition at line 1195 of file mptrac.h.

◆ NC_PUT_ATT_GLOBAL

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

Add a global text attribute to a NetCDF file.

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

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

Definition at line 1212 of file mptrac.h.

◆ NN

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

Perform nearest-neighbor interpolation.

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

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

Definition at line 1232 of file mptrac.h.

◆ NORM

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

Compute the norm (magnitude) of a vector.

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

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

Definition at line 1247 of file mptrac.h.

◆ PARTICLE_LOOP

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

Loop over particle indices with OpenACC acceleration.

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

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

Definition at line 1274 of file mptrac.h.

◆ P

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

Compute pressure at given altitude.

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

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

The barometric formula used for this calculation is:

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

where:

  • \( P(z) \) is the pressure at altitude \( z \),
  • \( P_0 \) is the standard pressure,
  • \( H_0 \) is the scale height.
Note
The constants \( P_0 \) and \( H_0 \) must be defined before using this macro.
Author
Lars Hoffmann

Definition at line 1304 of file mptrac.h.

◆ PSAT

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

Compute saturation pressure over water.

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

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

The saturation pressure over water is calculated using the formula:

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

where:

  • \( P_{\textrm{sat}}(t) \) is the saturation pressure over water at temperature \( t \),
  • \( T_0 \) is the reference temperature (0°C).
Note
The constants \( T_0 \) must be defined before using this macro.
Author
Lars Hoffmann

Definition at line 1328 of file mptrac.h.

◆ PSICE

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

Compute saturation pressure over ice (WMO, 2018).

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

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

The saturation pressure over ice is calculated using the formula:

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

where:

  • \( P_{\textrm{ice}}(t) \) is the saturation pressure over ice at temperature \( t \),
  • \( T_0 \) is the reference temperature (0°C).
Note
The constant \( T_0 \) must be defined before using this macro.
Author
Lars Hoffmann

Definition at line 1352 of file mptrac.h.

◆ PW

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

Calculate partial water vapor pressure.

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

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

The partial water vapor pressure is calculated using the formula:

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

where:

  • \( P_{\textrm{w}}(p, h_2o) \) is the partial water vapor pressure,
  • \( p \) is the total pressure in hPa,
  • \( h_2o \) is the water vapor mixing ratio in ppv,
  • \( \epsilon \) is the factor to account for saturation vapor pressure over water.
Note
The constant \( \epsilon \) must be defined before using this macro.
Author
Lars Hoffmann

Definition at line 1379 of file mptrac.h.

◆ RAD2DEG

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

Converts radians to degrees.

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

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

Definition at line 1396 of file mptrac.h.

◆ RH

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

Compute relative humidity over water.

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

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

The relative humidity over water is calculated using the formula:

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

where:

  • \( RH_{\textrm{w}}(p, t, h_2o) \) is the relative humidity over water,
  • \( P_{\textrm{w}}(p, h_2o) \) is the partial water vapor pressure,
  • \( P_{\textrm{sat}}(t) \) is the saturation pressure over water at the given temperature,
  • \( p \) is the total pressure in hPa,
  • \( t \) is the temperature in Kelvin,
  • \( h_2o \) is the water vapor mixing ratio in ppv.
Note
The macros PW() and PSAT() must be defined before using this macro.
Author
Lars Hoffmann

Definition at line 1426 of file mptrac.h.

◆ RHICE

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

Compute relative humidity over ice.

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

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

The relative humidity over ice is calculated using the formula:

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

where:

  • \( RH_{\textrm{ice}}(p, t, h_2o) \) is the relative humidity over ice,
  • \( P_{\textrm{w}}(p, h_2o) \) is the partial water vapor pressure,
  • \( P_{\textrm{ice}}(t) \) is the saturation pressure over ice at the given temperature,
  • \( p \) is the total pressure in hPa,
  • \( t \) is the temperature in Kelvin,
  • \( h_2o \) is the water vapor mixing ratio in ppv.
Note
The macros PW() and PSICE() must be defined before using this macro.
Author
Lars Hoffmann

Definition at line 1456 of file mptrac.h.

◆ RHO

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

Compute density of air.

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

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

The density of air is calculated using the formula:

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

where:

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

Definition at line 1481 of file mptrac.h.

◆ SET_ATM

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

Set atmospheric quantity value.

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

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

Definition at line 1500 of file mptrac.h.

◆ SET_QNT

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

Set atmospheric quantity index.

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

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

Definition at line 1523 of file mptrac.h.

◆ SH

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

Compute specific humidity from water vapor volume mixing ratio.

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

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

Definition at line 1544 of file mptrac.h.

◆ SQR

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

Compute the square of a value.

This macro computes the square of the input value.

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

Definition at line 1557 of file mptrac.h.

◆ SWAP

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

Swap two values.

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

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

Definition at line 1571 of file mptrac.h.

◆ TDEW

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

Calculate dew point temperature.

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

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

Formula:

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

where:

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

Definition at line 1595 of file mptrac.h.

◆ TICE

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

Calculate frost point temperature (WMO, 2018).

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

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

Formula:

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

where:

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

Definition at line 1620 of file mptrac.h.

◆ THETA

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

Compute potential temperature.

This macro calculates the potential temperature of the atmosphere.

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

Formula:

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

where:

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

Definition at line 1644 of file mptrac.h.

◆ THETAVIRT

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

Compute virtual potential temperature.

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

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

Formula:

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

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

where:

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

Definition at line 1673 of file mptrac.h.

◆ TOK

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

Get string tokens.

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

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

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

Author
Lars Hoffmann

Definition at line 1694 of file mptrac.h.

◆ TVIRT

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

Compute virtual temperature.

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

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

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

Note
EPS is typically defined as 0.622.
Author
Lars Hoffmann

Definition at line 1719 of file mptrac.h.

◆ Z

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

Convert pressure to altitude.

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

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

Formula:

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

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

Definition at line 1741 of file mptrac.h.

◆ ZDIFF

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

Calculate geopotential height difference.

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

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

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

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

Definition at line 1772 of file mptrac.h.

◆ ZETA

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

Computes the value of the zeta vertical coordinate.

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

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

Definition at line 1791 of file mptrac.h.

◆ LOGLEV

#define LOGLEV   2

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

Definition at line 1802 of file mptrac.h.

◆ LOG

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

Print a log message with a specified logging level.

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

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

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

The macro expands to a block of code that:

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

Definition at line 1834 of file mptrac.h.

◆ WARN

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

Print a warning message with contextual information.

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

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

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

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

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

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

Definition at line 1871 of file mptrac.h.

◆ ERRMSG

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

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

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

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

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

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

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

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

Definition at line 1904 of file mptrac.h.

◆ PRINT

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

Print the value of a variable with contextual information.

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

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

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

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

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

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

Definition at line 1939 of file mptrac.h.

◆ NTIMER

#define NTIMER   100

Maximum number of timers.

Definition at line 1948 of file mptrac.h.

◆ PRINT_TIMERS

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

Print the current state of all timers.

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

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

Definition at line 1963 of file mptrac.h.

◆ SELECT_TIMER

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

Select and start a timer with specific attributes.

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

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

Definition at line 1984 of file mptrac.h.

◆ START_TIMERS

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

Starts a timer for tracking.

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

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

Definition at line 2003 of file mptrac.h.

◆ STOP_TIMERS

#define STOP_TIMERS    NVTX_POP;

Stop the current timer.

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

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

Definition at line 2018 of file mptrac.h.

◆ NVTX_PUSH

#define NVTX_PUSH (   range_title,
  range_color 
)    {}

Definition at line 2110 of file mptrac.h.

◆ NVTX_POP

#define NVTX_POP   {}

Definition at line 2111 of file mptrac.h.

Function Documentation

◆ thrustSortWrapper()

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

Wrapper to Thrust sorting function.

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

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

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

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

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

◆ broadcast_large_data()

void broadcast_large_data ( void *  data,
size_t  N 
)

Broadcasts large data across all processes in an MPI communicator.

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

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

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

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

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

◆ cart2geo()

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

Converts Cartesian coordinates to geographic coordinates.

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

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

Converts Cartesian coordinates to geographic coordinates.

Definition at line 74 of file mptrac.c.

78 {
79
80 const double radius = NORM(x);
81
82 *lat = RAD2DEG(asin(x[2] / radius));
83 *lon = RAD2DEG(atan2(x[1], x[0]));
84 *z = radius - RE;
85}
#define NORM(a)
Compute the norm (magnitude) of a vector.
Definition: mptrac.h:1247
#define RAD2DEG(rad)
Converts radians to degrees.
Definition: mptrac.h:1396

◆ clim_oh()

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

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

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

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

Definition at line 89 of file mptrac.c.

95 {
96
97 /* Set SZA threshold... */
98 const double sza_thresh = DEG2RAD(85.), cos_sza_thresh = cos(sza_thresh);
99
100 /* Get OH data from climatology... */
101 const double oh = clim_zm(&clim->oh, t, lat, p);
102
103 /* Apply diurnal correction... */
104 if (ctl->oh_chem_beta > 0) {
105 double sza = sza_calc(t, lon, lat);
106 if (sza <= sza_thresh)
107 return oh * exp(-ctl->oh_chem_beta / cos(sza));
108 else
109 return oh * exp(-ctl->oh_chem_beta / cos_sza_thresh);
110 } else
111 return oh;
112}
double clim_zm(const clim_zm_t *zm, const double t, const double lat, const double p)
Interpolates monthly mean zonal mean climatological variables.
Definition: mptrac.c:401
double sza_calc(const double sec, const double lon, const double lat)
Calculates the solar zenith angle.
Definition: mptrac.c:9102
clim_zm_t oh
OH zonal means.
Definition: mptrac.h:3341
double oh_chem_beta
Beta parameter for diurnal variablity of OH.
Definition: mptrac.h:2857
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:3297
int np
Number of pressure levels.
Definition: mptrac.h:3294
double vmr[CT][CP][CY]
Volume mixing ratio [ppv].
Definition: mptrac.h:3306
int ntime
Number of timesteps.
Definition: mptrac.h:3288
int nlat
Number of latitudes.
Definition: mptrac.h:3291
double lat[CY]
Latitude [deg].
Definition: mptrac.h:3300
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:2045
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:1981
#define LIN(x0, y0, x1, y1, x)
Linear interpolation.
Definition: mptrac.h:859
#define MAX(a, b)
Macro to determine the maximum of two values.
Definition: mptrac.h:886
int nsza
Number of solar zenith angles.
Definition: mptrac.h:3215
double sza[CSZA]
Solar zenith angle [rad].
Definition: mptrac.h:3224
double p[CP]
Pressure [hPa].
Definition: mptrac.h:3221
double o3c[CO3]
Total column ozone [DU].
Definition: mptrac.h:3227
int np
Number of pressure levels.
Definition: mptrac.h:3212
int no3c
Number of total ozone columns.
Definition: mptrac.h:3218
Here is the call graph for this function:

◆ clim_tropo()

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

Calculates the tropopause pressure based on climatological data.

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

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

This function performs the following steps:

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

Definition at line 200 of file mptrac.c.

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

◆ clim_tropo_init()

void clim_tropo_init ( clim_t clim)

Initializes the tropopause data in the climatology structure.

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

Parameters
climPointer to the climatology structure to be initialized.

This function performs the following steps:

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

Definition at line 228 of file mptrac.c.

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

◆ clim_ts()

double clim_ts ( const clim_ts_t ts,
const double  t 
)

Interpolates a time series of climatological variables.

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

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

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

Author
Lars Hoffmann

Definition at line 383 of file mptrac.c.

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

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

◆ compress_zfp()

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

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

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

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

The function performs the following steps:

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

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

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

◆ compress_zstd()

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

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

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

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

The function performs the following steps:

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

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

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

◆ day2doy()

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

Get day of year from date.

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

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

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

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

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

Definition at line 900 of file mptrac.c.

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

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

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

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

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

◆ geo2cart()

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

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

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

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

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

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

Definition at line 988 of file mptrac.c.

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

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

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

◆ get_met_replace()

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

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

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

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

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

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

Definition at line 1071 of file mptrac.c.

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

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

1110 {
1111
1113
1114 ctl->met_tropo = met_tropo;
1115 read_met_tropo(ctl, clim, met);
1116#pragma omp parallel for default(shared) private(ci,cw)
1117 for (int ix = 0; ix < nx; ix++)
1118 for (int iy = 0; iy < ny; iy++) {
1119 intpol_met_space_2d(met, met->pt, lons[ix], lats[iy],
1120 &pt[iy * nx + ix], ci, cw, 1);
1121 intpol_met_space_2d(met, met->ps, lons[ix], lats[iy],
1122 &ps[iy * nx + ix], ci, cw, 0);
1123 intpol_met_space_2d(met, met->zs, lons[ix], lats[iy],
1124 &zs[iy * nx + ix], ci, cw, 0);
1125 intpol_met_space_3d(met, met->z, pt[iy * nx + ix], lons[ix],
1126 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
1127 intpol_met_space_3d(met, met->t, pt[iy * nx + ix], lons[ix],
1128 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
1129 intpol_met_space_3d(met, met->h2o, pt[iy * nx + ix], lons[ix],
1130 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
1131 intpol_met_space_3d(met, met->o3, pt[iy * nx + ix], lons[ix],
1132 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
1133 }
1134}
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:1462
void read_met_tropo(const ctl_t *ctl, const clim_t *clim, met_t *met)
Calculates the tropopause and related meteorological variables based on various methods and stores th...
Definition: mptrac.c:8656
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:1337
#define INTPOL_INIT
Initialize arrays for interpolation.
Definition: mptrac.h:682
int met_tropo
Tropopause definition (0=none, 1=clim, 2=cold point, 3=WMO_1st, 4=WMO_2nd, 5=dynamical).
Definition: mptrac.h:2617
float h2o[EX][EY][EP]
Water vapor volume mixing ratio [1].
Definition: mptrac.h:3496
float ps[EX][EY]
Surface pressure [hPa].
Definition: mptrac.h:3406
float zs[EX][EY]
Surface geopotential height [km].
Definition: mptrac.h:3412
float o3[EX][EY][EP]
Ozone volume mixing ratio [1].
Definition: mptrac.h:3499
float t[EX][EY][EP]
Temperature [K].
Definition: mptrac.h:3481
float pt[EX][EY]
Tropopause pressure [hPa].
Definition: mptrac.h:3439
float z[EX][EY][EP]
Geopotential height [km].
Definition: mptrac.h:3478
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 1138 of file mptrac.c.

1146 {
1147
1148 /* Check longitude... */
1149 *lon2 = FMOD(lon, 360.);
1150 if (*lon2 < lons[0])
1151 *lon2 += 360;
1152 else if (*lon2 > lons[nlon - 1])
1153 *lon2 -= 360;
1154
1155 /* Check latitude... */
1156 *lat2 = lat;
1157 if (lats[0] < lats[nlat - 1])
1158 *lat2 = MIN(MAX(*lat2, lats[0]), lats[nlat - 1]);
1159 else
1160 *lat2 = MIN(MAX(*lat2, lats[nlat - 1]), lats[0]);
1161}

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

1179 {
1180
1181 if (init) {
1182
1183 /* Check longitude and latitude... */
1184 double lon2, lat2;
1185 intpol_check_lon_lat(met0->lon, met0->nx, met0->lat, met0->ny, lon, lat,
1186 &lon2, &lat2);
1187
1188 /* Get horizontal indizes... */
1189 ci[0] = locate_irr(met0->lon, met0->nx, lon2);
1190 ci[1] = locate_irr(met0->lat, met0->ny, lat2);
1191
1192 /* Locate the vertical indizes for each edge of the column... */
1193 int ind[2][4];
1194 locate_vert(heights0, met0->npl, ci[0], ci[1], height, ind[0]);
1195 locate_vert(heights1, met1->npl, ci[0], ci[1], height, ind[1]);
1196
1197 /* Find minimum and maximum indizes... */
1198 ci[2] = ind[0][0];
1199 int k_max = ind[0][0];
1200 for (int i = 0; i < 2; i++)
1201 for (int j = 0; j < 4; j++) {
1202 if (ci[2] > ind[i][j])
1203 ci[2] = ind[i][j];
1204 if (k_max < ind[i][j])
1205 k_max = ind[i][j];
1206 }
1207
1208 /* Get weighting factors for time, longitude and latitude... */
1209 cw[3] = (ts - met0->time) / (met1->time - met0->time);
1210 cw[0] = (lon2 - met0->lon[ci[0]]) /
1211 (met0->lon[ci[0] + 1] - met0->lon[ci[0]]);
1212 cw[1] = (lat2 - met0->lat[ci[1]]) /
1213 (met0->lat[ci[1] + 1] - met0->lat[ci[1]]);
1214
1215 /* Interpolate in time at the lowest level... */
1216 double height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
1217 - heights0[ci[0]][ci[1]][ci[2]])
1218 + heights0[ci[0]][ci[1]][ci[2]];
1219 double height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
1220 - heights0[ci[0]][ci[1] + 1][ci[2]])
1221 + heights0[ci[0]][ci[1] + 1][ci[2]];
1222 double height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
1223 - heights0[ci[0] + 1][ci[1]][ci[2]])
1224 + heights0[ci[0] + 1][ci[1]][ci[2]];
1225 double height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
1226 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
1227 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
1228
1229 /* Interpolate in latitude direction... */
1230 double height0 = cw[1] * (height01 - height00) + height00;
1231 double height1 = cw[1] * (height11 - height10) + height10;
1232
1233 /* Interpolate in longitude direction... */
1234 double height_bot = cw[0] * (height1 - height0) + height0;
1235
1236 /* Interpolate in time at the upper level... */
1237 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
1238 - heights0[ci[0]][ci[1]][ci[2] + 1])
1239 + heights0[ci[0]][ci[1]][ci[2] + 1];
1240 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
1241 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
1242 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
1243 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
1244 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
1245 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
1246 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1247 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1248 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1249
1250 /* Interpolate in latitude direction... */
1251 height0 = cw[1] * (height01 - height00) + height00;
1252 height1 = cw[1] * (height11 - height10) + height10;
1253
1254 /* Interpolate in longitude direction... */
1255 double height_top = cw[0] * (height1 - height0) + height0;
1256
1257 /* Search at higher levels if height is not in box... */
1258 while (((heights0[0][0][0] > heights0[0][0][1]) &&
1259 ((height_bot <= height) || (height_top > height))
1260 && (height_bot >= height) && (ci[2] < k_max))
1261 ||
1262 ((heights0[0][0][0] < heights0[0][0][1]) &&
1263 ((height_bot >= height) || (height_top < height))
1264 && (height_bot <= height) && (ci[2] < k_max))
1265 ) {
1266
1267 ci[2]++;
1268 height_bot = height_top;
1269
1270 /* Interpolate in time at the next level... */
1271 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
1272 - heights0[ci[0]][ci[1]][ci[2] + 1])
1273 + heights0[ci[0]][ci[1]][ci[2] + 1];
1274 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
1275 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
1276 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
1277 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
1278 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
1279 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
1280 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1281 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1282 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1283
1284 /* Interpolate in latitude direction... */
1285 height0 = cw[1] * (height01 - height00) + height00;
1286 height1 = cw[1] * (height11 - height10) + height10;
1287
1288 /* Interpolate in longitude direction... */
1289 height_top = cw[0] * (height1 - height0) + height0;
1290 }
1291
1292 /* Get vertical weighting factors... */
1293 cw[2] = (height - height_bot)
1294 / (height_top - height_bot);
1295 }
1296
1297 /* Calculate the needed array values... */
1298 double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
1299 - array0[ci[0]][ci[1]][ci[2]])
1300 + array0[ci[0]][ci[1]][ci[2]];
1301 double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
1302 - array0[ci[0] + 1][ci[1]][ci[2]])
1303 + array0[ci[0] + 1][ci[1]][ci[2]];
1304 double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
1305 - array0[ci[0]][ci[1] + 1][ci[2]])
1306 + array0[ci[0]][ci[1] + 1][ci[2]];
1307 double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
1308 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
1309 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
1310 double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
1311 - array0[ci[0]][ci[1]][ci[2] + 1])
1312 + array0[ci[0]][ci[1]][ci[2] + 1];
1313 double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
1314 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
1315 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
1316 double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
1317 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
1318 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
1319 double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1320 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1321 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1322
1323 double array00 = cw[0] * (array100 - array000) + array000;
1324 double array10 = cw[0] * (array110 - array010) + array010;
1325 double array01 = cw[0] * (array101 - array001) + array001;
1326 double array11 = cw[0] * (array111 - array011) + array011;
1327
1328 double aux0 = cw[1] * (array10 - array00) + array00;
1329 double aux1 = cw[1] * (array11 - array01) + array01;
1330
1331 /* Interpolate vertically... */
1332 *var = cw[2] * (aux1 - aux0) + aux0;
1333}
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:2064
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:1138
int nx
Number of longitudes.
Definition: mptrac.h:3382
int ny
Number of latitudes.
Definition: mptrac.h:3385
double lon[EX]
Longitude [deg].
Definition: mptrac.h:3394
int npl
Number of model levels.
Definition: mptrac.h:3391
double time
Time [s].
Definition: mptrac.h:3379
double lat[EY]
Latitude [deg].
Definition: mptrac.h:3397
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 1337 of file mptrac.c.

1346 {
1347
1348 /* Initialize interpolation... */
1349 if (init) {
1350
1351 /* Check longitude and latitude... */
1352 double lon2, lat2;
1353 intpol_check_lon_lat(met->lon, met->nx, met->lat, met->ny, lon, lat,
1354 &lon2, &lat2);
1355
1356 /* Get interpolation indices... */
1357 ci[0] = locate_irr(met->p, met->np, p);
1358 ci[1] = locate_reg(met->lon, met->nx, lon2);
1359 ci[2] = locate_irr(met->lat, met->ny, lat2);
1360
1361 /* Get interpolation weights... */
1362 cw[0] = (met->p[ci[0] + 1] - p)
1363 / (met->p[ci[0] + 1] - met->p[ci[0]]);
1364 cw[1] = (met->lon[ci[1] + 1] - lon2)
1365 / (met->lon[ci[1] + 1] - met->lon[ci[1]]);
1366 cw[2] = (met->lat[ci[2] + 1] - lat2)
1367 / (met->lat[ci[2] + 1] - met->lat[ci[2]]);
1368 }
1369
1370 /* Interpolate vertically... */
1371 double aux00 =
1372 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
1373 + array[ci[1]][ci[2]][ci[0] + 1];
1374 double aux01 =
1375 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
1376 array[ci[1]][ci[2] + 1][ci[0] + 1])
1377 + array[ci[1]][ci[2] + 1][ci[0] + 1];
1378 double aux10 =
1379 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
1380 array[ci[1] + 1][ci[2]][ci[0] + 1])
1381 + array[ci[1] + 1][ci[2]][ci[0] + 1];
1382 double aux11 =
1383 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
1384 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
1385 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
1386
1387 /* Interpolate horizontally... */
1388 aux00 = cw[2] * (aux00 - aux01) + aux01;
1389 aux11 = cw[2] * (aux10 - aux11) + aux11;
1390 *var = cw[1] * (aux00 - aux11) + aux11;
1391}
int np
Number of pressure levels.
Definition: mptrac.h:3388
double p[EP]
Pressure levels [hPa].
Definition: mptrac.h:3400
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 1395 of file mptrac.c.

1402 {
1403
1404 /* Check longitude and latitude... */
1405 double lon2, lat2;
1406 intpol_check_lon_lat(met->lon, met->nx, met->lat, met->ny, lon, lat, &lon2,
1407 &lat2);
1408
1409 /* Get horizontal indices... */
1410 const int ix = locate_reg(met->lon, met->nx, lon2);
1411 const int iy = locate_irr(met->lat, met->ny, lat2);
1412
1413 /* Interpolate vertically... */
1414 int iz = locate_irr_float(zs[ix][iy], met->npl, z, 0);
1415 double aux00;
1416 if (z >= zs[ix][iy][iz + 1])
1417 aux00 = array[ix][iy][iz + 1];
1418 else if (z <= zs[ix][iy][iz])
1419 aux00 = array[ix][iy][iz];
1420 else
1421 aux00 = LIN(zs[ix][iy][iz], array[ix][iy][iz],
1422 zs[ix][iy][iz + 1], array[ix][iy][iz + 1], z);
1423
1424 iz = locate_irr_float(zs[ix][iy + 1], met->npl, z, iz);
1425 double aux01;
1426 if (z >= zs[ix][iy + 1][iz + 1])
1427 aux01 = array[ix][iy + 1][iz + 1];
1428 else if (z <= zs[ix][iy + 1][iz])
1429 aux01 = array[ix][iy + 1][iz];
1430 else
1431 aux01 = LIN(zs[ix][iy + 1][iz], array[ix][iy + 1][iz],
1432 zs[ix][iy + 1][iz + 1], array[ix][iy + 1][iz + 1], z);
1433
1434 iz = locate_irr_float(zs[ix + 1][iy], met->npl, z, iz);
1435 double aux10;
1436 if (z >= zs[ix + 1][iy][iz + 1])
1437 aux10 = array[ix + 1][iy][iz + 1];
1438 else if (z <= zs[ix + 1][iy][iz])
1439 aux10 = array[ix + 1][iy][iz];
1440 else
1441 aux10 = LIN(zs[ix + 1][iy][iz], array[ix + 1][iy][iz],
1442 zs[ix + 1][iy][iz + 1], array[ix + 1][iy][iz + 1], z);
1443
1444 iz = locate_irr_float(zs[ix + 1][iy + 1], met->npl, z, iz);
1445 double aux11;
1446 if (z >= zs[ix + 1][iy + 1][iz + 1])
1447 aux11 = array[ix + 1][iy + 1][iz + 1];
1448 else if (z <= zs[ix + 1][iy + 1][iz])
1449 aux11 = array[ix + 1][iy + 1][iz];
1450 else
1451 aux11 = LIN(zs[ix + 1][iy + 1][iz], array[ix + 1][iy + 1][iz],
1452 zs[ix + 1][iy + 1][iz + 1], array[ix + 1][iy + 1][iz + 1], z);
1453
1454 /* Interpolate horizontally... */
1455 double aux0 = LIN(met->lat[iy], aux00, met->lat[iy + 1], aux01, lat2);
1456 double aux1 = LIN(met->lat[iy], aux10, met->lat[iy + 1], aux11, lat2);
1457 *var = LIN(met->lon[ix], aux0, met->lon[ix + 1], aux1, lon2);
1458}
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:2011
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 1462 of file mptrac.c.

1470 {
1471
1472 /* Initialize interpolation... */
1473 if (init) {
1474
1475 /* Check longitude and latitude... */
1476 double lon2, lat2;
1477 intpol_check_lon_lat(met->lon, met->nx, met->lat, met->ny, lon, lat,
1478 &lon2, &lat2);
1479
1480 /* Get interpolation indices... */
1481 ci[1] = locate_reg(met->lon, met->nx, lon2);
1482 ci[2] = locate_irr(met->lat, met->ny, lat2);
1483
1484 /* Get interpolation weights... */
1485 cw[1] = (met->lon[ci[1] + 1] - lon2)
1486 / (met->lon[ci[1] + 1] - met->lon[ci[1]]);
1487 cw[2] = (met->lat[ci[2] + 1] - lat2)
1488 / (met->lat[ci[2] + 1] - met->lat[ci[2]]);
1489 }
1490
1491 /* Set variables... */
1492 double aux00 = array[ci[1]][ci[2]];
1493 double aux01 = array[ci[1]][ci[2] + 1];
1494 double aux10 = array[ci[1] + 1][ci[2]];
1495 double aux11 = array[ci[1] + 1][ci[2] + 1];
1496
1497 /* Interpolate horizontally... */
1498 if (isfinite(aux00) && isfinite(aux01)
1499 && isfinite(aux10) && isfinite(aux11)) {
1500 aux00 = cw[2] * (aux00 - aux01) + aux01;
1501 aux11 = cw[2] * (aux10 - aux11) + aux11;
1502 *var = cw[1] * (aux00 - aux11) + aux11;
1503 } else {
1504 if (cw[2] < 0.5) {
1505 if (cw[1] < 0.5)
1506 *var = aux11;
1507 else
1508 *var = aux01;
1509 } else {
1510 if (cw[1] < 0.5)
1511 *var = aux10;
1512 else
1513 *var = aux00;
1514 }
1515 }
1516}
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 1520 of file mptrac.c.

1532 {
1533
1534 double var0, var1;
1535
1536 /* Spatial interpolation... */
1537 intpol_met_space_3d(met0, array0, p, lon, lat, &var0, ci, cw, init);
1538 intpol_met_space_3d(met1, array1, p, lon, lat, &var1, ci, cw, 0);
1539
1540 /* Get weighting factor... */
1541 const double wt = (met1->time - ts) / (met1->time - met0->time);
1542
1543 /* Interpolate... */
1544 *var = wt * (var0 - var1) + var1;
1545}
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 1549 of file mptrac.c.

1560 {
1561
1562 double var0, var1;
1563
1564 /* Spatial interpolation... */
1565 intpol_met_space_3d_ml(met0, zs0, array0, p, lon, lat, &var0);
1566 intpol_met_space_3d_ml(met1, zs1, array1, p, lon, lat, &var1);
1567
1568 /* Interpolate... */
1569 *var = LIN(met0->time, var0, met1->time, var1, ts);
1570}
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:1395
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 1574 of file mptrac.c.

1585 {
1586
1587 double var0, var1;
1588
1589 /* Spatial interpolation... */
1590 intpol_met_space_2d(met0, array0, lon, lat, &var0, ci, cw, init);
1591 intpol_met_space_2d(met1, array1, lon, lat, &var1, ci, cw, 0);
1592
1593 /* Get weighting factor... */
1594 const double wt = (met1->time - ts) / (met1->time - met0->time);
1595
1596 /* Interpolate... */
1597 if (isfinite(var0) && isfinite(var1))
1598 *var = wt * (var0 - var1) + var1;
1599 else if (wt < 0.5)
1600 *var = var1;
1601 else
1602 *var = var0;
1603}
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 1607 of file mptrac.c.

1621 {
1622
1623 double aux0, aux1, aux00, aux01, aux10, aux11, mean = 0;
1624
1625 int n = 0;
1626
1627 /* Check longitude and latitude... */
1628 double lon2, lat2;
1629 intpol_check_lon_lat(lons, nlon, lats, nlat, lon, lat, &lon2, &lat2);
1630
1631 /* Get indices... */
1632 const int ix = locate_reg(lons, (int) nlon, lon2);
1633 const int iy = locate_irr(lats, (int) nlat, lat2);
1634
1635 /* Calculate standard deviation... */
1636 *sigma = 0;
1637 for (int dx = 0; dx < 2; dx++)
1638 for (int dy = 0; dy < 2; dy++) {
1639 if (isfinite(array0[ix + dx][iy + dy])) {
1640 mean += array0[ix + dx][iy + dy];
1641 *sigma += SQR(array0[ix + dx][iy + dy]);
1642 n++;
1643 }
1644 if (isfinite(array1[ix + dx][iy + dy])) {
1645 mean += array1[ix + dx][iy + dy];
1646 *sigma += SQR(array1[ix + dx][iy + dy]);
1647 n++;
1648 }
1649 }
1650 if (n > 0)
1651 *sigma = sqrt(MAX(*sigma / n - SQR(mean / n), 0.0));
1652
1653 /* Linear interpolation... */
1654 if (method == 1 && isfinite(array0[ix][iy])
1655 && isfinite(array0[ix][iy + 1])
1656 && isfinite(array0[ix + 1][iy])
1657 && isfinite(array0[ix + 1][iy + 1])
1658 && isfinite(array1[ix][iy])
1659 && isfinite(array1[ix][iy + 1])
1660 && isfinite(array1[ix + 1][iy])
1661 && isfinite(array1[ix + 1][iy + 1])) {
1662
1663 aux00 = LIN(lons[ix], array0[ix][iy],
1664 lons[ix + 1], array0[ix + 1][iy], lon2);
1665 aux01 = LIN(lons[ix], array0[ix][iy + 1],
1666 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
1667 aux0 = LIN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
1668
1669 aux10 = LIN(lons[ix], array1[ix][iy],
1670 lons[ix + 1], array1[ix + 1][iy], lon2);
1671 aux11 = LIN(lons[ix], array1[ix][iy + 1],
1672 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
1673 aux1 = LIN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
1674
1675 *var = LIN(time0, aux0, time1, aux1, time);
1676 }
1677
1678 /* Nearest neighbor interpolation... */
1679 else {
1680 aux00 = NN(lons[ix], array0[ix][iy],
1681 lons[ix + 1], array0[ix + 1][iy], lon2);
1682 aux01 = NN(lons[ix], array0[ix][iy + 1],
1683 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
1684 aux0 = NN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
1685
1686 aux10 = NN(lons[ix], array1[ix][iy],
1687 lons[ix + 1], array1[ix + 1][iy], lon2);
1688 aux11 = NN(lons[ix], array1[ix][iy + 1],
1689 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
1690 aux1 = NN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
1691
1692 *var = NN(time0, aux0, time1, aux1, time);
1693 }
1694}
#define NN(x0, y0, x1, y1, x)
Perform nearest-neighbor interpolation.
Definition: mptrac.h:1232
#define SQR(x)
Compute the square of a value.
Definition: mptrac.h:1557
Here is the call graph for this function:

◆ jsec2time()

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

Converts Julian seconds to calendar date and time components.

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

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

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

Author
Lars Hoffmann

Definition at line 1698 of file mptrac.c.

1706 {
1707
1708 struct tm t0, *t1;
1709
1710 t0.tm_year = 100;
1711 t0.tm_mon = 0;
1712 t0.tm_mday = 1;
1713 t0.tm_hour = 0;
1714 t0.tm_min = 0;
1715 t0.tm_sec = 0;
1716
1717 const time_t jsec0 = (time_t) jsec + timegm(&t0);
1718 t1 = gmtime(&jsec0);
1719
1720 *year = t1->tm_year + 1900;
1721 *mon = t1->tm_mon + 1;
1722 *day = t1->tm_mday;
1723 *hour = t1->tm_hour;
1724 *min = t1->tm_min;
1725 *sec = t1->tm_sec;
1726 *remain = jsec - floor(jsec);
1727}

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

1735 {
1736
1737 /* Check number of data points... */
1738 if (nk < 2)
1739 return 1.0;
1740
1741 /* Get altitude... */
1742 const double z = Z(p);
1743
1744 /* Get weighting factor... */
1745 if (z < kz[0])
1746 return kw[0];
1747 else if (z > kz[nk - 1])
1748 return kw[nk - 1];
1749 else {
1750 int idx = locate_irr(kz, nk, z);
1751 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
1752 }
1753}
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 1757 of file mptrac.c.

1759 {
1760
1761 /*
1762 Calculate moist adiabatic lapse rate [K/km] from temperature [K]
1763 and water vapor volume mixing ratio [1].
1764
1765 Reference: https://en.wikipedia.org/wiki/Lapse_rate
1766 */
1767
1768 const double a = RA * SQR(t), r = SH(h2o) / (1. - SH(h2o));
1769
1770 return 1e3 * G0 * (a + LV * r * t) / (CPD * a + SQR(LV) * r * EPS);
1771}
#define SH(h2o)
Compute specific humidity from water vapor volume mixing ratio.
Definition: mptrac.h:1544
#define LV
Latent heat of vaporization of water [J/kg].
Definition: mptrac.h:182
#define EPS
Ratio of the specific gas constant of dry air and water vapor [1].
Definition: mptrac.h:167
#define CPD
Specific heat of dry air at constant pressure [J/(kg K)].
Definition: mptrac.h:162

◆ level_definitions()

void level_definitions ( ctl_t ctl)

Defines pressure levels for meteorological data.

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

Parameters
ctlControl structure containing information about pressure level definitions.

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

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

Definition at line 1775 of file mptrac.c.

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

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

1984 {
1985
1986 int ilo = 0;
1987 int ihi = n - 1;
1988 int i = (ihi + ilo) >> 1;
1989
1990 if (xx[i] < xx[i + 1])
1991 while (ihi > ilo + 1) {
1992 i = (ihi + ilo) >> 1;
1993 if (xx[i] > x)
1994 ihi = i;
1995 else
1996 ilo = i;
1997 } else
1998 while (ihi > ilo + 1) {
1999 i = (ihi + ilo) >> 1;
2000 if (xx[i] <= x)
2001 ihi = i;
2002 else
2003 ilo = i;
2004 }
2005
2006 return ilo;
2007}

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

2015 {
2016
2017 int ilo = 0;
2018 int ihi = n - 1;
2019 int i = (ihi + ilo) >> 1;
2020
2021 if (x >= xx[ig] && x < xx[ig + 1])
2022 return ig;
2023
2024 if (xx[i] < xx[i + 1])
2025 while (ihi > ilo + 1) {
2026 i = (ihi + ilo) >> 1;
2027 if (xx[i] > x)
2028 ihi = i;
2029 else
2030 ilo = i;
2031 } else
2032 while (ihi > ilo + 1) {
2033 i = (ihi + ilo) >> 1;
2034 if (xx[i] <= x)
2035 ihi = i;
2036 else
2037 ilo = i;
2038 }
2039
2040 return ilo;
2041}

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

2048 {
2049
2050 /* Calculate index... */
2051 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2052
2053 /* Check range... */
2054 if (i < 0)
2055 return 0;
2056 else if (i > n - 2)
2057 return n - 2;
2058 else
2059 return i;
2060}

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

2070 {
2071
2072 ind[0] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind],
2073 np, height_ap, 0);
2074 ind[1] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind],
2075 np, height_ap, ind[0]);
2076 ind[2] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind + 1],
2077 np, height_ap, ind[1]);
2078 ind[3] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind + 1],
2079 np, height_ap, ind[2]);
2080}
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 2084 of file mptrac.c.

2089 {
2090
2091 /* Set timer... */
2092 SELECT_TIMER("MODULE_ADVECT", "PHYSICS", NVTX_GPU);
2093
2094 /* Use omega vertical velocity... */
2095 if (ctl->advect_vert_coord == 0 || ctl->advect_vert_coord == 2) {
2096
2097 /* Loop over particles... */
2098 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2099
2100 /* Init... */
2102 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
2103 x[3] = { 0, 0, 0 };
2104
2105 /* Loop over integration nodes... */
2106 for (int i = 0; i < ctl->advect; i++) {
2107
2108 /* Set position... */
2109 if (i == 0) {
2110 dts = 0.0;
2111 x[0] = atm->lon[ip];
2112 x[1] = atm->lat[ip];
2113 x[2] = atm->p[ip];
2114 } else {
2115 dts = (i == 3 ? 1.0 : 0.5) * cache->dt[ip];
2116 x[0] = atm->lon[ip] + DX2DEG(dts * u[i - 1] / 1000., atm->lat[ip]);
2117 x[1] = atm->lat[ip] + DY2DEG(dts * v[i - 1] / 1000.);
2118 x[2] = atm->p[ip] + dts * w[i - 1];
2119 }
2120 const double tm = atm->time[ip] + dts;
2121
2122 /* Interpolate meteo data on pressure levels... */
2123 if (ctl->advect_vert_coord == 0) {
2124 intpol_met_time_3d(met0, met0->u, met1, met1->u,
2125 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2126 intpol_met_time_3d(met0, met0->v, met1, met1->v,
2127 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2128 intpol_met_time_3d(met0, met0->w, met1, met1->w,
2129 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
2130 }
2131
2132 /* Interpolate meteo data on model levels... */
2133 else {
2134 intpol_met_time_3d_ml(met0, met0->pl, met0->ul,
2135 met1, met1->pl, met1->ul,
2136 tm, x[2], x[0], x[1], &u[i]);
2137 intpol_met_time_3d_ml(met0, met0->pl, met0->vl,
2138 met1, met1->pl, met1->vl,
2139 tm, x[2], x[0], x[1], &v[i]);
2140 intpol_met_time_3d_ml(met0, met0->pl, met0->wl,
2141 met1, met1->pl, met1->wl,
2142 tm, x[2], x[0], x[1], &w[i]);
2143 }
2144
2145 /* Get mean wind... */
2146 double k = 1.0;
2147 if (ctl->advect == 2)
2148 k = (i == 0 ? 0.0 : 1.0);
2149 else if (ctl->advect == 4)
2150 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2151 um += k * u[i];
2152 vm += k * v[i];
2153 wm += k * w[i];
2154 }
2155
2156 /* Set new position... */
2157 atm->time[ip] += cache->dt[ip];
2158 atm->lon[ip] += DX2DEG(cache->dt[ip] * um / 1000.,
2159 (ctl->advect == 2 ? x[1] : atm->lat[ip]));
2160 atm->lat[ip] += DY2DEG(cache->dt[ip] * vm / 1000.);
2161 atm->p[ip] += cache->dt[ip] * wm;
2162 }
2163 }
2164
2165 /* Use zetadot vertical velocity... */
2166 else if (ctl->advect_vert_coord == 1) {
2167
2168 /* Loop over particles... */
2169 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2170
2171 /* Convert pressure to zeta... */
2173
2174 // TODO: can we use intpol_met_time_3d_ml instead of intpol_met_4d_coord?
2175
2176 intpol_met_4d_coord(met0, met0->pl, met0->zetal, met1,
2177 met1->pl, met1->zetal, atm->time[ip], atm->p[ip],
2178 atm->lon[ip], atm->lat[ip],
2179 &atm->q[ctl->qnt_zeta][ip], ci, cw, 1);
2180
2181 /* Init... */
2182 double dts, u[4], um = 0, v[4], vm = 0, zeta_dot[4],
2183 zeta_dotm = 0, x[3] = { 0, 0, 0 };
2184
2185 /* Loop over integration nodes... */
2186 for (int i = 0; i < ctl->advect; i++) {
2187
2188 /* Set position... */
2189 if (i == 0) {
2190 dts = 0.0;
2191 x[0] = atm->lon[ip];
2192 x[1] = atm->lat[ip];
2193 x[2] = atm->q[ctl->qnt_zeta][ip];
2194 } else {
2195 dts = (i == 3 ? 1.0 : 0.5) * cache->dt[ip];
2196 x[0] = atm->lon[ip] + DX2DEG(dts * u[i - 1] / 1000., atm->lat[ip]);
2197 x[1] = atm->lat[ip] + DY2DEG(dts * v[i - 1] / 1000.);
2198 x[2] = atm->q[ctl->qnt_zeta][ip] + dts * zeta_dot[i - 1];
2199 }
2200 const double tm = atm->time[ip] + dts;
2201
2202 /* Interpolate meteo data... */
2203 intpol_met_4d_coord(met0, met0->zetal, met0->ul, met1, met1->zetal,
2204 met1->ul, tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2205 intpol_met_4d_coord(met0, met0->zetal, met0->vl, met1, met1->zetal,
2206 met1->vl, tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2207 intpol_met_4d_coord(met0, met0->zetal, met0->zeta_dotl, met1,
2208 met1->zetal, met1->zeta_dotl, tm, x[2], x[0],
2209 x[1], &zeta_dot[i], ci, cw, 0);
2210
2211 /* Get mean wind... */
2212 double k = 1.0;
2213 if (ctl->advect == 2)
2214 k = (i == 0 ? 0.0 : 1.0);
2215 else if (ctl->advect == 4)
2216 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2217 um += k * u[i];
2218 vm += k * v[i];
2219 zeta_dotm += k * zeta_dot[i];
2220 }
2221
2222 /* Set new position... */
2223 atm->time[ip] += cache->dt[ip];
2224 atm->lon[ip] += DX2DEG(cache->dt[ip] * um / 1000.,
2225 (ctl->advect == 2 ? x[1] : atm->lat[ip]));
2226 atm->lat[ip] += DY2DEG(cache->dt[ip] * vm / 1000.);
2227 atm->q[ctl->qnt_zeta][ip] += cache->dt[ip] * zeta_dotm;
2228
2229 /* Convert zeta to pressure... */
2230 intpol_met_4d_coord(met0, met0->zetal, met0->pl, met1, met1->zetal,
2231 met1->pl, atm->time[ip], atm->q[ctl->qnt_zeta][ip],
2232 atm->lon[ip], atm->lat[ip], &atm->p[ip], ci, cw, 1);
2233 }
2234 }
2235}
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:1165
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:1520
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:1549
#define PARTICLE_LOOP(ip0, ip1, check_dt,...)
Loop over particle indices with OpenACC acceleration.
Definition: mptrac.h:1274
#define DX2DEG(dx, lat)
Convert a distance in kilometers to degrees longitude at a given latitude.
Definition: mptrac.h:525
#define SELECT_TIMER(id, group, color)
Select and start a timer with specific attributes.
Definition: mptrac.h:1984
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
Definition: mptrac.h:543
double time[NP]
Time [s].
Definition: mptrac.h:3155
double lat[NP]
Latitude [deg].
Definition: mptrac.h:3164
double lon[NP]
Longitude [deg].
Definition: mptrac.h:3161
int np
Number of air parcels.
Definition: mptrac.h:3152
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
Definition: mptrac.h:3167
double p[NP]
Pressure [hPa].
Definition: mptrac.h:3158
double dt[NP]
Timesteps [s].
Definition: mptrac.h:3198
int advect
Advection scheme (0=off, 1=Euler, 2=midpoint, 4=Runge-Kutta).
Definition: mptrac.h:2652
int qnt_zeta
Quantity array index for zeta vertical coordinate.
Definition: mptrac.h:2372
int advect_vert_coord
Vertical velocity of air parcels (0=omega_on_plev, 1=zetadot_on_mlev, 2=omega_on_mlev).
Definition: mptrac.h:2656
float zeta_dotl[EX][EY][EP]
Vertical velocity on model levels [K/s].
Definition: mptrac.h:3532
float w[EX][EY][EP]
Vertical velocity [hPa/s].
Definition: mptrac.h:3490
float wl[EX][EY][EP]
Vertical velocity on model levels [hPa/s].
Definition: mptrac.h:3526
float vl[EX][EY][EP]
Meridional wind on model levels [m/s].
Definition: mptrac.h:3523
float u[EX][EY][EP]
Zonal wind [m/s].
Definition: mptrac.h:3484
float ul[EX][EY][EP]
Zonal wind on model levels [m/s].
Definition: mptrac.h:3520
float v[EX][EY][EP]
Meridional wind [m/s].
Definition: mptrac.h:3487
float pl[EX][EY][EP]
Pressure on model levels [hPa].
Definition: mptrac.h:3517
float zetal[EX][EY][EP]
Zeta on model levels [K].
Definition: mptrac.h:3529
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 2239 of file mptrac.c.

2244 {
2245
2246 /* Check parameters... */
2247 if (ctl->advect_vert_coord != 1)
2248 return;
2249
2250 /* Set timer... */
2251 SELECT_TIMER("MODULE_ADVECT_INIT", "PHYSICS", NVTX_GPU);
2252
2253 /* Loop over particles... */
2254 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,met0,met1,atm)") {
2255
2256 /* Initialize pressure consistent with zeta... */
2258 intpol_met_4d_coord(met0, met0->zetal, met0->pl, met1, met1->zetal,
2259 met1->pl, atm->time[ip], atm->q[ctl->qnt_zeta][ip],
2260 atm->lon[ip], atm->lat[ip], &atm->p[ip], ci, cw, 1);
2261 }
2262}
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 2266 of file mptrac.c.

2272 {
2273
2274 /* Set timer... */
2275 SELECT_TIMER("MODULE_BOUND_COND", "PHYSICS", NVTX_GPU);
2276
2277 /* Check quantity flags... */
2278 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0 && ctl->qnt_Cccl4
2279 && ctl->qnt_Cccl3f < 0 && ctl->qnt_Cccl2f2 < 0
2280 && ctl->qnt_Cn2o < 0 && ctl->qnt_Csf6 < 0 && ctl->qnt_aoa < 0)
2281 return;
2282
2283 /* Loop over particles... */
2284 PARTICLE_LOOP(0, atm->np, 1,
2285 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2286
2287 /* Check latitude and pressure range... */
2288 if (atm->lat[ip] < ctl->bound_lat0 || atm->lat[ip] > ctl->bound_lat1
2289 || atm->p[ip] > ctl->bound_p0 || atm->p[ip] < ctl->bound_p1)
2290 continue;
2291
2292 /* Check surface layer... */
2293 if (ctl->bound_dps > 0 || ctl->bound_dzs > 0
2294 || ctl->bound_zetas > 0 || ctl->bound_pbl) {
2295
2296 /* Get surface pressure... */
2297 double ps;
2299 INTPOL_2D(ps, 1);
2300
2301 /* Check pressure... */
2302 if (ctl->bound_dps > 0 && atm->p[ip] < ps - ctl->bound_dps)
2303 continue;
2304
2305 /* Check height... */
2306 if (ctl->bound_dzs > 0 && Z(atm->p[ip]) > Z(ps) + ctl->bound_dzs)
2307 continue;
2308
2309 /* Check zeta range... */
2310 if (ctl->bound_zetas > 0) {
2311 double t;
2312 INTPOL_3D(t, 1);
2313 if (ZETA(ps, atm->p[ip], t) > ctl->bound_zetas)
2314 continue;
2315 }
2316
2317 /* Check planetary boundary layer... */
2318 if (ctl->bound_pbl) {
2319 double pbl;
2320 INTPOL_2D(pbl, 0);
2321 if (atm->p[ip] < pbl)
2322 continue;
2323 }
2324 }
2325
2326 /* Set mass and volume mixing ratio... */
2327 if (ctl->qnt_m >= 0 && ctl->bound_mass >= 0)
2328 atm->q[ctl->qnt_m][ip] =
2329 ctl->bound_mass + ctl->bound_mass_trend * atm->time[ip];
2330 if (ctl->qnt_vmr >= 0 && ctl->bound_vmr >= 0)
2331 atm->q[ctl->qnt_vmr][ip] =
2332 ctl->bound_vmr + ctl->bound_vmr_trend * atm->time[ip];
2333
2334 /* Set CFC-10 volume mixing ratio... */
2335 if (ctl->qnt_Cccl4 >= 0 && ctl->clim_ccl4_timeseries[0] != '-')
2336 atm->q[ctl->qnt_Cccl4][ip] = clim_ts(&clim->ccl4, atm->time[ip]);
2337
2338 /* Set CFC-11 volume mixing ratio... */
2339 if (ctl->qnt_Cccl3f >= 0 && ctl->clim_ccl3f_timeseries[0] != '-')
2340 atm->q[ctl->qnt_Cccl3f][ip] = clim_ts(&clim->ccl3f, atm->time[ip]);
2341
2342 /* Set CFC-12 volume mixing ratio... */
2343 if (ctl->qnt_Cccl2f2 >= 0 && ctl->clim_ccl2f2_timeseries[0] != '-')
2344 atm->q[ctl->qnt_Cccl2f2][ip] = clim_ts(&clim->ccl2f2, atm->time[ip]);
2345
2346 /* Set N2O volume mixing ratio... */
2347 if (ctl->qnt_Cn2o >= 0 && ctl->clim_n2o_timeseries[0] != '-')
2348 atm->q[ctl->qnt_Cn2o][ip] = clim_ts(&clim->n2o, atm->time[ip]);
2349
2350 /* Set SF6 volume mixing ratio... */
2351 if (ctl->qnt_Csf6 >= 0 && ctl->clim_sf6_timeseries[0] != '-')
2352 atm->q[ctl->qnt_Csf6][ip] = clim_ts(&clim->sf6, atm->time[ip]);
2353
2354 /* Set age of air... */
2355 if (ctl->qnt_aoa >= 0)
2356 atm->q[ctl->qnt_aoa][ip] = atm->time[ip];
2357 }
2358}
double clim_ts(const clim_ts_t *ts, const double t)
Interpolates a time series of climatological variables.
Definition: mptrac.c:383
#define INTPOL_3D(var, init)
Perform 3D interpolation for a meteorological variable.
Definition: mptrac.h:713
#define ZETA(ps, p, t)
Computes the value of the zeta vertical coordinate.
Definition: mptrac.h:1791
#define INTPOL_2D(var, init)
Perform 2D interpolation for a meteorological variable.
Definition: mptrac.h:696
clim_ts_t ccl2f2
CFC-12 time series.
Definition: mptrac.h:3359
clim_ts_t sf6
SF6 time series.
Definition: mptrac.h:3365
clim_ts_t ccl4
CFC-10 time series.
Definition: mptrac.h:3353
clim_ts_t ccl3f
CFC-11 time series.
Definition: mptrac.h:3356
clim_ts_t n2o
N2O time series.
Definition: mptrac.h:3362
int qnt_Cccl2f2
Quantity array index for CFC-12 volume mixing ratio (chemistry code).
Definition: mptrac.h:2441
int qnt_m
Quantity array index for mass.
Definition: mptrac.h:2189
int qnt_aoa
Quantity array index for age of air.
Definition: mptrac.h:2450
char clim_n2o_timeseries[LEN]
Filename of N2O time series.
Definition: mptrac.h:2782
double bound_dzs
Boundary conditions surface layer depth [km].
Definition: mptrac.h:2731
int qnt_Cccl4
Quantity array index for CFC-10 volume mixing ratio (chemistry code).
Definition: mptrac.h:2435
double bound_mass
Boundary conditions mass per particle [kg].
Definition: mptrac.h:2704
int qnt_vmr
Quantity array index for volume mixing ratio.
Definition: mptrac.h:2192
double bound_lat1
Boundary conditions maximum longitude [deg].
Definition: mptrac.h:2719
int bound_pbl
Boundary conditions planetary boundary layer (0=no, 1=yes).
Definition: mptrac.h:2737
double bound_p1
Boundary conditions top pressure [hPa].
Definition: mptrac.h:2725
double bound_vmr
Boundary conditions volume mixing ratio [ppv].
Definition: mptrac.h:2710
double bound_lat0
Boundary conditions minimum longitude [deg].
Definition: mptrac.h:2716
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
Definition: mptrac.h:2713
int qnt_Cn2o
Quantity array index for N2O volume mixing ratio (chemistry code).
Definition: mptrac.h:2444
int qnt_Cccl3f
Quantity array index for CFC-11 volume mixing ratio (chemistry code).
Definition: mptrac.h:2438
int qnt_Csf6
Quantity array index for SF6 volume mixing ratio (chemistry code).
Definition: mptrac.h:2447
double bound_dps
Boundary conditions surface layer depth [hPa].
Definition: mptrac.h:2728
double bound_mass_trend
Boundary conditions mass per particle trend [kg/s].
Definition: mptrac.h:2707
double bound_p0
Boundary conditions bottom pressure [hPa].
Definition: mptrac.h:2722
char clim_ccl4_timeseries[LEN]
Filename of CFC-10 time series.
Definition: mptrac.h:2773
char clim_sf6_timeseries[LEN]
Filename of SF6 time series.
Definition: mptrac.h:2785
char clim_ccl3f_timeseries[LEN]
Filename of CFC-11 time series.
Definition: mptrac.h:2776
char clim_ccl2f2_timeseries[LEN]
Filename of CFC-12 time series.
Definition: mptrac.h:2779
double bound_zetas
Boundary conditions surface layer zeta [K].
Definition: mptrac.h:2734
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 2362 of file mptrac.c.

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

◆ module_chem_init()

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

Initializes the chemistry modules by setting atmospheric composition.

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

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

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

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

Definition at line 2509 of file mptrac.c.

2515 {
2516
2517 /* Set timer... */
2518 SELECT_TIMER("MODULE_CHEM_INIT", "PHYSICS", NVTX_GPU);
2519
2520 /* Loop over particles... */
2521 PARTICLE_LOOP(0, atm->np, 0,
2522 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2523
2524 /* Set H2O and O3 using meteo data... */
2526 if (ctl->qnt_Ch2o >= 0) {
2527 double h2o;
2528 INTPOL_3D(h2o, 1);
2529 SET_ATM(qnt_Ch2o, h2o);
2530 }
2531 if (ctl->qnt_Co3 >= 0) {
2532 double o3;
2533 INTPOL_3D(o3, 1);
2534 SET_ATM(qnt_Co3, o3);
2535 }
2536
2537 /* Set radical species... */
2538 SET_ATM(qnt_Coh, clim_oh(ctl, clim, atm->time[ip],
2539 atm->lon[ip], atm->lat[ip], atm->p[ip]));
2540 SET_ATM(qnt_Cho2, clim_zm(&clim->ho2, atm->time[ip],
2541 atm->lat[ip], atm->p[ip]));
2542 SET_ATM(qnt_Ch2o2, clim_zm(&clim->h2o2, atm->time[ip],
2543 atm->lat[ip], atm->p[ip]));
2544 SET_ATM(qnt_Co1d, clim_zm(&clim->o1d, atm->time[ip],
2545 atm->lat[ip], atm->p[ip]));
2546 }
2547}
double clim_oh(const ctl_t *ctl, const clim_t *clim, const double t, const double lon, const double lat, const double p)
Calculates the hydroxyl radical (OH) concentration from climatology data, with an optional diurnal co...
Definition: mptrac.c:89
#define SET_ATM(qnt, val)
Set atmospheric quantity value.
Definition: mptrac.h:1500
clim_zm_t ho2
HO2 zonal means.
Definition: mptrac.h:3347
clim_zm_t o1d
O(1D) zonal means.
Definition: mptrac.h:3350
clim_zm_t h2o2
H2O2 zonal means.
Definition: mptrac.h:3344
int qnt_Ch2o
Quantity array index for H2O volume mixing ratio (chemistry code).
Definition: mptrac.h:2408
int qnt_Co3
Quantity array index for O3 volume mixing ratio (chemistry code).
Definition: mptrac.h:2411
Here is the call graph for this function:

◆ module_convection()

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

Performs convective mixing of atmospheric particles.

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

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

Definition at line 2551 of file mptrac.c.

2556 {
2557
2558 /* Set timer... */
2559 SELECT_TIMER("MODULE_CONVECTION", "PHYSICS", NVTX_GPU);
2560
2561 /* Create random numbers... */
2562 module_rng(ctl, cache->rs, (size_t) atm->np, 0);
2563
2564 /* Loop over particles... */
2565 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2566
2567 /* Interpolate CAPE... */
2568 double ps;
2570 INTPOL_2D(ps, 1);
2571
2572 /* Initialize pressure range for vertical mixing... */
2573 double pbot = ps, ptop = ps;
2574
2575 /* Mixing in the PBL... */
2576 if (ctl->conv_mix_pbl) {
2577
2578 /* Interpolate PBL... */
2579 double pbl;
2580 INTPOL_2D(pbl, 0);
2581
2582 /* Set pressure range... */
2583 ptop = pbl - ctl->conv_pbl_trans * (ps - pbl);
2584 }
2585
2586 /* Convective mixing... */
2587 if (ctl->conv_cape >= 0) {
2588
2589 /* Interpolate CAPE, CIN, and equilibrium level... */
2590 double cape, cin, pel;
2591 INTPOL_2D(cape, 0);
2592 INTPOL_2D(cin, 0);
2593 INTPOL_2D(pel, 0);
2594
2595 /* Set pressure range... */
2596 if (isfinite(cape) && cape >= ctl->conv_cape
2597 && (ctl->conv_cin <= 0 || (isfinite(cin) && cin >= ctl->conv_cin)))
2598 ptop = GSL_MIN(ptop, pel);
2599 }
2600
2601 /* Apply vertical mixing... */
2602 if (ptop != pbot && atm->p[ip] >= ptop) {
2603
2604 /* Get density range... */
2605 double tbot, ttop;
2606 intpol_met_time_3d(met0, met0->t, met1, met1->t, atm->time[ip],
2607 pbot, atm->lon[ip], atm->lat[ip], &tbot, ci, cw, 1);
2608 intpol_met_time_3d(met0, met0->t, met1, met1->t, atm->time[ip],
2609 ptop, atm->lon[ip], atm->lat[ip], &ttop, ci, cw, 1);
2610 const double rhobot = pbot / tbot;
2611 const double rhotop = ptop / ttop;
2612
2613 /* Get new density... */
2614 const double rho = rhobot + (rhotop - rhobot) * cache->rs[ip];
2615
2616 /* Get pressure... */
2617 atm->p[ip] = LIN(rhobot, pbot, rhotop, ptop, rho);
2618 }
2619 }
2620}
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:3692
double rs[3 *NP+1]
Random numbers.
Definition: mptrac.h:3195
double conv_cape
CAPE threshold for convection module [J/kg].
Definition: mptrac.h:2695
double conv_pbl_trans
Depth of PBL transition layer (fraction of PBL depth).
Definition: mptrac.h:2692
int conv_mix_pbl
Vertical mixing in the PBL (0=off, 1=on).
Definition: mptrac.h:2689
double conv_cin
CIN threshold for convection module [J/kg].
Definition: mptrac.h:2698
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 2624 of file mptrac.c.

2628 {
2629
2630 /* Set timer... */
2631 SELECT_TIMER("MODULE_DECAY", "PHYSICS", NVTX_GPU);
2632
2633 /* Check quantity flags... */
2634 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
2635 ERRMSG("Module needs quantity mass or volume mixing ratio!");
2636
2637 /* Loop over particles... */
2638 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,clim,atm)") {
2639
2640 /* Get weighting factor... */
2641 const double w = tropo_weight(clim, atm, ip);
2642
2643 /* Set lifetime... */
2644 const double tdec = w * ctl->tdec_trop + (1 - w) * ctl->tdec_strat;
2645
2646 /* Calculate exponential decay... */
2647 const double aux = exp(-cache->dt[ip] / tdec);
2648 if (ctl->qnt_m >= 0) {
2649 if (ctl->qnt_mloss_decay >= 0)
2650 atm->q[ctl->qnt_mloss_decay][ip]
2651 += atm->q[ctl->qnt_m][ip] * (1 - aux);
2652 atm->q[ctl->qnt_m][ip] *= aux;
2653 if (ctl->qnt_loss_rate >= 0)
2654 atm->q[ctl->qnt_loss_rate][ip] += 1. / tdec;
2655 }
2656 if (ctl->qnt_vmr >= 0)
2657 atm->q[ctl->qnt_vmr][ip] *= aux;
2658 }
2659}
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:9277
int qnt_loss_rate
Quantity array index for total loss rate.
Definition: mptrac.h:2348
int qnt_mloss_decay
Quantity array index for total mass loss due to exponential decay.
Definition: mptrac.h:2345
double tdec_strat
Life time of particles in the stratosphere [s].
Definition: mptrac.h:2749
double tdec_trop
Life time of particles in the troposphere [s].
Definition: mptrac.h:2746
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 2663 of file mptrac.c.

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

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

◆ module_diff_turb()

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

Applies turbulent diffusion processes to atmospheric particles.

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

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

The function performs the following operations:

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

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

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

Definition at line 2865 of file mptrac.c.

2871 {
2872
2873 /* Set timer... */
2874 SELECT_TIMER("MODULE_DIFF_TURB", "PHYSICS", NVTX_GPU);
2875
2876 /* Create random numbers... */
2877 module_rng(ctl, cache->rs, 3 * (size_t) atm->np, 1);
2878
2879 /* Loop over particles... */
2880 PARTICLE_LOOP(0, atm->np, 1,
2881 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2882
2883 /* Get PBL and surface pressure... */
2884 double pbl, ps;
2886 INTPOL_2D(pbl, 1);
2887 INTPOL_2D(ps, 0);
2888
2889 /* Get weighting factors... */
2890 const double wpbl = pbl_weight(ctl, atm, ip, pbl, ps);
2891 const double wtrop = tropo_weight(clim, atm, ip) * (1.0 - wpbl);
2892 const double wstrat = 1.0 - wpbl - wtrop;
2893
2894 /* Set diffusivity... */
2895 const double dx = wpbl * ctl->turb_dx_pbl + wtrop * ctl->turb_dx_trop
2896 + wstrat * ctl->turb_dx_strat;
2897 const double dz = wpbl * ctl->turb_dz_pbl + wtrop * ctl->turb_dz_trop
2898 + wstrat * ctl->turb_dz_strat;
2899
2900 /* Horizontal turbulent diffusion... */
2901 if (dx > 0) {
2902 const double sigma = sqrt(2.0 * dx * fabs(cache->dt[ip])) / 1000.;
2903 atm->lon[ip] += DX2DEG(cache->rs[3 * ip] * sigma, atm->lat[ip]);
2904 atm->lat[ip] += DY2DEG(cache->rs[3 * ip + 1] * sigma);
2905 }
2906
2907 /* Vertical turbulent diffusion... */
2908 if (dz > 0) {
2909 const double sigma = sqrt(2.0 * dz * fabs(cache->dt[ip])) / 1000.;
2910 atm->p[ip] += DZ2DP(cache->rs[3 * ip + 2] * sigma, atm->p[ip]);
2911 }
2912 }
2913}
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:5892
double turb_dz_trop
Vertical turbulent diffusion coefficient (troposphere) [m^2/s].
Definition: mptrac.h:2677
double turb_dx_strat
Horizontal turbulent diffusion coefficient (stratosphere) [m^2/s].
Definition: mptrac.h:2671
double turb_dx_trop
Horizontal turbulent diffusion coefficient (troposphere) [m^2/s].
Definition: mptrac.h:2668
double turb_dx_pbl
Horizontal turbulent diffusion coefficient (PBL) [m^2/s].
Definition: mptrac.h:2665
double turb_dz_strat
Vertical turbulent diffusion coefficient (stratosphere) [m^2/s].
Definition: mptrac.h:2680
double turb_dz_pbl
Vertical turbulent diffusion coefficient (PBL) [m^2/s].
Definition: mptrac.h:2674
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 2917 of file mptrac.c.

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

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

◆ module_isosurf_init()

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

Initialize the isosurface module based on atmospheric data.

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

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

Definition at line 3063 of file mptrac.c.

3068 {
3069
3070 double t;
3071
3072 /* Set timer... */
3073 SELECT_TIMER("MODULE_ISOSURF_INIT", "PHYSICS", NVTX_GPU);
3074
3075 /* Save pressure... */
3076 if (ctl->isosurf == 1) {
3077 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,atm)") {
3078 cache->iso_var[ip] = atm->p[ip];
3079 }
3080 }
3081
3082 /* Save density... */
3083 else if (ctl->isosurf == 2) {
3084 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,met0,met1,atm)") {
3086 INTPOL_3D(t, 1);
3087 cache->iso_var[ip] = atm->p[ip] / t;
3088 }
3089 }
3090
3091 /* Save potential temperature... */
3092 else if (ctl->isosurf == 3) {
3093 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,met0,met1,atm)") {
3095 INTPOL_3D(t, 1);
3096 cache->iso_var[ip] = THETA(atm->p[ip], t);
3097 }
3098 }
3099
3100 /* Read balloon pressure data... */
3101 else if (ctl->isosurf == 4) {
3102
3103 /* Write info... */
3104 LOG(1, "Read balloon pressure data: %s", ctl->balloon);
3105
3106 /* Open file... */
3107 FILE *in;
3108 if (!(in = fopen(ctl->balloon, "r")))
3109 ERRMSG("Cannot open file!");
3110
3111 /* Read pressure time series... */
3112 char line[LEN];
3113 while (fgets(line, LEN, in))
3114 if (sscanf(line, "%lg %lg", &(cache->iso_ts[cache->iso_n]),
3115 &(cache->iso_ps[cache->iso_n])) == 2)
3116 if ((++cache->iso_n) > NP)
3117 ERRMSG("Too many data points!");
3118
3119 /* Check number of points... */
3120 if (cache->iso_n < 1)
3121 ERRMSG("Could not read any data!");
3122
3123 /* Close file... */
3124 fclose(in);
3125
3126 /* Update of cache data on device... */
3127 mptrac_update_device(NULL, cache, NULL, NULL, NULL, NULL);
3128 }
3129}
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:5565
#define NP
Maximum number of atmospheric data points.
Definition: mptrac.h:246
double iso_ts[NP]
Isosurface balloon time [s].
Definition: mptrac.h:3186
int iso_n
Isosurface balloon number of data points.
Definition: mptrac.h:3189
double iso_ps[NP]
Isosurface balloon pressure [hPa].
Definition: mptrac.h:3183
double iso_var[NP]
Isosurface variables.
Definition: mptrac.h:3180
char balloon[LEN]
Balloon position filename.
Definition: mptrac.h:2649
int isosurf
Isosurface parameter (0=none, 1=pressure, 2=density, 3=theta, 4=balloon).
Definition: mptrac.h:2646
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 3133 of file mptrac.c.

3138 {
3139
3140 /* Set timer... */
3141 SELECT_TIMER("MODULE_ISOSURF", "PHYSICS", NVTX_GPU);
3142
3143 /* Loop over particles... */
3144 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,cache,met0,met1,atm)") {
3145
3146 /* Init... */
3147 double t;
3149
3150 /* Restore pressure... */
3151 if (ctl->isosurf == 1)
3152 atm->p[ip] = cache->iso_var[ip];
3153
3154 /* Restore density... */
3155 else if (ctl->isosurf == 2) {
3156 INTPOL_3D(t, 1);
3157 atm->p[ip] = cache->iso_var[ip] * t;
3158 }
3159
3160 /* Restore potential temperature... */
3161 else if (ctl->isosurf == 3) {
3162 INTPOL_3D(t, 1);
3163 atm->p[ip] = 1000. * pow(cache->iso_var[ip] / t, -1. / 0.286);
3164 }
3165
3166 /* Interpolate pressure... */
3167 else if (ctl->isosurf == 4) {
3168 if (atm->time[ip] <= cache->iso_ts[0])
3169 atm->p[ip] = cache->iso_ps[0];
3170 else if (atm->time[ip] >= cache->iso_ts[cache->iso_n - 1])
3171 atm->p[ip] = cache->iso_ps[cache->iso_n - 1];
3172 else {
3173 int idx = locate_irr(cache->iso_ts, cache->iso_n, atm->time[ip]);
3174 atm->p[ip] = LIN(cache->iso_ts[idx], cache->iso_ps[idx],
3175 cache->iso_ts[idx + 1], cache->iso_ps[idx + 1],
3176 atm->time[ip]);
3177 }
3178 }
3179 }
3180}
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 3238 of file mptrac.c.

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

◆ module_mixing()

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

Update atmospheric properties through interparcel mixing.

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

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

Definition at line 3342 of file mptrac.c.

3346 {
3347
3348 /* Set timer... */
3349 SELECT_TIMER("MODULE_MIXING", "PHYSICS", NVTX_GPU);
3350
3351 /* Allocate... */
3352 const int np = atm->np;
3353 int *restrict const ixs = (int *) malloc((size_t) np * sizeof(int));
3354 int *restrict const iys = (int *) malloc((size_t) np * sizeof(int));
3355 int *restrict const izs = (int *) malloc((size_t) np * sizeof(int));
3356
3357 /* Set grid box size... */
3358 const double dz = (ctl->mixing_z1 - ctl->mixing_z0) / ctl->mixing_nz;
3359 const double dlon = (ctl->mixing_lon1 - ctl->mixing_lon0) / ctl->mixing_nx;
3360 const double dlat = (ctl->mixing_lat1 - ctl->mixing_lat0) / ctl->mixing_ny;
3361
3362 /* Set time interval... */
3363 const double t0 = t - 0.5 * ctl->dt_mod;
3364 const double t1 = t + 0.5 * ctl->dt_mod;
3365
3366 /* Get indices... */
3367#ifdef _OPENACC
3368#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
3369#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
3370#pragma acc parallel loop independent gang vector
3371#else
3372#pragma omp parallel for default(shared)
3373#endif
3374 for (int ip = 0; ip < np; ip++) {
3375 ixs[ip] = (int) ((atm->lon[ip] - ctl->mixing_lon0) / dlon);
3376 iys[ip] = (int) ((atm->lat[ip] - ctl->mixing_lat0) / dlat);
3377 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->mixing_z0) / dz);
3378 if (atm->time[ip] < t0 || atm->time[ip] > t1
3379 || ixs[ip] < 0 || ixs[ip] >= ctl->mixing_nx
3380 || iys[ip] < 0 || iys[ip] >= ctl->mixing_ny
3381 || izs[ip] < 0 || izs[ip] >= ctl->mixing_nz)
3382 izs[ip] = -1;
3383 }
3384
3385 /* Calculate interparcel mixing... */
3386 if (ctl->qnt_m >= 0)
3387 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_m);
3388 if (ctl->qnt_vmr >= 0)
3389 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_vmr);
3390 if (ctl->qnt_Ch2o >= 0)
3391 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Ch2o);
3392 if (ctl->qnt_Co3 >= 0)
3393 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Co3);
3394 if (ctl->qnt_Cco >= 0)
3395 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cco);
3396 if (ctl->qnt_Coh >= 0)
3397 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Coh);
3398 if (ctl->qnt_Ch >= 0)
3399 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Ch);
3400 if (ctl->qnt_Cho2 >= 0)
3401 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cho2);
3402 if (ctl->qnt_Ch2o2 >= 0)
3403 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Ch2o2);
3404 if (ctl->qnt_Co1d >= 0)
3405 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Co1d);
3406 if (ctl->qnt_Co3p >= 0)
3407 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Co3p);
3408 if (ctl->qnt_Cccl4 >= 0)
3409 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cccl4);
3410 if (ctl->qnt_Cccl3f >= 0)
3411 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cccl3f);
3412 if (ctl->qnt_Cccl2f2 >= 0)
3413 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cccl2f2);
3414 if (ctl->qnt_Cn2o >= 0)
3415 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cn2o);
3416 if (ctl->qnt_Csf6 >= 0)
3417 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Csf6);
3418 if (ctl->qnt_aoa >= 0)
3419 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_aoa);
3420
3421 /* Free... */
3422#ifdef _OPENACC
3423#pragma acc exit data delete(ixs,iys,izs)
3424#endif
3425 free(ixs);
3426 free(iys);
3427 free(izs);
3428}
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:3432
int qnt_Coh
Quantity array index for OH volume mixing ratio (chemistry code).
Definition: mptrac.h:2417
int mixing_nx
Number of longitudes of mixing grid.
Definition: mptrac.h:2806
double mixing_z1
Upper altitude of mixing grid [km].
Definition: mptrac.h:2803
int qnt_Co1d
Quantity array index for O(1D) volume mixing ratio (chemistry code).
Definition: mptrac.h:2429
double mixing_z0
Lower altitude of mixing grid [km].
Definition: mptrac.h:2800
int qnt_Cco
Quantity array index for CO volume mixing ratio (chemistry code).
Definition: mptrac.h:2414
int mixing_ny
Number of latitudes of mixing grid.
Definition: mptrac.h:2815
int qnt_Ch
Quantity array index for H volume mixing ratio (chemistry code).
Definition: mptrac.h:2420
double mixing_lat0
Lower latitude of mixing grid [deg].
Definition: mptrac.h:2818
int qnt_Cho2
Quantity array index for HO2 volume mixing ratio (chemistry code).
Definition: mptrac.h:2423
int mixing_nz
Number of altitudes of mixing grid.
Definition: mptrac.h:2797
double mixing_lon0
Lower longitude of mixing grid [deg].
Definition: mptrac.h:2809
double mixing_lat1
Upper latitude of mixing grid [deg].
Definition: mptrac.h:2821
int qnt_Co3p
Quantity array index for O(3P) volume mixing ratio (chemistry code).
Definition: mptrac.h:2432
int qnt_Ch2o2
Quantity array index for H2O2 volume mixing ratio (chemistry code).
Definition: mptrac.h:2426
double mixing_lon1
Upper longitude of mixing grid [deg].
Definition: mptrac.h:2812
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 3432 of file mptrac.c.

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

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

◆ module_position()

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

Update the positions and pressure levels of atmospheric particles.

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

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

Definition at line 3610 of file mptrac.c.

3614 {
3615
3616 /* Set timer... */
3617 SELECT_TIMER("MODULE_POSITION", "PHYSICS", NVTX_GPU);
3618
3619 /* Loop over particles... */
3620 PARTICLE_LOOP(0, atm->np, 1, "acc data present(cache,met0,met1,atm)") {
3621
3622 /* Init... */
3623 double ps;
3625
3626 /* Calculate modulo... */
3627 atm->lon[ip] = FMOD(atm->lon[ip], 360.);
3628 atm->lat[ip] = FMOD(atm->lat[ip], 360.);
3629
3630 /* Check latitude... */
3631 while (atm->lat[ip] < -90 || atm->lat[ip] > 90) {
3632 if (atm->lat[ip] > 90) {
3633 atm->lat[ip] = 180 - atm->lat[ip];
3634 atm->lon[ip] += 180;
3635 }
3636 if (atm->lat[ip] < -90) {
3637 atm->lat[ip] = -180 - atm->lat[ip];
3638 atm->lon[ip] += 180;
3639 }
3640 }
3641
3642 /* Check longitude... */
3643 while (atm->lon[ip] < -180)
3644 atm->lon[ip] += 360;
3645 while (atm->lon[ip] >= 180)
3646 atm->lon[ip] -= 360;
3647
3648 /* Check pressure... */
3649 if (atm->p[ip] < met0->p[met0->np - 1]) {
3650 atm->p[ip] = met0->p[met0->np - 1];
3651 } else if (atm->p[ip] > 300.) {
3652 INTPOL_2D(ps, 1);
3653 if (atm->p[ip] > ps)
3654 atm->p[ip] = ps;
3655 }
3656 }
3657}

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

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

◆ module_rng()

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

Generate random numbers using various methods and distributions.

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

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

Definition at line 3692 of file mptrac.c.

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

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

3802 {
3803
3804 /* Set timer... */
3805 SELECT_TIMER("MODULE_SEDI", "PHYSICS", NVTX_GPU);
3806
3807 /* Loop over particles... */
3808 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
3809
3810 /* Get temperature... */
3811 double t;
3813 INTPOL_3D(t, 1);
3814
3815 /* Sedimentation velocity... */
3816 const double v_s = sedi(atm->p[ip], t, atm->q[ctl->qnt_rp][ip],
3817 atm->q[ctl->qnt_rhop][ip]);
3818
3819 /* Calculate pressure change... */
3820 atm->p[ip] += DZ2DP(v_s * cache->dt[ip] / 1000., atm->p[ip]);
3821 }
3822}
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 3826 of file mptrac.c.

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

◆ module_sort_help()

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

Reorder an array based on a given permutation.

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

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

Definition at line 3886 of file mptrac.c.

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

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

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

◆ module_timesteps_init()

void module_timesteps_init ( ctl_t ctl,
const atm_t atm 
)

Initialize start time and time interval for time-stepping.

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

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

Definition at line 3959 of file mptrac.c.

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

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

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

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

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

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

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

4248 {
4249
4250 /* Delete data region on GPU... */
4251#ifdef _OPENACC
4252 SELECT_TIMER("DELETE_DATA_REGION", "MEMORY", NVTX_GPU);
4253#pragma acc exit data delete (ctl,cache,clim,met0,met1,atm)
4254#endif
4255
4256 /* Free... */
4257 SELECT_TIMER("FREE", "MEMORY", NVTX_CPU);
4258 free(atm);
4259 free(ctl);
4260 free(cache);
4261 free(clim);
4262 free(met0);
4263 free(met1);
4264}

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

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

◆ mptrac_init()

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

Initializes the MPTRAC model and its associated components.

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

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

The function performs the following operations:

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

Definition at line 4389 of file mptrac.c.

4394 {
4395
4396 /* Initialize timesteps... */
4397 module_timesteps_init(ctl, atm);
4398
4399 /* Initialize random number generator... */
4400 module_rng_init(ntask);
4401
4402 /* Update GPU memory... */
4403 mptrac_update_device(ctl, cache, clim, NULL, NULL, atm);
4404}
void module_timesteps_init(ctl_t *ctl, const atm_t *atm)
Initialize start time and time interval for time-stepping.
Definition: mptrac.c:3959
void module_rng_init(const int ntask)
Initialize random number generators for parallel tasks.
Definition: mptrac.c:3661
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 4408 of file mptrac.c.

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

◆ mptrac_read_clim()

void mptrac_read_clim ( const ctl_t ctl,
clim_t clim 
)

Reads various climatological data and populates the given climatology structure.

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

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

This function performs the following steps:

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

The function utilizes several helper functions:

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

Definition at line 4479 of file mptrac.c.

4481 {
4482
4483 /* Set timer... */
4484 SELECT_TIMER("READ_CLIM", "INPUT", NVTX_READ);
4485
4486 /* Init tropopause climatology... */
4487 clim_tropo_init(clim);
4488
4489 /* Read photolysis rates... */
4490 if (ctl->clim_photo[0] != '-')
4491 read_clim_photo(ctl->clim_photo, &clim->photo);
4492
4493 /* Read HNO3 climatology... */
4494 if (ctl->clim_hno3_filename[0] != '-')
4495 read_clim_zm(ctl->clim_hno3_filename, "HNO3", &clim->hno3);
4496
4497 /* Read OH climatology... */
4498 if (ctl->clim_oh_filename[0] != '-') {
4499 read_clim_zm(ctl->clim_oh_filename, "OH", &clim->oh);
4500 if (ctl->oh_chem_beta > 0)
4501 clim_oh_diurnal_correction(ctl, clim);
4502 }
4503
4504 /* Read H2O2 climatology... */
4505 if (ctl->clim_h2o2_filename[0] != '-')
4506 read_clim_zm(ctl->clim_h2o2_filename, "H2O2", &clim->h2o2);
4507
4508 /* Read HO2 climatology... */
4509 if (ctl->clim_ho2_filename[0] != '-')
4510 read_clim_zm(ctl->clim_ho2_filename, "HO2", &clim->ho2);
4511
4512 /* Read O(1D) climatology... */
4513 if (ctl->clim_o1d_filename[0] != '-')
4514 read_clim_zm(ctl->clim_o1d_filename, "O1D", &clim->o1d);
4515
4516 /* Read CFC-10 time series... */
4517 if (ctl->clim_ccl4_timeseries[0] != '-')
4519
4520 /* Read CFC-11 time series... */
4521 if (ctl->clim_ccl3f_timeseries[0] != '-')
4523
4524 /* Read CFC-12 time series... */
4525 if (ctl->clim_ccl2f2_timeseries[0] != '-')
4527
4528 /* Read N2O time series... */
4529 if (ctl->clim_n2o_timeseries[0] != '-')
4530 read_clim_ts(ctl->clim_n2o_timeseries, &clim->n2o);
4531
4532 /* Read SF6 time series... */
4533 if (ctl->clim_sf6_timeseries[0] != '-')
4534 read_clim_ts(ctl->clim_sf6_timeseries, &clim->sf6);
4535}
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:6101
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:6220
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:6274
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:2764
char clim_o1d_filename[LEN]
Filename of O(1D) climatology.
Definition: mptrac.h:2767
char clim_photo[LEN]
Filename of photolysis rates climatology.
Definition: mptrac.h:2752
char clim_h2o2_filename[LEN]
Filename of H2O2 climatology.
Definition: mptrac.h:2761
char clim_oh_filename[LEN]
Filename of OH climatology.
Definition: mptrac.h:2758
char clim_hno3_filename[LEN]
Filename of HNO3 climatology.
Definition: mptrac.h:2755
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 4539 of file mptrac.c.

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

◆ mptrac_read_met()

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

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

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

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

Definition at line 5373 of file mptrac.c.

5377 {
5378
5379 /* Write info... */
5380 LOG(1, "Read meteo data: %s", filename);
5381
5382 /* Set rank... */
5383 int rank = 0;
5384#ifdef MPI
5385 if (ctl->met_mpi_share)
5386 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5387#endif
5388
5389 /* Check rank... */
5390 if (!ctl->met_mpi_share || rank == 0) {
5391
5392 /* Read netCDF data... */
5393 if (ctl->met_type == 0) {
5394 if (read_met_nc(filename, ctl, clim, met) != 1)
5395 return 0;
5396 }
5397
5398 /* Read binary data... */
5399 else if (ctl->met_type >= 1 && ctl->met_type <= 5) {
5400 if (read_met_bin(filename, ctl, met) != 1)
5401 return 0;
5402 }
5403
5404 /* Not implemented... */
5405 else
5406 ERRMSG("MET_TYPE not implemented!");
5407 }
5408
5409 /* Broadcast data via MPI... */
5410#ifdef MPI
5411 if (ctl->met_mpi_share) {
5412
5413 /* Set timer... */
5414 SELECT_TIMER("READ_MET_MPI_BCAST", "COMM", NVTX_SEND);
5415 LOG(2, "Broadcast data on rank %d...", rank);
5416
5417 /* Broadcast... */
5418 broadcast_large_data(met, sizeof(met_t));
5419 }
5420#endif
5421
5422 /* Return success... */
5423 return 1;
5424}
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:7581
int read_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a binary file.
Definition: mptrac.c:6414
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 5428 of file mptrac.c.

5435 {
5436
5437 /* Initialize modules... */
5438 if (t == ctl->t_start) {
5439
5440 /* Initialize isosurface data... */
5441 if (ctl->isosurf >= 1 && ctl->isosurf <= 4)
5442 module_isosurf_init(ctl, cache, *met0, *met1, atm);
5443
5444 /* Initialize advection... */
5445 module_advect_init(ctl, cache, *met0, *met1, atm);
5446
5447 /* Initialize chemistry... */
5448 module_chem_init(ctl, cache, clim, *met0, *met1, atm);
5449 }
5450
5451 /* Set time steps of air parcels... */
5452 module_timesteps(ctl, cache, *met0, atm, t);
5453
5454 /* Sort particles... */
5455 if (ctl->sort_dt > 0 && fmod(t, ctl->sort_dt) == 0)
5456 module_sort(ctl, *met0, atm);
5457
5458 /* Check positions (initial)... */
5459 module_position(cache, *met0, *met1, atm);
5460
5461 /* Advection... */
5462 if (ctl->advect > 0)
5463 module_advect(ctl, cache, *met0, *met1, atm);
5464
5465 /* Turbulent diffusion... */
5466 if (ctl->diffusion == 1
5467 && (ctl->turb_dx_pbl > 0 || ctl->turb_dz_pbl > 0
5468 || ctl->turb_dx_trop > 0 || ctl->turb_dz_trop > 0
5469 || ctl->turb_dx_strat > 0 || ctl->turb_dz_strat > 0))
5470 module_diff_turb(ctl, cache, clim, *met0, *met1, atm);
5471
5472 /* Mesoscale diffusion... */
5473 if (ctl->diffusion == 1 && (ctl->turb_mesox > 0 || ctl->turb_mesoz > 0))
5474 module_diff_meso(ctl, cache, *met0, *met1, atm);
5475
5476 /* Diffusion... */
5477 if (ctl->diffusion == 2)
5478 module_diff_pbl(ctl, cache, *met0, *met1, atm);
5479
5480 /* Convection... */
5481 if ((ctl->conv_mix_pbl || ctl->conv_cape >= 0)
5482 && (ctl->conv_dt <= 0 || fmod(t, ctl->conv_dt) == 0))
5483 module_convection(ctl, cache, *met0, *met1, atm);
5484
5485 /* Sedimentation... */
5486 if (ctl->qnt_rp >= 0 && ctl->qnt_rhop >= 0)
5487 module_sedi(ctl, cache, *met0, *met1, atm);
5488
5489 /* Isosurface... */
5490 if (ctl->isosurf >= 1 && ctl->isosurf <= 4)
5491 module_isosurf(ctl, cache, *met0, *met1, atm);
5492
5493 /* Check positions (final)... */
5494 module_position(cache, *met0, *met1, atm);
5495
5496 /* Interpolate meteo data... */
5497 if (ctl->met_dt_out > 0
5498 && (ctl->met_dt_out < ctl->dt_mod || fmod(t, ctl->met_dt_out) == 0))
5499 module_meteo(ctl, cache, clim, *met0, *met1, atm);
5500
5501 /* Check boundary conditions (initial)... */
5502 if ((ctl->bound_lat0 < ctl->bound_lat1)
5503 && (ctl->bound_p0 > ctl->bound_p1))
5504 module_bound_cond(ctl, cache, clim, *met0, *met1, atm);
5505
5506 /* Initialize quantity of total loss rate... */
5507 if (ctl->qnt_loss_rate >= 0) {
5508 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,atm)") {
5509 atm->q[ctl->qnt_loss_rate][ip] = 0;
5510 }
5511 }
5512
5513 /* Decay of particle mass... */
5514 if (ctl->tdec_trop > 0 && ctl->tdec_strat > 0)
5515 module_decay(ctl, cache, clim, atm);
5516
5517 /* Interparcel mixing... */
5518 if (ctl->mixing_trop >= 0 && ctl->mixing_strat >= 0
5519 && (ctl->mixing_dt <= 0 || fmod(t, ctl->mixing_dt) == 0))
5520 module_mixing(ctl, clim, atm, t);
5521
5522 /* Calculate the tracer vmr in the chemistry grid... */
5523 if (ctl->oh_chem_reaction != 0 || ctl->h2o2_chem_reaction != 0
5524 || (ctl->kpp_chem && fmod(t, ctl->dt_kpp) == 0))
5525 module_chem_grid(ctl, *met0, *met1, atm, t);
5526
5527 /* OH chemistry... */
5528 if (ctl->oh_chem_reaction != 0)
5529 module_oh_chem(ctl, cache, clim, *met0, *met1, atm);
5530
5531 /* H2O2 chemistry (for SO2 aqueous phase oxidation)... */
5532 if (ctl->h2o2_chem_reaction != 0)
5533 module_h2o2_chem(ctl, cache, clim, *met0, *met1, atm);
5534
5535 /* First-order tracer chemistry... */
5536 if (ctl->tracer_chem)
5537 module_tracer_chem(ctl, cache, clim, *met0, *met1, atm);
5538
5539 /* KPP chemistry... */
5540 if (ctl->kpp_chem && fmod(t, ctl->dt_kpp) == 0) {
5541#ifdef KPP
5542 module_kpp_chem(ctl, cache, clim, *met0, *met1, atm);
5543#else
5544 ERRMSG("Code was compiled without KPP!");
5545#endif
5546 }
5547
5548 /* Wet deposition... */
5549 if ((ctl->wet_depo_ic_a > 0 || ctl->wet_depo_ic_h[0] > 0)
5550 && (ctl->wet_depo_bc_a > 0 || ctl->wet_depo_bc_h[0] > 0))
5551 module_wet_depo(ctl, cache, *met0, *met1, atm);
5552
5553 /* Dry deposition... */
5554 if (ctl->dry_depo_vdep > 0)
5555 module_dry_depo(ctl, cache, *met0, *met1, atm);
5556
5557 /* Check boundary conditions (final)... */
5558 if ((ctl->bound_lat0 < ctl->bound_lat1)
5559 && (ctl->bound_p0 > ctl->bound_p1))
5560 module_bound_cond(ctl, cache, clim, *met0, *met1, atm);
5561}
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:2084
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:3922
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:3238
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:2624
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:2509
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:3342
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:3063
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:4060
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:2362
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:3797
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:2551
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:2266
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:2239
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:3610
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:2663
void module_sort(const ctl_t *ctl, met_t *met0, atm_t *atm)
Sort particles according to box index.
Definition: mptrac.c:3826
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:2865
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:3990
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:2980
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:2740
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:3133
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:3526
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:2917
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 5677 of file mptrac.c.

5681 {
5682
5683 /* Set timer... */
5684 SELECT_TIMER("WRITE_ATM", "OUTPUT", NVTX_WRITE);
5685
5686 /* Write info... */
5687 LOG(1, "Write atmospheric data: %s", filename);
5688
5689 /* Write ASCII data... */
5690 if (ctl->atm_type_out == 0)
5691 write_atm_asc(filename, ctl, atm, t);
5692
5693 /* Write binary data... */
5694 else if (ctl->atm_type_out == 1)
5695 write_atm_bin(filename, ctl, atm);
5696
5697 /* Write netCDF data... */
5698 else if (ctl->atm_type_out == 2)
5699 write_atm_nc(filename, ctl, atm);
5700
5701 /* Write CLaMS trajectory data... */
5702 else if (ctl->atm_type_out == 3)
5703 write_atm_clams_traj(filename, ctl, atm, t);
5704
5705 /* Write CLaMS pos data... */
5706 else if (ctl->atm_type_out == 4)
5707 write_atm_clams(filename, ctl, atm);
5708
5709 /* Error... */
5710 else
5711 ERRMSG("Atmospheric data type not supported!");
5712
5713 /* Write info... */
5714 double mini, maxi;
5715 LOG(2, "Number of particles: %d", atm->np);
5716 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
5717 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
5718 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
5719 LOG(2, "Altitude range: %g ... %g km", Z(maxi), Z(mini));
5720 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
5721 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
5722 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
5723 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
5724 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
5725 for (int iq = 0; iq < ctl->nq; iq++) {
5726 char msg[5 * LEN];
5727 sprintf(msg, "Quantity %s range: %s ... %s %s",
5728 ctl->qnt_name[iq], ctl->qnt_format[iq],
5729 ctl->qnt_format[iq], ctl->qnt_unit[iq]);
5730 gsl_stats_minmax(&mini, &maxi, atm->q[iq], 1, (size_t) atm->np);
5731 LOG(2, msg, mini, maxi);
5732 }
5733}
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:9485
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:9300
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:9432
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:9382
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:9643
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 5737 of file mptrac.c.

5740 {
5741
5742 /* Set timer... */
5743 SELECT_TIMER("WRITE_MET", "OUTPUT", NVTX_WRITE);
5744
5745 /* Write info... */
5746 LOG(1, "Write meteo data: %s", filename);
5747
5748 /* Check compression flags... */
5749#ifndef ZFP
5750 if (ctl->met_type == 3)
5751 ERRMSG("MPTRAC was compiled without zfp compression!");
5752#endif
5753#ifndef ZSTD
5754 if (ctl->met_type == 4)
5755 ERRMSG("MPTRAC was compiled without zstd compression!");
5756#endif
5757#ifndef CMS
5758 if (ctl->met_type == 5)
5759 ERRMSG("MPTRAC was compiled without cmultiscale compression!");
5760#endif
5761
5762 /* Write netCDF data... */
5763 if (ctl->met_type == 0)
5764 write_met_nc(filename, ctl, met);
5765
5766 /* Write binary data... */
5767 else if (ctl->met_type >= 1 && ctl->met_type <= 5)
5768 write_met_bin(filename, ctl, met);
5769
5770 /* Not implemented... */
5771 else
5772 ERRMSG("MET_TYPE not implemented!");
5773}
void write_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a NetCDF file.
Definition: mptrac.c:10682
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:10476
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 5777 of file mptrac.c.

5783 {
5784
5785 char ext[10], filename[2 * LEN];
5786
5787 double r;
5788
5789 int year, mon, day, hour, min, sec;
5790
5791 /* Get time... */
5792 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
5793
5794 /* Update host... */
5795 if ((ctl->atm_basename[0] != '-' && fmod(t, ctl->atm_dt_out) == 0)
5796 || (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0)
5797 || (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0)
5798 || ctl->csi_basename[0] != '-' || ctl->prof_basename[0] != '-'
5799 || ctl->sample_basename[0] != '-' || ctl->stat_basename[0] != '-'
5800 || (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0))
5801 mptrac_update_host(NULL, NULL, NULL, NULL, NULL, atm);
5802
5803 /* Write atmospheric data... */
5804 if (ctl->atm_basename[0] != '-' &&
5805 (fmod(t, ctl->atm_dt_out) == 0 || t == ctl->t_stop)) {
5806 if (ctl->atm_type_out == 0)
5807 sprintf(ext, "tab");
5808 else if (ctl->atm_type_out == 1)
5809 sprintf(ext, "bin");
5810 else if (ctl->atm_type_out == 2)
5811 sprintf(ext, "nc");
5812 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
5813 dirname, ctl->atm_basename, year, mon, day, hour, min, ext);
5814 mptrac_write_atm(filename, ctl, atm, t);
5815 }
5816
5817 /* Write gridded data... */
5818 if (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0) {
5819 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
5820 dirname, ctl->grid_basename, year, mon, day, hour, min,
5821 ctl->grid_type == 0 ? "tab" : "nc");
5822 write_grid(filename, ctl, met0, met1, atm, t);
5823 }
5824
5825 /* Write CSI data... */
5826 if (ctl->csi_basename[0] != '-') {
5827 sprintf(filename, "%s/%s.tab", dirname, ctl->csi_basename);
5828 write_csi(filename, ctl, atm, t);
5829 }
5830
5831 /* Write ensemble data... */
5832 if (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0) {
5833 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
5834 dirname, ctl->ens_basename, year, mon, day, hour, min);
5835 write_ens(filename, ctl, atm, t);
5836 }
5837
5838 /* Write profile data... */
5839 if (ctl->prof_basename[0] != '-') {
5840 sprintf(filename, "%s/%s.tab", dirname, ctl->prof_basename);
5841 write_prof(filename, ctl, met0, met1, atm, t);
5842 }
5843
5844 /* Write sample data... */
5845 if (ctl->sample_basename[0] != '-') {
5846 sprintf(filename, "%s/%s.tab", dirname, ctl->sample_basename);
5847 write_sample(filename, ctl, met0, met1, atm, t);
5848 }
5849
5850 /* Write station data... */
5851 if (ctl->stat_basename[0] != '-') {
5852 sprintf(filename, "%s/%s.tab", dirname, ctl->stat_basename);
5853 write_station(filename, ctl, atm, t);
5854 }
5855
5856 /* Write VTK data... */
5857 if (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0) {
5858 static int nvtk;
5859 if (t == ctl->t_start)
5860 nvtk = 0;
5861 sprintf(filename, "%s/%s_%05d.vtk", dirname, ctl->vtk_basename, ++nvtk);
5862 write_vtk(filename, ctl, atm, t);
5863 }
5864}
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:5677
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:9954
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:10904
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:5621
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:11293
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:11379
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:11131
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:10051
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:9692
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 5565 of file mptrac.c.

5571 {
5572
5573 /* Update GPU... */
5574 if (ctl != NULL) {
5575#ifdef _OPENACC
5576 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5577#pragma acc update device(ctl[:1])
5578#endif
5579 }
5580
5581 if (cache != NULL) {
5582#ifdef _OPENACC
5583 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5584#pragma acc update device(cache[:1])
5585#endif
5586 }
5587
5588 if (clim != NULL) {
5589#ifdef _OPENACC
5590 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5591#pragma acc update device(clim[:1])
5592#endif
5593 }
5594
5595 if (met0 != NULL) {
5596#ifdef _OPENACC
5597 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5598 met_t *met0up = *met0;
5599#pragma acc update device(met0up[:1])
5600#endif
5601 }
5602
5603 if (met1 != NULL) {
5604#ifdef _OPENACC
5605 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5606 met_t *met1up = *met1;
5607#pragma acc update device(met1up[:1])
5608#endif
5609 }
5610
5611 if (atm != NULL) {
5612#ifdef _OPENACC
5613 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5614#pragma acc update device(atm[:1])
5615#endif
5616 }
5617}

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

5627 {
5628
5629 /* Update GPU... */
5630 if (ctl != NULL) {
5631#ifdef _OPENACC
5632 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5633#pragma acc update host(ctl[:1])
5634#endif
5635 }
5636
5637 if (cache != NULL) {
5638#ifdef _OPENACC
5639 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5640#pragma acc update host(cache[:1])
5641#endif
5642 }
5643
5644 if (clim != NULL) {
5645#ifdef _OPENACC
5646 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5647#pragma acc update host(clim[:1])
5648#endif
5649 }
5650
5651 if (met0 != NULL) {
5652#ifdef _OPENACC
5653 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5654 met_t *met0up = *met0;
5655#pragma acc update host(met0up[:1])
5656#endif
5657 }
5658
5659 if (met1 != NULL) {
5660#ifdef _OPENACC
5661 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5662 met_t *met1up = *met1;
5663#pragma acc update host(met1up[:1])
5664#endif
5665 }
5666
5667 if (atm != NULL) {
5668#ifdef _OPENACC
5669 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5670#pragma acc update host(atm[:1])
5671#endif
5672 }
5673}

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

5871 {
5872
5873 /* Check water vapor volume mixing ratio... */
5874 const double h2o_help = MAX(h2o, 0.1e-6);
5875
5876 /* Calculate T_NAT... */
5877 const double p_hno3 = hno3 * p / 1.333224;
5878 const double p_h2o = h2o_help * p / 1.333224;
5879 const double a = 0.009179 - 0.00088 * log10(p_h2o);
5880 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
5881 const double c = -11397.0 / a;
5882 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
5883 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
5884 if (x2 > 0)
5885 tnat = x2;
5886
5887 return tnat;
5888}

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

5897 {
5898
5899 /* Get pressure range... */
5900 const double p1 = pbl - ctl->conv_pbl_trans * (ps - pbl);
5901 const double p0 = pbl;
5902
5903 /* Get weighting factor... */
5904 if (atm->p[ip] > p0)
5905 return 1;
5906 else if (atm->p[ip] < p1)
5907 return 0;
5908 else
5909 return LIN(p0, 1.0, p1, 0.0, atm->p[ip]);
5910}

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

5917 {
5918
5919 /* Open file... */
5920 FILE *in;
5921 if (!(in = fopen(filename, "r"))) {
5922 WARN("Cannot open file!");
5923 return 0;
5924 }
5925
5926 /* Read line... */
5927 char line[LEN];
5928 while (fgets(line, LEN, in)) {
5929
5930 /* Read data... */
5931 char *tok;
5932 TOK(line, tok, "%lg", atm->time[atm->np]);
5933 TOK(NULL, tok, "%lg", atm->p[atm->np]);
5934 TOK(NULL, tok, "%lg", atm->lon[atm->np]);
5935 TOK(NULL, tok, "%lg", atm->lat[atm->np]);
5936 for (int iq = 0; iq < ctl->nq; iq++)
5937 TOK(NULL, tok, "%lg", atm->q[iq][atm->np]);
5938
5939 /* Convert altitude to pressure... */
5940 atm->p[atm->np] = P(atm->p[atm->np]);
5941
5942 /* Increment data point counter... */
5943 if ((++atm->np) > NP)
5944 ERRMSG("Too many data points!");
5945 }
5946
5947 /* Close file... */
5948 fclose(in);
5949
5950 /* Return success... */
5951 return 1;
5952}
#define TOK(line, tok, format, var)
Get string tokens.
Definition: mptrac.h:1694

◆ read_atm_bin()

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

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

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

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

This function performs the following steps:

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

The function utilizes several macros and helper functions:

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

Definition at line 5956 of file mptrac.c.

5959 {
5960
5961 /* Open file... */
5962 FILE *in;
5963 if (!(in = fopen(filename, "r")))
5964 return 0;
5965
5966 /* Check version of binary data... */
5967 int version;
5968 FREAD(&version, int,
5969 1,
5970 in);
5971 if (version != 100)
5972 ERRMSG("Wrong version of binary data!");
5973
5974 /* Read data... */
5975 FREAD(&atm->np, int,
5976 1,
5977 in);
5978 FREAD(atm->time, double,
5979 (size_t) atm->np,
5980 in);
5981 FREAD(atm->p, double,
5982 (size_t) atm->np,
5983 in);
5984 FREAD(atm->lon, double,
5985 (size_t) atm->np,
5986 in);
5987 FREAD(atm->lat, double,
5988 (size_t) atm->np,
5989 in);
5990 for (int iq = 0; iq < ctl->nq; iq++)
5991 FREAD(atm->q[iq], double,
5992 (size_t) atm->np,
5993 in);
5994
5995 /* Read final flag... */
5996 int final;
5997 FREAD(&final, int,
5998 1,
5999 in);
6000 if (final != 999)
6001 ERRMSG("Error while reading binary data!");
6002
6003 /* Close file... */
6004 fclose(in);
6005
6006 /* Return success... */
6007 return 1;
6008}

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

6015 {
6016
6017 int ncid, varid;
6018
6019 /* Open file... */
6020 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6021 return 0;
6022
6023 /* Get dimensions... */
6024 NC_INQ_DIM("NPARTS", &atm->np, 1, NP);
6025
6026 /* Get time... */
6027 if (nc_inq_varid(ncid, "TIME_INIT", &varid) == NC_NOERR) {
6028 NC(nc_get_var_double(ncid, varid, atm->time));
6029 } else {
6030 WARN("TIME_INIT not found use time instead!");
6031 double time_init;
6032 NC_GET_DOUBLE("time", &time_init, 1);
6033 for (int ip = 0; ip < atm->np; ip++) {
6034 atm->time[ip] = time_init;
6035 }
6036 }
6037
6038 /* Read zeta coordinate, pressure is optional... */
6039 if (ctl->advect_vert_coord == 1) {
6040 NC_GET_DOUBLE("ZETA", atm->q[ctl->qnt_zeta], 1);
6041 NC_GET_DOUBLE("PRESS", atm->p, 0);
6042 }
6043
6044 /* Read pressure, zeta coordinate is optional... */
6045 else {
6046 if (nc_inq_varid(ncid, "PRESS_INIT", &varid) == NC_NOERR) {
6047 NC(nc_get_var_double(ncid, varid, atm->p));
6048 } else {
6049 WARN("PRESS_INIT not found use PRESS instead!");
6050 nc_inq_varid(ncid, "PRESS", &varid);
6051 NC(nc_get_var_double(ncid, varid, atm->p));
6052 }
6053 }
6054
6055 /* Read longitude and latitude... */
6056 NC_GET_DOUBLE("LON", atm->lon, 1);
6057 NC_GET_DOUBLE("LAT", atm->lat, 1);
6058
6059 /* Close file... */
6060 NC(nc_close(ncid));
6061
6062 /* Return success... */
6063 return 1;
6064}
#define NC(cmd)
Execute a NetCDF command and check for errors.
Definition: mptrac.h:1016
#define NC_INQ_DIM(dimname, ptr, min, max)
Inquire the length of a dimension in a NetCDF file.
Definition: mptrac.h:1103
#define NC_GET_DOUBLE(varname, ptr, force)
Retrieve a double-precision variable from a NetCDF file.
Definition: mptrac.h:1075

◆ read_atm_nc()

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

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

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

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

This function performs the following steps:

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

The function utilizes several macros and helper functions:

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

Definition at line 6068 of file mptrac.c.

6071 {
6072
6073 int ncid, varid;
6074
6075 /* Open file... */
6076 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6077 return 0;
6078
6079 /* Get dimensions... */
6080 NC_INQ_DIM("obs", &atm->np, 1, NP);
6081
6082 /* Read geolocations... */
6083 NC_GET_DOUBLE("time", atm->time, 1);
6084 NC_GET_DOUBLE("press", atm->p, 1);
6085 NC_GET_DOUBLE("lon", atm->lon, 1);
6086 NC_GET_DOUBLE("lat", atm->lat, 1);
6087
6088 /* Read variables... */
6089 for (int iq = 0; iq < ctl->nq; iq++)
6090 NC_GET_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
6091
6092 /* Close file... */
6093 NC(nc_close(ncid));
6094
6095 /* Return success... */
6096 return 1;
6097}

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

6103 {
6104
6105 int ncid, varid;
6106
6107 /* Write info... */
6108 LOG(1, "Read photolysis rates: %s", filename);
6109
6110 /* Open netCDF file... */
6111 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
6112 WARN("Photolysis rate data are missing!");
6113 return;
6114 }
6115
6116 /* Read pressure data... */
6117 NC_INQ_DIM("press", &photo->np, 2, CP);
6118 NC_GET_DOUBLE("press", photo->p, 1);
6119 if (photo->p[0] < photo->p[1])
6120 ERRMSG("Pressure data are not descending!");
6121
6122 /* Read total column ozone data... */
6123 NC_INQ_DIM("total_o3col", &photo->no3c, 2, CO3);
6124 NC_GET_DOUBLE("total_o3col", photo->o3c, 1);
6125 if (photo->o3c[0] > photo->o3c[1])
6126 ERRMSG("Total column ozone data are not ascending!");
6127
6128 /* Read solar zenith angle data... */
6129 NC_INQ_DIM("sza", &photo->nsza, 2, CSZA);
6130 NC_GET_DOUBLE("sza", photo->sza, 1);
6131 if (photo->sza[0] > photo->sza[1])
6132 ERRMSG("Solar zenith angle data are not ascending!");
6133
6134 /* Read data... */
6135 read_clim_photo_help(ncid, "J_N2O", photo, photo->n2o);
6136 read_clim_photo_help(ncid, "J_CCl4", photo, photo->ccl4);
6137 read_clim_photo_help(ncid, "J_CFC-11", photo, photo->ccl3f);
6138 read_clim_photo_help(ncid, "J_CFC-12", photo, photo->ccl2f2);
6139 read_clim_photo_help(ncid, "J_O2", photo, photo->o2);
6140 read_clim_photo_help(ncid, "J_O3b", photo, photo->o3_1);
6141 read_clim_photo_help(ncid, "J_O3a", photo, photo->o3_2);
6142 read_clim_photo_help(ncid, "J_H2O2", photo, photo->h2o2);
6143 read_clim_photo_help(ncid, "J_H2O", photo, photo->h2o);
6144
6145 /* Close netCDF file... */
6146 NC(nc_close(ncid));
6147
6148 /* Write info... */
6149 LOG(2, "Number of pressure levels: %d", photo->np);
6150 LOG(2, "Altitude levels: %g, %g ... %g km",
6151 Z(photo->p[0]), Z(photo->p[1]), Z(photo->p[photo->np - 1]));
6152 LOG(2, "Pressure levels: %g, %g ... %g hPa",
6153 photo->p[0], photo->p[1], photo->p[photo->np - 1]);
6154 LOG(2, "Number of solar zenith angles: %d", photo->nsza);
6155 LOG(2, "Solar zenith angles: %g, %g ... %g deg",
6156 RAD2DEG(photo->sza[0]), RAD2DEG(photo->sza[1]),
6157 RAD2DEG(photo->sza[photo->nsza - 1]));
6158 LOG(2, "Number of total column ozone values: %d", photo->no3c);
6159 LOG(2, "Total column ozone: %g, %g ... %g DU",
6160 photo->o3c[0], photo->o3c[1], photo->o3c[photo->no3c - 1]);
6161 LOG(2, "N2O photolysis rate: %g, %g ... %g s**-1",
6162 photo->n2o[0][0][0], photo->n2o[1][0][0],
6163 photo->n2o[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6164 LOG(2, "CCl4 photolysis rate: %g, %g ... %g s**-1",
6165 photo->ccl4[0][0][0], photo->ccl4[1][0][0],
6166 photo->ccl4[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6167 LOG(2, "CFC-11 photolysis rate: %g, %g ... %g s**-1",
6168 photo->ccl3f[0][0][0], photo->ccl3f[1][0][0],
6169 photo->ccl3f[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6170 LOG(2, "CFC-12 photolysis rate: %g, %g ... %g s**-1",
6171 photo->ccl2f2[0][0][0], photo->ccl2f2[1][0][0],
6172 photo->ccl2f2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6173 LOG(2, "O2 photolysis rate: %g, %g ... %g s**-1",
6174 photo->o2[0][0][0], photo->o2[1][0][0],
6175 photo->o2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6176 LOG(2, "O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
6177 photo->o3_1[0][0][0], photo->o3_1[1][0][0],
6178 photo->o3_1[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6179 LOG(2, "O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
6180 photo->o3_2[0][0][0], photo->o3_2[1][0][0],
6181 photo->o3_2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6182 LOG(2, "H2O2 photolysis rate: %g, %g ... %g s**-1",
6183 photo->h2o2[0][0][0], photo->h2o2[1][0][0],
6184 photo->h2o2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6185 LOG(2, "H2O photolysis rate: %g, %g ... %g s**-1",
6186 photo->h2o[0][0][0], photo->h2o[1][0][0],
6187 photo->h2o[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6188}
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:6192
#define CP
Maximum number of pressure levels for climatological data.
Definition: mptrac.h:301
#define CO3
Maximum number of total column ozone data for climatological data.
Definition: mptrac.h:296
#define CSZA
Maximum number of solar zenith angles for climatological data.
Definition: mptrac.h:306
double o3_1[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O1d + O2) [1/s].
Definition: mptrac.h:3245
double o2[CP][CSZA][CO3]
O2 photolysis rate [1/s].
Definition: mptrac.h:3242
double h2o2[CP][CSZA][CO3]
H2O2 photolysis rate [1/s].
Definition: mptrac.h:3251
double h2o[CP][CSZA][CO3]
H2O photolysis rate [1/s].
Definition: mptrac.h:3254
double o3_2[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O3p + O2) [1/s].
Definition: mptrac.h:3248
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 6192 of file mptrac.c.

6196 {
6197
6198 /* Allocate... */
6199 double *help;
6200 ALLOC(help, double,
6201 photo->np * photo->nsza * photo->no3c);
6202
6203 /* Read varible... */
6204 int varid;
6205 NC_GET_DOUBLE(varname, help, 1);
6206
6207 /* Copy data... */
6208 for (int ip = 0; ip < photo->np; ip++)
6209 for (int is = 0; is < photo->nsza; is++)
6210 for (int io = 0; io < photo->no3c; io++)
6211 var[ip][is][io] =
6212 help[ARRAY_3D(ip, is, photo->nsza, io, photo->no3c)];
6213
6214 /* Free... */
6215 free(help);
6216}

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

6222 {
6223
6224 /* Write info... */
6225 LOG(1, "Read climatological time series: %s", filename);
6226
6227 /* Open file... */
6228 FILE *in;
6229 if (!(in = fopen(filename, "r"))) {
6230 WARN("Cannot open file!");
6231 return 0;
6232 }
6233
6234 /* Read data... */
6235 char line[LEN];
6236 int nh = 0;
6237 while (fgets(line, LEN, in))
6238 if (sscanf(line, "%lg %lg", &ts->time[nh], &ts->vmr[nh]) == 2) {
6239
6240 /* Convert years to seconds... */
6241 ts->time[nh] = (ts->time[nh] - 2000.0) * 365.25 * 86400.;
6242
6243 /* Check data... */
6244 if (nh > 0 && ts->time[nh] <= ts->time[nh - 1])
6245 ERRMSG("Time series must be ascending!");
6246
6247 /* Count time steps... */
6248 if ((++nh) >= CTS)
6249 ERRMSG("Too many data points!");
6250 }
6251
6252 /* Close file... */
6253 fclose(in);
6254
6255 /* Check number of data points... */
6256 ts->ntime = nh;
6257 if (nh < 2)
6258 ERRMSG("Not enough data points!");
6259
6260 /* Write info... */
6261 LOG(2, "Number of time steps: %d", ts->ntime);
6262 LOG(2, "Time steps: %.2f, %.2f ... %.2f s", ts->time[0], ts->time[1],
6263 ts->time[nh - 1]);
6264 LOG(2, "Volume mixing ratio range: %g ... %g ppv",
6265 gsl_stats_min(ts->vmr, 1, (size_t) nh), gsl_stats_max(ts->vmr, 1,
6266 (size_t) nh));
6267
6268 /* Exit success... */
6269 return 1;
6270}
#define CTS
Maximum number of data points of climatological time series.
Definition: mptrac.h:316

◆ read_clim_zm()

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

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

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

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

The function performs the following steps:

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

Definition at line 6274 of file mptrac.c.

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

◆ read_kernel()

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

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

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

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

The function performs the following steps:

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

Definition at line 6373 of file mptrac.c.

6377 {
6378
6379 /* Write info... */
6380 LOG(1, "Read kernel function: %s", filename);
6381
6382 /* Open file... */
6383 FILE *in;
6384 if (!(in = fopen(filename, "r")))
6385 ERRMSG("Cannot open file!");
6386
6387 /* Read data... */
6388 char line[LEN];
6389 int n = 0;
6390 while (fgets(line, LEN, in))
6391 if (sscanf(line, "%lg %lg", &kz[n], &kw[n]) == 2) {
6392 if (n > 0 && kz[n] < kz[n - 1])
6393 ERRMSG("Height levels must be ascending!");
6394 if ((++n) >= EP)
6395 ERRMSG("Too many height levels!");
6396 }
6397
6398 /* Close file... */
6399 fclose(in);
6400
6401 /* Check number of data points... */
6402 *nk = n;
6403 if (n < 2)
6404 ERRMSG("Not enough height levels!");
6405
6406 /* Normalize kernel function... */
6407 const double kmax = gsl_stats_max(kw, 1, (size_t) n);
6408 for (int iz = 0; iz < n; iz++)
6409 kw[iz] /= kmax;
6410}

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

6417 {
6418
6419 FILE *in;
6420
6421 double r;
6422
6423 int year, mon, day, hour, min, sec;
6424
6425 /* Set timer... */
6426 SELECT_TIMER("READ_MET_BIN", "INPUT", NVTX_READ);
6427
6428 /* Open file... */
6429 if (!(in = fopen(filename, "r"))) {
6430 WARN("Cannot open file!");
6431 return 0;
6432 }
6433
6434 /* Check type of binary data... */
6435 int met_type;
6436 FREAD(&met_type, int,
6437 1,
6438 in);
6439 if (met_type != ctl->met_type)
6440 ERRMSG("Wrong MET_TYPE of binary data!");
6441
6442 /* Check version of binary data... */
6443 int version;
6444 FREAD(&version, int,
6445 1,
6446 in);
6447 if (version != 103)
6448 ERRMSG("Wrong version of binary data!");
6449
6450 /* Read time... */
6451 FREAD(&met->time, double,
6452 1,
6453 in);
6454 jsec2time(met->time, &year, &mon, &day, &hour, &min, &sec, &r);
6455 LOG(2, "Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
6456 met->time, year, mon, day, hour, min);
6457 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
6458 || day < 1 || day > 31 || hour < 0 || hour > 23)
6459 ERRMSG("Error while reading time!");
6460
6461 /* Read dimensions... */
6462 FREAD(&met->nx, int,
6463 1,
6464 in);
6465 LOG(2, "Number of longitudes: %d", met->nx);
6466 if (met->nx < 2 || met->nx > EX)
6467 ERRMSG("Number of longitudes out of range!");
6468
6469 FREAD(&met->ny, int,
6470 1,
6471 in);
6472 LOG(2, "Number of latitudes: %d", met->ny);
6473 if (met->ny < 2 || met->ny > EY)
6474 ERRMSG("Number of latitudes out of range!");
6475
6476 FREAD(&met->np, int,
6477 1,
6478 in);
6479 LOG(2, "Number of levels: %d", met->np);
6480 if (met->np < 2 || met->np > EP)
6481 ERRMSG("Number of levels out of range!");
6482
6483 /* Read grid... */
6484 FREAD(met->lon, double,
6485 (size_t) met->nx,
6486 in);
6487 LOG(2, "Longitudes: %g, %g ... %g deg",
6488 met->lon[0], met->lon[1], met->lon[met->nx - 1]);
6489
6490 FREAD(met->lat, double,
6491 (size_t) met->ny,
6492 in);
6493 LOG(2, "Latitudes: %g, %g ... %g deg",
6494 met->lat[0], met->lat[1], met->lat[met->ny - 1]);
6495
6496 FREAD(met->p, double,
6497 (size_t) met->np,
6498 in);
6499 LOG(2, "Altitude levels: %g, %g ... %g km",
6500 Z(met->p[0]), Z(met->p[1]), Z(met->p[met->np - 1]));
6501 LOG(2, "Pressure levels: %g, %g ... %g hPa",
6502 met->p[0], met->p[1], met->p[met->np - 1]);
6503
6504 /* Read surface data... */
6505 read_met_bin_2d(in, met, met->ps, "PS");
6506 read_met_bin_2d(in, met, met->ts, "TS");
6507 read_met_bin_2d(in, met, met->zs, "ZS");
6508 read_met_bin_2d(in, met, met->us, "US");
6509 read_met_bin_2d(in, met, met->vs, "VS");
6510 read_met_bin_2d(in, met, met->ess, "ESS");
6511 read_met_bin_2d(in, met, met->nss, "NSS");
6512 read_met_bin_2d(in, met, met->shf, "SHF");
6513 read_met_bin_2d(in, met, met->lsm, "LSM");
6514 read_met_bin_2d(in, met, met->sst, "SST");
6515 read_met_bin_2d(in, met, met->pbl, "PBL");
6516 read_met_bin_2d(in, met, met->pt, "PT");
6517 read_met_bin_2d(in, met, met->tt, "TT");
6518 read_met_bin_2d(in, met, met->zt, "ZT");
6519 read_met_bin_2d(in, met, met->h2ot, "H2OT");
6520 read_met_bin_2d(in, met, met->pct, "PCT");
6521 read_met_bin_2d(in, met, met->pcb, "PCB");
6522 read_met_bin_2d(in, met, met->cl, "CL");
6523 read_met_bin_2d(in, met, met->plcl, "PLCL");
6524 read_met_bin_2d(in, met, met->plfc, "PLFC");
6525 read_met_bin_2d(in, met, met->pel, "PEL");
6526 read_met_bin_2d(in, met, met->cape, "CAPE");
6527 read_met_bin_2d(in, met, met->cin, "CIN");
6528 read_met_bin_2d(in, met, met->o3c, "O3C");
6529
6530 /* Read level data... */
6531 read_met_bin_3d(in, ctl, met, met->z, "Z", -1e34f, 1e34f);
6532 read_met_bin_3d(in, ctl, met, met->t, "T", 0, 1e34f);
6533 read_met_bin_3d(in, ctl, met, met->u, "U", -1e34f, 1e34f);
6534 read_met_bin_3d(in, ctl, met, met->v, "V", -1e34f, 1e34f);
6535 read_met_bin_3d(in, ctl, met, met->w, "W", -1e34f, 1e34f);
6536 read_met_bin_3d(in, ctl, met, met->pv, "PV", -1e34f, 1e34f);
6537 read_met_bin_3d(in, ctl, met, met->h2o, "H2O", 0, 1e34f);
6538 read_met_bin_3d(in, ctl, met, met->o3, "O3", 0, 1e34f);
6539 read_met_bin_3d(in, ctl, met, met->lwc, "LWC", 0, 1e34f);
6540 read_met_bin_3d(in, ctl, met, met->rwc, "RWC", 0, 1e34f);
6541 read_met_bin_3d(in, ctl, met, met->iwc, "IWC", 0, 1e34f);
6542 read_met_bin_3d(in, ctl, met, met->swc, "SWC", 0, 1e34f);
6543 read_met_bin_3d(in, ctl, met, met->cc, "CC", 0, 1);
6544
6545 /* Read final flag... */
6546 int final;
6547 FREAD(&final, int,
6548 1,
6549 in);
6550 if (final != 999)
6551 ERRMSG("Error while reading binary data!");
6552
6553 /* Close file... */
6554 fclose(in);
6555
6556 /* Return success... */
6557 return 1;
6558}
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:6562
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:6591
#define EY
Maximum number of latitudes for meteo data.
Definition: mptrac.h:271
float zt[EX][EY]
Tropopause geopotential height [km].
Definition: mptrac.h:3445
float sst[EX][EY]
Sea surface temperature [K].
Definition: mptrac.h:3433
float rwc[EX][EY][EP]
Cloud rain water content [kg/kg].
Definition: mptrac.h:3505
float o3c[EX][EY]
Total column ozone [DU].
Definition: mptrac.h:3475
float cape[EX][EY]
Convective available potential energy [J/kg].
Definition: mptrac.h:3469
float pct[EX][EY]
Cloud top pressure [hPa].
Definition: mptrac.h:3451
float shf[EX][EY]
Surface sensible heat flux [W/m^2].
Definition: mptrac.h:3427
float lwc[EX][EY][EP]
Cloud liquid water content [kg/kg].
Definition: mptrac.h:3502
float us[EX][EY]
Surface zonal wind [m/s].
Definition: mptrac.h:3415
float cc[EX][EY][EP]
Cloud cover [1].
Definition: mptrac.h:3514
float ts[EX][EY]
Surface temperature [K].
Definition: mptrac.h:3409
float ess[EX][EY]
Eastward turbulent surface stress [N/m^2].
Definition: mptrac.h:3421
float pcb[EX][EY]
Cloud bottom pressure [hPa].
Definition: mptrac.h:3454
float pel[EX][EY]
Pressure at equilibrium level (EL) [hPa].
Definition: mptrac.h:3466
float cin[EX][EY]
Convective inhibition [J/kg].
Definition: mptrac.h:3472
float plcl[EX][EY]
Pressure at lifted condensation level (LCL) [hPa].
Definition: mptrac.h:3460
float tt[EX][EY]
Tropopause temperature [K].
Definition: mptrac.h:3442
float pbl[EX][EY]
Boundary layer pressure [hPa].
Definition: mptrac.h:3436
float vs[EX][EY]
Surface meridional wind [m/s].
Definition: mptrac.h:3418
float lsm[EX][EY]
Land-sea mask [1].
Definition: mptrac.h:3430
float iwc[EX][EY][EP]
Cloud ice water content [kg/kg].
Definition: mptrac.h:3508
float h2ot[EX][EY]
Tropopause water vapor volume mixing ratio [ppv].
Definition: mptrac.h:3448
float pv[EX][EY][EP]
Potential vorticity [PVU].
Definition: mptrac.h:3493
float cl[EX][EY]
Total column cloud water [kg/m^2].
Definition: mptrac.h:3457
float nss[EX][EY]
Northward turbulent surface stress [N/m^2].
Definition: mptrac.h:3424
float plfc[EX][EY]
Pressure at level of free convection (LFC) [hPa].
Definition: mptrac.h:3463
float swc[EX][EY][EP]
Cloud snow water content [kg/kg].
Definition: mptrac.h:3511
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 6562 of file mptrac.c.

6566 {
6567
6568 float *help;
6569
6570 /* Allocate... */
6571 ALLOC(help, float,
6572 EX * EY);
6573
6574 /* Read uncompressed... */
6575 LOG(2, "Read 2-D variable: %s (uncompressed)", varname);
6576 FREAD(help, float,
6577 (size_t) (met->nx * met->ny),
6578 in);
6579
6580 /* Copy data... */
6581 for (int ix = 0; ix < met->nx; ix++)
6582 for (int iy = 0; iy < met->ny; iy++)
6583 var[ix][iy] = help[ARRAY_2D(ix, iy, met->ny)];
6584
6585 /* Free... */
6586 free(help);
6587}
#define ARRAY_2D(ix, iy, ny)
Macro for computing the linear index of a 2D array element.
Definition: mptrac.h:372

◆ read_met_bin_3d()

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

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

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

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

The function supports the following types of data:

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

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

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

Definition at line 6591 of file mptrac.c.

6598 {
6599
6600 float *help;
6601
6602 /* Allocate... */
6603 ALLOC(help, float,
6604 EX * EY * EP);
6605
6606 /* Read uncompressed data... */
6607 if (ctl->met_type == 1) {
6608 LOG(2, "Read 3-D variable: %s (uncompressed)", varname);
6609 FREAD(help, float,
6610 (size_t) (met->nx * met->ny * met->np),
6611 in);
6612 }
6613
6614 /* Read packed data... */
6615 else if (ctl->met_type == 2)
6616 compress_pck(varname, help, (size_t) (met->ny * met->nx),
6617 (size_t) met->np, 1, in);
6618
6619 /* Read zfp data... */
6620 else if (ctl->met_type == 3) {
6621#ifdef ZFP
6622 int precision;
6623 FREAD(&precision, int,
6624 1,
6625 in);
6626
6627 double tolerance;
6628 FREAD(&tolerance, double,
6629 1,
6630 in);
6631
6632 compress_zfp(varname, help, met->np, met->ny, met->nx, precision,
6633 tolerance, 1, in);
6634#else
6635 ERRMSG("MPTRAC was compiled without zfp compression!");
6636#endif
6637 }
6638
6639 /* Read zstd data... */
6640 else if (ctl->met_type == 4) {
6641#ifdef ZSTD
6642 compress_zstd(varname, help, (size_t) (met->np * met->ny * met->nx), 1,
6643 in);
6644#else
6645 ERRMSG("MPTRAC was compiled without zstd compression!");
6646#endif
6647 }
6648
6649 /* Read cmultiscale data... */
6650 else if (ctl->met_type == 5) {
6651#ifdef CMS
6652 compress_cms(ctl, varname, help, (size_t) met->nx, (size_t) met->ny,
6653 (size_t) met->np, 1, in);
6654#else
6655 ERRMSG("MPTRAC was compiled without cmultiscale compression!");
6656#endif
6657 }
6658
6659 /* Copy data... */
6660#pragma omp parallel for default(shared) collapse(2)
6661 for (int ix = 0; ix < met->nx; ix++)
6662 for (int iy = 0; iy < met->ny; iy++)
6663 for (int ip = 0; ip < met->np; ip++) {
6664 var[ix][iy][ip] = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
6665 if (var[ix][iy][ip] < bound_min)
6666 var[ix][iy][ip] = bound_min;
6667 else if (var[ix][iy][ip] > bound_max)
6668 var[ix][iy][ip] = bound_max;
6669 }
6670
6671 /* Free... */
6672 free(help);
6673}
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:665
void compress_cms(const ctl_t *ctl, const char *varname, float *array, const size_t nx, const size_t ny, const size_t np, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm.
void compress_zfp(const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using the ZFP library.
void compress_zstd(const char *varname, float *array, const size_t n, const int decompress, FILE *inout)
Compresses or decompresses an array of floats using the Zstandard (ZSTD) library.
Here is the call graph for this function:

◆ read_met_cape()

void read_met_cape ( const ctl_t ctl,
const clim_t clim,
met_t met 
)

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

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

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

The function performs the following steps:

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

Definition at line 6677 of file mptrac.c.

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

6793 {
6794
6795 /* Set timer... */
6796 SELECT_TIMER("READ_MET_CLOUD", "METPROC", NVTX_READ);
6797 LOG(2, "Calculate cloud data...");
6798
6799 /* Thresholds for cloud detection... */
6800 const double ccmin = 0.01, cwmin = 1e-6;
6801
6802 /* Loop over columns... */
6803#pragma omp parallel for default(shared) collapse(2)
6804 for (int ix = 0; ix < met->nx; ix++)
6805 for (int iy = 0; iy < met->ny; iy++) {
6806
6807 /* Init... */
6808 met->pct[ix][iy] = NAN;
6809 met->pcb[ix][iy] = NAN;
6810 met->cl[ix][iy] = 0;
6811
6812 /* Loop over pressure levels... */
6813 for (int ip = 0; ip < met->np - 1; ip++) {
6814
6815 /* Check pressure... */
6816 if (met->p[ip] > met->ps[ix][iy] || met->p[ip] < P(20.))
6817 continue;
6818
6819 /* Check ice water and liquid water content... */
6820 if (met->cc[ix][iy][ip] > ccmin
6821 && (met->iwc[ix][iy][ip] > cwmin
6822 || met->rwc[ix][iy][ip] > cwmin
6823 || met->lwc[ix][iy][ip] > cwmin
6824 || met->swc[ix][iy][ip] > cwmin)) {
6825
6826 /* Get cloud top pressure ... */
6827 met->pct[ix][iy]
6828 = (float) (0.5 * (met->p[ip] + (float) met->p[ip + 1]));
6829
6830 /* Get cloud bottom pressure ... */
6831 if (!isfinite(met->pcb[ix][iy]))
6832 met->pcb[ix][iy]
6833 = (float) (0.5 * (met->p[ip] + met->p[MAX(ip - 1, 0)]));
6834 }
6835
6836 /* Get cloud water... */
6837 met->cl[ix][iy] += (float)
6838 (0.5 * (met->lwc[ix][iy][ip] + met->lwc[ix][iy][ip + 1]
6839 + met->rwc[ix][iy][ip] + met->rwc[ix][iy][ip + 1]
6840 + met->iwc[ix][iy][ip] + met->iwc[ix][iy][ip + 1]
6841 + met->swc[ix][iy][ip] + met->swc[ix][iy][ip + 1])
6842 * 100. * (met->p[ip] - met->p[ip + 1]) / G0);
6843 }
6844 }
6845}

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

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

6954 {
6955
6956 /* Set timer... */
6957 SELECT_TIMER("READ_MET_EXTRAPOLATE", "METPROC", NVTX_READ);
6958 LOG(2, "Extrapolate meteo data...");
6959
6960 /* Loop over columns... */
6961#pragma omp parallel for default(shared) collapse(2)
6962 for (int ix = 0; ix < met->nx; ix++)
6963 for (int iy = 0; iy < met->ny; iy++) {
6964
6965 /* Find lowest valid data point... */
6966 int ip0;
6967 for (ip0 = met->np - 1; ip0 >= 0; ip0--)
6968 if (!isfinite(met->t[ix][iy][ip0])
6969 || !isfinite(met->u[ix][iy][ip0])
6970 || !isfinite(met->v[ix][iy][ip0])
6971 || !isfinite(met->w[ix][iy][ip0]))
6972 break;
6973
6974 /* Extrapolate... */
6975 for (int ip = ip0; ip >= 0; ip--) {
6976 met->t[ix][iy][ip] = met->t[ix][iy][ip + 1];
6977 met->u[ix][iy][ip] = met->u[ix][iy][ip + 1];
6978 met->v[ix][iy][ip] = met->v[ix][iy][ip + 1];
6979 met->w[ix][iy][ip] = met->w[ix][iy][ip + 1];
6980 met->h2o[ix][iy][ip] = met->h2o[ix][iy][ip + 1];
6981 met->o3[ix][iy][ip] = met->o3[ix][iy][ip + 1];
6982 met->lwc[ix][iy][ip] = met->lwc[ix][iy][ip + 1];
6983 met->rwc[ix][iy][ip] = met->rwc[ix][iy][ip + 1];
6984 met->iwc[ix][iy][ip] = met->iwc[ix][iy][ip + 1];
6985 met->swc[ix][iy][ip] = met->swc[ix][iy][ip + 1];
6986 met->cc[ix][iy][ip] = met->cc[ix][iy][ip + 1];
6987 }
6988 }
6989}

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

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

◆ read_met_grid()

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

Reads meteorological grid information from a NetCDF file.

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

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

The function performs the following steps:

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

Definition at line 7121 of file mptrac.c.

7125 {
7126
7127 char levname[LEN], tstr[10];
7128
7129 double rtime = 0, r, r2;
7130
7131 int varid, year2, mon2, day2, hour2, min2, sec2,
7132 year, mon, day, hour, min, sec;
7133
7134 size_t np;
7135
7136 /* Set timer... */
7137 SELECT_TIMER("READ_MET_GRID", "INPUT", NVTX_READ);
7138 LOG(2, "Read meteo grid information...");
7139
7140 /* MPTRAC meteo files... */
7141 if (ctl->met_clams == 0) {
7142
7143 /* Get time from filename... */
7144 met->time = time_from_filename(filename, 16);
7145
7146 /* Check time information from data file... */
7147 jsec2time(met->time, &year, &mon, &day, &hour, &min, &sec, &r);
7148 if (nc_inq_varid(ncid, "time", &varid) == NC_NOERR) {
7149 NC(nc_get_var_double(ncid, varid, &rtime));
7150 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
7151 WARN("Time information in meteo file does not match filename!");
7152 } else
7153 WARN("Time information in meteo file is missing!");
7154 }
7155
7156 /* CLaMS meteo files... */
7157 else {
7158
7159 /* Read time from file... */
7160 NC_GET_DOUBLE("time", &rtime, 0);
7161
7162 /* Get time from filename (considering the century)... */
7163 if (rtime < 0)
7164 sprintf(tstr, "19%.2s", &filename[strlen(filename) - 11]);
7165 else
7166 sprintf(tstr, "20%.2s", &filename[strlen(filename) - 11]);
7167 year = atoi(tstr);
7168 sprintf(tstr, "%.2s", &filename[strlen(filename) - 9]);
7169 mon = atoi(tstr);
7170 sprintf(tstr, "%.2s", &filename[strlen(filename) - 7]);
7171 day = atoi(tstr);
7172 sprintf(tstr, "%.2s", &filename[strlen(filename) - 5]);
7173 hour = atoi(tstr);
7174 time2jsec(year, mon, day, hour, 0, 0, 0, &met->time);
7175 }
7176
7177 /* Check time... */
7178 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
7179 || day < 1 || day > 31 || hour < 0 || hour > 23)
7180 ERRMSG("Cannot read time from filename!");
7181 jsec2time(met->time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
7182 LOG(2, "Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
7183 met->time, year2, mon2, day2, hour2, min2);
7184
7185 /* Get grid dimensions... */
7186 NC_INQ_DIM("lon", &met->nx, 2, EX);
7187 LOG(2, "Number of longitudes: %d", met->nx);
7188
7189 NC_INQ_DIM("lat", &met->ny, 2, EY);
7190 LOG(2, "Number of latitudes: %d", met->ny);
7191
7192 int dimid2;
7193 sprintf(levname, "lev");
7194 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
7195 sprintf(levname, "plev");
7196 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
7197 sprintf(levname, "hybrid");
7198
7199 NC_INQ_DIM(levname, &met->np, 1, EP);
7200 if (met->np == 1) {
7201 sprintf(levname, "lev_2");
7202 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR) {
7203 sprintf(levname, "plev");
7204 NC(nc_inq_dimid(ncid, levname, &dimid2));
7205 }
7206 NC(nc_inq_dimlen(ncid, dimid2, &np));
7207 met->np = (int) np;
7208 }
7209 LOG(2, "Number of levels: %d", met->np);
7210 if (met->np < 2 || met->np > EP)
7211 ERRMSG("Number of levels out of range!");
7212
7213 /* Read longitudes and latitudes... */
7214 NC_GET_DOUBLE("lon", met->lon, 1);
7215 LOG(2, "Longitudes: %g, %g ... %g deg",
7216 met->lon[0], met->lon[1], met->lon[met->nx - 1]);
7217 NC_GET_DOUBLE("lat", met->lat, 1);
7218 LOG(2, "Latitudes: %g, %g ... %g deg",
7219 met->lat[0], met->lat[1], met->lat[met->ny - 1]);
7220
7221 /* Check grid spacing... */
7222 for (int ix = 2; ix < met->nx; ix++)
7223 if (fabs
7224 (fabs(met->lon[ix] - met->lon[ix - 1]) -
7225 fabs(met->lon[1] - met->lon[0])) > 0.001)
7226 ERRMSG("No regular grid spacing in longitudes!");
7227 for (int iy = 2; iy < met->ny; iy++)
7228 if (fabs
7229 (fabs(met->lat[iy] - met->lat[iy - 1]) -
7230 fabs(met->lat[1] - met->lat[0])) > 0.001) {
7231 WARN("No regular grid spacing in latitudes!");
7232 break;
7233 }
7234
7235 /* Read pressure levels... */
7236 if (ctl->met_np <= 0) {
7237 NC_GET_DOUBLE(levname, met->p, 1);
7238 for (int ip = 0; ip < met->np; ip++)
7239 met->p[ip] /= 100.;
7240 LOG(2, "Altitude levels: %g, %g ... %g km",
7241 Z(met->p[0]), Z(met->p[1]), Z(met->p[met->np - 1]));
7242 LOG(2, "Pressure levels: %g, %g ... %g hPa",
7243 met->p[0], met->p[1], met->p[met->np - 1]);
7244 }
7245
7246 /* Read hybrid levels... */
7247 if (strcasecmp(levname, "hybrid") == 0)
7248 NC_GET_DOUBLE("hybrid", met->hybrid, 1);
7249}
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:9143
double time_from_filename(const char *filename, const int offset)
Extracts and converts a timestamp from a filename to Julian seconds.
Definition: mptrac.c:9242
double hybrid[EP]
Model hybrid levels.
Definition: mptrac.h:3403
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 7253 of file mptrac.c.

7256 {
7257
7258 /* Set timer... */
7259 SELECT_TIMER("READ_MET_LEVELS", "INPUT", NVTX_READ);
7260 LOG(2, "Read level data...");
7261
7262 /* Read temperature... */
7263 if (!read_met_nc_3d(ncid, "t", "T", "temp", "TEMP", ctl, met, met->t, 1.0))
7264 ERRMSG("Cannot read temperature!");
7265
7266 /* Read horizontal wind and vertical velocity... */
7267 if (!read_met_nc_3d(ncid, "u", "U", NULL, NULL, ctl, met, met->u, 1.0))
7268 ERRMSG("Cannot read zonal wind!");
7269 if (!read_met_nc_3d(ncid, "v", "V", NULL, NULL, ctl, met, met->v, 1.0))
7270 ERRMSG("Cannot read meridional wind!");
7271 if (!read_met_nc_3d
7272 (ncid, "w", "W", "omega", "OMEGA", ctl, met, met->w, 0.01f))
7273 WARN("Cannot read vertical velocity!");
7274
7275 /* Read water vapor... */
7276 if (!ctl->met_relhum) {
7277 if (!read_met_nc_3d
7278 (ncid, "q", "Q", "sh", "SH", ctl, met, met->h2o, (float) (MA / MH2O)))
7279 WARN("Cannot read specific humidity!");
7280 } else {
7281 if (!read_met_nc_3d
7282 (ncid, "rh", "RH", NULL, NULL, ctl, met, met->h2o, 0.01f))
7283 WARN("Cannot read relative humidity!");
7284#pragma omp parallel for default(shared) collapse(2)
7285 for (int ix = 0; ix < met->nx; ix++)
7286 for (int iy = 0; iy < met->ny; iy++)
7287 for (int ip = 0; ip < met->np; ip++) {
7288 double pw = met->h2o[ix][iy][ip] * PSAT(met->t[ix][iy][ip]);
7289 met->h2o[ix][iy][ip] =
7290 (float) (pw / (met->p[ip] - (1.0 - EPS) * pw));
7291 }
7292 }
7293
7294 /* Read ozone... */
7295 if (!read_met_nc_3d
7296 (ncid, "o3", "O3", NULL, NULL, ctl, met, met->o3, (float) (MA / MO3)))
7297 WARN("Cannot read ozone data!");
7298
7299 /* Read cloud data... */
7300 if (!read_met_nc_3d
7301 (ncid, "clwc", "CLWC", NULL, NULL, ctl, met, met->lwc, 1.0))
7302 WARN("Cannot read cloud liquid water content!");
7303 if (!read_met_nc_3d
7304 (ncid, "crwc", "CRWC", NULL, NULL, ctl, met, met->rwc, 1.0))
7305 WARN("Cannot read cloud rain water content!");
7306 if (!read_met_nc_3d
7307 (ncid, "ciwc", "CIWC", NULL, NULL, ctl, met, met->iwc, 1.0))
7308 WARN("Cannot read cloud ice water content!");
7309 if (!read_met_nc_3d
7310 (ncid, "cswc", "CSWC", NULL, NULL, ctl, met, met->swc, 1.0))
7311 WARN("Cannot read cloud snow water content!");
7312 if (!read_met_nc_3d(ncid, "cc", "CC", NULL, NULL, ctl, met, met->cc, 1.0))
7313 WARN("Cannot read cloud cover!");
7314
7315 /* Read zeta and zeta_dot... */
7316 if (!read_met_nc_3d
7317 (ncid, "ZETA", "zeta", NULL, NULL, ctl, met, met->zetal, 1.0))
7318 WARN("Cannot read ZETA!");
7319 if (!read_met_nc_3d
7320 (ncid, "ZETA_DOT_TOT", "ZETA_DOT_clr", "zeta_dot_clr",
7321 NULL, ctl, met, met->zeta_dotl, 0.00001157407f))
7322 WARN("Cannot read ZETA_DOT!");
7323
7324 /* Store velocities on model levels... */
7325 if (ctl->met_vert_coord != 0) {
7326 for (int ix = 0; ix < met->nx; ix++)
7327 for (int iy = 0; iy < met->ny; iy++)
7328 for (int ip = 0; ip < met->np; ip++) {
7329 met->ul[ix][iy][ip] = met->u[ix][iy][ip];
7330 met->vl[ix][iy][ip] = met->v[ix][iy][ip];
7331 met->wl[ix][iy][ip] = met->w[ix][iy][ip];
7332 }
7333
7334 /* Save number of model levels... */
7335 met->npl = met->np;
7336 }
7337
7338 /* Get pressure on model levels... */
7339 if (ctl->met_np > 0 || ctl->met_vert_coord != 0) {
7340
7341 /* Read 3-D pressure field... */
7342 if (ctl->met_vert_coord == 1) {
7343 if (!read_met_nc_3d
7344 (ncid, "pl", "PL", "pressure", "PRESSURE", ctl, met, met->pl,
7345 0.01f))
7346 if (!read_met_nc_3d
7347 (ncid, "press", "PRESS", NULL, NULL, ctl, met, met->pl, 1.0))
7348 ERRMSG("Cannot read pressure on model levels!");
7349 }
7350
7351 /* Use a and b coefficients for full levels... */
7352 else if (ctl->met_vert_coord == 2 || ctl->met_vert_coord == 3) {
7353
7354 /* Grid level coefficients... */
7355 double hyam[EP], hybm[EP];
7356
7357 /* Read coefficients... */
7358 if (ctl->met_vert_coord == 2) {
7359 int varid;
7360 NC_GET_DOUBLE("hyam", hyam, 1);
7361 NC_GET_DOUBLE("hybm", hybm, 1);
7362 }
7363
7364 /* Use control parameters... */
7365 else if (ctl->met_vert_coord == 3) {
7366
7367 /* Check number of levels... */
7368 if (met->np != ctl->met_nlev)
7369 ERRMSG("Mismatch in number of model levels!");
7370
7371 /* Copy parameters... */
7372 for (int ip = 0; ip < met->np; ip++) {
7373 hyam[ip] = ctl->met_lev_hyam[ip];
7374 hybm[ip] = ctl->met_lev_hybm[ip];
7375 }
7376 }
7377
7378 /* Calculate pressure... */
7379 for (int ix = 0; ix < met->nx; ix++)
7380 for (int iy = 0; iy < met->ny; iy++)
7381 for (int ip = 0; ip < met->np; ip++)
7382 met->pl[ix][iy][ip] =
7383 (float) (hyam[ip] / 100. + hybm[ip] * met->ps[ix][iy]);
7384 }
7385
7386 /* Use a and b coefficients for half levels... */
7387 else if (ctl->met_vert_coord == 4) {
7388
7389 /* Grid level coefficients... */
7390 double hyam[EP], hybm[EP];
7391
7392 /* Use control parameters... */
7393 for (int ip = 0; ip < met->np + 1; ip++) {
7394 hyam[ip] = ctl->met_lev_hyam[ip];
7395 hybm[ip] = ctl->met_lev_hybm[ip];
7396 }
7397
7398 /* Check number of levels... */
7399 if (met->np + 1 != ctl->met_nlev)
7400 ERRMSG("Mismatch in number of model levels!");
7401
7402 /* Calculate pressure... */
7403#pragma omp parallel for default(shared) collapse(2)
7404 for (int ix = 0; ix < met->nx; ix++)
7405 for (int iy = 0; iy < met->ny; iy++)
7406 for (int ip = 0; ip < met->np; ip++) {
7407 double p0 = hyam[ip] / 100. + hybm[ip] * met->ps[ix][iy];
7408 double p1 = hyam[ip + 1] / 100. + hybm[ip + 1] * met->ps[ix][iy];
7409 met->pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
7410 }
7411 }
7412
7413 /* Check ordering of pressure levels... */
7414 for (int ix = 0; ix < met->nx; ix++)
7415 for (int iy = 0; iy < met->ny; iy++)
7416 for (int ip = 1; ip < met->np; ip++)
7417 if ((met->pl[ix][iy][0] > met->pl[ix][iy][1]
7418 && met->pl[ix][iy][ip - 1] <= met->pl[ix][iy][ip])
7419 || (met->pl[ix][iy][0] < met->pl[ix][iy][1]
7420 && met->pl[ix][iy][ip - 1] >= met->pl[ix][iy][ip]))
7421 ERRMSG("Pressure profiles are not monotonic!");
7422 }
7423
7424 /* Interpolate from model levels to pressure levels... */
7425 if (ctl->met_np > 0) {
7426
7427 /* Interpolate variables... */
7428 read_met_ml2pl(ctl, met, met->t, "T");
7429 read_met_ml2pl(ctl, met, met->u, "U");
7430 read_met_ml2pl(ctl, met, met->v, "V");
7431 read_met_ml2pl(ctl, met, met->w, "W");
7432 read_met_ml2pl(ctl, met, met->h2o, "H2O");
7433 read_met_ml2pl(ctl, met, met->o3, "O3");
7434 read_met_ml2pl(ctl, met, met->lwc, "LWC");
7435 read_met_ml2pl(ctl, met, met->rwc, "RWC");
7436 read_met_ml2pl(ctl, met, met->iwc, "IWC");
7437 read_met_ml2pl(ctl, met, met->swc, "SWC");
7438 read_met_ml2pl(ctl, met, met->cc, "CC");
7439
7440 /* Set new pressure levels... */
7441 met->np = ctl->met_np;
7442 for (int ip = 0; ip < met->np; ip++)
7443 met->p[ip] = ctl->met_p[ip];
7444 }
7445
7446 /* Check ordering of pressure levels... */
7447 for (int ip = 1; ip < met->np; ip++)
7448 if (met->p[ip - 1] < met->p[ip])
7449 ERRMSG("Pressure levels must be descending!");
7450}
void read_met_ml2pl(const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname)
Interpolates meteorological data to specified pressure levels.
Definition: mptrac.c:7454
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:7810
#define MH2O
Molar mass of water vapor [g/mol].
Definition: mptrac.h:202
#define MO3
Molar mass of ozone [g/mol].
Definition: mptrac.h:207
int met_vert_coord
Vertical coordinate of input meteo data (0=plev, 1=mlev_p_file, 2=mlev_ab_file, 3=mlev_ab_full,...
Definition: mptrac.h:2479
Here is the call graph for this function:

◆ read_met_ml2pl()

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

Interpolates meteorological data to specified pressure levels.

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

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

This function performs the following steps:

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

Definition at line 7454 of file mptrac.c.

7458 {
7459
7460 double aux[EP], p[EP];
7461
7462 /* Set timer... */
7463 SELECT_TIMER("READ_MET_ML2PL", "METPROC", NVTX_READ);
7464 LOG(2, "Interpolate meteo data to pressure levels: %s", varname);
7465
7466 /* Loop over columns... */
7467#pragma omp parallel for default(shared) private(aux,p) collapse(2)
7468 for (int ix = 0; ix < met->nx; ix++)
7469 for (int iy = 0; iy < met->ny; iy++) {
7470
7471 /* Copy pressure profile... */
7472 for (int ip = 0; ip < met->np; ip++)
7473 p[ip] = met->pl[ix][iy][ip];
7474
7475 /* Interpolate... */
7476 for (int ip = 0; ip < ctl->met_np; ip++) {
7477 double pt = ctl->met_p[ip];
7478 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
7479 pt = p[0];
7480 else if ((pt > p[met->np - 1] && p[1] > p[0])
7481 || (pt < p[met->np - 1] && p[1] < p[0]))
7482 pt = p[met->np - 1];
7483 int ip2 = locate_irr(p, met->np, pt);
7484 aux[ip] = LIN(p[ip2], var[ix][iy][ip2],
7485 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
7486 }
7487
7488 /* Copy data... */
7489 for (int ip = 0; ip < ctl->met_np; ip++)
7490 var[ix][iy][ip] = (float) aux[ip];
7491 }
7492}
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 7496 of file mptrac.c.

7498 {
7499
7500 /* Check parameters... */
7501 if (ctl->advect_vert_coord != 1)
7502 return;
7503
7504 /* Set timer... */
7505 SELECT_TIMER("READ_MET_MONOTONIZE", "METPROC", NVTX_READ);
7506 LOG(2, "Make zeta profiles monotone...");
7507
7508 /* Create monotone zeta profiles... */
7509#pragma omp parallel for default(shared) collapse(2)
7510 for (int i = 0; i < met->nx; i++)
7511 for (int j = 0; j < met->ny; j++) {
7512 int k = 1;
7513
7514 while (k < met->npl) { /* Check if there is an inversion at level k... */
7515 if ((met->zetal[i][j][k - 1] >= met->zetal[i][j][k])) {
7516 /* Find the upper level k+l over the inversion... */
7517 int l = 0;
7518 do {
7519 l++;
7520 }
7521 while ((met->zetal[i][j][k - 1] >=
7522 met->zetal[i][j][k + l]) & (k + l < met->npl));
7523
7524 /* Interpolate linear between the top and bottom
7525 of the inversion... */
7526 float s =
7527 (float) (met->zetal[i][j][k + l] - met->zetal[i][j][k - 1])
7528 / (float) (met->hybrid[k + l] - met->hybrid[k - 1]);
7529
7530 for (int m = k; m < k + l; m++) {
7531 float d = (float) (met->hybrid[m] - met->hybrid[k - 1]);
7532 met->zetal[i][j][m] = s * d + met->zetal[i][j][k - 1];
7533 }
7534
7535 /* Search for more inversions above the last inversion ... */
7536 k = k + l;
7537 } else {
7538 k++;
7539 }
7540 }
7541 }
7542
7543 /* Create monotone pressure profiles... */
7544#pragma omp parallel for default(shared) collapse(2)
7545 for (int i = 0; i < met->nx; i++)
7546 for (int j = 0; j < met->ny; j++) {
7547 int k = 1;
7548
7549 while (k < met->npl) { /* Check if there is an inversion at level k... */
7550 if ((met->pl[i][j][k - 1] <= met->pl[i][j][k])) {
7551
7552 /* Find the upper level k+l over the inversion... */
7553 int l = 0;
7554 do {
7555 l++;
7556 }
7557 while ((met->pl[i][j][k - 1] <= met->pl[i][j][k + l]) & (k + l <
7558 met->npl));
7559
7560 /* Interpolate linear between the top and bottom
7561 of the inversion... */
7562 float s = (float) (met->pl[i][j][k + l] - met->pl[i][j][k - 1])
7563 / (float) (met->hybrid[k + l] - met->hybrid[k - 1]);
7564
7565 for (int m = k; m < k + l; m++) {
7566 float d = (float) (met->hybrid[m] - met->hybrid[k - 1]);
7567 met->pl[i][j][m] = s * d + met->pl[i][j][k - 1];
7568 }
7569
7570 /* Search for more inversions above the last inversion ... */
7571 k += l;
7572 } else {
7573 k++;
7574 }
7575 }
7576 }
7577}

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

7585 {
7586
7587 int ncid;
7588
7589 /* Open netCDF file... */
7590 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7591 WARN("Cannot open file!");
7592 return 0;
7593 }
7594
7595 /* Read coordinates of meteo data... */
7596 read_met_grid(filename, ncid, ctl, met);
7597
7598 /* Read surface data... */
7599 read_met_surface(ncid, ctl, met);
7600
7601 /* Read meteo data on vertical levels... */
7602 read_met_levels(ncid, ctl, met);
7603
7604 /* Extrapolate data for lower boundary... */
7606
7607 /* Fix polar winds... */
7609
7610 /* Create periodic boundary conditions... */
7611 read_met_periodic(met);
7612
7613 /* Downsampling... */
7614 read_met_sample(ctl, met);
7615
7616 /* Calculate geopotential heights... */
7617 read_met_geopot(ctl, met);
7618
7619 /* Calculate potential vorticity... */
7620 read_met_pv(met);
7621
7622 /* Calculate boundary layer data... */
7623 read_met_pbl(ctl, met);
7624
7625 /* Calculate tropopause data... */
7626 read_met_tropo(ctl, clim, met);
7627
7628 /* Calculate cloud properties... */
7629 read_met_cloud(met);
7630
7631 /* Calculate convective available potential energy... */
7632 read_met_cape(ctl, clim, met);
7633
7634 /* Calculate total column ozone... */
7635 read_met_ozone(met);
7636
7637 /* Detrending... */
7638 read_met_detrend(ctl, met);
7639
7640 /* Check meteo data and smooth zeta profiles ... */
7641 read_met_monotonize(ctl, met);
7642
7643 /* Close file... */
7644 NC(nc_close(ncid));
7645
7646 /* Return success... */
7647 return 1;
7648}
void read_met_geopot(const ctl_t *ctl, met_t *met)
Calculates geopotential heights from meteorological data.
Definition: mptrac.c:6993
void read_met_extrapolate(met_t *met)
Extrapolates meteorological data.
Definition: mptrac.c:6953
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:7253
void read_met_sample(const ctl_t *ctl, met_t *met)
Downsamples meteorological data based on specified parameters.
Definition: mptrac.c:8348
void read_met_cloud(met_t *met)
Calculates cloud-related variables for each grid point.
Definition: mptrac.c:6792
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:7956
void read_met_detrend(const ctl_t *ctl, met_t *met)
Detrends meteorological data.
Definition: mptrac.c:6849
void read_met_monotonize(const ctl_t *ctl, met_t *met)
Makes zeta and pressure profiles monotone.
Definition: mptrac.c:7496
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
Definition: mptrac.c:8093
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:7121
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:8520
void read_met_ozone(met_t *met)
Calculates the total column ozone from meteorological ozone data.
Definition: mptrac.c:8319
void read_met_pv(met_t *met)
Calculates potential vorticity (PV) from meteorological data.
Definition: mptrac.c:8213
void read_met_polar_winds(met_t *met)
Applies a fix for polar winds in meteorological data.
Definition: mptrac.c:8154
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:6677
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 7652 of file mptrac.c.

7664 {
7665
7666 char varsel[LEN];
7667
7668 float offset, scalfac;
7669
7670 int varid;
7671
7672 /* Check if variable exists... */
7673 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
7674 sprintf(varsel, "%s", varname);
7675 else if (varname2 != NULL
7676 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
7677 sprintf(varsel, "%s", varname2);
7678 else if (varname3 != NULL
7679 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
7680 sprintf(varsel, "%s", varname3);
7681 else if (varname4 != NULL
7682 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
7683 sprintf(varsel, "%s", varname4);
7684 else if (varname5 != NULL
7685 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
7686 sprintf(varsel, "%s", varname5);
7687 else if (varname6 != NULL
7688 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
7689 sprintf(varsel, "%s", varname6);
7690 else
7691 return 0;
7692
7693 /* Read packed data... */
7694 if (ctl->met_nc_scale
7695 && nc_get_att_float(ncid, varid, "add_offset", &offset) == NC_NOERR
7696 && nc_get_att_float(ncid, varid, "scale_factor",
7697 &scalfac) == NC_NOERR) {
7698
7699 /* Allocate... */
7700 short *help;
7701 ALLOC(help, short,
7702 EX * EY * EP);
7703
7704 /* Read fill value and missing value... */
7705 short fillval, missval;
7706 if (nc_get_att_short(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
7707 fillval = 0;
7708 if (nc_get_att_short(ncid, varid, "missing_value", &missval) != NC_NOERR)
7709 missval = 0;
7710
7711 /* Write info... */
7712 LOG(2, "Read 2-D variable: %s"
7713 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
7714 varsel, fillval, missval, scalfac, offset);
7715
7716 /* Read data... */
7717 NC(nc_get_var_short(ncid, varid, help));
7718
7719 /* Check meteo data layout... */
7720 if (ctl->met_convention != 0)
7721 ERRMSG("Meteo data layout not implemented for packed netCDF files!");
7722
7723 /* Copy and check data... */
7724#pragma omp parallel for default(shared) num_threads(12)
7725 for (int ix = 0; ix < met->nx; ix++)
7726 for (int iy = 0; iy < met->ny; iy++) {
7727 if (init)
7728 dest[ix][iy] = 0;
7729 const short aux = help[ARRAY_2D(iy, ix, met->nx)];
7730 if ((fillval == 0 || aux != fillval)
7731 && (missval == 0 || aux != missval)
7732 && fabsf(aux * scalfac + offset) < 1e14f)
7733 dest[ix][iy] += scl * (aux * scalfac + offset);
7734 else
7735 dest[ix][iy] = NAN;
7736 }
7737
7738 /* Free... */
7739 free(help);
7740 }
7741
7742 /* Unpacked data... */
7743 else {
7744
7745 /* Allocate... */
7746 float *help;
7747 ALLOC(help, float,
7748 EX * EY);
7749
7750 /* Read fill value and missing value... */
7751 float fillval, missval;
7752 if (nc_get_att_float(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
7753 fillval = 0;
7754 if (nc_get_att_float(ncid, varid, "missing_value", &missval) != NC_NOERR)
7755 missval = 0;
7756
7757 /* Write info... */
7758 LOG(2, "Read 2-D variable: %s (FILL = %g, MISS = %g)",
7759 varsel, fillval, missval);
7760
7761 /* Read data... */
7762 NC(nc_get_var_float(ncid, varid, help));
7763
7764 /* Check meteo data layout... */
7765 if (ctl->met_convention == 0) {
7766
7767 /* Copy and check data (ordering: lat, lon)... */
7768#pragma omp parallel for default(shared) num_threads(12)
7769 for (int ix = 0; ix < met->nx; ix++)
7770 for (int iy = 0; iy < met->ny; iy++) {
7771 if (init)
7772 dest[ix][iy] = 0;
7773 const float aux = help[ARRAY_2D(iy, ix, met->nx)];
7774 if ((fillval == 0 || aux != fillval)
7775 && (missval == 0 || aux != missval)
7776 && fabsf(aux) < 1e14f)
7777 dest[ix][iy] += scl * aux;
7778 else
7779 dest[ix][iy] = NAN;
7780 }
7781
7782 } else {
7783
7784 /* Copy and check data (ordering: lon, lat)... */
7785#pragma omp parallel for default(shared) num_threads(12)
7786 for (int iy = 0; iy < met->ny; iy++)
7787 for (int ix = 0; ix < met->nx; ix++) {
7788 if (init)
7789 dest[ix][iy] = 0;
7790 const float aux = help[ARRAY_2D(ix, iy, met->ny)];
7791 if ((fillval == 0 || aux != fillval)
7792 && (missval == 0 || aux != missval)
7793 && fabsf(aux) < 1e14f)
7794 dest[ix][iy] += scl * aux;
7795 else
7796 dest[ix][iy] = NAN;
7797 }
7798 }
7799
7800 /* Free... */
7801 free(help);
7802 }
7803
7804 /* Return... */
7805 return 1;
7806}
int met_nc_scale
Check netCDF scaling factors (0=no, 1=yes).
Definition: mptrac.h:2489
int met_convention
Meteo data layout (0=[lev, lat, lon], 1=[lon, lat, lev]).
Definition: mptrac.h:2475

◆ read_met_nc_3d()

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

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

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

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

The function performs the following steps:

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

Definition at line 7810 of file mptrac.c.

7819 {
7820
7821 char varsel[LEN];
7822
7823 float offset, scalfac;
7824
7825 int varid;
7826
7827 /* Check if variable exists... */
7828 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
7829 sprintf(varsel, "%s", varname);
7830 else if (varname2 != NULL
7831 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
7832 sprintf(varsel, "%s", varname2);
7833 else if (varname3 != NULL
7834 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
7835 sprintf(varsel, "%s", varname3);
7836 else if (varname4 != NULL
7837 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
7838 sprintf(varsel, "%s", varname4);
7839 else
7840 return 0;
7841
7842 /* Read packed data... */
7843 if (ctl->met_nc_scale
7844 && nc_get_att_float(ncid, varid, "add_offset", &offset) == NC_NOERR
7845 && nc_get_att_float(ncid, varid, "scale_factor",
7846 &scalfac) == NC_NOERR) {
7847
7848 /* Allocate... */
7849 short *help;
7850 ALLOC(help, short,
7851 EX * EY * EP);
7852
7853 /* Read fill value and missing value... */
7854 short fillval, missval;
7855 if (nc_get_att_short(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
7856 fillval = 0;
7857 if (nc_get_att_short(ncid, varid, "missing_value", &missval) != NC_NOERR)
7858 missval = 0;
7859
7860 /* Write info... */
7861 LOG(2, "Read 3-D variable: %s "
7862 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
7863 varsel, fillval, missval, scalfac, offset);
7864
7865 /* Read data... */
7866 NC(nc_get_var_short(ncid, varid, help));
7867
7868 /* Check meteo data layout... */
7869 if (ctl->met_convention != 0)
7870 ERRMSG("Meteo data layout not implemented for packed netCDF files!");
7871
7872 /* Copy and check data... */
7873#pragma omp parallel for default(shared) num_threads(12)
7874 for (int ix = 0; ix < met->nx; ix++)
7875 for (int iy = 0; iy < met->ny; iy++)
7876 for (int ip = 0; ip < met->np; ip++) {
7877 const short aux = help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)];
7878 if ((fillval == 0 || aux != fillval)
7879 && (missval == 0 || aux != missval)
7880 && fabsf(aux * scalfac + offset) < 1e14f)
7881 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
7882 else
7883 dest[ix][iy][ip] = NAN;
7884 }
7885
7886 /* Free... */
7887 free(help);
7888 }
7889
7890 /* Unpacked data... */
7891 else {
7892
7893 /* Allocate... */
7894 float *help;
7895 ALLOC(help, float,
7896 EX * EY * EP);
7897
7898 /* Read fill value and missing value... */
7899 float fillval, missval;
7900 if (nc_get_att_float(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
7901 fillval = 0;
7902 if (nc_get_att_float(ncid, varid, "missing_value", &missval) != NC_NOERR)
7903 missval = 0;
7904
7905 /* Write info... */
7906 LOG(2, "Read 3-D variable: %s (FILL = %g, MISS = %g)",
7907 varsel, fillval, missval);
7908
7909 /* Read data... */
7910 NC(nc_get_var_float(ncid, varid, help));
7911
7912 /* Check meteo data layout... */
7913 if (ctl->met_convention == 0) {
7914
7915 /* Copy and check data (ordering: lev, lat, lon)... */
7916#pragma omp parallel for default(shared) num_threads(12)
7917 for (int ix = 0; ix < met->nx; ix++)
7918 for (int iy = 0; iy < met->ny; iy++)
7919 for (int ip = 0; ip < met->np; ip++) {
7920 const float aux = help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)];
7921 if ((fillval == 0 || aux != fillval)
7922 && (missval == 0 || aux != missval)
7923 && fabsf(aux) < 1e14f)
7924 dest[ix][iy][ip] = scl * aux;
7925 else
7926 dest[ix][iy][ip] = NAN;
7927 }
7928
7929 } else {
7930
7931 /* Copy and check data (ordering: lon, lat, lev)... */
7932#pragma omp parallel for default(shared) num_threads(12)
7933 for (int ip = 0; ip < met->np; ip++)
7934 for (int iy = 0; iy < met->ny; iy++)
7935 for (int ix = 0; ix < met->nx; ix++) {
7936 const float aux = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
7937 if ((fillval == 0 || aux != fillval)
7938 && (missval == 0 || aux != missval)
7939 && fabsf(aux) < 1e14f)
7940 dest[ix][iy][ip] = scl * aux;
7941 else
7942 dest[ix][iy][ip] = NAN;
7943 }
7944 }
7945
7946 /* Free... */
7947 free(help);
7948 }
7949
7950 /* Return... */
7951 return 1;
7952}

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

7958 {
7959
7960 /* Set timer... */
7961 SELECT_TIMER("READ_MET_PBL", "METPROC", NVTX_READ);
7962 LOG(2, "Calculate planetary boundary layer...");
7963
7964 /* Convert PBL height from meteo file to pressure... */
7965 if (ctl->met_pbl == 1) {
7966
7967 /* Loop over grid points... */
7968#pragma omp parallel for default(shared) collapse(2)
7969 for (int ix = 0; ix < met->nx; ix++)
7970 for (int iy = 0; iy < met->ny; iy++) {
7971
7972 /* Get pressure at top of PBL... */
7973 const float z = met->zs[ix][iy] + met->pbl[ix][iy];
7974 const int ip = locate_irr_float(met->z[ix][iy], met->np, z, 0);
7975 met->pbl[ix][iy] =
7976 (float) (LIN(met->z[ix][iy][ip], met->p[ip],
7977 met->z[ix][iy][ip + 1], met->p[ip + 1], z));
7978 }
7979 }
7980
7981 /* Determine PBL based on Richardson number... */
7982 else if (ctl->met_pbl == 2) {
7983
7984 /* Parameters used to estimate the height of the PBL
7985 (e.g., Vogelezang and Holtslag, 1996; Seidel et al., 2012)... */
7986 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
7987
7988 /* Loop over grid points... */
7989#pragma omp parallel for default(shared) collapse(2)
7990 for (int ix = 0; ix < met->nx; ix++)
7991 for (int iy = 0; iy < met->ny; iy++) {
7992
7993 /* Set bottom level of PBL... */
7994 const double pbl_bot = met->ps[ix][iy] * exp(-dz / H0);
7995
7996 /* Find lowest level near the bottom... */
7997 int ip;
7998 for (ip = 1; ip < met->np; ip++)
7999 if (met->p[ip] < pbl_bot)
8000 break;
8001
8002 /* Get near surface data... */
8003 const double h2os = LIN(met->p[ip - 1], met->h2o[ix][iy][ip - 1],
8004 met->p[ip], met->h2o[ix][iy][ip], pbl_bot);
8005 const double tvs = THETAVIRT(pbl_bot, met->ts[ix][iy], h2os);
8006
8007 /* Init... */
8008 double rib_old = 0;
8009
8010 /* Loop over levels... */
8011 for (; ip < met->np; ip++) {
8012
8013 /* Get squared horizontal wind speed... */
8014 double vh2 = SQR(met->u[ix][iy][ip] - met->us[ix][iy])
8015 + SQR(met->v[ix][iy][ip] - met->vs[ix][iy]);
8016 vh2 = MAX(vh2, SQR(umin));
8017
8018 /* Calculate bulk Richardson number... */
8019 const double rib =
8020 G0 * 1e3 * (met->z[ix][iy][ip] - met->zs[ix][iy]) / tvs
8021 * (THETAVIRT(met->p[ip], met->t[ix][iy][ip],
8022 met->h2o[ix][iy][ip]) - tvs) / vh2;
8023
8024 /* Check for critical value... */
8025 if (rib >= rib_crit) {
8026 met->pbl[ix][iy] = (float) (LIN(rib_old, met->p[ip - 1],
8027 rib, met->p[ip], rib_crit));
8028 if (met->pbl[ix][iy] > pbl_bot)
8029 met->pbl[ix][iy] = (float) pbl_bot;
8030 break;
8031 }
8032
8033 /* Save Richardson number... */
8034 rib_old = rib;
8035 }
8036 }
8037 }
8038
8039 /* Determine PBL based on potential temperature... */
8040 if (ctl->met_pbl == 3) {
8041
8042 /* Parameters used to estimate the height of the PBL
8043 (following HYSPLIT model)... */
8044 const double dtheta = 2.0, zmin = 0.1;
8045
8046 /* Loop over grid points... */
8047#pragma omp parallel for default(shared) collapse(2)
8048 for (int ix = 0; ix < met->nx; ix++)
8049 for (int iy = 0; iy < met->ny; iy++) {
8050
8051 /* Potential temperature at the surface... */
8052 const double theta0 = THETA(met->ps[ix][iy], met->ts[ix][iy]);
8053
8054 /* Find topmost level where theta exceeds surface value by 2 K... */
8055 int ip;
8056 for (ip = met->np - 2; ip > 0; ip--)
8057 if (met->p[ip] >= 300.)
8058 if (met->p[ip] > met->ps[ix][iy]
8059 || THETA(met->p[ip], met->t[ix][iy][ip]) <= theta0 + dtheta)
8060 break;
8061
8062 /* Interpolate... */
8063 met->pbl[ix][iy]
8064 = (float) (LIN(THETA(met->p[ip + 1], met->t[ix][iy][ip + 1]),
8065 met->p[ip + 1],
8066 THETA(met->p[ip], met->t[ix][iy][ip]),
8067 met->p[ip], theta0 + dtheta));
8068
8069 /* Check minimum value... */
8070 double pbl_min = met->ps[ix][iy] * exp(-zmin / H0);
8071 if (met->pbl[ix][iy] > pbl_min || met->p[ip] > met->ps[ix][iy])
8072 met->pbl[ix][iy] = (float) pbl_min;
8073 }
8074 }
8075
8076 /* Loop over grid points... */
8077#pragma omp parallel for default(shared) collapse(2)
8078 for (int ix = 0; ix < met->nx; ix++)
8079 for (int iy = 0; iy < met->ny; iy++) {
8080
8081 /* Check minimum value... */
8082 double pbl_min = met->ps[ix][iy] * exp(-ctl->met_pbl_min / H0);
8083 met->pbl[ix][iy] = MIN(met->pbl[ix][iy], (float) pbl_min);
8084
8085 /* Check maximum value... */
8086 double pbl_max = met->ps[ix][iy] * exp(-ctl->met_pbl_max / H0);
8087 met->pbl[ix][iy] = MAX(met->pbl[ix][iy], (float) pbl_max);
8088 }
8089}
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 8093 of file mptrac.c.

8094 {
8095
8096 /* Set timer... */
8097 SELECT_TIMER("READ_MET_PERIODIC", "METPROC", NVTX_READ);
8098 LOG(2, "Apply periodic boundary conditions...");
8099
8100 /* Check longitudes... */
8101 if (!(fabs(met->lon[met->nx - 1] - met->lon[0]
8102 + met->lon[1] - met->lon[0] - 360) < 0.01))
8103 return;
8104
8105 /* Increase longitude counter... */
8106 if ((++met->nx) >= EX)
8107 ERRMSG("Cannot create periodic boundary conditions!");
8108
8109 /* Set longitude... */
8110 met->lon[met->nx - 1] = met->lon[met->nx - 2] + met->lon[1] - met->lon[0];
8111
8112 /* Loop over latitudes and pressure levels... */
8113#pragma omp parallel for default(shared)
8114 for (int iy = 0; iy < met->ny; iy++) {
8115 met->ps[met->nx - 1][iy] = met->ps[0][iy];
8116 met->zs[met->nx - 1][iy] = met->zs[0][iy];
8117 met->ts[met->nx - 1][iy] = met->ts[0][iy];
8118 met->us[met->nx - 1][iy] = met->us[0][iy];
8119 met->vs[met->nx - 1][iy] = met->vs[0][iy];
8120 met->ess[met->nx - 1][iy] = met->ess[0][iy];
8121 met->nss[met->nx - 1][iy] = met->nss[0][iy];
8122 met->shf[met->nx - 1][iy] = met->shf[0][iy];
8123 met->lsm[met->nx - 1][iy] = met->lsm[0][iy];
8124 met->sst[met->nx - 1][iy] = met->sst[0][iy];
8125 met->pbl[met->nx - 1][iy] = met->pbl[0][iy];
8126 met->cape[met->nx - 1][iy] = met->cape[0][iy];
8127 met->cin[met->nx - 1][iy] = met->cin[0][iy];
8128 for (int ip = 0; ip < met->np; ip++) {
8129 met->t[met->nx - 1][iy][ip] = met->t[0][iy][ip];
8130 met->u[met->nx - 1][iy][ip] = met->u[0][iy][ip];
8131 met->v[met->nx - 1][iy][ip] = met->v[0][iy][ip];
8132 met->w[met->nx - 1][iy][ip] = met->w[0][iy][ip];
8133 met->h2o[met->nx - 1][iy][ip] = met->h2o[0][iy][ip];
8134 met->o3[met->nx - 1][iy][ip] = met->o3[0][iy][ip];
8135 met->lwc[met->nx - 1][iy][ip] = met->lwc[0][iy][ip];
8136 met->rwc[met->nx - 1][iy][ip] = met->rwc[0][iy][ip];
8137 met->iwc[met->nx - 1][iy][ip] = met->iwc[0][iy][ip];
8138 met->swc[met->nx - 1][iy][ip] = met->swc[0][iy][ip];
8139 met->cc[met->nx - 1][iy][ip] = met->cc[0][iy][ip];
8140 }
8141 for (int ip = 0; ip < met->npl; ip++) {
8142 met->ul[met->nx - 1][iy][ip] = met->ul[0][iy][ip];
8143 met->vl[met->nx - 1][iy][ip] = met->vl[0][iy][ip];
8144 met->wl[met->nx - 1][iy][ip] = met->wl[0][iy][ip];
8145 met->pl[met->nx - 1][iy][ip] = met->pl[0][iy][ip];
8146 met->zetal[met->nx - 1][iy][ip] = met->zetal[0][iy][ip];
8147 met->zeta_dotl[met->nx - 1][iy][ip] = met->zeta_dotl[0][iy][ip];
8148 }
8149 }
8150}

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

8155 {
8156
8157 /* Set timer... */
8158 SELECT_TIMER("READ_MET_POLAR_WINDS", "METPROC", NVTX_READ);
8159 LOG(2, "Apply fix for polar winds...");
8160
8161 /* Check latitudes... */
8162 if (fabs(met->lat[0]) < 89.999 || fabs(met->lat[met->ny - 1]) < 89.999)
8163 return;
8164
8165 /* Loop over hemispheres... */
8166 for (int ihem = 0; ihem < 2; ihem++) {
8167
8168 /* Set latitude indices... */
8169 int i89 = 1, i90 = 0, sign = 1;
8170 if (ihem == 1) {
8171 i89 = met->ny - 2;
8172 i90 = met->ny - 1;
8173 }
8174 if (met->lat[i90] < 0)
8175 sign = -1;
8176
8177 /* Look-up table of cosinus and sinus... */
8178 double clon[EX], slon[EX];
8179#pragma omp parallel for default(shared)
8180 for (int ix = 0; ix < met->nx; ix++) {
8181 clon[ix] = cos(sign * DEG2RAD(met->lon[ix]));
8182 slon[ix] = sin(sign * DEG2RAD(met->lon[ix]));
8183 }
8184
8185 /* Loop over levels... */
8186#pragma omp parallel for default(shared)
8187 for (int ip = 0; ip < met->np; ip++) {
8188
8189 /* Transform 89 degree u and v winds into Cartesian coordinates and take the mean... */
8190 double vel89x = 0, vel89y = 0;
8191 for (int ix = 0; ix < met->nx; ix++) {
8192 vel89x +=
8193 (met->u[ix][i89][ip] * clon[ix] -
8194 met->v[ix][i89][ip] * slon[ix]) / met->nx;
8195 vel89y +=
8196 (met->u[ix][i89][ip] * slon[ix] +
8197 met->v[ix][i89][ip] * clon[ix]) / met->nx;
8198 }
8199
8200 /* Replace 90 degree winds by 89 degree mean... */
8201 for (int ix = 0; ix < met->nx; ix++) {
8202 met->u[ix][i90][ip]
8203 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
8204 met->v[ix][i90][ip]
8205 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
8206 }
8207 }
8208 }
8209}

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

8214 {
8215
8216 double pows[EP];
8217
8218 /* Set timer... */
8219 SELECT_TIMER("READ_MET_PV", "METPROC", NVTX_READ);
8220 LOG(2, "Calculate potential vorticity...");
8221
8222 /* Set powers... */
8223#pragma omp parallel for default(shared)
8224 for (int ip = 0; ip < met->np; ip++)
8225 pows[ip] = pow(1000. / met->p[ip], 0.286);
8226
8227 /* Loop over grid points... */
8228#pragma omp parallel for default(shared)
8229 for (int ix = 0; ix < met->nx; ix++) {
8230
8231 /* Set indices... */
8232 const int ix0 = MAX(ix - 1, 0);
8233 const int ix1 = MIN(ix + 1, met->nx - 1);
8234
8235 /* Loop over grid points... */
8236 for (int iy = 0; iy < met->ny; iy++) {
8237
8238 /* Set indices... */
8239 const int iy0 = MAX(iy - 1, 0);
8240 const int iy1 = MIN(iy + 1, met->ny - 1);
8241
8242 /* Set auxiliary variables... */
8243 const double latr = 0.5 * (met->lat[iy1] + met->lat[iy0]);
8244 const double dx = 1000. * DEG2DX(met->lon[ix1] - met->lon[ix0], latr);
8245 const double dy = 1000. * DEG2DY(met->lat[iy1] - met->lat[iy0]);
8246 const double c0 = cos(DEG2RAD(met->lat[iy0]));
8247 const double c1 = cos(DEG2RAD(met->lat[iy1]));
8248 const double cr = cos(DEG2RAD(latr));
8249 const double vort = 2 * 7.2921e-5 * sin(DEG2RAD(latr));
8250
8251 /* Loop over grid points... */
8252 for (int ip = 0; ip < met->np; ip++) {
8253
8254 /* Get gradients in longitude... */
8255 const double dtdx
8256 = (met->t[ix1][iy][ip] - met->t[ix0][iy][ip]) * pows[ip] / dx;
8257 const double dvdx = (met->v[ix1][iy][ip] - met->v[ix0][iy][ip]) / dx;
8258
8259 /* Get gradients in latitude... */
8260 const double dtdy
8261 = (met->t[ix][iy1][ip] - met->t[ix][iy0][ip]) * pows[ip] / dy;
8262 const double dudy
8263 = (met->u[ix][iy1][ip] * c1 - met->u[ix][iy0][ip] * c0) / dy;
8264
8265 /* Set indices... */
8266 const int ip0 = MAX(ip - 1, 0);
8267 const int ip1 = MIN(ip + 1, met->np - 1);
8268
8269 /* Get gradients in pressure... */
8270 double dtdp, dudp, dvdp;
8271 const double dp0 = 100. * (met->p[ip] - met->p[ip0]);
8272 const double dp1 = 100. * (met->p[ip1] - met->p[ip]);
8273 if (ip != ip0 && ip != ip1) {
8274 double denom = dp0 * dp1 * (dp0 + dp1);
8275 dtdp = (dp0 * dp0 * met->t[ix][iy][ip1] * pows[ip1]
8276 - dp1 * dp1 * met->t[ix][iy][ip0] * pows[ip0]
8277 + (dp1 * dp1 - dp0 * dp0) * met->t[ix][iy][ip] * pows[ip])
8278 / denom;
8279 dudp = (dp0 * dp0 * met->u[ix][iy][ip1]
8280 - dp1 * dp1 * met->u[ix][iy][ip0]
8281 + (dp1 * dp1 - dp0 * dp0) * met->u[ix][iy][ip])
8282 / denom;
8283 dvdp = (dp0 * dp0 * met->v[ix][iy][ip1]
8284 - dp1 * dp1 * met->v[ix][iy][ip0]
8285 + (dp1 * dp1 - dp0 * dp0) * met->v[ix][iy][ip])
8286 / denom;
8287 } else {
8288 const double denom = dp0 + dp1;
8289 dtdp =
8290 (met->t[ix][iy][ip1] * pows[ip1] -
8291 met->t[ix][iy][ip0] * pows[ip0]) / denom;
8292 dudp = (met->u[ix][iy][ip1] - met->u[ix][iy][ip0]) / denom;
8293 dvdp = (met->v[ix][iy][ip1] - met->v[ix][iy][ip0]) / denom;
8294 }
8295
8296 /* Calculate PV... */
8297 met->pv[ix][iy][ip] = (float)
8298 (1e6 * G0 *
8299 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
8300 }
8301 }
8302 }
8303
8304 /* Fix for polar regions... */
8305#pragma omp parallel for default(shared)
8306 for (int ix = 0; ix < met->nx; ix++)
8307 for (int ip = 0; ip < met->np; ip++) {
8308 met->pv[ix][0][ip]
8309 = met->pv[ix][1][ip]
8310 = met->pv[ix][2][ip];
8311 met->pv[ix][met->ny - 1][ip]
8312 = met->pv[ix][met->ny - 2][ip]
8313 = met->pv[ix][met->ny - 3][ip];
8314 }
8315}
#define DEG2DY(dlat)
Convert a latitude difference to a distance in the y-direction (north-south).
Definition: mptrac.h:461
#define DEG2DX(dlon, lat)
Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude.
Definition: mptrac.h:440

◆ read_met_ozone()

void read_met_ozone ( met_t met)

Calculates the total column ozone from meteorological ozone data.

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

Parameters
metA pointer to a structure containing meteorological ozone data.

The function performs the following steps:

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

Definition at line 8319 of file mptrac.c.

8320 {
8321
8322 /* Set timer... */
8323 SELECT_TIMER("READ_MET_OZONE", "METPROC", NVTX_READ);
8324 LOG(2, "Calculate total column ozone...");
8325
8326 /* Loop over columns... */
8327#pragma omp parallel for default(shared) collapse(2)
8328 for (int ix = 0; ix < met->nx; ix++)
8329 for (int iy = 0; iy < met->ny; iy++) {
8330
8331 /* Integrate... */
8332 double cd = 0;
8333 for (int ip = 1; ip < met->np; ip++)
8334 if (met->p[ip - 1] <= met->ps[ix][iy]) {
8335 const double vmr =
8336 0.5 * (met->o3[ix][iy][ip - 1] + met->o3[ix][iy][ip]);
8337 const double dp = met->p[ip - 1] - met->p[ip];
8338 cd += vmr * MO3 / MA * dp * 1e2 / G0;
8339 }
8340
8341 /* Convert to Dobson units... */
8342 met->o3c[ix][iy] = (float) (cd / 2.1415e-5);
8343 }
8344}

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

8350 {
8351
8352 met_t *help;
8353
8354 /* Check parameters... */
8355 if (ctl->met_dp <= 1 && ctl->met_dx <= 1 && ctl->met_dy <= 1
8356 && ctl->met_sp <= 1 && ctl->met_sx <= 1 && ctl->met_sy <= 1)
8357 return;
8358
8359 /* Set timer... */
8360 SELECT_TIMER("READ_MET_SAMPLE", "METPROC", NVTX_READ);
8361 LOG(2, "Downsampling of meteo data...");
8362
8363 /* Allocate... */
8364 ALLOC(help, met_t, 1);
8365
8366 /* Copy data... */
8367 help->nx = met->nx;
8368 help->ny = met->ny;
8369 help->np = met->np;
8370 memcpy(help->lon, met->lon, sizeof(met->lon));
8371 memcpy(help->lat, met->lat, sizeof(met->lat));
8372 memcpy(help->p, met->p, sizeof(met->p));
8373
8374 /* Smoothing... */
8375 for (int ix = 0; ix < met->nx; ix += ctl->met_dx) {
8376 for (int iy = 0; iy < met->ny; iy += ctl->met_dy) {
8377 for (int ip = 0; ip < met->np; ip += ctl->met_dp) {
8378 help->ps[ix][iy] = 0;
8379 help->zs[ix][iy] = 0;
8380 help->ts[ix][iy] = 0;
8381 help->us[ix][iy] = 0;
8382 help->vs[ix][iy] = 0;
8383 help->ess[ix][iy] = 0;
8384 help->nss[ix][iy] = 0;
8385 help->shf[ix][iy] = 0;
8386 help->lsm[ix][iy] = 0;
8387 help->sst[ix][iy] = 0;
8388 help->pbl[ix][iy] = 0;
8389 help->cape[ix][iy] = 0;
8390 help->cin[ix][iy] = 0;
8391 help->t[ix][iy][ip] = 0;
8392 help->u[ix][iy][ip] = 0;
8393 help->v[ix][iy][ip] = 0;
8394 help->w[ix][iy][ip] = 0;
8395 help->h2o[ix][iy][ip] = 0;
8396 help->o3[ix][iy][ip] = 0;
8397 help->lwc[ix][iy][ip] = 0;
8398 help->rwc[ix][iy][ip] = 0;
8399 help->iwc[ix][iy][ip] = 0;
8400 help->swc[ix][iy][ip] = 0;
8401 help->cc[ix][iy][ip] = 0;
8402 float wsum = 0;
8403 for (int ix2 = ix - ctl->met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
8404 ix2++) {
8405 int ix3 = ix2;
8406 if (ix3 < 0)
8407 ix3 += met->nx;
8408 else if (ix3 >= met->nx)
8409 ix3 -= met->nx;
8410
8411 for (int iy2 = MAX(iy - ctl->met_sy + 1, 0);
8412 iy2 <= MIN(iy + ctl->met_sy - 1, met->ny - 1); iy2++)
8413 for (int ip2 = MAX(ip - ctl->met_sp + 1, 0);
8414 ip2 <= MIN(ip + ctl->met_sp - 1, met->np - 1); ip2++) {
8415 float w = (1.0f - (float) abs(ix - ix2) / (float) ctl->met_sx)
8416 * (1.0f - (float) abs(iy - iy2) / (float) ctl->met_sy)
8417 * (1.0f - (float) abs(ip - ip2) / (float) ctl->met_sp);
8418 help->ps[ix][iy] += w * met->ps[ix3][iy2];
8419 help->zs[ix][iy] += w * met->zs[ix3][iy2];
8420 help->ts[ix][iy] += w * met->ts[ix3][iy2];
8421 help->us[ix][iy] += w * met->us[ix3][iy2];
8422 help->vs[ix][iy] += w * met->vs[ix3][iy2];
8423 help->ess[ix][iy] += w * met->ess[ix3][iy2];
8424 help->nss[ix][iy] += w * met->nss[ix3][iy2];
8425 help->shf[ix][iy] += w * met->shf[ix3][iy2];
8426 help->lsm[ix][iy] += w * met->lsm[ix3][iy2];
8427 help->sst[ix][iy] += w * met->sst[ix3][iy2];
8428 help->pbl[ix][iy] += w * met->pbl[ix3][iy2];
8429 help->cape[ix][iy] += w * met->cape[ix3][iy2];
8430 help->cin[ix][iy] += w * met->cin[ix3][iy2];
8431 help->t[ix][iy][ip] += w * met->t[ix3][iy2][ip2];
8432 help->u[ix][iy][ip] += w * met->u[ix3][iy2][ip2];
8433 help->v[ix][iy][ip] += w * met->v[ix3][iy2][ip2];
8434 help->w[ix][iy][ip] += w * met->w[ix3][iy2][ip2];
8435 help->h2o[ix][iy][ip] += w * met->h2o[ix3][iy2][ip2];
8436 help->o3[ix][iy][ip] += w * met->o3[ix3][iy2][ip2];
8437 help->lwc[ix][iy][ip] += w * met->lwc[ix3][iy2][ip2];
8438 help->rwc[ix][iy][ip] += w * met->rwc[ix3][iy2][ip2];
8439 help->iwc[ix][iy][ip] += w * met->iwc[ix3][iy2][ip2];
8440 help->swc[ix][iy][ip] += w * met->swc[ix3][iy2][ip2];
8441 help->cc[ix][iy][ip] += w * met->cc[ix3][iy2][ip2];
8442 wsum += w;
8443 }
8444 }
8445 help->ps[ix][iy] /= wsum;
8446 help->zs[ix][iy] /= wsum;
8447 help->ts[ix][iy] /= wsum;
8448 help->us[ix][iy] /= wsum;
8449 help->vs[ix][iy] /= wsum;
8450 help->ess[ix][iy] /= wsum;
8451 help->nss[ix][iy] /= wsum;
8452 help->shf[ix][iy] /= wsum;
8453 help->lsm[ix][iy] /= wsum;
8454 help->sst[ix][iy] /= wsum;
8455 help->pbl[ix][iy] /= wsum;
8456 help->cape[ix][iy] /= wsum;
8457 help->cin[ix][iy] /= wsum;
8458 help->t[ix][iy][ip] /= wsum;
8459 help->u[ix][iy][ip] /= wsum;
8460 help->v[ix][iy][ip] /= wsum;
8461 help->w[ix][iy][ip] /= wsum;
8462 help->h2o[ix][iy][ip] /= wsum;
8463 help->o3[ix][iy][ip] /= wsum;
8464 help->lwc[ix][iy][ip] /= wsum;
8465 help->rwc[ix][iy][ip] /= wsum;
8466 help->iwc[ix][iy][ip] /= wsum;
8467 help->swc[ix][iy][ip] /= wsum;
8468 help->cc[ix][iy][ip] /= wsum;
8469 }
8470 }
8471 }
8472
8473 /* Downsampling... */
8474 met->nx = 0;
8475 for (int ix = 0; ix < help->nx; ix += ctl->met_dx) {
8476 met->lon[met->nx] = help->lon[ix];
8477 met->ny = 0;
8478 for (int iy = 0; iy < help->ny; iy += ctl->met_dy) {
8479 met->lat[met->ny] = help->lat[iy];
8480 met->ps[met->nx][met->ny] = help->ps[ix][iy];
8481 met->zs[met->nx][met->ny] = help->zs[ix][iy];
8482 met->ts[met->nx][met->ny] = help->ts[ix][iy];
8483 met->us[met->nx][met->ny] = help->us[ix][iy];
8484 met->vs[met->nx][met->ny] = help->vs[ix][iy];
8485 met->ess[met->nx][met->ny] = help->ess[ix][iy];
8486 met->nss[met->nx][met->ny] = help->nss[ix][iy];
8487 met->shf[met->nx][met->ny] = help->shf[ix][iy];
8488 met->lsm[met->nx][met->ny] = help->lsm[ix][iy];
8489 met->sst[met->nx][met->ny] = help->sst[ix][iy];
8490 met->pbl[met->nx][met->ny] = help->pbl[ix][iy];
8491 met->cape[met->nx][met->ny] = help->cape[ix][iy];
8492 met->cin[met->nx][met->ny] = help->cin[ix][iy];
8493 met->np = 0;
8494 for (int ip = 0; ip < help->np; ip += ctl->met_dp) {
8495 met->p[met->np] = help->p[ip];
8496 met->t[met->nx][met->ny][met->np] = help->t[ix][iy][ip];
8497 met->u[met->nx][met->ny][met->np] = help->u[ix][iy][ip];
8498 met->v[met->nx][met->ny][met->np] = help->v[ix][iy][ip];
8499 met->w[met->nx][met->ny][met->np] = help->w[ix][iy][ip];
8500 met->h2o[met->nx][met->ny][met->np] = help->h2o[ix][iy][ip];
8501 met->o3[met->nx][met->ny][met->np] = help->o3[ix][iy][ip];
8502 met->lwc[met->nx][met->ny][met->np] = help->lwc[ix][iy][ip];
8503 met->rwc[met->nx][met->ny][met->np] = help->rwc[ix][iy][ip];
8504 met->iwc[met->nx][met->ny][met->np] = help->iwc[ix][iy][ip];
8505 met->swc[met->nx][met->ny][met->np] = help->swc[ix][iy][ip];
8506 met->cc[met->nx][met->ny][met->np] = help->cc[ix][iy][ip];
8507 met->np++;
8508 }
8509 met->ny++;
8510 }
8511 met->nx++;
8512 }
8513
8514 /* Free... */
8515 free(help);
8516}
int met_dp
Stride for pressure levels.
Definition: mptrac.h:2562
int met_sy
Smoothing for latitudes.
Definition: mptrac.h:2568
int met_sx
Smoothing for longitudes.
Definition: mptrac.h:2565
int met_dx
Stride for longitudes.
Definition: mptrac.h:2556
int met_sp
Smoothing for pressure levels.
Definition: mptrac.h:2571
int met_dy
Stride for latitudes.
Definition: mptrac.h:2559

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

8523 {
8524
8525 /* Set timer... */
8526 SELECT_TIMER("READ_MET_SURFACE", "INPUT", NVTX_READ);
8527 LOG(2, "Read surface data...");
8528
8529 /* Read surface pressure... */
8530 if (read_met_nc_2d
8531 (ncid, "lnsp", "LNSP", NULL, NULL, NULL, NULL, ctl, met, met->ps, 1.0f,
8532 1)) {
8533 for (int ix = 0; ix < met->nx; ix++)
8534 for (int iy = 0; iy < met->ny; iy++)
8535 met->ps[ix][iy] = (float) (exp(met->ps[ix][iy]) / 100.);
8536 } else
8537 if (!read_met_nc_2d
8538 (ncid, "ps", "PS", "sp", "SP", NULL, NULL, ctl, met, met->ps, 0.01f,
8539 1)) {
8540 WARN("Cannot not read surface pressure data (use lowest level)!");
8541 for (int ix = 0; ix < met->nx; ix++)
8542 for (int iy = 0; iy < met->ny; iy++)
8543 met->ps[ix][iy]
8544 = (ctl->met_np > 0 ? (float) ctl->met_p[0] : (float) met->p[0]);
8545 }
8546
8547 /* MPTRAC meteo data... */
8548 if (ctl->met_clams == 0) {
8549
8550 /* Read geopotential height at the surface... */
8551 if (!read_met_nc_2d
8552 (ncid, "z", "Z", NULL, NULL, NULL, NULL, ctl, met, met->zs,
8553 (float) (1. / (1000. * G0)), 1))
8554 if (!read_met_nc_2d
8555 (ncid, "zm", "ZM", NULL, NULL, NULL, NULL, ctl, met, met->zs,
8556 (float) (1. / 1000.), 1))
8557 WARN("Cannot read surface geopotential height!");
8558 }
8559
8560 /* CLaMS meteo data... */
8561 else {
8562
8563 /* Read geopotential height at the surface
8564 (use lowermost level of 3-D data field)... */
8565 float *help;
8566 ALLOC(help, float,
8567 EX * EY * EP);
8568 memcpy(help, met->pl, sizeof(met->pl));
8569 if (!read_met_nc_3d
8570 (ncid, "gph", "GPH", NULL, NULL, ctl, met, met->pl,
8571 (float) (1e-3 / G0)))
8572 ERRMSG("Cannot read geopotential height!");
8573 for (int ix = 0; ix < met->nx; ix++)
8574 for (int iy = 0; iy < met->ny; iy++)
8575 met->zs[ix][iy] = met->pl[ix][iy][0];
8576 memcpy(met->pl, help, sizeof(met->pl));
8577 free(help);
8578 }
8579
8580 /* Read temperature at the surface... */
8581 if (!read_met_nc_2d
8582 (ncid, "t2m", "T2M", "2t", "2T", "t2", "T2", ctl, met, met->ts, 1.0, 1))
8583 WARN("Cannot read surface temperature!");
8584
8585 /* Read zonal wind at the surface... */
8586 if (!read_met_nc_2d
8587 (ncid, "u10m", "U10M", "10u", "10U", "u10", "U10", ctl, met, met->us,
8588 1.0, 1))
8589 WARN("Cannot read surface zonal wind!");
8590
8591 /* Read meridional wind at the surface... */
8592 if (!read_met_nc_2d
8593 (ncid, "v10m", "V10M", "10v", "10V", "v10", "V10", ctl, met, met->vs,
8594 1.0, 1))
8595 WARN("Cannot read surface meridional wind!");
8596
8597 /* Read eastward turbulent surface stress... */
8598 if (!read_met_nc_2d
8599 (ncid, "iews", "IEWS", NULL, NULL, NULL, NULL, ctl, met, met->ess, 1.0,
8600 1))
8601 WARN("Cannot read eastward turbulent surface stress!");
8602
8603 /* Read northward turbulent surface stress... */
8604 if (!read_met_nc_2d
8605 (ncid, "inss", "INSS", NULL, NULL, NULL, NULL, ctl, met, met->nss, 1.0,
8606 1))
8607 WARN("Cannot read nothward turbulent surface stress!");
8608
8609 /* Read surface sensible heat flux... */
8610 if (!read_met_nc_2d
8611 (ncid, "ishf", "ISHF", NULL, NULL, NULL, NULL, ctl, met, met->shf, 1.0,
8612 1))
8613 WARN("Cannot read surface sensible heat flux!");
8614
8615 /* Read land-sea mask... */
8616 if (!read_met_nc_2d
8617 (ncid, "lsm", "LSM", NULL, NULL, NULL, NULL, ctl, met, met->lsm, 1.0,
8618 1))
8619 WARN("Cannot read land-sea mask!");
8620
8621 /* Read sea surface temperature... */
8622 if (!read_met_nc_2d
8623 (ncid, "sstk", "SSTK", "sst", "SST", NULL, NULL, ctl, met, met->sst,
8624 1.0, 1))
8625 WARN("Cannot read sea surface temperature!");
8626
8627 /* Read PBL... */
8628 if (ctl->met_pbl == 0)
8629 if (!read_met_nc_2d
8630 (ncid, "blp", "BLP", NULL, NULL, NULL, NULL, ctl, met, met->pbl,
8631 0.01f, 1))
8632 WARN("Cannot read planetary boundary layer pressure!");
8633 if (ctl->met_pbl == 1)
8634 if (!read_met_nc_2d
8635 (ncid, "blh", "BLH", NULL, NULL, NULL, NULL, ctl, met, met->pbl,
8636 0.001f, 1))
8637 WARN("Cannot read planetary boundary layer height!");
8638
8639 /* Read CAPE... */
8640 if (ctl->met_cape == 0)
8641 if (!read_met_nc_2d
8642 (ncid, "cape", "CAPE", NULL, NULL, NULL, NULL, ctl, met, met->cape,
8643 1.0, 1))
8644 WARN("Cannot read CAPE!");
8645
8646 /* Read CIN... */
8647 if (ctl->met_cape == 0)
8648 if (!read_met_nc_2d
8649 (ncid, "cin", "CIN", NULL, NULL, NULL, NULL, ctl, met, met->cin,
8650 1.0, 1))
8651 WARN("Cannot read convective inhibition!");
8652}
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:7652
Here is the call graph for this function:

◆ read_met_tropo()

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

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

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

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

The function performs the following steps:

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

Definition at line 8656 of file mptrac.c.

8659 {
8660
8661 double p2[200], pv[EP], pv2[200], t[EP], t2[200], th[EP],
8662 th2[200], z[EP], z2[200];
8663
8664 /* Set timer... */
8665 SELECT_TIMER("READ_MET_TROPO", "METPROC", NVTX_READ);
8666 LOG(2, "Calculate tropopause...");
8667
8668 /* Get altitude and pressure profiles... */
8669#pragma omp parallel for default(shared)
8670 for (int iz = 0; iz < met->np; iz++)
8671 z[iz] = Z(met->p[iz]);
8672#pragma omp parallel for default(shared)
8673 for (int iz = 0; iz <= 190; iz++) {
8674 z2[iz] = 4.5 + 0.1 * iz;
8675 p2[iz] = P(z2[iz]);
8676 }
8677
8678 /* Do not calculate tropopause... */
8679 if (ctl->met_tropo == 0)
8680#pragma omp parallel for default(shared) collapse(2)
8681 for (int ix = 0; ix < met->nx; ix++)
8682 for (int iy = 0; iy < met->ny; iy++)
8683 met->pt[ix][iy] = NAN;
8684
8685 /* Use tropopause climatology... */
8686 else if (ctl->met_tropo == 1) {
8687#pragma omp parallel for default(shared) collapse(2)
8688 for (int ix = 0; ix < met->nx; ix++)
8689 for (int iy = 0; iy < met->ny; iy++)
8690 met->pt[ix][iy] = (float) clim_tropo(clim, met->time, met->lat[iy]);
8691 }
8692
8693 /* Use cold point... */
8694 else if (ctl->met_tropo == 2) {
8695
8696 /* Loop over grid points... */
8697#pragma omp parallel for default(shared) private(t,t2) collapse(2)
8698 for (int ix = 0; ix < met->nx; ix++)
8699 for (int iy = 0; iy < met->ny; iy++) {
8700
8701 /* Interpolate temperature profile... */
8702 for (int iz = 0; iz < met->np; iz++)
8703 t[iz] = met->t[ix][iy][iz];
8704 spline(z, t, met->np, z2, t2, 171, ctl->met_tropo_spline);
8705
8706 /* Find minimum... */
8707 int iz = (int) gsl_stats_min_index(t2, 1, 171);
8708 if (iz > 0 && iz < 170)
8709 met->pt[ix][iy] = (float) p2[iz];
8710 else
8711 met->pt[ix][iy] = NAN;
8712 }
8713 }
8714
8715 /* Use WMO definition... */
8716 else if (ctl->met_tropo == 3 || ctl->met_tropo == 4) {
8717
8718 /* Loop over grid points... */
8719#pragma omp parallel for default(shared) private(t,t2) collapse(2)
8720 for (int ix = 0; ix < met->nx; ix++)
8721 for (int iy = 0; iy < met->ny; iy++) {
8722
8723 /* Interpolate temperature profile... */
8724 int iz;
8725 for (iz = 0; iz < met->np; iz++)
8726 t[iz] = met->t[ix][iy][iz];
8727 spline(z, t, met->np, z2, t2, 191, ctl->met_tropo_spline);
8728
8729 /* Find 1st tropopause... */
8730 met->pt[ix][iy] = NAN;
8731 for (iz = 0; iz <= 170; iz++) {
8732 int found = 1;
8733 for (int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
8734 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
8735 found = 0;
8736 break;
8737 }
8738 if (found) {
8739 if (iz > 0 && iz < 170)
8740 met->pt[ix][iy] = (float) p2[iz];
8741 break;
8742 }
8743 }
8744
8745 /* Find 2nd tropopause... */
8746 if (ctl->met_tropo == 4) {
8747 met->pt[ix][iy] = NAN;
8748 for (; iz <= 170; iz++) {
8749 int found = 1;
8750 for (int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
8751 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
8752 found = 0;
8753 break;
8754 }
8755 if (found)
8756 break;
8757 }
8758 for (; iz <= 170; iz++) {
8759 int found = 1;
8760 for (int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
8761 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
8762 found = 0;
8763 break;
8764 }
8765 if (found) {
8766 if (iz > 0 && iz < 170)
8767 met->pt[ix][iy] = (float) p2[iz];
8768 break;
8769 }
8770 }
8771 }
8772 }
8773 }
8774
8775 /* Use dynamical tropopause... */
8776 else if (ctl->met_tropo == 5) {
8777
8778 /* Loop over grid points... */
8779#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
8780 for (int ix = 0; ix < met->nx; ix++)
8781 for (int iy = 0; iy < met->ny; iy++) {
8782
8783 /* Interpolate potential vorticity profile... */
8784 for (int iz = 0; iz < met->np; iz++)
8785 pv[iz] = met->pv[ix][iy][iz];
8786 spline(z, pv, met->np, z2, pv2, 171, ctl->met_tropo_spline);
8787
8788 /* Interpolate potential temperature profile... */
8789 for (int iz = 0; iz < met->np; iz++)
8790 th[iz] = THETA(met->p[iz], met->t[ix][iy][iz]);
8791 spline(z, th, met->np, z2, th2, 171, ctl->met_tropo_spline);
8792
8793 /* Find dynamical tropopause... */
8794 met->pt[ix][iy] = NAN;
8795 for (int iz = 0; iz <= 170; iz++)
8796 if (fabs(pv2[iz]) >= ctl->met_tropo_pv
8797 || th2[iz] >= ctl->met_tropo_theta) {
8798 if (iz > 0 && iz < 170)
8799 met->pt[ix][iy] = (float) p2[iz];
8800 break;
8801 }
8802 }
8803 }
8804
8805 else
8806 ERRMSG("Cannot calculate tropopause!");
8807
8808 /* Interpolate temperature, geopotential height, and water vapor... */
8809#pragma omp parallel for default(shared) collapse(2)
8810 for (int ix = 0; ix < met->nx; ix++)
8811 for (int iy = 0; iy < met->ny; iy++) {
8812 double h2ot, tt, zt;
8814 intpol_met_space_3d(met, met->t, met->pt[ix][iy], met->lon[ix],
8815 met->lat[iy], &tt, ci, cw, 1);
8816 intpol_met_space_3d(met, met->z, met->pt[ix][iy], met->lon[ix],
8817 met->lat[iy], &zt, ci, cw, 0);
8818 intpol_met_space_3d(met, met->h2o, met->pt[ix][iy], met->lon[ix],
8819 met->lat[iy], &h2ot, ci, cw, 0);
8820 met->tt[ix][iy] = (float) tt;
8821 met->zt[ix][iy] = (float) zt;
8822 met->h2ot[ix][iy] = (float) h2ot;
8823 }
8824}
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:9034
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
Definition: mptrac.h:840
Here is the call graph for this function:

◆ read_obs()

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

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

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

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

The function performs the following steps:

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

Definition at line 8828 of file mptrac.c.

8836 {
8837
8838 /* Write info... */
8839 LOG(1, "Read observation data: %s", filename);
8840
8841 /* Read data... */
8842 if (ctl->obs_type == 0)
8843 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
8844 else if (ctl->obs_type == 1)
8845 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
8846 else
8847 ERRMSG("Set OBS_TYPE to 0 or 1!");
8848
8849 /* Check time... */
8850 for (int i = 1; i < *nobs; i++)
8851 if (rt[i] < rt[i - 1])
8852 ERRMSG("Time must be ascending!");
8853
8854 /* Write info... */
8855 int n = *nobs;
8856 double mini, maxi;
8857 LOG(2, "Number of observations: %d", *nobs);
8858 gsl_stats_minmax(&mini, &maxi, rt, 1, (size_t) n);
8859 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
8860 gsl_stats_minmax(&mini, &maxi, rz, 1, (size_t) n);
8861 LOG(2, "Altitude range: %g ... %g km", mini, maxi);
8862 gsl_stats_minmax(&mini, &maxi, rlon, 1, (size_t) n);
8863 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
8864 gsl_stats_minmax(&mini, &maxi, rlat, 1, (size_t) n);
8865 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
8866 gsl_stats_minmax(&mini, &maxi, robs, 1, (size_t) n);
8867 LOG(2, "Observation range: %g ... %g", mini, maxi);
8868}
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:8872
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:8900
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 8872 of file mptrac.c.

8879 {
8880
8881 /* Open observation data file... */
8882 FILE *in;
8883 if (!(in = fopen(filename, "r")))
8884 ERRMSG("Cannot open file!");
8885
8886 /* Read observations... */
8887 char line[LEN];
8888 while (fgets(line, LEN, in))
8889 if (sscanf(line, "%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
8890 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
8891 if ((++(*nobs)) >= NOBS)
8892 ERRMSG("Too many observations!");
8893
8894 /* Close observation data file... */
8895 fclose(in);
8896}
#define NOBS
Maximum number of observation data points.
Definition: mptrac.h:281

◆ read_obs_nc()

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

Reads observation data from a NetCDF file.

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

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

The function performs the following steps:

  • Attempts to open the specified NetCDF file in read-only mode using the nc_open function.
  • Queries the dimensions of the 'nobs' variable in the NetCDF file to determine the number of observations using the NC_INQ_DIM macro.
  • Reads the 'time', 'alt', 'lon', 'lat', and 'obs' variables from the NetCDF file using the NC_GET_DOUBLE macro and stores them in the respective arrays.
  • Closes the NetCDF file after reading all data using the nc_close function.
Note
The function assumes that the NetCDF file contains the required variables ('time', 'alt', 'lon', 'lat', 'obs') and that the arrays provided have sufficient memory allocated to store the data.
Author
Lars Hoffmann

Definition at line 8900 of file mptrac.c.

8907 {
8908
8909 int ncid, varid;
8910
8911 /* Open netCDF file... */
8912 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
8913 ERRMSG("Cannot open file!");
8914
8915 /* Read the observations from the NetCDF file... */
8916 NC_INQ_DIM("nobs", nobs, 1, NOBS);
8917 NC_GET_DOUBLE("time", rt, 1);
8918 NC_GET_DOUBLE("alt", rz, 1);
8919 NC_GET_DOUBLE("lon", rlon, 1);
8920 NC_GET_DOUBLE("lat", rlat, 1);
8921 NC_GET_DOUBLE("obs", robs, 1);
8922
8923 /* Close file... */
8924 NC(nc_close(ncid));
8925}

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

8936 {
8937
8938 FILE *in = NULL;
8939
8940 char fullname1[LEN], fullname2[LEN], rval[LEN];
8941
8942 int contain = 0, i;
8943
8944 /* Open file... */
8945 if (filename[strlen(filename) - 1] != '-')
8946 if (!(in = fopen(filename, "r")))
8947 ERRMSG("Cannot open file!");
8948
8949 /* Set full variable name... */
8950 if (arridx >= 0) {
8951 sprintf(fullname1, "%s[%d]", varname, arridx);
8952 sprintf(fullname2, "%s[*]", varname);
8953 } else {
8954 sprintf(fullname1, "%s", varname);
8955 sprintf(fullname2, "%s", varname);
8956 }
8957
8958 /* Read data... */
8959 if (in != NULL) {
8960 char dummy[LEN], line[LEN], rvarname[LEN];
8961 while (fgets(line, LEN, in)) {
8962 if (sscanf(line, "%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
8963 if (strcasecmp(rvarname, fullname1) == 0 ||
8964 strcasecmp(rvarname, fullname2) == 0) {
8965 contain = 1;
8966 break;
8967 }
8968 }
8969 }
8970 for (i = 1; i < argc - 1; i++)
8971 if (strcasecmp(argv[i], fullname1) == 0 ||
8972 strcasecmp(argv[i], fullname2) == 0) {
8973 sprintf(rval, "%s", argv[i + 1]);
8974 contain = 1;
8975 break;
8976 }
8977
8978 /* Close file... */
8979 if (in != NULL)
8980 fclose(in);
8981
8982 /* Check for missing variables... */
8983 if (!contain) {
8984 if (strlen(defvalue) > 0)
8985 sprintf(rval, "%s", defvalue);
8986 else
8987 ERRMSG("Missing variable %s!\n", fullname1);
8988 }
8989
8990 /* Write info... */
8991 LOG(1, "%s = %s", fullname1, rval);
8992
8993 /* Return values... */
8994 if (value != NULL)
8995 sprintf(value, "%s", rval);
8996 return atof(rval);
8997}

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

9005 {
9006
9007 /* Convert particle radius from microns to m... */
9008 const double rp_help = rp * 1e-6;
9009
9010 /* Density of dry air [kg / m^3]... */
9011 const double rho = RHO(p, T);
9012
9013 /* Dynamic viscosity of air [kg / (m s)]... */
9014 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
9015
9016 /* Thermal velocity of an air molecule [m / s]... */
9017 const double v = sqrt(8. * KB * T / (M_PI * 4.8096e-26));
9018
9019 /* Mean free path of an air molecule [m]... */
9020 const double lambda = 2. * eta / (rho * v);
9021
9022 /* Knudsen number for air (dimensionless)... */
9023 const double K = lambda / rp_help;
9024
9025 /* Cunningham slip-flow correction (dimensionless)... */
9026 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
9027
9028 /* Sedimentation velocity [m / s]... */
9029 return 2. * SQR(rp_help) * (rhop - rho) * G0 / (9. * eta) * G;
9030}
#define KB
Boltzmann constant [kg m^2/(K s^2)].
Definition: mptrac.h:192

◆ spline()

void spline ( const double *  x,
const double *  y,
const int  n,
const double *  x2,
double *  y2,
const int  n2,
const int  method 
)

Performs spline interpolation or linear interpolation.

This function interpolates a set of data points using either cubic spline interpolation or linear interpolation, depending on the specified method.

Parameters
xThe array of x-coordinates of the data points.
yThe array of y-coordinates of the data points.
nThe number of data points.
x2The array of x-coordinates where interpolation is required.
y2The array to store the interpolated y-values.
n2The number of points to interpolate.
methodThe interpolation method: 1 for cubic spline, 0 for linear interpolation.

If the method is set to 1 (cubic spline interpolation):

  • The function initializes a cubic spline interpolator using GSL.
  • It interpolates the y-values at the specified x-coordinates using the spline.
  • The interpolated y-values are stored in the provided y2 array.

If the method is set to 0 (linear interpolation):

  • The function performs linear interpolation between adjacent data points.
  • It locates the interval where each interpolation point falls and calculates the interpolated y-value using linear interpolation.
  • The interpolated y-values are stored in the provided y2 array.
Note
The x-coordinates in both arrays (x and x2) must be sorted in ascending order.
Author
Lars Hoffmann

Definition at line 9034 of file mptrac.c.

9041 {
9042
9043 /* Cubic spline interpolation... */
9044 if (method == 1) {
9045
9046 /* Allocate... */
9047 gsl_interp_accel *acc = gsl_interp_accel_alloc();
9048 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (size_t) n);
9049
9050 /* Interpolate profile... */
9051 gsl_spline_init(s, x, y, (size_t) n);
9052 for (int i = 0; i < n2; i++)
9053 if (x2[i] <= x[0])
9054 y2[i] = y[0];
9055 else if (x2[i] >= x[n - 1])
9056 y2[i] = y[n - 1];
9057 else
9058 y2[i] = gsl_spline_eval(s, x2[i], acc);
9059
9060 /* Free... */
9061 gsl_spline_free(s);
9062 gsl_interp_accel_free(acc);
9063 }
9064
9065 /* Linear interpolation... */
9066 else {
9067 for (int i = 0; i < n2; i++)
9068 if (x2[i] <= x[0])
9069 y2[i] = y[0];
9070 else if (x2[i] >= x[n - 1])
9071 y2[i] = y[n - 1];
9072 else {
9073 int idx = locate_irr(x, n, x2[i]);
9074 y2[i] = LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
9075 }
9076 }
9077}
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 9081 of file mptrac.c.

9083 {
9084
9085 if (n <= 0)
9086 return 0;
9087
9088 float mean = 0, var = 0;
9089
9090 for (int i = 0; i < n; ++i) {
9091 mean += data[i];
9092 var += SQR(data[i]);
9093 }
9094
9095 var = var / (float) n - SQR(mean / (float) n);
9096
9097 return (var > 0 ? sqrtf(var) : 0);
9098}

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

9105 {
9106
9107 /* Number of days and fraction with respect to 2000-01-01T12:00Z... */
9108 const double D = sec / 86400 - 0.5;
9109
9110 /* Geocentric apparent ecliptic longitude [rad]... */
9111 const double g = DEG2RAD(357.529 + 0.98560028 * D);
9112 const double q = 280.459 + 0.98564736 * D;
9113 const double L = DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
9114
9115 /* Mean obliquity of the ecliptic [rad]... */
9116 const double e = DEG2RAD(23.439 - 0.00000036 * D);
9117
9118 /* Declination [rad]... */
9119 const double sindec = sin(e) * sin(L);
9120
9121 /* Right ascension [rad]... */
9122 const double ra = atan2(cos(e) * sin(L), cos(L));
9123
9124 /* Greenwich Mean Sidereal Time [h]... */
9125 const double GMST = 18.697374558 + 24.06570982441908 * D;
9126
9127 /* Local Sidereal Time [h]... */
9128 const double LST = GMST + lon / 15;
9129
9130 /* Hour angle [rad]... */
9131 const double h = LST / 12 * M_PI - ra;
9132
9133 /* Convert latitude... */
9134 const double lat_help = DEG2RAD(lat);
9135
9136 /* Return solar zenith angle [rad]... */
9137 return acos(sin(lat_help) * sindec +
9138 cos(lat_help) * sqrt(1 - SQR(sindec)) * cos(h));
9139}

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

9151 {
9152
9153 struct tm t0, t1;
9154
9155 t0.tm_year = 100;
9156 t0.tm_mon = 0;
9157 t0.tm_mday = 1;
9158 t0.tm_hour = 0;
9159 t0.tm_min = 0;
9160 t0.tm_sec = 0;
9161
9162 t1.tm_year = year - 1900;
9163 t1.tm_mon = mon - 1;
9164 t1.tm_mday = day;
9165 t1.tm_hour = hour;
9166 t1.tm_min = min;
9167 t1.tm_sec = sec;
9168
9169 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
9170}

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

9177 {
9178
9179 static char names[NTIMER][100], groups[NTIMER][100];
9180
9181 static double rt_name[NTIMER], rt_group[NTIMER],
9182 rt_min[NTIMER], rt_max[NTIMER], dt, t0, t1;
9183
9184 static int iname = -1, igroup = -1, nname, ngroup, ct_name[NTIMER];
9185
9186 /* Get time... */
9187 t1 = omp_get_wtime();
9188 dt = t1 - t0;
9189
9190 /* Add elapsed time to current timers... */
9191 if (iname >= 0) {
9192 rt_name[iname] += dt;
9193 rt_min[iname] = (ct_name[iname] <= 0 ? dt : MIN(rt_min[iname], dt));
9194 rt_max[iname] = (ct_name[iname] <= 0 ? dt : MAX(rt_max[iname], dt));
9195 ct_name[iname]++;
9196 }
9197 if (igroup >= 0)
9198 rt_group[igroup] += t1 - t0;
9199
9200 /* Report timers... */
9201 if (output) {
9202 for (int i = 0; i < nname; i++)
9203 LOG(1, "TIMER_%s = %.3f s (min= %g s, mean= %g s,"
9204 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
9205 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
9206 for (int i = 0; i < ngroup; i++)
9207 LOG(1, "TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
9208 double total = 0.0;
9209 for (int i = 0; i < nname; i++)
9210 total += rt_name[i];
9211 LOG(1, "TIMER_TOTAL = %.3f s", total);
9212 }
9213
9214 /* Identify IDs of next timer... */
9215 for (iname = 0; iname < nname; iname++)
9216 if (strcasecmp(name, names[iname]) == 0)
9217 break;
9218 for (igroup = 0; igroup < ngroup; igroup++)
9219 if (strcasecmp(group, groups[igroup]) == 0)
9220 break;
9221
9222 /* Check whether this is a new timer... */
9223 if (iname >= nname) {
9224 sprintf(names[iname], "%s", name);
9225 if ((++nname) >= NTIMER)
9226 ERRMSG("Too many timers!");
9227 }
9228
9229 /* Check whether this is a new group... */
9230 if (igroup >= ngroup) {
9231 sprintf(groups[igroup], "%s", group);
9232 if ((++ngroup) >= NTIMER)
9233 ERRMSG("Too many groups!");
9234 }
9235
9236 /* Save starting time... */
9237 t0 = t1;
9238}
#define NTIMER
Maximum number of timers.
Definition: mptrac.h:1948

◆ time_from_filename()

double time_from_filename ( const char *  filename,
const int  offset 
)

Extracts and converts a timestamp from a filename to Julian seconds.

The time_from_filename function parses a given filename to extract a timestamp and converts it to Julian seconds. The timestamp is expected to follow a specific format and position within the filename, defined by the offset parameter.

Parameters
filenameA string representing the filename containing the timestamp.
offsetAn integer indicating the position from the end of the filename where the timestamp starts.
Returns
The time in Julian seconds as a double.

The function performs the following steps:

  • Extracts the year, month, day, hour, and minute components of the timestamp from the filename using the given offset.
  • Validates the extracted components to ensure they represent a valid date and time.
  • Converts the validated date and time components to Julian seconds using the time2jsec function.
  • Returns the computed time in Julian seconds.
Note
The expected format of the timestamp in the filename is YYYY-MM-DD_HH-MM (e.g., "2023-05-27_14-45").
Warning
If the extracted components do not represent a valid date and time, the function will trigger an error message.
Author
Lars Hoffmann

Definition at line 9242 of file mptrac.c.

9244 {
9245
9246 char tstr[10];
9247
9248 double t;
9249
9250 /* Get time from filename... */
9251 int len = (int) strlen(filename);
9252 sprintf(tstr, "%.4s", &filename[len - offset]);
9253 int year = atoi(tstr);
9254 sprintf(tstr, "%.2s", &filename[len - offset + 5]);
9255 int mon = atoi(tstr);
9256 sprintf(tstr, "%.2s", &filename[len - offset + 8]);
9257 int day = atoi(tstr);
9258 sprintf(tstr, "%.2s", &filename[len - offset + 11]);
9259 int hour = atoi(tstr);
9260 sprintf(tstr, "%.2s", &filename[len - offset + 14]);
9261 int min = atoi(tstr);
9262
9263 /* Check time... */
9264 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
9265 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
9266 ERRMSG("Cannot read time from filename!");
9267
9268 /* Convert time to Julian seconds... */
9269 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
9270
9271 /* Return time... */
9272 return t;
9273}
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 9277 of file mptrac.c.

9280 {
9281
9282 /* Get tropopause pressure... */
9283 const double pt = clim_tropo(clim, atm->time[ip], atm->lat[ip]);
9284
9285 /* Get pressure range... */
9286 const double p1 = pt * 0.866877899;
9287 const double p0 = pt / 0.866877899;
9288
9289 /* Get weighting factor... */
9290 if (atm->p[ip] > p0)
9291 return 1;
9292 else if (atm->p[ip] < p1)
9293 return 0;
9294 else
9295 return LIN(p0, 1.0, p1, 0.0, atm->p[ip]);
9296}
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 9300 of file mptrac.c.

9304 {
9305
9306 FILE *out;
9307
9308 /* Set time interval for output... */
9309 const double t0 = t - 0.5 * ctl->dt_mod;
9310 const double t1 = t + 0.5 * ctl->dt_mod;
9311
9312 /* Check if gnuplot output is requested... */
9313 if (ctl->atm_gpfile[0] != '-') {
9314
9315 /* Create gnuplot pipe... */
9316 if (!(out = popen("gnuplot", "w")))
9317 ERRMSG("Cannot create pipe to gnuplot!");
9318
9319 /* Set plot filename... */
9320 fprintf(out, "set out \"%s.png\"\n", filename);
9321
9322 /* Set time string... */
9323 double r;
9324 int year, mon, day, hour, min, sec;
9325 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
9326 fprintf(out, "timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
9327 year, mon, day, hour, min);
9328
9329 /* Dump gnuplot file to pipe... */
9330 FILE *in;
9331 if (!(in = fopen(ctl->atm_gpfile, "r")))
9332 ERRMSG("Cannot open file!");
9333 char line[LEN];
9334 while (fgets(line, LEN, in))
9335 fprintf(out, "%s", line);
9336 fclose(in);
9337 }
9338
9339 else {
9340
9341 /* Create file... */
9342 if (!(out = fopen(filename, "w")))
9343 ERRMSG("Cannot create file!");
9344 }
9345
9346 /* Write header... */
9347 fprintf(out,
9348 "# $1 = time [s]\n"
9349 "# $2 = altitude [km]\n"
9350 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
9351 for (int iq = 0; iq < ctl->nq; iq++)
9352 fprintf(out, "# $%i = %s [%s]\n", iq + 5, ctl->qnt_name[iq],
9353 ctl->qnt_unit[iq]);
9354 fprintf(out, "\n");
9355
9356 /* Write data... */
9357 for (int ip = 0; ip < atm->np; ip += ctl->atm_stride) {
9358
9359 /* Check time... */
9360 if (ctl->atm_filter == 2 && (atm->time[ip] < t0 || atm->time[ip] > t1))
9361 continue;
9362
9363 /* Write output... */
9364 fprintf(out, "%.2f %g %g %g", atm->time[ip], Z(atm->p[ip]),
9365 atm->lon[ip], atm->lat[ip]);
9366 for (int iq = 0; iq < ctl->nq; iq++) {
9367 fprintf(out, " ");
9368 if (ctl->atm_filter == 1 && (atm->time[ip] < t0 || atm->time[ip] > t1))
9369 fprintf(out, ctl->qnt_format[iq], NAN);
9370 else
9371 fprintf(out, ctl->qnt_format[iq], atm->q[iq][ip]);
9372 }
9373 fprintf(out, "\n");
9374 }
9375
9376 /* Close file... */
9377 fclose(out);
9378}
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 9382 of file mptrac.c.

9385 {
9386
9387 FILE *out;
9388
9389 /* Create file... */
9390 if (!(out = fopen(filename, "w")))
9391 ERRMSG("Cannot create file!");
9392
9393 /* Write version of binary data... */
9394 int version = 100;
9395 FWRITE(&version, int,
9396 1,
9397 out);
9398
9399 /* Write data... */
9400 FWRITE(&atm->np, int,
9401 1,
9402 out);
9403 FWRITE(atm->time, double,
9404 (size_t) atm->np,
9405 out);
9406 FWRITE(atm->p, double,
9407 (size_t) atm->np,
9408 out);
9409 FWRITE(atm->lon, double,
9410 (size_t) atm->np,
9411 out);
9412 FWRITE(atm->lat, double,
9413 (size_t) atm->np,
9414 out);
9415 for (int iq = 0; iq < ctl->nq; iq++)
9416 FWRITE(atm->q[iq], double,
9417 (size_t) atm->np,
9418 out);
9419
9420 /* Write final flag... */
9421 int final = 999;
9422 FWRITE(&final, int,
9423 1,
9424 out);
9425
9426 /* Close file... */
9427 fclose(out);
9428}

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

9435 {
9436
9437 int tid, pid, ncid, varid;
9438 size_t start[2], count[2];
9439
9440 /* Create file... */
9441 nc_create(filename, NC_NETCDF4, &ncid);
9442
9443 /* Define dimensions... */
9444 NC(nc_def_dim(ncid, "time", 1, &tid));
9445 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
9446
9447 /* Define variables and their attributes... */
9448 int dim_ids[2] = { tid, pid };
9449 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
9450 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
9451 NC_DEF_VAR("LAT", NC_DOUBLE, 1, &pid, "Latitude", "deg",
9452 ctl->atm_nc_level, 0);
9453 NC_DEF_VAR("LON", NC_DOUBLE, 1, &pid, "Longitude", "deg",
9454 ctl->atm_nc_level, 0);
9455 NC_DEF_VAR("PRESS", NC_DOUBLE, 1, &pid, "Pressure", "hPa",
9456 ctl->atm_nc_level, 0);
9457 NC_DEF_VAR("ZETA", NC_DOUBLE, 1, &pid, "Zeta", "K", ctl->atm_nc_level, 0);
9458 for (int iq = 0; iq < ctl->nq; iq++)
9459 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
9460 ctl->qnt_name[iq], ctl->qnt_unit[iq],
9461 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
9462
9463 /* Define global attributes... */
9464 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
9465 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
9466
9467 /* End definitions... */
9468 NC(nc_enddef(ncid));
9469
9470 /* Write data... */
9471 NC_PUT_DOUBLE("time", atm->time, 0);
9472 NC_PUT_DOUBLE("LAT", atm->lat, 0);
9473 NC_PUT_DOUBLE("LON", atm->lon, 0);
9474 NC_PUT_DOUBLE("PRESS", atm->p, 0);
9475 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 0);
9476 for (int iq = 0; iq < ctl->nq; iq++)
9477 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
9478
9479 /* Close file... */
9480 NC(nc_close(ncid));
9481}
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
Definition: mptrac.h:1212
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units, level, quant)
Define a NetCDF variable with attributes.
Definition: mptrac.h:1045
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
Write double precision data to a NetCDF variable.
Definition: mptrac.h:1126

◆ write_atm_clams_traj()

void write_atm_clams_traj ( const char *  dirname,
const ctl_t ctl,
const atm_t atm,
const double  t 
)

Writes CLaMS trajectory data to a NetCDF file.

The write_atm_clams_traj function writes trajectory data for the CLaMS model to a NetCDF file. The file is created and populated with data including time, latitude, longitude, pressure, and other quantities. The function also handles the creation of a final initialization file at the last time step.

Parameters
dirnameA string representing the directory name where the file will be created.
ctlA pointer to a ctl_t structure containing control parameters.
atmA pointer to an atm_t structure containing atmospheric data.
tThe current time in seconds since a reference epoch.

The function performs the following steps:

  • Determines the start and stop times of the calculation.
  • Constructs the output filename based on the start and stop times.
  • Defines the hyperslab for the trajectory file.
  • Creates the NetCDF file if it's the first time step and defines dimensions and variables.
  • Writes the trajectory data to the NetCDF file.
  • At the last time step, creates an initialization file with the final data.
Author
Jan Clemens

Definition at line 9485 of file mptrac.c.

9489 {
9490
9491 /* Global Counter... */
9492 static size_t out_cnt = 0;
9493
9494 double r, r_start, r_stop;
9495 int year, mon, day, hour, min, sec;
9496 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
9497 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
9498 char filename_out[2 * LEN] = "traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
9499
9500 int ncid, varid, tid, pid, cid;
9501 int dim_ids[2];
9502
9503 /* time, nparc */
9504 size_t start[2];
9505 size_t count[2];
9506
9507 /* Determine start and stop times of calculation... */
9508 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
9509 jsec2time(ctl->t_start, &year_start, &mon_start, &day_start, &hour_start,
9510 &min_start, &sec_start, &r_start);
9511 jsec2time(ctl->t_stop, &year_stop, &mon_stop, &day_stop, &hour_stop,
9512 &min_stop, &sec_stop, &r_stop);
9513
9514 sprintf(filename_out, "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc",
9515 dirname,
9516 year_start % 100, mon_start, day_start, hour_start,
9517 year_stop % 100, mon_stop, day_stop, hour_stop);
9518 LOG(1, "Write traj file: %s", filename_out);
9519
9520 /* Define hyperslap for the traj_file... */
9521 start[0] = out_cnt;
9522 start[1] = 0;
9523 count[0] = 1;
9524 count[1] = (size_t) atm->np;
9525
9526 /* Create the file at the first timestep... */
9527 if (out_cnt == 0) {
9528
9529 /* Create file... */
9530 nc_create(filename_out, NC_NETCDF4, &ncid);
9531
9532 /* Define dimensions... */
9533 NC(nc_def_dim(ncid, "time", NC_UNLIMITED, &tid));
9534 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
9535 NC(nc_def_dim(ncid, "TMDT", 7, &cid));
9536 dim_ids[0] = tid;
9537 dim_ids[1] = pid;
9538
9539 /* Define variables and their attributes... */
9540 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
9541 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
9542 NC_DEF_VAR("LAT", NC_DOUBLE, 2, dim_ids, "Latitude", "deg",
9543 ctl->atm_nc_level, 0);
9544 NC_DEF_VAR("LON", NC_DOUBLE, 2, dim_ids, "Longitude", "deg",
9545 ctl->atm_nc_level, 0);
9546 NC_DEF_VAR("PRESS", NC_DOUBLE, 2, dim_ids, "Pressure", "hPa",
9547 ctl->atm_nc_level, 0);
9548 NC_DEF_VAR("ZETA", NC_DOUBLE, 2, dim_ids, "Zeta", "K",
9549 ctl->atm_nc_level, 0);
9550 for (int iq = 0; iq < ctl->nq; iq++)
9551 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
9552 ctl->qnt_name[iq], ctl->qnt_unit[iq],
9553 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
9554
9555 /* Define global attributes... */
9556 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
9557 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
9558
9559 /* End definitions... */
9560 NC(nc_enddef(ncid));
9561 NC(nc_close(ncid));
9562 }
9563
9564 /* Increment global counter to change hyperslap... */
9565 out_cnt++;
9566
9567 /* Open file... */
9568 NC(nc_open(filename_out, NC_WRITE, &ncid));
9569
9570 /* Write data... */
9571 NC_PUT_DOUBLE("time", atm->time, 1);
9572 NC_PUT_DOUBLE("LAT", atm->lat, 1);
9573 NC_PUT_DOUBLE("LON", atm->lon, 1);
9574 NC_PUT_DOUBLE("PRESS", atm->p, 1);
9575 if (ctl->advect_vert_coord == 1) {
9576 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta], 1);
9577 } else if (ctl->qnt_zeta >= 0) {
9578 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 1);
9579 }
9580 for (int iq = 0; iq < ctl->nq; iq++)
9581 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 1);
9582
9583 /* Close file... */
9584 NC(nc_close(ncid));
9585
9586 /* At the last time step create the init_fix_YYYYMMDDHH file... */
9587 if ((year == year_stop) && (mon == mon_stop)
9588 && (day == day_stop) && (hour == hour_stop)) {
9589
9590 /* Set filename... */
9591 char filename_init[2 * LEN] = "./init_fix_YYYYMMDDHH.nc";
9592 sprintf(filename_init, "%s/init_fix_%02d%02d%02d%02d.nc",
9593 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
9594 LOG(1, "Write init file: %s", filename_init);
9595
9596 /* Create file... */
9597 nc_create(filename_init, NC_NETCDF4, &ncid);
9598
9599 /* Define dimensions... */
9600 NC(nc_def_dim(ncid, "time", 1, &tid));
9601 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
9602 dim_ids[0] = tid;
9603 dim_ids[1] = pid;
9604
9605 /* Define variables and their attributes... */
9606 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
9607 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
9608 NC_DEF_VAR("LAT", NC_DOUBLE, 1, &pid, "Latitude", "deg",
9609 ctl->atm_nc_level, 0);
9610 NC_DEF_VAR("LON", NC_DOUBLE, 1, &pid, "Longitude", "deg",
9611 ctl->atm_nc_level, 0);
9612 NC_DEF_VAR("PRESS", NC_DOUBLE, 1, &pid, "Pressure", "hPa",
9613 ctl->atm_nc_level, 0);
9614 NC_DEF_VAR("ZETA", NC_DOUBLE, 1, &pid, "Zeta", "K", ctl->atm_nc_level, 0);
9615 for (int iq = 0; iq < ctl->nq; iq++)
9616 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
9617 ctl->qnt_name[iq], ctl->qnt_unit[iq],
9618 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
9619
9620 /* Define global attributes... */
9621 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
9622 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
9623
9624 /* End definitions... */
9625 NC(nc_enddef(ncid));
9626
9627 /* Write data... */
9628 NC_PUT_DOUBLE("time", atm->time, 0);
9629 NC_PUT_DOUBLE("LAT", atm->lat, 0);
9630 NC_PUT_DOUBLE("LON", atm->lon, 0);
9631 NC_PUT_DOUBLE("PRESS", atm->p, 0);
9632 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 0);
9633 for (int iq = 0; iq < ctl->nq; iq++)
9634 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
9635
9636 /* Close file... */
9637 NC(nc_close(ncid));
9638 }
9639}
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 9643 of file mptrac.c.

9646 {
9647
9648 int ncid, obsid, varid;
9649
9650 size_t start[2], count[2];
9651
9652 /* Create file... */
9653 NC(nc_create(filename, NC_NETCDF4, &ncid));
9654
9655 /* Define dimensions... */
9656 NC(nc_def_dim(ncid, "obs", (size_t) atm->np, &obsid));
9657
9658 /* Define variables and their attributes... */
9659 NC_DEF_VAR("time", NC_DOUBLE, 1, &obsid, "time",
9660 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
9661 NC_DEF_VAR("press", NC_DOUBLE, 1, &obsid, "pressure", "hPa",
9662 ctl->atm_nc_level, 0);
9663 NC_DEF_VAR("lon", NC_DOUBLE, 1, &obsid, "longitude", "degrees_east",
9664 ctl->atm_nc_level, 0);
9665 NC_DEF_VAR("lat", NC_DOUBLE, 1, &obsid, "latitude", "degrees_north",
9666 ctl->atm_nc_level, 0);
9667 for (int iq = 0; iq < ctl->nq; iq++)
9668 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 1, &obsid,
9669 ctl->qnt_longname[iq], ctl->qnt_unit[iq],
9670 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
9671
9672 /* Define global attributes... */
9673 NC_PUT_ATT_GLOBAL("featureType", "point");
9674
9675 /* End definitions... */
9676 NC(nc_enddef(ncid));
9677
9678 /* Write data... */
9679 NC_PUT_DOUBLE("time", atm->time, 0);
9680 NC_PUT_DOUBLE("press", atm->p, 0);
9681 NC_PUT_DOUBLE("lon", atm->lon, 0);
9682 NC_PUT_DOUBLE("lat", atm->lat, 0);
9683 for (int iq = 0; iq < ctl->nq; iq++)
9684 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
9685
9686 /* Close file... */
9687 NC(nc_close(ncid));
9688}

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

9696 {
9697
9698 static FILE *out;
9699
9700 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
9701 *area, dlon, dlat, dz, x[NCSI], y[NCSI], obsstdn[NCSI], kz[EP], kw[EP];
9702
9703 static int *obscount, ct, cx, cy, cz, ip, ix, iy, iz, n, nobs, nk;
9704
9705 /* Set timer... */
9706 SELECT_TIMER("WRITE_CSI", "OUTPUT", NVTX_WRITE);
9707
9708 /* Init... */
9709 if (t == ctl->t_start) {
9710
9711 /* Check quantity index for mass... */
9712 if (ctl->qnt_m < 0)
9713 ERRMSG("Need quantity mass!");
9714
9715 /* Allocate... */
9716 ALLOC(area, double,
9717 ctl->csi_ny);
9718 ALLOC(rt, double,
9719 NOBS);
9720 ALLOC(rz, double,
9721 NOBS);
9722 ALLOC(rlon, double,
9723 NOBS);
9724 ALLOC(rlat, double,
9725 NOBS);
9726 ALLOC(robs, double,
9727 NOBS);
9728
9729 /* Read observation data... */
9730 read_obs(ctl->csi_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
9731
9732 /* Read kernel data... */
9733 if (ctl->csi_kernel[0] != '-')
9734 read_kernel(ctl->csi_kernel, kz, kw, &nk);
9735
9736 /* Create new file... */
9737 LOG(1, "Write CSI data: %s", filename);
9738 if (!(out = fopen(filename, "w")))
9739 ERRMSG("Cannot create file!");
9740
9741 /* Write header... */
9742 fprintf(out,
9743 "# $1 = time [s]\n"
9744 "# $2 = number of hits (cx)\n"
9745 "# $3 = number of misses (cy)\n"
9746 "# $4 = number of false alarms (cz)\n"
9747 "# $5 = number of observations (cx + cy)\n"
9748 "# $6 = number of forecasts (cx + cz)\n"
9749 "# $7 = bias (ratio of forecasts and observations) [%%]\n"
9750 "# $8 = probability of detection (POD) [%%]\n"
9751 "# $9 = false alarm rate (FAR) [%%]\n"
9752 "# $10 = critical success index (CSI) [%%]\n");
9753 fprintf(out,
9754 "# $11 = hits associated with random chance\n"
9755 "# $12 = equitable threat score (ETS) [%%]\n"
9756 "# $13 = Pearson linear correlation coefficient\n"
9757 "# $14 = Spearman rank-order correlation coefficient\n"
9758 "# $15 = column density mean error (F - O) [kg/m^2]\n"
9759 "# $16 = column density root mean square error (RMSE) [kg/m^2]\n"
9760 "# $17 = column density mean absolute error [kg/m^2]\n"
9761 "# $18 = log-likelihood function\n"
9762 "# $19 = number of data points\n\n");
9763
9764 /* Set grid box size... */
9765 dz = (ctl->csi_z1 - ctl->csi_z0) / ctl->csi_nz;
9766 dlon = (ctl->csi_lon1 - ctl->csi_lon0) / ctl->csi_nx;
9767 dlat = (ctl->csi_lat1 - ctl->csi_lat0) / ctl->csi_ny;
9768
9769 /* Set horizontal coordinates... */
9770 for (iy = 0; iy < ctl->csi_ny; iy++) {
9771 const double lat = ctl->csi_lat0 + dlat * (iy + 0.5);
9772 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat));
9773 }
9774 }
9775
9776 /* Set time interval... */
9777 const double t0 = t - 0.5 * ctl->dt_mod;
9778 const double t1 = t + 0.5 * ctl->dt_mod;
9779
9780 /* Allocate... */
9781 ALLOC(modmean, double,
9782 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
9783 ALLOC(obsmean, double,
9784 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
9785 ALLOC(obscount, int,
9786 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
9787 ALLOC(obsstd, double,
9788 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
9789
9790 /* Loop over observations... */
9791 for (int i = 0; i < nobs; i++) {
9792
9793 /* Check time... */
9794 if (rt[i] < t0)
9795 continue;
9796 else if (rt[i] >= t1)
9797 break;
9798
9799 /* Check observation data... */
9800 if (!isfinite(robs[i]))
9801 continue;
9802
9803 /* Calculate indices... */
9804 ix = (int) ((rlon[i] - ctl->csi_lon0) / dlon);
9805 iy = (int) ((rlat[i] - ctl->csi_lat0) / dlat);
9806 iz = (int) ((rz[i] - ctl->csi_z0) / dz);
9807
9808 /* Check indices... */
9809 if (ix < 0 || ix >= ctl->csi_nx ||
9810 iy < 0 || iy >= ctl->csi_ny || iz < 0 || iz >= ctl->csi_nz)
9811 continue;
9812
9813 /* Get mean observation index... */
9814 int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
9815 obsmean[idx] += robs[i];
9816 obsstd[idx] += SQR(robs[i]);
9817 obscount[idx]++;
9818 }
9819
9820 /* Analyze model data... */
9821 for (ip = 0; ip < atm->np; ip++) {
9822
9823 /* Check time... */
9824 if (atm->time[ip] < t0 || atm->time[ip] > t1)
9825 continue;
9826
9827 /* Get indices... */
9828 ix = (int) ((atm->lon[ip] - ctl->csi_lon0) / dlon);
9829 iy = (int) ((atm->lat[ip] - ctl->csi_lat0) / dlat);
9830 iz = (int) ((Z(atm->p[ip]) - ctl->csi_z0) / dz);
9831
9832 /* Check indices... */
9833 if (ix < 0 || ix >= ctl->csi_nx ||
9834 iy < 0 || iy >= ctl->csi_ny || iz < 0 || iz >= ctl->csi_nz)
9835 continue;
9836
9837 /* Get total mass in grid cell... */
9838 int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
9839 modmean[idx] += kernel_weight(kz, kw, nk, atm->p[ip])
9840 * atm->q[ctl->qnt_m][ip];
9841 }
9842
9843 /* Analyze all grid cells... */
9844 for (ix = 0; ix < ctl->csi_nx; ix++)
9845 for (iy = 0; iy < ctl->csi_ny; iy++)
9846 for (iz = 0; iz < ctl->csi_nz; iz++) {
9847
9848 /* Calculate mean observation index... */
9849 int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
9850 if (obscount[idx] > 0) {
9851 obsmean[idx] /= obscount[idx];
9852 obsstd[idx] -= SQR(obsmean[idx]);
9853 obsstd[idx] = sqrt(obsstd[idx]);
9854 }
9855
9856 /* Calculate column density... */
9857 if (modmean[idx] > 0)
9858 modmean[idx] /= (1e6 * area[iy]);
9859
9860 /* Calculate CSI... */
9861 if (obscount[idx] > 0) {
9862 ct++;
9863 if (obsmean[idx] >= ctl->csi_obsmin &&
9864 modmean[idx] >= ctl->csi_modmin)
9865 cx++;
9866 else if (obsmean[idx] >= ctl->csi_obsmin &&
9867 modmean[idx] < ctl->csi_modmin)
9868 cy++;
9869 else if (obsmean[idx] < ctl->csi_obsmin &&
9870 modmean[idx] >= ctl->csi_modmin)
9871 cz++;
9872 }
9873
9874 /* Save data for other verification statistics... */
9875 if (obscount[idx] > 0
9876 && (obsmean[idx] >= ctl->csi_obsmin
9877 || modmean[idx] >= ctl->csi_modmin)) {
9878 x[n] = modmean[idx];
9879 y[n] = obsmean[idx];
9880 if (modmean[idx] >= ctl->csi_modmin)
9881 obsstdn[n] = obsstd[idx];
9882 if ((++n) >= NCSI)
9883 ERRMSG("Too many data points to calculate statistics!");
9884 }
9885 }
9886
9887 /* Write output... */
9888 if (fmod(t, ctl->csi_dt_out) == 0) {
9889
9890 /* Calculate verification statistics
9891 (https://www.cawcr.gov.au/projects/verification/) ... */
9892 static double work[2 * NCSI], work2[2 * NCSI];;
9893 const int n_obs = cx + cy;
9894 const int n_for = cx + cz;
9895 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
9896 const double pod = (n_obs > 0) ? (100. * cx) / n_obs : NAN;
9897 const double far = (n_for > 0) ? (100. * cz) / n_for : NAN;
9898 const double csi =
9899 (cx + cy + cz > 0) ? (100. * cx) / (cx + cy + cz) : NAN;
9900 const double cx_rd = (ct > 0) ? (1. * n_obs * n_for) / ct : NAN;
9901 const double ets = (cx + cy + cz - cx_rd > 0) ?
9902 (100. * (cx - cx_rd)) / (cx + cy + cz - cx_rd) : NAN;
9903 const double rho_p =
9904 (n > 0) ? gsl_stats_correlation(x, 1, y, 1, (size_t) n) : NAN;
9905 const double rho_s =
9906 (n > 0) ? gsl_stats_spearman(x, 1, y, 1, (size_t) n, work) : NAN;
9907 for (int i = 0; i < n; i++) {
9908 work[i] = x[i] - y[i];
9909 work2[i] = (obsstdn[i] != 0) ? (x[i] - y[i]) / obsstdn[i] : 0;
9910 }
9911 const double mean = (n > 0) ? gsl_stats_mean(work, 1, (size_t) n) : NAN;
9912 const double rmse =
9913 (n > 0) ? gsl_stats_sd_with_fixed_mean(work, 1, (size_t) n,
9914 0.0) : NAN;
9915 const double absdev =
9916 (n > 0) ? gsl_stats_absdev_m(work, 1, (size_t) n, 0.0) : NAN;
9917 const double loglikelihood =
9918 (n > 0) ? gsl_stats_tss(work2, 1, (size_t) n) * (-0.5) : GSL_NAN;
9919
9920 /* Write... */
9921 fprintf(out,
9922 "%.2f %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n", t,
9923 cx, cy, cz, n_obs, n_for, bias, pod, far, csi, cx_rd, ets, rho_p,
9924 rho_s, mean, rmse, absdev, loglikelihood, n);
9925
9926 /* Set counters to zero... */
9927 n = ct = cx = cy = cz = 0;
9928 }
9929
9930 /* Free... */
9931 free(modmean);
9932 free(obsmean);
9933 free(obscount);
9934 free(obsstd);
9935
9936 /* Finalize... */
9937 if (t == ctl->t_stop) {
9938
9939 /* Close output file... */
9940 fclose(out);
9941
9942 /* Free... */
9943 free(area);
9944 free(rt);
9945 free(rz);
9946 free(rlon);
9947 free(rlat);
9948 free(robs);
9949 }
9950}
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:8828
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:6373
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:1731
#define NCSI
Maximum number of data points for CSI calculation.
Definition: mptrac.h:256
Here is the call graph for this function:

◆ write_ens()

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

Writes ensemble data to a file.

The write_ens function processes air parcel data to calculate ensemble means and standard deviations for various quantities and writes them to a specified output file. It handles ensemble members and calculates statistics such as means and standard deviations for each ensemble, along with latitude, longitude, altitude, and time information.

Parameters
filenameA string representing the name of the output file.
ctlA pointer to a ctl_t structure containing control parameters.
atmA pointer to an atm_t structure containing atmospheric data.
tA double representing the current time.

The function performs the following steps:

  • Initializes resources and sets up necessary variables.
  • Sets a time interval for processing data.
  • Loops over air parcels to accumulate means and standard deviations for each ensemble member.
  • Creates an output file and writes header information.
  • Writes ensemble data, including time, altitude, latitude, longitude, means, standard deviations, and the number of members.
  • Closes the output file.
Author
Lars Hoffmann

Definition at line 9954 of file mptrac.c.

9958 {
9959
9960 static FILE *out;
9961
9962 static double dummy, lat, lon, qm[NQ][NENS], qs[NQ][NENS], xm[NENS][3],
9963 x[3], zm[NENS];
9964
9965 static int n[NENS];
9966
9967 /* Set timer... */
9968 SELECT_TIMER("WRITE_ENS", "OUTPUT", NVTX_WRITE);
9969
9970 /* Check quantities... */
9971 if (ctl->qnt_ens < 0)
9972 ERRMSG("Missing ensemble IDs!");
9973
9974 /* Set time interval... */
9975 const double t0 = t - 0.5 * ctl->dt_mod;
9976 const double t1 = t + 0.5 * ctl->dt_mod;
9977
9978 /* Init... */
9979 for (int i = 0; i < NENS; i++) {
9980 for (int iq = 0; iq < ctl->nq; iq++)
9981 qm[iq][i] = qs[iq][i] = 0;
9982 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
9983 n[i] = 0;
9984 }
9985
9986 /* Loop over air parcels... */
9987 for (int ip = 0; ip < atm->np; ip++) {
9988
9989 /* Check time... */
9990 if (atm->time[ip] < t0 || atm->time[ip] > t1)
9991 continue;
9992
9993 /* Check ensemble ID... */
9994 if (atm->q[ctl->qnt_ens][ip] < 0 || atm->q[ctl->qnt_ens][ip] >= NENS)
9995 ERRMSG("Ensemble ID is out of range!");
9996
9997 /* Get means... */
9998 geo2cart(0, atm->lon[ip], atm->lat[ip], x);
9999 for (int iq = 0; iq < ctl->nq; iq++) {
10000 qm[iq][ctl->qnt_ens] += atm->q[iq][ip];
10001 qs[iq][ctl->qnt_ens] += SQR(atm->q[iq][ip]);
10002 }
10003 xm[ctl->qnt_ens][0] += x[0];
10004 xm[ctl->qnt_ens][1] += x[1];
10005 xm[ctl->qnt_ens][2] += x[2];
10006 zm[ctl->qnt_ens] += Z(atm->p[ip]);
10007 n[ctl->qnt_ens]++;
10008 }
10009
10010 /* Create file... */
10011 LOG(1, "Write ensemble data: %s", filename);
10012 if (!(out = fopen(filename, "w")))
10013 ERRMSG("Cannot create file!");
10014
10015 /* Write header... */
10016 fprintf(out,
10017 "# $1 = time [s]\n"
10018 "# $2 = altitude [km]\n"
10019 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
10020 for (int iq = 0; iq < ctl->nq; iq++)
10021 fprintf(out, "# $%d = %s (mean) [%s]\n", 5 + iq,
10022 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
10023 for (int iq = 0; iq < ctl->nq; iq++)
10024 fprintf(out, "# $%d = %s (sigma) [%s]\n", 5 + ctl->nq + iq,
10025 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
10026 fprintf(out, "# $%d = number of members\n\n", 5 + 2 * ctl->nq);
10027
10028 /* Write data... */
10029 for (int i = 0; i < NENS; i++)
10030 if (n[i] > 0) {
10031 cart2geo(xm[i], &dummy, &lon, &lat);
10032 fprintf(out, "%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
10033 for (int iq = 0; iq < ctl->nq; iq++) {
10034 fprintf(out, " ");
10035 fprintf(out, ctl->qnt_format[iq], qm[iq][i] / n[i]);
10036 }
10037 for (int iq = 0; iq < ctl->nq; iq++) {
10038 fprintf(out, " ");
10039 double var = qs[iq][i] / n[i] - SQR(qm[iq][i] / n[i]);
10040 fprintf(out, ctl->qnt_format[iq], (var > 0 ? sqrt(var) : 0));
10041 }
10042 fprintf(out, " %d\n", n[i]);
10043 }
10044
10045 /* Close file... */
10046 fclose(out);
10047}
void cart2geo(const double *x, double *z, double *lon, double *lat)
State variables of cuRAND random number generator.
Definition: mptrac.c:74
#define NENS
Maximum number of data points for ensemble analysis.
Definition: mptrac.h:276
Here is the call graph for this function:

◆ write_grid()

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

Writes grid data to a file in ASCII or netCDF format.

The write_grid function processes air parcel data to calculate various grid-based statistics such as column density, mean, and standard deviation for specified quantities. It then writes this data to a specified output file either in ASCII or netCDF format based on the configuration parameters provided in the ctl structure.

Parameters
filenameA string representing the name of the output file.
ctlA pointer to a ctl_t structure containing control parameters.
met0A pointer to a met_t structure containing meteorological data for the initial time step.
met1A pointer to a met_t structure containing meteorological data for the final time step.
atmA pointer to an atm_t structure containing atmospheric data.
tA double representing the current time.

The function performs the following steps:

  • Initializes resources and sets up necessary variables.
  • Reads kernel data if it is specified in the control parameters.
  • Allocates memory for various arrays to store grid data.
  • Determines the grid box size and sets up vertical and horizontal coordinates.
  • Sets a time interval for output data processing.
  • Calculates grid box indices for atmospheric model data.
  • Averages data within each grid box.
  • Calculates column density and volume mixing ratio.
  • Writes data to the output file either in ASCII or netCDF format based on the specified grid_type in the control parameters.
  • Frees allocated memory.
Note
The function supports parallel processing using OpenMP for certain computational tasks to improve performance.
Author
Lars Hoffmann

Definition at line 10051 of file mptrac.c.

10057 {
10058
10059 static double kz[EP], kw[EP];
10060
10061 static int nk;
10062
10063 double *cd, *mean[NQ], *sigma[NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
10064
10065 int *ixs, *iys, *izs, *np;
10066
10067 /* Set timer... */
10068 SELECT_TIMER("WRITE_GRID", "OUTPUT", NVTX_WRITE);
10069
10070 /* Write info... */
10071 LOG(1, "Write grid data: %s", filename);
10072
10073 /* Init... */
10074 if (t == ctl->t_start) {
10075
10076 /* Read kernel data... */
10077 if (ctl->grid_kernel[0] != '-')
10078 read_kernel(ctl->grid_kernel, kz, kw, &nk);
10079 }
10080
10081 /* Allocate... */
10082 ALLOC(cd, double,
10083 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10084 for (int iq = 0; iq < ctl->nq; iq++) {
10085 ALLOC(mean[iq], double,
10086 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10087 ALLOC(sigma[iq], double,
10088 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10089 }
10090 ALLOC(vmr_impl, double,
10091 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10092 ALLOC(z, double,
10093 ctl->grid_nz);
10094 ALLOC(lon, double,
10095 ctl->grid_nx);
10096 ALLOC(lat, double,
10097 ctl->grid_ny);
10098 ALLOC(area, double,
10099 ctl->grid_ny);
10100 ALLOC(press, double,
10101 ctl->grid_nz);
10102 ALLOC(np, int,
10103 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10104 ALLOC(ixs, int,
10105 atm->np);
10106 ALLOC(iys, int,
10107 atm->np);
10108 ALLOC(izs, int,
10109 atm->np);
10110
10111 /* Set grid box size... */
10112 const double dz = (ctl->grid_z1 - ctl->grid_z0) / ctl->grid_nz;
10113 const double dlon = (ctl->grid_lon1 - ctl->grid_lon0) / ctl->grid_nx;
10114 const double dlat = (ctl->grid_lat1 - ctl->grid_lat0) / ctl->grid_ny;
10115
10116 /* Set vertical coordinates... */
10117#pragma omp parallel for default(shared)
10118 for (int iz = 0; iz < ctl->grid_nz; iz++) {
10119 z[iz] = ctl->grid_z0 + dz * (iz + 0.5);
10120 press[iz] = P(z[iz]);
10121 }
10122
10123 /* Set horizontal coordinates... */
10124 for (int ix = 0; ix < ctl->grid_nx; ix++)
10125 lon[ix] = ctl->grid_lon0 + dlon * (ix + 0.5);
10126#pragma omp parallel for default(shared)
10127 for (int iy = 0; iy < ctl->grid_ny; iy++) {
10128 lat[iy] = ctl->grid_lat0 + dlat * (iy + 0.5);
10129 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
10130 }
10131
10132 /* Set time interval for output... */
10133 const double t0 = t - 0.5 * ctl->dt_mod;
10134 const double t1 = t + 0.5 * ctl->dt_mod;
10135
10136 /* Get grid box indices... */
10137#pragma omp parallel for default(shared)
10138 for (int ip = 0; ip < atm->np; ip++) {
10139 ixs[ip] = (int) ((atm->lon[ip] - ctl->grid_lon0) / dlon);
10140 iys[ip] = (int) ((atm->lat[ip] - ctl->grid_lat0) / dlat);
10141 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->grid_z0) / dz);
10142 if (atm->time[ip] < t0 || atm->time[ip] > t1
10143 || ixs[ip] < 0 || ixs[ip] >= ctl->grid_nx
10144 || iys[ip] < 0 || iys[ip] >= ctl->grid_ny
10145 || izs[ip] < 0 || izs[ip] >= ctl->grid_nz)
10146 izs[ip] = -1;
10147 }
10148
10149 /* Average data... */
10150 for (int ip = 0; ip < atm->np; ip++)
10151 if (izs[ip] >= 0) {
10152 int idx =
10153 ARRAY_3D(ixs[ip], iys[ip], ctl->grid_ny, izs[ip], ctl->grid_nz);
10154 double kernel = kernel_weight(kz, kw, nk, atm->p[ip]);
10155 np[idx]++;
10156 for (int iq = 0; iq < ctl->nq; iq++) {
10157 mean[iq][idx] += kernel * atm->q[iq][ip];
10158 sigma[iq][idx] += SQR(kernel * atm->q[iq][ip]);
10159 }
10160 }
10161
10162 /* Calculate column density and volume mixing ratio... */
10163#pragma omp parallel for default(shared)
10164 for (int ix = 0; ix < ctl->grid_nx; ix++)
10165 for (int iy = 0; iy < ctl->grid_ny; iy++)
10166 for (int iz = 0; iz < ctl->grid_nz; iz++) {
10167
10168 /* Get grid index... */
10169 int idx = ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz);
10170
10171 /* Calculate column density... */
10172 cd[idx] = NAN;
10173 if (ctl->qnt_m >= 0)
10174 cd[idx] = mean[ctl->qnt_m][idx] / (1e6 * area[iy]);
10175
10176 /* Calculate volume mixing ratio (implicit)... */
10177 vmr_impl[idx] = NAN;
10178 if (ctl->qnt_m >= 0 && ctl->molmass > 0 && met0 != NULL
10179 && met1 != NULL) {
10180 vmr_impl[idx] = 0;
10181 if (mean[ctl->qnt_m][idx] > 0) {
10182
10183 /* Get temperature... */
10184 double temp;
10186 intpol_met_time_3d(met0, met0->t, met1, met1->t, t, press[iz],
10187 lon[ix], lat[iy], &temp, ci, cw, 1);
10188
10189 /* Calculate volume mixing ratio... */
10190 vmr_impl[idx] =
10191 MA / ctl->molmass * cd[idx] / (RHO(press[iz], temp) * dz * 1e3);
10192 }
10193 }
10194
10195 /* Calculate mean... */
10196 if (np[idx] > 0)
10197 for (int iq = 0; iq < ctl->nq; iq++) {
10198 mean[iq][idx] /= np[idx];
10199 double var = sigma[iq][idx] / np[idx] - SQR(mean[iq][idx]);
10200 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
10201 } else
10202 for (int iq = 0; iq < ctl->nq; iq++) {
10203 mean[iq][idx] = NAN;
10204 sigma[iq][idx] = NAN;
10205 }
10206 }
10207
10208 /* Write ASCII data... */
10209 if (ctl->grid_type == 0)
10210 write_grid_asc(filename, ctl, cd, mean, sigma, vmr_impl,
10211 t, z, lon, lat, area, dz, np);
10212
10213 /* Write netCDF data... */
10214 else if (ctl->grid_type == 1)
10215 write_grid_nc(filename, ctl, cd, mean, sigma, vmr_impl,
10216 t, z, lon, lat, area, dz, np);
10217
10218 /* Error message... */
10219 else
10220 ERRMSG("Grid data format GRID_TYPE unknown!");
10221
10222 /* Free... */
10223 free(cd);
10224 for (int iq = 0; iq < ctl->nq; iq++) {
10225 free(mean[iq]);
10226 free(sigma[iq]);
10227 }
10228 free(vmr_impl);
10229 free(z);
10230 free(lon);
10231 free(lat);
10232 free(area);
10233 free(press);
10234 free(np);
10235 free(ixs);
10236 free(iys);
10237 free(izs);
10238}
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:10242
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:10346
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 10242 of file mptrac.c.

10255 {
10256
10257 FILE *out;
10258
10259 /* Check if gnuplot output is requested... */
10260 if (ctl->grid_gpfile[0] != '-') {
10261
10262 /* Create gnuplot pipe... */
10263 if (!(out = popen("gnuplot", "w")))
10264 ERRMSG("Cannot create pipe to gnuplot!");
10265
10266 /* Set plot filename... */
10267 fprintf(out, "set out \"%s.png\"\n", filename);
10268
10269 /* Set time string... */
10270 double r;
10271 int year, mon, day, hour, min, sec;
10272 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
10273 fprintf(out, "timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
10274 year, mon, day, hour, min);
10275
10276 /* Dump gnuplot file to pipe... */
10277 FILE *in;
10278 char line[LEN];
10279 if (!(in = fopen(ctl->grid_gpfile, "r")))
10280 ERRMSG("Cannot open file!");
10281 while (fgets(line, LEN, in))
10282 fprintf(out, "%s", line);
10283 fclose(in);
10284 }
10285
10286 else {
10287
10288 /* Create file... */
10289 if (!(out = fopen(filename, "w")))
10290 ERRMSG("Cannot create file!");
10291 }
10292
10293 /* Write header... */
10294 fprintf(out,
10295 "# $1 = time [s]\n"
10296 "# $2 = altitude [km]\n"
10297 "# $3 = longitude [deg]\n"
10298 "# $4 = latitude [deg]\n"
10299 "# $5 = surface area [km^2]\n"
10300 "# $6 = layer depth [km]\n"
10301 "# $7 = column density (implicit) [kg/m^2]\n"
10302 "# $8 = volume mixing ratio (implicit) [ppv]\n"
10303 "# $9 = number of particles [1]\n");
10304 for (int iq = 0; iq < ctl->nq; iq++)
10305 fprintf(out, "# $%i = %s (mean) [%s]\n", 10 + iq, ctl->qnt_name[iq],
10306 ctl->qnt_unit[iq]);
10307 if (ctl->grid_stddev)
10308 for (int iq = 0; iq < ctl->nq; iq++)
10309 fprintf(out, "# $%i = %s (stddev) [%s]\n", 10 + ctl->nq + iq,
10310 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
10311 fprintf(out, "\n");
10312
10313 /* Write data... */
10314 for (int ix = 0; ix < ctl->grid_nx; ix++) {
10315 if (ix > 0 && ctl->grid_ny > 1 && !ctl->grid_sparse)
10316 fprintf(out, "\n");
10317 for (int iy = 0; iy < ctl->grid_ny; iy++) {
10318 if (iy > 0 && ctl->grid_nz > 1 && !ctl->grid_sparse)
10319 fprintf(out, "\n");
10320 for (int iz = 0; iz < ctl->grid_nz; iz++) {
10321 int idx = ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz);
10322 if (!ctl->grid_sparse || vmr_impl[idx] > 0) {
10323 fprintf(out, "%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
10324 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
10325 for (int iq = 0; iq < ctl->nq; iq++) {
10326 fprintf(out, " ");
10327 fprintf(out, ctl->qnt_format[iq], mean[iq][idx]);
10328 }
10329 if (ctl->grid_stddev)
10330 for (int iq = 0; iq < ctl->nq; iq++) {
10331 fprintf(out, " ");
10332 fprintf(out, ctl->qnt_format[iq], sigma[iq][idx]);
10333 }
10334 fprintf(out, "\n");
10335 }
10336 }
10337 }
10338 }
10339
10340 /* Close file... */
10341 fclose(out);
10342}
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 10346 of file mptrac.c.

10359 {
10360
10361 char longname[2 * LEN], varname[2 * LEN];
10362
10363 double *help;
10364
10365 int *help2, ncid, dimid[10], varid;
10366
10367 size_t start[2], count[2];
10368
10369 /* Allocate... */
10370 ALLOC(help, double,
10371 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10372 ALLOC(help2, int,
10373 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10374
10375 /* Create file... */
10376 NC(nc_create(filename, NC_NETCDF4, &ncid));
10377
10378 /* Define dimensions... */
10379 NC(nc_def_dim(ncid, "time", 1, &dimid[0]));
10380 NC(nc_def_dim(ncid, "z", (size_t) ctl->grid_nz, &dimid[1]));
10381 NC(nc_def_dim(ncid, "lat", (size_t) ctl->grid_ny, &dimid[2]));
10382 NC(nc_def_dim(ncid, "lon", (size_t) ctl->grid_nx, &dimid[3]));
10383 NC(nc_def_dim(ncid, "dz", 1, &dimid[4]));
10384
10385 /* Define variables and their attributes... */
10386 NC_DEF_VAR("time", NC_DOUBLE, 1, &dimid[0], "time",
10387 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
10388 NC_DEF_VAR("z", NC_DOUBLE, 1, &dimid[1], "altitude", "km", 0, 0);
10389 NC_DEF_VAR("lat", NC_DOUBLE, 1, &dimid[2], "latitude", "degrees_north", 0,
10390 0);
10391 NC_DEF_VAR("lon", NC_DOUBLE, 1, &dimid[3], "longitude", "degrees_east", 0,
10392 0);
10393 NC_DEF_VAR("dz", NC_DOUBLE, 1, &dimid[1], "layer depth", "km", 0, 0);
10394 NC_DEF_VAR("area", NC_DOUBLE, 1, &dimid[2], "surface area", "km**2", 0, 0);
10395
10396 NC_DEF_VAR("cd", NC_FLOAT, 4, dimid, "column density", "kg m**-2",
10397 ctl->grid_nc_level, 0);
10398 NC_DEF_VAR("vmr_impl", NC_FLOAT, 4, dimid, "volume mixing ratio (implicit)",
10399 "ppv", ctl->grid_nc_level, 0);
10400 NC_DEF_VAR("np", NC_INT, 4, dimid, "number of particles", "1", 0, 0);
10401 for (int iq = 0; iq < ctl->nq; iq++) {
10402 sprintf(varname, "%s_mean", ctl->qnt_name[iq]);
10403 sprintf(longname, "%s (mean)", ctl->qnt_longname[iq]);
10404 NC_DEF_VAR(varname, NC_DOUBLE, 4, dimid, longname, ctl->qnt_unit[iq],
10405 ctl->grid_nc_level, ctl->grid_nc_quant[iq]);
10406 if (ctl->grid_stddev) {
10407 sprintf(varname, "%s_stddev", ctl->qnt_name[iq]);
10408 sprintf(longname, "%s (stddev)", ctl->qnt_longname[iq]);
10409 NC_DEF_VAR(varname, NC_DOUBLE, 4, dimid, longname, ctl->qnt_unit[iq],
10410 ctl->grid_nc_level, ctl->grid_nc_quant[iq]);
10411 }
10412 }
10413 /* End definitions... */
10414 NC(nc_enddef(ncid));
10415
10416 /* Write data... */
10417 NC_PUT_DOUBLE("time", &t, 0);
10418 NC_PUT_DOUBLE("lon", lon, 0);
10419 NC_PUT_DOUBLE("lat", lat, 0);
10420 NC_PUT_DOUBLE("z", z, 0);
10421 NC_PUT_DOUBLE("area", area, 0);
10422 NC_PUT_DOUBLE("dz", &dz, 0);
10423
10424 for (int ix = 0; ix < ctl->grid_nx; ix++)
10425 for (int iy = 0; iy < ctl->grid_ny; iy++)
10426 for (int iz = 0; iz < ctl->grid_nz; iz++)
10427 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
10428 cd[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
10429 NC_PUT_DOUBLE("cd", help, 0);
10430
10431 for (int ix = 0; ix < ctl->grid_nx; ix++)
10432 for (int iy = 0; iy < ctl->grid_ny; iy++)
10433 for (int iz = 0; iz < ctl->grid_nz; iz++)
10434 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
10435 vmr_impl[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
10436 NC_PUT_DOUBLE("vmr_impl", help, 0);
10437
10438 for (int ix = 0; ix < ctl->grid_nx; ix++)
10439 for (int iy = 0; iy < ctl->grid_ny; iy++)
10440 for (int iz = 0; iz < ctl->grid_nz; iz++)
10441 help2[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
10442 np[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
10443 NC_PUT_INT("np", help2, 0);
10444
10445 for (int iq = 0; iq < ctl->nq; iq++) {
10446 sprintf(varname, "%s_mean", ctl->qnt_name[iq]);
10447 for (int ix = 0; ix < ctl->grid_nx; ix++)
10448 for (int iy = 0; iy < ctl->grid_ny; iy++)
10449 for (int iz = 0; iz < ctl->grid_nz; iz++)
10450 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
10451 mean[iq][ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
10452 NC_PUT_DOUBLE(varname, help, 0);
10453 }
10454
10455 if (ctl->grid_stddev)
10456 for (int iq = 0; iq < ctl->nq; iq++) {
10457 sprintf(varname, "%s_stddev", ctl->qnt_name[iq]);
10458 for (int ix = 0; ix < ctl->grid_nx; ix++)
10459 for (int iy = 0; iy < ctl->grid_ny; iy++)
10460 for (int iz = 0; iz < ctl->grid_nz; iz++)
10461 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
10462 sigma[iq][ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
10463 NC_PUT_DOUBLE(varname, help, 0);
10464 }
10465
10466 /* Close file... */
10467 NC(nc_close(ncid));
10468
10469 /* Free... */
10470 free(help);
10471 free(help2);
10472}
#define NC_PUT_INT(varname, ptr, hyperslab)
Write integer data to a NetCDF variable.
Definition: mptrac.h:1173

◆ write_met_bin()

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

Writes meteorological data in binary format to a specified file.

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

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

Definition at line 10476 of file mptrac.c.

10479 {
10480
10481 /* Create file... */
10482 FILE *out;
10483 if (!(out = fopen(filename, "w")))
10484 ERRMSG("Cannot create file!");
10485
10486 /* Write type of binary data... */
10487 FWRITE(&ctl->met_type, int,
10488 1,
10489 out);
10490
10491 /* Write version of binary data... */
10492 int version = 103;
10493 FWRITE(&version, int,
10494 1,
10495 out);
10496
10497 /* Write grid data... */
10498 FWRITE(&met->time, double,
10499 1,
10500 out);
10501 FWRITE(&met->nx, int,
10502 1,
10503 out);
10504 FWRITE(&met->ny, int,
10505 1,
10506 out);
10507 FWRITE(&met->np, int,
10508 1,
10509 out);
10510 FWRITE(met->lon, double,
10511 (size_t) met->nx,
10512 out);
10513 FWRITE(met->lat, double,
10514 (size_t) met->ny,
10515 out);
10516 FWRITE(met->p, double,
10517 (size_t) met->np,
10518 out);
10519
10520 /* Write surface data... */
10521 write_met_bin_2d(out, met, met->ps, "PS");
10522 write_met_bin_2d(out, met, met->ts, "TS");
10523 write_met_bin_2d(out, met, met->zs, "ZS");
10524 write_met_bin_2d(out, met, met->us, "US");
10525 write_met_bin_2d(out, met, met->vs, "VS");
10526 write_met_bin_2d(out, met, met->ess, "ESS");
10527 write_met_bin_2d(out, met, met->nss, "NSS");
10528 write_met_bin_2d(out, met, met->shf, "SHF");
10529 write_met_bin_2d(out, met, met->lsm, "LSM");
10530 write_met_bin_2d(out, met, met->sst, "SST");
10531 write_met_bin_2d(out, met, met->pbl, "PBL");
10532 write_met_bin_2d(out, met, met->pt, "PT");
10533 write_met_bin_2d(out, met, met->tt, "TT");
10534 write_met_bin_2d(out, met, met->zt, "ZT");
10535 write_met_bin_2d(out, met, met->h2ot, "H2OT");
10536 write_met_bin_2d(out, met, met->pct, "PCT");
10537 write_met_bin_2d(out, met, met->pcb, "PCB");
10538 write_met_bin_2d(out, met, met->cl, "CL");
10539 write_met_bin_2d(out, met, met->plcl, "PLCL");
10540 write_met_bin_2d(out, met, met->plfc, "PLFC");
10541 write_met_bin_2d(out, met, met->pel, "PEL");
10542 write_met_bin_2d(out, met, met->cape, "CAPE");
10543 write_met_bin_2d(out, met, met->cin, "CIN");
10544 write_met_bin_2d(out, met, met->o3c, "O3C");
10545
10546 /* Write level data... */
10547 write_met_bin_3d(out, ctl, met, met->z, "Z",
10548 (ctl->met_zfp_tol_z <= 0 ? ctl->met_zfp_prec : 0),
10549 ctl->met_zfp_tol_z);
10550 write_met_bin_3d(out, ctl, met, met->t, "T",
10551 (ctl->met_zfp_tol_t <= 0 ? ctl->met_zfp_prec : 0),
10552 ctl->met_zfp_tol_t);
10553 write_met_bin_3d(out, ctl, met, met->u, "U", ctl->met_zfp_prec, 0);
10554 write_met_bin_3d(out, ctl, met, met->v, "V", ctl->met_zfp_prec, 0);
10555 write_met_bin_3d(out, ctl, met, met->w, "W", ctl->met_zfp_prec, 0);
10556 write_met_bin_3d(out, ctl, met, met->pv, "PV", ctl->met_zfp_prec, 0);
10557 write_met_bin_3d(out, ctl, met, met->h2o, "H2O", ctl->met_zfp_prec, 0);
10558 write_met_bin_3d(out, ctl, met, met->o3, "O3", ctl->met_zfp_prec, 0);
10559 write_met_bin_3d(out, ctl, met, met->lwc, "LWC", ctl->met_zfp_prec, 0);
10560 write_met_bin_3d(out, ctl, met, met->rwc, "RWC", ctl->met_zfp_prec, 0);
10561 write_met_bin_3d(out, ctl, met, met->iwc, "IWC", ctl->met_zfp_prec, 0);
10562 write_met_bin_3d(out, ctl, met, met->swc, "SWC", ctl->met_zfp_prec, 0);
10563 write_met_bin_3d(out, ctl, met, met->cc, "CC", ctl->met_zfp_prec, 0);
10564
10565 /* Write final flag... */
10566 int final = 999;
10567 FWRITE(&final, int,
10568 1,
10569 out);
10570
10571 /* Close file... */
10572 fclose(out);
10573}
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:10606
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:10577
int met_zfp_prec
ZFP compression precision for all variables, except z and T.
Definition: mptrac.h:2498
double met_zfp_tol_t
ZFP compression tolerance for temperature.
Definition: mptrac.h:2501
double met_zfp_tol_z
ZFP compression tolerance for geopotential height.
Definition: mptrac.h:2504
Here is the call graph for this function:

◆ write_met_bin_2d()

void write_met_bin_2d ( FILE *  out,
met_t met,
float  var[EX][EY],
const char *  varname 
)

Writes a 2-dimensional meteorological variable to a binary file.

The write_met_bin_2d function writes a 2-dimensional meteorological variable to a binary file specified by the out parameter. The variable data is provided in a 2-dimensional array var with maximum dimensions EX by EY. The variable name is provided as a string in the varname parameter.

Parameters
outA pointer to a FILE structure representing the output file.
metA pointer to a met_t structure containing meteorological data.
varAn array of floats representing the 2-dimensional variable data.
varnameA string containing the name of the variable being written.

The function performs the following steps:

  • Allocates memory for a temporary buffer to hold the variable data.
  • Copies the variable data from the 2-dimensional array var to the temporary buffer help.
  • Writes the uncompressed variable data to the binary file specified by out.
  • Logs a message indicating the successful writing of the variable data.
  • Frees the allocated memory.
Note
This function is typically used to write surface data or other 2-dimensional meteorological variables to a binary file.
Author
Lars Hoffmann

Definition at line 10577 of file mptrac.c.

10581 {
10582
10583 float *help;
10584
10585 /* Allocate... */
10586 ALLOC(help, float,
10587 EX * EY);
10588
10589 /* Copy data... */
10590 for (int ix = 0; ix < met->nx; ix++)
10591 for (int iy = 0; iy < met->ny; iy++)
10592 help[ARRAY_2D(ix, iy, met->ny)] = var[ix][iy];
10593
10594 /* Write uncompressed data... */
10595 LOG(2, "Write 2-D variable: %s (uncompressed)", varname);
10596 FWRITE(help, float,
10597 (size_t) (met->nx * met->ny),
10598 out);
10599
10600 /* Free... */
10601 free(help);
10602}

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

10613 {
10614
10615 float *help;
10616
10617 /* Allocate... */
10618 ALLOC(help, float,
10619 EX * EY * EP);
10620
10621 /* Copy data... */
10622#pragma omp parallel for default(shared) collapse(2)
10623 for (int ix = 0; ix < met->nx; ix++)
10624 for (int iy = 0; iy < met->ny; iy++)
10625 for (int ip = 0; ip < met->np; ip++)
10626 help[ARRAY_3D(ix, iy, met->ny, ip, met->np)] = var[ix][iy][ip];
10627
10628 /* Write uncompressed data... */
10629 if (ctl->met_type == 1) {
10630 LOG(2, "Write 3-D variable: %s (uncompressed)", varname);
10631 FWRITE(help, float,
10632 (size_t) (met->nx * met->ny * met->np),
10633 out);
10634 }
10635
10636 /* Write packed data... */
10637 else if (ctl->met_type == 2)
10638 compress_pck(varname, help, (size_t) (met->ny * met->nx),
10639 (size_t) met->np, 0, out);
10640
10641 /* Write zfp data... */
10642#ifdef ZFP
10643 else if (ctl->met_type == 3) {
10644 FWRITE(&precision, int,
10645 1,
10646 out);
10647 FWRITE(&tolerance, double,
10648 1,
10649 out);
10650 compress_zfp(varname, help, met->np, met->ny, met->nx, precision,
10651 tolerance, 0, out);
10652 }
10653#endif
10654
10655 /* Write zstd data... */
10656#ifdef ZSTD
10657 else if (ctl->met_type == 4)
10658 compress_zstd(varname, help, (size_t) (met->np * met->ny * met->nx), 0,
10659 out);
10660#endif
10661
10662 /* Write cmultiscale data... */
10663#ifdef CMS
10664 else if (ctl->met_type == 5) {
10665 compress_cms(ctl, varname, help, (size_t) met->nx, (size_t) met->ny,
10666 (size_t) met->np, 0, out);
10667 }
10668#endif
10669
10670 /* Unknown method... */
10671 else {
10672 ERRMSG("MET_TYPE not supported!");
10673 LOG(3, "%d %g", precision, tolerance);
10674 }
10675
10676 /* Free... */
10677 free(help);
10678}
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 10682 of file mptrac.c.

10685 {
10686
10687 /* Create file... */
10688 int ncid, varid;
10689 size_t start[4], count[4];
10690 nc_create(filename, NC_NETCDF4, &ncid);
10691
10692 /* Define dimensions... */
10693 int tid, lonid, latid, levid;
10694 NC(nc_def_dim(ncid, "time", 1, &tid));
10695 NC(nc_def_dim(ncid, "lon", (size_t) met->nx, &lonid));
10696 NC(nc_def_dim(ncid, "lat", (size_t) met->ny, &latid));
10697 NC(nc_def_dim(ncid, "lev", (size_t) met->np, &levid));
10698
10699 /* Define grid... */
10700 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "time",
10701 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
10702 NC_DEF_VAR("lon", NC_DOUBLE, 1, &lonid, "longitude", "degrees_east", 0, 0);
10703 NC_DEF_VAR("lat", NC_DOUBLE, 1, &latid, "latitude", "degrees_north", 0, 0);
10704 NC_DEF_VAR("lev", NC_DOUBLE, 1, &levid, "pressure", "Pa", 0, 0);
10705
10706 /* Define surface variables... */
10707 int dimid2[2] = { latid, lonid };
10708 NC_DEF_VAR("sp", NC_FLOAT, 2, dimid2, "Surface pressure", "Pa",
10709 ctl->met_nc_level, 0);
10710 NC_DEF_VAR("z", NC_FLOAT, 2, dimid2, "Geopotential", "m**2 s**-2",
10711 ctl->met_nc_level, 0);
10712 NC_DEF_VAR("t2m", NC_FLOAT, 2, dimid2, "2 metre temperature", "K",
10713 ctl->met_nc_level, 0);
10714 NC_DEF_VAR("u10m", NC_FLOAT, 2, dimid2, "10 metre U wind component",
10715 "m s**-1", ctl->met_nc_level, 0);
10716 NC_DEF_VAR("v10m", NC_FLOAT, 2, dimid2, "10 metre V wind component",
10717 "m s**-1", ctl->met_nc_level, 0);
10718 NC_DEF_VAR("iews", NC_FLOAT, 2, dimid2,
10719 "Instantaneous eastward turbulent surface stress", "N m**-2",
10720 ctl->met_nc_level, 0);
10721 NC_DEF_VAR("inss", NC_FLOAT, 2, dimid2,
10722 "Instantaneous northward turbulent surface stress", "N m**-2",
10723 ctl->met_nc_level, 0);
10724 NC_DEF_VAR("ishf", NC_FLOAT, 2, dimid2,
10725 "Instantaneous surface sensible heat flux", "W m**-1",
10726 ctl->met_nc_level, 0);
10727 NC_DEF_VAR("lsm", NC_FLOAT, 2, dimid2, "Land/sea mask", "-",
10728 ctl->met_nc_level, 0);
10729 NC_DEF_VAR("sstk", NC_FLOAT, 2, dimid2, "Sea surface temperature", "K",
10730 ctl->met_nc_level, 0);
10731 NC_DEF_VAR("blp", NC_FLOAT, 2, dimid2, "Boundary layer pressure", "Pa",
10732 ctl->met_nc_level, 0);
10733 NC_DEF_VAR("pt", NC_FLOAT, 2, dimid2, "Tropopause pressure", "Pa",
10734 ctl->met_nc_level, 0);
10735 NC_DEF_VAR("tt", NC_FLOAT, 2, dimid2, "Tropopause temperature", "K",
10736 ctl->met_nc_level, 0);
10737 NC_DEF_VAR("zt", NC_FLOAT, 2, dimid2, "Tropopause height", "m",
10738 ctl->met_nc_level, 0);
10739 NC_DEF_VAR("h2ot", NC_FLOAT, 2, dimid2, "Tropopause water vapor", "ppv",
10740 ctl->met_nc_level, 0);
10741 NC_DEF_VAR("pct", NC_FLOAT, 2, dimid2, "Cloud top pressure", "Pa",
10742 ctl->met_nc_level, 0);
10743 NC_DEF_VAR("pcb", NC_FLOAT, 2, dimid2, "Cloud bottom pressure", "Pa",
10744 ctl->met_nc_level, 0);
10745 NC_DEF_VAR("cl", NC_FLOAT, 2, dimid2, "Total column cloud water", "kg m**2",
10746 ctl->met_nc_level, 0);
10747 NC_DEF_VAR("plcl", NC_FLOAT, 2, dimid2,
10748 "Pressure at lifted condensation level (LCL)", "Pa",
10749 ctl->met_nc_level, 0);
10750 NC_DEF_VAR("plfc", NC_FLOAT, 2, dimid2,
10751 "Pressure at level of free convection (LFC)", "Pa",
10752 ctl->met_nc_level, 0);
10753 NC_DEF_VAR("pel", NC_FLOAT, 2, dimid2, "Pressure at equilibrium level (EL)",
10754 "Pa", ctl->met_nc_level, 0);
10755 NC_DEF_VAR("cape", NC_FLOAT, 2, dimid2,
10756 "Convective available potential energy", "J kg**-1",
10757 ctl->met_nc_level, 0);
10758 NC_DEF_VAR("cin", NC_FLOAT, 2, dimid2, "Convective inhibition", "J kg**-1",
10759 ctl->met_nc_level, 0);
10760 NC_DEF_VAR("o3c", NC_FLOAT, 2, dimid2, "Total column ozone", "DU",
10761 ctl->met_nc_level, 0);
10762
10763 /* Define level data... */
10764 int dimid3[3] = { levid, latid, lonid };
10765 NC_DEF_VAR("t", NC_FLOAT, 3, dimid3, "Temperature", "K",
10766 ctl->met_nc_level, ctl->met_nc_quant);
10767 NC_DEF_VAR("u", NC_FLOAT, 3, dimid3, "U velocity", "m s**-1",
10768 ctl->met_nc_level, ctl->met_nc_quant);
10769 NC_DEF_VAR("v", NC_FLOAT, 3, dimid3, "V velocity", "m s**-1",
10770 ctl->met_nc_level, ctl->met_nc_quant);
10771 NC_DEF_VAR("w", NC_FLOAT, 3, dimid3, "Vertical velocity", "Pa s**-1",
10772 ctl->met_nc_level, ctl->met_nc_quant);
10773 NC_DEF_VAR("q", NC_FLOAT, 3, dimid3, "Specific humidity", "kg kg**-1",
10774 ctl->met_nc_level, ctl->met_nc_quant);
10775 NC_DEF_VAR("o3", NC_FLOAT, 3, dimid3, "Ozone mass mixing ratio",
10776 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
10777 NC_DEF_VAR("clwc", NC_FLOAT, 3, dimid3, "Cloud liquid water content",
10778 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
10779 NC_DEF_VAR("crwc", NC_FLOAT, 3, dimid3, "Cloud rain water content",
10780 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
10781 NC_DEF_VAR("ciwc", NC_FLOAT, 3, dimid3, "Cloud ice water content",
10782 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
10783 NC_DEF_VAR("cswc", NC_FLOAT, 3, dimid3, "Cloud snow water content",
10784 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
10785 NC_DEF_VAR("cc", NC_FLOAT, 3, dimid3, "Cloud cover", "-",
10786 ctl->met_nc_level, ctl->met_nc_quant);
10787
10788 /* End definitions... */
10789 NC(nc_enddef(ncid));
10790
10791 /* Write grid data... */
10792 NC_PUT_DOUBLE("time", &met->time, 0);
10793 NC_PUT_DOUBLE("lon", met->lon, 0);
10794 NC_PUT_DOUBLE("lat", met->lat, 0);
10795 double phelp[EP];
10796 for (int ip = 0; ip < met->np; ip++)
10797 phelp[ip] = 100. * met->p[ip];
10798 NC_PUT_DOUBLE("lev", phelp, 0);
10799
10800 /* Write surface data... */
10801 write_met_nc_2d(ncid, "sp", met, met->ps, 100.0f);
10802 write_met_nc_2d(ncid, "z", met, met->zs, (float) (1000. * G0));
10803 write_met_nc_2d(ncid, "t2m", met, met->ts, 1.0f);
10804 write_met_nc_2d(ncid, "u10m", met, met->us, 1.0f);
10805 write_met_nc_2d(ncid, "v10m", met, met->vs, 1.0f);
10806 write_met_nc_2d(ncid, "iews", met, met->ess, 1.0f);
10807 write_met_nc_2d(ncid, "inss", met, met->nss, 1.0f);
10808 write_met_nc_2d(ncid, "ishf", met, met->shf, 1.0f);
10809 write_met_nc_2d(ncid, "lsm", met, met->lsm, 1.0f);
10810 write_met_nc_2d(ncid, "sstk", met, met->sst, 1.0f);
10811 write_met_nc_2d(ncid, "blp", met, met->pbl, 100.0f);
10812 write_met_nc_2d(ncid, "pt", met, met->pt, 100.0f);
10813 write_met_nc_2d(ncid, "tt", met, met->tt, 1.0f);
10814 write_met_nc_2d(ncid, "zt", met, met->zt, 1000.0f);
10815 write_met_nc_2d(ncid, "h2ot", met, met->h2ot, 1.0f);
10816 write_met_nc_2d(ncid, "pct", met, met->pct, 100.0f);
10817 write_met_nc_2d(ncid, "pcb", met, met->pcb, 100.0f);
10818 write_met_nc_2d(ncid, "cl", met, met->cl, 1.0f);
10819 write_met_nc_2d(ncid, "plcl", met, met->plcl, 100.0f);
10820 write_met_nc_2d(ncid, "plfc", met, met->plfc, 100.0f);
10821 write_met_nc_2d(ncid, "pel", met, met->pel, 100.0f);
10822 write_met_nc_2d(ncid, "cape", met, met->cape, 1.0f);
10823 write_met_nc_2d(ncid, "cin", met, met->cin, 1.0f);
10824 write_met_nc_2d(ncid, "o3c", met, met->o3c, 1.0f);
10825
10826 /* Write level data... */
10827 write_met_nc_3d(ncid, "t", met, met->t, 1.0f);
10828 write_met_nc_3d(ncid, "u", met, met->u, 1.0f);
10829 write_met_nc_3d(ncid, "v", met, met->v, 1.0f);
10830 write_met_nc_3d(ncid, "w", met, met->w, 100.0f);
10831 write_met_nc_3d(ncid, "q", met, met->h2o, (float) (MH2O / MA));
10832 write_met_nc_3d(ncid, "o3", met, met->o3, (float) (MO3 / MA));
10833 write_met_nc_3d(ncid, "clwc", met, met->lwc, 1.0f);
10834 write_met_nc_3d(ncid, "crwc", met, met->rwc, 1.0f);
10835 write_met_nc_3d(ncid, "ciwc", met, met->iwc, 1.0f);
10836 write_met_nc_3d(ncid, "cswc", met, met->swc, 1.0f);
10837 write_met_nc_3d(ncid, "cc", met, met->cc, 1.0f);
10838
10839 /* Close file... */
10840 NC(nc_close(ncid));
10841}
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:10845
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:10874
int met_nc_quant
Number of digits for quantization of netCDF meteo files (0=off).
Definition: mptrac.h:2495
int met_nc_level
zlib compression level of netCDF meteo files (0=off).
Definition: mptrac.h:2492
Here is the call graph for this function:

◆ write_met_nc_2d()

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

Writes a 2D meteorological variable to a NetCDF file.

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

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

Definition at line 10845 of file mptrac.c.

10850 {
10851
10852 int varid;
10853 size_t start[4], count[4];
10854
10855 /* Allocate... */
10856 float *help;
10857 ALLOC(help, float,
10858 EX * EY);
10859
10860 /* Copy data... */
10861 for (int ix = 0; ix < met->nx; ix++)
10862 for (int iy = 0; iy < met->ny; iy++)
10863 help[ARRAY_2D(iy, ix, met->nx)] = scl * var[ix][iy];
10864
10865 /* Write data... */
10866 NC_PUT_FLOAT(varname, help, 0);
10867
10868 /* Free... */
10869 free(help);
10870}
#define NC_PUT_FLOAT(varname, ptr, hyperslab)
Write a float array to a NetCDF file.
Definition: mptrac.h:1150

◆ write_met_nc_3d()

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

Writes a 3D meteorological variable to a NetCDF file.

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

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

Definition at line 10874 of file mptrac.c.

10879 {
10880
10881 int varid;
10882 size_t start[4], count[4];
10883
10884 /* Allocate... */
10885 float *help;
10886 ALLOC(help, float,
10887 EX * EY * EP);
10888
10889 /* Copy data... */
10890 for (int ix = 0; ix < met->nx; ix++)
10891 for (int iy = 0; iy < met->ny; iy++)
10892 for (int ip = 0; ip < met->np; ip++)
10893 help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)] = scl * var[ix][iy][ip];
10894
10895 /* Write data... */
10896 NC_PUT_FLOAT(varname, help, 0);
10897
10898 /* Free... */
10899 free(help);
10900}

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

10910 {
10911
10912 static FILE *out;
10913
10914 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
10915 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
10916
10917 static int nobs, *obscount, ip, okay;
10918
10919 /* Set timer... */
10920 SELECT_TIMER("WRITE_PROF", "OUTPUT", NVTX_WRITE);
10921
10922 /* Init... */
10923 if (t == ctl->t_start) {
10924
10925 /* Check quantity index for mass... */
10926 if (ctl->qnt_m < 0)
10927 ERRMSG("Need quantity mass!");
10928
10929 /* Check molar mass... */
10930 if (ctl->molmass <= 0)
10931 ERRMSG("Specify molar mass!");
10932
10933 /* Allocate... */
10934 ALLOC(lon, double,
10935 ctl->prof_nx);
10936 ALLOC(lat, double,
10937 ctl->prof_ny);
10938 ALLOC(area, double,
10939 ctl->prof_ny);
10940 ALLOC(z, double,
10941 ctl->prof_nz);
10942 ALLOC(press, double,
10943 ctl->prof_nz);
10944 ALLOC(rt, double,
10945 NOBS);
10946 ALLOC(rz, double,
10947 NOBS);
10948 ALLOC(rlon, double,
10949 NOBS);
10950 ALLOC(rlat, double,
10951 NOBS);
10952 ALLOC(robs, double,
10953 NOBS);
10954
10955 /* Read observation data... */
10956 read_obs(ctl->prof_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
10957
10958 /* Create new output file... */
10959 LOG(1, "Write profile data: %s", filename);
10960 if (!(out = fopen(filename, "w")))
10961 ERRMSG("Cannot create file!");
10962
10963 /* Write header... */
10964 fprintf(out,
10965 "# $1 = time [s]\n"
10966 "# $2 = altitude [km]\n"
10967 "# $3 = longitude [deg]\n"
10968 "# $4 = latitude [deg]\n"
10969 "# $5 = pressure [hPa]\n"
10970 "# $6 = temperature [K]\n"
10971 "# $7 = volume mixing ratio [ppv]\n"
10972 "# $8 = H2O volume mixing ratio [ppv]\n"
10973 "# $9 = O3 volume mixing ratio [ppv]\n"
10974 "# $10 = observed BT index [K]\n"
10975 "# $11 = number of observations\n");
10976
10977 /* Set grid box size... */
10978 dz = (ctl->prof_z1 - ctl->prof_z0) / ctl->prof_nz;
10979 dlon = (ctl->prof_lon1 - ctl->prof_lon0) / ctl->prof_nx;
10980 dlat = (ctl->prof_lat1 - ctl->prof_lat0) / ctl->prof_ny;
10981
10982 /* Set vertical coordinates... */
10983 for (int iz = 0; iz < ctl->prof_nz; iz++) {
10984 z[iz] = ctl->prof_z0 + dz * (iz + 0.5);
10985 press[iz] = P(z[iz]);
10986 }
10987
10988 /* Set horizontal coordinates... */
10989 for (int ix = 0; ix < ctl->prof_nx; ix++)
10990 lon[ix] = ctl->prof_lon0 + dlon * (ix + 0.5);
10991 for (int iy = 0; iy < ctl->prof_ny; iy++) {
10992 lat[iy] = ctl->prof_lat0 + dlat * (iy + 0.5);
10993 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
10994 }
10995 }
10996
10997 /* Set time interval... */
10998 const double t0 = t - 0.5 * ctl->dt_mod;
10999 const double t1 = t + 0.5 * ctl->dt_mod;
11000
11001 /* Allocate... */
11002 ALLOC(mass, double,
11003 ctl->prof_nx * ctl->prof_ny * ctl->prof_nz);
11004 ALLOC(obsmean, double,
11005 ctl->prof_nx * ctl->prof_ny);
11006 ALLOC(obscount, int,
11007 ctl->prof_nx * ctl->prof_ny);
11008
11009 /* Loop over observations... */
11010 for (int i = 0; i < nobs; i++) {
11011
11012 /* Check time... */
11013 if (rt[i] < t0)
11014 continue;
11015 else if (rt[i] >= t1)
11016 break;
11017
11018 /* Check observation data... */
11019 if (!isfinite(robs[i]))
11020 continue;
11021
11022 /* Calculate indices... */
11023 int ix = (int) ((rlon[i] - ctl->prof_lon0) / dlon);
11024 int iy = (int) ((rlat[i] - ctl->prof_lat0) / dlat);
11025
11026 /* Check indices... */
11027 if (ix < 0 || ix >= ctl->prof_nx || iy < 0 || iy >= ctl->prof_ny)
11028 continue;
11029
11030 /* Get mean observation index... */
11031 int idx = ARRAY_2D(ix, iy, ctl->prof_ny);
11032 obsmean[idx] += robs[i];
11033 obscount[idx]++;
11034 }
11035
11036 /* Analyze model data... */
11037 for (ip = 0; ip < atm->np; ip++) {
11038
11039 /* Check time... */
11040 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11041 continue;
11042
11043 /* Get indices... */
11044 int ix = (int) ((atm->lon[ip] - ctl->prof_lon0) / dlon);
11045 int iy = (int) ((atm->lat[ip] - ctl->prof_lat0) / dlat);
11046 int iz = (int) ((Z(atm->p[ip]) - ctl->prof_z0) / dz);
11047
11048 /* Check indices... */
11049 if (ix < 0 || ix >= ctl->prof_nx ||
11050 iy < 0 || iy >= ctl->prof_ny || iz < 0 || iz >= ctl->prof_nz)
11051 continue;
11052
11053 /* Get total mass in grid cell... */
11054 int idx = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
11055 mass[idx] += atm->q[ctl->qnt_m][ip];
11056 }
11057
11058 /* Extract profiles... */
11059 for (int ix = 0; ix < ctl->prof_nx; ix++)
11060 for (int iy = 0; iy < ctl->prof_ny; iy++) {
11061 int idx2 = ARRAY_2D(ix, iy, ctl->prof_ny);
11062 if (obscount[idx2] > 0) {
11063
11064 /* Check profile... */
11065 okay = 0;
11066 for (int iz = 0; iz < ctl->prof_nz; iz++) {
11067 int idx3 = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
11068 if (mass[idx3] > 0) {
11069 okay = 1;
11070 break;
11071 }
11072 }
11073 if (!okay)
11074 continue;
11075
11076 /* Write output... */
11077 fprintf(out, "\n");
11078
11079 /* Loop over altitudes... */
11080 for (int iz = 0; iz < ctl->prof_nz; iz++) {
11081
11082 /* Get temperature, water vapor, and ozone... */
11084 intpol_met_time_3d(met0, met0->t, met1, met1->t, t, press[iz],
11085 lon[ix], lat[iy], &temp, ci, cw, 1);
11086 intpol_met_time_3d(met0, met0->h2o, met1, met1->h2o, t, press[iz],
11087 lon[ix], lat[iy], &h2o, ci, cw, 0);
11088 intpol_met_time_3d(met0, met0->o3, met1, met1->o3, t, press[iz],
11089 lon[ix], lat[iy], &o3, ci, cw, 0);
11090
11091 /* Calculate volume mixing ratio... */
11092 const int idx3 = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
11093 vmr = MA / ctl->molmass * mass[idx3]
11094 / (RHO(press[iz], temp) * area[iy] * dz * 1e9);
11095
11096 /* Write output... */
11097 fprintf(out, "%.2f %g %g %g %g %g %g %g %g %g %d\n",
11098 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
11099 obsmean[idx2] / obscount[idx2], obscount[idx2]);
11100 }
11101 }
11102 }
11103
11104 /* Free... */
11105 free(mass);
11106 free(obsmean);
11107 free(obscount);
11108
11109 /* Finalize... */
11110 if (t == ctl->t_stop) {
11111
11112 /* Close output file... */
11113 fclose(out);
11114
11115 /* Free... */
11116 free(lon);
11117 free(lat);
11118 free(area);
11119 free(z);
11120 free(press);
11121 free(rt);
11122 free(rz);
11123 free(rlon);
11124 free(rlat);
11125 free(robs);
11126 }
11127}
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 11131 of file mptrac.c.

11137 {
11138
11139 static FILE *out;
11140
11141 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[EP],
11142 kw[EP];
11143
11144 static int nobs, nk;
11145
11146 /* Set timer... */
11147 SELECT_TIMER("WRITE_SAMPLE", "OUTPUT", NVTX_WRITE);
11148
11149 /* Init... */
11150 if (t == ctl->t_start) {
11151
11152 /* Allocate... */
11153 ALLOC(rt, double,
11154 NOBS);
11155 ALLOC(rz, double,
11156 NOBS);
11157 ALLOC(rlon, double,
11158 NOBS);
11159 ALLOC(rlat, double,
11160 NOBS);
11161 ALLOC(robs, double,
11162 NOBS);
11163
11164 /* Read observation data... */
11165 read_obs(ctl->sample_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
11166
11167 /* Read kernel data... */
11168 if (ctl->sample_kernel[0] != '-')
11169 read_kernel(ctl->sample_kernel, kz, kw, &nk);
11170
11171 /* Create output file... */
11172 LOG(1, "Write sample data: %s", filename);
11173 if (!(out = fopen(filename, "w")))
11174 ERRMSG("Cannot create file!");
11175
11176 /* Write header... */
11177 fprintf(out,
11178 "# $1 = time [s]\n"
11179 "# $2 = altitude [km]\n"
11180 "# $3 = longitude [deg]\n"
11181 "# $4 = latitude [deg]\n"
11182 "# $5 = surface area [km^2]\n"
11183 "# $6 = layer depth [km]\n"
11184 "# $7 = number of particles [1]\n"
11185 "# $8 = column density [kg/m^2]\n"
11186 "# $9 = volume mixing ratio [ppv]\n"
11187 "# $10 = observed BT index [K]\n\n");
11188
11189 /* Set latitude range, squared radius, and area... */
11190 dlat = DY2DEG(ctl->sample_dx);
11191 rmax2 = SQR(ctl->sample_dx);
11192 area = M_PI * rmax2;
11193 }
11194
11195 /* Set time interval for output... */
11196 const double t0 = t - 0.5 * ctl->dt_mod;
11197 const double t1 = t + 0.5 * ctl->dt_mod;
11198
11199 /* Loop over observations... */
11200 for (int i = 0; i < nobs; i++) {
11201
11202 /* Check time... */
11203 if (rt[i] < t0)
11204 continue;
11205 else if (rt[i] >= t1)
11206 break;
11207
11208 /* Calculate Cartesian coordinates... */
11209 double x0[3];
11210 geo2cart(0, rlon[i], rlat[i], x0);
11211
11212 /* Set pressure range... */
11213 const double rp = P(rz[i]);
11214 const double ptop = P(rz[i] + ctl->sample_dz);
11215 const double pbot = P(rz[i] - ctl->sample_dz);
11216
11217 /* Init... */
11218 double mass = 0;
11219 int np = 0;
11220
11221 /* Loop over air parcels... */
11222 //#pragma omp parallel for default(shared) reduction(+:mass,np)
11223 for (int ip = 0; ip < atm->np; ip++) {
11224
11225 /* Check time... */
11226 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11227 continue;
11228
11229 /* Check latitude... */
11230 if (fabs(rlat[i] - atm->lat[ip]) > dlat)
11231 continue;
11232
11233 /* Check horizontal distance... */
11234 double x1[3];
11235 geo2cart(0, atm->lon[ip], atm->lat[ip], x1);
11236 if (DIST2(x0, x1) > rmax2)
11237 continue;
11238
11239 /* Check pressure... */
11240 if (ctl->sample_dz > 0)
11241 if (atm->p[ip] > pbot || atm->p[ip] < ptop)
11242 continue;
11243
11244 /* Add mass... */
11245 if (ctl->qnt_m >= 0)
11246 mass +=
11247 kernel_weight(kz, kw, nk, atm->p[ip]) * atm->q[ctl->qnt_m][ip];
11248 np++;
11249 }
11250
11251 /* Calculate column density... */
11252 const double cd = mass / (1e6 * area);
11253
11254 /* Calculate volume mixing ratio... */
11255 double vmr = 0;
11256 if (ctl->molmass > 0 && ctl->sample_dz > 0) {
11257 if (mass > 0) {
11258
11259 /* Get temperature... */
11260 double temp;
11262 intpol_met_time_3d(met0, met0->t, met1, met1->t, rt[i], rp,
11263 rlon[i], rlat[i], &temp, ci, cw, 1);
11264
11265 /* Calculate volume mixing ratio... */
11266 vmr = MA / ctl->molmass * cd / (RHO(rp, temp) * ctl->sample_dz * 1e3);
11267 }
11268 } else
11269 vmr = NAN;
11270
11271 /* Write output... */
11272 fprintf(out, "%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
11273 rlon[i], rlat[i], area, ctl->sample_dz, np, cd, vmr, robs[i]);
11274 }
11275
11276 /* Finalize...... */
11277 if (t == ctl->t_stop) {
11278
11279 /* Close output file... */
11280 fclose(out);
11281
11282 /* Free... */
11283 free(rt);
11284 free(rz);
11285 free(rlon);
11286 free(rlat);
11287 free(robs);
11288 }
11289}
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 11293 of file mptrac.c.

11297 {
11298
11299 static FILE *out;
11300
11301 static double rmax2, x0[3], x1[3];
11302
11303 /* Set timer... */
11304 SELECT_TIMER("WRITE_STATION", "OUTPUT", NVTX_WRITE);
11305
11306 /* Init... */
11307 if (t == ctl->t_start) {
11308
11309 /* Write info... */
11310 LOG(1, "Write station data: %s", filename);
11311
11312 /* Create new file... */
11313 if (!(out = fopen(filename, "w")))
11314 ERRMSG("Cannot create file!");
11315
11316 /* Write header... */
11317 fprintf(out,
11318 "# $1 = time [s]\n"
11319 "# $2 = altitude [km]\n"
11320 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11321 for (int iq = 0; iq < ctl->nq; iq++)
11322 fprintf(out, "# $%i = %s [%s]\n", (iq + 5),
11323 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
11324 fprintf(out, "\n");
11325
11326 /* Set geolocation and search radius... */
11327 geo2cart(0, ctl->stat_lon, ctl->stat_lat, x0);
11328 rmax2 = SQR(ctl->stat_r);
11329 }
11330
11331 /* Set time interval for output... */
11332 const double t0 = t - 0.5 * ctl->dt_mod;
11333 const double t1 = t + 0.5 * ctl->dt_mod;
11334
11335 /* Loop over air parcels... */
11336 for (int ip = 0; ip < atm->np; ip++) {
11337
11338 /* Check time... */
11339 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11340 continue;
11341
11342 /* Check time range for station output... */
11343 if (atm->time[ip] < ctl->stat_t0 || atm->time[ip] > ctl->stat_t1)
11344 continue;
11345
11346 /* Check station flag... */
11347 if (ctl->qnt_stat >= 0)
11348 if ((int) atm->q[ctl->qnt_stat][ip])
11349 continue;
11350
11351 /* Get Cartesian coordinates... */
11352 geo2cart(0, atm->lon[ip], atm->lat[ip], x1);
11353
11354 /* Check horizontal distance... */
11355 if (DIST2(x0, x1) > rmax2)
11356 continue;
11357
11358 /* Set station flag... */
11359 if (ctl->qnt_stat >= 0)
11360 atm->q[ctl->qnt_stat][ip] = 1;
11361
11362 /* Write data... */
11363 fprintf(out, "%.2f %g %g %g",
11364 atm->time[ip], Z(atm->p[ip]), atm->lon[ip], atm->lat[ip]);
11365 for (int iq = 0; iq < ctl->nq; iq++) {
11366 fprintf(out, " ");
11367 fprintf(out, ctl->qnt_format[iq], atm->q[iq][ip]);
11368 }
11369 fprintf(out, "\n");
11370 }
11371
11372 /* Close file... */
11373 if (t == ctl->t_stop)
11374 fclose(out);
11375}
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 11379 of file mptrac.c.

11383 {
11384
11385 FILE *out;
11386
11387 /* Set timer... */
11388 SELECT_TIMER("WRITE_VTK", "OUTPUT", NVTX_WRITE);
11389
11390 /* Write info... */
11391 LOG(1, "Write VTK data: %s", filename);
11392
11393 /* Set time interval for output... */
11394 const double t0 = t - 0.5 * ctl->dt_mod;
11395 const double t1 = t + 0.5 * ctl->dt_mod;
11396
11397 /* Create file... */
11398 if (!(out = fopen(filename, "w")))
11399 ERRMSG("Cannot create file!");
11400
11401 /* Count data points... */
11402 int np = 0;
11403 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
11404 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11405 continue;
11406 np++;
11407 }
11408
11409 /* Write header... */
11410 fprintf(out,
11411 "# vtk DataFile Version 3.0\n"
11412 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
11413
11414 /* Write point coordinates... */
11415 fprintf(out, "POINTS %d float\n", np);
11416 if (ctl->vtk_sphere) {
11417 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
11418 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11419 continue;
11420 const double radius = (RE + Z(atm->p[ip]) * ctl->vtk_scale
11421 + ctl->vtk_offset) / RE;
11422 const double coslat = cos(DEG2RAD(atm->lat[ip]));
11423 const double x = radius * coslat * cos(DEG2RAD(atm->lon[ip]));
11424 const double y = radius * coslat * sin(DEG2RAD(atm->lon[ip]));
11425 const double z = radius * sin(DEG2RAD(atm->lat[ip]));
11426 fprintf(out, "%g %g %g\n", x, y, z);
11427 }
11428 } else
11429 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
11430 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11431 continue;
11432 fprintf(out, "%g %g %g\n", atm->lon[ip], atm->lat[ip],
11433 Z(atm->p[ip]) * ctl->vtk_scale + ctl->vtk_offset);
11434 }
11435
11436 /* Write point data... */
11437 fprintf(out, "POINT_DATA %d\n", np);
11438 for (int iq = 0; iq < ctl->nq; iq++) {
11439 fprintf(out, "SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
11440 ctl->qnt_name[iq]);
11441 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
11442 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11443 continue;
11444 fprintf(out, "%g\n", atm->q[iq][ip]);
11445 }
11446 }
11447
11448 /* Close file... */
11449 fclose(out);
11450}