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  particle_t
 Particle data. More...
 
struct  mpi_info_t
 MPI information 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 DD_NPOLE   -2
 Constants indicating the North pole [-]. More...
 
#define DD_SPOLE   -3
 Constants indicating the South pole [-]. More...
 
#define EP   140
 Maximum number of pressure levels for meteo data. More...
 
#define EX   1444
 Maximum number of longitudes for meteo data. More...
 
#define EY   724
 Maximum number of latitudes for meteo data. More...
 
#define EP_GLOB   150
 Maximum number of pressure levels for meteo data. More...
 
#define EX_GLOB   1202
 Maximum number of global longitudes for meteo data. More...
 
#define EY_GLOB   602
 Maximum number of global latitudes for meteo data. More...
 
#define LEN   5000
 Maximum length of ASCII data lines. More...
 
#define METVAR   13
 Number of 3-D meteorological variables. 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 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 DD_NPART   100000
 Maximum number of particles to send and recieve. More...
 
#define DD_NNMAX   26
 Maximum number of neighbours to communicate with. More...
 
#define ALLOC(ptr, type, n)
 Allocate memory for a pointer with error handling. More...
 
#define ARRAY_2D(ix, iy, ny)    ((ix) * (ny) + (iy))
 Macro for computing the linear index of a 2D array element. More...
 
#define ARRAY_3D(ix, iy, ny, iz, nz)    (((ix)*(ny) + (iy)) * (nz) + (iz))
 Compute the linear index of a 3D array element. More...
 
#define ARRHENIUS(a, b, t)    ((a) * exp( -(b) / (t)))
 Calculate the Arrhenius rate constant. More...
 
#define DEG2DX(dlon, lat)    (RE * DEG2RAD(dlon) * cos(DEG2RAD(lat)))
 Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude. More...
 
#define DEG2DY(dlat)    (RE * DEG2RAD(dlat))
 Convert a latitude difference to a distance in the y-direction (north-south). More...
 
#define DEG2RAD(deg)    ((deg) * (M_PI / 180.0))
 Converts degrees to radians. More...
 
#define DP2DZ(dp, p)    (- (dp) * H0 / (p))
 Convert a pressure difference to a height difference in the vertical direction. More...
 
#define DX2DEG(dx, lat)
 Convert a distance in kilometers to degrees longitude at a given latitude. More...
 
#define DY2DEG(dy)    ((dy) * 180. / (M_PI * RE))
 Convert a distance in kilometers to degrees latitude. More...
 
#define DZ2DP(dz, p)    (-(dz) * (p) / H0)
 Convert a change in altitude to a change in pressure. More...
 
#define DIST(a, b)    sqrt(DIST2(a, b))
 Calculate the distance between two points in Cartesian coordinates. More...
 
#define DIST2(a, b)    ((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])+(a[2]-b[2])*(a[2]-b[2]))
 Calculate the squared Euclidean distance between two points in Cartesian coordinates. More...
 
#define DOTP(a, b)    (a[0]*b[0]+a[1]*b[1]+a[2]*b[2])
 Calculate the dot product of two vectors. More...
 
#define ECC(cmd)
 Execute a ECCODES command and check for errors. More...
 
#define ECC_READ_2D(variable, target, scaling_factor, found_flag)
 Writes 2-D data from a grib message into the met struct. More...
 
#define ECC_READ_3D(variable, level, target, scaling_factor, found_flag)
 Writes 3D data from a grib message into the met struct. More...
 
#define ECC(cmd)
 Execute a ECCODES command and check for errors. More...
 
#define ECC_READ_2D(variable, target, scaling_factor, found_flag)
 Writes 2-D data from a grib message into the met struct. More...
 
#define ECC_READ_3D(variable, level, target, scaling_factor, found_flag)
 Writes 3D data from a grib message into the met struct. More...
 
#define FMOD(x, y)    ((x) - (int) ((x) / (y)) * (y))
 Calculate the floating-point remainder of dividing x by y. More...
 
#define FREAD(ptr, type, size, in)
 Read data from a file stream and store it in memory. More...
 
#define FWRITE(ptr, type, size, out)
 Write data from memory to a file stream. More...
 
#define INTPOL_INIT    double cw[4] = {0.0, 0.0, 0.0, 0.0}; int ci[3] = {0, 0, 0};
 Initialize arrays for interpolation. More...
 
#define INTPOL_2D(var, init)
 Perform 2D interpolation for a meteorological variable. More...
 
#define INTPOL_3D(var, init)
 Perform 3D interpolation for a meteorological variable. More...
 
#define INTPOL_SPACE_ALL(p, lon, lat)
 Interpolate multiple meteorological variables in space. More...
 
#define INTPOL_TIME_ALL(time, p, lon, lat)
 Interpolate multiple meteorological variables in time. More...
 
#define LAPSE(p1, t1, p2, t2)
 Calculate lapse rate. More...
 
#define LIN(x0, y0, x1, y1, x)    ((y0)+((y1)-(y0))/((x1)-(x0))*((x)-(x0)))
 Linear interpolation. More...
 
#define MAX(a, b)    (((a)>(b))?(a):(b))
 Macro to determine the maximum of two values. More...
 
#define MET_HEADER
 Write header for meteorological data file. More...
 
#define MIN(a, b)    (((a)<(b))?(a):(b))
 Macro to determine the minimum of two values. More...
 
#define MOLEC_DENS(p, t)    (AVO * 1e-6 * ((p) * 100) / (RI * (t)))
 Calculate the density of a gas molecule. More...
 
#define NC(cmd)
 Execute a NetCDF command and check for errors. More...
 
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units, level, quant)
 Define a NetCDF variable with attributes. More...
 
#define NC_GET_DOUBLE(varname, ptr, force)
 Retrieve a double-precision variable from a NetCDF file. More...
 
#define NC_INQ_DIM(dimname, ptr, min, max)
 Inquire the length of a dimension in a NetCDF file. More...
 
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
 Write double precision data to a NetCDF variable. More...
 
#define NC_PUT_FLOAT(varname, ptr, hyperslab)
 Write a float array to a NetCDF file. More...
 
#define NC_PUT_INT(varname, ptr, hyperslab)
 Write integer data to a NetCDF variable. More...
 
#define NC_PUT_ATT(varname, attname, text)
 Add a text attribute to a NetCDF variable. More...
 
#define NC_PUT_ATT_GLOBAL(attname, text)    NC(nc_put_att_text(ncid, NC_GLOBAL, attname, strnlen(text, LEN), text));
 Add a global text attribute to a NetCDF file. More...
 
#define NN(x0, y0, x1, y1, x)    (fabs((x) - (x0)) <= fabs((x) - (x1)) ? (y0) : (y1))
 Perform nearest-neighbor interpolation. More...
 
#define NORM(a)    sqrt(DOTP(a, a))
 Compute the norm (magnitude) of a vector. More...
 
#define PARTICLE_LOOP(ip0, ip1, check_dt, ...)
 Loop over particle indices with OpenACC acceleration. More...
 
#define P(z)    (P0 * exp(-(z) / H0))
 Compute pressure at given altitude. More...
 
#define PSAT(t)    (6.112 * exp(17.62 * ((t) - T0) / (243.12 + (t) - T0)))
 Compute saturation pressure over water. More...
 
#define PSICE(t)    (6.112 * exp(22.46 * ((t) - T0) / (272.62 + (t) - T0)))
 Compute saturation pressure over ice (WMO, 2018). More...
 
#define PW(p, h2o)    ((p) * MAX((h2o), 0.1e-6) / (1. + (1. - EPS) * MAX((h2o), 0.1e-6)))
 Calculate partial water vapor pressure. More...
 
#define RAD2DEG(rad)    ((rad) * (180.0 / M_PI))
 Converts radians to degrees. More...
 
#define RH(p, t, h2o)    (PW(p, h2o) / PSAT(t) * 100.)
 Compute relative humidity over water. More...
 
#define RHICE(p, t, h2o)    (PW(p, h2o) / PSICE(t) * 100.)
 Compute relative humidity over ice. More...
 
#define RHO(p, t)    (100. * (p) / (RA * (t)))
 Compute density of air. More...
 
#define SET_ATM(qnt, val)
 Set atmospheric quantity value. More...
 
#define SET_QNT(qnt, name, longname, unit)
 Set atmospheric quantity index. More...
 
#define SH(h2o)    (EPS * MAX((h2o), 0.1e-6))
 Compute specific humidity from water vapor volume mixing ratio. More...
 
#define SQR(x)    ((x)*(x))
 Compute the square of a value. More...
 
#define SWAP(x, y, type)    do {type tmp = x; x = y; y = tmp;} while(0);
 Swap two values. More...
 
#define TDEW(p, h2o)
 Calculate dew point temperature. More...
 
#define TICE(p, h2o)
 Calculate frost point temperature (WMO, 2018). More...
 
#define THETA(p, t)    ((t) * pow(1000. / (p), 0.286))
 Compute potential temperature. More...
 
#define THETAVIRT(p, t, h2o)    (TVIRT(THETA((p), (t)), MAX((h2o), 0.1e-6)))
 Compute virtual potential temperature. More...
 
#define TOK(line, tok, format, var)
 Get string tokens. More...
 
#define TVIRT(t, h2o)    ((t) * (1. + (1. - EPS) * MAX((h2o), 0.1e-6)))
 Compute virtual temperature. More...
 
#define Z(p)    (H0 * log(P0 / (p)))
 Convert pressure to altitude. More...
 
#define ZDIFF(lnp0, t0, h2o0, lnp1, t1, h2o1)
 Calculate geopotential height difference. More...
 
#define ZETA(ps, p, t)
 Computes the value of the zeta vertical coordinate. More...
 
#define LOGLEV   2
 Level of log messages (0=none, 1=basic, 2=detailed, 3=debug). More...
 
#define LOG(level, ...)
 Print a log message with a specified logging level. More...
 
#define WARN(...)
 Print a warning message with contextual information. More...
 
#define ERRMSG(...)
 Print an error message with contextual information and terminate the program. More...
 
#define PRINT(format, var)
 Print the value of a variable with contextual information. More...
 
#define NTIMER   100
 Maximum number of timers. More...
 
#define PRINT_TIMERS    timer("END", "END", 1);
 Print the current state of all timers. More...
 
#define SELECT_TIMER(id, group, color)
 Select and start a timer with specific attributes. More...
 
#define START_TIMERS    NVTX_PUSH("START", NVTX_CPU);
 Starts a timer for tracking. More...
 
#define STOP_TIMERS    NVTX_POP;
 Stop the current timer. More...
 
#define NVTX_PUSH(range_title, range_color)   {}
 
#define NVTX_POP   {}
 

Functions

void thrustSortWrapper (double *__restrict__ c, int n, int *__restrict__ index)
 Wrapper to Thrust sorting function. More...
 
void broadcast_large_data (void *data, size_t N)
 Broadcasts large data across all processes in an MPI communicator. More...
 
void cart2geo (const double *x, double *z, double *lon, double *lat)
 Converts Cartesian coordinates to geographic coordinates. More...
 
double clim_oh (const ctl_t *ctl, const clim_t *clim, const double t, const double lon, const double lat, const double p)
 Calculates the hydroxyl radical (OH) concentration from climatology data, with an optional diurnal correction based on solar zenith angle. More...
 
void clim_oh_diurnal_correction (const ctl_t *ctl, clim_t *clim)
 Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data. More...
 
double clim_photo (const double rate[CP][CSZA][CO3], const clim_photo_t *photo, const double p, const double sza, const double o3c)
 Calculates the photolysis rate for a given set of atmospheric conditions. More...
 
double clim_tropo (const clim_t *clim, const double t, const double lat)
 Calculates the tropopause pressure based on climatological data. More...
 
void clim_tropo_init (clim_t *clim)
 Initializes the tropopause data in the climatology structure. More...
 
double clim_ts (const clim_ts_t *ts, const double t)
 Interpolates a time series of climatological variables. More...
 
double clim_zm (const clim_zm_t *zm, const double t, const double lat, const double p)
 Interpolates monthly mean zonal mean climatological variables. More...
 
void compress_cms (const ctl_t *ctl, const char *varname, float *array, const size_t nx, const size_t ny, const size_t np, const int decompress, FILE *inout)
 Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm. More...
 
void compress_pck (const char *varname, float *array, const size_t nxy, const size_t nz, const int decompress, FILE *inout)
 Compresses or decompresses a 3D array of floats. More...
 
void compress_zfp (const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
 Compresses or decompresses a 3D array of floats using the ZFP library. More...
 
void compress_zstd (const char *varname, float *array, const size_t n, const int decompress, const int level, FILE *inout)
 Compresses or decompresses a float array using Zstandard (ZSTD). More...
 
void day2doy (const int year, const int mon, const int day, int *doy)
 Get day of year from date. More...
 
void doy2day (const int year, const int doy, int *mon, int *day)
 Converts a given day of the year (DOY) to a date (month and day). More...
 
void fft_help (double *fcReal, double *fcImag, const int n)
 Computes the Fast Fourier Transform (FFT) of a complex sequence. More...
 
void geo2cart (const double z, const double lon, const double lat, double *x)
 Converts geographic coordinates (longitude, latitude, altitude) to Cartesian coordinates. More...
 
void get_met_help (const ctl_t *ctl, const double t, const int direct, const char *metbase, const double dt_met, char *filename)
 Generates a formatted filename for meteorological data files based on the input parameters. More...
 
void get_met_replace (char *orig, char *search, char *repl)
 Replaces occurrences of a substring in a string with another substring. More...
 
void get_tropo (const int met_tropo, ctl_t *ctl, clim_t *clim, met_t *met, const double *lons, const int nx, const double *lats, const int ny, double *pt, double *zt, double *tt, double *qt, double *o3t, double *ps, double *zs)
 Calculate tropopause data. More...
 
void intpol_check_lon_lat (const double *lons, const int nlon, const double *lats, const int nlat, const double lon, const double lat, double *lon2, double *lat2)
 Adjusts longitude and latitude to ensure they fall within valid bounds. More...
 
void intpol_met_4d_coord (const met_t *met0, float height0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float height1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double height, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
 Interpolates meteorological variables to a given position and time. More...
 
void intpol_met_space_3d (const met_t *met, float array[EX][EY][EP], const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
 Interpolates meteorological variables in 3D space. More...
 
void intpol_met_space_3d_ml (const met_t *met, float zs[EX][EY][EP], float vals[EX][EY][EP], const double z, const double lon, const double lat, double *val)
 Interpolates meteorological data in 3D space. More...
 
void intpol_met_space_2d (const met_t *met, float array[EX][EY], const double lon, const double lat, double *var, int *ci, double *cw, const int init)
 Interpolates meteorological variables in 2D space. More...
 
void intpol_met_time_3d (const met_t *met0, float array0[EX][EY][EP], const met_t *met1, float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
 Interpolates meteorological data in 3D space and time. More...
 
void intpol_met_time_3d_ml (const met_t *met0, float zs0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float zs1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var)
 Interpolates meteorological data in both space and time. More...
 
void intpol_met_time_2d (const met_t *met0, float array0[EX][EY], const met_t *met1, float array1[EX][EY], const double ts, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
 Interpolates meteorological data in 2D space and time. More...
 
void intpol_tropo_3d (const double time0, float array0[EX][EY], const double time1, float array1[EX][EY], const double lons[EX], const double lats[EY], const int nlon, const int nlat, const double time, const double lon, const double lat, const int method, double *var, double *sigma)
 Interpolates tropopause data in 3D (latitude, longitude, and time). More...
 
void jsec2time (const double jsec, int *year, int *mon, int *day, int *hour, int *min, int *sec, double *remain)
 Converts Julian seconds to calendar date and time components. More...
 
double kernel_weight (const double kz[EP], const double kw[EP], const int nk, const double p)
 Calculates the kernel weight based on altitude and given kernel data. More...
 
double lapse_rate (const double t, const double h2o)
 Calculates the moist adiabatic lapse rate in Kelvin per kilometer. More...
 
void level_definitions (ctl_t *ctl)
 Defines pressure levels for meteorological data. More...
 
int locate_irr (const double *xx, const int n, const double x)
 Locate the index of the interval containing a given value in a sorted array. More...
 
int locate_irr_float (const float *xx, const int n, const double x, const int ig)
 Locate the index of the interval containing a given value in an irregularly spaced array. More...
 
int locate_reg (const double *xx, const int n, const double x)
 Locate the index of the interval containing a given value in a regular grid. More...
 
void locate_vert (float profiles[EX][EY][EP], const int np, const int lon_ap_ind, const int lat_ap_ind, const double alt_ap, int *ind)
 Locate the four vertical indizes of a box for a given height value. More...
 
void module_advect (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Advances particle positions using different advection schemes. More...
 
void module_advect_init (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Initializes the advection module by setting up pressure fields. More...
 
void module_bound_cond (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Apply boundary conditions to particles based on meteorological and climatological data. More...
 
void module_chem_grid (const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double t)
 Computes gridded chemical tracer concentrations (volume mixing ratio) from individual air parcel mass data and assigns them back to the parcels. 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, const int use_ensemble)
 Perform subgrid-scale interparcel mixing of a given quantity. More...
 
void module_oh_chem (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Perform hydroxyl chemistry calculations for atmospheric particles. More...
 
void module_position (const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Update the positions and pressure levels of atmospheric particles. More...
 
void module_rng_init (const int ntask)
 Initialize random number generators for parallel tasks. More...
 
void module_rng (const ctl_t *ctl, double *rs, const size_t n, const int method)
 Generate random numbers using various methods and distributions. More...
 
void module_sedi (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Simulate sedimentation of particles in the atmosphere. More...
 
void module_sort (const ctl_t *ctl, met_t *met0, atm_t *atm)
 Sort particles according to box index. More...
 
void module_sort_help (double *a, const int *p, const int np)
 Reorder an array based on a given permutation. More...
 
void module_timesteps (const ctl_t *ctl, cache_t *cache, met_t *met0, atm_t *atm, const double t)
 Calculate time steps for air parcels based on specified conditions. More...
 
void module_timesteps_init (ctl_t *ctl, const atm_t *atm)
 Initialize start time and time interval for time-stepping. More...
 
void module_tracer_chem (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Simulate chemical reactions involving long-lived atmospheric tracers. More...
 
void module_wet_depo (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Perform wet deposition calculations for air parcels. More...
 
void mptrac_alloc (ctl_t **ctl, cache_t **cache, clim_t **clim, met_t **met0, met_t **met1, atm_t **atm)
 Allocates and initializes memory resources for MPTRAC. More...
 
void mptrac_free (ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Frees memory resources allocated for MPTRAC. More...
 
void mptrac_get_met (ctl_t *ctl, clim_t *clim, const double t, met_t **met0, met_t **met1)
 Retrieves meteorological data for the specified time. More...
 
void mptrac_init (ctl_t *ctl, cache_t *cache, clim_t *clim, atm_t *atm, const int ntask)
 Initializes the MPTRAC model and its associated components. More...
 
int mptrac_read_atm (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads air parcel data from a specified file into the given atmospheric structure. More...
 
void mptrac_read_clim (const ctl_t *ctl, clim_t *clim)
 Reads various climatological data and populates the given climatology structure. More...
 
void mptrac_read_ctl (const char *filename, int argc, char *argv[], ctl_t *ctl)
 Reads control parameters from a configuration file and populates the given structure. More...
 
int mptrac_read_met (const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met)
 Reads meteorological data from a file, supporting multiple formats and MPI broadcasting. More...
 
void mptrac_run_timestep (ctl_t *ctl, cache_t *cache, clim_t *clim, met_t **met0, met_t **met1, atm_t *atm, double t)
 Executes a single timestep of the MPTRAC model simulation. More...
 
void mptrac_write_atm (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes air parcel data to a file in various formats. More...
 
void mptrac_write_met (const char *filename, const ctl_t *ctl, met_t *met)
 Writes meteorological data to a file, supporting multiple formats and compression options. More...
 
void mptrac_write_output (const char *dirname, const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double t)
 Writes various types of output data to files in a specified directory. More...
 
void mptrac_update_device (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
 Updates device memory for specified data structures. More...
 
void mptrac_update_host (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
 Updates host memory for specified data structures. More...
 
double nat_temperature (const double p, const double h2o, const double hno3)
 Calculates the nitric acid trihydrate (NAT) temperature. More...
 
double pbl_weight (const ctl_t *ctl, const atm_t *atm, const int ip, const double pbl, const double ps)
 Computes a weighting factor based on planetary boundary layer pressure. More...
 
int read_atm_asc (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads air parcel data from an ASCII file and populates the given atmospheric structure. More...
 
int read_atm_bin (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads air parcel data from a binary file and populates the given atmospheric structure. More...
 
int read_atm_clams (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads atmospheric data from a CLAMS NetCDF file. More...
 
int read_atm_nc (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads air parcel data from a generic netCDF file and populates the given atmospheric structure. More...
 
void read_clim_photo (const char *filename, clim_photo_t *photo)
 Reads photolysis rates from a NetCDF file and populates the given photolysis structure. More...
 
void read_clim_photo_help (const int ncid, const char *varname, const clim_photo_t *photo, double var[CP][CSZA][CO3])
 Reads a 3D climatological photochemistry variable from a NetCDF file. More...
 
int read_clim_ts (const char *filename, clim_ts_t *ts)
 Reads a climatological time series from a file and populates the given time series structure. More...
 
void read_clim_zm (const char *filename, const char *varname, clim_zm_t *zm)
 Reads zonally averaged climatological data from a netCDF file and populates the given structure. More...
 
void read_kernel (const char *filename, double kz[EP], double kw[EP], int *nk)
 Reads kernel function data from a file and populates the provided arrays. More...
 
int read_met_bin (const char *filename, const ctl_t *ctl, met_t *met)
 Reads meteorological data from a binary file. More...
 
void read_met_bin_2d (FILE *in, const met_t *met, float var[EX][EY], const char *varname)
 Reads a 2-dimensional meteorological variable from a binary file and stores it in the provided array. More...
 
void read_met_bin_3d (FILE *in, const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname, const float bound_min, const float bound_max)
 Reads 3D meteorological data from a binary file, potentially using different compression methods. More...
 
void read_met_cape (const ctl_t *ctl, const clim_t *clim, met_t *met)
 Calculates Convective Available Potential Energy (CAPE) for each grid point. More...
 
void read_met_cloud (met_t *met)
 Calculates cloud-related variables for each grid point. More...
 
void read_met_detrend (const ctl_t *ctl, met_t *met)
 Detrends meteorological data. More...
 
void read_met_extrapolate (met_t *met)
 Extrapolates meteorological data. More...
 
void read_met_geopot (const ctl_t *ctl, met_t *met)
 Calculates geopotential heights from meteorological data. More...
 
int read_met_grib (const char *filename, const ctl_t *ctl, met_t *met)
 Reads meteorological data from a grib file and processes it. More...
 
void read_met_ml2pl (const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname)
 Reads global meteorological information from a grib file. More...
 
void read_met_monotonize (const ctl_t *ctl, met_t *met)
 Makes zeta and pressure profiles monotone. More...
 
int read_met_nc (const char *filename, const ctl_t *ctl, met_t *met)
 Reads meteorological data from a NetCDF file and processes it. More...
 
void read_met_nc_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_nc_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_nc_grid (const char *filename, const int ncid, const ctl_t *ctl, met_t *met)
 Reads meteorological grid information from a NetCDF file. More...
 
int read_met_nc_dd (const char *filename, const ctl_t *ctl, met_t *met)
 Reads meteorological data from a NetCDF file and processes it. More...
 
void read_met_nc_grid_dd (const char *filename, const int ncid, const ctl_t *ctl, met_t *met)
 Reads meteorological grid data from NetCDF files with domain decomposition. More...
 
void read_met_nc_levels_dd (const int ncid, const ctl_t *ctl, met_t *met)
 Reads and processes meteorological level data from NetCDF files with domain decomposition. More...
 
void read_met_nc_surface_dd (const int ncid, const ctl_t *ctl, met_t *met)
 Reads and processes surface meteorological data from NetCDF files with domain decomposition. 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_2d_dd (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...
 
int read_met_nc_3d_dd (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_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_csi_ens (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes ensemble-based Critical Success Index (CSI) and other verification statistics to an output file. More...
 
void write_ens (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes ensemble data to a file. More...
 
void write_grid (const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
 Writes grid data to a file in ASCII or netCDF format. More...
 
void write_grid_asc (const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
 Writes grid data to an ASCII file. More...
 
void write_grid_nc (const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
 Writes grid data to a NetCDF file. More...
 
void write_met_bin (const char *filename, const ctl_t *ctl, met_t *met)
 Writes meteorological data in binary format to a specified file. More...
 
void write_met_bin_2d (FILE *out, met_t *met, float var[EX][EY], const char *varname)
 Writes a 2-dimensional meteorological variable to a binary file. More...
 
void write_met_bin_3d (FILE *out, const ctl_t *ctl, met_t *met, float var[EX][EY][EP], const char *varname, const int precision, const double tolerance)
 Writes a 3-dimensional meteorological variable to a binary file. More...
 
void write_met_nc (const char *filename, const ctl_t *ctl, met_t *met)
 Writes meteorological data to a NetCDF file. More...
 
void write_met_nc_2d (const int ncid, const char *varname, met_t *met, float var[EX][EY], const float scl)
 Writes a 2D meteorological variable to a NetCDF file. More...
 
void write_met_nc_3d (const int ncid, const char *varname, met_t *met, float var[EX][EY][EP], const float scl)
 Writes a 3D meteorological variable to a NetCDF file. More...
 
void write_prof (const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
 Writes profile data to a specified file. More...
 
void write_sample (const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
 Writes sample data to a specified file. More...
 
void write_station (const char *filename, const ctl_t *ctl, atm_t *atm, const double t)
 Writes station data to a specified file. More...
 
void write_vtk (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes VTK (Visualization Toolkit) data to a specified file. More...
 
void dd_atm2particles (atm_t *atm, particle_t *particles, ctl_t *ctl, int *nparticles, cache_t *cache, int rank)
 Converts atmospheric data to particle data. More...
 
void dd_particles2atm (atm_t *atm, particle_t *particles, ctl_t *ctl, int *nparticles, cache_t *cache)
 Converts particle data to atmospheric data. 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 184 of file mptrac.h.

◆ CPD

#define CPD   1003.5

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

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

◆ G0

#define G0   9.80665

Standard gravity [m/s^2].

Definition at line 199 of file mptrac.h.

◆ H0

#define H0   7.0

Scale height [km].

Definition at line 204 of file mptrac.h.

◆ LV

#define LV   2501000.

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

Definition at line 209 of file mptrac.h.

◆ KARMAN

#define KARMAN   0.40

Karman's constant.

Definition at line 214 of file mptrac.h.

◆ KB

#define KB   1.3806504e-23

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

Definition at line 219 of file mptrac.h.

◆ MA

#define MA   28.9644

Molar mass of dry air [g/mol].

Definition at line 224 of file mptrac.h.

◆ MH2O

#define MH2O   18.01528

Molar mass of water vapor [g/mol].

Definition at line 229 of file mptrac.h.

◆ MO3

#define MO3   48.00

Molar mass of ozone [g/mol].

Definition at line 234 of file mptrac.h.

◆ P0

#define P0   1013.25

Standard pressure [hPa].

Definition at line 239 of file mptrac.h.

◆ RA

#define RA   (1e3 * RI / MA)

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

Definition at line 244 of file mptrac.h.

◆ RE

#define RE   6367.421

Mean radius of Earth [km].

Definition at line 249 of file mptrac.h.

◆ RI

#define RI   8.3144598

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

Definition at line 254 of file mptrac.h.

◆ T0

#define T0   273.15

Standard temperature [K].

Definition at line 259 of file mptrac.h.

◆ DD_NPOLE

#define DD_NPOLE   -2

Constants indicating the North pole [-].

Definition at line 264 of file mptrac.h.

◆ DD_SPOLE

#define DD_SPOLE   -3

Constants indicating the South pole [-].

Definition at line 270 of file mptrac.h.

◆ EP

#define EP   140

Maximum number of pressure levels for meteo data.

Definition at line 279 of file mptrac.h.

◆ EX

#define EX   1444

Maximum number of longitudes for meteo data.

Definition at line 284 of file mptrac.h.

◆ EY

#define EY   724

Maximum number of latitudes for meteo data.

Definition at line 289 of file mptrac.h.

◆ EP_GLOB

#define EP_GLOB   150

Maximum number of pressure levels for meteo data.

Definition at line 294 of file mptrac.h.

◆ EX_GLOB

#define EX_GLOB   1202

Maximum number of global longitudes for meteo data.

Definition at line 299 of file mptrac.h.

◆ EY_GLOB

#define EY_GLOB   602

Maximum number of global latitudes for meteo data.

Definition at line 304 of file mptrac.h.

◆ LEN

#define LEN   5000

Maximum length of ASCII data lines.

Definition at line 309 of file mptrac.h.

◆ METVAR

#define METVAR   13

Number of 3-D meteorological variables.

Definition at line 314 of file mptrac.h.

◆ NP

#define NP   10000000

Maximum number of atmospheric data points.

Definition at line 319 of file mptrac.h.

◆ NQ

#define NQ   15

Maximum number of quantities per data point.

Definition at line 324 of file mptrac.h.

◆ NCSI

#define NCSI   1000000

Maximum number of data points for CSI calculation.

Definition at line 329 of file mptrac.h.

◆ NENS

#define NENS   2000

Maximum number of data points for ensemble analysis.

Definition at line 334 of file mptrac.h.

◆ NOBS

#define NOBS   10000000

Maximum number of observation data points.

Definition at line 339 of file mptrac.h.

◆ NTHREADS

#define NTHREADS   512

Maximum number of OpenMP threads.

Definition at line 344 of file mptrac.h.

◆ CY

#define CY   250

Maximum number of latitudes for climatological data.

Definition at line 349 of file mptrac.h.

◆ CO3

#define CO3   30

Maximum number of total column ozone data for climatological data.

Definition at line 354 of file mptrac.h.

◆ CP

#define CP   70

Maximum number of pressure levels for climatological data.

Definition at line 359 of file mptrac.h.

◆ CSZA

#define CSZA   50

Maximum number of solar zenith angles for climatological data.

Definition at line 364 of file mptrac.h.

◆ CT

#define CT   12

Maximum number of time steps for climatological data.

Definition at line 369 of file mptrac.h.

◆ CTS

#define CTS   1000

Maximum number of data points of climatological time series.

Definition at line 374 of file mptrac.h.

◆ DD_NPART

#define DD_NPART   100000

Maximum number of particles to send and recieve.

Definition at line 379 of file mptrac.h.

◆ DD_NNMAX

#define DD_NNMAX   26

Maximum number of neighbours to communicate with.

Definition at line 384 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 417 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 440 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 459 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 484 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 508 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 529 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 546 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 571 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:249
#define DEG2RAD(deg)
Converts degrees to radians.
Definition: mptrac.h:546

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 593 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 611 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 630 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 646 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 662 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 678 of file mptrac.h.

◆ ECC [1/2]

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

Execute a ECCODES command and check for errors.

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

Parameters
cmdECCODES command to execute.
Author
Nils Nobre Wittwer

Definition at line 757 of file mptrac.h.

◆ ECC_READ_2D [1/2]

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

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

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

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

Definition at line 776 of file mptrac.h.

◆ ECC_READ_3D [1/2]

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

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

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

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

Definition at line 800 of file mptrac.h.

◆ ECC [2/2]

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

Execute a ECCODES command and check for errors.

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

Parameters
cmdECCODES command to execute.
Author
Nils Nobre Wittwer

Definition at line 757 of file mptrac.h.

◆ ECC_READ_2D [2/2]

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

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

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

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

Definition at line 776 of file mptrac.h.

◆ ECC_READ_3D [2/2]

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

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

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

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

Definition at line 800 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 827 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 845 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 865 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 880 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:1580

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 894 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:1526

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 911 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 930 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 984 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:244
#define G0
Standard gravity [m/s^2].
Definition: mptrac.h:199

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 1038 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 1057 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 1084 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 1098 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 1185 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 1200 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 1214 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:309

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 1243 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:2069

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 1273 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 1301 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 1324 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 1348 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 1371 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 1393 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 1410 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 1430 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 1445 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 1472 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 1502 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 1526 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 1550 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 1577 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 1594 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 1624 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 1654 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 1679 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 1698 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 1721 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 1742 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 1755 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 1769 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:1577
#define T0
Standard temperature [K].
Definition: mptrac.h:259

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 1793 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 1818 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 1842 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 1871 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:2102

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 1892 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 1917 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 1939 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:1917
#define MA
Molar mass of dry air [g/mol].
Definition: mptrac.h:224
#define RI
Ideal gas constant [J/(mol K)].
Definition: mptrac.h:254

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 1970 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:1842

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

◆ LOGLEV

#define LOGLEV   2

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

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

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 2032 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 2069 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 2102 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 2137 of file mptrac.h.

◆ NTIMER

#define NTIMER   100

Maximum number of timers.

Definition at line 2146 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 2161 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 2182 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 2201 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 2216 of file mptrac.h.

◆ NVTX_PUSH

#define NVTX_PUSH (   range_title,
  range_color 
)    {}

Definition at line 2308 of file mptrac.h.

◆ NVTX_POP

#define NVTX_POP   {}

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

◆ 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:10668
clim_zm_t oh
OH zonal means.
Definition: mptrac.h:3613
double oh_chem_beta
Beta parameter for diurnal variablity of OH.
Definition: mptrac.h:3064
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:3569
int np
Number of pressure levels.
Definition: mptrac.h:3566
double vmr[CT][CP][CY]
Volume mixing ratio [ppv].
Definition: mptrac.h:3578
int ntime
Number of timesteps.
Definition: mptrac.h:3560
int nlat
Number of latitudes.
Definition: mptrac.h:3563
double lat[CY]
Latitude [deg].
Definition: mptrac.h:3572
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:2055
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:1991
#define LIN(x0, y0, x1, y1, x)
Linear interpolation.
Definition: mptrac.h:1057
#define MAX(a, b)
Macro to determine the maximum of two values.
Definition: mptrac.h:1084
int nsza
Number of solar zenith angles.
Definition: mptrac.h:3487
double sza[CSZA]
Solar zenith angle [rad].
Definition: mptrac.h:3496
double p[CP]
Pressure [hPa].
Definition: mptrac.h:3493
double o3c[CO3]
Total column ozone [DU].
Definition: mptrac.h:3499
int np
Number of pressure levels.
Definition: mptrac.h:3484
int no3c
Number of total ozone columns.
Definition: mptrac.h:3490
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:827
int tropo_ntime
Number of tropopause timesteps.
Definition: mptrac.h:3592
double tropo_lat[73]
Tropopause latitudes [deg].
Definition: mptrac.h:3601
int tropo_nlat
Number of tropopause latitudes.
Definition: mptrac.h:3595
double tropo[12][73]
Tropopause pressure values [hPa].
Definition: mptrac.h:3604
double tropo_time[12]
Tropopause time steps [s].
Definition: mptrac.h:3598
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:1185
#define Z(p)
Convert pressure to altitude.
Definition: mptrac.h:1939
#define LOG(level,...)
Print a log message with a specified logging level.
Definition: mptrac.h:2032

◆ 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:3546
double time[CTS]
Time [s].
Definition: mptrac.h:3543
int ntime
Number of timesteps.
Definition: mptrac.h:3540
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:3575
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 664 of file mptrac.c.

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

◆ compress_zfp()

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

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

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

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

The function performs the following steps:

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

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

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

◆ compress_zstd()

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

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

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

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

◆ day2doy()

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

Get day of year from date.

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

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

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

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

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

Definition at line 906 of file mptrac.c.

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

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

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

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

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

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

998 {
999
1000 const double radius = z + RE;
1001 const double latrad = DEG2RAD(lat);
1002 const double lonrad = DEG2RAD(lon);
1003 const double coslat = cos(latrad);
1004
1005 x[0] = radius * coslat * cos(lonrad);
1006 x[1] = radius * coslat * sin(lonrad);
1007 x[2] = radius * sin(latrad);
1008}

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

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

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

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

1116 {
1117
1119
1120 ctl->met_tropo = met_tropo;
1121 read_met_tropo(ctl, clim, met);
1122#pragma omp parallel for default(shared) private(ci,cw)
1123 for (int ix = 0; ix < nx; ix++)
1124 for (int iy = 0; iy < ny; iy++) {
1125 intpol_met_space_2d(met, met->pt, lons[ix], lats[iy],
1126 &pt[iy * nx + ix], ci, cw, 1);
1127 intpol_met_space_2d(met, met->ps, lons[ix], lats[iy],
1128 &ps[iy * nx + ix], ci, cw, 0);
1129 intpol_met_space_2d(met, met->zs, lons[ix], lats[iy],
1130 &zs[iy * nx + ix], ci, cw, 0);
1131 intpol_met_space_3d(met, met->z, pt[iy * nx + ix], lons[ix],
1132 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
1133 intpol_met_space_3d(met, met->t, pt[iy * nx + ix], lons[ix],
1134 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
1135 intpol_met_space_3d(met, met->h2o, pt[iy * nx + ix], lons[ix],
1136 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
1137 intpol_met_space_3d(met, met->o3, pt[iy * nx + ix], lons[ix],
1138 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
1139 }
1140}
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:1468
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:10222
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:1343
#define INTPOL_INIT
Initialize arrays for interpolation.
Definition: mptrac.h:880
int met_tropo
Tropopause definition (0=none, 1=clim, 2=cold point, 3=WMO_1st, 4=WMO_2nd, 5=dynamical).
Definition: mptrac.h:2824
float h2o[EX][EY][EP]
Water vapor volume mixing ratio [1].
Definition: mptrac.h:3784
float ps[EX][EY]
Surface pressure [hPa].
Definition: mptrac.h:3694
float zs[EX][EY]
Surface geopotential height [km].
Definition: mptrac.h:3700
float o3[EX][EY][EP]
Ozone volume mixing ratio [1].
Definition: mptrac.h:3787
float t[EX][EY][EP]
Temperature [K].
Definition: mptrac.h:3769
float pt[EX][EY]
Tropopause pressure [hPa].
Definition: mptrac.h:3727
float z[EX][EY][EP]
Geopotential height [km].
Definition: mptrac.h:3766
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 1144 of file mptrac.c.

1152 {
1153
1154 /* Check longitude... */
1155 *lon2 = FMOD(lon, 360.);
1156 if (*lon2 < lons[0])
1157 *lon2 += 360;
1158 else if (*lon2 > lons[nlon - 1])
1159 *lon2 -= 360;
1160
1161 /* Check latitude... */
1162 *lat2 = lat;
1163 if (lats[0] < lats[nlat - 1])
1164 *lat2 = MIN(MAX(*lat2, lats[0]), lats[nlat - 1]);
1165 else
1166 *lat2 = MIN(MAX(*lat2, lats[nlat - 1]), lats[0]);
1167}

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

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

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

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

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

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

1566 {
1567
1568 double var0, var1;
1569
1570 /* Spatial interpolation... */
1571 intpol_met_space_3d_ml(met0, zs0, array0, p, lon, lat, &var0);
1572 intpol_met_space_3d_ml(met1, zs1, array1, p, lon, lat, &var1);
1573
1574 /* Interpolate... */
1575 *var = LIN(met0->time, var0, met1->time, var1, ts);
1576}
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:1401
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 1580 of file mptrac.c.

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

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

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

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

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

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

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

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

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

1994 {
1995
1996 int ilo = 0;
1997 int ihi = n - 1;
1998 int i = (ihi + ilo) >> 1;
1999
2000 if (xx[i] < xx[i + 1])
2001 while (ihi > ilo + 1) {
2002 i = (ihi + ilo) >> 1;
2003 if (xx[i] > x)
2004 ihi = i;
2005 else
2006 ilo = i;
2007 } else
2008 while (ihi > ilo + 1) {
2009 i = (ihi + ilo) >> 1;
2010 if (xx[i] <= x)
2011 ihi = i;
2012 else
2013 ilo = i;
2014 }
2015
2016 return ilo;
2017}

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

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

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

2058 {
2059
2060 /* Calculate index... */
2061 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2062
2063 /* Check range... */
2064 if (i < 0)
2065 return 0;
2066 else if (i > n - 2)
2067 return n - 2;
2068 else
2069 return i;
2070}

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

2080 {
2081
2082 ind[0] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind],
2083 np, height_ap, 0);
2084 ind[1] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind],
2085 np, height_ap, ind[0]);
2086 ind[2] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind + 1],
2087 np, height_ap, ind[1]);
2088 ind[3] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind + 1],
2089 np, height_ap, ind[2]);
2090}
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 2094 of file mptrac.c.

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

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

2280 {
2281
2282 /* Set timer... */
2283 SELECT_TIMER("MODULE_BOUND_COND", "PHYSICS", NVTX_GPU);
2284
2285 /* Check quantity flags... */
2286 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0 && ctl->qnt_Cccl4
2287 && ctl->qnt_Cccl3f < 0 && ctl->qnt_Cccl2f2 < 0
2288 && ctl->qnt_Cn2o < 0 && ctl->qnt_Csf6 < 0 && ctl->qnt_aoa < 0)
2289 return;
2290
2291 /* Loop over particles... */
2292 PARTICLE_LOOP(0, atm->np, 1,
2293 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2294
2295 /* Check latitude and pressure range... */
2296 if (atm->lat[ip] < ctl->bound_lat0 || atm->lat[ip] > ctl->bound_lat1
2297 || atm->p[ip] > ctl->bound_p0 || atm->p[ip] < ctl->bound_p1)
2298 continue;
2299
2300 /* Check surface layer... */
2301 if (ctl->bound_dps > 0 || ctl->bound_dzs > 0
2302 || ctl->bound_zetas > 0 || ctl->bound_pbl) {
2303
2304 /* Get surface pressure... */
2305 double ps;
2307 INTPOL_2D(ps, 1);
2308
2309 /* Check pressure... */
2310 if (ctl->bound_dps > 0 && atm->p[ip] < ps - ctl->bound_dps)
2311 continue;
2312
2313 /* Check height... */
2314 if (ctl->bound_dzs > 0 && Z(atm->p[ip]) > Z(ps) + ctl->bound_dzs)
2315 continue;
2316
2317 /* Check zeta range... */
2318 if (ctl->bound_zetas > 0) {
2319 double t;
2320 INTPOL_3D(t, 1);
2321 if (ZETA(ps, atm->p[ip], t) > ctl->bound_zetas)
2322 continue;
2323 }
2324
2325 /* Check planetary boundary layer... */
2326 if (ctl->bound_pbl) {
2327 double pbl;
2328 INTPOL_2D(pbl, 0);
2329 if (atm->p[ip] < pbl)
2330 continue;
2331 }
2332 }
2333
2334 /* Set mass and volume mixing ratio... */
2335 if (ctl->qnt_m >= 0 && ctl->bound_mass >= 0)
2336 atm->q[ctl->qnt_m][ip] =
2337 ctl->bound_mass + ctl->bound_mass_trend * atm->time[ip];
2338 if (ctl->qnt_vmr >= 0 && ctl->bound_vmr >= 0)
2339 atm->q[ctl->qnt_vmr][ip] =
2340 ctl->bound_vmr + ctl->bound_vmr_trend * atm->time[ip];
2341
2342 /* Set CFC-10 volume mixing ratio... */
2343 if (ctl->qnt_Cccl4 >= 0 && ctl->clim_ccl4_timeseries[0] != '-')
2344 atm->q[ctl->qnt_Cccl4][ip] = clim_ts(&clim->ccl4, atm->time[ip]);
2345
2346 /* Set CFC-11 volume mixing ratio... */
2347 if (ctl->qnt_Cccl3f >= 0 && ctl->clim_ccl3f_timeseries[0] != '-')
2348 atm->q[ctl->qnt_Cccl3f][ip] = clim_ts(&clim->ccl3f, atm->time[ip]);
2349
2350 /* Set CFC-12 volume mixing ratio... */
2351 if (ctl->qnt_Cccl2f2 >= 0 && ctl->clim_ccl2f2_timeseries[0] != '-')
2352 atm->q[ctl->qnt_Cccl2f2][ip] = clim_ts(&clim->ccl2f2, atm->time[ip]);
2353
2354 /* Set N2O volume mixing ratio... */
2355 if (ctl->qnt_Cn2o >= 0 && ctl->clim_n2o_timeseries[0] != '-')
2356 atm->q[ctl->qnt_Cn2o][ip] = clim_ts(&clim->n2o, atm->time[ip]);
2357
2358 /* Set SF6 volume mixing ratio... */
2359 if (ctl->qnt_Csf6 >= 0 && ctl->clim_sf6_timeseries[0] != '-')
2360 atm->q[ctl->qnt_Csf6][ip] = clim_ts(&clim->sf6, atm->time[ip]);
2361
2362 /* Set age of air... */
2363 if (ctl->qnt_aoa >= 0)
2364 atm->q[ctl->qnt_aoa][ip] = atm->time[ip];
2365 }
2366}
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:911
#define ZETA(ps, p, t)
Computes the value of the zeta vertical coordinate.
Definition: mptrac.h:1989
#define INTPOL_2D(var, init)
Perform 2D interpolation for a meteorological variable.
Definition: mptrac.h:894
clim_ts_t ccl2f2
CFC-12 time series.
Definition: mptrac.h:3631
clim_ts_t sf6
SF6 time series.
Definition: mptrac.h:3637
clim_ts_t ccl4
CFC-10 time series.
Definition: mptrac.h:3625
clim_ts_t ccl3f
CFC-11 time series.
Definition: mptrac.h:3628
clim_ts_t n2o
N2O time series.
Definition: mptrac.h:3634
int qnt_Cccl2f2
Quantity array index for CFC-12 volume mixing ratio (chemistry code).
Definition: mptrac.h:2642
int qnt_m
Quantity array index for mass.
Definition: mptrac.h:2387
int qnt_aoa
Quantity array index for age of air.
Definition: mptrac.h:2651
char clim_n2o_timeseries[LEN]
Filename of N2O time series.
Definition: mptrac.h:2989
double bound_dzs
Boundary conditions surface layer depth [km].
Definition: mptrac.h:2938
int qnt_Cccl4
Quantity array index for CFC-10 volume mixing ratio (chemistry code).
Definition: mptrac.h:2636
double bound_mass
Boundary conditions mass per particle [kg].
Definition: mptrac.h:2911
int qnt_vmr
Quantity array index for volume mixing ratio.
Definition: mptrac.h:2390
double bound_lat1
Boundary conditions maximum longitude [deg].
Definition: mptrac.h:2926
int bound_pbl
Boundary conditions planetary boundary layer (0=no, 1=yes).
Definition: mptrac.h:2944
double bound_p1
Boundary conditions top pressure [hPa].
Definition: mptrac.h:2932
double bound_vmr
Boundary conditions volume mixing ratio [ppv].
Definition: mptrac.h:2917
double bound_lat0
Boundary conditions minimum longitude [deg].
Definition: mptrac.h:2923
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
Definition: mptrac.h:2920
int qnt_Cn2o
Quantity array index for N2O volume mixing ratio (chemistry code).
Definition: mptrac.h:2645
int qnt_Cccl3f
Quantity array index for CFC-11 volume mixing ratio (chemistry code).
Definition: mptrac.h:2639
int qnt_Csf6
Quantity array index for SF6 volume mixing ratio (chemistry code).
Definition: mptrac.h:2648
double bound_dps
Boundary conditions surface layer depth [hPa].
Definition: mptrac.h:2935
double bound_mass_trend
Boundary conditions mass per particle trend [kg/s].
Definition: mptrac.h:2914
double bound_p0
Boundary conditions bottom pressure [hPa].
Definition: mptrac.h:2929
char clim_ccl4_timeseries[LEN]
Filename of CFC-10 time series.
Definition: mptrac.h:2980
char clim_sf6_timeseries[LEN]
Filename of SF6 time series.
Definition: mptrac.h:2992
char clim_ccl3f_timeseries[LEN]
Filename of CFC-11 time series.
Definition: mptrac.h:2983
char clim_ccl2f2_timeseries[LEN]
Filename of CFC-12 time series.
Definition: mptrac.h:2986
double bound_zetas
Boundary conditions surface layer zeta [K].
Definition: mptrac.h:2941
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 
)

Computes gridded chemical tracer concentrations (volume mixing ratio) from individual air parcel mass data and assigns them back to the parcels.

This function aggregates the mass of tracer particles onto a 3D chemical grid (longitude × latitude × altitude), accounting for either single or ensemble simulations depending on ctl->nens. It then interpolates meteorological temperature fields and computes volume mixing ratios, storing them in the specified tracer quantity (e.g., ctl->qnt_Cx).

If the molar mass is undefined or required quantity indices are missing, the function exits early.

Parallelization is supported via OpenMP or OpenACC.

Parameters
[in]ctlPointer to the control structure containing configuration parameters, including grid dimensions, tracer indices, and simulation mode.
[in]met0Pointer to the meteorological data at the beginning of the interpolation interval.
[in]met1Pointer to the meteorological data at the end of the interpolation interval.
[in,out]atmPointer to the atmospheric state, including parcel coordinates, time, mass, and output tracer fields.
[in]tCentral time step used for output and interpolation.
Note
  • Requires ctl->molmass > 0, and ctl->qnt_m and ctl->qnt_Cx to be set.
  • Uses ensemble mode if ctl->nens > 0 and assigns each parcel to its ensemble member via ctl->qnt_ens.
  • Grid box volume mixing ratios are computed assuming ideal gas law and a layered spherical grid.
  • The output quantity (e.g., qnt_Cx) is given in ppbv.
See also
intpol_met_time_3d()
P(), Z(), RHO()
ARRAY_3D macro
Authors
Mingzhao Liu
Lars Hoffmann

Definition at line 2370 of file mptrac.c.

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

2538 {
2539
2540 /* Set timer... */
2541 SELECT_TIMER("MODULE_CHEM_INIT", "PHYSICS", NVTX_GPU);
2542
2543 /* Loop over particles... */
2544 PARTICLE_LOOP(0, atm->np, 0,
2545 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2546
2547 /* Set H2O and O3 using meteo data... */
2549 if (ctl->qnt_Ch2o >= 0) {
2550 double h2o;
2551 INTPOL_3D(h2o, 1);
2552 SET_ATM(qnt_Ch2o, h2o);
2553 }
2554 if (ctl->qnt_Co3 >= 0) {
2555 double o3;
2556 INTPOL_3D(o3, 1);
2557 SET_ATM(qnt_Co3, o3);
2558 }
2559
2560 /* Set radical species... */
2561 SET_ATM(qnt_Coh, clim_oh(ctl, clim, atm->time[ip],
2562 atm->lon[ip], atm->lat[ip], atm->p[ip]));
2563 SET_ATM(qnt_Cho2, clim_zm(&clim->ho2, atm->time[ip],
2564 atm->lat[ip], atm->p[ip]));
2565 SET_ATM(qnt_Ch2o2, clim_zm(&clim->h2o2, atm->time[ip],
2566 atm->lat[ip], atm->p[ip]));
2567 SET_ATM(qnt_Co1d, clim_zm(&clim->o1d, atm->time[ip],
2568 atm->lat[ip], atm->p[ip]));
2569 }
2570}
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:1698
clim_zm_t ho2
HO2 zonal means.
Definition: mptrac.h:3619
clim_zm_t o1d
O(1D) zonal means.
Definition: mptrac.h:3622
clim_zm_t h2o2
H2O2 zonal means.
Definition: mptrac.h:3616
int qnt_Ch2o
Quantity array index for H2O volume mixing ratio (chemistry code).
Definition: mptrac.h:2609
int qnt_Co3
Quantity array index for O3 volume mixing ratio (chemistry code).
Definition: mptrac.h:2612
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 2574 of file mptrac.c.

2579 {
2580
2581 /* Set timer... */
2582 SELECT_TIMER("MODULE_CONVECTION", "PHYSICS", NVTX_GPU);
2583
2584 /* Create random numbers... */
2585 module_rng(ctl, cache->rs, (size_t) atm->np, 0);
2586
2587 /* Loop over particles... */
2588 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2589
2590 /* Interpolate CAPE... */
2591 double ps;
2593 INTPOL_2D(ps, 1);
2594
2595 /* Initialize pressure range for vertical mixing... */
2596 double pbot = ps, ptop = ps;
2597
2598 /* Mixing in the PBL... */
2599 if (ctl->conv_mix_pbl) {
2600
2601 /* Interpolate PBL... */
2602 double pbl;
2603 INTPOL_2D(pbl, 0);
2604
2605 /* Set pressure range... */
2606 ptop = pbl - ctl->conv_pbl_trans * (ps - pbl);
2607 }
2608
2609 /* Convective mixing... */
2610 if (ctl->conv_cape >= 0) {
2611
2612 /* Interpolate CAPE, CIN, and equilibrium level... */
2613 double cape, cin, pel;
2614 INTPOL_2D(cape, 0);
2615 INTPOL_2D(cin, 0);
2616 INTPOL_2D(pel, 0);
2617
2618 /* Set pressure range... */
2619 if (isfinite(cape) && cape >= ctl->conv_cape
2620 && (ctl->conv_cin <= 0 || (isfinite(cin) && cin >= ctl->conv_cin)))
2621 ptop = GSL_MIN(ptop, pel);
2622 }
2623
2624 /* Apply vertical mixing... */
2625 if (ptop != pbot && atm->p[ip] >= ptop) {
2626
2627 /* Get density range... */
2628 double tbot, ttop;
2629 intpol_met_time_3d(met0, met0->t, met1, met1->t, atm->time[ip],
2630 pbot, atm->lon[ip], atm->lat[ip], &tbot, ci, cw, 1);
2631 intpol_met_time_3d(met0, met0->t, met1, met1->t, atm->time[ip], ptop,
2632 atm->lon[ip], atm->lat[ip], &ttop, ci, cw, 1);
2633 const double rhobot = pbot / tbot;
2634 const double rhotop = ptop / ttop;
2635
2636 /* Get new density... */
2637 const double rho = rhobot + (rhotop - rhobot) * cache->rs[ip];
2638
2639 /* Get pressure... */
2640 atm->p[ip] = LIN(rhobot, pbot, rhotop, ptop, rho);
2641 }
2642 }
2643}
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:3704
double rs[3 *NP+1]
Random numbers.
Definition: mptrac.h:3467
double conv_cape
CAPE threshold for convection module [J/kg].
Definition: mptrac.h:2902
double conv_pbl_trans
Depth of PBL transition layer (fraction of PBL depth).
Definition: mptrac.h:2899
int conv_mix_pbl
Vertical mixing in the PBL (0=off, 1=on).
Definition: mptrac.h:2896
double conv_cin
CIN threshold for convection module [J/kg].
Definition: mptrac.h:2905
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 2647 of file mptrac.c.

2651 {
2652
2653 /* Set timer... */
2654 SELECT_TIMER("MODULE_DECAY", "PHYSICS", NVTX_GPU);
2655
2656 /* Check quantity flags... */
2657 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
2658 ERRMSG("Module needs quantity mass or volume mixing ratio!");
2659
2660 /* Loop over particles... */
2661 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,clim,atm)") {
2662
2663 /* Get weighting factor... */
2664 const double w = tropo_weight(clim, atm, ip);
2665
2666 /* Set lifetime... */
2667 const double tdec = w * ctl->tdec_trop + (1 - w) * ctl->tdec_strat;
2668
2669 /* Calculate exponential decay... */
2670 const double aux = exp(-cache->dt[ip] / tdec);
2671 if (ctl->qnt_m >= 0) {
2672 if (ctl->qnt_mloss_decay >= 0)
2673 atm->q[ctl->qnt_mloss_decay][ip]
2674 += atm->q[ctl->qnt_m][ip] * (1 - aux);
2675 atm->q[ctl->qnt_m][ip] *= aux;
2676 if (ctl->qnt_loss_rate >= 0)
2677 atm->q[ctl->qnt_loss_rate][ip] += 1. / tdec;
2678 }
2679 if (ctl->qnt_vmr >= 0)
2680 atm->q[ctl->qnt_vmr][ip] *= aux;
2681 }
2682}
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:10843
int qnt_loss_rate
Quantity array index for total loss rate.
Definition: mptrac.h:2546
int qnt_mloss_decay
Quantity array index for total mass loss due to exponential decay.
Definition: mptrac.h:2543
double tdec_strat
Life time of particles in the stratosphere [s].
Definition: mptrac.h:2956
double tdec_trop
Life time of particles in the troposphere [s].
Definition: mptrac.h:2953
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 2686 of file mptrac.c.

2691 {
2692
2693 /* Set timer... */
2694 SELECT_TIMER("MODULE_DIFF_MESO", "PHYSICS", NVTX_GPU);
2695
2696 /* Create random numbers... */
2697 module_rng(ctl, cache->rs, 3 * (size_t) atm->np, 1);
2698
2699 /* Loop over particles... */
2700 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2701
2702 /* Get indices... */
2703 const int ix = locate_reg(met0->lon, met0->nx, atm->lon[ip]);
2704 const int iy = locate_irr(met0->lat, met0->ny, atm->lat[ip]);
2705 const int iz = locate_irr(met0->p, met0->np, atm->p[ip]);
2706
2707 /* Get standard deviations of local wind data... */
2708 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
2709 for (int i = 0; i < 2; i++)
2710 for (int j = 0; j < 2; j++)
2711 for (int k = 0; k < 2; k++) {
2712 umean += met0->u[ix + i][iy + j][iz + k];
2713 usig += SQR(met0->u[ix + i][iy + j][iz + k]);
2714 vmean += met0->v[ix + i][iy + j][iz + k];
2715 vsig += SQR(met0->v[ix + i][iy + j][iz + k]);
2716 wmean += met0->w[ix + i][iy + j][iz + k];
2717 wsig += SQR(met0->w[ix + i][iy + j][iz + k]);
2718
2719 umean += met1->u[ix + i][iy + j][iz + k];
2720 usig += SQR(met1->u[ix + i][iy + j][iz + k]);
2721 vmean += met1->v[ix + i][iy + j][iz + k];
2722 vsig += SQR(met1->v[ix + i][iy + j][iz + k]);
2723 wmean += met1->w[ix + i][iy + j][iz + k];
2724 wsig += SQR(met1->w[ix + i][iy + j][iz + k]);
2725 }
2726 usig = usig / 16.f - SQR(umean / 16.f);
2727 usig = (usig > 0 ? sqrtf(usig) : 0);
2728 vsig = vsig / 16.f - SQR(vmean / 16.f);
2729 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
2730 wsig = wsig / 16.f - SQR(wmean / 16.f);
2731 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
2732
2733 /* Set temporal correlations for mesoscale fluctuations... */
2734 const double r = 1 - 2 * fabs(cache->dt[ip]) / ctl->dt_met;
2735 const double r2 = sqrt(1 - r * r);
2736
2737 /* Calculate horizontal mesoscale wind fluctuations... */
2738 if (ctl->turb_mesox > 0) {
2739 cache->uvwp[ip][0] =
2740 (float) (r * cache->uvwp[ip][0] +
2741 r2 * cache->rs[3 * ip] * ctl->turb_mesox * usig);
2742 atm->lon[ip] +=
2743 DX2DEG(cache->uvwp[ip][0] * cache->dt[ip] / 1000., atm->lat[ip]);
2744
2745 cache->uvwp[ip][1] =
2746 (float) (r * cache->uvwp[ip][1] +
2747 r2 * cache->rs[3 * ip + 1] * ctl->turb_mesox * vsig);
2748 atm->lat[ip] += DY2DEG(cache->uvwp[ip][1] * cache->dt[ip] / 1000.);
2749 }
2750
2751 /* Calculate vertical mesoscale wind fluctuations... */
2752 if (ctl->turb_mesoz > 0) {
2753 cache->uvwp[ip][2] =
2754 (float) (r * cache->uvwp[ip][2] +
2755 r2 * cache->rs[3 * ip + 2] * ctl->turb_mesoz * wsig);
2756 atm->p[ip] += cache->uvwp[ip][2] * cache->dt[ip];
2757 }
2758 }
2759}
float uvwp[NP][3]
Wind perturbations [m/s].
Definition: mptrac.h:3464
double turb_mesoz
Vertical scaling factor for mesoscale wind fluctuations.
Definition: mptrac.h:2893
double dt_met
Time step of meteo data [s].
Definition: mptrac.h:2679
double turb_mesox
Horizontal scaling factor for mesoscale wind fluctuations.
Definition: mptrac.h:2890
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 2763 of file mptrac.c.

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

2894 {
2895
2896 /* Set timer... */
2897 SELECT_TIMER("MODULE_DIFF_TURB", "PHYSICS", NVTX_GPU);
2898
2899 /* Create random numbers... */
2900 module_rng(ctl, cache->rs, 3 * (size_t) atm->np, 1);
2901
2902 /* Loop over particles... */
2903 PARTICLE_LOOP(0, atm->np, 1,
2904 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2905
2906 /* Get PBL and surface pressure... */
2907 double pbl, ps;
2909 INTPOL_2D(pbl, 1);
2910 INTPOL_2D(ps, 0);
2911
2912 /* Get weighting factors... */
2913 const double wpbl = pbl_weight(ctl, atm, ip, pbl, ps);
2914 const double wtrop = tropo_weight(clim, atm, ip) * (1.0 - wpbl);
2915 const double wstrat = 1.0 - wpbl - wtrop;
2916
2917 /* Set diffusivity... */
2918 const double dx = wpbl * ctl->turb_dx_pbl + wtrop * ctl->turb_dx_trop
2919 + wstrat * ctl->turb_dx_strat;
2920 const double dz = wpbl * ctl->turb_dz_pbl + wtrop * ctl->turb_dz_trop
2921 + wstrat * ctl->turb_dz_strat;
2922
2923 /* Horizontal turbulent diffusion... */
2924 if (dx > 0) {
2925 const double sigma = sqrt(2.0 * dx * fabs(cache->dt[ip])) / 1000.;
2926 atm->lon[ip] += DX2DEG(cache->rs[3 * ip] * sigma, atm->lat[ip]);
2927 atm->lat[ip] += DY2DEG(cache->rs[3 * ip + 1] * sigma);
2928 }
2929
2930 /* Vertical turbulent diffusion... */
2931 if (dz > 0) {
2932 const double sigma = sqrt(2.0 * dz * fabs(cache->dt[ip])) / 1000.;
2933 atm->p[ip] += DZ2DP(cache->rs[3 * ip + 2] * sigma, atm->p[ip]);
2934 }
2935 }
2936}
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:6043
double turb_dz_trop
Vertical turbulent diffusion coefficient (troposphere) [m^2/s].
Definition: mptrac.h:2884
double turb_dx_strat
Horizontal turbulent diffusion coefficient (stratosphere) [m^2/s].
Definition: mptrac.h:2878
double turb_dx_trop
Horizontal turbulent diffusion coefficient (troposphere) [m^2/s].
Definition: mptrac.h:2875
double turb_dx_pbl
Horizontal turbulent diffusion coefficient (PBL) [m^2/s].
Definition: mptrac.h:2872
double turb_dz_strat
Vertical turbulent diffusion coefficient (stratosphere) [m^2/s].
Definition: mptrac.h:2887
double turb_dz_pbl
Vertical turbulent diffusion coefficient (PBL) [m^2/s].
Definition: mptrac.h:2881
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 2940 of file mptrac.c.

2945 {
2946
2947 /* Set timer... */
2948 SELECT_TIMER("MODULE_DRY_DEPO", "PHYSICS", NVTX_GPU);
2949
2950 /* Check quantity flags... */
2951 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
2952 ERRMSG("Module needs quantity mass or volume mixing ratio!");
2953
2954 /* Loop over particles... */
2955 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2956
2957 /* Get surface pressure... */
2958 double ps;
2960 INTPOL_2D(ps, 1);
2961
2962 /* Check whether particle is above the surface layer... */
2963 if (atm->p[ip] < ps - ctl->dry_depo_dp)
2964 continue;
2965
2966 /* Set depth of surface layer... */
2967 const double dz = 1000. * (Z(ps - ctl->dry_depo_dp) - Z(ps));
2968
2969 /* Calculate sedimentation velocity for particles... */
2970 double v_dep;
2971 if (ctl->qnt_rp > 0 && ctl->qnt_rhop > 0) {
2972
2973 /* Get temperature... */
2974 double t;
2975 INTPOL_3D(t, 1);
2976
2977 /* Set deposition velocity... */
2978 v_dep = sedi(atm->p[ip], t, atm->q[ctl->qnt_rp][ip],
2979 atm->q[ctl->qnt_rhop][ip]);
2980 }
2981
2982 /* Use explicit sedimentation velocity for gases... */
2983 else
2984 v_dep = ctl->dry_depo_vdep;
2985
2986 /* Calculate loss of mass based on deposition velocity... */
2987 const double aux = exp(-cache->dt[ip] * v_dep / dz);
2988 if (ctl->qnt_m >= 0) {
2989 if (ctl->qnt_mloss_dry >= 0)
2990 atm->q[ctl->qnt_mloss_dry][ip]
2991 += atm->q[ctl->qnt_m][ip] * (1 - aux);
2992 atm->q[ctl->qnt_m][ip] *= aux;
2993 if (ctl->qnt_loss_rate >= 0)
2994 atm->q[ctl->qnt_loss_rate][ip] += v_dep / dz;
2995 }
2996 if (ctl->qnt_vmr >= 0)
2997 atm->q[ctl->qnt_vmr][ip] *= aux;
2998 }
2999}
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:10567
int qnt_rhop
Quantity array index for particle density.
Definition: mptrac.h:2396
int qnt_rp
Quantity array index for particle radius.
Definition: mptrac.h:2393
double dry_depo_dp
Dry deposition surface layer [hPa].
Definition: mptrac.h:3109
int qnt_mloss_dry
Quantity array index for total mass loss due to dry deposition.
Definition: mptrac.h:2540
double dry_depo_vdep
Dry deposition velocity [m/s].
Definition: mptrac.h:3112
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 3003 of file mptrac.c.

3009 {
3010
3011 /* Set timer... */
3012 SELECT_TIMER("MODULE_H2O2_CHEM", "PHYSICS", NVTX_GPU);
3013
3014 /* Check quantity flags... */
3015 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
3016 ERRMSG("Module needs quantity mass or volume mixing ratio!");
3017
3018 /* Parameter of SO2 correction... */
3019 const double a = 3.12541941e-06;
3020 const double b = -5.72532259e-01;
3021 const double low = pow(1. / a, 1. / b);
3022
3023 /* Loop over particles... */
3024 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
3025
3026 /* Check whether particle is inside cloud... */
3027 double lwc, rwc;
3029 INTPOL_3D(lwc, 1);
3030 INTPOL_3D(rwc, 0);
3031 if (!(lwc > 0 || rwc > 0))
3032 continue;
3033
3034 /* Get temperature... */
3035 double t;
3036 INTPOL_3D(t, 0);
3037
3038 /* Get molecular density... */
3039 const double M = MOLEC_DENS(atm->p[ip], t);
3040
3041 /* Reaction rate (Berglen et al., 2004)... */
3042 const double k = 9.1e7 * exp(-29700. / RI * (1. / t - 1. / 298.15)); /* (Maass, 1999), unit: M^(-2) */
3043
3044 /* Henry constant of SO2... */
3045 const double H_SO2 =
3046 1.3e-2 * exp(2900. * (1. / t - 1. / 298.15)) * RI * t;
3047 const double K_1S = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15)); /* unit: mol/L */
3048
3049 /* Henry constant of H2O2... */
3050 const double H_h2o2 =
3051 8.3e2 * exp(7600. * (1. / t - 1. / 298.15)) * RI * t;
3052
3053 /* Correction factor for high SO2 concentration
3054 (if qnt_Cx is defined, the correction is switched on)... */
3055 double cor = 1.0;
3056 if (ctl->qnt_Cx >= 0)
3057 cor = atm->q[ctl->qnt_Cx][ip] >
3058 low ? a * pow(atm->q[ctl->qnt_Cx][ip], b) : 1;
3059
3060 const double h2o2 = H_h2o2
3061 * clim_zm(&clim->h2o2, atm->time[ip], atm->lat[ip], atm->p[ip])
3062 * M * cor * 1000. / AVO; /* unit: mol/L */
3063
3064 /* Volume water content in cloud [m^3 m^(-3)]... */
3065 const double rho_air = atm->p[ip] / (RI * t) * MA / 10.;
3066 const double CWC = (lwc + rwc) * rho_air / 1e3;
3067
3068 /* Calculate exponential decay (Rolph et al., 1992)... */
3069 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
3070 const double aux = exp(-cache->dt[ip] * rate_coef);
3071 if (ctl->qnt_m >= 0) {
3072 if (ctl->qnt_mloss_h2o2 >= 0)
3073 atm->q[ctl->qnt_mloss_h2o2][ip] += atm->q[ctl->qnt_m][ip] * (1 - aux);
3074 atm->q[ctl->qnt_m][ip] *= aux;
3075 if (ctl->qnt_loss_rate >= 0)
3076 atm->q[ctl->qnt_loss_rate][ip] += rate_coef;
3077 }
3078 if (ctl->qnt_vmr >= 0)
3079 atm->q[ctl->qnt_vmr][ip] *= aux;
3080 }
3081}
#define AVO
Avogadro constant [1/mol].
Definition: mptrac.h:184
#define MOLEC_DENS(p, t)
Calculate the density of a gas molecule.
Definition: mptrac.h:1200
int qnt_mloss_h2o2
Quantity array index for total mass loss due to H2O2 chemistry.
Definition: mptrac.h:2531
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 3085 of file mptrac.c.

3090 {
3091
3092 double t;
3093
3094 /* Set timer... */
3095 SELECT_TIMER("MODULE_ISOSURF_INIT", "PHYSICS", NVTX_GPU);
3096
3097 /* Save pressure... */
3098 if (ctl->isosurf == 1) {
3099 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,atm)") {
3100 cache->iso_var[ip] = atm->p[ip];
3101 }
3102 }
3103
3104 /* Save density... */
3105 else if (ctl->isosurf == 2) {
3106 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,met0,met1,atm)") {
3108 INTPOL_3D(t, 1);
3109 cache->iso_var[ip] = atm->p[ip] / t;
3110 }
3111 }
3112
3113 /* Save potential temperature... */
3114 else if (ctl->isosurf == 3) {
3115 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,met0,met1,atm)") {
3117 INTPOL_3D(t, 1);
3118 cache->iso_var[ip] = THETA(atm->p[ip], t);
3119 }
3120 }
3121
3122 /* Read balloon pressure data... */
3123 else if (ctl->isosurf == 4) {
3124
3125 /* Write info... */
3126 LOG(1, "Read balloon pressure data: %s", ctl->balloon);
3127
3128 /* Open file... */
3129 FILE *in;
3130 if (!(in = fopen(ctl->balloon, "r")))
3131 ERRMSG("Cannot open file!");
3132
3133 /* Read pressure time series... */
3134 char line[LEN];
3135 while (fgets(line, LEN, in))
3136 if (sscanf(line, "%lg %lg", &(cache->iso_ts[cache->iso_n]),
3137 &(cache->iso_ps[cache->iso_n])) == 2)
3138 if ((++cache->iso_n) > NP)
3139 ERRMSG("Too many data points!");
3140
3141 /* Check number of points... */
3142 if (cache->iso_n < 1)
3143 ERRMSG("Could not read any data!");
3144
3145 /* Close file... */
3146 fclose(in);
3147
3148 /* Update of cache data on device... */
3149 mptrac_update_device(NULL, cache, NULL, NULL, NULL, NULL);
3150 }
3151}
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:5716
#define NP
Maximum number of atmospheric data points.
Definition: mptrac.h:319
double iso_ts[NP]
Isosurface balloon time [s].
Definition: mptrac.h:3458
int iso_n
Isosurface balloon number of data points.
Definition: mptrac.h:3461
double iso_ps[NP]
Isosurface balloon pressure [hPa].
Definition: mptrac.h:3455
double iso_var[NP]
Isosurface variables.
Definition: mptrac.h:3452
char balloon[LEN]
Balloon position filename.
Definition: mptrac.h:2856
int isosurf
Isosurface parameter (0=none, 1=pressure, 2=density, 3=theta, 4=balloon).
Definition: mptrac.h:2853
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 3155 of file mptrac.c.

3160 {
3161
3162 /* Set timer... */
3163 SELECT_TIMER("MODULE_ISOSURF", "PHYSICS", NVTX_GPU);
3164
3165 /* Loop over particles... */
3166 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,cache,met0,met1,atm)") {
3167
3168 /* Init... */
3169 double t;
3171
3172 /* Restore pressure... */
3173 if (ctl->isosurf == 1)
3174 atm->p[ip] = cache->iso_var[ip];
3175
3176 /* Restore density... */
3177 else if (ctl->isosurf == 2) {
3178 INTPOL_3D(t, 1);
3179 atm->p[ip] = cache->iso_var[ip] * t;
3180 }
3181
3182 /* Restore potential temperature... */
3183 else if (ctl->isosurf == 3) {
3184 INTPOL_3D(t, 1);
3185 atm->p[ip] = 1000. * pow(cache->iso_var[ip] / t, -1. / 0.286);
3186 }
3187
3188 /* Interpolate pressure... */
3189 else if (ctl->isosurf == 4) {
3190 if (atm->time[ip] <= cache->iso_ts[0])
3191 atm->p[ip] = cache->iso_ps[0];
3192 else if (atm->time[ip] >= cache->iso_ts[cache->iso_n - 1])
3193 atm->p[ip] = cache->iso_ps[cache->iso_n - 1];
3194 else {
3195 int idx = locate_irr(cache->iso_ts, cache->iso_n, atm->time[ip]);
3196 atm->p[ip] = LIN(cache->iso_ts[idx], cache->iso_ps[idx],
3197 cache->iso_ts[idx + 1], cache->iso_ps[idx + 1],
3198 atm->time[ip]);
3199 }
3200 }
3201 }
3202}
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 3260 of file mptrac.c.

3266 {
3267
3268 /* Set timer... */
3269 SELECT_TIMER("MODULE_METEO", "PHYSICS", NVTX_GPU);
3270
3271 /* Check quantity flags... */
3272 if (ctl->qnt_tsts >= 0)
3273 if (ctl->qnt_tice < 0 || ctl->qnt_tnat < 0)
3274 ERRMSG("Need T_ice and T_NAT to calculate T_STS!");
3275
3276 /* Loop over particles... */
3277 PARTICLE_LOOP(0, atm->np, 0,
3278 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3279
3280 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
3281 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
3282 o3, lwc, rwc, iwc, swc, cc, z, zt;
3283
3284 /* Interpolate meteo data... */
3286 INTPOL_TIME_ALL(atm->time[ip], atm->p[ip], atm->lon[ip], atm->lat[ip]);
3287
3288 /* Set quantities... */
3289 SET_ATM(qnt_ps, ps);
3290 SET_ATM(qnt_ts, ts);
3291 SET_ATM(qnt_zs, zs);
3292 SET_ATM(qnt_us, us);
3293 SET_ATM(qnt_vs, vs);
3294 SET_ATM(qnt_ess, ess);
3295 SET_ATM(qnt_nss, nss);
3296 SET_ATM(qnt_shf, shf);
3297 SET_ATM(qnt_lsm, lsm);
3298 SET_ATM(qnt_sst, sst);
3299 SET_ATM(qnt_pbl, pbl);
3300 SET_ATM(qnt_pt, pt);
3301 SET_ATM(qnt_tt, tt);
3302 SET_ATM(qnt_zt, zt);
3303 SET_ATM(qnt_h2ot, h2ot);
3304 SET_ATM(qnt_zg, z);
3305 SET_ATM(qnt_p, atm->p[ip]);
3306 SET_ATM(qnt_t, t);
3307 SET_ATM(qnt_rho, RHO(atm->p[ip], t));
3308 SET_ATM(qnt_u, u);
3309 SET_ATM(qnt_v, v);
3310 SET_ATM(qnt_w, w);
3311 SET_ATM(qnt_h2o, h2o);
3312 SET_ATM(qnt_o3, o3);
3313 SET_ATM(qnt_lwc, lwc);
3314 SET_ATM(qnt_rwc, rwc);
3315 SET_ATM(qnt_iwc, iwc);
3316 SET_ATM(qnt_swc, swc);
3317 SET_ATM(qnt_cc, cc);
3318 SET_ATM(qnt_pct, pct);
3319 SET_ATM(qnt_pcb, pcb);
3320 SET_ATM(qnt_cl, cl);
3321 SET_ATM(qnt_plcl, plcl);
3322 SET_ATM(qnt_plfc, plfc);
3323 SET_ATM(qnt_pel, pel);
3324 SET_ATM(qnt_cape, cape);
3325 SET_ATM(qnt_cin, cin);
3326 SET_ATM(qnt_o3c, o3c);
3327 SET_ATM(qnt_hno3,
3328 clim_zm(&clim->hno3, atm->time[ip], atm->lat[ip], atm->p[ip]));
3329 SET_ATM(qnt_oh, clim_oh(ctl, clim, atm->time[ip],
3330 atm->lon[ip], atm->lat[ip], atm->p[ip]));
3331 SET_ATM(qnt_h2o2, clim_zm(&clim->h2o2, atm->time[ip],
3332 atm->lat[ip], atm->p[ip]));
3333 SET_ATM(qnt_ho2, clim_zm(&clim->ho2, atm->time[ip],
3334 atm->lat[ip], atm->p[ip]));
3335 SET_ATM(qnt_o1d, clim_zm(&clim->o1d, atm->time[ip],
3336 atm->lat[ip], atm->p[ip]));
3337 SET_ATM(qnt_vh, sqrt(u * u + v * v));
3338 SET_ATM(qnt_vz, -1e3 * H0 / atm->p[ip] * w);
3339 SET_ATM(qnt_psat, PSAT(t));
3340 SET_ATM(qnt_psice, PSICE(t));
3341 SET_ATM(qnt_pw, PW(atm->p[ip], h2o));
3342 SET_ATM(qnt_sh, SH(h2o));
3343 SET_ATM(qnt_rh, RH(atm->p[ip], t, h2o));
3344 SET_ATM(qnt_rhice, RHICE(atm->p[ip], t, h2o));
3345 SET_ATM(qnt_theta, THETA(atm->p[ip], t));
3346 SET_ATM(qnt_zeta, atm->q[ctl->qnt_zeta][ip]);
3347 SET_ATM(qnt_zeta_d, ZETA(ps, atm->p[ip], t));
3348 SET_ATM(qnt_zeta_dot, atm->q[ctl->qnt_zeta_dot][ip]);
3349 SET_ATM(qnt_tvirt, TVIRT(t, h2o));
3350 SET_ATM(qnt_lapse, lapse_rate(t, h2o));
3351 SET_ATM(qnt_pv, pv);
3352 SET_ATM(qnt_tdew, TDEW(atm->p[ip], h2o));
3353 SET_ATM(qnt_tice, TICE(atm->p[ip], h2o));
3354 SET_ATM(qnt_tnat,
3355 nat_temperature(atm->p[ip], h2o,
3356 clim_zm(&clim->hno3, atm->time[ip],
3357 atm->lat[ip], atm->p[ip])));
3358 SET_ATM(qnt_tsts,
3359 0.5 * (atm->q[ctl->qnt_tice][ip] + atm->q[ctl->qnt_tnat][ip]));
3360 }
3361}
double nat_temperature(const double p, const double h2o, const double hno3)
Calculates the nitric acid trihydrate (NAT) temperature.
Definition: mptrac.c:6019
double lapse_rate(const double t, const double h2o)
Calculates the moist adiabatic lapse rate in Kelvin per kilometer.
Definition: mptrac.c:1763
#define H0
Scale height [km].
Definition: mptrac.h:204
#define PSICE(t)
Compute saturation pressure over ice (WMO, 2018).
Definition: mptrac.h:1550
#define TICE(p, h2o)
Calculate frost point temperature (WMO, 2018).
Definition: mptrac.h:1818
#define RHICE(p, t, h2o)
Compute relative humidity over ice.
Definition: mptrac.h:1654
#define INTPOL_TIME_ALL(time, p, lon, lat)
Interpolate multiple meteorological variables in time.
Definition: mptrac.h:984
#define RH(p, t, h2o)
Compute relative humidity over water.
Definition: mptrac.h:1624
#define TDEW(p, h2o)
Calculate dew point temperature.
Definition: mptrac.h:1793
#define PSAT(t)
Compute saturation pressure over water.
Definition: mptrac.h:1526
clim_zm_t hno3
HNO3 zonal means.
Definition: mptrac.h:3610
int qnt_tnat
Quantity array index for T_NAT.
Definition: mptrac.h:2603
int qnt_tice
Quantity array index for T_ice.
Definition: mptrac.h:2597
int qnt_zeta_dot
Quantity array index forvelocity of zeta vertical coordinate.
Definition: mptrac.h:2576
int qnt_tsts
Quantity array index for T_STS.
Definition: mptrac.h:2600
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 3365 of file mptrac.c.

3369 {
3370
3371 /* Set timer... */
3372 SELECT_TIMER("MODULE_MIXING", "PHYSICS", NVTX_GPU);
3373
3374 /* Allocate... */
3375 const int np = atm->np;
3376 int *restrict const ixs = (int *) malloc((size_t) np * sizeof(int));
3377 int *restrict const iys = (int *) malloc((size_t) np * sizeof(int));
3378 int *restrict const izs = (int *) malloc((size_t) np * sizeof(int));
3379
3380 /* Set grid box size... */
3381 const double dz = (ctl->mixing_z1 - ctl->mixing_z0) / ctl->mixing_nz;
3382 const double dlon = (ctl->mixing_lon1 - ctl->mixing_lon0) / ctl->mixing_nx;
3383 const double dlat = (ctl->mixing_lat1 - ctl->mixing_lat0) / ctl->mixing_ny;
3384
3385 /* Set time interval... */
3386 const double t0 = t - 0.5 * ctl->dt_mod;
3387 const double t1 = t + 0.5 * ctl->dt_mod;
3388
3389 /* Get indices... */
3390#ifdef _OPENACC
3391#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
3392#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
3393#pragma acc parallel loop independent gang vector
3394#else
3395#pragma omp parallel for default(shared)
3396#endif
3397 for (int ip = 0; ip < np; ip++) {
3398 ixs[ip] = (int) ((atm->lon[ip] - ctl->mixing_lon0) / dlon);
3399 iys[ip] = (int) ((atm->lat[ip] - ctl->mixing_lat0) / dlat);
3400 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->mixing_z0) / dz);
3401 if (atm->time[ip] < t0 || atm->time[ip] > t1
3402 || ixs[ip] < 0 || ixs[ip] >= ctl->mixing_nx
3403 || iys[ip] < 0 || iys[ip] >= ctl->mixing_ny
3404 || izs[ip] < 0 || izs[ip] >= ctl->mixing_nz)
3405 izs[ip] = -1;
3406 }
3407
3408 /* Calculate interparcel mixing... */
3409 const int use_ensemble = (ctl->nens > 0);
3410
3411 const int quantities[] = {
3412 ctl->qnt_m, ctl->qnt_vmr, ctl->qnt_Ch2o, ctl->qnt_Co3,
3413 ctl->qnt_Cco, ctl->qnt_Coh, ctl->qnt_Ch, ctl->qnt_Cho2,
3414 ctl->qnt_Ch2o2, ctl->qnt_Co1d, ctl->qnt_Co3p, ctl->qnt_Cccl4,
3415 ctl->qnt_Cccl3f, ctl->qnt_Cccl2f2, ctl->qnt_Cn2o,
3416 ctl->qnt_Csf6, ctl->qnt_aoa
3417 };
3418 const int n_qnt = sizeof(quantities) / sizeof(quantities[0]);
3419
3420 for (int i = 0; i < n_qnt; i++)
3421 if (quantities[i] >= 0)
3422 module_mixing_help(ctl, clim, atm, ixs, iys, izs, quantities[i],
3423 use_ensemble);
3424
3425 /* Free... */
3426#ifdef _OPENACC
3427#pragma acc exit data delete(ixs,iys,izs)
3428#endif
3429 free(ixs);
3430 free(iys);
3431 free(izs);
3432}
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, const int use_ensemble)
Perform subgrid-scale interparcel mixing of a given quantity.
Definition: mptrac.c:3436
int qnt_Coh
Quantity array index for OH volume mixing ratio (chemistry code).
Definition: mptrac.h:2618
int mixing_nx
Number of longitudes of mixing grid.
Definition: mptrac.h:3013
double mixing_z1
Upper altitude of mixing grid [km].
Definition: mptrac.h:3010
int qnt_Co1d
Quantity array index for O(1D) volume mixing ratio (chemistry code).
Definition: mptrac.h:2630
double mixing_z0
Lower altitude of mixing grid [km].
Definition: mptrac.h:3007
int qnt_Cco
Quantity array index for CO volume mixing ratio (chemistry code).
Definition: mptrac.h:2615
int mixing_ny
Number of latitudes of mixing grid.
Definition: mptrac.h:3022
int qnt_Ch
Quantity array index for H volume mixing ratio (chemistry code).
Definition: mptrac.h:2621
double mixing_lat0
Lower latitude of mixing grid [deg].
Definition: mptrac.h:3025
int qnt_Cho2
Quantity array index for HO2 volume mixing ratio (chemistry code).
Definition: mptrac.h:2624
int mixing_nz
Number of altitudes of mixing grid.
Definition: mptrac.h:3004
double mixing_lon0
Lower longitude of mixing grid [deg].
Definition: mptrac.h:3016
double mixing_lat1
Upper latitude of mixing grid [deg].
Definition: mptrac.h:3028
int qnt_Co3p
Quantity array index for O(3P) volume mixing ratio (chemistry code).
Definition: mptrac.h:2633
int qnt_Ch2o2
Quantity array index for H2O2 volume mixing ratio (chemistry code).
Definition: mptrac.h:2627
double mixing_lon1
Upper longitude of mixing grid [deg].
Definition: mptrac.h:3019
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,
const int  use_ensemble 
)

Perform subgrid-scale interparcel mixing of a given quantity.

This function computes the average of a specified quantity within each subgrid box (and optionally for each ensemble member) and applies a mixing adjustment to particle values based on the computed local mean.

The mixing accounts for differences in tropopause and stratosphere mixing via a weighted parameterization. It supports both ensemble and non-ensemble modes using the use_ensemble flag.

Parameters
[in]ctlPointer to control/configuration structure.
[in]climPointer to climatological data structure.
[in,out]atmPointer to atmospheric state (includes particles).
[in]ixsArray of x-grid indices for each particle.
[in]iysArray of y-grid indices for each particle.
[in]izsArray of z-grid indices for each particle (-1 for invalid).
[in]qnt_idxIndex of the quantity in atm->q to be mixed.
[in]use_ensembleFlag indicating whether to use ensemble-aware logic (0 = no, 1 = yes).
Note
Particles with izs[ip] < 0 are excluded from mixing.
Uses OpenACC or OpenMP for parallelism depending on compilation options.
Requires ctl->qnt_ens to be valid if use_ensemble is true.
Authors
Mingzhao Liu
Lars Hoffmann

Definition at line 3436 of file mptrac.c.

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

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

3626 {
3627
3628 /* Set timer... */
3629 SELECT_TIMER("MODULE_POSITION", "PHYSICS", NVTX_GPU);
3630
3631 /* Loop over particles... */
3632 PARTICLE_LOOP(0, atm->np, 1, "acc data present(cache,met0,met1,atm)") {
3633
3634 /* Init... */
3635 double ps;
3637
3638 /* Calculate modulo... */
3639 atm->lon[ip] = FMOD(atm->lon[ip], 360.);
3640 atm->lat[ip] = FMOD(atm->lat[ip], 360.);
3641
3642 /* Check latitude... */
3643 while (atm->lat[ip] < -90 || atm->lat[ip] > 90) {
3644 if (atm->lat[ip] > 90) {
3645 atm->lat[ip] = 180 - atm->lat[ip];
3646 atm->lon[ip] += 180;
3647 }
3648 if (atm->lat[ip] < -90) {
3649 atm->lat[ip] = -180 - atm->lat[ip];
3650 atm->lon[ip] += 180;
3651 }
3652 }
3653
3654 /* Check longitude... */
3655 while (atm->lon[ip] < -180)
3656 atm->lon[ip] += 360;
3657 while (atm->lon[ip] >= 180)
3658 atm->lon[ip] -= 360;
3659
3660 /* Check pressure... */
3661 if (atm->p[ip] < met0->p[met0->np - 1]) {
3662 atm->p[ip] = met0->p[met0->np - 1];
3663 } else if (atm->p[ip] > 300.) {
3664 INTPOL_2D(ps, 1);
3665 if (atm->p[ip] > ps)
3666 atm->p[ip] = ps;
3667 }
3668 }
3669}

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

3674 {
3675
3676 /* Initialize GSL random number generators... */
3677 gsl_rng_env_setup();
3678 if (omp_get_max_threads() > NTHREADS)
3679 ERRMSG("Too many threads!");
3680 for (int i = 0; i < NTHREADS; i++) {
3681 rng[i] = gsl_rng_alloc(gsl_rng_default);
3682 gsl_rng_set(rng[i], gsl_rng_default_seed
3683 + (long unsigned) (ntask * NTHREADS + i));
3684 }
3685
3686 /* Initialize cuRAND random number generators... */
3687#ifdef CURAND
3688 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
3689 CURAND_STATUS_SUCCESS)
3690 ERRMSG("Cannot create random number generator!");
3691 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
3692 CURAND_STATUS_SUCCESS)
3693 ERRMSG("Cannot set seed for random number generator!");
3694 if (curandSetStream
3695 (rng_curand,
3696 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
3697 CURAND_STATUS_SUCCESS)
3698 ERRMSG("Cannot set stream for random number generator!");
3699#endif
3700}
#define NTHREADS
Maximum number of OpenMP threads.
Definition: mptrac.h:344

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

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

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

3814 {
3815
3816 /* Set timer... */
3817 SELECT_TIMER("MODULE_SEDI", "PHYSICS", NVTX_GPU);
3818
3819 /* Loop over particles... */
3820 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
3821
3822 /* Get temperature... */
3823 double t;
3825 INTPOL_3D(t, 1);
3826
3827 /* Sedimentation velocity... */
3828 const double v_s = sedi(atm->p[ip], t, atm->q[ctl->qnt_rp][ip],
3829 atm->q[ctl->qnt_rhop][ip]);
3830
3831 /* Calculate pressure change... */
3832 atm->p[ip] += DZ2DP(v_s * cache->dt[ip] / 1000., atm->p[ip]);
3833 }
3834}
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 3838 of file mptrac.c.

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

3901 {
3902
3903 /* Allocate... */
3904 double *restrict const help =
3905 (double *) malloc((size_t) np * sizeof(double));
3906
3907 /* Reordering of array... */
3908#ifdef _OPENACC
3909#pragma acc enter data create(help[0:np])
3910#pragma acc data present(a,p,help)
3911#pragma acc parallel loop independent gang vector
3912#else
3913#pragma omp parallel for default(shared)
3914#endif
3915 for (int ip = 0; ip < np; ip++)
3916 help[ip] = a[p[ip]];
3917#ifdef _OPENACC
3918#pragma acc parallel loop independent gang vector
3919#else
3920#pragma omp parallel for default(shared)
3921#endif
3922 for (int ip = 0; ip < np; ip++)
3923 a[ip] = help[ip];
3924
3925 /* Free... */
3926#ifdef _OPENACC
3927#pragma acc exit data delete(help)
3928#endif
3929 free(help);
3930}

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

3939 {
3940
3941 /* Set timer... */
3942 SELECT_TIMER("MODULE_TIMESTEPS", "PHYSICS", NVTX_GPU);
3943
3944 const double latmin = gsl_stats_min(met0->lat, 1, (size_t) met0->ny),
3945 latmax = gsl_stats_max(met0->lat, 1, (size_t) met0->ny);
3946
3947 const int local =
3948 (fabs(met0->lon[met0->nx - 1] - met0->lon[0] - 360.0) >= 0.01);
3949
3950 /* Loop over particles... */
3951 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,cache,met0,atm)") {
3952
3953 /* Set time step for each air parcel... */
3954 if ((ctl->direction * (atm->time[ip] - ctl->t_start) >= 0
3955 && ctl->direction * (atm->time[ip] - ctl->t_stop) <= 0
3956 && ctl->direction * (atm->time[ip] - t) < 0))
3957 cache->dt[ip] = t - atm->time[ip];
3958 else
3959 cache->dt[ip] = 0.0;
3960
3961 /* Check horizontal boundaries of local meteo data... */
3962#ifndef DD
3963 if (local && (atm->lon[ip] <= met0->lon[0]
3964 || atm->lon[ip] >= met0->lon[met0->nx - 1]
3965 || atm->lat[ip] <= latmin || atm->lat[ip] >= latmax))
3966 cache->dt[ip] = 0.0;
3967#else
3968 if ((int) atm->q[ctl->qnt_subdomain][ip] == -1)
3969 cache->dt[ip] = 0;
3970#endif
3971 }
3972}
int direction
Direction flag (1=forward calculation, -1=backward calculation).
Definition: mptrac.h:2660
double t_stop
Stop time of simulation [s].
Definition: mptrac.h:2666
int qnt_subdomain
Quantity array index for current subdomain in domain decomposition.
Definition: mptrac.h:2654
double t_start
Start time of simulation [s].
Definition: mptrac.h:2663

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

3978 {
3979
3980 /* Set timer... */
3981 SELECT_TIMER("MODULE_TIMESTEPS_INIT", "PHYSICS", NVTX_GPU);
3982
3983 /* Set start time... */
3984 if (ctl->direction == 1) {
3985 ctl->t_start = gsl_stats_min(atm->time, 1, (size_t) atm->np);
3986 if (ctl->t_stop > 1e99)
3987 ctl->t_stop = gsl_stats_max(atm->time, 1, (size_t) atm->np);
3988 } else {
3989 ctl->t_start = gsl_stats_max(atm->time, 1, (size_t) atm->np);
3990 if (ctl->t_stop > 1e99)
3991 ctl->t_stop = gsl_stats_min(atm->time, 1, (size_t) atm->np);
3992 }
3993
3994 /* Check time interval... */
3995 if (ctl->direction * (ctl->t_stop - ctl->t_start) <= 0)
3996 ERRMSG("Nothing to do! Check T_STOP and DIRECTION!");
3997
3998 /* Round start time... */
3999 if (ctl->direction == 1)
4000 ctl->t_start = floor(ctl->t_start / ctl->dt_mod) * ctl->dt_mod;
4001 else
4002 ctl->t_start = ceil(ctl->t_start / ctl->dt_mod) * ctl->dt_mod;
4003}

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

4013 {
4014
4015 /* Set timer... */
4016 SELECT_TIMER("MODULE_TRACER_CHEM", "PHYSICS", NVTX_GPU);
4017
4018 /* Loop over particles... */
4019 PARTICLE_LOOP(0, atm->np, 1,
4020 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4021
4022 /* Get temperature... */
4023 double t;
4025 INTPOL_3D(t, 1);
4026
4027 /* Get molecular density... */
4028 const double M = MOLEC_DENS(atm->p[ip], t);
4029
4030 /* Get total column ozone... */
4031 double o3c;
4032 INTPOL_2D(o3c, 1);
4033
4034 /* Get solar zenith angle... */
4035 const double sza = sza_calc(atm->time[ip], atm->lon[ip], atm->lat[ip]);
4036
4037 /* Get O(1D) volume mixing ratio... */
4038 const double o1d =
4039 clim_zm(&clim->o1d, atm->time[ip], atm->lat[ip], atm->p[ip]);
4040
4041 /* Reactions for CFC-10... */
4042 if (ctl->qnt_Cccl4 >= 0) {
4043 const double K_o1d = ARRHENIUS(3.30e-10, 0, t) * o1d * M;
4044 const double K_hv = clim_photo(clim->photo.ccl4, &(clim->photo),
4045 atm->p[ip], sza, o3c);
4046 atm->q[ctl->qnt_Cccl4][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4047 }
4048
4049 /* Reactions for CFC-11... */
4050 if (ctl->qnt_Cccl3f >= 0) {
4051 const double K_o1d = ARRHENIUS(2.30e-10, 0, t) * o1d * M;
4052 const double K_hv = clim_photo(clim->photo.ccl3f, &(clim->photo),
4053 atm->p[ip], sza, o3c);
4054 atm->q[ctl->qnt_Cccl3f][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4055 }
4056
4057 /* Reactions for CFC-12... */
4058 if (ctl->qnt_Cccl2f2 >= 0) {
4059 const double K_o1d = ARRHENIUS(1.40e-10, -25, t) * o1d * M;
4060 const double K_hv = clim_photo(clim->photo.ccl2f2, &(clim->photo),
4061 atm->p[ip], sza, o3c);
4062 atm->q[ctl->qnt_Cccl2f2][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4063 }
4064
4065 /* Reactions for N2O... */
4066 if (ctl->qnt_Cn2o >= 0) {
4067 const double K_o1d = ARRHENIUS(1.19e-10, -20, t) * o1d * M;
4068 const double K_hv = clim_photo(clim->photo.n2o, &(clim->photo),
4069 atm->p[ip], sza, o3c);
4070 atm->q[ctl->qnt_Cn2o][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4071 }
4072 }
4073}
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:484
double ccl2f2[CP][CSZA][CO3]
CCl2F2 photolysis rate [1/s].
Definition: mptrac.h:3511
double ccl3f[CP][CSZA][CO3]
CCl3F photolysis rate [1/s].
Definition: mptrac.h:3508
double n2o[CP][CSZA][CO3]
N2O photolysis rate [1/s].
Definition: mptrac.h:3502
double ccl4[CP][CSZA][CO3]
CCl4 photolysis rate [1/s].
Definition: mptrac.h:3505
clim_photo_t photo
Photolysis rates.
Definition: mptrac.h:3607
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 4077 of file mptrac.c.

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

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

4218 {
4219
4220 /* Initialize GPU... */
4221#ifdef _OPENACC
4222 SELECT_TIMER("ACC_INIT", "INIT", NVTX_GPU);
4223 int rank = 0;
4224#ifdef MPI
4225 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
4226#endif
4227 if (acc_get_num_devices(acc_device_nvidia) <= 0)
4228 ERRMSG("Not running on a GPU device!");
4229 acc_set_device_num(rank % acc_get_num_devices(acc_device_nvidia),
4230 acc_device_nvidia);
4231 acc_device_t device_type = acc_get_device_type();
4232 acc_init(device_type);
4233#endif
4234
4235 /* Allocate... */
4236 SELECT_TIMER("ALLOC", "MEMORY", NVTX_CPU);
4237 ALLOC(*ctl, ctl_t, 1);
4238 ALLOC(*cache, cache_t, 1);
4239 ALLOC(*clim, clim_t, 1);
4240 ALLOC(*met0, met_t, 1);
4241 ALLOC(*met1, met_t, 1);
4242 ALLOC(*atm, atm_t, 1);
4243
4244 /* Create data region on GPU... */
4245#ifdef _OPENACC
4246 SELECT_TIMER("CREATE_DATA_REGION", "MEMORY", NVTX_GPU);
4247 ctl_t *ctlup = *ctl;
4248 cache_t *cacheup = *cache;
4249 clim_t *climup = *clim;
4250 met_t *met0up = *met0;
4251 met_t *met1up = *met1;
4252 atm_t *atmup = *atm;
4253#pragma acc enter data create(ctlup[:1],cacheup[:1],climup[:1],met0up[:1],met1up[:1],atmup[:1])
4254#endif
4255}
Air parcel data.
Definition: mptrac.h:3371
Cache data structure.
Definition: mptrac.h:3449
Climatological data.
Definition: mptrac.h:3589
Control parameters.
Definition: mptrac.h:2356
Meteo data structure.
Definition: mptrac.h:3648

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

4275 {
4276#endif
4277
4278 /* Delete data region on GPU... */
4279#ifdef _OPENACC
4280 SELECT_TIMER("DELETE_DATA_REGION", "MEMORY", NVTX_GPU);
4281#pragma acc exit data delete (ctl,cache,clim,met0,met1,atm)
4282#endif
4283
4284 /* Free... */
4285 SELECT_TIMER("FREE", "MEMORY", NVTX_CPU);
4286 free(atm);
4287 free(ctl);
4288 free(cache);
4289 free(clim);
4290 free(met0);
4291 free(met1);
4292
4293 /* Free MPI datatype... */
4294#ifdef DD
4295 MPI_Type_free(&mpi_info->MPI_Particle);
4296#endif
4297}

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

4306 {
4307
4308 static int init;
4309
4310 met_t *mets;
4311
4312 char cachefile[LEN], cmd[2 * LEN], filename[LEN];
4313
4314 /* Set timer... */
4315 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4316
4317 /* Init... */
4318 if (t == ctl->t_start || !init) {
4319 init = 1;
4320
4321 /* Read meteo data... */
4322 get_met_help(ctl, t + (ctl->direction == -1 ? -1 : 0), -1,
4323 ctl->metbase, ctl->dt_met, filename);
4324 if (!mptrac_read_met(filename, ctl, clim, *met0))
4325 ERRMSG("Cannot open file!");
4326
4327 get_met_help(ctl, t + (ctl->direction == 1 ? 1 : 0), 1,
4328 ctl->metbase, ctl->dt_met, filename);
4329 if (!mptrac_read_met(filename, ctl, clim, *met1))
4330 ERRMSG("Cannot open file!");
4331
4332 /* Update GPU... */
4333 mptrac_update_device(NULL, NULL, NULL, met0, met1, NULL);
4334 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4335
4336 /* Caching... */
4337 if (ctl->met_cache && t != ctl->t_stop) {
4338 get_met_help(ctl, t + 1.1 * ctl->dt_met * ctl->direction,
4339 ctl->direction, ctl->metbase, ctl->dt_met, cachefile);
4340 sprintf(cmd, "cat %s > /dev/null &", cachefile);
4341 LOG(1, "Caching: %s", cachefile);
4342 if (system(cmd) != 0)
4343 WARN("Caching command failed!");
4344 }
4345 }
4346
4347 /* Read new data for forward trajectories... */
4348 if (t > (*met1)->time) {
4349
4350 /* Pointer swap... */
4351 mets = *met1;
4352 *met1 = *met0;
4353 *met0 = mets;
4354
4355 /* Read new meteo data... */
4356 get_met_help(ctl, t, 1, ctl->metbase, ctl->dt_met, filename);
4357 if (!mptrac_read_met(filename, ctl, clim, *met1))
4358 ERRMSG("Cannot open file!");
4359
4360 /* Update GPU... */
4361 mptrac_update_device(NULL, NULL, NULL, NULL, met1, NULL);
4362 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4363
4364 /* Caching... */
4365 if (ctl->met_cache && t != ctl->t_stop) {
4366 get_met_help(ctl, t + ctl->dt_met, 1, ctl->metbase, ctl->dt_met,
4367 cachefile);
4368 sprintf(cmd, "cat %s > /dev/null &", cachefile);
4369 LOG(1, "Caching: %s", cachefile);
4370 if (system(cmd) != 0)
4371 WARN("Caching command failed!");
4372 }
4373 }
4374
4375 /* Read new data for backward trajectories... */
4376 if (t < (*met0)->time) {
4377
4378 /* Pointer swap... */
4379 mets = *met1;
4380 *met1 = *met0;
4381 *met0 = mets;
4382
4383 /* Read new meteo data... */
4384 get_met_help(ctl, t, -1, ctl->metbase, ctl->dt_met, filename);
4385 if (!mptrac_read_met(filename, ctl, clim, *met0))
4386 ERRMSG("Cannot open file!");
4387
4388 /* Update GPU... */
4389 mptrac_update_device(NULL, NULL, NULL, met0, NULL, NULL);
4390 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4391
4392 /* Caching... */
4393 if (ctl->met_cache && t != ctl->t_stop) {
4394 get_met_help(ctl, t - ctl->dt_met, -1, ctl->metbase, ctl->dt_met,
4395 cachefile);
4396 sprintf(cmd, "cat %s > /dev/null &", cachefile);
4397 LOG(1, "Caching: %s", cachefile);
4398 if (system(cmd) != 0)
4399 WARN("Caching command failed!");
4400 }
4401 }
4402
4403 /* Check that grids are consistent... */
4404 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
4405 if ((*met0)->nx != (*met1)->nx
4406 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
4407 ERRMSG("Meteo grid dimensions do not match!");
4408 for (int ix = 0; ix < (*met0)->nx; ix++)
4409 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
4410 ERRMSG("Meteo grid longitudes do not match!");
4411 for (int iy = 0; iy < (*met0)->ny; iy++)
4412 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
4413 ERRMSG("Meteo grid latitudes do not match!");
4414 for (int ip = 0; ip < (*met0)->np; ip++)
4415 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
4416 ERRMSG("Meteo grid pressure levels do not match!");
4417 }
4418}
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:5445
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:1012
int met_cache
Preload meteo data into disk cache (0=no, 1=yes).
Definition: mptrac.h:2839
char metbase[LEN]
Basename for meteo data.
Definition: mptrac.h:2676
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 4422 of file mptrac.c.

4427 {
4428
4429 /* Initialize timesteps... */
4430 module_timesteps_init(ctl, atm);
4431
4432 /* Initialize random number generator... */
4433 module_rng_init(ntask);
4434
4435 /* Update GPU memory... */
4436 mptrac_update_device(ctl, cache, clim, NULL, NULL, atm);
4437}
void module_timesteps_init(ctl_t *ctl, const atm_t *atm)
Initialize start time and time interval for time-stepping.
Definition: mptrac.c:3976
void module_rng_init(const int ntask)
Initialize random number generators for parallel tasks.
Definition: mptrac.c:3673
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 4441 of file mptrac.c.

4444 {
4445
4446 int result;
4447
4448 /* Set timer... */
4449 SELECT_TIMER("READ_ATM", "INPUT", NVTX_READ);
4450
4451 /* Init... */
4452 atm->np = 0;
4453
4454 /* Write info... */
4455 LOG(1, "Read atmospheric data: %s", filename);
4456
4457 /* Read ASCII data... */
4458 if (ctl->atm_type == 0)
4459 result = read_atm_asc(filename, ctl, atm);
4460
4461 /* Read binary data... */
4462 else if (ctl->atm_type == 1)
4463 result = read_atm_bin(filename, ctl, atm);
4464
4465 /* Read netCDF data... */
4466 else if (ctl->atm_type == 2)
4467 result = read_atm_nc(filename, ctl, atm);
4468
4469 /* Read CLaMS data... */
4470 else if (ctl->atm_type == 3 || ctl->atm_type == 4)
4471 result = read_atm_clams(filename, ctl, atm);
4472
4473 /* Error... */
4474 else
4475 ERRMSG("Atmospheric data type not supported!");
4476
4477 /* Check result... */
4478 if (result != 1)
4479 return 0;
4480
4481 /* Check number of air parcels... */
4482 if (atm->np < 1)
4483 ERRMSG("Can not read any data!");
4484
4485 /* Write info... */
4486 double mini, maxi;
4487 LOG(2, "Number of particles: %d", atm->np);
4488 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
4489 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
4490 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
4491 LOG(2, "Altitude range: %g ... %g km", Z(maxi), Z(mini));
4492 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
4493 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
4494 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
4495 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
4496 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
4497 for (int iq = 0; iq < ctl->nq; iq++) {
4498 char msg[5 * LEN];
4499 sprintf(msg, "Quantity %s range: %s ... %s %s",
4500 ctl->qnt_name[iq], ctl->qnt_format[iq],
4501 ctl->qnt_format[iq], ctl->qnt_unit[iq]);
4502 gsl_stats_minmax(&mini, &maxi, atm->q[iq], 1, (size_t) atm->np);
4503 LOG(2, msg, mini, maxi);
4504 }
4505
4506 /* Return success... */
4507 return 1;
4508}
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:6223
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:6107
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:6163
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:6065
char qnt_format[NQ][LEN]
Quantity output format.
Definition: mptrac.h:2375
int atm_type
Type of atmospheric data files (0=ASCII, 1=binary, 2=netCDF, 3=CLaMS_traj, 4=CLaMS_pos).
Definition: mptrac.h:3141
char qnt_unit[NQ][LEN]
Quantity units.
Definition: mptrac.h:2372
char qnt_name[NQ][LEN]
Quantity names.
Definition: mptrac.h:2366
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 4512 of file mptrac.c.

4514 {
4515
4516 /* Set timer... */
4517 SELECT_TIMER("READ_CLIM", "INPUT", NVTX_READ);
4518
4519 /* Init tropopause climatology... */
4520 clim_tropo_init(clim);
4521
4522 /* Read photolysis rates... */
4523 if (ctl->clim_photo[0] != '-')
4524 read_clim_photo(ctl->clim_photo, &clim->photo);
4525
4526 /* Read HNO3 climatology... */
4527 if (ctl->clim_hno3_filename[0] != '-')
4528 read_clim_zm(ctl->clim_hno3_filename, "HNO3", &clim->hno3);
4529
4530 /* Read OH climatology... */
4531 if (ctl->clim_oh_filename[0] != '-') {
4532 read_clim_zm(ctl->clim_oh_filename, "OH", &clim->oh);
4533 if (ctl->oh_chem_beta > 0)
4534 clim_oh_diurnal_correction(ctl, clim);
4535 }
4536
4537 /* Read H2O2 climatology... */
4538 if (ctl->clim_h2o2_filename[0] != '-')
4539 read_clim_zm(ctl->clim_h2o2_filename, "H2O2", &clim->h2o2);
4540
4541 /* Read HO2 climatology... */
4542 if (ctl->clim_ho2_filename[0] != '-')
4543 read_clim_zm(ctl->clim_ho2_filename, "HO2", &clim->ho2);
4544
4545 /* Read O(1D) climatology... */
4546 if (ctl->clim_o1d_filename[0] != '-')
4547 read_clim_zm(ctl->clim_o1d_filename, "O1D", &clim->o1d);
4548
4549 /* Read CFC-10 time series... */
4550 if (ctl->clim_ccl4_timeseries[0] != '-')
4552
4553 /* Read CFC-11 time series... */
4554 if (ctl->clim_ccl3f_timeseries[0] != '-')
4556
4557 /* Read CFC-12 time series... */
4558 if (ctl->clim_ccl2f2_timeseries[0] != '-')
4560
4561 /* Read N2O time series... */
4562 if (ctl->clim_n2o_timeseries[0] != '-')
4563 read_clim_ts(ctl->clim_n2o_timeseries, &clim->n2o);
4564
4565 /* Read SF6 time series... */
4566 if (ctl->clim_sf6_timeseries[0] != '-')
4567 read_clim_ts(ctl->clim_sf6_timeseries, &clim->sf6);
4568}
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:6256
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:6375
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:6429
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:2971
char clim_o1d_filename[LEN]
Filename of O(1D) climatology.
Definition: mptrac.h:2974
char clim_photo[LEN]
Filename of photolysis rates climatology.
Definition: mptrac.h:2959
char clim_h2o2_filename[LEN]
Filename of H2O2 climatology.
Definition: mptrac.h:2968
char clim_oh_filename[LEN]
Filename of OH climatology.
Definition: mptrac.h:2965
char clim_hno3_filename[LEN]
Filename of HNO3 climatology.
Definition: mptrac.h:2962
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 4572 of file mptrac.c.

4576 {
4577
4578 /* Set timer... */
4579 SELECT_TIMER("READ_CTL", "INPUT", NVTX_READ);
4580
4581 /* Write info... */
4582 LOG(1, "\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
4583 "(executable: %s | version: %s | compiled: %s, %s)\n",
4584 argv[0], VERSION, __DATE__, __TIME__);
4585
4586 /* Initialize quantity indices... */
4587 ctl->qnt_idx = -1;
4588 ctl->qnt_ens = -1;
4589 ctl->qnt_stat = -1;
4590 ctl->qnt_m = -1;
4591 ctl->qnt_vmr = -1;
4592 ctl->qnt_rp = -1;
4593 ctl->qnt_rhop = -1;
4594 ctl->qnt_ps = -1;
4595 ctl->qnt_ts = -1;
4596 ctl->qnt_zs = -1;
4597 ctl->qnt_us = -1;
4598 ctl->qnt_vs = -1;
4599 ctl->qnt_ess = -1;
4600 ctl->qnt_nss = -1;
4601 ctl->qnt_shf = -1;
4602 ctl->qnt_lsm = -1;
4603 ctl->qnt_sst = -1;
4604 ctl->qnt_pbl = -1;
4605 ctl->qnt_pt = -1;
4606 ctl->qnt_tt = -1;
4607 ctl->qnt_zt = -1;
4608 ctl->qnt_h2ot = -1;
4609 ctl->qnt_zg = -1;
4610 ctl->qnt_p = -1;
4611 ctl->qnt_t = -1;
4612 ctl->qnt_rho = -1;
4613 ctl->qnt_u = -1;
4614 ctl->qnt_v = -1;
4615 ctl->qnt_w = -1;
4616 ctl->qnt_h2o = -1;
4617 ctl->qnt_o3 = -1;
4618 ctl->qnt_lwc = -1;
4619 ctl->qnt_rwc = -1;
4620 ctl->qnt_iwc = -1;
4621 ctl->qnt_swc = -1;
4622 ctl->qnt_cc = -1;
4623 ctl->qnt_pct = -1;
4624 ctl->qnt_pcb = -1;
4625 ctl->qnt_cl = -1;
4626 ctl->qnt_plcl = -1;
4627 ctl->qnt_plfc = -1;
4628 ctl->qnt_pel = -1;
4629 ctl->qnt_cape = -1;
4630 ctl->qnt_cin = -1;
4631 ctl->qnt_o3c = -1;
4632 ctl->qnt_hno3 = -1;
4633 ctl->qnt_oh = -1;
4634 ctl->qnt_h2o2 = -1;
4635 ctl->qnt_ho2 = -1;
4636 ctl->qnt_o1d = -1;
4637 ctl->qnt_mloss_oh = -1;
4638 ctl->qnt_mloss_h2o2 = -1;
4639 ctl->qnt_mloss_kpp = -1;
4640 ctl->qnt_mloss_wet = -1;
4641 ctl->qnt_mloss_dry = -1;
4642 ctl->qnt_mloss_decay = -1;
4643 ctl->qnt_loss_rate = -1;
4644 ctl->qnt_psat = -1;
4645 ctl->qnt_psice = -1;
4646 ctl->qnt_pw = -1;
4647 ctl->qnt_sh = -1;
4648 ctl->qnt_rh = -1;
4649 ctl->qnt_rhice = -1;
4650 ctl->qnt_theta = -1;
4651 ctl->qnt_zeta = -1;
4652 ctl->qnt_zeta_d = -1;
4653 ctl->qnt_zeta_dot = -1;
4654 ctl->qnt_tvirt = -1;
4655 ctl->qnt_lapse = -1;
4656 ctl->qnt_vh = -1;
4657 ctl->qnt_vz = -1;
4658 ctl->qnt_pv = -1;
4659 ctl->qnt_tdew = -1;
4660 ctl->qnt_tice = -1;
4661 ctl->qnt_tsts = -1;
4662 ctl->qnt_tnat = -1;
4663 ctl->qnt_Cx = -1;
4664 ctl->qnt_Ch2o = -1;
4665 ctl->qnt_Co3 = -1;
4666 ctl->qnt_Cco = -1;
4667 ctl->qnt_Coh = -1;
4668 ctl->qnt_Ch = -1;
4669 ctl->qnt_Cho2 = -1;
4670 ctl->qnt_Ch2o2 = -1;
4671 ctl->qnt_Co1d = -1;
4672 ctl->qnt_Co3p = -1;
4673 ctl->qnt_Cccl4 = -1;
4674 ctl->qnt_Cccl3f = -1;
4675 ctl->qnt_Cccl2f2 = -1;
4676 ctl->qnt_Cn2o = -1;
4677 ctl->qnt_Csf6 = -1;
4678 ctl->qnt_aoa = -1;
4679
4680#ifdef DD
4681 ctl->qnt_destination = -1;
4682 ctl->qnt_subdomain = -1;
4683#endif
4684
4685 /* Read quantities... */
4686 ctl->nq = (int) scan_ctl(filename, argc, argv, "NQ", -1, "0", NULL);
4687 if (ctl->nq > NQ)
4688 ERRMSG("Too many quantities!");
4689 for (int iq = 0; iq < ctl->nq; iq++) {
4690
4691 /* Read quantity name and format... */
4692 scan_ctl(filename, argc, argv, "QNT_NAME", iq, "", ctl->qnt_name[iq]);
4693 scan_ctl(filename, argc, argv, "QNT_LONGNAME", iq, ctl->qnt_name[iq],
4694 ctl->qnt_longname[iq]);
4695 scan_ctl(filename, argc, argv, "QNT_FORMAT", iq, "%g",
4696 ctl->qnt_format[iq]);
4697 if (strcasecmp(ctl->qnt_name[iq], "aoa") == 0)
4698 sprintf(ctl->qnt_format[iq], "%%.2f");
4699
4700 /* Try to identify quantity... */
4701 SET_QNT(qnt_idx, "idx", "particle index", "-")
4702 SET_QNT(qnt_ens, "ens", "ensemble index", "-")
4703 SET_QNT(qnt_stat, "stat", "station flag", "-")
4704 SET_QNT(qnt_m, "m", "mass", "kg")
4705 SET_QNT(qnt_vmr, "vmr", "volume mixing ratio", "ppv")
4706 SET_QNT(qnt_rp, "rp", "particle radius", "microns")
4707 SET_QNT(qnt_rhop, "rhop", "particle density", "kg/m^3")
4708 SET_QNT(qnt_ps, "ps", "surface pressure", "hPa")
4709 SET_QNT(qnt_ts, "ts", "surface temperature", "K")
4710 SET_QNT(qnt_zs, "zs", "surface height", "km")
4711 SET_QNT(qnt_us, "us", "surface zonal wind", "m/s")
4712 SET_QNT(qnt_vs, "vs", "surface meridional wind", "m/s")
4713 SET_QNT(qnt_ess, "ess", "eastward turbulent surface stress", "N/m^2")
4714 SET_QNT(qnt_nss, "nss", "northward turbulent surface stress", "N/m^2")
4715 SET_QNT(qnt_shf, "shf", "surface sensible heat flux", "W/m^2")
4716 SET_QNT(qnt_lsm, "lsm", "land-sea mask", "1")
4717 SET_QNT(qnt_sst, "sst", "sea surface temperature", "K")
4718 SET_QNT(qnt_pbl, "pbl", "planetary boundary layer", "hPa")
4719 SET_QNT(qnt_pt, "pt", "tropopause pressure", "hPa")
4720 SET_QNT(qnt_tt, "tt", "tropopause temperature", "K")
4721 SET_QNT(qnt_zt, "zt", "tropopause geopotential height", "km")
4722 SET_QNT(qnt_h2ot, "h2ot", "tropopause water vapor", "ppv")
4723 SET_QNT(qnt_zg, "zg", "geopotential height", "km")
4724 SET_QNT(qnt_p, "p", "pressure", "hPa")
4725 SET_QNT(qnt_t, "t", "temperature", "K")
4726 SET_QNT(qnt_rho, "rho", "air density", "kg/m^3")
4727 SET_QNT(qnt_u, "u", "zonal wind", "m/s")
4728 SET_QNT(qnt_v, "v", "meridional wind", "m/s")
4729 SET_QNT(qnt_w, "w", "vertical velocity", "hPa/s")
4730 SET_QNT(qnt_h2o, "h2o", "water vapor", "ppv")
4731 SET_QNT(qnt_o3, "o3", "ozone", "ppv")
4732 SET_QNT(qnt_lwc, "lwc", "cloud liquid water content", "kg/kg")
4733 SET_QNT(qnt_rwc, "rwc", "cloud rain water content", "kg/kg")
4734 SET_QNT(qnt_iwc, "iwc", "cloud ice water content", "kg/kg")
4735 SET_QNT(qnt_swc, "swc", "cloud snow water content", "kg/kg")
4736 SET_QNT(qnt_cc, "cc", "cloud cover", "1")
4737 SET_QNT(qnt_pct, "pct", "cloud top pressure", "hPa")
4738 SET_QNT(qnt_pcb, "pcb", "cloud bottom pressure", "hPa")
4739 SET_QNT(qnt_cl, "cl", "total column cloud water", "kg/m^2")
4740 SET_QNT(qnt_plcl, "plcl", "lifted condensation level", "hPa")
4741 SET_QNT(qnt_plfc, "plfc", "level of free convection", "hPa")
4742 SET_QNT(qnt_pel, "pel", "equilibrium level", "hPa")
4743 SET_QNT(qnt_cape, "cape", "convective available potential energy",
4744 "J/kg")
4745 SET_QNT(qnt_cin, "cin", "convective inhibition", "J/kg")
4746 SET_QNT(qnt_o3c, "o3c", "total column ozone", "DU")
4747 SET_QNT(qnt_hno3, "hno3", "nitric acid", "ppv")
4748 SET_QNT(qnt_oh, "oh", "hydroxyl radical", "ppv")
4749 SET_QNT(qnt_h2o2, "h2o2", "hydrogen peroxide", "ppv")
4750 SET_QNT(qnt_ho2, "ho2", "hydroperoxyl radical", "ppv")
4751 SET_QNT(qnt_o1d, "o1d", "atomic oxygen", "ppv")
4752 SET_QNT(qnt_mloss_oh, "mloss_oh", "mass loss due to OH chemistry", "kg")
4753 SET_QNT(qnt_mloss_h2o2, "mloss_h2o2",
4754 "mass loss due to H2O2 chemistry", "kg")
4755 SET_QNT(qnt_mloss_kpp, "mloss_kpp", "mass loss due to kpp chemistry",
4756 "kg")
4757 SET_QNT(qnt_mloss_wet, "mloss_wet", "mass loss due to wet deposition",
4758 "kg")
4759 SET_QNT(qnt_mloss_dry, "mloss_dry", "mass loss due to dry deposition",
4760 "kg")
4761 SET_QNT(qnt_mloss_decay, "mloss_decay",
4762 "mass loss due to exponential decay", "kg")
4763 SET_QNT(qnt_loss_rate, "loss_rate", "total loss rate", "s^-1")
4764 SET_QNT(qnt_psat, "psat", "saturation pressure over water", "hPa")
4765 SET_QNT(qnt_psice, "psice", "saturation pressure over ice", "hPa")
4766 SET_QNT(qnt_pw, "pw", "partial water vapor pressure", "hPa")
4767 SET_QNT(qnt_sh, "sh", "specific humidity", "kg/kg")
4768 SET_QNT(qnt_rh, "rh", "relative humidity", "%%")
4769 SET_QNT(qnt_rhice, "rhice", "relative humidity over ice", "%%")
4770 SET_QNT(qnt_theta, "theta", "potential temperature", "K")
4771 SET_QNT(qnt_zeta, "zeta", "zeta coordinate", "K")
4772 SET_QNT(qnt_zeta_d, "zeta_d", "diagnosed zeta coordinate", "K")
4773 SET_QNT(qnt_zeta_dot, "zeta_dot", "velocity of zeta coordinate",
4774 "K/day")
4775 SET_QNT(qnt_tvirt, "tvirt", "virtual temperature", "K")
4776 SET_QNT(qnt_lapse, "lapse", "temperature lapse rate", "K/km")
4777 SET_QNT(qnt_vh, "vh", "horizontal velocity", "m/s")
4778 SET_QNT(qnt_vz, "vz", "vertical velocity", "m/s")
4779 SET_QNT(qnt_pv, "pv", "potential vorticity", "PVU")
4780 SET_QNT(qnt_tdew, "tdew", "dew point temperature", "K")
4781 SET_QNT(qnt_tice, "tice", "frost point temperature", "K")
4782 SET_QNT(qnt_tsts, "tsts", "STS existence temperature", "K")
4783 SET_QNT(qnt_tnat, "tnat", "NAT existence temperature", "K")
4784 SET_QNT(qnt_Cx, "Cx", "Trace species x volume mixing ratio", "ppv")
4785 SET_QNT(qnt_Ch2o, "Ch2o", "H2O volume mixing ratio", "ppv")
4786 SET_QNT(qnt_Co3, "Co3", "O3 volume mixing ratio", "ppv")
4787 SET_QNT(qnt_Cco, "Cco", "CO volume mixing ratio", "ppv")
4788 SET_QNT(qnt_Coh, "Coh", "HO volume mixing ratio", "ppv")
4789 SET_QNT(qnt_Ch, "Ch", "H radical volume mixing ratio", "ppv")
4790 SET_QNT(qnt_Cho2, "Cho2", "HO2 volume mixing ratio", "ppv")
4791 SET_QNT(qnt_Ch2o2, "Ch2o2", "H2O2 volume mixing ratio", "ppv")
4792 SET_QNT(qnt_Co1d, "Co1d", "O(1D) volume mixing ratio", "ppv")
4793 SET_QNT(qnt_Co3p, "Co3p", "O(3P) radical volume mixing ratio", "ppv")
4794 SET_QNT(qnt_Cccl4, "Cccl4", "CCl4 (CFC-10) volume mixing ratio", "ppv")
4795 SET_QNT(qnt_Cccl3f, "Cccl3f", "CCl3F (CFC-11) volume mixing ratio",
4796 "ppv")
4797 SET_QNT(qnt_Cccl2f2, "Cccl2f2", "CCl2F2 (CFC-12) volume mixing ratio",
4798 "ppv")
4799 SET_QNT(qnt_Cn2o, "Cn2o", "N2O volume mixing ratio", "ppv")
4800 SET_QNT(qnt_Csf6, "Csf6", "SF6 volume mixing ratio", "ppv")
4801 SET_QNT(qnt_aoa, "aoa", "age of air", "s")
4802#ifdef DD
4803 SET_QNT(qnt_destination, "destination",
4804 "subdomain index of destination", "-")
4805 SET_QNT(qnt_subdomain, "subdomain", "current subdomain index", "-")
4806#endif
4807 scan_ctl(filename, argc, argv, "QNT_UNIT", iq, "", ctl->qnt_unit[iq]);
4808 }
4809
4810 /* Vertical coordinates and velocities... */
4811 ctl->advect_vert_coord =
4812 (int) scan_ctl(filename, argc, argv, "ADVECT_VERT_COORD", -1, "0", NULL);
4813 if (ctl->advect_vert_coord < 0 || ctl->advect_vert_coord > 2)
4814 ERRMSG("Set ADVECT_VERT_COORD to 0, 1, or 2!");
4815 ctl->met_vert_coord =
4816 (int) scan_ctl(filename, argc, argv, "MET_VERT_COORD", -1, "0", NULL);
4817 if (ctl->met_vert_coord < 0 || ctl->met_vert_coord > 4)
4818 ERRMSG("Set MET_VERT_COORD to 0, 1, 2, 3, or 4!");
4819 if (ctl->advect_vert_coord == 1 && ctl->qnt_zeta < 0)
4820 ERRMSG("Please add zeta to your quantities for diabatic calculations!");
4821 if (ctl->advect_vert_coord == 2 && ctl->met_vert_coord == 0)
4822 ERRMSG
4823 ("Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
4824
4825 /* Time steps of simulation... */
4826 ctl->direction =
4827 (int) scan_ctl(filename, argc, argv, "DIRECTION", -1, "1", NULL);
4828 if (ctl->direction != -1 && ctl->direction != 1)
4829 ERRMSG("Set DIRECTION to -1 or 1!");
4830 ctl->t_stop = scan_ctl(filename, argc, argv, "T_STOP", -1, "1e100", NULL);
4831 ctl->dt_mod = scan_ctl(filename, argc, argv, "DT_MOD", -1, "180", NULL);
4832
4833 /* Meteo data... */
4834 scan_ctl(filename, argc, argv, "METBASE", -1, "-", ctl->metbase);
4835 ctl->dt_met = scan_ctl(filename, argc, argv, "DT_MET", -1, "3600", NULL);
4836 ctl->met_convention =
4837 (int) scan_ctl(filename, argc, argv, "MET_CONVENTION", -1, "0", NULL);
4838 ctl->met_type =
4839 (int) scan_ctl(filename, argc, argv, "MET_TYPE", -1, "0", NULL);
4840 if (ctl->advect_vert_coord == 1 && ctl->met_type != 0)
4841 ERRMSG
4842 ("Please use meteo files in netcdf format for diabatic calculations.");
4843 ctl->met_clams =
4844 (int) scan_ctl(filename, argc, argv, "MET_CLAMS", -1, "0", NULL);
4845 ctl->met_nc_scale =
4846 (int) scan_ctl(filename, argc, argv, "MET_NC_SCALE", -1, "1", NULL);
4847 ctl->met_nc_level =
4848 (int) scan_ctl(filename, argc, argv, "MET_NC_LEVEL", -1, "0", NULL);
4849 ctl->met_nc_quant =
4850 (int) scan_ctl(filename, argc, argv, "MET_NC_QUANT", -1, "0", NULL);
4851 ctl->met_zstd_level =
4852 (int) scan_ctl(filename, argc, argv, "MET_ZSTD_LEVEL", -1, "0", NULL);
4853 for (int i = 0; i < METVAR; i++) {
4854 char defprec[LEN] = "0", deftol[LEN] = "0.0";
4855 if (i == 0) /* geopotential height */
4856 sprintf(deftol, "0.5");
4857 else if (i == 1) /* temperature */
4858 sprintf(deftol, "5.0");
4859 else /* other variables */
4860 sprintf(defprec, "8");
4861 ctl->met_zfp_prec[i] =
4862 (int) scan_ctl(filename, argc, argv, "MET_ZFP_PREC", i, defprec, NULL);
4863 ctl->met_zfp_tol[i] =
4864 scan_ctl(filename, argc, argv, "MET_ZFP_TOL", i, deftol, NULL);
4865 }
4866 ctl->met_cms_batch =
4867 (int) scan_ctl(filename, argc, argv, "MET_CMS_BATCH", -1, "-1", NULL);
4868 ctl->met_cms_zstd =
4869 (int) scan_ctl(filename, argc, argv, "MET_CMS_ZSTD", -1, "1", NULL);
4870 ctl->met_cms_heur =
4871 (int) scan_ctl(filename, argc, argv, "MET_CMS_HEUR", -1, "1", NULL);
4872 ctl->met_cms_eps_z =
4873 scan_ctl(filename, argc, argv, "MET_CMS_EPS_Z", -1, "1.0", NULL);
4874 ctl->met_cms_eps_t =
4875 scan_ctl(filename, argc, argv, "MET_CMS_EPS_T", -1, "0.05", NULL);
4876 ctl->met_cms_eps_u =
4877 scan_ctl(filename, argc, argv, "MET_CMS_EPS_U", -1, "0.05", NULL);
4878 ctl->met_cms_eps_v =
4879 scan_ctl(filename, argc, argv, "MET_CMS_EPS_V", -1, "0.05", NULL);
4880 ctl->met_cms_eps_w =
4881 scan_ctl(filename, argc, argv, "MET_CMS_EPS_W", -1, "1.0", NULL);
4882 ctl->met_cms_eps_pv =
4883 scan_ctl(filename, argc, argv, "MET_CMS_EPS_PV", -1, "1.0", NULL);
4884 ctl->met_cms_eps_h2o =
4885 scan_ctl(filename, argc, argv, "MET_CMS_EPS_H2O", -1, "1.0", NULL);
4886 ctl->met_cms_eps_o3 =
4887 scan_ctl(filename, argc, argv, "MET_CMS_EPS_O3", -1, "1.0", NULL);
4888 ctl->met_cms_eps_lwc =
4889 scan_ctl(filename, argc, argv, "MET_CMS_EPS_LWC", -1, "1.0", NULL);
4890 ctl->met_cms_eps_rwc =
4891 scan_ctl(filename, argc, argv, "MET_CMS_EPS_RWC", -1, "1.0", NULL);
4892 ctl->met_cms_eps_iwc =
4893 scan_ctl(filename, argc, argv, "MET_CMS_EPS_IWC", -1, "1.0", NULL);
4894 ctl->met_cms_eps_swc =
4895 scan_ctl(filename, argc, argv, "MET_CMS_EPS_SWC", -1, "1.0", NULL);
4896 ctl->met_cms_eps_cc =
4897 scan_ctl(filename, argc, argv, "MET_CMS_EPS_CC", -1, "1.0", NULL);
4898 ctl->met_dx = (int) scan_ctl(filename, argc, argv, "MET_DX", -1, "1", NULL);
4899 ctl->met_dy = (int) scan_ctl(filename, argc, argv, "MET_DY", -1, "1", NULL);
4900 ctl->met_dp = (int) scan_ctl(filename, argc, argv, "MET_DP", -1, "1", NULL);
4901 if (ctl->met_dx < 1 || ctl->met_dy < 1 || ctl->met_dp < 1)
4902 ERRMSG("MET_DX, MET_DY, and MET_DP need to be greater than zero!");
4903 ctl->met_sx = (int) scan_ctl(filename, argc, argv, "MET_SX", -1, "1", NULL);
4904 ctl->met_sy = (int) scan_ctl(filename, argc, argv, "MET_SY", -1, "1", NULL);
4905 ctl->met_sp = (int) scan_ctl(filename, argc, argv, "MET_SP", -1, "1", NULL);
4906 if (ctl->met_sx < 1 || ctl->met_sy < 1 || ctl->met_sp < 1)
4907 ERRMSG("MET_SX, MET_SY, and MET_SP need to be greater than zero!");
4908 ctl->met_detrend =
4909 scan_ctl(filename, argc, argv, "MET_DETREND", -1, "-999", NULL);
4910 ctl->met_np = (int) scan_ctl(filename, argc, argv, "MET_NP", -1, "0", NULL);
4911 if (ctl->met_np > EP)
4912 ERRMSG("Too many pressure levels!");
4913 ctl->met_press_level_def =
4914 (int) scan_ctl(filename, argc, argv, "MET_PRESS_LEVEL_DEF", -1, "-1",
4915 NULL);
4916 if (ctl->met_press_level_def >= 0) {
4917 level_definitions(ctl);
4918 } else {
4919 if (ctl->met_np > 0) {
4920 for (int ip = 0; ip < ctl->met_np; ip++)
4921 ctl->met_p[ip] =
4922 scan_ctl(filename, argc, argv, "MET_P", ip, "", NULL);
4923 }
4924 }
4925 ctl->met_nlev =
4926 (int) scan_ctl(filename, argc, argv, "MET_NLEV", -1, "0", NULL);
4927 if (ctl->met_nlev > EP)
4928 ERRMSG("Too many model levels!");
4929 for (int ip = 0; ip < ctl->met_nlev; ip++) {
4930 ctl->met_lev_hyam[ip] =
4931 scan_ctl(filename, argc, argv, "MET_LEV_HYAM", ip, "", NULL);
4932 ctl->met_lev_hybm[ip] =
4933 scan_ctl(filename, argc, argv, "MET_LEV_HYBM", ip, "", NULL);
4934 }
4935 ctl->met_geopot_sx =
4936 (int) scan_ctl(filename, argc, argv, "MET_GEOPOT_SX", -1, "-1", NULL);
4937 ctl->met_geopot_sy =
4938 (int) scan_ctl(filename, argc, argv, "MET_GEOPOT_SY", -1, "-1", NULL);
4939 ctl->met_relhum =
4940 (int) scan_ctl(filename, argc, argv, "MET_RELHUM", -1, "0", NULL);
4941 ctl->met_cape =
4942 (int) scan_ctl(filename, argc, argv, "MET_CAPE", -1, "1", NULL);
4943 if (ctl->met_cape < 0 || ctl->met_cape > 1)
4944 ERRMSG("Set MET_CAPE to 0 or 1!");
4945 ctl->met_pbl =
4946 (int) scan_ctl(filename, argc, argv, "MET_PBL", -1, "3", NULL);
4947 if (ctl->met_pbl < 0 || ctl->met_pbl > 3)
4948 ERRMSG("Set MET_PBL to 0 ... 3!");
4949 ctl->met_pbl_min =
4950 scan_ctl(filename, argc, argv, "MET_PBL_MIN", -1, "0.1", NULL);
4951 ctl->met_pbl_max =
4952 scan_ctl(filename, argc, argv, "MET_PBL_MAX", -1, "5.0", NULL);
4953 ctl->met_tropo =
4954 (int) scan_ctl(filename, argc, argv, "MET_TROPO", -1, "3", NULL);
4955 if (ctl->met_tropo < 0 || ctl->met_tropo > 5)
4956 ERRMSG("Set MET_TROPO to 0 ... 5!");
4957 ctl->met_tropo_pv =
4958 scan_ctl(filename, argc, argv, "MET_TROPO_PV", -1, "3.5", NULL);
4959 ctl->met_tropo_theta =
4960 scan_ctl(filename, argc, argv, "MET_TROPO_THETA", -1, "380", NULL);
4961 ctl->met_tropo_spline =
4962 (int) scan_ctl(filename, argc, argv, "MET_TROPO_SPLINE", -1, "1", NULL);
4963 ctl->met_dt_out =
4964 scan_ctl(filename, argc, argv, "MET_DT_OUT", -1, "0.1", NULL);
4965 ctl->met_cache =
4966 (int) scan_ctl(filename, argc, argv, "MET_CACHE", -1, "0", NULL);
4967 ctl->met_mpi_share =
4968 (int) scan_ctl(filename, argc, argv, "MET_MPI_SHARE", -1, "0", NULL);
4969
4970 /* Sorting... */
4971 ctl->sort_dt = scan_ctl(filename, argc, argv, "SORT_DT", -1, "-999", NULL);
4972
4973 /* Isosurface parameters... */
4974 ctl->isosurf =
4975 (int) scan_ctl(filename, argc, argv, "ISOSURF", -1, "0", NULL);
4976 scan_ctl(filename, argc, argv, "BALLOON", -1, "-", ctl->balloon);
4977
4978 /* Random number generator... */
4979 ctl->rng_type =
4980 (int) scan_ctl(filename, argc, argv, "RNG_TYPE", -1, "1", NULL);
4981 if (ctl->rng_type < 0 || ctl->rng_type > 2)
4982 ERRMSG("Set RNG_TYPE to 0, 1, or 2!");
4983
4984 /* Advection parameters... */
4985 ctl->advect = (int) scan_ctl(filename, argc, argv, "ADVECT", -1, "2", NULL);
4986 if (!
4987 (ctl->advect == 0 || ctl->advect == 1 || ctl->advect == 2
4988 || ctl->advect == 4))
4989 ERRMSG("Set ADVECT to 0, 1, 2, or 4!");
4990
4991 /* Diffusion parameters... */
4992 ctl->diffusion
4993 = (int) scan_ctl(filename, argc, argv, "DIFFUSION", -1, "0", NULL);
4994 if (ctl->diffusion < 0 || ctl->diffusion > 2)
4995 ERRMSG("Set DIFFUSION to 0, 1 or 2!");
4996 ctl->turb_dx_pbl =
4997 scan_ctl(filename, argc, argv, "TURB_DX_PBL", -1, "50", NULL);
4998 ctl->turb_dx_trop =
4999 scan_ctl(filename, argc, argv, "TURB_DX_TROP", -1, "50", NULL);
5000 ctl->turb_dx_strat =
5001 scan_ctl(filename, argc, argv, "TURB_DX_STRAT", -1, "0", NULL);
5002 ctl->turb_dz_pbl =
5003 scan_ctl(filename, argc, argv, "TURB_DZ_PBL", -1, "0", NULL);
5004 ctl->turb_dz_trop =
5005 scan_ctl(filename, argc, argv, "TURB_DZ_TROP", -1, "0", NULL);
5006 ctl->turb_dz_strat =
5007 scan_ctl(filename, argc, argv, "TURB_DZ_STRAT", -1, "0.1", NULL);
5008 ctl->turb_mesox =
5009 scan_ctl(filename, argc, argv, "TURB_MESOX", -1, "0.16", NULL);
5010 ctl->turb_mesoz =
5011 scan_ctl(filename, argc, argv, "TURB_MESOZ", -1, "0.16", NULL);
5012
5013 /* Convection... */
5014 ctl->conv_mix_pbl
5015 = (int) scan_ctl(filename, argc, argv, "CONV_MIX_PBL", -1, "0", NULL);
5016 ctl->conv_pbl_trans
5017 = scan_ctl(filename, argc, argv, "CONV_PBL_TRANS", -1, "0", NULL);
5018 ctl->conv_cape
5019 = scan_ctl(filename, argc, argv, "CONV_CAPE", -1, "-999", NULL);
5020 ctl->conv_cin
5021 = scan_ctl(filename, argc, argv, "CONV_CIN", -1, "-999", NULL);
5022 ctl->conv_dt = scan_ctl(filename, argc, argv, "CONV_DT", -1, "-999", NULL);
5023
5024 /* Boundary conditions... */
5025 ctl->bound_mass =
5026 scan_ctl(filename, argc, argv, "BOUND_MASS", -1, "-999", NULL);
5027 ctl->bound_mass_trend =
5028 scan_ctl(filename, argc, argv, "BOUND_MASS_TREND", -1, "0", NULL);
5029 ctl->bound_vmr =
5030 scan_ctl(filename, argc, argv, "BOUND_VMR", -1, "-999", NULL);
5031 ctl->bound_vmr_trend =
5032 scan_ctl(filename, argc, argv, "BOUND_VMR_TREND", -1, "0", NULL);
5033 ctl->bound_lat0 =
5034 scan_ctl(filename, argc, argv, "BOUND_LAT0", -1, "-999", NULL);
5035 ctl->bound_lat1 =
5036 scan_ctl(filename, argc, argv, "BOUND_LAT1", -1, "-999", NULL);
5037 ctl->bound_p0 =
5038 scan_ctl(filename, argc, argv, "BOUND_P0", -1, "-999", NULL);
5039 ctl->bound_p1 =
5040 scan_ctl(filename, argc, argv, "BOUND_P1", -1, "-999", NULL);
5041 ctl->bound_dps =
5042 scan_ctl(filename, argc, argv, "BOUND_DPS", -1, "-999", NULL);
5043 ctl->bound_dzs =
5044 scan_ctl(filename, argc, argv, "BOUND_DZS", -1, "-999", NULL);
5045 ctl->bound_zetas =
5046 scan_ctl(filename, argc, argv, "BOUND_ZETAS", -1, "-999", NULL);
5047 ctl->bound_pbl =
5048 (int) scan_ctl(filename, argc, argv, "BOUND_PBL", -1, "0", NULL);
5049
5050 /* Species parameters... */
5051 scan_ctl(filename, argc, argv, "SPECIES", -1, "-", ctl->species);
5052 if (strcasecmp(ctl->species, "CF2Cl2") == 0) {
5053 ctl->molmass = 120.907;
5054 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 3e-5;
5055 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3500.0;
5056 } else if (strcasecmp(ctl->species, "CFCl3") == 0) {
5057 ctl->molmass = 137.359;
5058 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.1e-4;
5059 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3300.0;
5060 } else if (strcasecmp(ctl->species, "CH4") == 0) {
5061 ctl->molmass = 16.043;
5062 ctl->oh_chem_reaction = 2;
5063 ctl->oh_chem[0] = 2.45e-12;
5064 ctl->oh_chem[1] = 1775;
5065 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.4e-5;
5066 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1600.0;
5067 } else if (strcasecmp(ctl->species, "CO") == 0) {
5068 ctl->molmass = 28.01;
5069 ctl->oh_chem_reaction = 3;
5070 ctl->oh_chem[0] = 6.9e-33;
5071 ctl->oh_chem[1] = 2.1;
5072 ctl->oh_chem[2] = 1.1e-12;
5073 ctl->oh_chem[3] = -1.3;
5074 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 9.7e-6;
5075 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1300.0;
5076 } else if (strcasecmp(ctl->species, "CO2") == 0) {
5077 ctl->molmass = 44.009;
5078 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 3.3e-4;
5079 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2400.0;
5080 } else if (strcasecmp(ctl->species, "H2O") == 0) {
5081 ctl->molmass = 18.01528;
5082 } else if (strcasecmp(ctl->species, "N2O") == 0) {
5083 ctl->molmass = 44.013;
5084 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.4e-4;
5085 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2600.;
5086 } else if (strcasecmp(ctl->species, "NH3") == 0) {
5087 ctl->molmass = 17.031;
5088 ctl->oh_chem_reaction = 2;
5089 ctl->oh_chem[0] = 1.7e-12;
5090 ctl->oh_chem[1] = 710;
5091 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 5.9e-1;
5092 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 4200.0;
5093 } else if (strcasecmp(ctl->species, "HNO3") == 0) {
5094 ctl->molmass = 63.012;
5095 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.1e3;
5096 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 8700.0;
5097 } else if (strcasecmp(ctl->species, "NO") == 0) {
5098 ctl->molmass = 30.006;
5099 ctl->oh_chem_reaction = 3;
5100 ctl->oh_chem[0] = 7.1e-31;
5101 ctl->oh_chem[1] = 2.6;
5102 ctl->oh_chem[2] = 3.6e-11;
5103 ctl->oh_chem[3] = 0.1;
5104 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.9e-5;
5105 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1600.0;
5106 } else if (strcasecmp(ctl->species, "NO2") == 0) {
5107 ctl->molmass = 46.005;
5108 ctl->oh_chem_reaction = 3;
5109 ctl->oh_chem[0] = 1.8e-30;
5110 ctl->oh_chem[1] = 3.0;
5111 ctl->oh_chem[2] = 2.8e-11;
5112 ctl->oh_chem[3] = 0.0;
5113 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.2e-4;
5114 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2400.0;
5115 } else if (strcasecmp(ctl->species, "O3") == 0) {
5116 ctl->molmass = 47.997;
5117 ctl->oh_chem_reaction = 2;
5118 ctl->oh_chem[0] = 1.7e-12;
5119 ctl->oh_chem[1] = 940;
5120 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1e-4;
5121 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2800.0;
5122 } else if (strcasecmp(ctl->species, "SF6") == 0) {
5123 ctl->molmass = 146.048;
5124 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.4e-6;
5125 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3100.0;
5126 } else if (strcasecmp(ctl->species, "SO2") == 0) {
5127 ctl->molmass = 64.066;
5128 ctl->oh_chem_reaction = 3;
5129 ctl->oh_chem[0] = 2.9e-31;
5130 ctl->oh_chem[1] = 4.1;
5131 ctl->oh_chem[2] = 1.7e-12;
5132 ctl->oh_chem[3] = -0.2;
5133 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.3e-2;
5134 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2900.0;
5135 }
5136
5137 /* Molar mass... */
5138 char defstr[LEN];
5139 sprintf(defstr, "%g", ctl->molmass);
5140 ctl->molmass = scan_ctl(filename, argc, argv, "MOLMASS", -1, defstr, NULL);
5141
5142 /* OH chemistry... */
5143 sprintf(defstr, "%d", ctl->oh_chem_reaction);
5144 ctl->oh_chem_reaction =
5145 (int) scan_ctl(filename, argc, argv, "OH_CHEM_REACTION", -1, defstr,
5146 NULL);
5147 for (int ip = 0; ip < 4; ip++) {
5148 sprintf(defstr, "%g", ctl->oh_chem[ip]);
5149 ctl->oh_chem[ip] =
5150 scan_ctl(filename, argc, argv, "OH_CHEM", ip, defstr, NULL);
5151 }
5152 ctl->oh_chem_beta =
5153 scan_ctl(filename, argc, argv, "OH_CHEM_BETA", -1, "0", NULL);
5154
5155 /* H2O2 chemistry... */
5156 ctl->h2o2_chem_reaction =
5157 (int) scan_ctl(filename, argc, argv, "H2O2_CHEM_REACTION", -1, "0", NULL);
5158
5159 /* KPP chemistry... */
5160 ctl->kpp_chem =
5161 (int) scan_ctl(filename, argc, argv, "KPP_CHEM", -1, "0", NULL);
5162 ctl->dt_kpp = scan_ctl(filename, argc, argv, "DT_KPP", -1, "1800", NULL);
5163
5164 /* First order tracer chemistry... */
5165 ctl->tracer_chem =
5166 (int) scan_ctl(filename, argc, argv, "TRACER_CHEM", -1, "0", NULL);
5167
5168 /* Wet deposition... */
5169 for (int ip = 0; ip < 2; ip++) {
5170 sprintf(defstr, "%g", ctl->wet_depo_ic_h[ip]);
5171 ctl->wet_depo_ic_h[ip] =
5172 scan_ctl(filename, argc, argv, "WET_DEPO_IC_H", ip, defstr, NULL);
5173 }
5174 for (int ip = 0; ip < 1; ip++) {
5175 sprintf(defstr, "%g", ctl->wet_depo_bc_h[ip]);
5176 ctl->wet_depo_bc_h[ip] =
5177 scan_ctl(filename, argc, argv, "WET_DEPO_BC_H", ip, defstr, NULL);
5178 }
5179 ctl->wet_depo_so2_ph =
5180 scan_ctl(filename, argc, argv, "WET_DEPO_SO2_PH", -1, "0", NULL);
5181 ctl->wet_depo_ic_a =
5182 scan_ctl(filename, argc, argv, "WET_DEPO_IC_A", -1, "0", NULL);
5183 ctl->wet_depo_ic_b =
5184 scan_ctl(filename, argc, argv, "WET_DEPO_IC_B", -1, "0", NULL);
5185 ctl->wet_depo_bc_a =
5186 scan_ctl(filename, argc, argv, "WET_DEPO_BC_A", -1, "0", NULL);
5187 ctl->wet_depo_bc_b =
5188 scan_ctl(filename, argc, argv, "WET_DEPO_BC_B", -1, "0", NULL);
5189 ctl->wet_depo_pre[0] =
5190 scan_ctl(filename, argc, argv, "WET_DEPO_PRE", 0, "0.5", NULL);
5191 ctl->wet_depo_pre[1] =
5192 scan_ctl(filename, argc, argv, "WET_DEPO_PRE", 1, "0.36", NULL);
5194 scan_ctl(filename, argc, argv, "WET_DEPO_IC_RET_RATIO", -1, "1", NULL);
5196 scan_ctl(filename, argc, argv, "WET_DEPO_BC_RET_RATIO", -1, "1", NULL);
5197
5198 /* Dry deposition... */
5199 ctl->dry_depo_vdep =
5200 scan_ctl(filename, argc, argv, "DRY_DEPO_VDEP", -1, "0", NULL);
5201 ctl->dry_depo_dp =
5202 scan_ctl(filename, argc, argv, "DRY_DEPO_DP", -1, "30", NULL);
5203
5204 /* Climatological data... */
5205 scan_ctl(filename, argc, argv, "CLIM_PHOTO", -1,
5206 "../../data/clams_photolysis_rates.nc", ctl->clim_photo);
5207 scan_ctl(filename, argc, argv, "CLIM_HNO3_FILENAME", -1,
5208 "../../data/gozcards_HNO3.nc", ctl->clim_hno3_filename);
5209 scan_ctl(filename, argc, argv, "CLIM_OH_FILENAME", -1,
5210 "../../data/clams_radical_species_vmr.nc", ctl->clim_oh_filename);
5211 scan_ctl(filename, argc, argv, "CLIM_H2O2_FILENAME", -1,
5212 "../../data/cams_H2O2.nc", ctl->clim_h2o2_filename);
5213 scan_ctl(filename, argc, argv, "CLIM_HO2_FILENAME", -1,
5214 "../../data/clams_radical_species_vmr.nc", ctl->clim_ho2_filename);
5215 scan_ctl(filename, argc, argv, "CLIM_O1D_FILENAME", -1,
5216 "../../data/clams_radical_species_vmr.nc", ctl->clim_o1d_filename);
5217 scan_ctl(filename, argc, argv, "CLIM_CCL4_TIMESERIES", -1,
5218 "../../data/noaa_gml_ccl4.tab", ctl->clim_ccl4_timeseries);
5219 scan_ctl(filename, argc, argv, "CLIM_CCL3F_TIMESERIES", -1,
5220 "../../data/noaa_gml_cfc11.tab", ctl->clim_ccl3f_timeseries);
5221 scan_ctl(filename, argc, argv, "CLIM_CCL2F2_TIMESERIES", -1,
5222 "../../data/noaa_gml_cfc12.tab", ctl->clim_ccl2f2_timeseries);
5223 scan_ctl(filename, argc, argv, "CLIM_N2O_TIMESERIES", -1,
5224 "../../data/noaa_gml_n2o.tab", ctl->clim_n2o_timeseries);
5225 scan_ctl(filename, argc, argv, "CLIM_SF6_TIMESERIES", -1,
5226 "../../data/noaa_gml_sf6.tab", ctl->clim_sf6_timeseries);
5227
5228 /* Mixing... */
5229 ctl->mixing_dt =
5230 scan_ctl(filename, argc, argv, "MIXING_DT", -1, "3600.", NULL);
5231 ctl->mixing_trop =
5232 scan_ctl(filename, argc, argv, "MIXING_TROP", -1, "-999", NULL);
5233 ctl->mixing_strat =
5234 scan_ctl(filename, argc, argv, "MIXING_STRAT", -1, "-999", NULL);
5235 ctl->mixing_z0 =
5236 scan_ctl(filename, argc, argv, "MIXING_Z0", -1, "-5", NULL);
5237 ctl->mixing_z1 =
5238 scan_ctl(filename, argc, argv, "MIXING_Z1", -1, "85", NULL);
5239 ctl->mixing_nz =
5240 (int) scan_ctl(filename, argc, argv, "MIXING_NZ", -1, "90", NULL);
5241 ctl->mixing_lon0 =
5242 scan_ctl(filename, argc, argv, "MIXING_LON0", -1, "-180", NULL);
5243 ctl->mixing_lon1 =
5244 scan_ctl(filename, argc, argv, "MIXING_LON1", -1, "180", NULL);
5245 ctl->mixing_nx =
5246 (int) scan_ctl(filename, argc, argv, "MIXING_NX", -1, "360", NULL);
5247 ctl->mixing_lat0 =
5248 scan_ctl(filename, argc, argv, "MIXING_LAT0", -1, "-90", NULL);
5249 ctl->mixing_lat1 =
5250 scan_ctl(filename, argc, argv, "MIXING_LAT1", -1, "90", NULL);
5251 ctl->mixing_ny =
5252 (int) scan_ctl(filename, argc, argv, "MIXING_NY", -1, "180", NULL);
5253
5254 /* Chemistry grid... */
5255 ctl->chemgrid_z0 =
5256 scan_ctl(filename, argc, argv, "CHEMGRID_Z0", -1, "-5", NULL);
5257 ctl->chemgrid_z1 =
5258 scan_ctl(filename, argc, argv, "CHEMGRID_Z1", -1, "85", NULL);
5259 ctl->chemgrid_nz =
5260 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NZ", -1, "90", NULL);
5261 ctl->chemgrid_lon0 =
5262 scan_ctl(filename, argc, argv, "CHEMGRID_LON0", -1, "-180", NULL);
5263 ctl->chemgrid_lon1 =
5264 scan_ctl(filename, argc, argv, "CHEMGRID_LON1", -1, "180", NULL);
5265 ctl->chemgrid_nx =
5266 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NX", -1, "360", NULL);
5267 ctl->chemgrid_lat0 =
5268 scan_ctl(filename, argc, argv, "CHEMGRID_LAT0", -1, "-90", NULL);
5269 ctl->chemgrid_lat1 =
5270 scan_ctl(filename, argc, argv, "CHEMGRID_LAT1", -1, "90", NULL);
5271 ctl->chemgrid_ny =
5272 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NY", -1, "180", NULL);
5273
5274 /* Exponential decay... */
5275 ctl->tdec_trop = scan_ctl(filename, argc, argv, "TDEC_TROP", -1, "0", NULL);
5276 ctl->tdec_strat =
5277 scan_ctl(filename, argc, argv, "TDEC_STRAT", -1, "0", NULL);
5278
5279 /* PSC analysis... */
5280 ctl->psc_h2o = scan_ctl(filename, argc, argv, "PSC_H2O", -1, "4e-6", NULL);
5281 ctl->psc_hno3 =
5282 scan_ctl(filename, argc, argv, "PSC_HNO3", -1, "9e-9", NULL);
5283
5284 /* Output of atmospheric data... */
5285 scan_ctl(filename, argc, argv, "ATM_BASENAME", -1, "-", ctl->atm_basename);
5286 scan_ctl(filename, argc, argv, "ATM_GPFILE", -1, "-", ctl->atm_gpfile);
5287 ctl->atm_dt_out =
5288 scan_ctl(filename, argc, argv, "ATM_DT_OUT", -1, "86400", NULL);
5289 ctl->atm_filter =
5290 (int) scan_ctl(filename, argc, argv, "ATM_FILTER", -1, "0", NULL);
5291 ctl->atm_stride =
5292 (int) scan_ctl(filename, argc, argv, "ATM_STRIDE", -1, "1", NULL);
5293 ctl->atm_type =
5294 (int) scan_ctl(filename, argc, argv, "ATM_TYPE", -1, "0", NULL);
5295 ctl->atm_type_out =
5296 (int) scan_ctl(filename, argc, argv, "ATM_TYPE_OUT", -1, "-1", NULL);
5297 if (ctl->atm_type_out == -1)
5298 ctl->atm_type_out = ctl->atm_type;
5299 ctl->atm_nc_level =
5300 (int) scan_ctl(filename, argc, argv, "ATM_NC_LEVEL", -1, "0", NULL);
5301 for (int iq = 0; iq < ctl->nq; iq++)
5302 ctl->atm_nc_quant[iq] =
5303 (int) scan_ctl(filename, argc, argv, "ATM_NC_QUANT", iq, "0", NULL);
5304 ctl->obs_type =
5305 (int) scan_ctl(filename, argc, argv, "OBS_TYPE", -1, "0", NULL);
5306
5307 /* Output of CSI data... */
5308 scan_ctl(filename, argc, argv, "CSI_BASENAME", -1, "-", ctl->csi_basename);
5309 scan_ctl(filename, argc, argv, "CSI_KERNEL", -1, "-", ctl->csi_kernel);
5310 ctl->csi_dt_out =
5311 scan_ctl(filename, argc, argv, "CSI_DT_OUT", -1, "86400", NULL);
5312 scan_ctl(filename, argc, argv, "CSI_OBSFILE", -1, "-", ctl->csi_obsfile);
5313 ctl->csi_obsmin =
5314 scan_ctl(filename, argc, argv, "CSI_OBSMIN", -1, "0", NULL);
5315 ctl->csi_modmin =
5316 scan_ctl(filename, argc, argv, "CSI_MODMIN", -1, "0", NULL);
5317 ctl->csi_z0 = scan_ctl(filename, argc, argv, "CSI_Z0", -1, "-5", NULL);
5318 ctl->csi_z1 = scan_ctl(filename, argc, argv, "CSI_Z1", -1, "85", NULL);
5319 ctl->csi_nz = (int) scan_ctl(filename, argc, argv, "CSI_NZ", -1, "1", NULL);
5320 ctl->csi_lon0 =
5321 scan_ctl(filename, argc, argv, "CSI_LON0", -1, "-180", NULL);
5322 ctl->csi_lon1 = scan_ctl(filename, argc, argv, "CSI_LON1", -1, "180", NULL);
5323 ctl->csi_nx =
5324 (int) scan_ctl(filename, argc, argv, "CSI_NX", -1, "360", NULL);
5325 ctl->csi_lat0 = scan_ctl(filename, argc, argv, "CSI_LAT0", -1, "-90", NULL);
5326 ctl->csi_lat1 = scan_ctl(filename, argc, argv, "CSI_LAT1", -1, "90", NULL);
5327 ctl->csi_ny =
5328 (int) scan_ctl(filename, argc, argv, "CSI_NY", -1, "180", NULL);
5329
5330 /* Output of ensemble data... */
5331 ctl->nens = (int) scan_ctl(filename, argc, argv, "NENS", -1, "0", NULL);
5332 scan_ctl(filename, argc, argv, "ENS_BASENAME", -1, "-", ctl->ens_basename);
5333 ctl->ens_dt_out =
5334 scan_ctl(filename, argc, argv, "ENS_DT_OUT", -1, "86400", NULL);
5335
5336 /* Output of grid data... */
5337 scan_ctl(filename, argc, argv, "GRID_BASENAME", -1, "-",
5338 ctl->grid_basename);
5339 scan_ctl(filename, argc, argv, "GRID_KERNEL", -1, "-", ctl->grid_kernel);
5340 scan_ctl(filename, argc, argv, "GRID_GPFILE", -1, "-", ctl->grid_gpfile);
5341 ctl->grid_dt_out =
5342 scan_ctl(filename, argc, argv, "GRID_DT_OUT", -1, "86400", NULL);
5343 ctl->grid_sparse =
5344 (int) scan_ctl(filename, argc, argv, "GRID_SPARSE", -1, "0", NULL);
5345 ctl->grid_nc_level =
5346 (int) scan_ctl(filename, argc, argv, "GRID_NC_LEVEL", -1, "0", NULL);
5347 for (int iq = 0; iq < ctl->nq; iq++)
5348 ctl->grid_nc_quant[iq] =
5349 (int) scan_ctl(filename, argc, argv, "GRID_NC_QUANT", iq, "0", NULL);
5350 ctl->grid_stddev =
5351 (int) scan_ctl(filename, argc, argv, "GRID_STDDEV", -1, "0", NULL);
5352 ctl->grid_z0 = scan_ctl(filename, argc, argv, "GRID_Z0", -1, "-5", NULL);
5353 ctl->grid_z1 = scan_ctl(filename, argc, argv, "GRID_Z1", -1, "85", NULL);
5354 ctl->grid_nz =
5355 (int) scan_ctl(filename, argc, argv, "GRID_NZ", -1, "1", NULL);
5356 ctl->grid_lon0 =
5357 scan_ctl(filename, argc, argv, "GRID_LON0", -1, "-180", NULL);
5358 ctl->grid_lon1 =
5359 scan_ctl(filename, argc, argv, "GRID_LON1", -1, "180", NULL);
5360 ctl->grid_nx =
5361 (int) scan_ctl(filename, argc, argv, "GRID_NX", -1, "360", NULL);
5362 ctl->grid_lat0 =
5363 scan_ctl(filename, argc, argv, "GRID_LAT0", -1, "-90", NULL);
5364 ctl->grid_lat1 =
5365 scan_ctl(filename, argc, argv, "GRID_LAT1", -1, "90", NULL);
5366 ctl->grid_ny =
5367 (int) scan_ctl(filename, argc, argv, "GRID_NY", -1, "180", NULL);
5368 ctl->grid_type =
5369 (int) scan_ctl(filename, argc, argv, "GRID_TYPE", -1, "0", NULL);
5370
5371 /* Output of profile data... */
5372 scan_ctl(filename, argc, argv, "PROF_BASENAME", -1, "-",
5373 ctl->prof_basename);
5374 scan_ctl(filename, argc, argv, "PROF_OBSFILE", -1, "-", ctl->prof_obsfile);
5375 ctl->prof_z0 = scan_ctl(filename, argc, argv, "PROF_Z0", -1, "0", NULL);
5376 ctl->prof_z1 = scan_ctl(filename, argc, argv, "PROF_Z1", -1, "60", NULL);
5377 ctl->prof_nz =
5378 (int) scan_ctl(filename, argc, argv, "PROF_NZ", -1, "60", NULL);
5379 ctl->prof_lon0 =
5380 scan_ctl(filename, argc, argv, "PROF_LON0", -1, "-180", NULL);
5381 ctl->prof_lon1 =
5382 scan_ctl(filename, argc, argv, "PROF_LON1", -1, "180", NULL);
5383 ctl->prof_nx =
5384 (int) scan_ctl(filename, argc, argv, "PROF_NX", -1, "360", NULL);
5385 ctl->prof_lat0 =
5386 scan_ctl(filename, argc, argv, "PROF_LAT0", -1, "-90", NULL);
5387 ctl->prof_lat1 =
5388 scan_ctl(filename, argc, argv, "PROF_LAT1", -1, "90", NULL);
5389 ctl->prof_ny =
5390 (int) scan_ctl(filename, argc, argv, "PROF_NY", -1, "180", NULL);
5391
5392 /* Output of sample data... */
5393 scan_ctl(filename, argc, argv, "SAMPLE_BASENAME", -1, "-",
5394 ctl->sample_basename);
5395 scan_ctl(filename, argc, argv, "SAMPLE_KERNEL", -1, "-",
5396 ctl->sample_kernel);
5397 scan_ctl(filename, argc, argv, "SAMPLE_OBSFILE", -1, "-",
5398 ctl->sample_obsfile);
5399 ctl->sample_dx =
5400 scan_ctl(filename, argc, argv, "SAMPLE_DX", -1, "50", NULL);
5401 ctl->sample_dz =
5402 scan_ctl(filename, argc, argv, "SAMPLE_DZ", -1, "-999", NULL);
5403
5404 /* Output of station data... */
5405 scan_ctl(filename, argc, argv, "STAT_BASENAME", -1, "-",
5406 ctl->stat_basename);
5407 ctl->stat_lon = scan_ctl(filename, argc, argv, "STAT_LON", -1, "0", NULL);
5408 ctl->stat_lat = scan_ctl(filename, argc, argv, "STAT_LAT", -1, "0", NULL);
5409 ctl->stat_r = scan_ctl(filename, argc, argv, "STAT_R", -1, "50", NULL);
5410 ctl->stat_t0 =
5411 scan_ctl(filename, argc, argv, "STAT_T0", -1, "-1e100", NULL);
5412 ctl->stat_t1 = scan_ctl(filename, argc, argv, "STAT_T1", -1, "1e100", NULL);
5413
5414 /* Output of VTK data... */
5415 scan_ctl(filename, argc, argv, "VTK_BASENAME", -1, "-", ctl->vtk_basename);
5416 ctl->vtk_dt_out =
5417 scan_ctl(filename, argc, argv, "VTK_DT_OUT", -1, "86400", NULL);
5418 ctl->vtk_stride =
5419 (int) scan_ctl(filename, argc, argv, "VTK_STRIDE", -1, "1", NULL);
5420 ctl->vtk_scale =
5421 scan_ctl(filename, argc, argv, "VTK_SCALE", -1, "1.0", NULL);
5422 ctl->vtk_offset =
5423 scan_ctl(filename, argc, argv, "VTK_OFFSET", -1, "0.0", NULL);
5424 ctl->vtk_sphere =
5425 (int) scan_ctl(filename, argc, argv, "VTK_SPHERE", -1, "0", NULL);
5426
5427#ifdef DD
5428 /* Controle of domain decomposition... */
5430 (int) scan_ctl(filename, argc, argv, "DD_SUBDOMAINS_MERIDIONAL", -1, "1",
5431 NULL);
5432 ctl->dd_subdomains_zonal =
5433 (int) scan_ctl(filename, argc, argv, "DD_SUBDOMAINS_ZONAL", -1, "1",
5434 NULL);
5435 ctl->dd_nbr_neighbours =
5436 (int) scan_ctl(filename, argc, argv, "DD_NBR_NEIGHBOURS", -1, "8", NULL);
5437 ctl->dd_halos_size =
5438 (int) scan_ctl(filename, argc, argv, "DD_HALOS_SIZE", -1, "1", NULL);
5439#endif
5440
5441}
void level_definitions(ctl_t *ctl)
Defines pressure levels for meteorological data.
Definition: mptrac.c:1781
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:10495
#define METVAR
Number of 3-D meteorological variables.
Definition: mptrac.h:314
#define NQ
Maximum number of quantities per data point.
Definition: mptrac.h:324
#define SET_QNT(qnt, name, longname, unit)
Set atmospheric quantity index.
Definition: mptrac.h:1721
double grid_z0
Lower altitude of gridded data [km].
Definition: mptrac.h:3239
int qnt_o3
Quantity array index for ozone volume mixing ratio.
Definition: mptrac.h:2468
double csi_lat1
Upper latitude of gridded CSI data [deg].
Definition: mptrac.h:3200
char csi_obsfile[LEN]
Observation data file for CSI analysis.
Definition: mptrac.h:3167
int met_nc_scale
Check netCDF scaling factors (0=no, 1=yes).
Definition: mptrac.h:2696
int qnt_pel
Quantity array index for pressure at equilibrium level (EL).
Definition: mptrac.h:2501
int csi_nz
Number of altitudes of gridded CSI data.
Definition: mptrac.h:3176
int qnt_p
Quantity array index for pressure.
Definition: mptrac.h:2447
int dd_halos_size
Size of halos given in grid-points.
Definition: mptrac.h:3359
char atm_gpfile[LEN]
Gnuplot file for atmospheric data.
Definition: mptrac.h:3128
int qnt_swc
Quantity array index for cloud snow water content.
Definition: mptrac.h:2480
double csi_obsmin
Minimum observation index to trigger detection.
Definition: mptrac.h:3170
int qnt_pcb
Quantity array index for cloud bottom pressure.
Definition: mptrac.h:2489
double csi_lon1
Upper longitude of gridded CSI data [deg].
Definition: mptrac.h:3191
int qnt_u
Quantity array index for zonal wind.
Definition: mptrac.h:2456
double stat_lon
Longitude of station [deg].
Definition: mptrac.h:3317
double sort_dt
Time step for sorting of particle data [s].
Definition: mptrac.h:2849
double stat_r
Search radius around station [km].
Definition: mptrac.h:3323
int met_zstd_level
ZSTD compression level (from -5 to 22).
Definition: mptrac.h:2705
int csi_ny
Number of latitudes of gridded CSI data.
Definition: mptrac.h:3194
int vtk_sphere
Spherical projection for VTK data (0=no, 1=yes).
Definition: mptrac.h:3347
double met_pbl_min
Minimum depth of planetary boundary layer [km].
Definition: mptrac.h:2817
int qnt_iwc
Quantity array index for cloud ice water content.
Definition: mptrac.h:2477
double met_cms_eps_pv
cmultiscale compression epsilon for potential vorticity.
Definition: mptrac.h:2739
int qnt_pw
Quantity array index for partial water vapor pressure.
Definition: mptrac.h:2555
char prof_basename[LEN]
Basename for profile output file.
Definition: mptrac.h:3266
double grid_z1
Upper altitude of gridded data [km].
Definition: mptrac.h:3242
int met_dp
Stride for pressure levels.
Definition: mptrac.h:2769
double met_dt_out
Time step for sampling of meteo data along trajectories [s].
Definition: mptrac.h:2836
int qnt_h2o2
Quantity array index for H2O2 volume mixing ratio (climatology).
Definition: mptrac.h:2519
int qnt_vh
Quantity array index for horizontal wind.
Definition: mptrac.h:2585
char species[LEN]
Species.
Definition: mptrac.h:2947
int csi_nx
Number of longitudes of gridded CSI data.
Definition: mptrac.h:3185
double csi_lat0
Lower latitude of gridded CSI data [deg].
Definition: mptrac.h:3197
int met_pbl
Planetary boundary layer data (0=file, 1=z2p, 2=Richardson, 3=theta).
Definition: mptrac.h:2814
int qnt_lwc
Quantity array index for cloud liquid water content.
Definition: mptrac.h:2471
int grid_nc_level
zlib compression level of netCDF grid data files (0=off).
Definition: mptrac.h:3227
int grid_nx
Number of longitudes of gridded data.
Definition: mptrac.h:3245
double grid_lat0
Lower latitude of gridded data [deg].
Definition: mptrac.h:3257
int qnt_ts
Quantity array index for surface temperature.
Definition: mptrac.h:2402
double met_cms_eps_h2o
cmultiscale compression epsilon for water vapor.
Definition: mptrac.h:2742
int qnt_plfc
Quantity array index for pressure at level of free convection (LCF).
Definition: mptrac.h:2498
double grid_lon0
Lower longitude of gridded data [deg].
Definition: mptrac.h:3248
int qnt_o1d
Quantity array index for O(1D) volume mixing ratio (climatology).
Definition: mptrac.h:2525
int met_tropo_spline
Tropopause interpolation method (0=linear, 1=spline).
Definition: mptrac.h:2833
char sample_kernel[LEN]
Kernel data file for sample output.
Definition: mptrac.h:3302
int qnt_tvirt
Quantity array index for virtual temperature.
Definition: mptrac.h:2579
int met_geopot_sy
Latitudinal smoothing of geopotential heights.
Definition: mptrac.h:2805
char grid_gpfile[LEN]
Gnuplot file for gridded data.
Definition: mptrac.h:3218
double met_cms_eps_u
cmultiscale compression epsilon for zonal wind.
Definition: mptrac.h:2730
int qnt_lsm
Quantity array index for land-sea mask.
Definition: mptrac.h:2423
int qnt_theta
Quantity array index for potential temperature.
Definition: mptrac.h:2567
double stat_t1
Stop time for station output [s].
Definition: mptrac.h:3329
char csi_kernel[LEN]
Kernel data file for CSI output.
Definition: mptrac.h:3161
int grid_type
Type of grid data files (0=ASCII, 1=netCDF).
Definition: mptrac.h:3263
double csi_lon0
Lower longitude of gridded CSI data [deg].
Definition: mptrac.h:3188
int qnt_pbl
Quantity array index for boundary layer pressure.
Definition: mptrac.h:2429
int grid_stddev
Include standard deviations in grid output (0=no, 1=yes).
Definition: mptrac.h:3233
int qnt_psice
Quantity array index for saturation pressure over ice.
Definition: mptrac.h:2552
int met_geopot_sx
Longitudinal smoothing of geopotential heights.
Definition: mptrac.h:2802
int met_sy
Smoothing for latitudes.
Definition: mptrac.h:2775
int qnt_ps
Quantity array index for surface pressure.
Definition: mptrac.h:2399
char prof_obsfile[LEN]
Observation data file for profile output.
Definition: mptrac.h:3269
int qnt_zs
Quantity array index for surface geopotential height.
Definition: mptrac.h:2405
int prof_nz
Number of altitudes of gridded profile data.
Definition: mptrac.h:3272
double csi_dt_out
Time step for CSI output [s].
Definition: mptrac.h:3164
int met_cape
Convective available potential energy data (0=file, 1=calculate).
Definition: mptrac.h:2811
double csi_modmin
Minimum column density to trigger detection [kg/m^2].
Definition: mptrac.h:3173
int met_sx
Smoothing for longitudes.
Definition: mptrac.h:2772
double met_cms_eps_iwc
cmultiscale compression epsilon for cloud ice water content.
Definition: mptrac.h:2754
double met_cms_eps_swc
cmultiscale compression epsilon for cloud snow water content.
Definition: mptrac.h:2757
char grid_kernel[LEN]
Kernel data file for grid output.
Definition: mptrac.h:3215
double met_cms_eps_v
cmultiscale compression epsilon for meridional wind.
Definition: mptrac.h:2733
double prof_z0
Lower altitude of gridded profile data [km].
Definition: mptrac.h:3275
int qnt_w
Quantity array index for vertical velocity.
Definition: mptrac.h:2462
double met_tropo_pv
Dynamical tropopause potential vorticity threshold [PVU].
Definition: mptrac.h:2827
int prof_nx
Number of longitudes of gridded profile data.
Definition: mptrac.h:3281
int qnt_stat
Quantity array index for station flag.
Definition: mptrac.h:2384
int met_mpi_share
Use MPI to share meteo (0=no, 1=yes).
Definition: mptrac.h:2842
int qnt_vz
Quantity array index for vertical velocity.
Definition: mptrac.h:2588
int qnt_ho2
Quantity array index for HO2 volume mixing ratio (climatology).
Definition: mptrac.h:2522
double csi_z1
Upper altitude of gridded CSI data [km].
Definition: mptrac.h:3182
double stat_t0
Start time for station output [s].
Definition: mptrac.h:3326
int atm_type_out
Type of atmospheric data files for output (-1=same as ATM_TYPE, 0=ASCII, 1=binary,...
Definition: mptrac.h:3146
int met_nlev
Number of meteo data model levels.
Definition: mptrac.h:2793
double dt_kpp
Time step for KPP chemistry [s].
Definition: mptrac.h:3073
char csi_basename[LEN]
Basename of CSI data files.
Definition: mptrac.h:3158
int qnt_shf
Quantity array index for surface sensible heat flux.
Definition: mptrac.h:2420
int qnt_vs
Quantity array index for surface meridional wind.
Definition: mptrac.h:2411
double vtk_dt_out
Time step for VTK data output [s].
Definition: mptrac.h:3335
double conv_dt
Time interval for convection module [s].
Definition: mptrac.h:2908
char sample_obsfile[LEN]
Observation data file for sample output.
Definition: mptrac.h:3305
int qnt_hno3
Quantity array index for HNO3 volume mixing ratio (climatology).
Definition: mptrac.h:2513
char grid_basename[LEN]
Basename of grid data files.
Definition: mptrac.h:3212
int qnt_h2ot
Quantity array index for tropopause water vapor volume mixing ratio.
Definition: mptrac.h:2441
int qnt_rh
Quantity array index for relative humidity over water.
Definition: mptrac.h:2561
double met_cms_eps_cc
cmultiscale compression epsilon for cloud cover.
Definition: mptrac.h:2760
double met_pbl_max
Maximum depth of planetary boundary layer [km].
Definition: mptrac.h:2820
int met_dx
Stride for longitudes.
Definition: mptrac.h:2763
int qnt_destination
Quantity array index for destination subdomain in domain decomposition.
Definition: mptrac.h:2657
int met_convention
Meteo data layout (0=[lev, lat, lon], 1=[lon, lat, lev]).
Definition: mptrac.h:2682
int qnt_zeta_d
Quantity array index for diagnosed zeta vertical coordinate.
Definition: mptrac.h:2573
int tracer_chem
Switch for first order tracer chemistry module (0=off, 1=on).
Definition: mptrac.h:3076
int diffusion
Diffusion scheme (0=off, 1=fixed-K, 2=PBL).
Definition: mptrac.h:2869
int qnt_zg
Quantity array index for geopotential height.
Definition: mptrac.h:2444
double vtk_offset
Vertical offset for VTK data [km].
Definition: mptrac.h:3344
int qnt_v
Quantity array index for meridional wind.
Definition: mptrac.h:2459
double met_zfp_tol[METVAR]
ZFP compression tolerance.
Definition: mptrac.h:2711
int qnt_oh
Quantity array index for OH volume mixing ratio (climatology).
Definition: mptrac.h:2516
int qnt_h2o
Quantity array index for water vapor volume mixing ratio.
Definition: mptrac.h:2465
int prof_ny
Number of latitudes of gridded profile data.
Definition: mptrac.h:3290
int qnt_rhice
Quantity array index for relative humidity over ice.
Definition: mptrac.h:2564
int qnt_rho
Quantity array index for density of air.
Definition: mptrac.h:2453
double sample_dz
Layer depth for sample output [km].
Definition: mptrac.h:3311
int obs_type
Type of observation data files (0=ASCII, 1=netCDF).
Definition: mptrac.h:3155
int grid_nc_quant[NQ]
Number of digits for quantization of netCDF grid data files (0=off).
Definition: mptrac.h:3230
double met_cms_eps_lwc
cmultiscale compression epsilon for cloud liquid water content.
Definition: mptrac.h:2748
int qnt_us
Quantity array index for surface zonal wind.
Definition: mptrac.h:2408
double met_cms_eps_z
cmultiscale compression epsilon for geopotential height.
Definition: mptrac.h:2724
double grid_lon1
Upper longitude of gridded data [deg].
Definition: mptrac.h:3251
char atm_basename[LEN]
Basename of atmospheric data files.
Definition: mptrac.h:3125
int qnt_pt
Quantity array index for tropopause pressure.
Definition: mptrac.h:2432
int qnt_cl
Quantity array index for total column cloud water.
Definition: mptrac.h:2492
double prof_z1
Upper altitude of gridded profile data [km].
Definition: mptrac.h:3278
double met_lev_hyam[EP]
Meteo data model level a coefficients.
Definition: mptrac.h:2796
int qnt_t
Quantity array index for temperature.
Definition: mptrac.h:2450
int atm_filter
Time filter for atmospheric data output (0=none, 1=missval, 2=remove).
Definition: mptrac.h:3134
int kpp_chem
Switch for KPP chemistry module (0=off, 1=on).
Definition: mptrac.h:3070
char ens_basename[LEN]
Basename of ensemble data file.
Definition: mptrac.h:3206
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:2686
double csi_z0
Lower altitude of gridded CSI data [km].
Definition: mptrac.h:3179
int qnt_lapse
Quantity array index for lapse rate.
Definition: mptrac.h:2582
double stat_lat
Latitude of station [deg].
Definition: mptrac.h:3320
int grid_ny
Number of latitudes of gridded data.
Definition: mptrac.h:3254
double met_detrend
FWHM of horizontal Gaussian used for detrending [km].
Definition: mptrac.h:2781
int dd_nbr_neighbours
Number of neighbours to communicate with.
Definition: mptrac.h:3356
double met_cms_eps_t
cmultiscale compression epsilon for temperature.
Definition: mptrac.h:2727
int qnt_cape
Quantity array index for convective available potential energy (CAPE).
Definition: mptrac.h:2504
int qnt_o3c
Quantity array index for total column ozone.
Definition: mptrac.h:2510
int grid_nz
Number of altitudes of gridded data.
Definition: mptrac.h:3236
int qnt_nss
Quantity array index for northward turbulent surface stress.
Definition: mptrac.h:2417
double ens_dt_out
Time step for ensemble output [s].
Definition: mptrac.h:3209
char sample_basename[LEN]
Basename of sample data file.
Definition: mptrac.h:3299
int atm_stride
Particle index stride for atmospheric data files.
Definition: mptrac.h:3137
int met_relhum
Try to read relative humidity (0=no, 1=yes).
Definition: mptrac.h:2808
double atm_dt_out
Time step for atmospheric data output [s].
Definition: mptrac.h:3131
double prof_lat1
Upper latitude of gridded profile data [deg].
Definition: mptrac.h:3296
int met_cms_batch
cmultiscale batch size.
Definition: mptrac.h:2714
double psc_h2o
H2O volume mixing ratio for PSC analysis.
Definition: mptrac.h:3115
int met_sp
Smoothing for pressure levels.
Definition: mptrac.h:2778
double prof_lon0
Lower longitude of gridded profile data [deg].
Definition: mptrac.h:3284
int qnt_pct
Quantity array index for cloud top pressure.
Definition: mptrac.h:2486
int qnt_mloss_kpp
Quantity array index for total mass loss due to KPP chemistry.
Definition: mptrac.h:2534
int qnt_psat
Quantity array index for saturation pressure over water.
Definition: mptrac.h:2549
double met_lev_hybm[EP]
Meteo data model level b coefficients.
Definition: mptrac.h:2799
double prof_lat0
Lower latitude of gridded profile data [deg].
Definition: mptrac.h:3293
int qnt_cin
Quantity array index for convective inhibition (CIN).
Definition: mptrac.h:2507
double psc_hno3
HNO3 volume mixing ratio for PSC analysis.
Definition: mptrac.h:3118
double prof_lon1
Upper longitude of gridded profile data [deg].
Definition: mptrac.h:3287
double met_cms_eps_rwc
cmultiscale compression epsilon for cloud rain water content.
Definition: mptrac.h:2751
int met_nc_quant
Number of digits for quantization of netCDF meteo files (0=off).
Definition: mptrac.h:2702
int h2o2_chem_reaction
Reaction type for H2O2 chemistry (0=none, 1=SO2).
Definition: mptrac.h:3067
int atm_nc_quant[NQ]
Number of digits for quantization of netCDF atmospheric data files (0=off).
Definition: mptrac.h:3152
double met_cms_eps_o3
cmultiscale compression epsilon for ozone.
Definition: mptrac.h:2745
int met_cms_zstd
cmultiscale zstd compression (0=off, 1=on).
Definition: mptrac.h:2717
int grid_sparse
Sparse output in grid data files (0=no, 1=yes).
Definition: mptrac.h:3224
char vtk_basename[LEN]
Basename of VTK data files.
Definition: mptrac.h:3332
int qnt_tt
Quantity array index for tropopause temperature.
Definition: mptrac.h:2435
int met_nc_level
zlib compression level of netCDF meteo files (0=off).
Definition: mptrac.h:2699
double mixing_dt
Time interval for mixing [s].
Definition: mptrac.h:2995
double vtk_scale
Vertical scaling factor for VTK data.
Definition: mptrac.h:3341
double met_cms_eps_w
cmultiscale compression epsilon for vertical velocity.
Definition: mptrac.h:2736
int qnt_pv
Quantity array index for potential vorticity.
Definition: mptrac.h:2591
int qnt_sst
Quantity array index for sea surface temperature.
Definition: mptrac.h:2426
int atm_nc_level
zlib compression level of netCDF atmospheric data files (0=off).
Definition: mptrac.h:3149
int met_cms_heur
cmultiscale coarsening heuristics (0=default, 1=mean diff, 2=median diff, 3=max diff).
Definition: mptrac.h:2721
int qnt_sh
Quantity array index for specific humidity.
Definition: mptrac.h:2558
int qnt_ess
Quantity array index for eastward turbulent surface stress.
Definition: mptrac.h:2414
int met_dy
Stride for latitudes.
Definition: mptrac.h:2766
int dd_subdomains_zonal
Zonal subdomain number.
Definition: mptrac.h:3350
int qnt_idx
Quantity array index for air parcel IDs.
Definition: mptrac.h:2378
double met_tropo_theta
Dynamical tropopause potential temperature threshold [K].
Definition: mptrac.h:2830
int qnt_rwc
Quantity array index for cloud rain water content.
Definition: mptrac.h:2474
char qnt_longname[NQ][LEN]
Quantity long names.
Definition: mptrac.h:2369
int met_zfp_prec[METVAR]
ZFP compression precision.
Definition: mptrac.h:2708
double sample_dx
Horizontal radius for sample output [km].
Definition: mptrac.h:3308
int vtk_stride
Particle index stride for VTK data.
Definition: mptrac.h:3338
char stat_basename[LEN]
Basename of station data file.
Definition: mptrac.h:3314
double grid_lat1
Upper latitude of gridded data [deg].
Definition: mptrac.h:3260
int dd_subdomains_meridional
Meridional subdomain number.
Definition: mptrac.h:3353
int qnt_zt
Quantity array index for tropopause geopotential height.
Definition: mptrac.h:2438
int qnt_cc
Quantity array index for cloud cover.
Definition: mptrac.h:2483
int qnt_plcl
Quantity array index for pressure at lifted condensation level (LCL).
Definition: mptrac.h:2495
double grid_dt_out
Time step for gridded data output [s].
Definition: mptrac.h:3221
int qnt_tdew
Quantity array index for dew point temperature.
Definition: mptrac.h:2594
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 ctl->met_type is 6, the data is read from grib files using the read_met_grib function.
  • If the met_type is not recognized, an error message is generated.
Author
Lars Hoffmann

Definition at line 5445 of file mptrac.c.

5449 {
5450
5451 /* Write info... */
5452 LOG(1, "Read meteo data: %s", filename);
5453
5454 /* Set rank... */
5455 int rank = 0;
5456#ifdef MPI
5457 if (ctl->met_mpi_share)
5458 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5459#endif
5460
5461 /* Check rank... */
5462 if (!ctl->met_mpi_share || rank == 0) {
5463
5464#ifdef DD
5465 /* Read netCDF data... */
5466 if (ctl->met_type == 0) {
5467 if (read_met_nc_dd(filename, ctl, met) != 1)
5468 return 0;
5469 }
5470#else
5471 /* Read netCDF data... */
5472 if (ctl->met_type == 0) {
5473 if (read_met_nc(filename, ctl, met) != 1)
5474 return 0;
5475 }
5476#endif
5477
5478 /* Read binary data... */
5479 else if (ctl->met_type >= 1 && ctl->met_type <= 5) {
5480 if (read_met_bin(filename, ctl, met) != 1)
5481 return 0;
5482 }
5483#ifdef ECCODES
5484 /* Read grib data... */
5485 else if (ctl->met_type == 6) {
5486 if (read_met_grib(filename, ctl, met) != 1)
5487 return 0;
5488 }
5489#endif
5490
5491 /* Not implemented... */
5492 else
5493 ERRMSG("MET_TYPE not implemented!");
5494
5495 /* Preprocessing for netCDF and grib files... */
5496 if (ctl->met_type == 0 || ctl->met_type == 6) {
5497
5498 /* Extrapolate data for lower boundary... */
5500
5501 /* Fix polar winds... */
5503
5504 /* Create periodic boundary conditions... */
5505#ifndef DD
5506 read_met_periodic(met);
5507#endif
5508
5509 /* Downsampling... */
5510 read_met_sample(ctl, met);
5511
5512 /* Calculate geopotential heights... */
5513 read_met_geopot(ctl, met);
5514
5515 /* Calculate potential vorticity... */
5516 read_met_pv(met);
5517
5518 /* Calculate boundary layer data... */
5519 read_met_pbl(ctl, met);
5520
5521 /* Calculate tropopause data... */
5522 read_met_tropo(ctl, clim, met);
5523
5524 /* Calculate cloud properties... */
5525 read_met_cloud(met);
5526
5527 /* Calculate convective available potential energy... */
5528 read_met_cape(ctl, clim, met);
5529
5530 /* Calculate total column ozone... */
5531 read_met_ozone(met);
5532
5533 /* Detrending... */
5534 read_met_detrend(ctl, met);
5535
5536 /* Check meteo data and smooth zeta profiles ... */
5537 read_met_monotonize(ctl, met);
5538 }
5539 }
5540
5541 /* Broadcast data via MPI... */
5542#ifdef MPI
5543 if (ctl->met_mpi_share) {
5544
5545 /* Set timer... */
5546 SELECT_TIMER("READ_MET_MPI_BCAST", "COMM", NVTX_SEND);
5547 LOG(2, "Broadcast data on rank %d...", rank);
5548
5549 /* Broadcast... */
5550 broadcast_large_data(met, sizeof(met_t));
5551 }
5552#endif
5553
5554 /* Return success... */
5555 return 1;
5556}
void read_met_geopot(const ctl_t *ctl, met_t *met)
Calculates geopotential heights from meteorological data.
Definition: mptrac.c:7148
void read_met_extrapolate(met_t *met)
Extrapolates meteorological data.
Definition: mptrac.c:7108
void read_met_sample(const ctl_t *ctl, met_t *met)
Downsamples meteorological data based on specified parameters.
Definition: mptrac.c:10050
void read_met_cloud(met_t *met)
Calculates cloud-related variables for each grid point.
Definition: mptrac.c:6947
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:9658
void read_met_detrend(const ctl_t *ctl, met_t *met)
Detrends meteorological data.
Definition: mptrac.c:7004
void read_met_monotonize(const ctl_t *ctl, met_t *met)
Makes zeta and pressure profiles monotone.
Definition: mptrac.c:8742
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
Definition: mptrac.c:9795
void read_met_ozone(met_t *met)
Calculates the total column ozone from meteorological ozone data.
Definition: mptrac.c:10021
void read_met_pv(met_t *met)
Calculates potential vorticity (PV) from meteorological data.
Definition: mptrac.c:9915
int read_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a NetCDF file and processes it.
Definition: mptrac.c:8827
int read_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a binary file.
Definition: mptrac.c:6569
void read_met_polar_winds(met_t *met)
Applies a fix for polar winds in meteorological data.
Definition: mptrac.c:9856
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:6832
int read_met_nc_dd(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a NetCDF file and processes it.
int read_met_grib(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a grib file and processes it.
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.
mpi_infoMPI information required for the domain decomposition.
Authors
Lars Hoffmann

Definition at line 5571 of file mptrac.c.

5578 {
5579#endif
5580 /* Initialize modules... */
5581 if (t == ctl->t_start) {
5582
5583 /* Initialize isosurface data... */
5584 if (ctl->isosurf >= 1 && ctl->isosurf <= 4)
5585 module_isosurf_init(ctl, cache, *met0, *met1, atm);
5586
5587 /* Initialize advection... */
5588 module_advect_init(ctl, cache, *met0, *met1, atm);
5589
5590 /* Initialize chemistry... */
5591 module_chem_init(ctl, cache, clim, *met0, *met1, atm);
5592 }
5593
5594 /* Set time steps of air parcels... */
5595 module_timesteps(ctl, cache, *met0, atm, t);
5596
5597#ifndef DD
5598 /* Sort particles... */
5599 if (ctl->sort_dt > 0 && fmod(t, ctl->sort_dt) == 0)
5600 module_sort(ctl, *met0, atm);
5601#endif
5602
5603 /* Check positions (initial)... */
5604 module_position(cache, *met0, *met1, atm);
5605
5606 /* Advection... */
5607 if (ctl->advect > 0)
5608 module_advect(ctl, cache, *met0, *met1, atm);
5609
5610 /* Turbulent diffusion... */
5611 if (ctl->diffusion == 1
5612 && (ctl->turb_dx_pbl > 0 || ctl->turb_dz_pbl > 0
5613 || ctl->turb_dx_trop > 0 || ctl->turb_dz_trop > 0
5614 || ctl->turb_dx_strat > 0 || ctl->turb_dz_strat > 0))
5615 module_diff_turb(ctl, cache, clim, *met0, *met1, atm);
5616
5617 /* Mesoscale diffusion... */
5618 if (ctl->diffusion == 1 && (ctl->turb_mesox > 0 || ctl->turb_mesoz > 0))
5619 module_diff_meso(ctl, cache, *met0, *met1, atm);
5620
5621 /* Diffusion... */
5622 if (ctl->diffusion == 2)
5623 module_diff_pbl(ctl, cache, *met0, *met1, atm);
5624
5625 /* Convection... */
5626 if ((ctl->conv_mix_pbl || ctl->conv_cape >= 0)
5627 && (ctl->conv_dt <= 0 || fmod(t, ctl->conv_dt) == 0))
5628 module_convection(ctl, cache, *met0, *met1, atm);
5629
5630 /* Sedimentation... */
5631 if (ctl->qnt_rp >= 0 && ctl->qnt_rhop >= 0)
5632 module_sedi(ctl, cache, *met0, *met1, atm);
5633
5634 /* Isosurface... */
5635 if (ctl->isosurf >= 1 && ctl->isosurf <= 4)
5636 module_isosurf(ctl, cache, *met0, *met1, atm);
5637
5638 /* Check positions (final)... */
5639 module_position(cache, *met0, *met1, atm);
5640
5641 /* Interpolate meteo data... */
5642 if (ctl->met_dt_out > 0
5643 && (ctl->met_dt_out < ctl->dt_mod || fmod(t, ctl->met_dt_out) == 0))
5644 module_meteo(ctl, cache, clim, *met0, *met1, atm);
5645
5646 /* Check boundary conditions (initial)... */
5647 if ((ctl->bound_lat0 < ctl->bound_lat1)
5648 && (ctl->bound_p0 > ctl->bound_p1))
5649 module_bound_cond(ctl, cache, clim, *met0, *met1, atm);
5650
5651 /* Initialize quantity of total loss rate... */
5652 if (ctl->qnt_loss_rate >= 0) {
5653 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,atm)") {
5654 atm->q[ctl->qnt_loss_rate][ip] = 0;
5655 }
5656 }
5657
5658 /* Decay of particle mass... */
5659 if (ctl->tdec_trop > 0 && ctl->tdec_strat > 0)
5660 module_decay(ctl, cache, clim, atm);
5661
5662 /* Interparcel mixing... */
5663 if (ctl->mixing_trop >= 0 && ctl->mixing_strat >= 0
5664 && (ctl->mixing_dt <= 0 || fmod(t, ctl->mixing_dt) == 0))
5665 module_mixing(ctl, clim, atm, t);
5666
5667 /* Calculate the tracer vmr in the chemistry grid... */
5668 if (ctl->oh_chem_reaction != 0 || ctl->h2o2_chem_reaction != 0
5669 || (ctl->kpp_chem && fmod(t, ctl->dt_kpp) == 0))
5670 module_chem_grid(ctl, *met0, *met1, atm, t);
5671
5672 /* OH chemistry... */
5673 if (ctl->oh_chem_reaction != 0)
5674 module_oh_chem(ctl, cache, clim, *met0, *met1, atm);
5675
5676 /* H2O2 chemistry (for SO2 aqueous phase oxidation)... */
5677 if (ctl->h2o2_chem_reaction != 0)
5678 module_h2o2_chem(ctl, cache, clim, *met0, *met1, atm);
5679
5680 /* First-order tracer chemistry... */
5681 if (ctl->tracer_chem)
5682 module_tracer_chem(ctl, cache, clim, *met0, *met1, atm);
5683
5684 /* Domain decomposition... */
5685#ifdef DD
5687 module_dd(ctl, atm, cache, mpi_info, met0);
5688#endif
5689
5690 /* KPP chemistry... */
5691 if (ctl->kpp_chem && fmod(t, ctl->dt_kpp) == 0) {
5692#ifdef KPP
5693 module_kpp_chem(ctl, cache, clim, *met0, *met1, atm);
5694#else
5695 ERRMSG("Code was compiled without KPP!");
5696#endif
5697 }
5698
5699 /* Wet deposition... */
5700 if ((ctl->wet_depo_ic_a > 0 || ctl->wet_depo_ic_h[0] > 0)
5701 && (ctl->wet_depo_bc_a > 0 || ctl->wet_depo_bc_h[0] > 0))
5702 module_wet_depo(ctl, cache, *met0, *met1, atm);
5703
5704 /* Dry deposition... */
5705 if (ctl->dry_depo_vdep > 0)
5706 module_dry_depo(ctl, cache, *met0, *met1, atm);
5707
5708 /* Check boundary conditions (final)... */
5709 if ((ctl->bound_lat0 < ctl->bound_lat1)
5710 && (ctl->bound_p0 > ctl->bound_p1))
5711 module_bound_cond(ctl, cache, clim, *met0, *met1, atm);
5712}
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:2094
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:3934
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:3260
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:2647
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:2532
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:3365
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:3085
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:4077
void module_chem_grid(const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double tt)
Computes gridded chemical tracer concentrations (volume mixing ratio) from individual air parcel mass...
Definition: mptrac.c:2370
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:3809
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:2574
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:2274
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:2247
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:3622
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:2686
void module_sort(const ctl_t *ctl, met_t *met0, atm_t *atm)
Sort particles according to box index.
Definition: mptrac.c:3838
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:2888
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:4007
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:3003
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:2763
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:3155
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:3538
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:2940
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 5828 of file mptrac.c.

5832 {
5833
5834 /* Set timer... */
5835 SELECT_TIMER("WRITE_ATM", "OUTPUT", NVTX_WRITE);
5836
5837 /* Write info... */
5838 LOG(1, "Write atmospheric data: %s", filename);
5839
5840 /* Write ASCII data... */
5841 if (ctl->atm_type_out == 0)
5842 write_atm_asc(filename, ctl, atm, t);
5843
5844 /* Write binary data... */
5845 else if (ctl->atm_type_out == 1)
5846 write_atm_bin(filename, ctl, atm);
5847
5848 /* Write netCDF data... */
5849 else if (ctl->atm_type_out == 2)
5850 write_atm_nc(filename, ctl, atm);
5851
5852 /* Write CLaMS trajectory data... */
5853 else if (ctl->atm_type_out == 3)
5854 write_atm_clams_traj(filename, ctl, atm, t);
5855
5856 /* Write CLaMS pos data... */
5857 else if (ctl->atm_type_out == 4)
5858 write_atm_clams(filename, ctl, atm);
5859
5860 /* Error... */
5861 else
5862 ERRMSG("Atmospheric data type not supported!");
5863
5864 /* Write info... */
5865 double mini, maxi;
5866 LOG(2, "Number of particles: %d", atm->np);
5867 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
5868 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
5869 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
5870 LOG(2, "Altitude range: %g ... %g km", Z(maxi), Z(mini));
5871 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
5872 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
5873 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
5874 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
5875 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
5876 for (int iq = 0; iq < ctl->nq; iq++) {
5877 char msg[5 * LEN];
5878 sprintf(msg, "Quantity %s range: %s ... %s %s",
5879 ctl->qnt_name[iq], ctl->qnt_format[iq],
5880 ctl->qnt_format[iq], ctl->qnt_unit[iq]);
5881 gsl_stats_minmax(&mini, &maxi, atm->q[iq], 1, (size_t) atm->np);
5882 LOG(2, msg, mini, maxi);
5883 }
5884}
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:11051
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:10866
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:10998
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:10948
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:11209
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 5888 of file mptrac.c.

5891 {
5892
5893 /* Set timer... */
5894 SELECT_TIMER("WRITE_MET", "OUTPUT", NVTX_WRITE);
5895
5896 /* Write info... */
5897 LOG(1, "Write meteo data: %s", filename);
5898
5899 /* Check compression flags... */
5900#ifndef ZFP
5901 if (ctl->met_type == 3)
5902 ERRMSG("MPTRAC was compiled without zfp compression!");
5903#endif
5904#ifndef ZSTD
5905 if (ctl->met_type == 4)
5906 ERRMSG("MPTRAC was compiled without zstd compression!");
5907#endif
5908#ifndef CMS
5909 if (ctl->met_type == 5)
5910 ERRMSG("MPTRAC was compiled without cmultiscale compression!");
5911#endif
5912
5913 /* Write netCDF data... */
5914 if (ctl->met_type == 0)
5915 write_met_nc(filename, ctl, met);
5916
5917 /* Write binary data... */
5918 else if (ctl->met_type >= 1 && ctl->met_type <= 5)
5919 write_met_bin(filename, ctl, met);
5920
5921 /* Not implemented... */
5922 else
5923 ERRMSG("MET_TYPE not implemented!");
5924}
void write_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a NetCDF file.
Definition: mptrac.c:12273
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:12056
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 5928 of file mptrac.c.

5934 {
5935
5936 char ext[10], filename[2 * LEN];
5937
5938 double r;
5939
5940 int year, mon, day, hour, min, sec;
5941
5942 /* Get time... */
5943 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
5944
5945 /* Update host... */
5946 if ((ctl->atm_basename[0] != '-' && fmod(t, ctl->atm_dt_out) == 0)
5947 || (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0)
5948 || (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0)
5949 || ctl->csi_basename[0] != '-' || ctl->prof_basename[0] != '-'
5950 || ctl->sample_basename[0] != '-' || ctl->stat_basename[0] != '-'
5951 || (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0))
5952 mptrac_update_host(NULL, NULL, NULL, NULL, NULL, atm);
5953
5954 /* Write atmospheric data... */
5955 if (ctl->atm_basename[0] != '-' &&
5956 (fmod(t, ctl->atm_dt_out) == 0 || t == ctl->t_stop)) {
5957 if (ctl->atm_type_out == 0)
5958 sprintf(ext, "tab");
5959 else if (ctl->atm_type_out == 1)
5960 sprintf(ext, "bin");
5961 else if (ctl->atm_type_out == 2)
5962 sprintf(ext, "nc");
5963 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
5964 dirname, ctl->atm_basename, year, mon, day, hour, min, ext);
5965 mptrac_write_atm(filename, ctl, atm, t);
5966 }
5967
5968 /* Write gridded data... */
5969 if (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0) {
5970 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
5971 dirname, ctl->grid_basename, year, mon, day, hour, min,
5972 ctl->grid_type == 0 ? "tab" : "nc");
5973 write_grid(filename, ctl, met0, met1, atm, t);
5974 }
5975
5976 /* Write CSI data... */
5977 if (ctl->csi_basename[0] != '-') {
5978 sprintf(filename, "%s/%s.tab", dirname, ctl->csi_basename);
5979 write_csi(filename, ctl, atm, t);
5980 }
5981
5982 /* Write ensemble data... */
5983 if (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0) {
5984 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
5985 dirname, ctl->ens_basename, year, mon, day, hour, min);
5986 write_ens(filename, ctl, atm, t);
5987 }
5988
5989 /* Write profile data... */
5990 if (ctl->prof_basename[0] != '-') {
5991 sprintf(filename, "%s/%s.tab", dirname, ctl->prof_basename);
5992 write_prof(filename, ctl, met0, met1, atm, t);
5993 }
5994
5995 /* Write sample data... */
5996 if (ctl->sample_basename[0] != '-') {
5997 sprintf(filename, "%s/%s.tab", dirname, ctl->sample_basename);
5998 write_sample(filename, ctl, met0, met1, atm, t);
5999 }
6000
6001 /* Write station data... */
6002 if (ctl->stat_basename[0] != '-') {
6003 sprintf(filename, "%s/%s.tab", dirname, ctl->stat_basename);
6004 write_station(filename, ctl, atm, t);
6005 }
6006
6007 /* Write VTK data... */
6008 if (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0) {
6009 static int nvtk;
6010 if (t == ctl->t_start)
6011 nvtk = 0;
6012 sprintf(filename, "%s/%s_%05d.vtk", dirname, ctl->vtk_basename, ++nvtk);
6013 write_vtk(filename, ctl, atm, t);
6014 }
6015}
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:5828
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:11534
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:12496
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:5772
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:12885
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:12971
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:12723
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:11631
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:11258
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 5716 of file mptrac.c.

5722 {
5723
5724 /* Update GPU... */
5725 if (ctl != NULL) {
5726#ifdef _OPENACC
5727 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5728#pragma acc update device(ctl[:1])
5729#endif
5730 }
5731
5732 if (cache != NULL) {
5733#ifdef _OPENACC
5734 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5735#pragma acc update device(cache[:1])
5736#endif
5737 }
5738
5739 if (clim != NULL) {
5740#ifdef _OPENACC
5741 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5742#pragma acc update device(clim[:1])
5743#endif
5744 }
5745
5746 if (met0 != NULL) {
5747#ifdef _OPENACC
5748 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5749 met_t *met0up = *met0;
5750#pragma acc update device(met0up[:1])
5751#endif
5752 }
5753
5754 if (met1 != NULL) {
5755#ifdef _OPENACC
5756 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5757 met_t *met1up = *met1;
5758#pragma acc update device(met1up[:1])
5759#endif
5760 }
5761
5762 if (atm != NULL) {
5763#ifdef _OPENACC
5764 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5765#pragma acc update device(atm[:1])
5766#endif
5767 }
5768}

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

5778 {
5779
5780 /* Update GPU... */
5781 if (ctl != NULL) {
5782#ifdef _OPENACC
5783 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5784#pragma acc update host(ctl[:1])
5785#endif
5786 }
5787
5788 if (cache != NULL) {
5789#ifdef _OPENACC
5790 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5791#pragma acc update host(cache[:1])
5792#endif
5793 }
5794
5795 if (clim != NULL) {
5796#ifdef _OPENACC
5797 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5798#pragma acc update host(clim[:1])
5799#endif
5800 }
5801
5802 if (met0 != NULL) {
5803#ifdef _OPENACC
5804 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5805 met_t *met0up = *met0;
5806#pragma acc update host(met0up[:1])
5807#endif
5808 }
5809
5810 if (met1 != NULL) {
5811#ifdef _OPENACC
5812 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5813 met_t *met1up = *met1;
5814#pragma acc update host(met1up[:1])
5815#endif
5816 }
5817
5818 if (atm != NULL) {
5819#ifdef _OPENACC
5820 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5821#pragma acc update host(atm[:1])
5822#endif
5823 }
5824}

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

6022 {
6023
6024 /* Check water vapor volume mixing ratio... */
6025 const double h2o_help = MAX(h2o, 0.1e-6);
6026
6027 /* Calculate T_NAT... */
6028 const double p_hno3 = hno3 * p / 1.333224;
6029 const double p_h2o = h2o_help * p / 1.333224;
6030 const double a = 0.009179 - 0.00088 * log10(p_h2o);
6031 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
6032 const double c = -11397.0 / a;
6033 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
6034 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
6035 if (x2 > 0)
6036 tnat = x2;
6037
6038 return tnat;
6039}

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

6048 {
6049
6050 /* Get pressure range... */
6051 const double p1 = pbl - ctl->conv_pbl_trans * (ps - pbl);
6052 const double p0 = pbl;
6053
6054 /* Get weighting factor... */
6055 if (atm->p[ip] > p0)
6056 return 1;
6057 else if (atm->p[ip] < p1)
6058 return 0;
6059 else
6060 return LIN(p0, 1.0, p1, 0.0, atm->p[ip]);
6061}

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

6068 {
6069
6070 /* Open file... */
6071 FILE *in;
6072 if (!(in = fopen(filename, "r"))) {
6073 WARN("Cannot open file!");
6074 return 0;
6075 }
6076
6077 /* Read line... */
6078 char line[LEN];
6079 while (fgets(line, LEN, in)) {
6080
6081 /* Read data... */
6082 char *tok;
6083 TOK(line, tok, "%lg", atm->time[atm->np]);
6084 TOK(NULL, tok, "%lg", atm->p[atm->np]);
6085 TOK(NULL, tok, "%lg", atm->lon[atm->np]);
6086 TOK(NULL, tok, "%lg", atm->lat[atm->np]);
6087 for (int iq = 0; iq < ctl->nq; iq++)
6088 TOK(NULL, tok, "%lg", atm->q[iq][atm->np]);
6089
6090 /* Convert altitude to pressure... */
6091 atm->p[atm->np] = P(atm->p[atm->np]);
6092
6093 /* Increment data point counter... */
6094 if ((++atm->np) > NP)
6095 ERRMSG("Too many data points!");
6096 }
6097
6098 /* Close file... */
6099 fclose(in);
6100
6101 /* Return success... */
6102 return 1;
6103}
#define TOK(line, tok, format, var)
Get string tokens.
Definition: mptrac.h:1892

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

6110 {
6111
6112 /* Open file... */
6113 FILE *in;
6114 if (!(in = fopen(filename, "r")))
6115 return 0;
6116
6117 /* Check version of binary data... */
6118 int version;
6119 FREAD(&version, int,
6120 1,
6121 in);
6122 if (version != 100)
6123 ERRMSG("Wrong version of binary data!");
6124
6125 /* Read data... */
6126 FREAD(&atm->np, int,
6127 1,
6128 in);
6129 FREAD(atm->time, double,
6130 (size_t) atm->np,
6131 in);
6132 FREAD(atm->p, double,
6133 (size_t) atm->np,
6134 in);
6135 FREAD(atm->lon, double,
6136 (size_t) atm->np,
6137 in);
6138 FREAD(atm->lat, double,
6139 (size_t) atm->np,
6140 in);
6141 for (int iq = 0; iq < ctl->nq; iq++)
6142 FREAD(atm->q[iq], double,
6143 (size_t) atm->np,
6144 in);
6145
6146 /* Read final flag... */
6147 int final;
6148 FREAD(&final, int,
6149 1,
6150 in);
6151 if (final != 999)
6152 ERRMSG("Error while reading binary data!");
6153
6154 /* Close file... */
6155 fclose(in);
6156
6157 /* Return success... */
6158 return 1;
6159}

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

6166 {
6167
6168 int ncid, varid;
6169
6170 /* Open file... */
6171 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6172 return 0;
6173
6174 /* Get dimensions... */
6175 NC_INQ_DIM("NPARTS", &atm->np, 1, NP);
6176
6177 /* Get time... */
6178 if (nc_inq_varid(ncid, "TIME_INIT", &varid) == NC_NOERR) {
6179 NC(nc_get_var_double(ncid, varid, atm->time));
6180 } else {
6181 WARN("TIME_INIT not found use time instead!");
6182 double time_init;
6183 NC_GET_DOUBLE("time", &time_init, 1);
6184 for (int ip = 0; ip < atm->np; ip++) {
6185 atm->time[ip] = time_init;
6186 }
6187 }
6188
6189 /* Read zeta coordinate, pressure is optional... */
6190 if (ctl->advect_vert_coord == 1) {
6191 NC_GET_DOUBLE("ZETA", atm->q[ctl->qnt_zeta], 1);
6192 NC_GET_DOUBLE("PRESS", atm->p, 0);
6193 }
6194
6195 /* Read pressure, zeta coordinate is optional... */
6196 else {
6197 if (nc_inq_varid(ncid, "PRESS_INIT", &varid) == NC_NOERR) {
6198 NC(nc_get_var_double(ncid, varid, atm->p));
6199 } else {
6200 WARN("PRESS_INIT not found use PRESS instead!");
6201 nc_inq_varid(ncid, "PRESS", &varid);
6202 NC(nc_get_var_double(ncid, varid, atm->p));
6203 }
6204 }
6205
6206 /* Read further quantities if requested... */
6207 for (int iq = 0; iq < ctl->nq; iq++)
6208 NC_GET_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
6209
6210 /* Read longitude and latitude... */
6211 NC_GET_DOUBLE("LON", atm->lon, 1);
6212 NC_GET_DOUBLE("LAT", atm->lat, 1);
6213
6214 /* Close file... */
6215 NC(nc_close(ncid));
6216
6217 /* Return success... */
6218 return 1;
6219}
#define NC(cmd)
Execute a NetCDF command and check for errors.
Definition: mptrac.h:1214
#define NC_INQ_DIM(dimname, ptr, min, max)
Inquire the length of a dimension in a NetCDF file.
Definition: mptrac.h:1301
#define NC_GET_DOUBLE(varname, ptr, force)
Retrieve a double-precision variable from a NetCDF file.
Definition: mptrac.h:1273

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

6226 {
6227
6228 int ncid, varid;
6229
6230 /* Open file... */
6231 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6232 return 0;
6233
6234 /* Get dimensions... */
6235 NC_INQ_DIM("obs", &atm->np, 1, NP);
6236
6237 /* Read geolocations... */
6238 NC_GET_DOUBLE("time", atm->time, 1);
6239 NC_GET_DOUBLE("press", atm->p, 1);
6240 NC_GET_DOUBLE("lon", atm->lon, 1);
6241 NC_GET_DOUBLE("lat", atm->lat, 1);
6242
6243 /* Read variables... */
6244 for (int iq = 0; iq < ctl->nq; iq++)
6245 NC_GET_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
6246
6247 /* Close file... */
6248 NC(nc_close(ncid));
6249
6250 /* Return success... */
6251 return 1;
6252}

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

6258 {
6259
6260 int ncid, varid;
6261
6262 /* Write info... */
6263 LOG(1, "Read photolysis rates: %s", filename);
6264
6265 /* Open netCDF file... */
6266 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
6267 WARN("Photolysis rate data are missing!");
6268 return;
6269 }
6270
6271 /* Read pressure data... */
6272 NC_INQ_DIM("press", &photo->np, 2, CP);
6273 NC_GET_DOUBLE("press", photo->p, 1);
6274 if (photo->p[0] < photo->p[1])
6275 ERRMSG("Pressure data are not descending!");
6276
6277 /* Read total column ozone data... */
6278 NC_INQ_DIM("total_o3col", &photo->no3c, 2, CO3);
6279 NC_GET_DOUBLE("total_o3col", photo->o3c, 1);
6280 if (photo->o3c[0] > photo->o3c[1])
6281 ERRMSG("Total column ozone data are not ascending!");
6282
6283 /* Read solar zenith angle data... */
6284 NC_INQ_DIM("sza", &photo->nsza, 2, CSZA);
6285 NC_GET_DOUBLE("sza", photo->sza, 1);
6286 if (photo->sza[0] > photo->sza[1])
6287 ERRMSG("Solar zenith angle data are not ascending!");
6288
6289 /* Read data... */
6290 read_clim_photo_help(ncid, "J_N2O", photo, photo->n2o);
6291 read_clim_photo_help(ncid, "J_CCl4", photo, photo->ccl4);
6292 read_clim_photo_help(ncid, "J_CFC-11", photo, photo->ccl3f);
6293 read_clim_photo_help(ncid, "J_CFC-12", photo, photo->ccl2f2);
6294 read_clim_photo_help(ncid, "J_O2", photo, photo->o2);
6295 read_clim_photo_help(ncid, "J_O3b", photo, photo->o3_1);
6296 read_clim_photo_help(ncid, "J_O3a", photo, photo->o3_2);
6297 read_clim_photo_help(ncid, "J_H2O2", photo, photo->h2o2);
6298 read_clim_photo_help(ncid, "J_H2O", photo, photo->h2o);
6299
6300 /* Close netCDF file... */
6301 NC(nc_close(ncid));
6302
6303 /* Write info... */
6304 LOG(2, "Number of pressure levels: %d", photo->np);
6305 LOG(2, "Altitude levels: %g, %g ... %g km",
6306 Z(photo->p[0]), Z(photo->p[1]), Z(photo->p[photo->np - 1]));
6307 LOG(2, "Pressure levels: %g, %g ... %g hPa",
6308 photo->p[0], photo->p[1], photo->p[photo->np - 1]);
6309 LOG(2, "Number of solar zenith angles: %d", photo->nsza);
6310 LOG(2, "Solar zenith angles: %g, %g ... %g deg",
6311 RAD2DEG(photo->sza[0]), RAD2DEG(photo->sza[1]),
6312 RAD2DEG(photo->sza[photo->nsza - 1]));
6313 LOG(2, "Number of total column ozone values: %d", photo->no3c);
6314 LOG(2, "Total column ozone: %g, %g ... %g DU",
6315 photo->o3c[0], photo->o3c[1], photo->o3c[photo->no3c - 1]);
6316 LOG(2, "N2O photolysis rate: %g, %g ... %g s**-1",
6317 photo->n2o[0][0][0], photo->n2o[1][0][0],
6318 photo->n2o[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6319 LOG(2, "CCl4 photolysis rate: %g, %g ... %g s**-1",
6320 photo->ccl4[0][0][0], photo->ccl4[1][0][0],
6321 photo->ccl4[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6322 LOG(2, "CFC-11 photolysis rate: %g, %g ... %g s**-1",
6323 photo->ccl3f[0][0][0], photo->ccl3f[1][0][0],
6324 photo->ccl3f[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6325 LOG(2, "CFC-12 photolysis rate: %g, %g ... %g s**-1",
6326 photo->ccl2f2[0][0][0], photo->ccl2f2[1][0][0],
6327 photo->ccl2f2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6328 LOG(2, "O2 photolysis rate: %g, %g ... %g s**-1",
6329 photo->o2[0][0][0], photo->o2[1][0][0],
6330 photo->o2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6331 LOG(2, "O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
6332 photo->o3_1[0][0][0], photo->o3_1[1][0][0],
6333 photo->o3_1[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6334 LOG(2, "O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
6335 photo->o3_2[0][0][0], photo->o3_2[1][0][0],
6336 photo->o3_2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6337 LOG(2, "H2O2 photolysis rate: %g, %g ... %g s**-1",
6338 photo->h2o2[0][0][0], photo->h2o2[1][0][0],
6339 photo->h2o2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6340 LOG(2, "H2O photolysis rate: %g, %g ... %g s**-1",
6341 photo->h2o[0][0][0], photo->h2o[1][0][0],
6342 photo->h2o[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6343}
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:6347
#define CP
Maximum number of pressure levels for climatological data.
Definition: mptrac.h:359
#define CO3
Maximum number of total column ozone data for climatological data.
Definition: mptrac.h:354
#define CSZA
Maximum number of solar zenith angles for climatological data.
Definition: mptrac.h:364
double o3_1[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O1d + O2) [1/s].
Definition: mptrac.h:3517
double o2[CP][CSZA][CO3]
O2 photolysis rate [1/s].
Definition: mptrac.h:3514
double h2o2[CP][CSZA][CO3]
H2O2 photolysis rate [1/s].
Definition: mptrac.h:3523
double h2o[CP][CSZA][CO3]
H2O photolysis rate [1/s].
Definition: mptrac.h:3526
double o3_2[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O3p + O2) [1/s].
Definition: mptrac.h:3520
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 6347 of file mptrac.c.

6351 {
6352
6353 /* Allocate... */
6354 double *help;
6355 ALLOC(help, double,
6356 photo->np * photo->nsza * photo->no3c);
6357
6358 /* Read varible... */
6359 int varid;
6360 NC_GET_DOUBLE(varname, help, 1);
6361
6362 /* Copy data... */
6363 for (int ip = 0; ip < photo->np; ip++)
6364 for (int is = 0; is < photo->nsza; is++)
6365 for (int io = 0; io < photo->no3c; io++)
6366 var[ip][is][io] =
6367 help[ARRAY_3D(ip, is, photo->nsza, io, photo->no3c)];
6368
6369 /* Free... */
6370 free(help);
6371}

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

6377 {
6378
6379 /* Write info... */
6380 LOG(1, "Read climatological time series: %s", filename);
6381
6382 /* Open file... */
6383 FILE *in;
6384 if (!(in = fopen(filename, "r"))) {
6385 WARN("Cannot open file!");
6386 return 0;
6387 }
6388
6389 /* Read data... */
6390 char line[LEN];
6391 int nh = 0;
6392 while (fgets(line, LEN, in))
6393 if (sscanf(line, "%lg %lg", &ts->time[nh], &ts->vmr[nh]) == 2) {
6394
6395 /* Convert years to seconds... */
6396 ts->time[nh] = (ts->time[nh] - 2000.0) * 365.25 * 86400.;
6397
6398 /* Check data... */
6399 if (nh > 0 && ts->time[nh] <= ts->time[nh - 1])
6400 ERRMSG("Time series must be ascending!");
6401
6402 /* Count time steps... */
6403 if ((++nh) >= CTS)
6404 ERRMSG("Too many data points!");
6405 }
6406
6407 /* Close file... */
6408 fclose(in);
6409
6410 /* Check number of data points... */
6411 ts->ntime = nh;
6412 if (nh < 2)
6413 ERRMSG("Not enough data points!");
6414
6415 /* Write info... */
6416 LOG(2, "Number of time steps: %d", ts->ntime);
6417 LOG(2, "Time steps: %.2f, %.2f ... %.2f s", ts->time[0], ts->time[1],
6418 ts->time[nh - 1]);
6419 LOG(2, "Volume mixing ratio range: %g ... %g ppv",
6420 gsl_stats_min(ts->vmr, 1, (size_t) nh), gsl_stats_max(ts->vmr, 1,
6421 (size_t) nh));
6422
6423 /* Exit success... */
6424 return 1;
6425}
#define CTS
Maximum number of data points of climatological time series.
Definition: mptrac.h:374

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

6432 {
6433
6434 int ncid, varid, it, iy, iz, iz2, nt;
6435
6436 double *help, varmin = 1e99, varmax = -1e99;
6437
6438 /* Write info... */
6439 LOG(1, "Read %s data: %s", varname, filename);
6440
6441 /* Open netCDF file... */
6442 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
6443 WARN("%s climatology data are missing!", varname);
6444 return;
6445 }
6446
6447 /* Read pressure data... */
6448 NC_INQ_DIM("press", &zm->np, 2, CP);
6449 NC_GET_DOUBLE("press", zm->p, 1);
6450 if (zm->p[0] < zm->p[1])
6451 ERRMSG("Pressure data are not descending!");
6452
6453 /* Read latitudes... */
6454 NC_INQ_DIM("lat", &zm->nlat, 2, CY);
6455 NC_GET_DOUBLE("lat", zm->lat, 1);
6456 if (zm->lat[0] > zm->lat[1])
6457 ERRMSG("Latitude data are not ascending!");
6458
6459 /* Set time data (for monthly means)... */
6460 zm->ntime = 12;
6461 zm->time[0] = 1209600.00;
6462 zm->time[1] = 3888000.00;
6463 zm->time[2] = 6393600.00;
6464 zm->time[3] = 9072000.00;
6465 zm->time[4] = 11664000.00;
6466 zm->time[5] = 14342400.00;
6467 zm->time[6] = 16934400.00;
6468 zm->time[7] = 19612800.00;
6469 zm->time[8] = 22291200.00;
6470 zm->time[9] = 24883200.00;
6471 zm->time[10] = 27561600.00;
6472 zm->time[11] = 30153600.00;
6473
6474 /* Check number of timesteps... */
6475 NC_INQ_DIM("time", &nt, 12, 12);
6476
6477 /* Read data... */
6478 ALLOC(help, double,
6479 zm->nlat * zm->np * zm->ntime);
6480 NC_GET_DOUBLE(varname, help, 1);
6481 for (it = 0; it < zm->ntime; it++)
6482 for (iz = 0; iz < zm->np; iz++)
6483 for (iy = 0; iy < zm->nlat; iy++)
6484 zm->vmr[it][iz][iy] = help[ARRAY_3D(it, iz, zm->np, iy, zm->nlat)];
6485 free(help);
6486
6487 /* Fix data gaps... */
6488 for (it = 0; it < zm->ntime; it++)
6489 for (iy = 0; iy < zm->nlat; iy++)
6490 for (iz = 0; iz < zm->np; iz++) {
6491 if (zm->vmr[it][iz][iy] < 0) {
6492 for (iz2 = 0; iz2 < zm->np; iz2++)
6493 if (zm->vmr[it][iz2][iy] >= 0) {
6494 zm->vmr[it][iz][iy] = zm->vmr[it][iz2][iy];
6495 break;
6496 }
6497 for (iz2 = zm->np - 1; iz2 >= 0; iz2--)
6498 if (zm->vmr[it][iz2][iy] >= 0) {
6499 zm->vmr[it][iz][iy] = zm->vmr[it][iz2][iy];
6500 break;
6501 }
6502 }
6503 varmin = MIN(varmin, zm->vmr[it][iz][iy]);
6504 varmax = MAX(varmax, zm->vmr[it][iz][iy]);
6505 }
6506
6507 /* Close netCDF file... */
6508 NC(nc_close(ncid));
6509
6510 /* Write info... */
6511 LOG(2, "Number of time steps: %d", zm->ntime);
6512 LOG(2, "Time steps: %.2f, %.2f ... %.2f s",
6513 zm->time[0], zm->time[1], zm->time[zm->ntime - 1]);
6514 LOG(2, "Number of pressure levels: %d", zm->np);
6515 LOG(2, "Altitude levels: %g, %g ... %g km",
6516 Z(zm->p[0]), Z(zm->p[1]), Z(zm->p[zm->np - 1]));
6517 LOG(2, "Pressure levels: %g, %g ... %g hPa", zm->p[0],
6518 zm->p[1], zm->p[zm->np - 1]);
6519 LOG(2, "Number of latitudes: %d", zm->nlat);
6520 LOG(2, "Latitudes: %g, %g ... %g deg",
6521 zm->lat[0], zm->lat[1], zm->lat[zm->nlat - 1]);
6522 LOG(2, "%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
6523 varmax);
6524}
#define CY
Maximum number of latitudes for climatological data.
Definition: mptrac.h:349

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

6532 {
6533
6534 /* Write info... */
6535 LOG(1, "Read kernel function: %s", filename);
6536
6537 /* Open file... */
6538 FILE *in;
6539 if (!(in = fopen(filename, "r")))
6540 ERRMSG("Cannot open file!");
6541
6542 /* Read data... */
6543 char line[LEN];
6544 int n = 0;
6545 while (fgets(line, LEN, in))
6546 if (sscanf(line, "%lg %lg", &kz[n], &kw[n]) == 2) {
6547 if (n > 0 && kz[n] < kz[n - 1])
6548 ERRMSG("Height levels must be ascending!");
6549 if ((++n) >= EP)
6550 ERRMSG("Too many height levels!");
6551 }
6552
6553 /* Close file... */
6554 fclose(in);
6555
6556 /* Check number of data points... */
6557 *nk = n;
6558 if (n < 2)
6559 ERRMSG("Not enough height levels!");
6560
6561 /* Normalize kernel function... */
6562 const double kmax = gsl_stats_max(kw, 1, (size_t) n);
6563 for (int iz = 0; iz < n; iz++)
6564 kw[iz] /= kmax;
6565}

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

6572 {
6573
6574 FILE *in;
6575
6576 double r;
6577
6578 int year, mon, day, hour, min, sec;
6579
6580 /* Set timer... */
6581 SELECT_TIMER("READ_MET_BIN", "INPUT", NVTX_READ);
6582
6583 /* Open file... */
6584 if (!(in = fopen(filename, "r"))) {
6585 WARN("Cannot open file!");
6586 return 0;
6587 }
6588
6589 /* Check type of binary data... */
6590 int met_type;
6591 FREAD(&met_type, int,
6592 1,
6593 in);
6594 if (met_type != ctl->met_type)
6595 ERRMSG("Wrong MET_TYPE of binary data!");
6596
6597 /* Check version of binary data... */
6598 int version;
6599 FREAD(&version, int,
6600 1,
6601 in);
6602 if (version != 103)
6603 ERRMSG("Wrong version of binary data!");
6604
6605 /* Read time... */
6606 FREAD(&met->time, double,
6607 1,
6608 in);
6609 jsec2time(met->time, &year, &mon, &day, &hour, &min, &sec, &r);
6610 LOG(2, "Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
6611 met->time, year, mon, day, hour, min);
6612 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
6613 || day < 1 || day > 31 || hour < 0 || hour > 23)
6614 ERRMSG("Error while reading time!");
6615
6616 /* Read dimensions... */
6617 FREAD(&met->nx, int,
6618 1,
6619 in);
6620 LOG(2, "Number of longitudes: %d", met->nx);
6621 if (met->nx < 2 || met->nx > EX)
6622 ERRMSG("Number of longitudes out of range!");
6623
6624 FREAD(&met->ny, int,
6625 1,
6626 in);
6627 LOG(2, "Number of latitudes: %d", met->ny);
6628 if (met->ny < 2 || met->ny > EY)
6629 ERRMSG("Number of latitudes out of range!");
6630
6631 FREAD(&met->np, int,
6632 1,
6633 in);
6634 LOG(2, "Number of levels: %d", met->np);
6635 if (met->np < 2 || met->np > EP)
6636 ERRMSG("Number of levels out of range!");
6637
6638 /* Read grid... */
6639 FREAD(met->lon, double,
6640 (size_t) met->nx,
6641 in);
6642 LOG(2, "Longitudes: %g, %g ... %g deg",
6643 met->lon[0], met->lon[1], met->lon[met->nx - 1]);
6644
6645 FREAD(met->lat, double,
6646 (size_t) met->ny,
6647 in);
6648 LOG(2, "Latitudes: %g, %g ... %g deg",
6649 met->lat[0], met->lat[1], met->lat[met->ny - 1]);
6650
6651 FREAD(met->p, double,
6652 (size_t) met->np,
6653 in);
6654 LOG(2, "Altitude levels: %g, %g ... %g km",
6655 Z(met->p[0]), Z(met->p[1]), Z(met->p[met->np - 1]));
6656 LOG(2, "Pressure levels: %g, %g ... %g hPa",
6657 met->p[0], met->p[1], met->p[met->np - 1]);
6658
6659 /* Read surface data... */
6660 read_met_bin_2d(in, met, met->ps, "PS");
6661 read_met_bin_2d(in, met, met->ts, "TS");
6662 read_met_bin_2d(in, met, met->zs, "ZS");
6663 read_met_bin_2d(in, met, met->us, "US");
6664 read_met_bin_2d(in, met, met->vs, "VS");
6665 read_met_bin_2d(in, met, met->ess, "ESS");
6666 read_met_bin_2d(in, met, met->nss, "NSS");
6667 read_met_bin_2d(in, met, met->shf, "SHF");
6668 read_met_bin_2d(in, met, met->lsm, "LSM");
6669 read_met_bin_2d(in, met, met->sst, "SST");
6670 read_met_bin_2d(in, met, met->pbl, "PBL");
6671 read_met_bin_2d(in, met, met->pt, "PT");
6672 read_met_bin_2d(in, met, met->tt, "TT");
6673 read_met_bin_2d(in, met, met->zt, "ZT");
6674 read_met_bin_2d(in, met, met->h2ot, "H2OT");
6675 read_met_bin_2d(in, met, met->pct, "PCT");
6676 read_met_bin_2d(in, met, met->pcb, "PCB");
6677 read_met_bin_2d(in, met, met->cl, "CL");
6678 read_met_bin_2d(in, met, met->plcl, "PLCL");
6679 read_met_bin_2d(in, met, met->plfc, "PLFC");
6680 read_met_bin_2d(in, met, met->pel, "PEL");
6681 read_met_bin_2d(in, met, met->cape, "CAPE");
6682 read_met_bin_2d(in, met, met->cin, "CIN");
6683 read_met_bin_2d(in, met, met->o3c, "O3C");
6684
6685 /* Read level data... */
6686 read_met_bin_3d(in, ctl, met, met->z, "Z", -1e34f, 1e34f);
6687 read_met_bin_3d(in, ctl, met, met->t, "T", 0, 1e34f);
6688 read_met_bin_3d(in, ctl, met, met->u, "U", -1e34f, 1e34f);
6689 read_met_bin_3d(in, ctl, met, met->v, "V", -1e34f, 1e34f);
6690 read_met_bin_3d(in, ctl, met, met->w, "W", -1e34f, 1e34f);
6691 read_met_bin_3d(in, ctl, met, met->pv, "PV", -1e34f, 1e34f);
6692 read_met_bin_3d(in, ctl, met, met->h2o, "H2O", 0, 1e34f);
6693 read_met_bin_3d(in, ctl, met, met->o3, "O3", 0, 1e34f);
6694 read_met_bin_3d(in, ctl, met, met->lwc, "LWC", 0, 1e34f);
6695 read_met_bin_3d(in, ctl, met, met->rwc, "RWC", 0, 1e34f);
6696 read_met_bin_3d(in, ctl, met, met->iwc, "IWC", 0, 1e34f);
6697 read_met_bin_3d(in, ctl, met, met->swc, "SWC", 0, 1e34f);
6698 read_met_bin_3d(in, ctl, met, met->cc, "CC", 0, 1);
6699
6700 /* Read final flag... */
6701 int final;
6702 FREAD(&final, int,
6703 1,
6704 in);
6705 if (final != 999)
6706 ERRMSG("Error while reading binary data!");
6707
6708 /* Close file... */
6709 fclose(in);
6710
6711 /* Return success... */
6712 return 1;
6713}
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:6717
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:6746
#define EY
Maximum number of latitudes for meteo data.
Definition: mptrac.h:289
float zt[EX][EY]
Tropopause geopotential height [km].
Definition: mptrac.h:3733
float sst[EX][EY]
Sea surface temperature [K].
Definition: mptrac.h:3721
float rwc[EX][EY][EP]
Cloud rain water content [kg/kg].
Definition: mptrac.h:3793
float o3c[EX][EY]
Total column ozone [DU].
Definition: mptrac.h:3763
float cape[EX][EY]
Convective available potential energy [J/kg].
Definition: mptrac.h:3757
float pct[EX][EY]
Cloud top pressure [hPa].
Definition: mptrac.h:3739
float shf[EX][EY]
Surface sensible heat flux [W/m^2].
Definition: mptrac.h:3715
float lwc[EX][EY][EP]
Cloud liquid water content [kg/kg].
Definition: mptrac.h:3790
float us[EX][EY]
Surface zonal wind [m/s].
Definition: mptrac.h:3703
float cc[EX][EY][EP]
Cloud cover [1].
Definition: mptrac.h:3802
float ts[EX][EY]
Surface temperature [K].
Definition: mptrac.h:3697
float ess[EX][EY]
Eastward turbulent surface stress [N/m^2].
Definition: mptrac.h:3709
float pcb[EX][EY]
Cloud bottom pressure [hPa].
Definition: mptrac.h:3742
float pel[EX][EY]
Pressure at equilibrium level (EL) [hPa].
Definition: mptrac.h:3754
float cin[EX][EY]
Convective inhibition [J/kg].
Definition: mptrac.h:3760
float plcl[EX][EY]
Pressure at lifted condensation level (LCL) [hPa].
Definition: mptrac.h:3748
float tt[EX][EY]
Tropopause temperature [K].
Definition: mptrac.h:3730
float pbl[EX][EY]
Boundary layer pressure [hPa].
Definition: mptrac.h:3724
float vs[EX][EY]
Surface meridional wind [m/s].
Definition: mptrac.h:3706
float lsm[EX][EY]
Land-sea mask [1].
Definition: mptrac.h:3718
float iwc[EX][EY][EP]
Cloud ice water content [kg/kg].
Definition: mptrac.h:3796
float h2ot[EX][EY]
Tropopause water vapor volume mixing ratio [ppv].
Definition: mptrac.h:3736
float pv[EX][EY][EP]
Potential vorticity [PVU].
Definition: mptrac.h:3781
float cl[EX][EY]
Total column cloud water [kg/m^2].
Definition: mptrac.h:3745
float nss[EX][EY]
Northward turbulent surface stress [N/m^2].
Definition: mptrac.h:3712
float plfc[EX][EY]
Pressure at level of free convection (LFC) [hPa].
Definition: mptrac.h:3751
float swc[EX][EY][EP]
Cloud snow water content [kg/kg].
Definition: mptrac.h:3799
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 6717 of file mptrac.c.

6721 {
6722
6723 float *help;
6724
6725 /* Allocate... */
6726 ALLOC(help, float,
6727 EX * EY);
6728
6729 /* Read uncompressed... */
6730 LOG(2, "Read 2-D variable: %s (uncompressed)", varname);
6731 FREAD(help, float,
6732 (size_t) (met->nx * met->ny),
6733 in);
6734
6735 /* Copy data... */
6736 for (int ix = 0; ix < met->nx; ix++)
6737 for (int iy = 0; iy < met->ny; iy++)
6738 var[ix][iy] = help[ARRAY_2D(ix, iy, met->ny)];
6739
6740 /* Free... */
6741 free(help);
6742}
#define ARRAY_2D(ix, iy, ny)
Macro for computing the linear index of a 2D array element.
Definition: mptrac.h:440

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

6753 {
6754
6755 float *help;
6756
6757 /* Allocate... */
6758 ALLOC(help, float,
6759 EX * EY * EP);
6760
6761 /* Read uncompressed data... */
6762 if (ctl->met_type == 1) {
6763 LOG(2, "Read 3-D variable: %s (uncompressed)", varname);
6764 FREAD(help, float,
6765 (size_t) (met->nx * met->ny * met->np),
6766 in);
6767 }
6768
6769 /* Read packed data... */
6770 else if (ctl->met_type == 2)
6771 compress_pck(varname, help, (size_t) (met->ny * met->nx),
6772 (size_t) met->np, 1, in);
6773
6774 /* Read zfp data... */
6775 else if (ctl->met_type == 3) {
6776#ifdef ZFP
6777 int precision;
6778 FREAD(&precision, int,
6779 1,
6780 in);
6781
6782 double tolerance;
6783 FREAD(&tolerance, double,
6784 1,
6785 in);
6786
6787 compress_zfp(varname, help, met->np, met->ny, met->nx, precision,
6788 tolerance, 1, in);
6789#else
6790 ERRMSG("MPTRAC was compiled without zfp compression!");
6791#endif
6792 }
6793
6794 /* Read zstd data... */
6795 else if (ctl->met_type == 4) {
6796#ifdef ZSTD
6797 compress_zstd(varname, help, (size_t) (met->np * met->ny * met->nx), 1,
6798 ctl->met_zstd_level, in);
6799#else
6800 ERRMSG("MPTRAC was compiled without zstd compression!");
6801#endif
6802 }
6803
6804 /* Read cmultiscale data... */
6805 else if (ctl->met_type == 5) {
6806#ifdef CMS
6807 compress_cms(ctl, varname, help, (size_t) met->nx, (size_t) met->ny,
6808 (size_t) met->np, 1, in);
6809#else
6810 ERRMSG("MPTRAC was compiled without cmultiscale compression!");
6811#endif
6812 }
6813
6814 /* Copy data... */
6815#pragma omp parallel for default(shared) collapse(2)
6816 for (int ix = 0; ix < met->nx; ix++)
6817 for (int iy = 0; iy < met->ny; iy++)
6818 for (int ip = 0; ip < met->np; ip++) {
6819 var[ix][iy][ip] = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
6820 if (var[ix][iy][ip] < bound_min)
6821 var[ix][iy][ip] = bound_min;
6822 else if (var[ix][iy][ip] > bound_max)
6823 var[ix][iy][ip] = bound_max;
6824 }
6825
6826 /* Free... */
6827 free(help);
6828}
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:664
void compress_zstd(const char *varname, float *array, const size_t n, const int decompress, const int level, FILE *inout)
Compresses or decompresses a float array using Zstandard (ZSTD).
void compress_cms(const ctl_t *ctl, const char *varname, float *array, const size_t nx, const size_t ny, const size_t np, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm.
void compress_zfp(const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using the ZFP library.
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 6832 of file mptrac.c.

6835 {
6836
6837 /* Check parameters... */
6838 if (ctl->met_cape != 1)
6839 return;
6840
6841 /* Set timer... */
6842 SELECT_TIMER("READ_MET_CAPE", "METPROC", NVTX_READ);
6843 LOG(2, "Calculate CAPE...");
6844
6845 /* Vertical spacing (about 100 m)... */
6846 const double pfac = 1.01439, dz0 = RI / MA / G0 * log(pfac);
6847
6848 /* Loop over columns... */
6849#pragma omp parallel for default(shared) collapse(2)
6850 for (int ix = 0; ix < met->nx; ix++)
6851 for (int iy = 0; iy < met->ny; iy++) {
6852
6853 /* Get potential temperature and water vapor at lowest 50 hPa... */
6854 int n = 0;
6855 double h2o = 0, t, theta = 0;
6856 double pbot = MIN(met->ps[ix][iy], met->p[0]);
6857 double ptop = pbot - 50.;
6858 for (int ip = 0; ip < met->np; ip++) {
6859 if (met->p[ip] <= pbot) {
6860 theta += THETA(met->p[ip], met->t[ix][iy][ip]);
6861 h2o += met->h2o[ix][iy][ip];
6862 n++;
6863 }
6864 if (met->p[ip] < ptop && n > 0)
6865 break;
6866 }
6867 theta /= n;
6868 h2o /= n;
6869
6870 /* Cannot compute anything if water vapor is missing... */
6871 met->plcl[ix][iy] = NAN;
6872 met->plfc[ix][iy] = NAN;
6873 met->pel[ix][iy] = NAN;
6874 met->cape[ix][iy] = NAN;
6875 met->cin[ix][iy] = NAN;
6876 if (h2o <= 0)
6877 continue;
6878
6879 /* Find lifted condensation level (LCL)... */
6880 ptop = P(20.);
6881 pbot = met->ps[ix][iy];
6882 do {
6883 met->plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
6884 t = theta / pow(1000. / met->plcl[ix][iy], 0.286);
6885 if (RH(met->plcl[ix][iy], t, h2o) > 100.)
6886 ptop = met->plcl[ix][iy];
6887 else
6888 pbot = met->plcl[ix][iy];
6889 } while (pbot - ptop > 0.1);
6890
6891 /* Calculate CIN up to LCL... */
6893 double dcape, dz, h2o_env, t_env;
6894 double p = met->ps[ix][iy];
6895 met->cape[ix][iy] = met->cin[ix][iy] = 0;
6896 do {
6897 dz = dz0 * TVIRT(t, h2o);
6898 p /= pfac;
6899 t = theta / pow(1000. / p, 0.286);
6900 intpol_met_space_3d(met, met->t, p, met->lon[ix], met->lat[iy],
6901 &t_env, ci, cw, 1);
6902 intpol_met_space_3d(met, met->h2o, p, met->lon[ix], met->lat[iy],
6903 &h2o_env, ci, cw, 0);
6904 dcape = 1e3 * G0 * (TVIRT(t, h2o) - TVIRT(t_env, h2o_env)) /
6905 TVIRT(t_env, h2o_env) * dz;
6906 if (dcape < 0)
6907 met->cin[ix][iy] += fabsf((float) dcape);
6908 } while (p > met->plcl[ix][iy]);
6909
6910 /* Calculate level of free convection (LFC), equilibrium level (EL),
6911 and convective available potential energy (CAPE)... */
6912 dcape = 0;
6913 p = met->plcl[ix][iy];
6914 t = theta / pow(1000. / p, 0.286);
6915 ptop = 0.75 * clim_tropo(clim, met->time, met->lat[iy]);
6916 do {
6917 dz = dz0 * TVIRT(t, h2o);
6918 p /= pfac;
6919 t -= lapse_rate(t, h2o) * dz;
6920 double psat = PSAT(t);
6921 h2o = psat / (p - (1. - EPS) * psat);
6922 intpol_met_space_3d(met, met->t, p, met->lon[ix], met->lat[iy],
6923 &t_env, ci, cw, 1);
6924 intpol_met_space_3d(met, met->h2o, p, met->lon[ix], met->lat[iy],
6925 &h2o_env, ci, cw, 0);
6926 double dcape_old = dcape;
6927 dcape = 1e3 * G0 * (TVIRT(t, h2o) - TVIRT(t_env, h2o_env)) /
6928 TVIRT(t_env, h2o_env) * dz;
6929 if (dcape > 0) {
6930 met->cape[ix][iy] += (float) dcape;
6931 if (!isfinite(met->plfc[ix][iy]))
6932 met->plfc[ix][iy] = (float) p;
6933 } else if (dcape_old > 0)
6934 met->pel[ix][iy] = (float) p;
6935 if (dcape < 0 && !isfinite(met->plfc[ix][iy]))
6936 met->cin[ix][iy] += fabsf((float) dcape);
6937 } while (p > ptop);
6938
6939 /* Check results... */
6940 if (!isfinite(met->plfc[ix][iy]))
6941 met->cin[ix][iy] = NAN;
6942 }
6943}
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 6947 of file mptrac.c.

6948 {
6949
6950 /* Set timer... */
6951 SELECT_TIMER("READ_MET_CLOUD", "METPROC", NVTX_READ);
6952 LOG(2, "Calculate cloud data...");
6953
6954 /* Thresholds for cloud detection... */
6955 const double ccmin = 0.01, cwmin = 1e-6;
6956
6957 /* Loop over columns... */
6958#pragma omp parallel for default(shared) collapse(2)
6959 for (int ix = 0; ix < met->nx; ix++)
6960 for (int iy = 0; iy < met->ny; iy++) {
6961
6962 /* Init... */
6963 met->pct[ix][iy] = NAN;
6964 met->pcb[ix][iy] = NAN;
6965 met->cl[ix][iy] = 0;
6966
6967 /* Loop over pressure levels... */
6968 for (int ip = 0; ip < met->np - 1; ip++) {
6969
6970 /* Check pressure... */
6971 if (met->p[ip] > met->ps[ix][iy] || met->p[ip] < P(20.))
6972 continue;
6973
6974 /* Check ice water and liquid water content... */
6975 if (met->cc[ix][iy][ip] > ccmin
6976 && (met->lwc[ix][iy][ip] > cwmin
6977 || met->rwc[ix][iy][ip] > cwmin
6978 || met->iwc[ix][iy][ip] > cwmin
6979 || met->swc[ix][iy][ip] > cwmin)) {
6980
6981 /* Get cloud top pressure ... */
6982 met->pct[ix][iy]
6983 = (float) (0.5 * (met->p[ip] + (float) met->p[ip + 1]));
6984
6985 /* Get cloud bottom pressure ... */
6986 if (!isfinite(met->pcb[ix][iy]))
6987 met->pcb[ix][iy]
6988 = (float) (0.5 * (met->p[ip] + met->p[MAX(ip - 1, 0)]));
6989 }
6990
6991 /* Get cloud water... */
6992 met->cl[ix][iy] += (float)
6993 (0.5 * (met->lwc[ix][iy][ip] + met->lwc[ix][iy][ip + 1]
6994 + met->rwc[ix][iy][ip] + met->rwc[ix][iy][ip + 1]
6995 + met->iwc[ix][iy][ip] + met->iwc[ix][iy][ip + 1]
6996 + met->swc[ix][iy][ip] + met->swc[ix][iy][ip + 1])
6997 * 100. * (met->p[ip] - met->p[ip + 1]) / G0);
6998 }
6999 }
7000}

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

7006 {
7007
7008 met_t *help;
7009
7010 /* Check parameters... */
7011 if (ctl->met_detrend <= 0)
7012 return;
7013
7014 /* Set timer... */
7015 SELECT_TIMER("READ_MET_DETREND", "METPROC", NVTX_READ);
7016 LOG(2, "Detrend meteo data...");
7017
7018 /* Allocate... */
7019 ALLOC(help, met_t, 1);
7020
7021 /* Calculate standard deviation... */
7022 const double sigma = ctl->met_detrend / 2.355;
7023 const double tssq = 2. * SQR(sigma);
7024
7025 /* Calculate box size in latitude... */
7026 int sy = (int) (3. * DY2DEG(sigma) / fabs(met->lat[1] - met->lat[0]));
7027 sy = MIN(MAX(1, sy), met->ny / 2);
7028
7029 /* Calculate background... */
7030#pragma omp parallel for default(shared) collapse(2)
7031 for (int ix = 0; ix < met->nx; ix++) {
7032 for (int iy = 0; iy < met->ny; iy++) {
7033
7034 /* Calculate Cartesian coordinates... */
7035 double x0[3];
7036 geo2cart(0.0, met->lon[ix], met->lat[iy], x0);
7037
7038 /* Calculate box size in longitude... */
7039 int sx =
7040 (int) (3. * DX2DEG(sigma, met->lat[iy]) /
7041 fabs(met->lon[1] - met->lon[0]));
7042 sx = MIN(MAX(1, sx), met->nx / 2);
7043
7044 /* Init... */
7045 float wsum = 0;
7046 for (int ip = 0; ip < met->np; ip++) {
7047 help->t[ix][iy][ip] = 0;
7048 help->u[ix][iy][ip] = 0;
7049 help->v[ix][iy][ip] = 0;
7050 help->w[ix][iy][ip] = 0;
7051 }
7052
7053 /* Loop over neighboring grid points... */
7054 for (int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
7055 int ix3 = ix2;
7056 if (ix3 < 0)
7057 ix3 += met->nx;
7058 else if (ix3 >= met->nx)
7059 ix3 -= met->nx;
7060 for (int iy2 = MAX(iy - sy, 0);
7061 iy2 <= MIN(iy + sy, met->ny - 1); iy2++) {
7062
7063 /* Calculate Cartesian coordinates... */
7064 double x1[3];
7065 geo2cart(0.0, met->lon[ix3], met->lat[iy2], x1);
7066
7067 /* Calculate weighting factor... */
7068 const float w = (float) exp(-DIST2(x0, x1) / tssq);
7069
7070 /* Add data... */
7071 wsum += w;
7072 for (int ip = 0; ip < met->np; ip++) {
7073 help->t[ix][iy][ip] += w * met->t[ix3][iy2][ip];
7074 help->u[ix][iy][ip] += w * met->u[ix3][iy2][ip];
7075 help->v[ix][iy][ip] += w * met->v[ix3][iy2][ip];
7076 help->w[ix][iy][ip] += w * met->w[ix3][iy2][ip];
7077 }
7078 }
7079 }
7080
7081 /* Normalize... */
7082 for (int ip = 0; ip < met->np; ip++) {
7083 help->t[ix][iy][ip] /= wsum;
7084 help->u[ix][iy][ip] /= wsum;
7085 help->v[ix][iy][ip] /= wsum;
7086 help->w[ix][iy][ip] /= wsum;
7087 }
7088 }
7089 }
7090
7091 /* Subtract background... */
7092#pragma omp parallel for default(shared) collapse(3)
7093 for (int ix = 0; ix < met->nx; ix++)
7094 for (int iy = 0; iy < met->ny; iy++)
7095 for (int ip = 0; ip < met->np; ip++) {
7096 met->t[ix][iy][ip] -= help->t[ix][iy][ip];
7097 met->u[ix][iy][ip] -= help->u[ix][iy][ip];
7098 met->v[ix][iy][ip] -= help->v[ix][iy][ip];
7099 met->w[ix][iy][ip] -= help->w[ix][iy][ip];
7100 }
7101
7102 /* Free... */
7103 free(help);
7104}
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:994
#define DIST2(a, b)
Calculate the squared Euclidean distance between two points in Cartesian coordinates.
Definition: mptrac.h:662
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 7108 of file mptrac.c.

7109 {
7110
7111 /* Set timer... */
7112 SELECT_TIMER("READ_MET_EXTRAPOLATE", "METPROC", NVTX_READ);
7113 LOG(2, "Extrapolate meteo data...");
7114
7115 /* Loop over columns... */
7116#pragma omp parallel for default(shared) collapse(2)
7117 for (int ix = 0; ix < met->nx; ix++)
7118 for (int iy = 0; iy < met->ny; iy++) {
7119
7120 /* Find lowest valid data point... */
7121 int ip0;
7122 for (ip0 = met->np - 1; ip0 >= 0; ip0--)
7123 if (!isfinite(met->t[ix][iy][ip0])
7124 || !isfinite(met->u[ix][iy][ip0])
7125 || !isfinite(met->v[ix][iy][ip0])
7126 || !isfinite(met->w[ix][iy][ip0]))
7127 break;
7128
7129 /* Extrapolate... */
7130 for (int ip = ip0; ip >= 0; ip--) {
7131 met->t[ix][iy][ip] = met->t[ix][iy][ip + 1];
7132 met->u[ix][iy][ip] = met->u[ix][iy][ip + 1];
7133 met->v[ix][iy][ip] = met->v[ix][iy][ip + 1];
7134 met->w[ix][iy][ip] = met->w[ix][iy][ip + 1];
7135 met->h2o[ix][iy][ip] = met->h2o[ix][iy][ip + 1];
7136 met->o3[ix][iy][ip] = met->o3[ix][iy][ip + 1];
7137 met->lwc[ix][iy][ip] = met->lwc[ix][iy][ip + 1];
7138 met->rwc[ix][iy][ip] = met->rwc[ix][iy][ip + 1];
7139 met->iwc[ix][iy][ip] = met->iwc[ix][iy][ip + 1];
7140 met->swc[ix][iy][ip] = met->swc[ix][iy][ip + 1];
7141 met->cc[ix][iy][ip] = met->cc[ix][iy][ip + 1];
7142 }
7143 }
7144}

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

7150 {
7151
7152 float *help;
7153
7154 double logp[EP];
7155
7156 int dx = ctl->met_geopot_sx, dy = ctl->met_geopot_sy;
7157
7158 /* Set timer... */
7159 SELECT_TIMER("READ_MET_GEOPOT", "METPROC", NVTX_READ);
7160 LOG(2, "Calculate geopotential heights...");
7161
7162 /* Allocate... */
7163 ALLOC(help, float,
7164 EX * EY * EP);
7165
7166 /* Calculate log pressure... */
7167#pragma omp parallel for default(shared)
7168 for (int ip = 0; ip < met->np; ip++)
7169 logp[ip] = log(met->p[ip]);
7170
7171 /* Apply hydrostatic equation to calculate geopotential heights... */
7172#pragma omp parallel for default(shared) collapse(2)
7173 for (int ix = 0; ix < met->nx; ix++)
7174 for (int iy = 0; iy < met->ny; iy++) {
7175
7176 /* Get surface height and pressure... */
7177 const double zs = met->zs[ix][iy];
7178 const double lnps = log(met->ps[ix][iy]);
7179
7180 /* Get temperature and water vapor at the surface... */
7181 const int ip0 = locate_irr(met->p, met->np, met->ps[ix][iy]);
7182 const double ts = LIN(met->p[ip0], met->t[ix][iy][ip0], met->p[ip0 + 1],
7183 met->t[ix][iy][ip0 + 1], met->ps[ix][iy]);
7184 const double h2os =
7185 LIN(met->p[ip0], met->h2o[ix][iy][ip0], met->p[ip0 + 1],
7186 met->h2o[ix][iy][ip0 + 1], met->ps[ix][iy]);
7187
7188 /* Upper part of profile... */
7189 met->z[ix][iy][ip0 + 1]
7190 = (float) (zs +
7191 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
7192 met->t[ix][iy][ip0 + 1], met->h2o[ix][iy][ip0 + 1]));
7193 for (int ip = ip0 + 2; ip < met->np; ip++)
7194 met->z[ix][iy][ip]
7195 = (float) (met->z[ix][iy][ip - 1] +
7196 ZDIFF(logp[ip - 1], met->t[ix][iy][ip - 1],
7197 met->h2o[ix][iy][ip - 1], logp[ip],
7198 met->t[ix][iy][ip], met->h2o[ix][iy][ip]));
7199
7200 /* Lower part of profile... */
7201 met->z[ix][iy][ip0]
7202 = (float) (zs +
7203 ZDIFF(lnps, ts, h2os, logp[ip0],
7204 met->t[ix][iy][ip0], met->h2o[ix][iy][ip0]));
7205 for (int ip = ip0 - 1; ip >= 0; ip--)
7206 met->z[ix][iy][ip]
7207 = (float) (met->z[ix][iy][ip + 1] +
7208 ZDIFF(logp[ip + 1], met->t[ix][iy][ip + 1],
7209 met->h2o[ix][iy][ip + 1], logp[ip],
7210 met->t[ix][iy][ip], met->h2o[ix][iy][ip]));
7211 }
7212
7213 /* Check control parameters... */
7214 if (dx == 0 || dy == 0)
7215 return;
7216
7217 /* Default smoothing parameters... */
7218 if (dx < 0 || dy < 0) {
7219 if (fabs(met->lon[1] - met->lon[0]) < 0.5) {
7220 dx = 3;
7221 dy = 2;
7222 } else {
7223 dx = 6;
7224 dy = 4;
7225 }
7226 }
7227
7228 /* Calculate weights for smoothing... */
7229 float ws[dx + 1][dy + 1];
7230#pragma omp parallel for default(shared) collapse(2)
7231 for (int ix = 0; ix <= dx; ix++)
7232 for (int iy = 0; iy < dy; iy++)
7233 ws[ix][iy] = (1.0f - (float) ix / (float) dx)
7234 * (1.0f - (float) iy / (float) dy);
7235
7236 /* Copy data... */
7237#pragma omp parallel for default(shared) collapse(3)
7238 for (int ix = 0; ix < met->nx; ix++)
7239 for (int iy = 0; iy < met->ny; iy++)
7240 for (int ip = 0; ip < met->np; ip++)
7241 help[ARRAY_3D(ip, ix, met->nx, iy, met->ny)] = met->z[ix][iy][ip];
7242
7243 /* Horizontal smoothing... */
7244#pragma omp parallel for default(shared) collapse(3)
7245 for (int ip = 0; ip < met->np; ip++)
7246 for (int ix = 0; ix < met->nx; ix++)
7247 for (int iy = 0; iy < met->ny; iy++) {
7248 float res = 0, wsum = 0;
7249 int iy0 = MAX(iy - dy + 1, 0);
7250 int iy1 = MIN(iy + dy - 1, met->ny - 1);
7251 for (int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
7252 int ix3 = ix2;
7253 if (ix3 < 0)
7254 ix3 += met->nx;
7255 else if (ix3 >= met->nx)
7256 ix3 -= met->nx;
7257 for (int iy2 = iy0; iy2 <= iy1; ++iy2)
7258 if (isfinite(help[ARRAY_3D(ip, ix3, met->nx, iy2, met->ny)])) {
7259 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
7260 res += w * help[ARRAY_3D(ip, ix3, met->nx, iy2, met->ny)];
7261 wsum += w;
7262 }
7263 }
7264 if (wsum > 0)
7265 met->z[ix][iy][ip] = res / wsum;
7266 else
7267 met->z[ix][iy][ip] = NAN;
7268 }
7269
7270 /* Free... */
7271 free(help);
7272}
#define ZDIFF(lnp0, t0, h2o0, lnp1, t1, h2o1)
Calculate geopotential height difference.
Definition: mptrac.h:1970
Here is the call graph for this function:

◆ read_met_grib()

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

Reads meteorological data from a grib file and processes it.

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

Parameters
filenameA constant character pointer representing the name of the grib files to read the meteorological data from. The sf or ml suffixes indicating surface or multi-level data should be replaced with XX.
ctlA pointer to a ctl_t structure, which contains control parameters for reading and processing the meteorological data.
metA pointer to a met_t structure that will store the meteorological data read and processed from the NetCDF file.
Returns
Returns 1 on success, or 0 if the file cannot be opened.
Note
  • The function reads grid data, vertical level data, and surface data from the file, and processes the data to calculate additional meteorological parameters.
  • If the file cannot be opened, the function logs a warning and returns 0.
Author
Nils Nobre Wittwer

◆ read_met_ml2pl()

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

Reads global meteorological information from a grib file.

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

Parameters
handlesA pointer to an array of codes_handle pointers representing the grib messages.
count_handlesThe total number of grib messages in the handles array.
metA pointer to a structure to store meteorological data.

The function performs the following steps:

  • Sets up a timer to monitor the reading time for meteorological grid information.
  • Determines the time information from the data file.
  • Retrieves grid dimensions (longitude, latitude, and vertical levels) from the grib file.
  • Reads longitudes and latitudes boundaries and increments from the grib file and computes the grid.
  • Logs the retrieved grid information for verification and debugging purposes.
Authors
Nils Nobre Wittwer

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

This function reads meteorological variables such as temperature, wind components, specific humidity, ozone data, cloud parameters, and cloud cover at various vertical levels from a grib file.

Parameters
handlesA pointer to an array of codes_handle pointers representing the grib messages.
num_messagesThe total number of grib messages in the handles array.
ctlA pointer to a structure containing control parameters.
metA pointer to a structure to store meteorological data.

The function performs the following steps:

  • Sets up a timer to monitor the reading time for meteorological level data.
  • Reads meteorological variables from the grib file.
  • Checks the ordering of pressure levels to ensure they are in descending order.
Authors
Nils Nobre Wittwer

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

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

Parameters
handlesA pointer to an array of codes_handle pointers representing the grib messages.
num_messagesThe total number of grib messages in the handles array.
ctlA pointer to a structure containing control parameters.
metA pointer to a structure to store meteorological data.

The function performs the following steps:

  • Sets a timer for performance monitoring.
  • Reads surface meteorological data based on the configuration:
  • Reads surface pressure from "lnsp", "ps", or "sp" variables.
  • Converts surface pressure to Pa.
  • Reads geopotential height at the surface from "z" or "zm" variables.
  • Reads surface temperature from "t2m" or "2t" variables.
  • Reads zonal wind at the surface from "u10m" or "10u" variables.
  • Reads meridional wind at the surface from "v10m" or "10v" variables.
  • Reads land-sea mask from "lsm" variable.
  • Reads sea surface temperature from "sstk" or "sst" variables.
Authors
Nils Nobre Wittwer

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

8704 {
8705
8706 double aux[EP], p[EP];
8707
8708 /* Set timer... */
8709 SELECT_TIMER("READ_MET_ML2PL", "METPROC", NVTX_READ);
8710 LOG(2, "Interpolate meteo data to pressure levels: %s", varname);
8711
8712 /* Loop over columns... */
8713#pragma omp parallel for default(shared) private(aux,p) collapse(2)
8714 for (int ix = 0; ix < met->nx; ix++)
8715 for (int iy = 0; iy < met->ny; iy++) {
8716
8717 /* Copy pressure profile... */
8718 for (int ip = 0; ip < met->np; ip++)
8719 p[ip] = met->pl[ix][iy][ip];
8720
8721 /* Interpolate... */
8722 for (int ip = 0; ip < ctl->met_np; ip++) {
8723 double pt = ctl->met_p[ip];
8724 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
8725 pt = p[0];
8726 else if ((pt > p[met->np - 1] && p[1] > p[0])
8727 || (pt < p[met->np - 1] && p[1] < p[0]))
8728 pt = p[met->np - 1];
8729 int ip2 = locate_irr(p, met->np, pt);
8730 aux[ip] = LIN(p[ip2], var[ix][iy][ip2],
8731 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
8732 }
8733
8734 /* Copy data... */
8735 for (int ip = 0; ip < ctl->met_np; ip++)
8736 var[ix][iy][ip] = (float) aux[ip];
8737 }
8738}
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 8742 of file mptrac.c.

8744 {
8745
8746 /* Check parameters... */
8747 if (ctl->advect_vert_coord != 1)
8748 return;
8749
8750 /* Set timer... */
8751 SELECT_TIMER("READ_MET_MONOTONIZE", "METPROC", NVTX_READ);
8752 LOG(2, "Make zeta profiles monotone...");
8753
8754 /* Create monotone zeta profiles... */
8755#pragma omp parallel for default(shared) collapse(2)
8756 for (int i = 0; i < met->nx; i++)
8757 for (int j = 0; j < met->ny; j++) {
8758 int k = 1;
8759
8760 while (k < met->npl) { /* Check if there is an inversion at level k... */
8761 if ((met->zetal[i][j][k - 1] >= met->zetal[i][j][k])) {
8762 /* Find the upper level k+l over the inversion... */
8763 int l = 0;
8764 do {
8765 l++;
8766 }
8767 while ((met->zetal[i][j][k - 1] >=
8768 met->zetal[i][j][k + l]) & (k + l < met->npl));
8769
8770 /* Interpolate linear between the top and bottom
8771 of the inversion... */
8772 float s =
8773 (float) (met->zetal[i][j][k + l] - met->zetal[i][j][k - 1])
8774 / (float) (met->hybrid[k + l] - met->hybrid[k - 1]);
8775
8776 for (int m = k; m < k + l; m++) {
8777 float d = (float) (met->hybrid[m] - met->hybrid[k - 1]);
8778 met->zetal[i][j][m] = s * d + met->zetal[i][j][k - 1];
8779 }
8780
8781 /* Search for more inversions above the last inversion ... */
8782 k = k + l;
8783 } else {
8784 k++;
8785 }
8786 }
8787 }
8788
8789 /* Create monotone pressure profiles... */
8790#pragma omp parallel for default(shared) collapse(2)
8791 for (int i = 0; i < met->nx; i++)
8792 for (int j = 0; j < met->ny; j++) {
8793 int k = 1;
8794
8795 while (k < met->npl) { /* Check if there is an inversion at level k... */
8796 if ((met->pl[i][j][k - 1] <= met->pl[i][j][k])) {
8797
8798 /* Find the upper level k+l over the inversion... */
8799 int l = 0;
8800 do {
8801 l++;
8802 }
8803 while ((met->pl[i][j][k - 1] <= met->pl[i][j][k + l]) & (k + l <
8804 met->npl));
8805
8806 /* Interpolate linear between the top and bottom
8807 of the inversion... */
8808 float s = (float) (met->pl[i][j][k + l] - met->pl[i][j][k - 1])
8809 / (float) (met->hybrid[k + l] - met->hybrid[k - 1]);
8810
8811 for (int m = k; m < k + l; m++) {
8812 float d = (float) (met->hybrid[m] - met->hybrid[k - 1]);
8813 met->pl[i][j][m] = s * d + met->pl[i][j][k - 1];
8814 }
8815
8816 /* Search for more inversions above the last inversion ... */
8817 k += l;
8818 } else {
8819 k++;
8820 }
8821 }
8822 }
8823}
double hybrid[EP]
Model hybrid levels.
Definition: mptrac.h:3691

◆ read_met_nc()

int read_met_nc ( const char *  filename,
const ctl_t ctl,
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.
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 8827 of file mptrac.c.

8830 {
8831
8832 int ncid;
8833
8834 /* Open netCDF file... */
8835 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
8836 WARN("Cannot open file!");
8837 return 0;
8838 }
8839
8840 /* Read coordinates of meteo data... */
8841 read_met_nc_grid(filename, ncid, ctl, met);
8842
8843 /* Read surface data... */
8844 read_met_nc_surface(ncid, ctl, met);
8845
8846 /* Read meteo data on vertical levels... */
8847 read_met_nc_levels(ncid, ctl, met);
8848
8849 /* Close file... */
8850 NC(nc_close(ncid));
8851
8852 /* Return success... */
8853 return 1;
8854}
void read_met_nc_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:9522
void read_met_nc_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:9174
void read_met_nc_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:9308
Here is the call graph for this function:

◆ read_met_nc_levels()

void read_met_nc_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 9308 of file mptrac.c.

9311 {
9312
9313 /* Set timer... */
9314 SELECT_TIMER("READ_MET_NC_LEVELS", "INPUT", NVTX_READ);
9315 LOG(2, "Read level data...");
9316
9317 /* Read temperature... */
9318 if (!read_met_nc_3d(ncid, "t", "T", "temp", "TEMP", ctl, met, met->t, 1.0))
9319 ERRMSG("Cannot read temperature!");
9320
9321 /* Read horizontal wind and vertical velocity... */
9322 if (!read_met_nc_3d(ncid, "u", "U", NULL, NULL, ctl, met, met->u, 1.0))
9323 ERRMSG("Cannot read zonal wind!");
9324 if (!read_met_nc_3d(ncid, "v", "V", NULL, NULL, ctl, met, met->v, 1.0))
9325 ERRMSG("Cannot read meridional wind!");
9326 if (!read_met_nc_3d
9327 (ncid, "w", "W", "omega", "OMEGA", ctl, met, met->w, 0.01f))
9328 WARN("Cannot read vertical velocity!");
9329
9330 /* Read water vapor... */
9331 if (!ctl->met_relhum) {
9332 if (!read_met_nc_3d
9333 (ncid, "q", "Q", "sh", "SH", ctl, met, met->h2o, (float) (MA / MH2O)))
9334 WARN("Cannot read specific humidity!");
9335 } else {
9336 if (!read_met_nc_3d
9337 (ncid, "rh", "RH", NULL, NULL, ctl, met, met->h2o, 0.01f))
9338 WARN("Cannot read relative humidity!");
9339#pragma omp parallel for default(shared) collapse(2)
9340 for (int ix = 0; ix < met->nx; ix++)
9341 for (int iy = 0; iy < met->ny; iy++)
9342 for (int ip = 0; ip < met->np; ip++) {
9343 double pw = met->h2o[ix][iy][ip] * PSAT(met->t[ix][iy][ip]);
9344 met->h2o[ix][iy][ip] =
9345 (float) (pw / (met->p[ip] - (1.0 - EPS) * pw));
9346 }
9347 }
9348
9349 /* Read ozone... */
9350 if (!read_met_nc_3d
9351 (ncid, "o3", "O3", NULL, NULL, ctl, met, met->o3, (float) (MA / MO3)))
9352 WARN("Cannot read ozone data!");
9353
9354 /* Read cloud data... */
9355 if (!read_met_nc_3d
9356 (ncid, "clwc", "CLWC", NULL, NULL, ctl, met, met->lwc, 1.0))
9357 WARN("Cannot read cloud liquid water content!");
9358 if (!read_met_nc_3d
9359 (ncid, "crwc", "CRWC", NULL, NULL, ctl, met, met->rwc, 1.0))
9360 WARN("Cannot read cloud rain water content!");
9361 if (!read_met_nc_3d
9362 (ncid, "ciwc", "CIWC", NULL, NULL, ctl, met, met->iwc, 1.0))
9363 WARN("Cannot read cloud ice water content!");
9364 if (!read_met_nc_3d
9365 (ncid, "cswc", "CSWC", NULL, NULL, ctl, met, met->swc, 1.0))
9366 WARN("Cannot read cloud snow water content!");
9367 if (!read_met_nc_3d(ncid, "cc", "CC", NULL, NULL, ctl, met, met->cc, 1.0))
9368 WARN("Cannot read cloud cover!");
9369
9370 /* Read zeta and zeta_dot... */
9371 if (!read_met_nc_3d
9372 (ncid, "ZETA", "zeta", NULL, NULL, ctl, met, met->zetal, 1.0))
9373 WARN("Cannot read ZETA!");
9374 if (!read_met_nc_3d
9375 (ncid, "ZETA_DOT_TOT", "ZETA_DOT_clr", "zeta_dot_clr",
9376 NULL, ctl, met, met->zeta_dotl, 0.00001157407f))
9377 WARN("Cannot read ZETA_DOT!");
9378
9379 /* Store velocities on model levels... */
9380 if (ctl->met_vert_coord != 0) {
9381 for (int ix = 0; ix < met->nx; ix++)
9382 for (int iy = 0; iy < met->ny; iy++)
9383 for (int ip = 0; ip < met->np; ip++) {
9384 met->ul[ix][iy][ip] = met->u[ix][iy][ip];
9385 met->vl[ix][iy][ip] = met->v[ix][iy][ip];
9386 met->wl[ix][iy][ip] = met->w[ix][iy][ip];
9387 }
9388
9389 /* Save number of model levels... */
9390 met->npl = met->np;
9391 }
9392
9393 /* Get pressure on model levels... */
9394 if (ctl->met_np > 0 || ctl->met_vert_coord != 0) {
9395
9396 /* Read 3-D pressure field... */
9397 if (ctl->met_vert_coord == 1) {
9398 if (!read_met_nc_3d
9399 (ncid, "pl", "PL", "pressure", "PRESSURE", ctl, met, met->pl,
9400 0.01f))
9401 if (!read_met_nc_3d
9402 (ncid, "press", "PRESS", NULL, NULL, ctl, met, met->pl, 1.0))
9403 ERRMSG("Cannot read pressure on model levels!");
9404 }
9405
9406 /* Use a and b coefficients for full levels... */
9407 else if (ctl->met_vert_coord == 2 || ctl->met_vert_coord == 3) {
9408
9409 /* Grid level coefficients... */
9410 double hyam[EP], hybm[EP];
9411
9412 /* Read coefficients from file... */
9413 if (ctl->met_vert_coord == 2) {
9414 int varid;
9415 if (nc_inq_varid(ncid, "hyam", &varid) == NC_NOERR
9416 && nc_inq_varid(ncid, "hybm", &varid) == NC_NOERR) {
9417 NC_GET_DOUBLE("hyam", hyam, 1);
9418 NC_GET_DOUBLE("hybm", hybm, 1);
9419 } else if (nc_inq_varid(ncid, "a_hybrid_level", &varid) == NC_NOERR
9420 && nc_inq_varid(ncid, "b_hybrid_level",
9421 &varid) == NC_NOERR) {
9422 NC_GET_DOUBLE("a_hybrid_level", hyam, 1);
9423 NC_GET_DOUBLE("b_hybrid_level", hybm, 1);
9424 } else
9425 ERRMSG("Cannot read a and b level coefficients from netCDF file!");
9426 }
9427
9428 /* Use control parameters... */
9429 else if (ctl->met_vert_coord == 3) {
9430
9431 /* Check number of levels... */
9432 if (met->np != ctl->met_nlev)
9433 ERRMSG("Mismatch in number of model levels!");
9434
9435 /* Copy parameters... */
9436 for (int ip = 0; ip < met->np; ip++) {
9437 hyam[ip] = ctl->met_lev_hyam[ip];
9438 hybm[ip] = ctl->met_lev_hybm[ip];
9439 }
9440 }
9441
9442 /* Calculate pressure... */
9443 for (int ix = 0; ix < met->nx; ix++)
9444 for (int iy = 0; iy < met->ny; iy++)
9445 for (int ip = 0; ip < met->np; ip++)
9446 met->pl[ix][iy][ip] =
9447 (float) (hyam[ip] / 100. + hybm[ip] * met->ps[ix][iy]);
9448 }
9449
9450 /* Use a and b coefficients for half levels... */
9451 else if (ctl->met_vert_coord == 4) {
9452
9453 /* Grid level coefficients... */
9454 double hyam[EP], hybm[EP];
9455
9456 /* Use control parameters... */
9457 for (int ip = 0; ip < met->np + 1; ip++) {
9458 hyam[ip] = ctl->met_lev_hyam[ip];
9459 hybm[ip] = ctl->met_lev_hybm[ip];
9460 }
9461
9462 /* Check number of levels... */
9463 if (met->np + 1 != ctl->met_nlev)
9464 ERRMSG("Mismatch in number of model levels!");
9465
9466 /* Calculate pressure... */
9467#pragma omp parallel for default(shared) collapse(2)
9468 for (int ix = 0; ix < met->nx; ix++)
9469 for (int iy = 0; iy < met->ny; iy++)
9470 for (int ip = 0; ip < met->np; ip++) {
9471 double p0 = hyam[ip] / 100. + hybm[ip] * met->ps[ix][iy];
9472 double p1 = hyam[ip + 1] / 100. + hybm[ip + 1] * met->ps[ix][iy];
9473 met->pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
9474 }
9475 }
9476
9477 /* Check ordering of pressure levels... */
9478 for (int ix = 0; ix < met->nx; ix++)
9479 for (int iy = 0; iy < met->ny; iy++)
9480 for (int ip = 1; ip < met->np; ip++)
9481 if ((met->pl[ix][iy][0] > met->pl[ix][iy][1]
9482 && met->pl[ix][iy][ip - 1] <= met->pl[ix][iy][ip])
9483 || (met->pl[ix][iy][0] < met->pl[ix][iy][1]
9484 && met->pl[ix][iy][ip - 1] >= met->pl[ix][iy][ip]))
9485 ERRMSG("Pressure profiles are not monotonic!");
9486 }
9487
9488 /* Interpolate from model levels to pressure levels... */
9489 if (ctl->met_np > 0) {
9490
9491 /* Check pressure on model levels... */
9492 if (met->pl[0][0][0] <= 0)
9493 ERRMSG("Pressure on model levels is missing, check MET_VERT_COORD!");
9494
9495 /* Interpolate variables... */
9496 read_met_ml2pl(ctl, met, met->t, "T");
9497 read_met_ml2pl(ctl, met, met->u, "U");
9498 read_met_ml2pl(ctl, met, met->v, "V");
9499 read_met_ml2pl(ctl, met, met->w, "W");
9500 read_met_ml2pl(ctl, met, met->h2o, "H2O");
9501 read_met_ml2pl(ctl, met, met->o3, "O3");
9502 read_met_ml2pl(ctl, met, met->lwc, "LWC");
9503 read_met_ml2pl(ctl, met, met->rwc, "RWC");
9504 read_met_ml2pl(ctl, met, met->iwc, "IWC");
9505 read_met_ml2pl(ctl, met, met->swc, "SWC");
9506 read_met_ml2pl(ctl, met, met->cc, "CC");
9507
9508 /* Set new pressure levels... */
9509 met->np = ctl->met_np;
9510 for (int ip = 0; ip < met->np; ip++)
9511 met->p[ip] = ctl->met_p[ip];
9512 }
9513
9514 /* Check ordering of pressure levels... */
9515 for (int ip = 1; ip < met->np; ip++)
9516 if (met->p[ip - 1] < met->p[ip])
9517 ERRMSG("Pressure levels must be descending!");
9518}
void read_met_ml2pl(const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname)
Reads global meteorological information from a grib file.
Definition: mptrac.c:8700
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:9022
#define MH2O
Molar mass of water vapor [g/mol].
Definition: mptrac.h:229
#define MO3
Molar mass of ozone [g/mol].
Definition: mptrac.h:234
Here is the call graph for this function:

◆ read_met_nc_surface()

void read_met_nc_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 9522 of file mptrac.c.

9525 {
9526
9527 /* Set timer... */
9528 SELECT_TIMER("READ_MET_NC_SURFACE", "INPUT", NVTX_READ);
9529 LOG(2, "Read surface data...");
9530
9531 /* Read surface pressure... */
9532 if (read_met_nc_2d
9533 (ncid, "lnsp", "LNSP", NULL, NULL, NULL, NULL, ctl, met, met->ps,
9534 1.0f, 1)) {
9535 for (int ix = 0; ix < met->nx; ix++)
9536 for (int iy = 0; iy < met->ny; iy++)
9537 met->ps[ix][iy] = (float) (exp(met->ps[ix][iy]) / 100.);
9538 } else
9539 if (!read_met_nc_2d
9540 (ncid, "ps", "PS", "sp", "SP", NULL, NULL, ctl, met, met->ps, 0.01f,
9541 1)) {
9542 WARN("Cannot not read surface pressure data (use lowest level)!");
9543 for (int ix = 0; ix < met->nx; ix++)
9544 for (int iy = 0; iy < met->ny; iy++)
9545 met->ps[ix][iy]
9546 = (ctl->met_np > 0 ? (float) ctl->met_p[0] : (float) met->p[0]);
9547 }
9548
9549 /* MPTRAC meteo data... */
9550 if (ctl->met_clams == 0) {
9551
9552 /* Read geopotential height at the surface... */
9553 if (!read_met_nc_2d
9554 (ncid, "z", "Z", NULL, NULL, NULL, NULL, ctl, met, met->zs,
9555 (float) (1. / (1000. * G0)), 1))
9556 if (!read_met_nc_2d
9557 (ncid, "zm", "ZM", NULL, NULL, NULL, NULL, ctl, met, met->zs,
9558 (float) (1. / 1000.), 1))
9559 WARN("Cannot read surface geopotential height!");
9560 }
9561
9562 /* CLaMS meteo data... */
9563 else {
9564
9565 /* Read geopotential height at the surface
9566 (use lowermost level of 3-D data field)... */
9567 float *help;
9568 ALLOC(help, float,
9569 EX * EY * EP);
9570 memcpy(help, met->pl, sizeof(met->pl));
9571 if (!read_met_nc_3d
9572 (ncid, "gph", "GPH", NULL, NULL, ctl, met, met->pl,
9573 (float) (1e-3 / G0)))
9574 ERRMSG("Cannot read geopotential height!");
9575 for (int ix = 0; ix < met->nx; ix++)
9576 for (int iy = 0; iy < met->ny; iy++)
9577 met->zs[ix][iy] = met->pl[ix][iy][0];
9578 memcpy(met->pl, help, sizeof(met->pl));
9579 free(help);
9580 }
9581
9582 /* Read temperature at the surface... */
9583 if (!read_met_nc_2d
9584 (ncid, "t2m", "T2M", "2t", "2T", "t2", "T2", ctl, met, met->ts, 1.0, 1))
9585 WARN("Cannot read surface temperature!");
9586
9587 /* Read zonal wind at the surface... */
9588 if (!read_met_nc_2d
9589 (ncid, "u10m", "U10M", "10u", "10U", "u10", "U10", ctl, met, met->us,
9590 1.0, 1))
9591 WARN("Cannot read surface zonal wind!");
9592
9593 /* Read meridional wind at the surface... */
9594 if (!read_met_nc_2d
9595 (ncid, "v10m", "V10M", "10v", "10V", "v10", "V10", ctl, met, met->vs,
9596 1.0, 1))
9597 WARN("Cannot read surface meridional wind!");
9598
9599 /* Read eastward turbulent surface stress... */
9600 if (!read_met_nc_2d
9601 (ncid, "iews", "IEWS", NULL, NULL, NULL, NULL, ctl, met, met->ess,
9602 1.0, 1))
9603 WARN("Cannot read eastward turbulent surface stress!");
9604
9605 /* Read northward turbulent surface stress... */
9606 if (!read_met_nc_2d
9607 (ncid, "inss", "INSS", NULL, NULL, NULL, NULL, ctl, met, met->nss,
9608 1.0, 1))
9609 WARN("Cannot read nothward turbulent surface stress!");
9610
9611 /* Read surface sensible heat flux... */
9612 if (!read_met_nc_2d
9613 (ncid, "ishf", "ISHF", NULL, NULL, NULL, NULL, ctl, met, met->shf,
9614 1.0, 1))
9615 WARN("Cannot read surface sensible heat flux!");
9616
9617 /* Read land-sea mask... */
9618 if (!read_met_nc_2d
9619 (ncid, "lsm", "LSM", NULL, NULL, NULL, NULL, ctl, met, met->lsm, 1.0,
9620 1))
9621 WARN("Cannot read land-sea mask!");
9622
9623 /* Read sea surface temperature... */
9624 if (!read_met_nc_2d
9625 (ncid, "sstk", "SSTK", "sst", "SST", NULL, NULL, ctl, met, met->sst,
9626 1.0, 1))
9627 WARN("Cannot read sea surface temperature!");
9628
9629 /* Read PBL... */
9630 if (ctl->met_pbl == 0)
9631 if (!read_met_nc_2d
9632 (ncid, "blp", "BLP", NULL, NULL, NULL, NULL, ctl, met, met->pbl,
9633 0.01f, 1))
9634 WARN("Cannot read planetary boundary layer pressure!");
9635 if (ctl->met_pbl == 1)
9636 if (!read_met_nc_2d
9637 (ncid, "blh", "BLH", NULL, NULL, NULL, NULL, ctl, met, met->pbl,
9638 0.001f, 1))
9639 WARN("Cannot read planetary boundary layer height!");
9640
9641 /* Read CAPE... */
9642 if (ctl->met_cape == 0)
9643 if (!read_met_nc_2d
9644 (ncid, "cape", "CAPE", NULL, NULL, NULL, NULL, ctl, met, met->cape,
9645 1.0, 1))
9646 WARN("Cannot read CAPE!");
9647
9648 /* Read CIN... */
9649 if (ctl->met_cape == 0)
9650 if (!read_met_nc_2d
9651 (ncid, "cin", "CIN", NULL, NULL, NULL, NULL, ctl, met, met->cin,
9652 1.0, 1))
9653 WARN("Cannot read convective inhibition!");
9654}
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:8858
Here is the call graph for this function:

◆ read_met_nc_grid()

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

9178 {
9179
9180 char levname[LEN], tstr[10];
9181
9182 double rtime = 0, r, r2;
9183
9184 int varid, ndims, dimids[NC_MAX_DIMS], year2, mon2, day2, hour2, min2, sec2,
9185 year, mon, day, hour, min, sec;
9186
9187 size_t dimlen;
9188
9189 /* Set timer... */
9190 SELECT_TIMER("READ_MET_NC_GRID", "INPUT", NVTX_READ);
9191 LOG(2, "Read meteo grid information...");
9192
9193 /* MPTRAC meteo files... */
9194 if (ctl->met_clams == 0) {
9195
9196 /* Get time from filename... */
9197 met->time = time_from_filename(filename, 16);
9198
9199 /* Check time information from data file... */
9200 jsec2time(met->time, &year, &mon, &day, &hour, &min, &sec, &r);
9201 if (nc_inq_varid(ncid, "time", &varid) == NC_NOERR) {
9202 NC(nc_get_var_double(ncid, varid, &rtime));
9203 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
9204 WARN("Time information in meteo file does not match filename!");
9205 } else
9206 WARN("Time information in meteo file is missing!");
9207 }
9208
9209 /* CLaMS meteo files... */
9210 else {
9211
9212 /* Read time from file... */
9213 NC_GET_DOUBLE("time", &rtime, 0);
9214
9215 /* Get time from filename (considering the century)... */
9216 if (rtime < 0)
9217 sprintf(tstr, "19%.2s", &filename[strlen(filename) - 11]);
9218 else
9219 sprintf(tstr, "20%.2s", &filename[strlen(filename) - 11]);
9220 year = atoi(tstr);
9221 sprintf(tstr, "%.2s", &filename[strlen(filename) - 9]);
9222 mon = atoi(tstr);
9223 sprintf(tstr, "%.2s", &filename[strlen(filename) - 7]);
9224 day = atoi(tstr);
9225 sprintf(tstr, "%.2s", &filename[strlen(filename) - 5]);
9226 hour = atoi(tstr);
9227 time2jsec(year, mon, day, hour, 0, 0, 0, &met->time);
9228 }
9229
9230 /* Check time... */
9231 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
9232 || day < 1 || day > 31 || hour < 0 || hour > 23)
9233 ERRMSG("Cannot read time from filename!");
9234 jsec2time(met->time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
9235 LOG(2, "Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
9236 met->time, year2, mon2, day2, hour2, min2);
9237
9238 /* Get grid dimensions... */
9239 NC_INQ_DIM("lon", &met->nx, 2, EX);
9240 LOG(2, "Number of longitudes: %d", met->nx);
9241
9242 NC_INQ_DIM("lat", &met->ny, 2, EY);
9243 LOG(2, "Number of latitudes: %d", met->ny);
9244
9245 /* Read longitudes and latitudes... */
9246 NC_GET_DOUBLE("lon", met->lon, 1);
9247 LOG(2, "Longitudes: %g, %g ... %g deg",
9248 met->lon[0], met->lon[1], met->lon[met->nx - 1]);
9249 NC_GET_DOUBLE("lat", met->lat, 1);
9250 LOG(2, "Latitudes: %g, %g ... %g deg",
9251 met->lat[0], met->lat[1], met->lat[met->ny - 1]);
9252
9253 /* Check grid spacing... */
9254 for (int ix = 2; ix < met->nx; ix++)
9255 if (fabs
9256 (fabs(met->lon[ix] - met->lon[ix - 1]) -
9257 fabs(met->lon[1] - met->lon[0])) > 0.001)
9258 ERRMSG("No regular grid spacing in longitudes!");
9259 for (int iy = 2; iy < met->ny; iy++)
9260 if (fabs
9261 (fabs(met->lat[iy] - met->lat[iy - 1]) -
9262 fabs(met->lat[1] - met->lat[0])) > 0.001) {
9263 WARN("No regular grid spacing in latitudes!");
9264 break;
9265 }
9266
9267 /* Get vertical dimension... */
9268 if (nc_inq_varid(ncid, "u", &varid) != NC_NOERR)
9269 if (nc_inq_varid(ncid, "U", &varid) != NC_NOERR)
9270 ERRMSG
9271 ("Variable 'u' or 'U' not found, cannot determine vertical dimension!");
9272
9273 NC(nc_inq_varndims(ncid, varid, &ndims));
9274 NC(nc_inq_vardimid(ncid, varid, dimids));
9275
9276 if (ndims == 4) {
9277 NC(nc_inq_dim
9278 (ncid, dimids[ctl->met_convention == 0 ? 1 : 3], levname, &dimlen));
9279 } else if (ndims == 3) {
9280 NC(nc_inq_dim
9281 (ncid, dimids[ctl->met_convention == 0 ? 0 : 2], levname, &dimlen));
9282 } else
9283 ERRMSG("Cannot determine vertical dimension!")
9284 met->np = (int) dimlen;
9285
9286 LOG(2, "Number of levels: %d", met->np);
9287 if (met->np < 2 || met->np > EP)
9288 ERRMSG("Number of levels out of range!");
9289
9290 /* Read pressure levels... */
9291 if (ctl->met_np <= 0) {
9292 NC_GET_DOUBLE(levname, met->p, 1);
9293 for (int ip = 0; ip < met->np; ip++)
9294 met->p[ip] /= 100.;
9295 LOG(2, "Altitude levels: %g, %g ... %g km",
9296 Z(met->p[0]), Z(met->p[1]), Z(met->p[met->np - 1]));
9297 LOG(2, "Pressure levels: %g, %g ... %g hPa",
9298 met->p[0], met->p[1], met->p[met->np - 1]);
9299 }
9300
9301 /* Read hybrid levels... */
9302 if (strcasecmp(levname, "hybrid") == 0)
9303 NC_GET_DOUBLE("hybrid", met->hybrid, 1);
9304}
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:10709
double time_from_filename(const char *filename, const int offset)
Extracts and converts a timestamp from a filename to Julian seconds.
Definition: mptrac.c:10808
Here is the call graph for this function:

◆ read_met_nc_dd()

int read_met_nc_dd ( const char *  filename,
const ctl_t ctl,
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.
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

◆ read_met_nc_grid_dd()

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

Reads meteorological grid data from NetCDF files with domain decomposition.

The read_met_nc_grid_dd function reads meteorological data from NetCDF files and processes it with domain decomposition for parallel processing. It extracts time information, grid dimensions, and coordinates, and sets up hyperslabs for subdomains and halos. It also reads pressure levels and handles model level and surface data.

Parameters
filenameA string representing the filename of the NetCDF file to read.
ctlA pointer to a ctl_t structure containing control parameters.
metA pointer to a met_t structure where meteorological data will be stored.

The function performs the following steps:

  • Sets filenames for meteorological data files.
  • Extracts time information from the filename or NetCDF file.
  • Validates the time information and logs it.
  • Retrieves global and local grid dimensions and checks for regular grid spacing.
  • Sets up hyperslabs for subdomains and halos, considering edge cases.
  • Adjusts grid dimensions and coordinates for subdomains and halos.
  • Reads pressure levels and computes the 3D pressure field.
  • Handles model level and surface data using GRIB handles.
  • Reads grid data and surface data from the respective files.
  • Computes the 3D pressure field and reads model level data.
Note
This function assumes that the input filename and structures are properly initialized. It uses MPI for parallel processing and handles domain decomposition. The function is designed to work with NetCDF and GRIB file formats. It logs various stages of processing for debugging and validation purposes.
Author
Lars Hoffmann
Jan Clemens

◆ read_met_nc_levels_dd()

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

Reads and processes meteorological level data from NetCDF files with domain decomposition.

The read_met_nc_levels_dd function reads meteorological level data from a NetCDF file and processes it for use in a domain decomposition context. It handles various meteorological parameters such as temperature, wind components, humidity, ozone, cloud data, and vertical velocity. The function also processes pressure levels and interpolates data between model and pressure levels as needed.

Parameters
ncidAn integer representing the NetCDF file ID.
ctlA pointer to a ctl_t structure containing control parameters and settings.
metA pointer to a met_t structure where meteorological level data will be stored.

The function performs the following steps:

  • Reads temperature, horizontal wind components, and vertical velocity data.
  • Processes water vapor data, handling both specific and relative humidity.
  • Reads ozone and various cloud-related data such as liquid water content, ice water content, and cloud cover.
  • Processes zeta and zeta_dot data.
  • Stores velocities on model levels and saves the number of model levels.
  • Computes pressure on model levels using different methods based on control parameters.
  • Checks the ordering of pressure levels to ensure they are monotonic.
  • Interpolates meteorological variables from model levels to pressure levels if specified.
  • Validates the ordering of pressure levels to ensure they are in descending order.
Note
This function assumes that the NetCDF file ID and structures are properly initialized. It is designed to work with NetCDF files and uses OpenMP for parallel processing. The function logs errors and warnings for missing or unreadable data fields and handles different data formats.
Author
Lars Hoffmann
Jan Clemens

◆ read_met_nc_surface_dd()

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

Reads and processes surface meteorological data from NetCDF files with domain decomposition.

The read_met_nc_surface_dd function reads surface meteorological data from a NetCDF file and processes it for use in a domain decomposition context. It handles various surface parameters such as pressure, geopotential height, temperature, wind components, and other relevant meteorological data. The function is designed to work with different meteorological data formats and configurations.

Parameters
ncidAn integer representing the NetCDF file ID.
ctlA pointer to a ctl_t structure containing control parameters and settings.
metA pointer to a met_t structure where surface meteorological data will be stored.

The function performs the following steps:

  • Reads surface pressure data and converts it if necessary.
  • Handles different data formats for MPTRAC and CLaMS meteorological data.
  • Reads geopotential height at the surface and processes it based on the data format.
  • Retrieves surface temperature, zonal and meridional wind, and other surface parameters.
  • Logs warnings if specific data fields cannot be read.
  • Uses helper functions to read 2D and 3D data fields from the NetCDF file.
  • Processes and stores the read data into the provided meteorological data structure.
Note
This function assumes that the NetCDF file ID and structures are properly initialized. It is designed to work with NetCDF files and uses MPI for parallel processing. The function logs warnings for missing or unreadable data fields and handles different data formats.
Author
Lars Hoffmann
Jan Clemens

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

8870 {
8871
8872 char varsel[LEN];
8873
8874 float offset, scalfac;
8875
8876 int varid;
8877
8878 /* Check if variable exists... */
8879 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
8880 sprintf(varsel, "%s", varname);
8881 else if (varname2 != NULL
8882 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
8883 sprintf(varsel, "%s", varname2);
8884 else if (varname3 != NULL
8885 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
8886 sprintf(varsel, "%s", varname3);
8887 else if (varname4 != NULL
8888 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
8889 sprintf(varsel, "%s", varname4);
8890 else if (varname5 != NULL
8891 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
8892 sprintf(varsel, "%s", varname5);
8893 else if (varname6 != NULL
8894 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
8895 sprintf(varsel, "%s", varname6);
8896 else
8897 return 0;
8898
8899 /* Read packed data... */
8900 if (ctl->met_nc_scale
8901 && nc_get_att_float(ncid, varid, "add_offset", &offset) == NC_NOERR
8902 && nc_get_att_float(ncid, varid, "scale_factor",
8903 &scalfac) == NC_NOERR) {
8904
8905 /* Allocate... */
8906 short *help;
8907 ALLOC(help, short,
8908 EX * EY * EP);
8909
8910 /* Read fill value and missing value... */
8911 short fillval, missval;
8912 if (nc_get_att_short(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
8913 fillval = 0;
8914 if (nc_get_att_short(ncid, varid, "missing_value", &missval) != NC_NOERR)
8915 missval = 0;
8916
8917 /* Write info... */
8918 LOG(2, "Read 2-D variable: %s"
8919 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
8920 varsel, fillval, missval, scalfac, offset);
8921
8922 /* Read data... */
8923 NC(nc_get_var_short(ncid, varid, help));
8924
8925 /* Check meteo data layout... */
8926 if (ctl->met_convention != 0)
8927 ERRMSG("Meteo data layout not implemented for packed netCDF files!");
8928
8929 /* Copy and check data... */
8930 omp_set_dynamic(1);
8931#pragma omp parallel for default(shared)
8932 for (int ix = 0; ix < met->nx; ix++)
8933 for (int iy = 0; iy < met->ny; iy++) {
8934 if (init)
8935 dest[ix][iy] = 0;
8936 const short aux = help[ARRAY_2D(iy, ix, met->nx)];
8937 if ((fillval == 0 || aux != fillval)
8938 && (missval == 0 || aux != missval)
8939 && fabsf(aux * scalfac + offset) < 1e14f)
8940 dest[ix][iy] += scl * (aux * scalfac + offset);
8941 else
8942 dest[ix][iy] = NAN;
8943 }
8944 omp_set_dynamic(0);
8945
8946 /* Free... */
8947 free(help);
8948 }
8949
8950 /* Unpacked data... */
8951 else {
8952
8953 /* Allocate... */
8954 float *help;
8955 ALLOC(help, float,
8956 EX * EY);
8957
8958 /* Read fill value and missing value... */
8959 float fillval, missval;
8960 if (nc_get_att_float(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
8961 fillval = 0;
8962 if (nc_get_att_float(ncid, varid, "missing_value", &missval) != NC_NOERR)
8963 missval = 0;
8964
8965 /* Write info... */
8966 LOG(2, "Read 2-D variable: %s (FILL = %g, MISS = %g)",
8967 varsel, fillval, missval);
8968
8969 /* Read data... */
8970 NC(nc_get_var_float(ncid, varid, help));
8971
8972 /* Check meteo data layout... */
8973 if (ctl->met_convention == 0) {
8974
8975 /* Copy and check data (ordering: lat, lon)... */
8976 omp_set_dynamic(1);
8977#pragma omp parallel for default(shared)
8978 for (int ix = 0; ix < met->nx; ix++)
8979 for (int iy = 0; iy < met->ny; iy++) {
8980 if (init)
8981 dest[ix][iy] = 0;
8982 const float aux = help[ARRAY_2D(iy, ix, met->nx)];
8983 if ((fillval == 0 || aux != fillval)
8984 && (missval == 0 || aux != missval)
8985 && fabsf(aux) < 1e14f)
8986 dest[ix][iy] += scl * aux;
8987 else
8988 dest[ix][iy] = NAN;
8989 }
8990 omp_set_dynamic(0);
8991
8992 } else {
8993
8994 /* Copy and check data (ordering: lon, lat)... */
8995 omp_set_dynamic(1);
8996#pragma omp parallel for default(shared)
8997 for (int iy = 0; iy < met->ny; iy++)
8998 for (int ix = 0; ix < met->nx; ix++) {
8999 if (init)
9000 dest[ix][iy] = 0;
9001 const float aux = help[ARRAY_2D(ix, iy, met->ny)];
9002 if ((fillval == 0 || aux != fillval)
9003 && (missval == 0 || aux != missval)
9004 && fabsf(aux) < 1e14f)
9005 dest[ix][iy] += scl * aux;
9006 else
9007 dest[ix][iy] = NAN;
9008 }
9009 omp_set_dynamic(0);
9010 }
9011
9012 /* Free... */
9013 free(help);
9014 }
9015
9016 /* Return... */
9017 return 1;
9018}

◆ read_met_nc_2d_dd()

int read_met_nc_2d_dd ( 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 in parallel 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

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

9031 {
9032
9033 char varsel[LEN];
9034
9035 float offset, scalfac;
9036
9037 int varid;
9038
9039 /* Check if variable exists... */
9040 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
9041 sprintf(varsel, "%s", varname);
9042 else if (varname2 != NULL
9043 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
9044 sprintf(varsel, "%s", varname2);
9045 else if (varname3 != NULL
9046 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
9047 sprintf(varsel, "%s", varname3);
9048 else if (varname4 != NULL
9049 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
9050 sprintf(varsel, "%s", varname4);
9051 else
9052 return 0;
9053
9054 /* Read packed data... */
9055 if (ctl->met_nc_scale
9056 && nc_get_att_float(ncid, varid, "add_offset", &offset) == NC_NOERR
9057 && nc_get_att_float(ncid, varid, "scale_factor",
9058 &scalfac) == NC_NOERR) {
9059
9060 /* Allocate... */
9061 short *help;
9062 ALLOC(help, short,
9063 EX * EY * EP);
9064
9065 /* Read fill value and missing value... */
9066 short fillval, missval;
9067 if (nc_get_att_short(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
9068 fillval = 0;
9069 if (nc_get_att_short(ncid, varid, "missing_value", &missval) != NC_NOERR)
9070 missval = 0;
9071
9072 /* Write info... */
9073 LOG(2, "Read 3-D variable: %s "
9074 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
9075 varsel, fillval, missval, scalfac, offset);
9076
9077 /* Read data... */
9078 NC(nc_get_var_short(ncid, varid, help));
9079
9080 /* Check meteo data layout... */
9081 if (ctl->met_convention != 0)
9082 ERRMSG("Meteo data layout not implemented for packed netCDF files!");
9083
9084 /* Copy and check data... */
9085 omp_set_dynamic(1);
9086#pragma omp parallel for default(shared)
9087 for (int ix = 0; ix < met->nx; ix++)
9088 for (int iy = 0; iy < met->ny; iy++)
9089 for (int ip = 0; ip < met->np; ip++) {
9090 const short aux = help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)];
9091 if ((fillval == 0 || aux != fillval)
9092 && (missval == 0 || aux != missval)
9093 && fabsf(aux * scalfac + offset) < 1e14f)
9094 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
9095 else
9096 dest[ix][iy][ip] = NAN;
9097 }
9098 omp_set_dynamic(0);
9099
9100 /* Free... */
9101 free(help);
9102 }
9103
9104 /* Unpacked data... */
9105 else {
9106
9107 /* Allocate... */
9108 float *help;
9109 ALLOC(help, float,
9110 EX * EY * EP);
9111
9112 /* Read fill value and missing value... */
9113 float fillval, missval;
9114 if (nc_get_att_float(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
9115 fillval = 0;
9116 if (nc_get_att_float(ncid, varid, "missing_value", &missval) != NC_NOERR)
9117 missval = 0;
9118
9119 /* Write info... */
9120 LOG(2, "Read 3-D variable: %s (FILL = %g, MISS = %g)",
9121 varsel, fillval, missval);
9122
9123 /* Read data... */
9124 NC(nc_get_var_float(ncid, varid, help));
9125
9126 /* Check meteo data layout... */
9127 if (ctl->met_convention == 0) {
9128
9129 /* Copy and check data (ordering: lev, lat, lon)... */
9130 omp_set_dynamic(1);
9131#pragma omp parallel for default(shared)
9132 for (int ix = 0; ix < met->nx; ix++)
9133 for (int iy = 0; iy < met->ny; iy++)
9134 for (int ip = 0; ip < met->np; ip++) {
9135 const float aux = help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)];
9136 if ((fillval == 0 || aux != fillval)
9137 && (missval == 0 || aux != missval)
9138 && fabsf(aux) < 1e14f)
9139 dest[ix][iy][ip] = scl * aux;
9140 else
9141 dest[ix][iy][ip] = NAN;
9142 }
9143 omp_set_dynamic(0);
9144
9145 } else {
9146
9147 /* Copy and check data (ordering: lon, lat, lev)... */
9148 omp_set_dynamic(1);
9149#pragma omp parallel for default(shared)
9150 for (int ip = 0; ip < met->np; ip++)
9151 for (int iy = 0; iy < met->ny; iy++)
9152 for (int ix = 0; ix < met->nx; ix++) {
9153 const float aux = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
9154 if ((fillval == 0 || aux != fillval)
9155 && (missval == 0 || aux != missval)
9156 && fabsf(aux) < 1e14f)
9157 dest[ix][iy][ip] = scl * aux;
9158 else
9159 dest[ix][iy][ip] = NAN;
9160 }
9161 omp_set_dynamic(0);
9162 }
9163
9164 /* Free... */
9165 free(help);
9166 }
9167
9168 /* Return... */
9169 return 1;
9170}

◆ read_met_nc_3d_dd()

int read_met_nc_3d_dd ( 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

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

9660 {
9661
9662 /* Set timer... */
9663 SELECT_TIMER("READ_MET_PBL", "METPROC", NVTX_READ);
9664 LOG(2, "Calculate planetary boundary layer...");
9665
9666 /* Convert PBL height from meteo file to pressure... */
9667 if (ctl->met_pbl == 1) {
9668
9669 /* Loop over grid points... */
9670#pragma omp parallel for default(shared) collapse(2)
9671 for (int ix = 0; ix < met->nx; ix++)
9672 for (int iy = 0; iy < met->ny; iy++) {
9673
9674 /* Get pressure at top of PBL... */
9675 const float z = met->zs[ix][iy] + met->pbl[ix][iy];
9676 const int ip = locate_irr_float(met->z[ix][iy], met->np, z, 0);
9677 met->pbl[ix][iy] =
9678 (float) (LIN(met->z[ix][iy][ip], met->p[ip],
9679 met->z[ix][iy][ip + 1], met->p[ip + 1], z));
9680 }
9681 }
9682
9683 /* Determine PBL based on Richardson number... */
9684 else if (ctl->met_pbl == 2) {
9685
9686 /* Parameters used to estimate the height of the PBL
9687 (e.g., Vogelezang and Holtslag, 1996; Seidel et al., 2012)... */
9688 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
9689
9690 /* Loop over grid points... */
9691#pragma omp parallel for default(shared) collapse(2)
9692 for (int ix = 0; ix < met->nx; ix++)
9693 for (int iy = 0; iy < met->ny; iy++) {
9694
9695 /* Set bottom level of PBL... */
9696 const double pbl_bot = met->ps[ix][iy] * exp(-dz / H0);
9697
9698 /* Find lowest level near the bottom... */
9699 int ip;
9700 for (ip = 1; ip < met->np; ip++)
9701 if (met->p[ip] < pbl_bot)
9702 break;
9703
9704 /* Get near surface data... */
9705 const double h2os = LIN(met->p[ip - 1], met->h2o[ix][iy][ip - 1],
9706 met->p[ip], met->h2o[ix][iy][ip], pbl_bot);
9707 const double tvs = THETAVIRT(pbl_bot, met->ts[ix][iy], h2os);
9708
9709 /* Init... */
9710 double rib_old = 0;
9711
9712 /* Loop over levels... */
9713 for (; ip < met->np; ip++) {
9714
9715 /* Get squared horizontal wind speed... */
9716 double vh2 = SQR(met->u[ix][iy][ip] - met->us[ix][iy])
9717 + SQR(met->v[ix][iy][ip] - met->vs[ix][iy]);
9718 vh2 = MAX(vh2, SQR(umin));
9719
9720 /* Calculate bulk Richardson number... */
9721 const double rib =
9722 G0 * 1e3 * (met->z[ix][iy][ip] - met->zs[ix][iy]) / tvs
9723 * (THETAVIRT(met->p[ip], met->t[ix][iy][ip],
9724 met->h2o[ix][iy][ip]) - tvs) / vh2;
9725
9726 /* Check for critical value... */
9727 if (rib >= rib_crit) {
9728 met->pbl[ix][iy] = (float) (LIN(rib_old, met->p[ip - 1],
9729 rib, met->p[ip], rib_crit));
9730 if (met->pbl[ix][iy] > pbl_bot)
9731 met->pbl[ix][iy] = (float) pbl_bot;
9732 break;
9733 }
9734
9735 /* Save Richardson number... */
9736 rib_old = rib;
9737 }
9738 }
9739 }
9740
9741 /* Determine PBL based on potential temperature... */
9742 if (ctl->met_pbl == 3) {
9743
9744 /* Parameters used to estimate the height of the PBL
9745 (following HYSPLIT model)... */
9746 const double dtheta = 2.0, zmin = 0.1;
9747
9748 /* Loop over grid points... */
9749#pragma omp parallel for default(shared) collapse(2)
9750 for (int ix = 0; ix < met->nx; ix++)
9751 for (int iy = 0; iy < met->ny; iy++) {
9752
9753 /* Potential temperature at the surface... */
9754 const double theta0 = THETA(met->ps[ix][iy], met->ts[ix][iy]);
9755
9756 /* Find topmost level where theta exceeds surface value by 2 K... */
9757 int ip;
9758 for (ip = met->np - 2; ip > 0; ip--)
9759 if (met->p[ip] >= 300.)
9760 if (met->p[ip] > met->ps[ix][iy]
9761 || THETA(met->p[ip], met->t[ix][iy][ip]) <= theta0 + dtheta)
9762 break;
9763
9764 /* Interpolate... */
9765 met->pbl[ix][iy]
9766 = (float) (LIN(THETA(met->p[ip + 1], met->t[ix][iy][ip + 1]),
9767 met->p[ip + 1],
9768 THETA(met->p[ip], met->t[ix][iy][ip]),
9769 met->p[ip], theta0 + dtheta));
9770
9771 /* Check minimum value... */
9772 double pbl_min = met->ps[ix][iy] * exp(-zmin / H0);
9773 if (met->pbl[ix][iy] > pbl_min || met->p[ip] > met->ps[ix][iy])
9774 met->pbl[ix][iy] = (float) pbl_min;
9775 }
9776 }
9777
9778 /* Loop over grid points... */
9779#pragma omp parallel for default(shared) collapse(2)
9780 for (int ix = 0; ix < met->nx; ix++)
9781 for (int iy = 0; iy < met->ny; iy++) {
9782
9783 /* Check minimum value... */
9784 double pbl_min = met->ps[ix][iy] * exp(-ctl->met_pbl_min / H0);
9785 met->pbl[ix][iy] = MIN(met->pbl[ix][iy], (float) pbl_min);
9786
9787 /* Check maximum value... */
9788 double pbl_max = met->ps[ix][iy] * exp(-ctl->met_pbl_max / H0);
9789 met->pbl[ix][iy] = MAX(met->pbl[ix][iy], (float) pbl_max);
9790 }
9791}
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 9795 of file mptrac.c.

9796 {
9797
9798 /* Set timer... */
9799 SELECT_TIMER("READ_MET_PERIODIC", "METPROC", NVTX_READ);
9800 LOG(2, "Apply periodic boundary conditions...");
9801
9802 /* Check longitudes... */
9803 if (!(fabs(met->lon[met->nx - 1] - met->lon[0]
9804 + met->lon[1] - met->lon[0] - 360) < 0.01))
9805 return;
9806
9807 /* Increase longitude counter... */
9808 if ((++met->nx) >= EX)
9809 ERRMSG("Cannot create periodic boundary conditions!");
9810
9811 /* Set longitude... */
9812 met->lon[met->nx - 1] = met->lon[met->nx - 2] + met->lon[1] - met->lon[0];
9813
9814 /* Loop over latitudes and pressure levels... */
9815#pragma omp parallel for default(shared)
9816 for (int iy = 0; iy < met->ny; iy++) {
9817 met->ps[met->nx - 1][iy] = met->ps[0][iy];
9818 met->zs[met->nx - 1][iy] = met->zs[0][iy];
9819 met->ts[met->nx - 1][iy] = met->ts[0][iy];
9820 met->us[met->nx - 1][iy] = met->us[0][iy];
9821 met->vs[met->nx - 1][iy] = met->vs[0][iy];
9822 met->ess[met->nx - 1][iy] = met->ess[0][iy];
9823 met->nss[met->nx - 1][iy] = met->nss[0][iy];
9824 met->shf[met->nx - 1][iy] = met->shf[0][iy];
9825 met->lsm[met->nx - 1][iy] = met->lsm[0][iy];
9826 met->sst[met->nx - 1][iy] = met->sst[0][iy];
9827 met->pbl[met->nx - 1][iy] = met->pbl[0][iy];
9828 met->cape[met->nx - 1][iy] = met->cape[0][iy];
9829 met->cin[met->nx - 1][iy] = met->cin[0][iy];
9830 for (int ip = 0; ip < met->np; ip++) {
9831 met->t[met->nx - 1][iy][ip] = met->t[0][iy][ip];
9832 met->u[met->nx - 1][iy][ip] = met->u[0][iy][ip];
9833 met->v[met->nx - 1][iy][ip] = met->v[0][iy][ip];
9834 met->w[met->nx - 1][iy][ip] = met->w[0][iy][ip];
9835 met->h2o[met->nx - 1][iy][ip] = met->h2o[0][iy][ip];
9836 met->o3[met->nx - 1][iy][ip] = met->o3[0][iy][ip];
9837 met->lwc[met->nx - 1][iy][ip] = met->lwc[0][iy][ip];
9838 met->rwc[met->nx - 1][iy][ip] = met->rwc[0][iy][ip];
9839 met->iwc[met->nx - 1][iy][ip] = met->iwc[0][iy][ip];
9840 met->swc[met->nx - 1][iy][ip] = met->swc[0][iy][ip];
9841 met->cc[met->nx - 1][iy][ip] = met->cc[0][iy][ip];
9842 }
9843 for (int ip = 0; ip < met->npl; ip++) {
9844 met->ul[met->nx - 1][iy][ip] = met->ul[0][iy][ip];
9845 met->vl[met->nx - 1][iy][ip] = met->vl[0][iy][ip];
9846 met->wl[met->nx - 1][iy][ip] = met->wl[0][iy][ip];
9847 met->pl[met->nx - 1][iy][ip] = met->pl[0][iy][ip];
9848 met->zetal[met->nx - 1][iy][ip] = met->zetal[0][iy][ip];
9849 met->zeta_dotl[met->nx - 1][iy][ip] = met->zeta_dotl[0][iy][ip];
9850 }
9851 }
9852}

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

9857 {
9858
9859 /* Set timer... */
9860 SELECT_TIMER("READ_MET_POLAR_WINDS", "METPROC", NVTX_READ);
9861 LOG(2, "Apply fix for polar winds...");
9862
9863 /* Check latitudes... */
9864 if (fabs(met->lat[0]) < 89.999 || fabs(met->lat[met->ny - 1]) < 89.999)
9865 return;
9866
9867 /* Loop over hemispheres... */
9868 for (int ihem = 0; ihem < 2; ihem++) {
9869
9870 /* Set latitude indices... */
9871 int i89 = 1, i90 = 0, sign = 1;
9872 if (ihem == 1) {
9873 i89 = met->ny - 2;
9874 i90 = met->ny - 1;
9875 }
9876 if (met->lat[i90] < 0)
9877 sign = -1;
9878
9879 /* Look-up table of cosinus and sinus... */
9880 double clon[EX], slon[EX];
9881#pragma omp parallel for default(shared)
9882 for (int ix = 0; ix < met->nx; ix++) {
9883 clon[ix] = cos(sign * DEG2RAD(met->lon[ix]));
9884 slon[ix] = sin(sign * DEG2RAD(met->lon[ix]));
9885 }
9886
9887 /* Loop over levels... */
9888#pragma omp parallel for default(shared)
9889 for (int ip = 0; ip < met->np; ip++) {
9890
9891 /* Transform 89 degree u and v winds into Cartesian coordinates and take the mean... */
9892 double vel89x = 0, vel89y = 0;
9893 for (int ix = 0; ix < met->nx; ix++) {
9894 vel89x +=
9895 (met->u[ix][i89][ip] * clon[ix] -
9896 met->v[ix][i89][ip] * slon[ix]) / met->nx;
9897 vel89y +=
9898 (met->u[ix][i89][ip] * slon[ix] +
9899 met->v[ix][i89][ip] * clon[ix]) / met->nx;
9900 }
9901
9902 /* Replace 90 degree winds by 89 degree mean... */
9903 for (int ix = 0; ix < met->nx; ix++) {
9904 met->u[ix][i90][ip]
9905 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
9906 met->v[ix][i90][ip]
9907 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
9908 }
9909 }
9910 }
9911}

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

9916 {
9917
9918 double pows[EP];
9919
9920 /* Set timer... */
9921 SELECT_TIMER("READ_MET_PV", "METPROC", NVTX_READ);
9922 LOG(2, "Calculate potential vorticity...");
9923
9924 /* Set powers... */
9925#pragma omp parallel for default(shared)
9926 for (int ip = 0; ip < met->np; ip++)
9927 pows[ip] = pow(1000. / met->p[ip], 0.286);
9928
9929 /* Loop over grid points... */
9930#pragma omp parallel for default(shared)
9931 for (int ix = 0; ix < met->nx; ix++) {
9932
9933 /* Set indices... */
9934 const int ix0 = MAX(ix - 1, 0);
9935 const int ix1 = MIN(ix + 1, met->nx - 1);
9936
9937 /* Loop over grid points... */
9938 for (int iy = 0; iy < met->ny; iy++) {
9939
9940 /* Set indices... */
9941 const int iy0 = MAX(iy - 1, 0);
9942 const int iy1 = MIN(iy + 1, met->ny - 1);
9943
9944 /* Set auxiliary variables... */
9945 const double latr = 0.5 * (met->lat[iy1] + met->lat[iy0]);
9946 const double dx = 1000. * DEG2DX(met->lon[ix1] - met->lon[ix0], latr);
9947 const double dy = 1000. * DEG2DY(met->lat[iy1] - met->lat[iy0]);
9948 const double c0 = cos(DEG2RAD(met->lat[iy0]));
9949 const double c1 = cos(DEG2RAD(met->lat[iy1]));
9950 const double cr = cos(DEG2RAD(latr));
9951 const double vort = 2 * 7.2921e-5 * sin(DEG2RAD(latr));
9952
9953 /* Loop over grid points... */
9954 for (int ip = 0; ip < met->np; ip++) {
9955
9956 /* Get gradients in longitude... */
9957 const double dtdx
9958 = (met->t[ix1][iy][ip] - met->t[ix0][iy][ip]) * pows[ip] / dx;
9959 const double dvdx = (met->v[ix1][iy][ip] - met->v[ix0][iy][ip]) / dx;
9960
9961 /* Get gradients in latitude... */
9962 const double dtdy
9963 = (met->t[ix][iy1][ip] - met->t[ix][iy0][ip]) * pows[ip] / dy;
9964 const double dudy
9965 = (met->u[ix][iy1][ip] * c1 - met->u[ix][iy0][ip] * c0) / dy;
9966
9967 /* Set indices... */
9968 const int ip0 = MAX(ip - 1, 0);
9969 const int ip1 = MIN(ip + 1, met->np - 1);
9970
9971 /* Get gradients in pressure... */
9972 double dtdp, dudp, dvdp;
9973 const double dp0 = 100. * (met->p[ip] - met->p[ip0]);
9974 const double dp1 = 100. * (met->p[ip1] - met->p[ip]);
9975 if (ip != ip0 && ip != ip1) {
9976 double denom = dp0 * dp1 * (dp0 + dp1);
9977 dtdp = (dp0 * dp0 * met->t[ix][iy][ip1] * pows[ip1]
9978 - dp1 * dp1 * met->t[ix][iy][ip0] * pows[ip0]
9979 + (dp1 * dp1 - dp0 * dp0) * met->t[ix][iy][ip] * pows[ip])
9980 / denom;
9981 dudp = (dp0 * dp0 * met->u[ix][iy][ip1]
9982 - dp1 * dp1 * met->u[ix][iy][ip0]
9983 + (dp1 * dp1 - dp0 * dp0) * met->u[ix][iy][ip])
9984 / denom;
9985 dvdp = (dp0 * dp0 * met->v[ix][iy][ip1]
9986 - dp1 * dp1 * met->v[ix][iy][ip0]
9987 + (dp1 * dp1 - dp0 * dp0) * met->v[ix][iy][ip])
9988 / denom;
9989 } else {
9990 const double denom = dp0 + dp1;
9991 dtdp =
9992 (met->t[ix][iy][ip1] * pows[ip1] -
9993 met->t[ix][iy][ip0] * pows[ip0]) / denom;
9994 dudp = (met->u[ix][iy][ip1] - met->u[ix][iy][ip0]) / denom;
9995 dvdp = (met->v[ix][iy][ip1] - met->v[ix][iy][ip0]) / denom;
9996 }
9997
9998 /* Calculate PV... */
9999 met->pv[ix][iy][ip] = (float)
10000 (1e6 * G0 *
10001 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
10002 }
10003 }
10004 }
10005
10006 /* Fix for polar regions... */
10007#pragma omp parallel for default(shared)
10008 for (int ix = 0; ix < met->nx; ix++)
10009 for (int ip = 0; ip < met->np; ip++) {
10010 met->pv[ix][0][ip]
10011 = met->pv[ix][1][ip]
10012 = met->pv[ix][2][ip];
10013 met->pv[ix][met->ny - 1][ip]
10014 = met->pv[ix][met->ny - 2][ip]
10015 = met->pv[ix][met->ny - 3][ip];
10016 }
10017}
#define DEG2DY(dlat)
Convert a latitude difference to a distance in the y-direction (north-south).
Definition: mptrac.h:529
#define DEG2DX(dlon, lat)
Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude.
Definition: mptrac.h:508

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

10022 {
10023
10024 /* Set timer... */
10025 SELECT_TIMER("READ_MET_OZONE", "METPROC", NVTX_READ);
10026 LOG(2, "Calculate total column ozone...");
10027
10028 /* Loop over columns... */
10029#pragma omp parallel for default(shared) collapse(2)
10030 for (int ix = 0; ix < met->nx; ix++)
10031 for (int iy = 0; iy < met->ny; iy++) {
10032
10033 /* Integrate... */
10034 double cd = 0;
10035 for (int ip = 1; ip < met->np; ip++)
10036 if (met->p[ip - 1] <= met->ps[ix][iy]) {
10037 const double vmr =
10038 0.5 * (met->o3[ix][iy][ip - 1] + met->o3[ix][iy][ip]);
10039 const double dp = met->p[ip - 1] - met->p[ip];
10040 cd += vmr * MO3 / MA * dp * 1e2 / G0;
10041 }
10042
10043 /* Convert to Dobson units... */
10044 met->o3c[ix][iy] = (float) (cd / 2.1415e-5);
10045 }
10046}

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

10052 {
10053
10054 met_t *help;
10055
10056 /* Check parameters... */
10057 if (ctl->met_dp <= 1 && ctl->met_dx <= 1 && ctl->met_dy <= 1
10058 && ctl->met_sp <= 1 && ctl->met_sx <= 1 && ctl->met_sy <= 1)
10059 return;
10060
10061 /* Set timer... */
10062 SELECT_TIMER("READ_MET_SAMPLE", "METPROC", NVTX_READ);
10063 LOG(2, "Downsampling of meteo data...");
10064
10065 /* Allocate... */
10066 ALLOC(help, met_t, 1);
10067
10068 /* Copy data... */
10069 help->nx = met->nx;
10070 help->ny = met->ny;
10071 help->np = met->np;
10072 memcpy(help->lon, met->lon, sizeof(met->lon));
10073 memcpy(help->lat, met->lat, sizeof(met->lat));
10074 memcpy(help->p, met->p, sizeof(met->p));
10075
10076 /* Smoothing... */
10077 for (int ix = 0; ix < met->nx; ix += ctl->met_dx) {
10078 for (int iy = 0; iy < met->ny; iy += ctl->met_dy) {
10079 for (int ip = 0; ip < met->np; ip += ctl->met_dp) {
10080 help->ps[ix][iy] = 0;
10081 help->zs[ix][iy] = 0;
10082 help->ts[ix][iy] = 0;
10083 help->us[ix][iy] = 0;
10084 help->vs[ix][iy] = 0;
10085 help->ess[ix][iy] = 0;
10086 help->nss[ix][iy] = 0;
10087 help->shf[ix][iy] = 0;
10088 help->lsm[ix][iy] = 0;
10089 help->sst[ix][iy] = 0;
10090 help->pbl[ix][iy] = 0;
10091 help->cape[ix][iy] = 0;
10092 help->cin[ix][iy] = 0;
10093 help->t[ix][iy][ip] = 0;
10094 help->u[ix][iy][ip] = 0;
10095 help->v[ix][iy][ip] = 0;
10096 help->w[ix][iy][ip] = 0;
10097 help->h2o[ix][iy][ip] = 0;
10098 help->o3[ix][iy][ip] = 0;
10099 help->lwc[ix][iy][ip] = 0;
10100 help->rwc[ix][iy][ip] = 0;
10101 help->iwc[ix][iy][ip] = 0;
10102 help->swc[ix][iy][ip] = 0;
10103 help->cc[ix][iy][ip] = 0;
10104 float wsum = 0;
10105 for (int ix2 = ix - ctl->met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
10106 ix2++) {
10107 int ix3 = ix2;
10108 if (ix3 < 0)
10109 ix3 += met->nx;
10110 else if (ix3 >= met->nx)
10111 ix3 -= met->nx;
10112
10113 for (int iy2 = MAX(iy - ctl->met_sy + 1, 0);
10114 iy2 <= MIN(iy + ctl->met_sy - 1, met->ny - 1); iy2++)
10115 for (int ip2 = MAX(ip - ctl->met_sp + 1, 0);
10116 ip2 <= MIN(ip + ctl->met_sp - 1, met->np - 1); ip2++) {
10117 float w = (1.0f - (float) abs(ix - ix2) / (float) ctl->met_sx)
10118 * (1.0f - (float) abs(iy - iy2) / (float) ctl->met_sy)
10119 * (1.0f - (float) abs(ip - ip2) / (float) ctl->met_sp);
10120 help->ps[ix][iy] += w * met->ps[ix3][iy2];
10121 help->zs[ix][iy] += w * met->zs[ix3][iy2];
10122 help->ts[ix][iy] += w * met->ts[ix3][iy2];
10123 help->us[ix][iy] += w * met->us[ix3][iy2];
10124 help->vs[ix][iy] += w * met->vs[ix3][iy2];
10125 help->ess[ix][iy] += w * met->ess[ix3][iy2];
10126 help->nss[ix][iy] += w * met->nss[ix3][iy2];
10127 help->shf[ix][iy] += w * met->shf[ix3][iy2];
10128 help->lsm[ix][iy] += w * met->lsm[ix3][iy2];
10129 help->sst[ix][iy] += w * met->sst[ix3][iy2];
10130 help->pbl[ix][iy] += w * met->pbl[ix3][iy2];
10131 help->cape[ix][iy] += w * met->cape[ix3][iy2];
10132 help->cin[ix][iy] += w * met->cin[ix3][iy2];
10133 help->t[ix][iy][ip] += w * met->t[ix3][iy2][ip2];
10134 help->u[ix][iy][ip] += w * met->u[ix3][iy2][ip2];
10135 help->v[ix][iy][ip] += w * met->v[ix3][iy2][ip2];
10136 help->w[ix][iy][ip] += w * met->w[ix3][iy2][ip2];
10137 help->h2o[ix][iy][ip] += w * met->h2o[ix3][iy2][ip2];
10138 help->o3[ix][iy][ip] += w * met->o3[ix3][iy2][ip2];
10139 help->lwc[ix][iy][ip] += w * met->lwc[ix3][iy2][ip2];
10140 help->rwc[ix][iy][ip] += w * met->rwc[ix3][iy2][ip2];
10141 help->iwc[ix][iy][ip] += w * met->iwc[ix3][iy2][ip2];
10142 help->swc[ix][iy][ip] += w * met->swc[ix3][iy2][ip2];
10143 help->cc[ix][iy][ip] += w * met->cc[ix3][iy2][ip2];
10144 wsum += w;
10145 }
10146 }
10147 help->ps[ix][iy] /= wsum;
10148 help->zs[ix][iy] /= wsum;
10149 help->ts[ix][iy] /= wsum;
10150 help->us[ix][iy] /= wsum;
10151 help->vs[ix][iy] /= wsum;
10152 help->ess[ix][iy] /= wsum;
10153 help->nss[ix][iy] /= wsum;
10154 help->shf[ix][iy] /= wsum;
10155 help->lsm[ix][iy] /= wsum;
10156 help->sst[ix][iy] /= wsum;
10157 help->pbl[ix][iy] /= wsum;
10158 help->cape[ix][iy] /= wsum;
10159 help->cin[ix][iy] /= wsum;
10160 help->t[ix][iy][ip] /= wsum;
10161 help->u[ix][iy][ip] /= wsum;
10162 help->v[ix][iy][ip] /= wsum;
10163 help->w[ix][iy][ip] /= wsum;
10164 help->h2o[ix][iy][ip] /= wsum;
10165 help->o3[ix][iy][ip] /= wsum;
10166 help->lwc[ix][iy][ip] /= wsum;
10167 help->rwc[ix][iy][ip] /= wsum;
10168 help->iwc[ix][iy][ip] /= wsum;
10169 help->swc[ix][iy][ip] /= wsum;
10170 help->cc[ix][iy][ip] /= wsum;
10171 }
10172 }
10173 }
10174
10175 /* Downsampling... */
10176 met->nx = 0;
10177 for (int ix = 0; ix < help->nx; ix += ctl->met_dx) {
10178 met->lon[met->nx] = help->lon[ix];
10179 met->ny = 0;
10180 for (int iy = 0; iy < help->ny; iy += ctl->met_dy) {
10181 met->lat[met->ny] = help->lat[iy];
10182 met->ps[met->nx][met->ny] = help->ps[ix][iy];
10183 met->zs[met->nx][met->ny] = help->zs[ix][iy];
10184 met->ts[met->nx][met->ny] = help->ts[ix][iy];
10185 met->us[met->nx][met->ny] = help->us[ix][iy];
10186 met->vs[met->nx][met->ny] = help->vs[ix][iy];
10187 met->ess[met->nx][met->ny] = help->ess[ix][iy];
10188 met->nss[met->nx][met->ny] = help->nss[ix][iy];
10189 met->shf[met->nx][met->ny] = help->shf[ix][iy];
10190 met->lsm[met->nx][met->ny] = help->lsm[ix][iy];
10191 met->sst[met->nx][met->ny] = help->sst[ix][iy];
10192 met->pbl[met->nx][met->ny] = help->pbl[ix][iy];
10193 met->cape[met->nx][met->ny] = help->cape[ix][iy];
10194 met->cin[met->nx][met->ny] = help->cin[ix][iy];
10195 met->np = 0;
10196 for (int ip = 0; ip < help->np; ip += ctl->met_dp) {
10197 met->p[met->np] = help->p[ip];
10198 met->t[met->nx][met->ny][met->np] = help->t[ix][iy][ip];
10199 met->u[met->nx][met->ny][met->np] = help->u[ix][iy][ip];
10200 met->v[met->nx][met->ny][met->np] = help->v[ix][iy][ip];
10201 met->w[met->nx][met->ny][met->np] = help->w[ix][iy][ip];
10202 met->h2o[met->nx][met->ny][met->np] = help->h2o[ix][iy][ip];
10203 met->o3[met->nx][met->ny][met->np] = help->o3[ix][iy][ip];
10204 met->lwc[met->nx][met->ny][met->np] = help->lwc[ix][iy][ip];
10205 met->rwc[met->nx][met->ny][met->np] = help->rwc[ix][iy][ip];
10206 met->iwc[met->nx][met->ny][met->np] = help->iwc[ix][iy][ip];
10207 met->swc[met->nx][met->ny][met->np] = help->swc[ix][iy][ip];
10208 met->cc[met->nx][met->ny][met->np] = help->cc[ix][iy][ip];
10209 met->np++;
10210 }
10211 met->ny++;
10212 }
10213 met->nx++;
10214 }
10215
10216 /* Free... */
10217 free(help);
10218}

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

10225 {
10226
10227 double p2[200], pv[EP], pv2[200], t[EP], t2[200], th[EP],
10228 th2[200], z[EP], z2[200];
10229
10230 /* Set timer... */
10231 SELECT_TIMER("READ_MET_TROPO", "METPROC", NVTX_READ);
10232 LOG(2, "Calculate tropopause...");
10233
10234 /* Get altitude and pressure profiles... */
10235#pragma omp parallel for default(shared)
10236 for (int iz = 0; iz < met->np; iz++)
10237 z[iz] = Z(met->p[iz]);
10238#pragma omp parallel for default(shared)
10239 for (int iz = 0; iz <= 190; iz++) {
10240 z2[iz] = 4.5 + 0.1 * iz;
10241 p2[iz] = P(z2[iz]);
10242 }
10243
10244 /* Do not calculate tropopause... */
10245 if (ctl->met_tropo == 0)
10246#pragma omp parallel for default(shared) collapse(2)
10247 for (int ix = 0; ix < met->nx; ix++)
10248 for (int iy = 0; iy < met->ny; iy++)
10249 met->pt[ix][iy] = NAN;
10250
10251 /* Use tropopause climatology... */
10252 else if (ctl->met_tropo == 1) {
10253#pragma omp parallel for default(shared) collapse(2)
10254 for (int ix = 0; ix < met->nx; ix++)
10255 for (int iy = 0; iy < met->ny; iy++)
10256 met->pt[ix][iy] = (float) clim_tropo(clim, met->time, met->lat[iy]);
10257 }
10258
10259 /* Use cold point... */
10260 else if (ctl->met_tropo == 2) {
10261
10262 /* Loop over grid points... */
10263#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10264 for (int ix = 0; ix < met->nx; ix++)
10265 for (int iy = 0; iy < met->ny; iy++) {
10266
10267 /* Interpolate temperature profile... */
10268 for (int iz = 0; iz < met->np; iz++)
10269 t[iz] = met->t[ix][iy][iz];
10270 spline(z, t, met->np, z2, t2, 171, ctl->met_tropo_spline);
10271
10272 /* Find minimum... */
10273 int iz = (int) gsl_stats_min_index(t2, 1, 171);
10274 if (iz > 0 && iz < 170)
10275 met->pt[ix][iy] = (float) p2[iz];
10276 else
10277 met->pt[ix][iy] = NAN;
10278 }
10279 }
10280
10281 /* Use WMO definition... */
10282 else if (ctl->met_tropo == 3 || ctl->met_tropo == 4) {
10283
10284 /* Loop over grid points... */
10285#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10286 for (int ix = 0; ix < met->nx; ix++)
10287 for (int iy = 0; iy < met->ny; iy++) {
10288
10289 /* Interpolate temperature profile... */
10290 int iz;
10291 for (iz = 0; iz < met->np; iz++)
10292 t[iz] = met->t[ix][iy][iz];
10293 spline(z, t, met->np, z2, t2, 191, ctl->met_tropo_spline);
10294
10295 /* Find 1st tropopause... */
10296 met->pt[ix][iy] = NAN;
10297 for (iz = 0; iz <= 170; iz++) {
10298 int found = 1;
10299 for (int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10300 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10301 found = 0;
10302 break;
10303 }
10304 if (found) {
10305 if (iz > 0 && iz < 170)
10306 met->pt[ix][iy] = (float) p2[iz];
10307 break;
10308 }
10309 }
10310
10311 /* Find 2nd tropopause... */
10312 if (ctl->met_tropo == 4) {
10313 met->pt[ix][iy] = NAN;
10314 for (; iz <= 170; iz++) {
10315 int found = 1;
10316 for (int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
10317 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
10318 found = 0;
10319 break;
10320 }
10321 if (found)
10322 break;
10323 }
10324 for (; iz <= 170; iz++) {
10325 int found = 1;
10326 for (int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10327 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10328 found = 0;
10329 break;
10330 }
10331 if (found) {
10332 if (iz > 0 && iz < 170)
10333 met->pt[ix][iy] = (float) p2[iz];
10334 break;
10335 }
10336 }
10337 }
10338 }
10339 }
10340
10341 /* Use dynamical tropopause... */
10342 else if (ctl->met_tropo == 5) {
10343
10344 /* Loop over grid points... */
10345#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
10346 for (int ix = 0; ix < met->nx; ix++)
10347 for (int iy = 0; iy < met->ny; iy++) {
10348
10349 /* Interpolate potential vorticity profile... */
10350 for (int iz = 0; iz < met->np; iz++)
10351 pv[iz] = met->pv[ix][iy][iz];
10352 spline(z, pv, met->np, z2, pv2, 171, ctl->met_tropo_spline);
10353
10354 /* Interpolate potential temperature profile... */
10355 for (int iz = 0; iz < met->np; iz++)
10356 th[iz] = THETA(met->p[iz], met->t[ix][iy][iz]);
10357 spline(z, th, met->np, z2, th2, 171, ctl->met_tropo_spline);
10358
10359 /* Find dynamical tropopause... */
10360 met->pt[ix][iy] = NAN;
10361 for (int iz = 0; iz <= 170; iz++)
10362 if (fabs(pv2[iz]) >= ctl->met_tropo_pv
10363 || th2[iz] >= ctl->met_tropo_theta) {
10364 if (iz > 0 && iz < 170)
10365 met->pt[ix][iy] = (float) p2[iz];
10366 break;
10367 }
10368 }
10369 }
10370
10371 else
10372 ERRMSG("Cannot calculate tropopause!");
10373
10374 /* Interpolate temperature, geopotential height, and water vapor... */
10375#pragma omp parallel for default(shared) collapse(2)
10376 for (int ix = 0; ix < met->nx; ix++)
10377 for (int iy = 0; iy < met->ny; iy++) {
10378 double h2ot, tt, zt;
10380 intpol_met_space_3d(met, met->t, met->pt[ix][iy], met->lon[ix],
10381 met->lat[iy], &tt, ci, cw, 1);
10382 intpol_met_space_3d(met, met->z, met->pt[ix][iy], met->lon[ix],
10383 met->lat[iy], &zt, ci, cw, 0);
10384 intpol_met_space_3d(met, met->h2o, met->pt[ix][iy], met->lon[ix],
10385 met->lat[iy], &h2ot, ci, cw, 0);
10386 met->tt[ix][iy] = (float) tt;
10387 met->zt[ix][iy] = (float) zt;
10388 met->h2ot[ix][iy] = (float) h2ot;
10389 }
10390}
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:10600
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
Definition: mptrac.h:1038
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 10394 of file mptrac.c.

10402 {
10403
10404 /* Write info... */
10405 LOG(1, "Read observation data: %s", filename);
10406
10407 /* Read data... */
10408 if (ctl->obs_type == 0)
10409 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
10410 else if (ctl->obs_type == 1)
10411 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
10412 else
10413 ERRMSG("Set OBS_TYPE to 0 or 1!");
10414
10415 /* Check time... */
10416 for (int i = 1; i < *nobs; i++)
10417 if (rt[i] < rt[i - 1])
10418 ERRMSG("Time must be ascending!");
10419
10420 /* Write info... */
10421 int n = *nobs;
10422 double mini, maxi;
10423 LOG(2, "Number of observations: %d", *nobs);
10424 gsl_stats_minmax(&mini, &maxi, rt, 1, (size_t) n);
10425 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
10426 gsl_stats_minmax(&mini, &maxi, rz, 1, (size_t) n);
10427 LOG(2, "Altitude range: %g ... %g km", mini, maxi);
10428 gsl_stats_minmax(&mini, &maxi, rlon, 1, (size_t) n);
10429 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
10430 gsl_stats_minmax(&mini, &maxi, rlat, 1, (size_t) n);
10431 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
10432 gsl_stats_minmax(&mini, &maxi, robs, 1, (size_t) n);
10433 LOG(2, "Observation range: %g ... %g", mini, maxi);
10434}
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:10438
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:10466
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 10438 of file mptrac.c.

10445 {
10446
10447 /* Open observation data file... */
10448 FILE *in;
10449 if (!(in = fopen(filename, "r")))
10450 ERRMSG("Cannot open file!");
10451
10452 /* Read observations... */
10453 char line[LEN];
10454 while (fgets(line, LEN, in))
10455 if (sscanf(line, "%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
10456 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
10457 if ((++(*nobs)) >= NOBS)
10458 ERRMSG("Too many observations!");
10459
10460 /* Close observation data file... */
10461 fclose(in);
10462}
#define NOBS
Maximum number of observation data points.
Definition: mptrac.h:339

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

10473 {
10474
10475 int ncid, varid;
10476
10477 /* Open netCDF file... */
10478 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
10479 ERRMSG("Cannot open file!");
10480
10481 /* Read the observations from the NetCDF file... */
10482 NC_INQ_DIM("nobs", nobs, 1, NOBS);
10483 NC_GET_DOUBLE("time", rt, 1);
10484 NC_GET_DOUBLE("alt", rz, 1);
10485 NC_GET_DOUBLE("lon", rlon, 1);
10486 NC_GET_DOUBLE("lat", rlat, 1);
10487 NC_GET_DOUBLE("obs", robs, 1);
10488
10489 /* Close file... */
10490 NC(nc_close(ncid));
10491}

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

10502 {
10503
10504 FILE *in = NULL;
10505
10506 char fullname1[LEN], fullname2[LEN], rval[LEN];
10507
10508 int contain = 0, i;
10509
10510 /* Open file... */
10511 if (filename[strlen(filename) - 1] != '-')
10512 if (!(in = fopen(filename, "r")))
10513 ERRMSG("Cannot open file!");
10514
10515 /* Set full variable name... */
10516 if (arridx >= 0) {
10517 sprintf(fullname1, "%s[%d]", varname, arridx);
10518 sprintf(fullname2, "%s[*]", varname);
10519 } else {
10520 sprintf(fullname1, "%s", varname);
10521 sprintf(fullname2, "%s", varname);
10522 }
10523
10524 /* Read data... */
10525 if (in != NULL) {
10526 char dummy[LEN], line[LEN], rvarname[LEN];
10527 while (fgets(line, LEN, in)) {
10528 if (sscanf(line, "%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
10529 if (strcasecmp(rvarname, fullname1) == 0 ||
10530 strcasecmp(rvarname, fullname2) == 0) {
10531 contain = 1;
10532 break;
10533 }
10534 }
10535 }
10536 for (i = 1; i < argc - 1; i++)
10537 if (strcasecmp(argv[i], fullname1) == 0 ||
10538 strcasecmp(argv[i], fullname2) == 0) {
10539 sprintf(rval, "%s", argv[i + 1]);
10540 contain = 1;
10541 break;
10542 }
10543
10544 /* Close file... */
10545 if (in != NULL)
10546 fclose(in);
10547
10548 /* Check for missing variables... */
10549 if (!contain) {
10550 if (strlen(defvalue) > 0)
10551 sprintf(rval, "%s", defvalue);
10552 else
10553 ERRMSG("Missing variable %s!\n", fullname1);
10554 }
10555
10556 /* Write info... */
10557 LOG(1, "%s = %s", fullname1, rval);
10558
10559 /* Return values... */
10560 if (value != NULL)
10561 sprintf(value, "%s", rval);
10562 return atof(rval);
10563}

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

10571 {
10572
10573 /* Convert particle radius from microns to m... */
10574 const double rp_help = rp * 1e-6;
10575
10576 /* Density of dry air [kg / m^3]... */
10577 const double rho = RHO(p, T);
10578
10579 /* Dynamic viscosity of air [kg / (m s)]... */
10580 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
10581
10582 /* Thermal velocity of an air molecule [m / s]... */
10583 const double v = sqrt(8. * KB * T / (M_PI * 4.8096e-26));
10584
10585 /* Mean free path of an air molecule [m]... */
10586 const double lambda = 2. * eta / (rho * v);
10587
10588 /* Knudsen number for air (dimensionless)... */
10589 const double K = lambda / rp_help;
10590
10591 /* Cunningham slip-flow correction (dimensionless)... */
10592 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
10593
10594 /* Sedimentation velocity [m / s]... */
10595 return 2. * SQR(rp_help) * (rhop - rho) * G0 / (9. * eta) * G;
10596}
#define KB
Boltzmann constant [kg m^2/(K s^2)].
Definition: mptrac.h:219

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

10607 {
10608
10609 /* Cubic spline interpolation... */
10610 if (method == 1) {
10611
10612 /* Allocate... */
10613 gsl_interp_accel *acc = gsl_interp_accel_alloc();
10614 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (size_t) n);
10615
10616 /* Interpolate profile... */
10617 gsl_spline_init(s, x, y, (size_t) n);
10618 for (int i = 0; i < n2; i++)
10619 if (x2[i] <= x[0])
10620 y2[i] = y[0];
10621 else if (x2[i] >= x[n - 1])
10622 y2[i] = y[n - 1];
10623 else
10624 y2[i] = gsl_spline_eval(s, x2[i], acc);
10625
10626 /* Free... */
10627 gsl_spline_free(s);
10628 gsl_interp_accel_free(acc);
10629 }
10630
10631 /* Linear interpolation... */
10632 else {
10633 for (int i = 0; i < n2; i++)
10634 if (x2[i] <= x[0])
10635 y2[i] = y[0];
10636 else if (x2[i] >= x[n - 1])
10637 y2[i] = y[n - 1];
10638 else {
10639 int idx = locate_irr(x, n, x2[i]);
10640 y2[i] = LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
10641 }
10642 }
10643}
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 10647 of file mptrac.c.

10649 {
10650
10651 if (n <= 0)
10652 return 0;
10653
10654 float mean = 0, var = 0;
10655
10656 for (int i = 0; i < n; ++i) {
10657 mean += data[i];
10658 var += SQR(data[i]);
10659 }
10660
10661 var = var / (float) n - SQR(mean / (float) n);
10662
10663 return (var > 0 ? sqrtf(var) : 0);
10664}

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

10671 {
10672
10673 /* Number of days and fraction with respect to 2000-01-01T12:00Z... */
10674 const double D = sec / 86400 - 0.5;
10675
10676 /* Geocentric apparent ecliptic longitude [rad]... */
10677 const double g = DEG2RAD(357.529 + 0.98560028 * D);
10678 const double q = 280.459 + 0.98564736 * D;
10679 const double L = DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
10680
10681 /* Mean obliquity of the ecliptic [rad]... */
10682 const double e = DEG2RAD(23.439 - 0.00000036 * D);
10683
10684 /* Declination [rad]... */
10685 const double sindec = sin(e) * sin(L);
10686
10687 /* Right ascension [rad]... */
10688 const double ra = atan2(cos(e) * sin(L), cos(L));
10689
10690 /* Greenwich Mean Sidereal Time [h]... */
10691 const double GMST = 18.697374558 + 24.06570982441908 * D;
10692
10693 /* Local Sidereal Time [h]... */
10694 const double LST = GMST + lon / 15;
10695
10696 /* Hour angle [rad]... */
10697 const double h = LST / 12 * M_PI - ra;
10698
10699 /* Convert latitude... */
10700 const double lat_help = DEG2RAD(lat);
10701
10702 /* Return solar zenith angle [rad]... */
10703 return acos(sin(lat_help) * sindec +
10704 cos(lat_help) * sqrt(1 - SQR(sindec)) * cos(h));
10705}

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

10717 {
10718
10719 struct tm t0, t1;
10720
10721 t0.tm_year = 100;
10722 t0.tm_mon = 0;
10723 t0.tm_mday = 1;
10724 t0.tm_hour = 0;
10725 t0.tm_min = 0;
10726 t0.tm_sec = 0;
10727
10728 t1.tm_year = year - 1900;
10729 t1.tm_mon = mon - 1;
10730 t1.tm_mday = day;
10731 t1.tm_hour = hour;
10732 t1.tm_min = min;
10733 t1.tm_sec = sec;
10734
10735 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
10736}

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

10743 {
10744
10745 static char names[NTIMER][100], groups[NTIMER][100];
10746
10747 static double rt_name[NTIMER], rt_group[NTIMER],
10748 rt_min[NTIMER], rt_max[NTIMER], dt, t0, t1;
10749
10750 static int iname = -1, igroup = -1, nname, ngroup, ct_name[NTIMER];
10751
10752 /* Get time... */
10753 t1 = omp_get_wtime();
10754 dt = t1 - t0;
10755
10756 /* Add elapsed time to current timers... */
10757 if (iname >= 0) {
10758 rt_name[iname] += dt;
10759 rt_min[iname] = (ct_name[iname] <= 0 ? dt : MIN(rt_min[iname], dt));
10760 rt_max[iname] = (ct_name[iname] <= 0 ? dt : MAX(rt_max[iname], dt));
10761 ct_name[iname]++;
10762 }
10763 if (igroup >= 0)
10764 rt_group[igroup] += t1 - t0;
10765
10766 /* Report timers... */
10767 if (output) {
10768 for (int i = 0; i < nname; i++)
10769 LOG(1, "TIMER_%s = %.3f s (min= %g s, mean= %g s,"
10770 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
10771 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
10772 for (int i = 0; i < ngroup; i++)
10773 LOG(1, "TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
10774 double total = 0.0;
10775 for (int i = 0; i < nname; i++)
10776 total += rt_name[i];
10777 LOG(1, "TIMER_TOTAL = %.3f s", total);
10778 }
10779
10780 /* Identify IDs of next timer... */
10781 for (iname = 0; iname < nname; iname++)
10782 if (strcasecmp(name, names[iname]) == 0)
10783 break;
10784 for (igroup = 0; igroup < ngroup; igroup++)
10785 if (strcasecmp(group, groups[igroup]) == 0)
10786 break;
10787
10788 /* Check whether this is a new timer... */
10789 if (iname >= nname) {
10790 sprintf(names[iname], "%s", name);
10791 if ((++nname) >= NTIMER)
10792 ERRMSG("Too many timers!");
10793 }
10794
10795 /* Check whether this is a new group... */
10796 if (igroup >= ngroup) {
10797 sprintf(groups[igroup], "%s", group);
10798 if ((++ngroup) >= NTIMER)
10799 ERRMSG("Too many groups!");
10800 }
10801
10802 /* Save starting time... */
10803 t0 = t1;
10804}
#define NTIMER
Maximum number of timers.
Definition: mptrac.h:2146

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

10810 {
10811
10812 char tstr[10];
10813
10814 double t;
10815
10816 /* Get time from filename... */
10817 int len = (int) strlen(filename);
10818 sprintf(tstr, "%.4s", &filename[len - offset]);
10819 int year = atoi(tstr);
10820 sprintf(tstr, "%.2s", &filename[len - offset + 5]);
10821 int mon = atoi(tstr);
10822 sprintf(tstr, "%.2s", &filename[len - offset + 8]);
10823 int day = atoi(tstr);
10824 sprintf(tstr, "%.2s", &filename[len - offset + 11]);
10825 int hour = atoi(tstr);
10826 sprintf(tstr, "%.2s", &filename[len - offset + 14]);
10827 int min = atoi(tstr);
10828
10829 /* Check time... */
10830 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
10831 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
10832 ERRMSG("Cannot read time from filename!");
10833
10834 /* Convert time to Julian seconds... */
10835 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
10836
10837 /* Return time... */
10838 return t;
10839}
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 10843 of file mptrac.c.

10846 {
10847
10848 /* Get tropopause pressure... */
10849 const double pt = clim_tropo(clim, atm->time[ip], atm->lat[ip]);
10850
10851 /* Get pressure range... */
10852 const double p1 = pt * 0.866877899;
10853 const double p0 = pt / 0.866877899;
10854
10855 /* Get weighting factor... */
10856 if (atm->p[ip] > p0)
10857 return 1;
10858 else if (atm->p[ip] < p1)
10859 return 0;
10860 else
10861 return LIN(p0, 1.0, p1, 0.0, atm->p[ip]);
10862}
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 10866 of file mptrac.c.

10870 {
10871
10872 FILE *out;
10873
10874 /* Set time interval for output... */
10875 const double t0 = t - 0.5 * ctl->dt_mod;
10876 const double t1 = t + 0.5 * ctl->dt_mod;
10877
10878 /* Check if gnuplot output is requested... */
10879 if (ctl->atm_gpfile[0] != '-') {
10880
10881 /* Create gnuplot pipe... */
10882 if (!(out = popen("gnuplot", "w")))
10883 ERRMSG("Cannot create pipe to gnuplot!");
10884
10885 /* Set plot filename... */
10886 fprintf(out, "set out \"%s.png\"\n", filename);
10887
10888 /* Set time string... */
10889 double r;
10890 int year, mon, day, hour, min, sec;
10891 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
10892 fprintf(out, "timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
10893 year, mon, day, hour, min);
10894
10895 /* Dump gnuplot file to pipe... */
10896 FILE *in;
10897 if (!(in = fopen(ctl->atm_gpfile, "r")))
10898 ERRMSG("Cannot open file!");
10899 char line[LEN];
10900 while (fgets(line, LEN, in))
10901 fprintf(out, "%s", line);
10902 fclose(in);
10903 }
10904
10905 else {
10906
10907 /* Create file... */
10908 if (!(out = fopen(filename, "w")))
10909 ERRMSG("Cannot create file!");
10910 }
10911
10912 /* Write header... */
10913 fprintf(out,
10914 "# $1 = time [s]\n"
10915 "# $2 = altitude [km]\n"
10916 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
10917 for (int iq = 0; iq < ctl->nq; iq++)
10918 fprintf(out, "# $%i = %s [%s]\n", iq + 5, ctl->qnt_name[iq],
10919 ctl->qnt_unit[iq]);
10920 fprintf(out, "\n");
10921
10922 /* Write data... */
10923 for (int ip = 0; ip < atm->np; ip += ctl->atm_stride) {
10924
10925 /* Check time... */
10926 if (ctl->atm_filter == 2 && (atm->time[ip] < t0 || atm->time[ip] > t1))
10927 continue;
10928
10929 /* Write output... */
10930 fprintf(out, "%.2f %g %g %g", atm->time[ip], Z(atm->p[ip]),
10931 atm->lon[ip], atm->lat[ip]);
10932 for (int iq = 0; iq < ctl->nq; iq++) {
10933 fprintf(out, " ");
10934 if (ctl->atm_filter == 1 && (atm->time[ip] < t0 || atm->time[ip] > t1))
10935 fprintf(out, ctl->qnt_format[iq], NAN);
10936 else
10937 fprintf(out, ctl->qnt_format[iq], atm->q[iq][ip]);
10938 }
10939 fprintf(out, "\n");
10940 }
10941
10942 /* Close file... */
10943 fclose(out);
10944}
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 10948 of file mptrac.c.

10951 {
10952
10953 FILE *out;
10954
10955 /* Create file... */
10956 if (!(out = fopen(filename, "w")))
10957 ERRMSG("Cannot create file!");
10958
10959 /* Write version of binary data... */
10960 int version = 100;
10961 FWRITE(&version, int,
10962 1,
10963 out);
10964
10965 /* Write data... */
10966 FWRITE(&atm->np, int,
10967 1,
10968 out);
10969 FWRITE(atm->time, double,
10970 (size_t) atm->np,
10971 out);
10972 FWRITE(atm->p, double,
10973 (size_t) atm->np,
10974 out);
10975 FWRITE(atm->lon, double,
10976 (size_t) atm->np,
10977 out);
10978 FWRITE(atm->lat, double,
10979 (size_t) atm->np,
10980 out);
10981 for (int iq = 0; iq < ctl->nq; iq++)
10982 FWRITE(atm->q[iq], double,
10983 (size_t) atm->np,
10984 out);
10985
10986 /* Write final flag... */
10987 int final = 999;
10988 FWRITE(&final, int,
10989 1,
10990 out);
10991
10992 /* Close file... */
10993 fclose(out);
10994}

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

11001 {
11002
11003 int tid, pid, ncid, varid;
11004 size_t start[2], count[2];
11005
11006 /* Create file... */
11007 nc_create(filename, NC_NETCDF4, &ncid);
11008
11009 /* Define dimensions... */
11010 NC(nc_def_dim(ncid, "time", 1, &tid));
11011 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
11012
11013 /* Define variables and their attributes... */
11014 int dim_ids[2] = { tid, pid };
11015 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
11016 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
11017 NC_DEF_VAR("LAT", NC_DOUBLE, 1, &pid, "Latitude", "deg",
11018 ctl->atm_nc_level, 0);
11019 NC_DEF_VAR("LON", NC_DOUBLE, 1, &pid, "Longitude", "deg",
11020 ctl->atm_nc_level, 0);
11021 NC_DEF_VAR("PRESS", NC_DOUBLE, 1, &pid, "Pressure", "hPa",
11022 ctl->atm_nc_level, 0);
11023 NC_DEF_VAR("ZETA", NC_DOUBLE, 1, &pid, "Zeta", "K", ctl->atm_nc_level, 0);
11024 for (int iq = 0; iq < ctl->nq; iq++)
11025 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
11026 ctl->qnt_name[iq], ctl->qnt_unit[iq],
11027 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
11028
11029 /* Define global attributes... */
11030 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
11031 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
11032
11033 /* End definitions... */
11034 NC(nc_enddef(ncid));
11035
11036 /* Write data... */
11037 NC_PUT_DOUBLE("time", atm->time, 0);
11038 NC_PUT_DOUBLE("LAT", atm->lat, 0);
11039 NC_PUT_DOUBLE("LON", atm->lon, 0);
11040 NC_PUT_DOUBLE("PRESS", atm->p, 0);
11041 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 0);
11042 for (int iq = 0; iq < ctl->nq; iq++)
11043 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
11044
11045 /* Close file... */
11046 NC(nc_close(ncid));
11047}
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
Definition: mptrac.h:1410
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units, level, quant)
Define a NetCDF variable with attributes.
Definition: mptrac.h:1243
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
Write double precision data to a NetCDF variable.
Definition: mptrac.h:1324

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

11055 {
11056
11057 /* Global Counter... */
11058 static size_t out_cnt = 0;
11059
11060 double r, r_start, r_stop;
11061 int year, mon, day, hour, min, sec;
11062 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
11063 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
11064 char filename_out[2 * LEN] = "traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
11065
11066 int ncid, varid, tid, pid, cid;
11067 int dim_ids[2];
11068
11069 /* time, nparc */
11070 size_t start[2];
11071 size_t count[2];
11072
11073 /* Determine start and stop times of calculation... */
11074 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11075 jsec2time(ctl->t_start, &year_start, &mon_start, &day_start, &hour_start,
11076 &min_start, &sec_start, &r_start);
11077 jsec2time(ctl->t_stop, &year_stop, &mon_stop, &day_stop, &hour_stop,
11078 &min_stop, &sec_stop, &r_stop);
11079
11080 sprintf(filename_out,
11081 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
11082 year_start % 100, mon_start, day_start, hour_start,
11083 year_stop % 100, mon_stop, day_stop, hour_stop);
11084 LOG(1, "Write traj file: %s", filename_out);
11085
11086 /* Define hyperslap for the traj_file... */
11087 start[0] = out_cnt;
11088 start[1] = 0;
11089 count[0] = 1;
11090 count[1] = (size_t) atm->np;
11091
11092 /* Create the file at the first timestep... */
11093 if (out_cnt == 0) {
11094
11095 /* Create file... */
11096 nc_create(filename_out, NC_NETCDF4, &ncid);
11097
11098 /* Define dimensions... */
11099 NC(nc_def_dim(ncid, "time", NC_UNLIMITED, &tid));
11100 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
11101 NC(nc_def_dim(ncid, "TMDT", 7, &cid));
11102 dim_ids[0] = tid;
11103 dim_ids[1] = pid;
11104
11105 /* Define variables and their attributes... */
11106 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
11107 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
11108 NC_DEF_VAR("LAT", NC_DOUBLE, 2, dim_ids, "Latitude", "deg",
11109 ctl->atm_nc_level, 0);
11110 NC_DEF_VAR("LON", NC_DOUBLE, 2, dim_ids, "Longitude", "deg",
11111 ctl->atm_nc_level, 0);
11112 NC_DEF_VAR("PRESS", NC_DOUBLE, 2, dim_ids, "Pressure", "hPa",
11113 ctl->atm_nc_level, 0);
11114 NC_DEF_VAR("ZETA", NC_DOUBLE, 2, dim_ids, "Zeta", "K",
11115 ctl->atm_nc_level, 0);
11116 for (int iq = 0; iq < ctl->nq; iq++)
11117 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
11118 ctl->qnt_name[iq], ctl->qnt_unit[iq],
11119 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
11120
11121 /* Define global attributes... */
11122 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
11123 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
11124
11125 /* End definitions... */
11126 NC(nc_enddef(ncid));
11127 NC(nc_close(ncid));
11128 }
11129
11130 /* Increment global counter to change hyperslap... */
11131 out_cnt++;
11132
11133 /* Open file... */
11134 NC(nc_open(filename_out, NC_WRITE, &ncid));
11135
11136 /* Write data... */
11137 NC_PUT_DOUBLE("time", atm->time, 1);
11138 NC_PUT_DOUBLE("LAT", atm->lat, 1);
11139 NC_PUT_DOUBLE("LON", atm->lon, 1);
11140 NC_PUT_DOUBLE("PRESS", atm->p, 1);
11141 if (ctl->advect_vert_coord == 1) {
11142 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta], 1);
11143 } else if (ctl->qnt_zeta >= 0) {
11144 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 1);
11145 }
11146 for (int iq = 0; iq < ctl->nq; iq++)
11147 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 1);
11148
11149 /* Close file... */
11150 NC(nc_close(ncid));
11151
11152 /* At the last time step create the init_fix_YYYYMMDDHH file... */
11153 if ((year == year_stop) && (mon == mon_stop)
11154 && (day == day_stop) && (hour == hour_stop)) {
11155
11156 /* Set filename... */
11157 char filename_init[2 * LEN] = "./init_fix_YYYYMMDDHH.nc";
11158 sprintf(filename_init, "%s/init_fix_%02d%02d%02d%02d.nc",
11159 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
11160 LOG(1, "Write init file: %s", filename_init);
11161
11162 /* Create file... */
11163 nc_create(filename_init, NC_NETCDF4, &ncid);
11164
11165 /* Define dimensions... */
11166 NC(nc_def_dim(ncid, "time", 1, &tid));
11167 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
11168 dim_ids[0] = tid;
11169 dim_ids[1] = pid;
11170
11171 /* Define variables and their attributes... */
11172 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
11173 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
11174 NC_DEF_VAR("LAT", NC_DOUBLE, 1, &pid, "Latitude", "deg",
11175 ctl->atm_nc_level, 0);
11176 NC_DEF_VAR("LON", NC_DOUBLE, 1, &pid, "Longitude", "deg",
11177 ctl->atm_nc_level, 0);
11178 NC_DEF_VAR("PRESS", NC_DOUBLE, 1, &pid, "Pressure", "hPa",
11179 ctl->atm_nc_level, 0);
11180 NC_DEF_VAR("ZETA", NC_DOUBLE, 1, &pid, "Zeta", "K", ctl->atm_nc_level, 0);
11181 for (int iq = 0; iq < ctl->nq; iq++)
11182 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
11183 ctl->qnt_name[iq], ctl->qnt_unit[iq],
11184 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
11185
11186 /* Define global attributes... */
11187 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
11188 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
11189
11190 /* End definitions... */
11191 NC(nc_enddef(ncid));
11192
11193 /* Write data... */
11194 NC_PUT_DOUBLE("time", atm->time, 0);
11195 NC_PUT_DOUBLE("LAT", atm->lat, 0);
11196 NC_PUT_DOUBLE("LON", atm->lon, 0);
11197 NC_PUT_DOUBLE("PRESS", atm->p, 0);
11198 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 0);
11199 for (int iq = 0; iq < ctl->nq; iq++)
11200 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
11201
11202 /* Close file... */
11203 NC(nc_close(ncid));
11204 }
11205}
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 11209 of file mptrac.c.

11212 {
11213
11214 int ncid, obsid, varid;
11215
11216 size_t start[2], count[2];
11217
11218 /* Create file... */
11219 NC(nc_create(filename, NC_NETCDF4, &ncid));
11220
11221 /* Define dimensions... */
11222 NC(nc_def_dim(ncid, "obs", (size_t) atm->np, &obsid));
11223
11224 /* Define variables and their attributes... */
11225 NC_DEF_VAR("time", NC_DOUBLE, 1, &obsid, "time",
11226 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
11227 NC_DEF_VAR("press", NC_DOUBLE, 1, &obsid, "pressure", "hPa",
11228 ctl->atm_nc_level, 0);
11229 NC_DEF_VAR("lon", NC_DOUBLE, 1, &obsid, "longitude", "degrees_east",
11230 ctl->atm_nc_level, 0);
11231 NC_DEF_VAR("lat", NC_DOUBLE, 1, &obsid, "latitude", "degrees_north",
11232 ctl->atm_nc_level, 0);
11233 for (int iq = 0; iq < ctl->nq; iq++)
11234 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 1, &obsid,
11235 ctl->qnt_longname[iq], ctl->qnt_unit[iq],
11236 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
11237
11238 /* Define global attributes... */
11239 NC_PUT_ATT_GLOBAL("featureType", "point");
11240
11241 /* End definitions... */
11242 NC(nc_enddef(ncid));
11243
11244 /* Write data... */
11245 NC_PUT_DOUBLE("time", atm->time, 0);
11246 NC_PUT_DOUBLE("press", atm->p, 0);
11247 NC_PUT_DOUBLE("lon", atm->lon, 0);
11248 NC_PUT_DOUBLE("lat", atm->lat, 0);
11249 for (int iq = 0; iq < ctl->nq; iq++)
11250 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
11251
11252 /* Close file... */
11253 NC(nc_close(ncid));
11254}

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

11262 {
11263
11264 static FILE *out;
11265
11266 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
11267 *area, dlon, dlat, dz, x[NCSI], y[NCSI], obsstdn[NCSI], kz[EP], kw[EP];
11268
11269 static int *obscount, nobs, nk;
11270
11271 static int ct[NENS], cx[NENS], cy[NENS], cz[NENS], n[NENS];
11272
11273 const int ensemble = (ctl->nens > 0);
11274
11275 /* Set timer */
11276 SELECT_TIMER("WRITE_CSI", "OUTPUT", NVTX_WRITE);
11277
11278 /* Check quantities... */
11279 if (ctl->qnt_m < 0)
11280 ERRMSG("Need quantity mass!");
11281 if (ensemble) {
11282 if (ctl->qnt_ens < 0)
11283 ERRMSG("Missing ensemble IDs!");
11284 if (ctl->nens > NENS)
11285 ERRMSG("Too many ensembles!");
11286 }
11287
11288 /* Init... */
11289 if (t == ctl->t_start) {
11290
11291 /* Allocate.. */
11292 ALLOC(area, double,
11293 ctl->csi_ny);
11294 ALLOC(rt, double,
11295 NOBS);
11296 ALLOC(rz, double,
11297 NOBS);
11298 ALLOC(rlon, double,
11299 NOBS);
11300 ALLOC(rlat, double,
11301 NOBS);
11302 ALLOC(robs, double,
11303 NOBS);
11304
11305 /* Read observation data... */
11306 read_obs(ctl->csi_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
11307
11308 /* Read kernel data... */
11309 if (ctl->csi_kernel[0] != '-')
11310 read_kernel(ctl->csi_kernel, kz, kw, &nk);
11311
11312 /* Create new file... */
11313 LOG(1, "Write CSI%s data: %s", ensemble ? " ensemble" : "", filename);
11314 if (!(out = fopen(filename, "w")))
11315 ERRMSG("Cannot create file!");
11316
11317 /* Write header... */
11318 fprintf(out,
11319 "# $1 = time [s]\n"
11320 "# $2 = ensemble ID\n"
11321 "# $3 = number of hits (cx)\n"
11322 "# $4 = number of misses (cy)\n"
11323 "# $5 = number of false alarms (cz)\n"
11324 "# $6 = number of observations (cx + cy)\n"
11325 "# $7 = number of forecasts (cx + cz)\n"
11326 "# $8 = bias (%%)\n"
11327 "# $9 = POD (%%)\n"
11328 "# $10 = FAR (%%)\n"
11329 "# $11 = CSI (%%)\n"
11330 "# $12 = hits by random chance\n"
11331 "# $13 = ETS (%%)\n"
11332 "# $14 = Pearson R\n"
11333 "# $15 = Spearman R\n"
11334 "# $16 = mean error [kg/m²]\n"
11335 "# $17 = RMSE [kg/m²]\n"
11336 "# $18 = MAE [kg/m²]\n"
11337 "# $19 = log-likelihood\n" "# $20 = number of points\n\n");
11338
11339 /* Set grid box size... */
11340 dz = (ctl->csi_z1 - ctl->csi_z0) / ctl->csi_nz;
11341 dlon = (ctl->csi_lon1 - ctl->csi_lon0) / ctl->csi_nx;
11342 dlat = (ctl->csi_lat1 - ctl->csi_lat0) / ctl->csi_ny;
11343
11344 /* Set horizontal coordinates... */
11345 for (int iy = 0; iy < ctl->csi_ny; iy++) {
11346 double lat = ctl->csi_lat0 + dlat * (iy + 0.5);
11347 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.0) * cos(DEG2RAD(lat));
11348 }
11349 }
11350
11351 /* Set time interval... */
11352 double t0 = t - 0.5 * ctl->dt_mod;
11353 double t1 = t + 0.5 * ctl->dt_mod;
11354
11355 /* Allocate... */
11356 int grid_size = ctl->csi_nx * ctl->csi_ny * ctl->csi_nz;
11357 ALLOC(modmean, double,
11358 (ensemble ? ctl->nens : 1) * grid_size);
11359 ALLOC(obsmean, double,
11360 grid_size);
11361 ALLOC(obscount, int,
11362 grid_size);
11363 ALLOC(obsstd, double,
11364 grid_size);
11365
11366 /* Init... */
11367 for (int i = 0; i < (ensemble ? ctl->nens : 1); i++)
11368 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
11369
11370 /* Loop over observations... */
11371 for (int i = 0; i < nobs; i++) {
11372 if (rt[i] < t0 || rt[i] >= t1 || !isfinite(robs[i]))
11373 continue;
11374
11375 /* Calculate indices... */
11376 int ix = (int) ((rlon[i] - ctl->csi_lon0) / dlon);
11377 int iy = (int) ((rlat[i] - ctl->csi_lat0) / dlat);
11378 int iz = (int) ((rz[i] - ctl->csi_z0) / dz);
11379 if (ix < 0 || ix >= ctl->csi_nx || iy < 0 || iy >= ctl->csi_ny || iz < 0
11380 || iz >= ctl->csi_nz)
11381 continue;
11382
11383 /* Get mean observation index... */
11384 const int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
11385 obsmean[idx] += robs[i];
11386 obsstd[idx] += SQR(robs[i]);
11387 obscount[idx]++;
11388 }
11389
11390 /* Analyze model data... */
11391 for (int ip = 0; ip < atm->np; ip++) {
11392
11393 /* Check time... */
11394 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11395 continue;
11396
11397 /* Get ensemble ID... */
11398 int ens_id = ensemble ? (int) atm->q[ctl->qnt_ens][ip] : 0;
11399 if (ens_id < 0 || ens_id >= (ensemble ? ctl->nens : 1))
11400 ERRMSG("Ensemble ID out of range!");
11401
11402 /* Get indices... */
11403 int ix = (int) ((atm->lon[ip] - ctl->csi_lon0) / dlon);
11404 int iy = (int) ((atm->lat[ip] - ctl->csi_lat0) / dlat);
11405 int iz = (int) ((Z(atm->p[ip]) - ctl->csi_z0) / dz);
11406 if (ix < 0 || ix >= ctl->csi_nx || iy < 0 || iy >= ctl->csi_ny || iz < 0
11407 || iz >= ctl->csi_nz)
11408 continue;
11409
11410 /* Get total mass in grid cell... */
11411 int idx =
11412 ens_id * grid_size + ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
11413 modmean[idx] +=
11414 kernel_weight(kz, kw, nk, atm->p[ip]) * atm->q[ctl->qnt_m][ip];
11415 }
11416
11417 /* Analyze all grid cells... */
11418 for (int ix = 0; ix < ctl->csi_nx; ix++)
11419 for (int iy = 0; iy < ctl->csi_ny; iy++)
11420 for (int iz = 0; iz < ctl->csi_nz; iz++) {
11421
11422 /* Calculate mean observation index... */
11423 int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
11424 if (obscount[idx]) {
11425 obsmean[idx] /= obscount[idx];
11426 obsstd[idx] = sqrt(obsstd[idx] - SQR(obsmean[idx]));
11427 }
11428
11429 /* Calculate model mean per ensemble... */
11430 for (int e = 0; e < (ensemble ? ctl->nens : 1); e++) {
11431 int midx = e * grid_size + idx;
11432 if (modmean[midx] > 0)
11433 modmean[midx] /= (1e6 * area[iy]);
11434 }
11435
11436 /* Check number of observations... */
11437 if (obscount[idx]) {
11438
11439 /* Calculate CSI... */
11440 for (int e = 0; e < (ensemble ? ctl->nens : 1); e++) {
11441 int midx = e * grid_size + idx;
11442 ct[e]++;
11443 if (obsmean[idx] >= ctl->csi_obsmin
11444 && modmean[midx] >= ctl->csi_modmin)
11445 cx[e]++;
11446 else if (obsmean[idx] >= ctl->csi_obsmin)
11447 cy[e]++;
11448 else if (modmean[midx] >= ctl->csi_modmin)
11449 cz[e]++;
11450
11451 /* Save data for other verification statistics... */
11452 if (obsmean[idx] >= ctl->csi_obsmin
11453 || modmean[midx] >= ctl->csi_modmin) {
11454 x[n[e]] = modmean[midx];
11455 y[n[e]] = obsmean[idx];
11456 if (modmean[midx] >= ctl->csi_modmin)
11457 obsstdn[n[e]] = obsstd[idx];
11458 if ((++n[e]) >= NCSI)
11459 ERRMSG("Too many points for statistics!");
11460 }
11461 }
11462 }
11463 }
11464
11465 /* Write output... */
11466 if (fmod(t, ctl->csi_dt_out) == 0) {
11467 for (int e = 0; e < (ensemble ? ctl->nens : 1); e++) {
11468
11469 if (n[e] == 0)
11470 continue;
11471
11472 /* Calculate verification statistics
11473 (https://www.cawcr.gov.au/projects/verification/) ... */
11474 static double work[2 * NCSI], work2[2 * NCSI];
11475 int n_obs = cx[e] + cy[e];
11476 int n_for = cx[e] + cz[e];
11477 double cx_rd = (ct[e] > 0) ? (1. * n_obs * n_for) / ct[e] : NAN;
11478 double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
11479 double pod = (n_obs > 0) ? 100. * cx[e] / n_obs : NAN;
11480 double far = (n_for > 0) ? 100. * cz[e] / n_for : NAN;
11481 double csi =
11482 (cx[e] + cy[e] + cz[e] >
11483 0) ? 100. * cx[e] / (cx[e] + cy[e] + cz[e]) : NAN;
11484 double ets =
11485 (cx[e] + cy[e] + cz[e] - cx_rd >
11486 0) ? 100. * (cx[e] - cx_rd) / (cx[e] + cy[e] + cz[e] - cx_rd) : NAN;
11487 double rho_p = gsl_stats_correlation(x, 1, y, 1, (size_t) n[e]);
11488 double rho_s = gsl_stats_spearman(x, 1, y, 1, (size_t) n[e], work);
11489 for (int i = 0; i < n[e]; i++) {
11490 work[i] = x[i] - y[i];
11491 work2[i] = (obsstdn[i] != 0) ? work[i] / obsstdn[i] : 0;
11492 }
11493 double mean = gsl_stats_mean(work, 1, (size_t) n[e]);
11494 double rmse = gsl_stats_sd_with_fixed_mean(work, 1, (size_t) n[e], 0.0);
11495 double absdev = gsl_stats_absdev_m(work, 1, (size_t) n[e], 0.0);
11496 double loglikelihood = gsl_stats_tss(work2, 1, (size_t) n[e]) * -0.5;
11497
11498 /* Write... */
11499 fprintf(out,
11500 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
11501 t, ensemble ? e : -999, cx[e], cy[e], cz[e], n_obs, n_for, bias,
11502 pod, far, csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
11503 loglikelihood, n[e]);
11504
11505 /* Set counters to zero... */
11506 ct[e] = cx[e] = cy[e] = cz[e] = n[e] = 0;
11507 }
11508 }
11509
11510 /* Free... */
11511 free(modmean);
11512 free(obsmean);
11513 free(obscount);
11514 free(obsstd);
11515
11516 /* Finalize... */
11517 if (t == ctl->t_stop) {
11518
11519 /* Close output file... */
11520 fclose(out);
11521
11522 /* Free... */
11523 free(area);
11524 free(rt);
11525 free(rz);
11526 free(rlon);
11527 free(rlat);
11528 free(robs);
11529 }
11530}
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:10394
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:6528
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:1737
#define NENS
Maximum number of data points for ensemble analysis.
Definition: mptrac.h:334
#define NCSI
Maximum number of data points for CSI calculation.
Definition: mptrac.h:329
Here is the call graph for this function:

◆ write_csi_ens()

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

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

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

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

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

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

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

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

11538 {
11539
11540 static FILE *out;
11541
11542 static double dummy, lat, lon, qm[NQ][NENS], qs[NQ][NENS], xm[NENS][3],
11543 x[3], zm[NENS];
11544
11545 static int n[NENS];
11546
11547 /* Set timer... */
11548 SELECT_TIMER("WRITE_ENS", "OUTPUT", NVTX_WRITE);
11549
11550 /* Check quantities... */
11551 if (ctl->qnt_ens < 0)
11552 ERRMSG("Missing ensemble IDs!");
11553
11554 /* Set time interval... */
11555 const double t0 = t - 0.5 * ctl->dt_mod;
11556 const double t1 = t + 0.5 * ctl->dt_mod;
11557
11558 /* Init... */
11559 for (int i = 0; i < NENS; i++) {
11560 for (int iq = 0; iq < ctl->nq; iq++)
11561 qm[iq][i] = qs[iq][i] = 0;
11562 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
11563 n[i] = 0;
11564 }
11565
11566 /* Loop over air parcels... */
11567 for (int ip = 0; ip < atm->np; ip++) {
11568
11569 /* Check time... */
11570 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11571 continue;
11572
11573 /* Check ensemble ID... */
11574 if (atm->q[ctl->qnt_ens][ip] < 0 || atm->q[ctl->qnt_ens][ip] >= NENS)
11575 ERRMSG("Ensemble ID is out of range!");
11576
11577 /* Get means... */
11578 geo2cart(0, atm->lon[ip], atm->lat[ip], x);
11579 for (int iq = 0; iq < ctl->nq; iq++) {
11580 qm[iq][ctl->qnt_ens] += atm->q[iq][ip];
11581 qs[iq][ctl->qnt_ens] += SQR(atm->q[iq][ip]);
11582 }
11583 xm[ctl->qnt_ens][0] += x[0];
11584 xm[ctl->qnt_ens][1] += x[1];
11585 xm[ctl->qnt_ens][2] += x[2];
11586 zm[ctl->qnt_ens] += Z(atm->p[ip]);
11587 n[ctl->qnt_ens]++;
11588 }
11589
11590 /* Create file... */
11591 LOG(1, "Write ensemble data: %s", filename);
11592 if (!(out = fopen(filename, "w")))
11593 ERRMSG("Cannot create file!");
11594
11595 /* Write header... */
11596 fprintf(out,
11597 "# $1 = time [s]\n"
11598 "# $2 = altitude [km]\n"
11599 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11600 for (int iq = 0; iq < ctl->nq; iq++)
11601 fprintf(out, "# $%d = %s (mean) [%s]\n", 5 + iq,
11602 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
11603 for (int iq = 0; iq < ctl->nq; iq++)
11604 fprintf(out, "# $%d = %s (sigma) [%s]\n", 5 + ctl->nq + iq,
11605 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
11606 fprintf(out, "# $%d = number of members\n\n", 5 + 2 * ctl->nq);
11607
11608 /* Write data... */
11609 for (int i = 0; i < NENS; i++)
11610 if (n[i] > 0) {
11611 cart2geo(xm[i], &dummy, &lon, &lat);
11612 fprintf(out, "%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
11613 for (int iq = 0; iq < ctl->nq; iq++) {
11614 fprintf(out, " ");
11615 fprintf(out, ctl->qnt_format[iq], qm[iq][i] / n[i]);
11616 }
11617 for (int iq = 0; iq < ctl->nq; iq++) {
11618 fprintf(out, " ");
11619 double var = qs[iq][i] / n[i] - SQR(qm[iq][i] / n[i]);
11620 fprintf(out, ctl->qnt_format[iq], (var > 0 ? sqrt(var) : 0));
11621 }
11622 fprintf(out, " %d\n", n[i]);
11623 }
11624
11625 /* Close file... */
11626 fclose(out);
11627}
void cart2geo(const double *x, double *z, double *lon, double *lat)
State variables of cuRAND random number generator.
Definition: mptrac.c:74
Here is the call graph for this function:

◆ write_grid()

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

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

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

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

The function performs the following steps:

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

Definition at line 11631 of file mptrac.c.

11637 {
11638
11639 static double kz[EP], kw[EP];
11640
11641 static int nk;
11642
11643 double *cd, *mean[NQ], *sigma[NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
11644
11645 int *ixs, *iys, *izs, *np;
11646
11647 /* Set timer... */
11648 SELECT_TIMER("WRITE_GRID", "OUTPUT", NVTX_WRITE);
11649
11650 /* Write info... */
11651 LOG(1, "Write grid data: %s", filename);
11652
11653 /* Init... */
11654 if (t == ctl->t_start) {
11655
11656 /* Read kernel data... */
11657 if (ctl->grid_kernel[0] != '-')
11658 read_kernel(ctl->grid_kernel, kz, kw, &nk);
11659 }
11660
11661 /* Allocate... */
11662 ALLOC(cd, double,
11663 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
11664 for (int iq = 0; iq < ctl->nq; iq++) {
11665 ALLOC(mean[iq], double,
11666 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
11667 ALLOC(sigma[iq], double,
11668 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
11669 }
11670 ALLOC(vmr_impl, double,
11671 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
11672 ALLOC(z, double,
11673 ctl->grid_nz);
11674 ALLOC(lon, double,
11675 ctl->grid_nx);
11676 ALLOC(lat, double,
11677 ctl->grid_ny);
11678 ALLOC(area, double,
11679 ctl->grid_ny);
11680 ALLOC(press, double,
11681 ctl->grid_nz);
11682 ALLOC(np, int,
11683 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
11684 ALLOC(ixs, int,
11685 atm->np);
11686 ALLOC(iys, int,
11687 atm->np);
11688 ALLOC(izs, int,
11689 atm->np);
11690
11691 /* Set grid box size... */
11692 const double dz = (ctl->grid_z1 - ctl->grid_z0) / ctl->grid_nz;
11693 const double dlon = (ctl->grid_lon1 - ctl->grid_lon0) / ctl->grid_nx;
11694 const double dlat = (ctl->grid_lat1 - ctl->grid_lat0) / ctl->grid_ny;
11695
11696 /* Set vertical coordinates... */
11697#pragma omp parallel for default(shared)
11698 for (int iz = 0; iz < ctl->grid_nz; iz++) {
11699 z[iz] = ctl->grid_z0 + dz * (iz + 0.5);
11700 press[iz] = P(z[iz]);
11701 }
11702
11703 /* Set horizontal coordinates... */
11704 for (int ix = 0; ix < ctl->grid_nx; ix++)
11705 lon[ix] = ctl->grid_lon0 + dlon * (ix + 0.5);
11706#pragma omp parallel for default(shared)
11707 for (int iy = 0; iy < ctl->grid_ny; iy++) {
11708 lat[iy] = ctl->grid_lat0 + dlat * (iy + 0.5);
11709 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
11710 }
11711
11712 /* Set time interval for output... */
11713 const double t0 = t - 0.5 * ctl->dt_mod;
11714 const double t1 = t + 0.5 * ctl->dt_mod;
11715
11716 /* Get grid box indices... */
11717#pragma omp parallel for default(shared)
11718 for (int ip = 0; ip < atm->np; ip++) {
11719 ixs[ip] = (int) ((atm->lon[ip] - ctl->grid_lon0) / dlon);
11720 iys[ip] = (int) ((atm->lat[ip] - ctl->grid_lat0) / dlat);
11721 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->grid_z0) / dz);
11722 if (atm->time[ip] < t0 || atm->time[ip] > t1
11723 || ixs[ip] < 0 || ixs[ip] >= ctl->grid_nx
11724 || iys[ip] < 0 || iys[ip] >= ctl->grid_ny
11725 || izs[ip] < 0 || izs[ip] >= ctl->grid_nz)
11726 izs[ip] = -1;
11727 }
11728
11729 /* Average data... */
11730 for (int ip = 0; ip < atm->np; ip++)
11731 if (izs[ip] >= 0) {
11732 int idx =
11733 ARRAY_3D(ixs[ip], iys[ip], ctl->grid_ny, izs[ip], ctl->grid_nz);
11734 double kernel = kernel_weight(kz, kw, nk, atm->p[ip]);
11735 np[idx]++;
11736 for (int iq = 0; iq < ctl->nq; iq++) {
11737 mean[iq][idx] += kernel * atm->q[iq][ip];
11738 sigma[iq][idx] += SQR(kernel * atm->q[iq][ip]);
11739 }
11740 }
11741
11742 /* Calculate column density and volume mixing ratio... */
11743#pragma omp parallel for default(shared)
11744 for (int ix = 0; ix < ctl->grid_nx; ix++)
11745 for (int iy = 0; iy < ctl->grid_ny; iy++)
11746 for (int iz = 0; iz < ctl->grid_nz; iz++) {
11747
11748 /* Get grid index... */
11749 int idx = ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz);
11750
11751 /* Calculate column density... */
11752 cd[idx] = NAN;
11753 if (ctl->qnt_m >= 0)
11754 cd[idx] = mean[ctl->qnt_m][idx] / (1e6 * area[iy]);
11755
11756 /* Calculate volume mixing ratio (implicit)... */
11757 vmr_impl[idx] = NAN;
11758 if (ctl->qnt_m >= 0 && ctl->molmass > 0 && met0 != NULL
11759 && met1 != NULL) {
11760 vmr_impl[idx] = 0;
11761 if (mean[ctl->qnt_m][idx] > 0) {
11762
11763 /* Get temperature... */
11764 double temp;
11766 intpol_met_time_3d(met0, met0->t, met1, met1->t, t, press[iz],
11767 lon[ix], lat[iy], &temp, ci, cw, 1);
11768
11769 /* Calculate volume mixing ratio... */
11770 vmr_impl[idx] =
11771 MA / ctl->molmass * cd[idx] / (RHO(press[iz], temp) * dz * 1e3);
11772 }
11773 }
11774
11775 /* Calculate mean... */
11776 if (np[idx] > 0)
11777 for (int iq = 0; iq < ctl->nq; iq++) {
11778 mean[iq][idx] /= np[idx];
11779 double var = sigma[iq][idx] / np[idx] - SQR(mean[iq][idx]);
11780 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
11781 } else
11782 for (int iq = 0; iq < ctl->nq; iq++) {
11783 mean[iq][idx] = NAN;
11784 sigma[iq][idx] = NAN;
11785 }
11786 }
11787
11788 /* Write ASCII data... */
11789 if (ctl->grid_type == 0)
11790 write_grid_asc(filename, ctl, cd, mean, sigma, vmr_impl,
11791 t, z, lon, lat, area, dz, np);
11792
11793 /* Write netCDF data... */
11794 else if (ctl->grid_type == 1)
11795 write_grid_nc(filename, ctl, cd, mean, sigma, vmr_impl,
11796 t, z, lon, lat, area, dz, np);
11797
11798 /* Error message... */
11799 else
11800 ERRMSG("Grid data format GRID_TYPE unknown!");
11801
11802 /* Free... */
11803 free(cd);
11804 for (int iq = 0; iq < ctl->nq; iq++) {
11805 free(mean[iq]);
11806 free(sigma[iq]);
11807 }
11808 free(vmr_impl);
11809 free(z);
11810 free(lon);
11811 free(lat);
11812 free(area);
11813 free(press);
11814 free(np);
11815 free(ixs);
11816 free(iys);
11817 free(izs);
11818}
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:11822
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:11926
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 11822 of file mptrac.c.

11835 {
11836
11837 FILE *out;
11838
11839 /* Check if gnuplot output is requested... */
11840 if (ctl->grid_gpfile[0] != '-') {
11841
11842 /* Create gnuplot pipe... */
11843 if (!(out = popen("gnuplot", "w")))
11844 ERRMSG("Cannot create pipe to gnuplot!");
11845
11846 /* Set plot filename... */
11847 fprintf(out, "set out \"%s.png\"\n", filename);
11848
11849 /* Set time string... */
11850 double r;
11851 int year, mon, day, hour, min, sec;
11852 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11853 fprintf(out, "timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
11854 year, mon, day, hour, min);
11855
11856 /* Dump gnuplot file to pipe... */
11857 FILE *in;
11858 char line[LEN];
11859 if (!(in = fopen(ctl->grid_gpfile, "r")))
11860 ERRMSG("Cannot open file!");
11861 while (fgets(line, LEN, in))
11862 fprintf(out, "%s", line);
11863 fclose(in);
11864 }
11865
11866 else {
11867
11868 /* Create file... */
11869 if (!(out = fopen(filename, "w")))
11870 ERRMSG("Cannot create file!");
11871 }
11872
11873 /* Write header... */
11874 fprintf(out,
11875 "# $1 = time [s]\n"
11876 "# $2 = altitude [km]\n"
11877 "# $3 = longitude [deg]\n"
11878 "# $4 = latitude [deg]\n"
11879 "# $5 = surface area [km^2]\n"
11880 "# $6 = layer depth [km]\n"
11881 "# $7 = column density (implicit) [kg/m^2]\n"
11882 "# $8 = volume mixing ratio (implicit) [ppv]\n"
11883 "# $9 = number of particles [1]\n");
11884 for (int iq = 0; iq < ctl->nq; iq++)
11885 fprintf(out, "# $%i = %s (mean) [%s]\n", 10 + iq, ctl->qnt_name[iq],
11886 ctl->qnt_unit[iq]);
11887 if (ctl->grid_stddev)
11888 for (int iq = 0; iq < ctl->nq; iq++)
11889 fprintf(out, "# $%i = %s (stddev) [%s]\n", 10 + ctl->nq + iq,
11890 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
11891 fprintf(out, "\n");
11892
11893 /* Write data... */
11894 for (int ix = 0; ix < ctl->grid_nx; ix++) {
11895 if (ix > 0 && ctl->grid_ny > 1 && !ctl->grid_sparse)
11896 fprintf(out, "\n");
11897 for (int iy = 0; iy < ctl->grid_ny; iy++) {
11898 if (iy > 0 && ctl->grid_nz > 1 && !ctl->grid_sparse)
11899 fprintf(out, "\n");
11900 for (int iz = 0; iz < ctl->grid_nz; iz++) {
11901 int idx = ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz);
11902 if (!ctl->grid_sparse || vmr_impl[idx] > 0) {
11903 fprintf(out, "%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
11904 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
11905 for (int iq = 0; iq < ctl->nq; iq++) {
11906 fprintf(out, " ");
11907 fprintf(out, ctl->qnt_format[iq], mean[iq][idx]);
11908 }
11909 if (ctl->grid_stddev)
11910 for (int iq = 0; iq < ctl->nq; iq++) {
11911 fprintf(out, " ");
11912 fprintf(out, ctl->qnt_format[iq], sigma[iq][idx]);
11913 }
11914 fprintf(out, "\n");
11915 }
11916 }
11917 }
11918 }
11919
11920 /* Close file... */
11921 fclose(out);
11922}
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 11926 of file mptrac.c.

11939 {
11940
11941 char longname[2 * LEN], varname[2 * LEN];
11942
11943 double *help;
11944
11945 int *help2, ncid, dimid[10], varid;
11946
11947 size_t start[2], count[2];
11948
11949 /* Allocate... */
11950 ALLOC(help, double,
11951 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
11952 ALLOC(help2, int,
11953 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
11954
11955 /* Create file... */
11956 NC(nc_create(filename, NC_NETCDF4, &ncid));
11957
11958 /* Define dimensions... */
11959 NC(nc_def_dim(ncid, "time", 1, &dimid[0]));
11960 NC(nc_def_dim(ncid, "z", (size_t) ctl->grid_nz, &dimid[1]));
11961 NC(nc_def_dim(ncid, "lat", (size_t) ctl->grid_ny, &dimid[2]));
11962 NC(nc_def_dim(ncid, "lon", (size_t) ctl->grid_nx, &dimid[3]));
11963 NC(nc_def_dim(ncid, "dz", 1, &dimid[4]));
11964
11965 /* Define variables and their attributes... */
11966 NC_DEF_VAR("time", NC_DOUBLE, 1, &dimid[0], "time",
11967 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
11968 NC_DEF_VAR("z", NC_DOUBLE, 1, &dimid[1], "altitude", "km", 0, 0);
11969 NC_DEF_VAR("lat", NC_DOUBLE, 1, &dimid[2], "latitude", "degrees_north", 0,
11970 0);
11971 NC_DEF_VAR("lon", NC_DOUBLE, 1, &dimid[3], "longitude", "degrees_east", 0,
11972 0);
11973 NC_DEF_VAR("dz", NC_DOUBLE, 1, &dimid[1], "layer depth", "km", 0, 0);
11974 NC_DEF_VAR("area", NC_DOUBLE, 1, &dimid[2], "surface area", "km**2", 0, 0);
11975
11976 NC_DEF_VAR("cd", NC_FLOAT, 4, dimid, "column density", "kg m**-2",
11977 ctl->grid_nc_level, 0);
11978 NC_DEF_VAR("vmr_impl", NC_FLOAT, 4, dimid,
11979 "volume mixing ratio (implicit)", "ppv", ctl->grid_nc_level, 0);
11980 NC_DEF_VAR("np", NC_INT, 4, dimid, "number of particles", "1", 0, 0);
11981 for (int iq = 0; iq < ctl->nq; iq++) {
11982 sprintf(varname, "%s_mean", ctl->qnt_name[iq]);
11983 sprintf(longname, "%s (mean)", ctl->qnt_longname[iq]);
11984 NC_DEF_VAR(varname, NC_DOUBLE, 4, dimid, longname, ctl->qnt_unit[iq],
11985 ctl->grid_nc_level, ctl->grid_nc_quant[iq]);
11986 if (ctl->grid_stddev) {
11987 sprintf(varname, "%s_stddev", ctl->qnt_name[iq]);
11988 sprintf(longname, "%s (stddev)", ctl->qnt_longname[iq]);
11989 NC_DEF_VAR(varname, NC_DOUBLE, 4, dimid, longname, ctl->qnt_unit[iq],
11990 ctl->grid_nc_level, ctl->grid_nc_quant[iq]);
11991 }
11992 }
11993 /* End definitions... */
11994 NC(nc_enddef(ncid));
11995
11996 /* Write data... */
11997 NC_PUT_DOUBLE("time", &t, 0);
11998 NC_PUT_DOUBLE("lon", lon, 0);
11999 NC_PUT_DOUBLE("lat", lat, 0);
12000 NC_PUT_DOUBLE("z", z, 0);
12001 NC_PUT_DOUBLE("area", area, 0);
12002 NC_PUT_DOUBLE("dz", &dz, 0);
12003
12004 for (int ix = 0; ix < ctl->grid_nx; ix++)
12005 for (int iy = 0; iy < ctl->grid_ny; iy++)
12006 for (int iz = 0; iz < ctl->grid_nz; iz++)
12007 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
12008 cd[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
12009 NC_PUT_DOUBLE("cd", help, 0);
12010
12011 for (int ix = 0; ix < ctl->grid_nx; ix++)
12012 for (int iy = 0; iy < ctl->grid_ny; iy++)
12013 for (int iz = 0; iz < ctl->grid_nz; iz++)
12014 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
12015 vmr_impl[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
12016 NC_PUT_DOUBLE("vmr_impl", help, 0);
12017
12018 for (int ix = 0; ix < ctl->grid_nx; ix++)
12019 for (int iy = 0; iy < ctl->grid_ny; iy++)
12020 for (int iz = 0; iz < ctl->grid_nz; iz++)
12021 help2[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
12022 np[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
12023 NC_PUT_INT("np", help2, 0);
12024
12025 for (int iq = 0; iq < ctl->nq; iq++) {
12026 sprintf(varname, "%s_mean", ctl->qnt_name[iq]);
12027 for (int ix = 0; ix < ctl->grid_nx; ix++)
12028 for (int iy = 0; iy < ctl->grid_ny; iy++)
12029 for (int iz = 0; iz < ctl->grid_nz; iz++)
12030 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
12031 mean[iq][ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
12032 NC_PUT_DOUBLE(varname, help, 0);
12033 }
12034
12035 if (ctl->grid_stddev)
12036 for (int iq = 0; iq < ctl->nq; iq++) {
12037 sprintf(varname, "%s_stddev", ctl->qnt_name[iq]);
12038 for (int ix = 0; ix < ctl->grid_nx; ix++)
12039 for (int iy = 0; iy < ctl->grid_ny; iy++)
12040 for (int iz = 0; iz < ctl->grid_nz; iz++)
12041 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
12042 sigma[iq][ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
12043 NC_PUT_DOUBLE(varname, help, 0);
12044 }
12045
12046 /* Close file... */
12047 NC(nc_close(ncid));
12048
12049 /* Free... */
12050 free(help);
12051 free(help2);
12052}
#define NC_PUT_INT(varname, ptr, hyperslab)
Write integer data to a NetCDF variable.
Definition: mptrac.h:1371

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

12059 {
12060
12061 /* Create file... */
12062 FILE *out;
12063 if (!(out = fopen(filename, "w")))
12064 ERRMSG("Cannot create file!");
12065
12066 /* Write type of binary data... */
12067 FWRITE(&ctl->met_type, int,
12068 1,
12069 out);
12070
12071 /* Write version of binary data... */
12072 int version = 103;
12073 FWRITE(&version, int,
12074 1,
12075 out);
12076
12077 /* Write grid data... */
12078 FWRITE(&met->time, double,
12079 1,
12080 out);
12081 FWRITE(&met->nx, int,
12082 1,
12083 out);
12084 FWRITE(&met->ny, int,
12085 1,
12086 out);
12087 FWRITE(&met->np, int,
12088 1,
12089 out);
12090 FWRITE(met->lon, double,
12091 (size_t) met->nx,
12092 out);
12093 FWRITE(met->lat, double,
12094 (size_t) met->ny,
12095 out);
12096 FWRITE(met->p, double,
12097 (size_t) met->np,
12098 out);
12099
12100 /* Write surface data... */
12101 write_met_bin_2d(out, met, met->ps, "PS");
12102 write_met_bin_2d(out, met, met->ts, "TS");
12103 write_met_bin_2d(out, met, met->zs, "ZS");
12104 write_met_bin_2d(out, met, met->us, "US");
12105 write_met_bin_2d(out, met, met->vs, "VS");
12106 write_met_bin_2d(out, met, met->ess, "ESS");
12107 write_met_bin_2d(out, met, met->nss, "NSS");
12108 write_met_bin_2d(out, met, met->shf, "SHF");
12109 write_met_bin_2d(out, met, met->lsm, "LSM");
12110 write_met_bin_2d(out, met, met->sst, "SST");
12111 write_met_bin_2d(out, met, met->pbl, "PBL");
12112 write_met_bin_2d(out, met, met->pt, "PT");
12113 write_met_bin_2d(out, met, met->tt, "TT");
12114 write_met_bin_2d(out, met, met->zt, "ZT");
12115 write_met_bin_2d(out, met, met->h2ot, "H2OT");
12116 write_met_bin_2d(out, met, met->pct, "PCT");
12117 write_met_bin_2d(out, met, met->pcb, "PCB");
12118 write_met_bin_2d(out, met, met->cl, "CL");
12119 write_met_bin_2d(out, met, met->plcl, "PLCL");
12120 write_met_bin_2d(out, met, met->plfc, "PLFC");
12121 write_met_bin_2d(out, met, met->pel, "PEL");
12122 write_met_bin_2d(out, met, met->cape, "CAPE");
12123 write_met_bin_2d(out, met, met->cin, "CIN");
12124 write_met_bin_2d(out, met, met->o3c, "O3C");
12125
12126 /* Write level data... */
12127 write_met_bin_3d(out, ctl, met, met->z, "Z",
12128 ctl->met_zfp_prec[0], ctl->met_zfp_tol[0]);
12129 write_met_bin_3d(out, ctl, met, met->t, "T",
12130 ctl->met_zfp_prec[1], ctl->met_zfp_tol[1]);
12131 write_met_bin_3d(out, ctl, met, met->u, "U",
12132 ctl->met_zfp_prec[2], ctl->met_zfp_tol[2]);
12133 write_met_bin_3d(out, ctl, met, met->v, "V",
12134 ctl->met_zfp_prec[3], ctl->met_zfp_tol[3]);
12135 write_met_bin_3d(out, ctl, met, met->w, "W",
12136 ctl->met_zfp_prec[4], ctl->met_zfp_tol[4]);
12137 write_met_bin_3d(out, ctl, met, met->pv, "PV",
12138 ctl->met_zfp_prec[5], ctl->met_zfp_tol[5]);
12139 write_met_bin_3d(out, ctl, met, met->h2o, "H2O",
12140 ctl->met_zfp_prec[6], ctl->met_zfp_tol[6]);
12141 write_met_bin_3d(out, ctl, met, met->o3, "O3",
12142 ctl->met_zfp_prec[7], ctl->met_zfp_tol[7]);
12143 write_met_bin_3d(out, ctl, met, met->lwc, "LWC",
12144 ctl->met_zfp_prec[8], ctl->met_zfp_tol[8]);
12145 write_met_bin_3d(out, ctl, met, met->rwc, "RWC",
12146 ctl->met_zfp_prec[9], ctl->met_zfp_tol[9]);
12147 write_met_bin_3d(out, ctl, met, met->iwc, "IWC",
12148 ctl->met_zfp_prec[10], ctl->met_zfp_tol[10]);
12149 write_met_bin_3d(out, ctl, met, met->swc, "SWC",
12150 ctl->met_zfp_prec[11], ctl->met_zfp_tol[11]);
12151 write_met_bin_3d(out, ctl, met, met->cc, "CC",
12152 ctl->met_zfp_prec[12], ctl->met_zfp_tol[12]);
12153 if (METVAR != 13)
12154 ERRMSG("Number of meteo variables doesn't match!");
12155
12156 /* Write final flag... */
12157 int final = 999;
12158 FWRITE(&final, int,
12159 1,
12160 out);
12161
12162 /* Close file... */
12163 fclose(out);
12164}
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:12197
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:12168
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 12168 of file mptrac.c.

12172 {
12173
12174 float *help;
12175
12176 /* Allocate... */
12177 ALLOC(help, float,
12178 EX * EY);
12179
12180 /* Copy data... */
12181 for (int ix = 0; ix < met->nx; ix++)
12182 for (int iy = 0; iy < met->ny; iy++)
12183 help[ARRAY_2D(ix, iy, met->ny)] = var[ix][iy];
12184
12185 /* Write uncompressed data... */
12186 LOG(2, "Write 2-D variable: %s (uncompressed)", varname);
12187 FWRITE(help, float,
12188 (size_t) (met->nx * met->ny),
12189 out);
12190
12191 /* Free... */
12192 free(help);
12193}

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

12204 {
12205
12206 float *help;
12207
12208 /* Allocate... */
12209 ALLOC(help, float,
12210 EX * EY * EP);
12211
12212 /* Copy data... */
12213#pragma omp parallel for default(shared) collapse(2)
12214 for (int ix = 0; ix < met->nx; ix++)
12215 for (int iy = 0; iy < met->ny; iy++)
12216 for (int ip = 0; ip < met->np; ip++)
12217 help[ARRAY_3D(ix, iy, met->ny, ip, met->np)] = var[ix][iy][ip];
12218
12219 /* Write uncompressed data... */
12220 if (ctl->met_type == 1) {
12221 LOG(2, "Write 3-D variable: %s (uncompressed)", varname);
12222 FWRITE(help, float,
12223 (size_t) (met->nx * met->ny * met->np),
12224 out);
12225 }
12226
12227 /* Write packed data... */
12228 else if (ctl->met_type == 2)
12229 compress_pck(varname, help, (size_t) (met->ny * met->nx),
12230 (size_t) met->np, 0, out);
12231
12232 /* Write zfp data... */
12233#ifdef ZFP
12234 else if (ctl->met_type == 3) {
12235 FWRITE(&precision, int,
12236 1,
12237 out);
12238 FWRITE(&tolerance, double,
12239 1,
12240 out);
12241 compress_zfp(varname, help, met->np, met->ny, met->nx, precision,
12242 tolerance, 0, out);
12243 }
12244#endif
12245
12246 /* Write zstd data... */
12247#ifdef ZSTD
12248 else if (ctl->met_type == 4)
12249 compress_zstd(varname, help, (size_t) (met->np * met->ny * met->nx), 0,
12250 ctl->met_zstd_level, out);
12251#endif
12252
12253 /* Write cmultiscale data... */
12254#ifdef CMS
12255 else if (ctl->met_type == 5) {
12256 compress_cms(ctl, varname, help, (size_t) met->nx, (size_t) met->ny,
12257 (size_t) met->np, 0, out);
12258 }
12259#endif
12260
12261 /* Unknown method... */
12262 else {
12263 ERRMSG("MET_TYPE not supported!");
12264 LOG(3, "%d %g", precision, tolerance);
12265 }
12266
12267 /* Free... */
12268 free(help);
12269}
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 12273 of file mptrac.c.

12276 {
12277
12278 /* Create file... */
12279 int ncid, varid;
12280 size_t start[4], count[4];
12281 nc_create(filename, NC_NETCDF4, &ncid);
12282
12283 /* Define dimensions... */
12284 int tid, lonid, latid, levid;
12285 NC(nc_def_dim(ncid, "time", 1, &tid));
12286 NC(nc_def_dim(ncid, "lon", (size_t) met->nx, &lonid));
12287 NC(nc_def_dim(ncid, "lat", (size_t) met->ny, &latid));
12288 NC(nc_def_dim(ncid, "lev", (size_t) met->np, &levid));
12289
12290 /* Define grid... */
12291 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "time",
12292 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12293 NC_DEF_VAR("lon", NC_DOUBLE, 1, &lonid, "longitude", "degrees_east", 0, 0);
12294 NC_DEF_VAR("lat", NC_DOUBLE, 1, &latid, "latitude", "degrees_north", 0, 0);
12295 NC_DEF_VAR("lev", NC_DOUBLE, 1, &levid, "pressure", "Pa", 0, 0);
12296
12297 /* Define surface variables... */
12298 int dimid2[2] = { latid, lonid };
12299 NC_DEF_VAR("sp", NC_FLOAT, 2, dimid2, "Surface pressure", "Pa",
12300 ctl->met_nc_level, 0);
12301 NC_DEF_VAR("z", NC_FLOAT, 2, dimid2, "Geopotential", "m**2 s**-2",
12302 ctl->met_nc_level, 0);
12303 NC_DEF_VAR("t2m", NC_FLOAT, 2, dimid2, "2 metre temperature", "K",
12304 ctl->met_nc_level, 0);
12305 NC_DEF_VAR("u10m", NC_FLOAT, 2, dimid2, "10 metre U wind component",
12306 "m s**-1", ctl->met_nc_level, 0);
12307 NC_DEF_VAR("v10m", NC_FLOAT, 2, dimid2, "10 metre V wind component",
12308 "m s**-1", ctl->met_nc_level, 0);
12309 NC_DEF_VAR("iews", NC_FLOAT, 2, dimid2,
12310 "Instantaneous eastward turbulent surface stress", "N m**-2",
12311 ctl->met_nc_level, 0);
12312 NC_DEF_VAR("inss", NC_FLOAT, 2, dimid2,
12313 "Instantaneous northward turbulent surface stress", "N m**-2",
12314 ctl->met_nc_level, 0);
12315 NC_DEF_VAR("ishf", NC_FLOAT, 2, dimid2,
12316 "Instantaneous surface sensible heat flux", "W m**-1",
12317 ctl->met_nc_level, 0);
12318 NC_DEF_VAR("lsm", NC_FLOAT, 2, dimid2, "Land/sea mask", "-",
12319 ctl->met_nc_level, 0);
12320 NC_DEF_VAR("sstk", NC_FLOAT, 2, dimid2, "Sea surface temperature", "K",
12321 ctl->met_nc_level, 0);
12322 NC_DEF_VAR("blp", NC_FLOAT, 2, dimid2, "Boundary layer pressure", "Pa",
12323 ctl->met_nc_level, 0);
12324 NC_DEF_VAR("pt", NC_FLOAT, 2, dimid2, "Tropopause pressure", "Pa",
12325 ctl->met_nc_level, 0);
12326 NC_DEF_VAR("tt", NC_FLOAT, 2, dimid2, "Tropopause temperature", "K",
12327 ctl->met_nc_level, 0);
12328 NC_DEF_VAR("zt", NC_FLOAT, 2, dimid2, "Tropopause height", "m",
12329 ctl->met_nc_level, 0);
12330 NC_DEF_VAR("h2ot", NC_FLOAT, 2, dimid2, "Tropopause water vapor", "ppv",
12331 ctl->met_nc_level, 0);
12332 NC_DEF_VAR("pct", NC_FLOAT, 2, dimid2, "Cloud top pressure", "Pa",
12333 ctl->met_nc_level, 0);
12334 NC_DEF_VAR("pcb", NC_FLOAT, 2, dimid2, "Cloud bottom pressure", "Pa",
12335 ctl->met_nc_level, 0);
12336 NC_DEF_VAR("cl", NC_FLOAT, 2, dimid2, "Total column cloud water",
12337 "kg m**2", ctl->met_nc_level, 0);
12338 NC_DEF_VAR("plcl", NC_FLOAT, 2, dimid2,
12339 "Pressure at lifted condensation level (LCL)", "Pa",
12340 ctl->met_nc_level, 0);
12341 NC_DEF_VAR("plfc", NC_FLOAT, 2, dimid2,
12342 "Pressure at level of free convection (LFC)", "Pa",
12343 ctl->met_nc_level, 0);
12344 NC_DEF_VAR("pel", NC_FLOAT, 2, dimid2,
12345 "Pressure at equilibrium level (EL)", "Pa", ctl->met_nc_level,
12346 0);
12347 NC_DEF_VAR("cape", NC_FLOAT, 2, dimid2,
12348 "Convective available potential energy", "J kg**-1",
12349 ctl->met_nc_level, 0);
12350 NC_DEF_VAR("cin", NC_FLOAT, 2, dimid2, "Convective inhibition",
12351 "J kg**-1", ctl->met_nc_level, 0);
12352 NC_DEF_VAR("o3c", NC_FLOAT, 2, dimid2, "Total column ozone", "DU",
12353 ctl->met_nc_level, 0);
12354
12355 /* Define level data... */
12356 int dimid3[3] = { levid, latid, lonid };
12357 NC_DEF_VAR("t", NC_FLOAT, 3, dimid3, "Temperature", "K",
12358 ctl->met_nc_level, ctl->met_nc_quant);
12359 NC_DEF_VAR("u", NC_FLOAT, 3, dimid3, "U velocity", "m s**-1",
12360 ctl->met_nc_level, ctl->met_nc_quant);
12361 NC_DEF_VAR("v", NC_FLOAT, 3, dimid3, "V velocity", "m s**-1",
12362 ctl->met_nc_level, ctl->met_nc_quant);
12363 NC_DEF_VAR("w", NC_FLOAT, 3, dimid3, "Vertical velocity", "Pa s**-1",
12364 ctl->met_nc_level, ctl->met_nc_quant);
12365 NC_DEF_VAR("q", NC_FLOAT, 3, dimid3, "Specific humidity", "kg kg**-1",
12366 ctl->met_nc_level, ctl->met_nc_quant);
12367 NC_DEF_VAR("o3", NC_FLOAT, 3, dimid3, "Ozone mass mixing ratio",
12368 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
12369 NC_DEF_VAR("clwc", NC_FLOAT, 3, dimid3, "Cloud liquid water content",
12370 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
12371 NC_DEF_VAR("crwc", NC_FLOAT, 3, dimid3, "Cloud rain water content",
12372 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
12373 NC_DEF_VAR("ciwc", NC_FLOAT, 3, dimid3, "Cloud ice water content",
12374 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
12375 NC_DEF_VAR("cswc", NC_FLOAT, 3, dimid3, "Cloud snow water content",
12376 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
12377 NC_DEF_VAR("cc", NC_FLOAT, 3, dimid3, "Cloud cover", "-",
12378 ctl->met_nc_level, ctl->met_nc_quant);
12379
12380 /* End definitions... */
12381 NC(nc_enddef(ncid));
12382
12383 /* Write grid data... */
12384 NC_PUT_DOUBLE("time", &met->time, 0);
12385 NC_PUT_DOUBLE("lon", met->lon, 0);
12386 NC_PUT_DOUBLE("lat", met->lat, 0);
12387 double phelp[EP];
12388 for (int ip = 0; ip < met->np; ip++)
12389 phelp[ip] = 100. * met->p[ip];
12390 NC_PUT_DOUBLE("lev", phelp, 0);
12391
12392 /* Write surface data... */
12393 write_met_nc_2d(ncid, "sp", met, met->ps, 100.0f);
12394 write_met_nc_2d(ncid, "z", met, met->zs, (float) (1000. * G0));
12395 write_met_nc_2d(ncid, "t2m", met, met->ts, 1.0f);
12396 write_met_nc_2d(ncid, "u10m", met, met->us, 1.0f);
12397 write_met_nc_2d(ncid, "v10m", met, met->vs, 1.0f);
12398 write_met_nc_2d(ncid, "iews", met, met->ess, 1.0f);
12399 write_met_nc_2d(ncid, "inss", met, met->nss, 1.0f);
12400 write_met_nc_2d(ncid, "ishf", met, met->shf, 1.0f);
12401 write_met_nc_2d(ncid, "lsm", met, met->lsm, 1.0f);
12402 write_met_nc_2d(ncid, "sstk", met, met->sst, 1.0f);
12403 write_met_nc_2d(ncid, "blp", met, met->pbl, 100.0f);
12404 write_met_nc_2d(ncid, "pt", met, met->pt, 100.0f);
12405 write_met_nc_2d(ncid, "tt", met, met->tt, 1.0f);
12406 write_met_nc_2d(ncid, "zt", met, met->zt, 1000.0f);
12407 write_met_nc_2d(ncid, "h2ot", met, met->h2ot, 1.0f);
12408 write_met_nc_2d(ncid, "pct", met, met->pct, 100.0f);
12409 write_met_nc_2d(ncid, "pcb", met, met->pcb, 100.0f);
12410 write_met_nc_2d(ncid, "cl", met, met->cl, 1.0f);
12411 write_met_nc_2d(ncid, "plcl", met, met->plcl, 100.0f);
12412 write_met_nc_2d(ncid, "plfc", met, met->plfc, 100.0f);
12413 write_met_nc_2d(ncid, "pel", met, met->pel, 100.0f);
12414 write_met_nc_2d(ncid, "cape", met, met->cape, 1.0f);
12415 write_met_nc_2d(ncid, "cin", met, met->cin, 1.0f);
12416 write_met_nc_2d(ncid, "o3c", met, met->o3c, 1.0f);
12417
12418 /* Write level data... */
12419 write_met_nc_3d(ncid, "t", met, met->t, 1.0f);
12420 write_met_nc_3d(ncid, "u", met, met->u, 1.0f);
12421 write_met_nc_3d(ncid, "v", met, met->v, 1.0f);
12422 write_met_nc_3d(ncid, "w", met, met->w, 100.0f);
12423 write_met_nc_3d(ncid, "q", met, met->h2o, (float) (MH2O / MA));
12424 write_met_nc_3d(ncid, "o3", met, met->o3, (float) (MO3 / MA));
12425 write_met_nc_3d(ncid, "clwc", met, met->lwc, 1.0f);
12426 write_met_nc_3d(ncid, "crwc", met, met->rwc, 1.0f);
12427 write_met_nc_3d(ncid, "ciwc", met, met->iwc, 1.0f);
12428 write_met_nc_3d(ncid, "cswc", met, met->swc, 1.0f);
12429 write_met_nc_3d(ncid, "cc", met, met->cc, 1.0f);
12430
12431 /* Close file... */
12432 NC(nc_close(ncid));
12433}
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:12437
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:12466
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 12437 of file mptrac.c.

12442 {
12443
12444 int varid;
12445 size_t start[4], count[4];
12446
12447 /* Allocate... */
12448 float *help;
12449 ALLOC(help, float,
12450 EX * EY);
12451
12452 /* Copy data... */
12453 for (int ix = 0; ix < met->nx; ix++)
12454 for (int iy = 0; iy < met->ny; iy++)
12455 help[ARRAY_2D(iy, ix, met->nx)] = scl * var[ix][iy];
12456
12457 /* Write data... */
12458 NC_PUT_FLOAT(varname, help, 0);
12459
12460 /* Free... */
12461 free(help);
12462}
#define NC_PUT_FLOAT(varname, ptr, hyperslab)
Write a float array to a NetCDF file.
Definition: mptrac.h:1348

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

12471 {
12472
12473 int varid;
12474 size_t start[4], count[4];
12475
12476 /* Allocate... */
12477 float *help;
12478 ALLOC(help, float,
12479 EX * EY * EP);
12480
12481 /* Copy data... */
12482 for (int ix = 0; ix < met->nx; ix++)
12483 for (int iy = 0; iy < met->ny; iy++)
12484 for (int ip = 0; ip < met->np; ip++)
12485 help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)] = scl * var[ix][iy][ip];
12486
12487 /* Write data... */
12488 NC_PUT_FLOAT(varname, help, 0);
12489
12490 /* Free... */
12491 free(help);
12492}

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

12502 {
12503
12504 static FILE *out;
12505
12506 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
12507 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
12508
12509 static int nobs, *obscount, ip, okay;
12510
12511 /* Set timer... */
12512 SELECT_TIMER("WRITE_PROF", "OUTPUT", NVTX_WRITE);
12513
12514 /* Init... */
12515 if (t == ctl->t_start) {
12516
12517 /* Check quantity index for mass... */
12518 if (ctl->qnt_m < 0)
12519 ERRMSG("Need quantity mass!");
12520
12521 /* Check molar mass... */
12522 if (ctl->molmass <= 0)
12523 ERRMSG("Specify molar mass!");
12524
12525 /* Allocate... */
12526 ALLOC(lon, double,
12527 ctl->prof_nx);
12528 ALLOC(lat, double,
12529 ctl->prof_ny);
12530 ALLOC(area, double,
12531 ctl->prof_ny);
12532 ALLOC(z, double,
12533 ctl->prof_nz);
12534 ALLOC(press, double,
12535 ctl->prof_nz);
12536 ALLOC(rt, double,
12537 NOBS);
12538 ALLOC(rz, double,
12539 NOBS);
12540 ALLOC(rlon, double,
12541 NOBS);
12542 ALLOC(rlat, double,
12543 NOBS);
12544 ALLOC(robs, double,
12545 NOBS);
12546
12547 /* Read observation data... */
12548 read_obs(ctl->prof_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
12549
12550 /* Create new output file... */
12551 LOG(1, "Write profile data: %s", filename);
12552 if (!(out = fopen(filename, "w")))
12553 ERRMSG("Cannot create file!");
12554
12555 /* Write header... */
12556 fprintf(out,
12557 "# $1 = time [s]\n"
12558 "# $2 = altitude [km]\n"
12559 "# $3 = longitude [deg]\n"
12560 "# $4 = latitude [deg]\n"
12561 "# $5 = pressure [hPa]\n"
12562 "# $6 = temperature [K]\n"
12563 "# $7 = volume mixing ratio [ppv]\n"
12564 "# $8 = H2O volume mixing ratio [ppv]\n"
12565 "# $9 = O3 volume mixing ratio [ppv]\n"
12566 "# $10 = observed BT index [K]\n"
12567 "# $11 = number of observations\n");
12568
12569 /* Set grid box size... */
12570 dz = (ctl->prof_z1 - ctl->prof_z0) / ctl->prof_nz;
12571 dlon = (ctl->prof_lon1 - ctl->prof_lon0) / ctl->prof_nx;
12572 dlat = (ctl->prof_lat1 - ctl->prof_lat0) / ctl->prof_ny;
12573
12574 /* Set vertical coordinates... */
12575 for (int iz = 0; iz < ctl->prof_nz; iz++) {
12576 z[iz] = ctl->prof_z0 + dz * (iz + 0.5);
12577 press[iz] = P(z[iz]);
12578 }
12579
12580 /* Set horizontal coordinates... */
12581 for (int ix = 0; ix < ctl->prof_nx; ix++)
12582 lon[ix] = ctl->prof_lon0 + dlon * (ix + 0.5);
12583 for (int iy = 0; iy < ctl->prof_ny; iy++) {
12584 lat[iy] = ctl->prof_lat0 + dlat * (iy + 0.5);
12585 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
12586 }
12587 }
12588
12589 /* Set time interval... */
12590 const double t0 = t - 0.5 * ctl->dt_mod;
12591 const double t1 = t + 0.5 * ctl->dt_mod;
12592
12593 /* Allocate... */
12594 ALLOC(mass, double,
12595 ctl->prof_nx * ctl->prof_ny * ctl->prof_nz);
12596 ALLOC(obsmean, double,
12597 ctl->prof_nx * ctl->prof_ny);
12598 ALLOC(obscount, int,
12599 ctl->prof_nx * ctl->prof_ny);
12600
12601 /* Loop over observations... */
12602 for (int i = 0; i < nobs; i++) {
12603
12604 /* Check time... */
12605 if (rt[i] < t0)
12606 continue;
12607 else if (rt[i] >= t1)
12608 break;
12609
12610 /* Check observation data... */
12611 if (!isfinite(robs[i]))
12612 continue;
12613
12614 /* Calculate indices... */
12615 int ix = (int) ((rlon[i] - ctl->prof_lon0) / dlon);
12616 int iy = (int) ((rlat[i] - ctl->prof_lat0) / dlat);
12617
12618 /* Check indices... */
12619 if (ix < 0 || ix >= ctl->prof_nx || iy < 0 || iy >= ctl->prof_ny)
12620 continue;
12621
12622 /* Get mean observation index... */
12623 int idx = ARRAY_2D(ix, iy, ctl->prof_ny);
12624 obsmean[idx] += robs[i];
12625 obscount[idx]++;
12626 }
12627
12628 /* Analyze model data... */
12629 for (ip = 0; ip < atm->np; ip++) {
12630
12631 /* Check time... */
12632 if (atm->time[ip] < t0 || atm->time[ip] > t1)
12633 continue;
12634
12635 /* Get indices... */
12636 int ix = (int) ((atm->lon[ip] - ctl->prof_lon0) / dlon);
12637 int iy = (int) ((atm->lat[ip] - ctl->prof_lat0) / dlat);
12638 int iz = (int) ((Z(atm->p[ip]) - ctl->prof_z0) / dz);
12639
12640 /* Check indices... */
12641 if (ix < 0 || ix >= ctl->prof_nx ||
12642 iy < 0 || iy >= ctl->prof_ny || iz < 0 || iz >= ctl->prof_nz)
12643 continue;
12644
12645 /* Get total mass in grid cell... */
12646 int idx = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
12647 mass[idx] += atm->q[ctl->qnt_m][ip];
12648 }
12649
12650 /* Extract profiles... */
12651 for (int ix = 0; ix < ctl->prof_nx; ix++)
12652 for (int iy = 0; iy < ctl->prof_ny; iy++) {
12653 int idx2 = ARRAY_2D(ix, iy, ctl->prof_ny);
12654 if (obscount[idx2] > 0) {
12655
12656 /* Check profile... */
12657 okay = 0;
12658 for (int iz = 0; iz < ctl->prof_nz; iz++) {
12659 int idx3 = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
12660 if (mass[idx3] > 0) {
12661 okay = 1;
12662 break;
12663 }
12664 }
12665 if (!okay)
12666 continue;
12667
12668 /* Write output... */
12669 fprintf(out, "\n");
12670
12671 /* Loop over altitudes... */
12672 for (int iz = 0; iz < ctl->prof_nz; iz++) {
12673
12674 /* Get temperature, water vapor, and ozone... */
12676 intpol_met_time_3d(met0, met0->t, met1, met1->t, t, press[iz],
12677 lon[ix], lat[iy], &temp, ci, cw, 1);
12678 intpol_met_time_3d(met0, met0->h2o, met1, met1->h2o, t, press[iz],
12679 lon[ix], lat[iy], &h2o, ci, cw, 0);
12680 intpol_met_time_3d(met0, met0->o3, met1, met1->o3, t, press[iz],
12681 lon[ix], lat[iy], &o3, ci, cw, 0);
12682
12683 /* Calculate volume mixing ratio... */
12684 const int idx3 = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
12685 vmr = MA / ctl->molmass * mass[idx3]
12686 / (RHO(press[iz], temp) * area[iy] * dz * 1e9);
12687
12688 /* Write output... */
12689 fprintf(out, "%.2f %g %g %g %g %g %g %g %g %g %d\n",
12690 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
12691 obsmean[idx2] / obscount[idx2], obscount[idx2]);
12692 }
12693 }
12694 }
12695
12696 /* Free... */
12697 free(mass);
12698 free(obsmean);
12699 free(obscount);
12700
12701 /* Finalize... */
12702 if (t == ctl->t_stop) {
12703
12704 /* Close output file... */
12705 fclose(out);
12706
12707 /* Free... */
12708 free(lon);
12709 free(lat);
12710 free(area);
12711 free(z);
12712 free(press);
12713 free(rt);
12714 free(rz);
12715 free(rlon);
12716 free(rlat);
12717 free(robs);
12718 }
12719}
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 12723 of file mptrac.c.

12729 {
12730
12731 static FILE *out;
12732
12733 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[EP],
12734 kw[EP];
12735
12736 static int nobs, nk;
12737
12738 /* Set timer... */
12739 SELECT_TIMER("WRITE_SAMPLE", "OUTPUT", NVTX_WRITE);
12740
12741 /* Init... */
12742 if (t == ctl->t_start) {
12743
12744 /* Allocate... */
12745 ALLOC(rt, double,
12746 NOBS);
12747 ALLOC(rz, double,
12748 NOBS);
12749 ALLOC(rlon, double,
12750 NOBS);
12751 ALLOC(rlat, double,
12752 NOBS);
12753 ALLOC(robs, double,
12754 NOBS);
12755
12756 /* Read observation data... */
12757 read_obs(ctl->sample_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
12758
12759 /* Read kernel data... */
12760 if (ctl->sample_kernel[0] != '-')
12761 read_kernel(ctl->sample_kernel, kz, kw, &nk);
12762
12763 /* Create output file... */
12764 LOG(1, "Write sample data: %s", filename);
12765 if (!(out = fopen(filename, "w")))
12766 ERRMSG("Cannot create file!");
12767
12768 /* Write header... */
12769 fprintf(out,
12770 "# $1 = time [s]\n"
12771 "# $2 = altitude [km]\n"
12772 "# $3 = longitude [deg]\n"
12773 "# $4 = latitude [deg]\n"
12774 "# $5 = surface area [km^2]\n"
12775 "# $6 = layer depth [km]\n"
12776 "# $7 = number of particles [1]\n"
12777 "# $8 = column density [kg/m^2]\n"
12778 "# $9 = volume mixing ratio [ppv]\n"
12779 "# $10 = observed BT index [K]\n\n");
12780
12781 /* Set latitude range, squared radius, and area... */
12782 dlat = DY2DEG(ctl->sample_dx);
12783 rmax2 = SQR(ctl->sample_dx);
12784 area = M_PI * rmax2;
12785 }
12786
12787 /* Set time interval for output... */
12788 const double t0 = t - 0.5 * ctl->dt_mod;
12789 const double t1 = t + 0.5 * ctl->dt_mod;
12790
12791 /* Loop over observations... */
12792 for (int i = 0; i < nobs; i++) {
12793
12794 /* Check time... */
12795 if (rt[i] < t0)
12796 continue;
12797 else if (rt[i] >= t1)
12798 break;
12799
12800 /* Calculate Cartesian coordinates... */
12801 double x0[3];
12802 geo2cart(0, rlon[i], rlat[i], x0);
12803
12804 /* Set pressure range... */
12805 const double rp = P(rz[i]);
12806 const double ptop = P(rz[i] + ctl->sample_dz);
12807 const double pbot = P(rz[i] - ctl->sample_dz);
12808
12809 /* Init... */
12810 double mass = 0;
12811 int np = 0;
12812
12813 /* Loop over air parcels... */
12814 //#pragma omp parallel for default(shared) reduction(+:mass,np)
12815 for (int ip = 0; ip < atm->np; ip++) {
12816
12817 /* Check time... */
12818 if (atm->time[ip] < t0 || atm->time[ip] > t1)
12819 continue;
12820
12821 /* Check latitude... */
12822 if (fabs(rlat[i] - atm->lat[ip]) > dlat)
12823 continue;
12824
12825 /* Check horizontal distance... */
12826 double x1[3];
12827 geo2cart(0, atm->lon[ip], atm->lat[ip], x1);
12828 if (DIST2(x0, x1) > rmax2)
12829 continue;
12830
12831 /* Check pressure... */
12832 if (ctl->sample_dz > 0)
12833 if (atm->p[ip] > pbot || atm->p[ip] < ptop)
12834 continue;
12835
12836 /* Add mass... */
12837 if (ctl->qnt_m >= 0)
12838 mass +=
12839 kernel_weight(kz, kw, nk, atm->p[ip]) * atm->q[ctl->qnt_m][ip];
12840 np++;
12841 }
12842
12843 /* Calculate column density... */
12844 const double cd = mass / (1e6 * area);
12845
12846 /* Calculate volume mixing ratio... */
12847 double vmr = 0;
12848 if (ctl->molmass > 0 && ctl->sample_dz > 0) {
12849 if (mass > 0) {
12850
12851 /* Get temperature... */
12852 double temp;
12854 intpol_met_time_3d(met0, met0->t, met1, met1->t, rt[i], rp,
12855 rlon[i], rlat[i], &temp, ci, cw, 1);
12856
12857 /* Calculate volume mixing ratio... */
12858 vmr = MA / ctl->molmass * cd / (RHO(rp, temp) * ctl->sample_dz * 1e3);
12859 }
12860 } else
12861 vmr = NAN;
12862
12863 /* Write output... */
12864 fprintf(out, "%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
12865 rlon[i], rlat[i], area, ctl->sample_dz, np, cd, vmr, robs[i]);
12866 }
12867
12868 /* Finalize...... */
12869 if (t == ctl->t_stop) {
12870
12871 /* Close output file... */
12872 fclose(out);
12873
12874 /* Free... */
12875 free(rt);
12876 free(rz);
12877 free(rlon);
12878 free(rlat);
12879 free(robs);
12880 }
12881}
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 12885 of file mptrac.c.

12889 {
12890
12891 static FILE *out;
12892
12893 static double rmax2, x0[3], x1[3];
12894
12895 /* Set timer... */
12896 SELECT_TIMER("WRITE_STATION", "OUTPUT", NVTX_WRITE);
12897
12898 /* Init... */
12899 if (t == ctl->t_start) {
12900
12901 /* Write info... */
12902 LOG(1, "Write station data: %s", filename);
12903
12904 /* Create new file... */
12905 if (!(out = fopen(filename, "w")))
12906 ERRMSG("Cannot create file!");
12907
12908 /* Write header... */
12909 fprintf(out,
12910 "# $1 = time [s]\n"
12911 "# $2 = altitude [km]\n"
12912 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
12913 for (int iq = 0; iq < ctl->nq; iq++)
12914 fprintf(out, "# $%i = %s [%s]\n", (iq + 5),
12915 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
12916 fprintf(out, "\n");
12917
12918 /* Set geolocation and search radius... */
12919 geo2cart(0, ctl->stat_lon, ctl->stat_lat, x0);
12920 rmax2 = SQR(ctl->stat_r);
12921 }
12922
12923 /* Set time interval for output... */
12924 const double t0 = t - 0.5 * ctl->dt_mod;
12925 const double t1 = t + 0.5 * ctl->dt_mod;
12926
12927 /* Loop over air parcels... */
12928 for (int ip = 0; ip < atm->np; ip++) {
12929
12930 /* Check time... */
12931 if (atm->time[ip] < t0 || atm->time[ip] > t1)
12932 continue;
12933
12934 /* Check time range for station output... */
12935 if (atm->time[ip] < ctl->stat_t0 || atm->time[ip] > ctl->stat_t1)
12936 continue;
12937
12938 /* Check station flag... */
12939 if (ctl->qnt_stat >= 0)
12940 if ((int) atm->q[ctl->qnt_stat][ip])
12941 continue;
12942
12943 /* Get Cartesian coordinates... */
12944 geo2cart(0, atm->lon[ip], atm->lat[ip], x1);
12945
12946 /* Check horizontal distance... */
12947 if (DIST2(x0, x1) > rmax2)
12948 continue;
12949
12950 /* Set station flag... */
12951 if (ctl->qnt_stat >= 0)
12952 atm->q[ctl->qnt_stat][ip] = 1;
12953
12954 /* Write data... */
12955 fprintf(out, "%.2f %g %g %g",
12956 atm->time[ip], Z(atm->p[ip]), atm->lon[ip], atm->lat[ip]);
12957 for (int iq = 0; iq < ctl->nq; iq++) {
12958 fprintf(out, " ");
12959 fprintf(out, ctl->qnt_format[iq], atm->q[iq][ip]);
12960 }
12961 fprintf(out, "\n");
12962 }
12963
12964 /* Close file... */
12965 if (t == ctl->t_stop)
12966 fclose(out);
12967}
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 12971 of file mptrac.c.

12975 {
12976
12977 FILE *out;
12978
12979 /* Set timer... */
12980 SELECT_TIMER("WRITE_VTK", "OUTPUT", NVTX_WRITE);
12981
12982 /* Write info... */
12983 LOG(1, "Write VTK data: %s", filename);
12984
12985 /* Set time interval for output... */
12986 const double t0 = t - 0.5 * ctl->dt_mod;
12987 const double t1 = t + 0.5 * ctl->dt_mod;
12988
12989 /* Create file... */
12990 if (!(out = fopen(filename, "w")))
12991 ERRMSG("Cannot create file!");
12992
12993 /* Count data points... */
12994 int np = 0;
12995 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
12996 if (atm->time[ip] < t0 || atm->time[ip] > t1)
12997 continue;
12998 np++;
12999 }
13000
13001 /* Write header... */
13002 fprintf(out,
13003 "# vtk DataFile Version 3.0\n"
13004 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
13005
13006 /* Write point coordinates... */
13007 fprintf(out, "POINTS %d float\n", np);
13008 if (ctl->vtk_sphere) {
13009 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
13010 if (atm->time[ip] < t0 || atm->time[ip] > t1)
13011 continue;
13012 const double radius = (RE + Z(atm->p[ip]) * ctl->vtk_scale
13013 + ctl->vtk_offset) / RE;
13014 const double coslat = cos(DEG2RAD(atm->lat[ip]));
13015 const double x = radius * coslat * cos(DEG2RAD(atm->lon[ip]));
13016 const double y = radius * coslat * sin(DEG2RAD(atm->lon[ip]));
13017 const double z = radius * sin(DEG2RAD(atm->lat[ip]));
13018 fprintf(out, "%g %g %g\n", x, y, z);
13019 }
13020 } else
13021 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
13022 if (atm->time[ip] < t0 || atm->time[ip] > t1)
13023 continue;
13024 fprintf(out, "%g %g %g\n", atm->lon[ip], atm->lat[ip],
13025 Z(atm->p[ip]) * ctl->vtk_scale + ctl->vtk_offset);
13026 }
13027
13028 /* Write point data... */
13029 fprintf(out, "POINT_DATA %d\n", np);
13030 for (int iq = 0; iq < ctl->nq; iq++) {
13031 fprintf(out, "SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
13032 ctl->qnt_name[iq]);
13033 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
13034 if (atm->time[ip] < t0 || atm->time[ip] > t1)
13035 continue;
13036 fprintf(out, "%g\n", atm->q[iq][ip]);
13037 }
13038 }
13039
13040 /* Close file... */
13041 fclose(out);
13042}

◆ dd_atm2particles()

void dd_atm2particles ( atm_t atm,
particle_t particles,
ctl_t ctl,
int *  nparticles,
cache_t cache,
int  rank 
)

Converts atmospheric data to particle data.

The dd_atm2particles function converts data from an atmospheric data structure (atm_t) to an array of particle structures (particle_t). It iterates over each particle and assigns corresponding values from the atmospheric data based on control parameters (ctl_t).

Parameters
atmA pointer to an atm_t structure containing atmospheric data.
particlesAn array of particle_t structures to be populated with data.
ctlA ctl_t structure containing control parameters.

The function performs the following steps:

  • Iterates through each particle index up to the number of particles (np) in atm.
  • Assigns time, longitude, latitude, and pressure values from atm to each particle.
  • Copies additional quantities (q) from atm to each particle based on the number of quantities (nq) in ctl.
Note
This function assumes that the particles array is pre-allocated with sufficient memory to hold np particles. The ctl structure must be properly initialized.
Author
Jan Clemens

◆ dd_particles2atm()

void dd_particles2atm ( atm_t atm,
particle_t particles,
ctl_t ctl,
int *  nparticles,
cache_t cache 
)

Converts particle data to atmospheric data.

The dd_particles2atm function converts data from an array of particle structures (particle_t) to an atmospheric data structure (atm_t). It updates the atmospheric data with values from the particles and modifies the cache with control parameters (ctl_t).

Parameters
atmA pointer to an atm_t structure containing atmospheric data to be updated.
particlesAn array of particle_t structures from which data will be taken.
ctlA pointer to a ctl_t structure containing control parameters.
nparticlesA pointer to an integer representing the number of particles to process.
cacheA pointer to a cache_t structure used for storing intermediate values.

The function performs the following steps:

  • Copies particle data (time, longitude, latitude, pressure, and quantities) into the atmospheric data structure.
  • Updates the cache with a time modification value from the control parameters.
  • Increases the particle count in the atmospheric data structure by the number of particles processed.
Note
This function assumes that the particles array and atm structure are properly initialized. It also assumes that the cache is pre-allocated and accessible. The function uses OpenACC directives for parallel processing.
Author
Jan Clemens