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_sort.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 an 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 meteo struct. More...
 
#define ECC_READ_3D(variable, level, target, scaling_factor, found_flag)
 Writes 3D data from a grib message into the meteo 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 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 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_sz3 (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 3-D float array using the SZ3 library. 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 193 of file mptrac.h.

◆ CPD

#define CPD   1003.5

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

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

◆ G0

#define G0   9.80665

Standard gravity [m/s^2].

Definition at line 208 of file mptrac.h.

◆ H0

#define H0   7.0

Scale height [km].

Definition at line 213 of file mptrac.h.

◆ LV

#define LV   2501000.

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

Definition at line 218 of file mptrac.h.

◆ KARMAN

#define KARMAN   0.40

Karman's constant.

Definition at line 223 of file mptrac.h.

◆ KB

#define KB   1.3806504e-23

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

Definition at line 228 of file mptrac.h.

◆ MA

#define MA   28.9644

Molar mass of dry air [g/mol].

Definition at line 233 of file mptrac.h.

◆ MH2O

#define MH2O   18.01528

Molar mass of water vapor [g/mol].

Definition at line 238 of file mptrac.h.

◆ MO3

#define MO3   48.00

Molar mass of ozone [g/mol].

Definition at line 243 of file mptrac.h.

◆ P0

#define P0   1013.25

Standard pressure [hPa].

Definition at line 248 of file mptrac.h.

◆ RA

#define RA   (1e3 * RI / MA)

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

Definition at line 253 of file mptrac.h.

◆ RE

#define RE   6367.421

Mean radius of Earth [km].

Definition at line 258 of file mptrac.h.

◆ RI

#define RI   8.3144598

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

Definition at line 263 of file mptrac.h.

◆ T0

#define T0   273.15

Standard temperature [K].

Definition at line 268 of file mptrac.h.

◆ DD_NPOLE

#define DD_NPOLE   -2

Constants indicating the North pole [-].

Definition at line 273 of file mptrac.h.

◆ DD_SPOLE

#define DD_SPOLE   -3

Constants indicating the South pole [-].

Definition at line 279 of file mptrac.h.

◆ EP

#define EP   140

Maximum number of pressure levels for meteo data.

Definition at line 288 of file mptrac.h.

◆ EX

#define EX   1444

Maximum number of longitudes for meteo data.

Definition at line 293 of file mptrac.h.

◆ EY

#define EY   724

Maximum number of latitudes for meteo data.

Definition at line 298 of file mptrac.h.

◆ EP_GLOB

#define EP_GLOB   150

Maximum number of pressure levels for meteo data.

Definition at line 303 of file mptrac.h.

◆ EX_GLOB

#define EX_GLOB   1202

Maximum number of global longitudes for meteo data.

Definition at line 308 of file mptrac.h.

◆ EY_GLOB

#define EY_GLOB   602

Maximum number of global latitudes for meteo data.

Definition at line 313 of file mptrac.h.

◆ LEN

#define LEN   5000

Maximum length of ASCII data lines.

Definition at line 318 of file mptrac.h.

◆ METVAR

#define METVAR   13

Number of 3-D meteorological variables.

Definition at line 323 of file mptrac.h.

◆ NP

#define NP   10000000

Maximum number of atmospheric data points.

Definition at line 328 of file mptrac.h.

◆ NQ

#define NQ   15

Maximum number of quantities per data point.

Definition at line 333 of file mptrac.h.

◆ NCSI

#define NCSI   1000000

Maximum number of data points for CSI calculation.

Definition at line 338 of file mptrac.h.

◆ NENS

#define NENS   2000

Maximum number of data points for ensemble analysis.

Definition at line 343 of file mptrac.h.

◆ NOBS

#define NOBS   10000000

Maximum number of observation data points.

Definition at line 348 of file mptrac.h.

◆ NTHREADS

#define NTHREADS   512

Maximum number of OpenMP threads.

Definition at line 353 of file mptrac.h.

◆ CY

#define CY   250

Maximum number of latitudes for climatological data.

Definition at line 358 of file mptrac.h.

◆ CO3

#define CO3   30

Maximum number of total column ozone data for climatological data.

Definition at line 363 of file mptrac.h.

◆ CP

#define CP   70

Maximum number of pressure levels for climatological data.

Definition at line 368 of file mptrac.h.

◆ CSZA

#define CSZA   50

Maximum number of solar zenith angles for climatological data.

Definition at line 373 of file mptrac.h.

◆ CT

#define CT   12

Maximum number of time steps for climatological data.

Definition at line 378 of file mptrac.h.

◆ CTS

#define CTS   1000

Maximum number of data points of climatological time series.

Definition at line 383 of file mptrac.h.

◆ DD_NPART

#define DD_NPART   100000

Maximum number of particles to send and recieve.

Definition at line 388 of file mptrac.h.

◆ DD_NNMAX

#define DD_NNMAX   26

Maximum number of neighbours to communicate with.

Definition at line 393 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 426 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 449 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 468 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 493 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 517 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 538 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 555 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 580 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:258
#define DEG2RAD(deg)
Converts degrees to radians.
Definition: mptrac.h:555

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 602 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 620 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 639 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 655 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 671 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 687 of file mptrac.h.

◆ ECC

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

Execute an ECCODES command and check for errors.

This macro executes an 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 701 of file mptrac.h.

◆ ECC_READ_2D

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

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

This macro writes 2-D data from a one-dimensional grib message into the corresponding 2-D variable in the meteo struct.

Parameters
variableName of the current meteorological variable
targetPointer to the 2-D array in the meteo 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 720 of file mptrac.h.

◆ ECC_READ_3D

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

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

This macro writes 3D data from a one-dimensional grib message into the corresponding 3D variable in the meteo struct.

Parameters
variableName of the current meteorological variable.
levelIndex of the vertical level in the 3D array where the data should be stored.
targetPointer to the 3D array in the meteo struct where the data will be stored.
scaling_factorScaling factor to apply to the data.
found_flagCounter to store, how many messages containing data for this variable have been read.
Author
Nils Nobre Wittwer

Definition at line 743 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 768 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 786 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 806 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 821 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:1680

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 835 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:1626

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 852 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 871 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 925 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:253
#define G0
Standard gravity [m/s^2].
Definition: mptrac.h:208

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 979 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 998 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 1025 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 1039 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 1126 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 1141 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 1155 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:318

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 1184 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:1995

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 1214 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 1242 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 1265 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 1289 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 1312 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 1334 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 1351 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 1371 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 1398 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 1428 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 1452 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 1476 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 1503 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 1520 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 1550 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 1580 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 1605 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 1624 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 1647 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 1668 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 1681 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 1695 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:1503
#define T0
Standard temperature [K].
Definition: mptrac.h:268

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 1719 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 1744 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 1768 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 1797 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:2028

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 1818 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 1843 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 1865 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:1843
#define MA
Molar mass of dry air [g/mol].
Definition: mptrac.h:233
#define RI
Ideal gas constant [J/(mol K)].
Definition: mptrac.h:263

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 1896 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:1768

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

◆ LOGLEV

#define LOGLEV   2

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

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

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 1958 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 1995 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 2028 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 2063 of file mptrac.h.

◆ NTIMER

#define NTIMER   100

Maximum number of timers.

Definition at line 2072 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 2087 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 2108 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 2127 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 2142 of file mptrac.h.

◆ NVTX_PUSH

#define NVTX_PUSH (   range_title,
  range_color 
)    {}

Definition at line 2234 of file mptrac.h.

◆ NVTX_POP

#define NVTX_POP   {}

Definition at line 2235 of file mptrac.h.

Function Documentation

◆ 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 = sqrt(DOTP(x, x));
81
82 *lat = RAD2DEG(asin(x[2] / radius));
83 *lon = RAD2DEG(atan2(x[1], x[0]));
84 *z = radius - RE;
85}
#define DOTP(a, b)
Calculate the dot product of two vectors.
Definition: mptrac.h:687
#define RAD2DEG(rad)
Converts radians to degrees.
Definition: mptrac.h:1520

◆ 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.
Author
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 /* Check beta... */
104 if (ctl->oh_chem_beta <= 0)
105 return oh;
106
107 /* Apply diurnal correction... */
108 const double sza = sza_calc(t, lon, lat);
109 const double denom = (sza <= sza_thresh) ? cos(sza) : cos_sza_thresh;
110 return oh * exp(-ctl->oh_chem_beta / denom);
111}
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:406
double sza_calc(const double sec, const double lon, const double lat)
Calculates the solar zenith angle.
Definition: mptrac.c:10840
clim_zm_t oh
OH zonal means.
Definition: mptrac.h:3507
double oh_chem_beta
Beta parameter for diurnal variablity of OH.
Definition: mptrac.h:2957
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.
Author
Lars Hoffmann
Mingzhao Liu

Definition at line 115 of file mptrac.c.

117 {
118
119 /* Set SZA threshold... */
120 const double sza_thresh = DEG2RAD(85.), cos_sza_thresh = cos(sza_thresh);
121
122 /* Loop over climatology data points... */
123 for (int it = 0; it < clim->oh.ntime; it++)
124 for (int iz = 0; iz < clim->oh.np; iz++)
125 for (int iy = 0; iy < clim->oh.nlat; iy++) {
126
127 /* Init... */
128 int n = 0;
129 double sum = 0;
130
131 /* Integrate day/night correction factor over longitude... */
132 for (double lon = -180; lon < 180; lon += 1.0) {
133 const double sza =
134 sza_calc(clim->oh.time[it], lon, clim->oh.lat[iy]);
135 const double denom =
136 (sza <= sza_thresh) ? cos(sza) : cos_sza_thresh;
137 sum += exp(-ctl->oh_chem_beta / denom);
138 n++;
139 }
140
141 /* Apply scaling factor to OH data... */
142 clim->oh.vmr[it][iz][iy] /= (sum / (double) n);
143 }
144}
double time[CT]
Time [s].
Definition: mptrac.h:3463
int np
Number of pressure levels.
Definition: mptrac.h:3460
double vmr[CT][CP][CY]
Volume mixing ratio [ppv].
Definition: mptrac.h:3472
int ntime
Number of timesteps.
Definition: mptrac.h:3454
int nlat
Number of latitudes.
Definition: mptrac.h:3457
double lat[CY]
Latitude [deg].
Definition: mptrac.h:3466
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.
Author
Lars Hoffmann
Mingzhao Liu

Definition at line 148 of file mptrac.c.

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

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

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

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

390 {
391
392 /* Interpolate... */
393 if (t <= ts->time[0])
394 return ts->vmr[0];
395 else if (t >= ts->time[ts->ntime - 1])
396 return ts->vmr[ts->ntime - 1];
397 else {
398 const int idx = locate_irr(ts->time, ts->ntime, t);
399 return LIN(ts->time[idx], ts->vmr[idx],
400 ts->time[idx + 1], ts->vmr[idx + 1], t);
401 }
402}
double vmr[CTS]
Volume mixing ratio [ppv].
Definition: mptrac.h:3440
double time[CTS]
Time [s].
Definition: mptrac.h:3437
int ntime
Number of timesteps.
Definition: mptrac.h:3434
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 406 of file mptrac.c.

410 {
411
412 /* Get seconds since begin of year... */
413 double sec = FMOD(t, 365.25 * 86400.);
414 while (sec < 0)
415 sec += 365.25 * 86400.;
416
417 /* Check pressure range... */
418 double p_help = p;
419 if (p < zm->p[zm->np - 1])
420 p_help = zm->p[zm->np - 1];
421 else if (p > zm->p[0])
422 p_help = zm->p[0];
423
424 /* Check latitude range... */
425 double lat_help = lat;
426 if (lat < zm->lat[0])
427 lat_help = zm->lat[0];
428 else if (lat > zm->lat[zm->nlat - 1])
429 lat_help = zm->lat[zm->nlat - 1];
430
431 /* Get indices... */
432 const int isec = locate_irr(zm->time, zm->ntime, sec);
433 const int ilat = locate_reg(zm->lat, zm->nlat, lat_help);
434 const int ip = locate_irr(zm->p, zm->np, p_help);
435
436 /* Interpolate climatology data... */
437 const double aux00 = LIN(zm->p[ip], zm->vmr[isec][ip][ilat],
438 zm->p[ip + 1], zm->vmr[isec][ip + 1][ilat],
439 p_help);
440 const double aux01 = LIN(zm->p[ip], zm->vmr[isec][ip][ilat + 1],
441 zm->p[ip + 1], zm->vmr[isec][ip + 1][ilat + 1],
442 p_help);
443 const double aux10 = LIN(zm->p[ip], zm->vmr[isec + 1][ip][ilat],
444 zm->p[ip + 1], zm->vmr[isec + 1][ip + 1][ilat],
445 p_help);
446 const double aux11 = LIN(zm->p[ip], zm->vmr[isec + 1][ip][ilat + 1],
447 zm->p[ip + 1], zm->vmr[isec + 1][ip + 1][ilat + 1],
448 p_help);
449 const double aux0 =
450 LIN(zm->lat[ilat], aux00, zm->lat[ilat + 1], aux01, lat_help);
451 const double aux1 =
452 LIN(zm->lat[ilat], aux10, zm->lat[ilat + 1], aux11, lat_help);
453 const double aux = LIN(zm->time[isec], aux0, zm->time[isec + 1], aux1, sec);
454 return MAX(aux, 0.0);
455}
double p[CP]
Pressure [hPa].
Definition: mptrac.h:3469
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 673 of file mptrac.c.

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

◆ compress_sz3()

void compress_sz3 ( 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 3-D float array using the SZ3 library.

This function either compresses a 3-D floating-point array and writes it to a file stream, or reads compressed SZ3 data from a file stream and decompresses it into the provided array. The SZ3 error bound can be specified either by relative precision (bits) or absolute tolerance.

Parameters
varnameName of the variable (used for logging).
arrayPointer to the 3-D float array (input for compression, output for decompression).
nxSize of the first dimension.
nySize of the second dimension.
nzSize of the third dimension.
precisionRelative precision in bits (used if > 0; tolerance must be 0).
toleranceAbsolute error bound (used if > 0; precision must be 0).
decompressNon-zero to decompress data from inout into array; zero to compress array into inout.
inoutFile stream for reading/writing compressed data.
Note
Exactly one of precision or tolerance must be set to a positive value.
The SZ3 data type is fixed to SZ_FLOAT for this function.
Exceptions
ERRMSGif input parameters are invalid, memory allocation fails, compression/decompression fails, or file I/O errors occur.
See also
SZ_compress_args
SZ_decompress
Author
Lars Hoffmann

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

1008 {
1009
1010 const int
1011 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1012 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1013
1014 /* Get day of year... */
1015 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
1016 *doy = d0l[mon - 1] + day - 1;
1017 else
1018 *doy = d0[mon - 1] + day - 1;
1019}

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

1027 {
1028
1029 const int
1030 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1031 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1032
1033 int i;
1034
1035 /* Get month and day... */
1036 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
1037 for (i = 11; i > 0; i--)
1038 if (d0l[i] <= doy)
1039 break;
1040 *mon = i + 1;
1041 *day = doy - d0l[i] + 1;
1042 } else {
1043 for (i = 11; i > 0; i--)
1044 if (d0[i] <= doy)
1045 break;
1046 *mon = i + 1;
1047 *day = doy - d0[i] + 1;
1048 }
1049}

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

1056 {
1057
1058 double data[2 * EX];
1059
1060 /* Check size... */
1061 if (n > EX)
1062 ERRMSG("Too many data points!");
1063
1064 /* Allocate... */
1065 gsl_fft_complex_wavetable *wavetable =
1066 gsl_fft_complex_wavetable_alloc((size_t) n);
1067 gsl_fft_complex_workspace *workspace =
1068 gsl_fft_complex_workspace_alloc((size_t) n);
1069
1070 /* Set data (real, complex)... */
1071 for (int i = 0; i < n; i++) {
1072 data[2 * i] = fcReal[i];
1073 data[2 * i + 1] = fcImag[i];
1074 }
1075
1076 /* Calculate FFT... */
1077 gsl_fft_complex_forward(data, 1, (size_t) n, wavetable, workspace);
1078
1079 /* Copy data... */
1080 for (int i = 0; i < n; i++) {
1081 fcReal[i] = data[2 * i];
1082 fcImag[i] = data[2 * i + 1];
1083 }
1084
1085 /* Free... */
1086 gsl_fft_complex_wavetable_free(wavetable);
1087 gsl_fft_complex_workspace_free(workspace);
1088}
#define EX
Maximum number of longitudes for meteo data.
Definition: mptrac.h:293

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

1096 {
1097
1098 const double radius = z + RE;
1099 const double latrad = DEG2RAD(lat);
1100 const double lonrad = DEG2RAD(lon);
1101 const double coslat = cos(latrad);
1102
1103 x[0] = radius * coslat * cos(lonrad);
1104 x[1] = radius * coslat * sin(lonrad);
1105 x[2] = radius * sin(latrad);
1106}

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

1116 {
1117
1118 char repl[LEN];
1119
1120 double t6, r;
1121
1122 int year, mon, day, hour, min, sec;
1123
1124 /* Round time to fixed intervals... */
1125 if (direct == -1)
1126 t6 = floor(t / dt_met) * dt_met;
1127 else
1128 t6 = ceil(t / dt_met) * dt_met;
1129
1130 /* Decode time... */
1131 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
1132
1133 /* Set filename of MPTRAC meteo files... */
1134 if (ctl->met_clams == 0) {
1135 if (ctl->met_type == 0)
1136 sprintf(filename, "%s_YYYY_MM_DD_HH.nc", metbase);
1137 else if (ctl->met_type == 1)
1138 sprintf(filename, "%s_YYYY_MM_DD_HH.bin", metbase);
1139 else if (ctl->met_type == 2)
1140 sprintf(filename, "%s_YYYY_MM_DD_HH.pck", metbase);
1141 else if (ctl->met_type == 3)
1142 sprintf(filename, "%s_YYYY_MM_DD_HH.zfp", metbase);
1143 else if (ctl->met_type == 4)
1144 sprintf(filename, "%s_YYYY_MM_DD_HH.zstd", metbase);
1145 else if (ctl->met_type == 5)
1146 sprintf(filename, "%s_YYYY_MM_DD_HH.cms", metbase);
1147 else if (ctl->met_type == 7)
1148 sprintf(filename, "%s_YYYY_MM_DD_HH.sz3", metbase);
1149 sprintf(repl, "%d", year);
1150 get_met_replace(filename, "YYYY", repl);
1151 sprintf(repl, "%02d", mon);
1152 get_met_replace(filename, "MM", repl);
1153 sprintf(repl, "%02d", day);
1154 get_met_replace(filename, "DD", repl);
1155 sprintf(repl, "%02d", hour);
1156 get_met_replace(filename, "HH", repl);
1157 }
1158
1159 /* Set filename of CLaMS meteo files... */
1160 else {
1161 sprintf(filename, "%s_YYMMDDHH.nc", metbase);
1162 sprintf(repl, "%d", year);
1163 get_met_replace(filename, "YYYY", repl);
1164 sprintf(repl, "%02d", year % 100);
1165 get_met_replace(filename, "YY", repl);
1166 sprintf(repl, "%02d", mon);
1167 get_met_replace(filename, "MM", repl);
1168 sprintf(repl, "%02d", day);
1169 get_met_replace(filename, "DD", repl);
1170 sprintf(repl, "%02d", hour);
1171 get_met_replace(filename, "HH", repl);
1172 }
1173}
void get_met_replace(char *orig, char *search, char *repl)
Replaces occurrences of a substring in a string with another substring.
Definition: mptrac.c:1177
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:1804
int met_clams
Read MPTRAC or CLaMS meteo data (0=MPTRAC, 1=CLaMS).
Definition: mptrac.h:2586
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:2583
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 1177 of file mptrac.c.

1180 {
1181
1182 char buffer[LEN];
1183
1184 /* Iterate... */
1185 for (int i = 0; i < 3; i++) {
1186
1187 /* Replace sub-string... */
1188 char *ch;
1189 if (!(ch = strstr(orig, search)))
1190 return;
1191 strncpy(buffer, orig, (size_t) (ch - orig));
1192 buffer[ch - orig] = 0;
1193 sprintf(buffer + (ch - orig), "%s%s", repl, ch + strlen(search));
1194 orig[0] = 0;
1195 strcpy(orig, buffer);
1196 }
1197}

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

1216 {
1217
1219
1220 ctl->met_tropo = met_tropo;
1221 read_met_tropo(ctl, clim, met);
1222#pragma omp parallel for default(shared) private(ci,cw)
1223 for (int ix = 0; ix < nx; ix++)
1224 for (int iy = 0; iy < ny; iy++) {
1225 intpol_met_space_2d(met, met->pt, lons[ix], lats[iy],
1226 &pt[iy * nx + ix], ci, cw, 1);
1227 intpol_met_space_2d(met, met->ps, lons[ix], lats[iy],
1228 &ps[iy * nx + ix], ci, cw, 0);
1229 intpol_met_space_2d(met, met->zs, lons[ix], lats[iy],
1230 &zs[iy * nx + ix], ci, cw, 0);
1231 intpol_met_space_3d(met, met->z, pt[iy * nx + ix], lons[ix],
1232 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
1233 intpol_met_space_3d(met, met->t, pt[iy * nx + ix], lons[ix],
1234 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
1235 intpol_met_space_3d(met, met->h2o, pt[iy * nx + ix], lons[ix],
1236 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
1237 intpol_met_space_3d(met, met->o3, pt[iy * nx + ix], lons[ix],
1238 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
1239 }
1240}
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:1568
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:10394
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:1443
#define INTPOL_INIT
Initialize arrays for interpolation.
Definition: mptrac.h:821
int met_tropo
Tropopause definition (0=none, 1=clim, 2=cold point, 3=WMO_1st, 4=WMO_2nd, 5=dynamical).
Definition: mptrac.h:2717
float h2o[EX][EY][EP]
Water vapor volume mixing ratio [1].
Definition: mptrac.h:3678
float ps[EX][EY]
Surface pressure [hPa].
Definition: mptrac.h:3588
float zs[EX][EY]
Surface geopotential height [km].
Definition: mptrac.h:3594
float o3[EX][EY][EP]
Ozone volume mixing ratio [1].
Definition: mptrac.h:3681
float t[EX][EY][EP]
Temperature [K].
Definition: mptrac.h:3663
float pt[EX][EY]
Tropopause pressure [hPa].
Definition: mptrac.h:3621
float z[EX][EY][EP]
Geopotential height [km].
Definition: mptrac.h:3660
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 1244 of file mptrac.c.

1252 {
1253
1254 /* Check longitude... */
1255 *lon2 = FMOD(lon, 360.);
1256 if (*lon2 < lons[0])
1257 *lon2 += 360;
1258 else if (*lon2 > lons[nlon - 1])
1259 *lon2 -= 360;
1260
1261 /* Check latitude... */
1262 *lat2 = lat;
1263 if (lats[0] < lats[nlat - 1])
1264 *lat2 = MIN(MAX(*lat2, lats[0]), lats[nlat - 1]);
1265 else
1266 *lat2 = MIN(MAX(*lat2, lats[nlat - 1]), lats[0]);
1267}

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

1285 {
1286
1287 if (init) {
1288
1289 /* Check longitude and latitude... */
1290 double lon2, lat2;
1291 intpol_check_lon_lat(met0->lon, met0->nx, met0->lat, met0->ny, lon, lat,
1292 &lon2, &lat2);
1293
1294 /* Get horizontal indizes... */
1295 ci[0] = locate_irr(met0->lon, met0->nx, lon2);
1296 ci[1] = locate_irr(met0->lat, met0->ny, lat2);
1297
1298 /* Locate the vertical indizes for each edge of the column... */
1299 int ind[2][4];
1300 locate_vert(heights0, met0->npl, ci[0], ci[1], height, ind[0]);
1301 locate_vert(heights1, met1->npl, ci[0], ci[1], height, ind[1]);
1302
1303 /* Find minimum and maximum indizes... */
1304 ci[2] = ind[0][0];
1305 int k_max = ind[0][0];
1306 for (int i = 0; i < 2; i++)
1307 for (int j = 0; j < 4; j++) {
1308 if (ci[2] > ind[i][j])
1309 ci[2] = ind[i][j];
1310 if (k_max < ind[i][j])
1311 k_max = ind[i][j];
1312 }
1313
1314 /* Get weighting factors for time, longitude and latitude... */
1315 cw[3] = (ts - met0->time) / (met1->time - met0->time);
1316 cw[0] = (lon2 - met0->lon[ci[0]]) /
1317 (met0->lon[ci[0] + 1] - met0->lon[ci[0]]);
1318 cw[1] = (lat2 - met0->lat[ci[1]]) /
1319 (met0->lat[ci[1] + 1] - met0->lat[ci[1]]);
1320
1321 /* Interpolate in time at the lowest level... */
1322 double height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
1323 - heights0[ci[0]][ci[1]][ci[2]])
1324 + heights0[ci[0]][ci[1]][ci[2]];
1325 double height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
1326 - heights0[ci[0]][ci[1] + 1][ci[2]])
1327 + heights0[ci[0]][ci[1] + 1][ci[2]];
1328 double height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
1329 - heights0[ci[0] + 1][ci[1]][ci[2]])
1330 + heights0[ci[0] + 1][ci[1]][ci[2]];
1331 double height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
1332 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
1333 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
1334
1335 /* Interpolate in latitude direction... */
1336 double height0 = cw[1] * (height01 - height00) + height00;
1337 double height1 = cw[1] * (height11 - height10) + height10;
1338
1339 /* Interpolate in longitude direction... */
1340 double height_bot = cw[0] * (height1 - height0) + height0;
1341
1342 /* Interpolate in time at the upper level... */
1343 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
1344 - heights0[ci[0]][ci[1]][ci[2] + 1])
1345 + heights0[ci[0]][ci[1]][ci[2] + 1];
1346 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
1347 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
1348 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
1349 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
1350 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
1351 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
1352 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1353 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1354 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1355
1356 /* Interpolate in latitude direction... */
1357 height0 = cw[1] * (height01 - height00) + height00;
1358 height1 = cw[1] * (height11 - height10) + height10;
1359
1360 /* Interpolate in longitude direction... */
1361 double height_top = cw[0] * (height1 - height0) + height0;
1362
1363 /* Search at higher levels if height is not in box... */
1364 while (((heights0[0][0][0] > heights0[0][0][1]) &&
1365 ((height_bot <= height) || (height_top > height))
1366 && (height_bot >= height) && (ci[2] < k_max))
1367 ||
1368 ((heights0[0][0][0] < heights0[0][0][1]) &&
1369 ((height_bot >= height) || (height_top < height))
1370 && (height_bot <= height) && (ci[2] < k_max))
1371 ) {
1372
1373 ci[2]++;
1374 height_bot = height_top;
1375
1376 /* Interpolate in time at the next level... */
1377 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
1378 - heights0[ci[0]][ci[1]][ci[2] + 1])
1379 + heights0[ci[0]][ci[1]][ci[2] + 1];
1380 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
1381 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
1382 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
1383 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
1384 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
1385 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
1386 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1387 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1388 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1389
1390 /* Interpolate in latitude direction... */
1391 height0 = cw[1] * (height01 - height00) + height00;
1392 height1 = cw[1] * (height11 - height10) + height10;
1393
1394 /* Interpolate in longitude direction... */
1395 height_top = cw[0] * (height1 - height0) + height0;
1396 }
1397
1398 /* Get vertical weighting factors... */
1399 cw[2] = (height - height_bot)
1400 / (height_top - height_bot);
1401 }
1402
1403 /* Calculate the needed array values... */
1404 const double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
1405 - array0[ci[0]][ci[1]][ci[2]])
1406 + array0[ci[0]][ci[1]][ci[2]];
1407 const double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
1408 - array0[ci[0] + 1][ci[1]][ci[2]])
1409 + array0[ci[0] + 1][ci[1]][ci[2]];
1410 const double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
1411 - array0[ci[0]][ci[1] + 1][ci[2]])
1412 + array0[ci[0]][ci[1] + 1][ci[2]];
1413 const double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
1414 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
1415 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
1416 const double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
1417 - array0[ci[0]][ci[1]][ci[2] + 1])
1418 + array0[ci[0]][ci[1]][ci[2] + 1];
1419 const double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
1420 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
1421 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
1422 const double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
1423 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
1424 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
1425 const double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1426 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1427 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1428
1429 const double array00 = cw[0] * (array100 - array000) + array000;
1430 const double array10 = cw[0] * (array110 - array010) + array010;
1431 const double array01 = cw[0] * (array101 - array001) + array001;
1432 const double array11 = cw[0] * (array111 - array011) + array011;
1433
1434 const double aux0 = cw[1] * (array10 - array00) + array00;
1435 const double aux1 = cw[1] * (array11 - array01) + array01;
1436
1437 /* Interpolate vertically... */
1438 *var = cw[2] * (aux1 - aux0) + aux0;
1439}
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:2174
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:1244
int nx
Number of longitudes.
Definition: mptrac.h:3548
int ny
Number of latitudes.
Definition: mptrac.h:3551
double lon[EX]
Longitudes [deg].
Definition: mptrac.h:3567
int npl
Number of model levels.
Definition: mptrac.h:3557
double time
Time [s].
Definition: mptrac.h:3545
double lat[EY]
Latitudes [deg].
Definition: mptrac.h:3574
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 1443 of file mptrac.c.

1452 {
1453
1454 /* Initialize interpolation... */
1455 if (init) {
1456
1457 /* Check longitude and latitude... */
1458 double lon2, lat2;
1459 intpol_check_lon_lat(met->lon, met->nx, met->lat, met->ny, lon, lat,
1460 &lon2, &lat2);
1461
1462 /* Get interpolation indices... */
1463 ci[0] = locate_irr(met->p, met->np, p);
1464 ci[1] = locate_reg(met->lon, met->nx, lon2);
1465 ci[2] = locate_irr(met->lat, met->ny, lat2);
1466
1467 /* Get interpolation weights... */
1468 cw[0] = (met->p[ci[0] + 1] - p)
1469 / (met->p[ci[0] + 1] - met->p[ci[0]]);
1470 cw[1] = (met->lon[ci[1] + 1] - lon2)
1471 / (met->lon[ci[1] + 1] - met->lon[ci[1]]);
1472 cw[2] = (met->lat[ci[2] + 1] - lat2)
1473 / (met->lat[ci[2] + 1] - met->lat[ci[2]]);
1474 }
1475
1476 /* Interpolate vertically... */
1477 const double aux00 =
1478 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
1479 + array[ci[1]][ci[2]][ci[0] + 1];
1480 const double aux01 =
1481 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
1482 array[ci[1]][ci[2] + 1][ci[0] + 1])
1483 + array[ci[1]][ci[2] + 1][ci[0] + 1];
1484 const double aux10 =
1485 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
1486 array[ci[1] + 1][ci[2]][ci[0] + 1])
1487 + array[ci[1] + 1][ci[2]][ci[0] + 1];
1488 const double aux11 =
1489 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
1490 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
1491 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
1492
1493 /* Interpolate horizontally... */
1494 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
1495 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
1496 *var = cw[1] * (aux0 - aux1) + aux1;
1497}
int np
Number of pressure levels.
Definition: mptrac.h:3554
double p[EP]
Pressure levels [hPa].
Definition: mptrac.h:3581
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 1501 of file mptrac.c.

1508 {
1509
1510 /* Check longitude and latitude... */
1511 double lon2, lat2;
1512 intpol_check_lon_lat(met->lon, met->nx, met->lat, met->ny, lon, lat, &lon2,
1513 &lat2);
1514
1515 /* Get horizontal indices... */
1516 const int ix = locate_reg(met->lon, met->nx, lon2);
1517 const int iy = locate_irr(met->lat, met->ny, lat2);
1518
1519 /* Interpolate vertically... */
1520 int iz = locate_irr_float(zs[ix][iy], met->npl, z, 0);
1521 double aux00;
1522 if (z >= zs[ix][iy][iz + 1])
1523 aux00 = array[ix][iy][iz + 1];
1524 else if (z <= zs[ix][iy][iz])
1525 aux00 = array[ix][iy][iz];
1526 else
1527 aux00 = LIN(zs[ix][iy][iz], array[ix][iy][iz],
1528 zs[ix][iy][iz + 1], array[ix][iy][iz + 1], z);
1529
1530 iz = locate_irr_float(zs[ix][iy + 1], met->npl, z, iz);
1531 double aux01;
1532 if (z >= zs[ix][iy + 1][iz + 1])
1533 aux01 = array[ix][iy + 1][iz + 1];
1534 else if (z <= zs[ix][iy + 1][iz])
1535 aux01 = array[ix][iy + 1][iz];
1536 else
1537 aux01 = LIN(zs[ix][iy + 1][iz], array[ix][iy + 1][iz],
1538 zs[ix][iy + 1][iz + 1], array[ix][iy + 1][iz + 1], z);
1539
1540 iz = locate_irr_float(zs[ix + 1][iy], met->npl, z, iz);
1541 double aux10;
1542 if (z >= zs[ix + 1][iy][iz + 1])
1543 aux10 = array[ix + 1][iy][iz + 1];
1544 else if (z <= zs[ix + 1][iy][iz])
1545 aux10 = array[ix + 1][iy][iz];
1546 else
1547 aux10 = LIN(zs[ix + 1][iy][iz], array[ix + 1][iy][iz],
1548 zs[ix + 1][iy][iz + 1], array[ix + 1][iy][iz + 1], z);
1549
1550 iz = locate_irr_float(zs[ix + 1][iy + 1], met->npl, z, iz);
1551 double aux11;
1552 if (z >= zs[ix + 1][iy + 1][iz + 1])
1553 aux11 = array[ix + 1][iy + 1][iz + 1];
1554 else if (z <= zs[ix + 1][iy + 1][iz])
1555 aux11 = array[ix + 1][iy + 1][iz];
1556 else
1557 aux11 = LIN(zs[ix + 1][iy + 1][iz], array[ix + 1][iy + 1][iz],
1558 zs[ix + 1][iy + 1][iz + 1], array[ix + 1][iy + 1][iz + 1], z);
1559
1560 /* Interpolate horizontally... */
1561 const double aux0 = LIN(met->lat[iy], aux00, met->lat[iy + 1], aux01, lat2);
1562 const double aux1 = LIN(met->lat[iy], aux10, met->lat[iy + 1], aux11, lat2);
1563 *var = LIN(met->lon[ix], aux0, met->lon[ix + 1], aux1, lon2);
1564}
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:2121
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 1568 of file mptrac.c.

1576 {
1577
1578 /* Initialize interpolation... */
1579 if (init) {
1580
1581 /* Check longitude and latitude... */
1582 double lon2, lat2;
1583 intpol_check_lon_lat(met->lon, met->nx, met->lat, met->ny, lon, lat,
1584 &lon2, &lat2);
1585
1586 /* Get interpolation indices... */
1587 ci[1] = locate_reg(met->lon, met->nx, lon2);
1588 ci[2] = locate_irr(met->lat, met->ny, lat2);
1589
1590 /* Get interpolation weights... */
1591 cw[1] = (met->lon[ci[1] + 1] - lon2)
1592 / (met->lon[ci[1] + 1] - met->lon[ci[1]]);
1593 cw[2] = (met->lat[ci[2] + 1] - lat2)
1594 / (met->lat[ci[2] + 1] - met->lat[ci[2]]);
1595 }
1596
1597 /* Set variables... */
1598 const double aux00 = array[ci[1]][ci[2]];
1599 const double aux01 = array[ci[1]][ci[2] + 1];
1600 const double aux10 = array[ci[1] + 1][ci[2]];
1601 const double aux11 = array[ci[1] + 1][ci[2] + 1];
1602
1603 /* Interpolate horizontally... */
1604 if (isfinite(aux00) && isfinite(aux01)
1605 && isfinite(aux10) && isfinite(aux11)) {
1606 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
1607 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
1608 *var = cw[1] * (aux0 - aux1) + aux1;
1609 } else {
1610 if (cw[2] < 0.5) {
1611 if (cw[1] < 0.5)
1612 *var = aux11;
1613 else
1614 *var = aux01;
1615 } else {
1616 if (cw[1] < 0.5)
1617 *var = aux10;
1618 else
1619 *var = aux00;
1620 }
1621 }
1622}
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 1626 of file mptrac.c.

1638 {
1639
1640 double var0, var1;
1641
1642 /* Spatial interpolation... */
1643 intpol_met_space_3d(met0, array0, p, lon, lat, &var0, ci, cw, init);
1644 intpol_met_space_3d(met1, array1, p, lon, lat, &var1, ci, cw, 0);
1645
1646 /* Get weighting factor... */
1647 const double wt = (met1->time - ts) / (met1->time - met0->time);
1648
1649 /* Interpolate... */
1650 *var = wt * (var0 - var1) + var1;
1651}
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 1655 of file mptrac.c.

1666 {
1667
1668 double var0, var1;
1669
1670 /* Spatial interpolation... */
1671 intpol_met_space_3d_ml(met0, zs0, array0, p, lon, lat, &var0);
1672 intpol_met_space_3d_ml(met1, zs1, array1, p, lon, lat, &var1);
1673
1674 /* Interpolate... */
1675 *var = LIN(met0->time, var0, met1->time, var1, ts);
1676}
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:1501
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 1680 of file mptrac.c.

1691 {
1692
1693 double var0, var1;
1694
1695 /* Spatial interpolation... */
1696 intpol_met_space_2d(met0, array0, lon, lat, &var0, ci, cw, init);
1697 intpol_met_space_2d(met1, array1, lon, lat, &var1, ci, cw, 0);
1698
1699 /* Get weighting factor... */
1700 const double wt = (met1->time - ts) / (met1->time - met0->time);
1701
1702 /* Interpolate... */
1703 if (isfinite(var0) && isfinite(var1))
1704 *var = wt * (var0 - var1) + var1;
1705 else if (wt < 0.5)
1706 *var = var1;
1707 else
1708 *var = var0;
1709}
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 1713 of file mptrac.c.

1727 {
1728
1729 double mean = 0;
1730
1731 int n = 0;
1732
1733 /* Check longitude and latitude... */
1734 double lon2, lat2;
1735 intpol_check_lon_lat(lons, nlon, lats, nlat, lon, lat, &lon2, &lat2);
1736
1737 /* Get indices... */
1738 const int ix = locate_reg(lons, (int) nlon, lon2);
1739 const int iy = locate_irr(lats, (int) nlat, lat2);
1740
1741 /* Calculate standard deviation... */
1742 *sigma = 0;
1743 for (int dx = 0; dx < 2; dx++)
1744 for (int dy = 0; dy < 2; dy++) {
1745 if (isfinite(array0[ix + dx][iy + dy])) {
1746 mean += array0[ix + dx][iy + dy];
1747 *sigma += SQR(array0[ix + dx][iy + dy]);
1748 n++;
1749 }
1750 if (isfinite(array1[ix + dx][iy + dy])) {
1751 mean += array1[ix + dx][iy + dy];
1752 *sigma += SQR(array1[ix + dx][iy + dy]);
1753 n++;
1754 }
1755 }
1756 if (n > 0)
1757 *sigma = sqrt(MAX(*sigma / n - SQR(mean / n), 0.0));
1758
1759 /* Linear interpolation... */
1760 if (method == 1 && isfinite(array0[ix][iy])
1761 && isfinite(array0[ix][iy + 1])
1762 && isfinite(array0[ix + 1][iy])
1763 && isfinite(array0[ix + 1][iy + 1])
1764 && isfinite(array1[ix][iy])
1765 && isfinite(array1[ix][iy + 1])
1766 && isfinite(array1[ix + 1][iy])
1767 && isfinite(array1[ix + 1][iy + 1])) {
1768
1769 const double aux00 = LIN(lons[ix], array0[ix][iy],
1770 lons[ix + 1], array0[ix + 1][iy], lon2);
1771 const double aux01 = LIN(lons[ix], array0[ix][iy + 1],
1772 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
1773 const double aux0 = LIN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
1774
1775 const double aux10 = LIN(lons[ix], array1[ix][iy],
1776 lons[ix + 1], array1[ix + 1][iy], lon2);
1777 const double aux11 = LIN(lons[ix], array1[ix][iy + 1],
1778 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
1779 const double aux1 = LIN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
1780
1781 *var = LIN(time0, aux0, time1, aux1, time);
1782 }
1783
1784 /* Nearest neighbor interpolation... */
1785 else {
1786 const double aux00 = NN(lons[ix], array0[ix][iy],
1787 lons[ix + 1], array0[ix + 1][iy], lon2);
1788 const double aux01 = NN(lons[ix], array0[ix][iy + 1],
1789 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
1790 const double aux0 = NN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
1791
1792 const double aux10 = NN(lons[ix], array1[ix][iy],
1793 lons[ix + 1], array1[ix + 1][iy], lon2);
1794 const double aux11 = NN(lons[ix], array1[ix][iy + 1],
1795 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
1796 const double aux1 = NN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
1797
1798 *var = NN(time0, aux0, time1, aux1, time);
1799 }
1800}
#define NN(x0, y0, x1, y1, x)
Perform nearest-neighbor interpolation.
Definition: mptrac.h:1371
#define SQR(x)
Compute the square of a value.
Definition: mptrac.h:1681
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 1804 of file mptrac.c.

1812 {
1813
1814 struct tm t0, *t1;
1815
1816 t0.tm_year = 100;
1817 t0.tm_mon = 0;
1818 t0.tm_mday = 1;
1819 t0.tm_hour = 0;
1820 t0.tm_min = 0;
1821 t0.tm_sec = 0;
1822
1823 const time_t jsec0 = (time_t) jsec + timegm(&t0);
1824 t1 = gmtime(&jsec0);
1825
1826 *year = t1->tm_year + 1900;
1827 *mon = t1->tm_mon + 1;
1828 *day = t1->tm_mday;
1829 *hour = t1->tm_hour;
1830 *min = t1->tm_min;
1831 *sec = t1->tm_sec;
1832 *remain = jsec - floor(jsec);
1833}

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

1841 {
1842
1843 /* Check number of data points... */
1844 if (nk < 2)
1845 return 1.0;
1846
1847 /* Get altitude... */
1848 const double z = Z(p);
1849
1850 /* Get weighting factor... */
1851 if (z < kz[0])
1852 return kw[0];
1853 else if (z > kz[nk - 1])
1854 return kw[nk - 1];
1855 else {
1856 const int idx = locate_irr(kz, nk, z);
1857 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
1858 }
1859}
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 1863 of file mptrac.c.

1865 {
1866
1867 /*
1868 Calculate moist adiabatic lapse rate [K/km] from temperature [K]
1869 and water vapor volume mixing ratio [1].
1870
1871 Reference: https://en.wikipedia.org/wiki/Lapse_rate
1872 */
1873
1874 const double a = RA * SQR(t), r = SH(h2o) / (1. - SH(h2o));
1875
1876 return 1e3 * G0 * (a + LV * r * t) / (CPD * a + SQR(LV) * r * EPS);
1877}
#define SH(h2o)
Compute specific humidity from water vapor volume mixing ratio.
Definition: mptrac.h:1668
#define LV
Latent heat of vaporization of water [J/kg].
Definition: mptrac.h:218
#define EPS
Ratio of the specific gas constant of dry air and water vapor [1].
Definition: mptrac.h:203
#define CPD
Specific heat of dry air at constant pressure [J/(kg K)].
Definition: mptrac.h:198

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

1882 {
1883
1884 if (0 == ctl->met_press_level_def) {
1885
1886 ctl->met_np = 138;
1887
1888 const double press[138] = {
1889 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
1890 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
1891 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
1892 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
1893 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
1894 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
1895 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
1896 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
1897 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
1898 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
1899 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
1900 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
1901 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
1902 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
1903 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
1904 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
1905 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
1906 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
1907 1010.8487, 1013.2500, 1044.45
1908 };
1909
1910 for (int ip = 0; ip < ctl->met_np; ip++)
1911 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
1912
1913 } else if (1 == ctl->met_press_level_def) {
1914
1915 ctl->met_np = 92;
1916
1917 const double press[92] = {
1918 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
1919 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
1920 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
1921 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
1922 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
1923 113.6382,
1924 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
1925 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
1926 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
1927 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
1928 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
1929 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
1930 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
1931 1007.4431, 1010.8487, 1013.2500, 1044.45
1932 };
1933
1934 for (int ip = 0; ip < ctl->met_np; ip++)
1935 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
1936
1937 } else if (2 == ctl->met_press_level_def) {
1938
1939 ctl->met_np = 60;
1940
1941 const double press[60] = {
1942 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
1943 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
1944 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
1945 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
1946 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
1947 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
1948 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
1949 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1044.45
1950 };
1951
1952 for (int ip = 0; ip < ctl->met_np; ip++)
1953 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
1954
1955 } else if (3 == ctl->met_press_level_def) {
1956
1957 ctl->met_np = 147;
1958
1959 const double press[147] = {
1960 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
1961 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
1962 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
1963 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
1964 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
1965 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
1966 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
1967 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
1968 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
1969 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
1970 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
1971 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
1972 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
1973 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
1974 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
1975 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
1976 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
1977 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
1978 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73, 1028.85,
1979 1031.97,
1980 1035.09, 1038.21, 1041.33, 1044.45
1981 };
1982
1983 for (int ip = 0; ip < ctl->met_np; ip++)
1984 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
1985
1986 } else if (4 == ctl->met_press_level_def) {
1987
1988 ctl->met_np = 101;
1989
1990 const double press[101] = {
1991 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
1992 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
1993 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
1994 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
1995 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
1996 113.6382,
1997 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
1998 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
1999 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
2000 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
2001 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
2002 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
2003 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
2004 1007.4431, 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73,
2005 1028.85, 1031.97,
2006 1035.09, 1038.21, 1041.33, 1044.45
2007 };
2008
2009 for (int ip = 0; ip < ctl->met_np; ip++)
2010 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
2011
2012 } else if (5 == ctl->met_press_level_def) {
2013
2014 ctl->met_np = 62;
2015
2016 const double press[62] = {
2017 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
2018 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
2019 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
2020 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
2021 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
2022 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
2023 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
2024 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1034.86, 1039.65,
2025 1044.45
2026 };
2027
2028 for (int ip = 0; ip < ctl->met_np; ip++)
2029 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
2030
2031 } else if (6 == ctl->met_press_level_def) {
2032
2033 ctl->met_np = 137;
2034
2035 const double press[137] = {
2036 0.01, 0.02, 0.031, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861,
2037 0.2499, 0.3299, 0.4288, 0.5496, 0.6952, 0.869, 1.0742,
2038 1.3143, 1.5928, 1.9134, 2.2797, 2.6954, 3.1642, 3.6898,
2039 4.2759, 4.9262, 5.6441, 6.4334, 7.2974, 8.2397, 9.2634,
2040 10.372, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945, 18.9752,
2041 20.761, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2042 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.199, 54.5299,
2043 57.9834, 61.5607, 65.2695, 69.1187, 73.1187, 77.281, 81.6182,
2044 86.145, 90.8774, 95.828, 101.005, 106.415, 112.068, 117.971,
2045 124.134, 130.564, 137.27, 144.262, 151.549, 159.14, 167.045,
2046 175.273, 183.834, 192.739, 201.997, 211.619, 221.615, 231.995,
2047 242.772, 253.955, 265.556, 277.585, 290.055, 302.976, 316.361,
2048 330.22, 344.566, 359.411, 374.767, 390.645, 407.058, 424.019,
2049 441.539, 459.632, 478.31, 497.584, 517.42, 537.72, 558.343,
2050 579.193, 600.167, 621.162, 642.076, 662.808, 683.262, 703.347,
2051 722.979, 742.086, 760.6, 778.466, 795.64, 812.085, 827.776,
2052 842.696, 856.838, 870.2, 882.791, 894.622, 905.712, 916.081,
2053 925.757, 934.767, 943.14, 950.908, 958.104, 965.299, 972.495,
2054 979.69, 986.886, 994.081, 1001.28, 1008.47, 1015.67, 1022.86,
2055 1030.06, 1037.25, 1044.45
2056 };
2057
2058 for (int ip = 0; ip < ctl->met_np; ip++)
2059 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
2060
2061 } else if (7 == ctl->met_press_level_def) {
2062
2063 ctl->met_np = 59;
2064
2065 const double press[59] = {
2066 0.1, 0.2, 0.3843, 0.6365, 0.9564, 1.3448, 1.8058, 2.3478,
2067 2.985, 3.7397, 4.6462, 5.7565, 7.1322, 8.8366, 10.9483,
2068 13.5647, 16.8064, 20.8227, 25.7989, 31.9642, 39.6029, 49.0671,
2069 60.1802, 73.0663, 87.7274, 104.229, 122.614, 142.902, 165.089,
2070 189.147, 215.025, 242.652, 272.059, 303.217, 336.044, 370.407,
2071 406.133, 443.009, 480.791, 519.209, 557.973, 596.777, 635.306,
2072 673.24, 710.263, 746.063, 780.346, 812.83, 843.263, 871.42,
2073 897.112, 920.189, 940.551, 958.148, 975.744, 993.341, 1010.94,
2074 1028.53, 1046.13
2075 };
2076
2077 for (int ip = 0; ip < ctl->met_np; ip++)
2078 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
2079
2080 } else {
2081 ERRMSG("Use 0 for l137, 1 for l91, 2 for l60 or values between 3 and 7.");
2082 }
2083
2084 if (ctl->met_np > EP) {
2085 ERRMSG("Recompile with larger EP to use this pressure level definition.");
2086 }
2087}
int met_press_level_def
Use predefined pressure levels or not.
Definition: mptrac.h:2683
int met_np
Number of target pressure levels.
Definition: mptrac.h:2677
double met_p[EP]
Target pressure levels [hPa].
Definition: mptrac.h:2680

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

2094 {
2095
2096 int ilo = 0;
2097 int ihi = n - 1;
2098 int i = (ihi + ilo) >> 1;
2099
2100 if (xx[i] < xx[i + 1])
2101 while (ihi > ilo + 1) {
2102 i = (ihi + ilo) >> 1;
2103 if (xx[i] > x)
2104 ihi = i;
2105 else
2106 ilo = i;
2107 } else
2108 while (ihi > ilo + 1) {
2109 i = (ihi + ilo) >> 1;
2110 if (xx[i] <= x)
2111 ihi = i;
2112 else
2113 ilo = i;
2114 }
2115
2116 return ilo;
2117}

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

2125 {
2126
2127 int ilo = 0;
2128 int ihi = n - 1;
2129 int i = (ihi + ilo) >> 1;
2130
2131 if (x >= xx[ig] && x < xx[ig + 1])
2132 return ig;
2133
2134 if (xx[i] < xx[i + 1])
2135 while (ihi > ilo + 1) {
2136 i = (ihi + ilo) >> 1;
2137 if (xx[i] > x)
2138 ihi = i;
2139 else
2140 ilo = i;
2141 } else
2142 while (ihi > ilo + 1) {
2143 i = (ihi + ilo) >> 1;
2144 if (xx[i] <= x)
2145 ihi = i;
2146 else
2147 ilo = i;
2148 }
2149
2150 return ilo;
2151}

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

2158 {
2159
2160 /* Calculate index... */
2161 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2162
2163 /* Check range... */
2164 if (i < 0)
2165 return 0;
2166 else if (i > n - 2)
2167 return n - 2;
2168 else
2169 return i;
2170}

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

2180 {
2181
2182 ind[0] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind],
2183 np, height_ap, 0);
2184 ind[1] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind],
2185 np, height_ap, ind[0]);
2186 ind[2] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind + 1],
2187 np, height_ap, ind[1]);
2188 ind[3] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind + 1],
2189 np, height_ap, ind[2]);
2190}
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.
Author
Lars Hoffmann
Jan Clemens

Definition at line 2194 of file mptrac.c.

2199 {
2200
2201 /* Set timer... */
2202 SELECT_TIMER("MODULE_ADVECT", "PHYSICS", NVTX_GPU);
2203
2204 /* Use omega vertical velocity... */
2205 if (ctl->advect_vert_coord == 0 || ctl->advect_vert_coord == 2) {
2206
2207 /* Loop over particles... */
2208 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2209
2210 /* Init... */
2212 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
2213 x[3] = { 0, 0, 0 };
2214
2215 /* Loop over integration nodes... */
2216 for (int i = 0; i < ctl->advect; i++) {
2217
2218 /* Set position... */
2219 if (i == 0) {
2220 dts = 0.0;
2221 x[0] = atm->lon[ip];
2222 x[1] = atm->lat[ip];
2223 x[2] = atm->p[ip];
2224 } else {
2225 dts = (i == 3 ? 1.0 : 0.5) * cache->dt[ip];
2226 x[0] = atm->lon[ip] + DX2DEG(dts * u[i - 1] / 1000., atm->lat[ip]);
2227 x[1] = atm->lat[ip] + DY2DEG(dts * v[i - 1] / 1000.);
2228 x[2] = atm->p[ip] + dts * w[i - 1];
2229 }
2230 const double tm = atm->time[ip] + dts;
2231
2232 /* Interpolate meteo data on pressure levels... */
2233 if (ctl->advect_vert_coord == 0) {
2234 intpol_met_time_3d(met0, met0->u, met1, met1->u,
2235 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2236 intpol_met_time_3d(met0, met0->v, met1, met1->v,
2237 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2238 intpol_met_time_3d(met0, met0->w, met1, met1->w,
2239 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
2240 }
2241
2242 /* Interpolate meteo data on model levels... */
2243 else {
2244 intpol_met_time_3d_ml(met0, met0->pl, met0->ul,
2245 met1, met1->pl, met1->ul,
2246 tm, x[2], x[0], x[1], &u[i]);
2247 intpol_met_time_3d_ml(met0, met0->pl, met0->vl,
2248 met1, met1->pl, met1->vl,
2249 tm, x[2], x[0], x[1], &v[i]);
2250 intpol_met_time_3d_ml(met0, met0->pl, met0->wl,
2251 met1, met1->pl, met1->wl,
2252 tm, x[2], x[0], x[1], &w[i]);
2253 }
2254
2255 /* Get mean wind... */
2256 double k = 1.0;
2257 if (ctl->advect == 2)
2258 k = (i == 0 ? 0.0 : 1.0);
2259 else if (ctl->advect == 4)
2260 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2261 um += k * u[i];
2262 vm += k * v[i];
2263 wm += k * w[i];
2264 }
2265
2266 /* Set new position... */
2267 atm->time[ip] += cache->dt[ip];
2268 atm->lon[ip] += DX2DEG(cache->dt[ip] * um / 1000.,
2269 (ctl->advect == 2 ? x[1] : atm->lat[ip]));
2270 atm->lat[ip] += DY2DEG(cache->dt[ip] * vm / 1000.);
2271 atm->p[ip] += cache->dt[ip] * wm;
2272 }
2273 }
2274
2275 /* Use zetadot vertical velocity... */
2276 else if (ctl->advect_vert_coord == 1) {
2277
2278 /* Loop over particles... */
2279 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2280
2281 /* Convert pressure to zeta... */
2283 intpol_met_4d_coord(met0, met0->pl, met0->zetal, met1,
2284 met1->pl, met1->zetal, atm->time[ip], atm->p[ip],
2285 atm->lon[ip], atm->lat[ip],
2286 &atm->q[ctl->qnt_zeta][ip], ci, cw, 1);
2287
2288 /* Init... */
2289 double dts, u[4], um = 0, v[4], vm = 0, zeta_dot[4],
2290 zeta_dotm = 0, x[3] = { 0, 0, 0 };
2291
2292 /* Loop over integration nodes... */
2293 for (int i = 0; i < ctl->advect; i++) {
2294
2295 /* Set position... */
2296 if (i == 0) {
2297 dts = 0.0;
2298 x[0] = atm->lon[ip];
2299 x[1] = atm->lat[ip];
2300 x[2] = atm->q[ctl->qnt_zeta][ip];
2301 } else {
2302 dts = (i == 3 ? 1.0 : 0.5) * cache->dt[ip];
2303 x[0] = atm->lon[ip] + DX2DEG(dts * u[i - 1] / 1000., atm->lat[ip]);
2304 x[1] = atm->lat[ip] + DY2DEG(dts * v[i - 1] / 1000.);
2305 x[2] = atm->q[ctl->qnt_zeta][ip] + dts * zeta_dot[i - 1];
2306 }
2307 const double tm = atm->time[ip] + dts;
2308
2309 /* Interpolate meteo data... */
2310 intpol_met_4d_coord(met0, met0->zetal, met0->ul, met1, met1->zetal,
2311 met1->ul, tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2312 intpol_met_4d_coord(met0, met0->zetal, met0->vl, met1, met1->zetal,
2313 met1->vl, tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2314 intpol_met_4d_coord(met0, met0->zetal, met0->zeta_dotl, met1,
2315 met1->zetal, met1->zeta_dotl, tm, x[2], x[0],
2316 x[1], &zeta_dot[i], ci, cw, 0);
2317
2318 /* Get mean wind... */
2319 double k = 1.0;
2320 if (ctl->advect == 2)
2321 k = (i == 0 ? 0.0 : 1.0);
2322 else if (ctl->advect == 4)
2323 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2324 um += k * u[i];
2325 vm += k * v[i];
2326 zeta_dotm += k * zeta_dot[i];
2327 }
2328
2329 /* Set new position... */
2330 atm->time[ip] += cache->dt[ip];
2331 atm->lon[ip] += DX2DEG(cache->dt[ip] * um / 1000.,
2332 (ctl->advect == 2 ? x[1] : atm->lat[ip]));
2333 atm->lat[ip] += DY2DEG(cache->dt[ip] * vm / 1000.);
2334 atm->q[ctl->qnt_zeta][ip] += cache->dt[ip] * zeta_dotm;
2335
2336 /* Convert zeta to pressure... */
2337 intpol_met_4d_coord(met0, met0->zetal, met0->pl, met1, met1->zetal,
2338 met1->pl, atm->time[ip],
2339 atm->q[ctl->qnt_zeta][ip], atm->lon[ip],
2340 atm->lat[ip], &atm->p[ip], ci, cw, 1);
2341 }
2342 }
2343}
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:1271
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:1626
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:1655
#define PARTICLE_LOOP(ip0, ip1, check_dt,...)
Loop over particle indices with OpenACC acceleration.
Definition: mptrac.h:1398
#define DX2DEG(dx, lat)
Convert a distance in kilometers to degrees longitude at a given latitude.
Definition: mptrac.h:602
#define SELECT_TIMER(id, group, color)
Select and start a timer with specific attributes.
Definition: mptrac.h:2108
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
Definition: mptrac.h:620
double time[NP]
Time [s].
Definition: mptrac.h:3270
double lat[NP]
Latitude [deg].
Definition: mptrac.h:3279
double lon[NP]
Longitude [deg].
Definition: mptrac.h:3276
int np
Number of air parcels.
Definition: mptrac.h:3267
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
Definition: mptrac.h:3282
double p[NP]
Pressure [hPa].
Definition: mptrac.h:3273
double dt[NP]
Timesteps [s].
Definition: mptrac.h:3364
int advect
Advection scheme (0=off, 1=Euler, 2=midpoint, 4=Runge-Kutta).
Definition: mptrac.h:2752
int qnt_zeta
Quantity array index for zeta vertical coordinate.
Definition: mptrac.h:2463
int advect_vert_coord
Vertical velocity of air parcels (0=omega_on_plev, 1=zetadot_on_mlev, 2=omega_on_mlev).
Definition: mptrac.h:2756
float zeta_dotl[EX][EY][EP]
Vertical velocity on model levels [K/s].
Definition: mptrac.h:3714
float w[EX][EY][EP]
Vertical velocity [hPa/s].
Definition: mptrac.h:3672
float wl[EX][EY][EP]
Vertical velocity on model levels [hPa/s].
Definition: mptrac.h:3708
float vl[EX][EY][EP]
Meridional wind on model levels [m/s].
Definition: mptrac.h:3705
float u[EX][EY][EP]
Zonal wind [m/s].
Definition: mptrac.h:3666
float ul[EX][EY][EP]
Zonal wind on model levels [m/s].
Definition: mptrac.h:3702
float v[EX][EY][EP]
Meridional wind [m/s].
Definition: mptrac.h:3669
float pl[EX][EY][EP]
Pressure on model levels [hPa].
Definition: mptrac.h:3699
float zetal[EX][EY][EP]
Zeta on model levels [K].
Definition: mptrac.h:3711
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 2347 of file mptrac.c.

2352 {
2353
2354 /* Check parameters... */
2355 if (ctl->advect_vert_coord != 1)
2356 return;
2357
2358 /* Set timer... */
2359 SELECT_TIMER("MODULE_ADVECT_INIT", "PHYSICS", NVTX_GPU);
2360
2361 /* Loop over particles... */
2362 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,met0,met1,atm)") {
2363
2364 /* Initialize pressure consistent with zeta... */
2366 intpol_met_4d_coord(met0, met0->zetal, met0->pl, met1, met1->zetal,
2367 met1->pl, atm->time[ip], atm->q[ctl->qnt_zeta][ip],
2368 atm->lon[ip], atm->lat[ip], &atm->p[ip], ci, cw, 1);
2369 }
2370}
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.
Author
Lars Hoffmann
Mingzhao Liu

Definition at line 2374 of file mptrac.c.

2380 {
2381
2382 /* Set timer... */
2383 SELECT_TIMER("MODULE_BOUND_COND", "PHYSICS", NVTX_GPU);
2384
2385 /* Check quantity flags... */
2386 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0 && ctl->qnt_Cccl4
2387 && ctl->qnt_Cccl3f < 0 && ctl->qnt_Cccl2f2 < 0
2388 && ctl->qnt_Cn2o < 0 && ctl->qnt_Csf6 < 0 && ctl->qnt_aoa < 0)
2389 return;
2390
2391 /* Loop over particles... */
2392 PARTICLE_LOOP(0, atm->np, 1,
2393 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2394
2395 /* Check latitude and pressure range... */
2396 if (atm->lat[ip] < ctl->bound_lat0 || atm->lat[ip] > ctl->bound_lat1
2397 || atm->p[ip] > ctl->bound_p0 || atm->p[ip] < ctl->bound_p1)
2398 continue;
2399
2400 /* Check surface layer... */
2401 if (ctl->bound_dps > 0 || ctl->bound_dzs > 0
2402 || ctl->bound_zetas > 0 || ctl->bound_pbl) {
2403
2404 /* Get surface pressure... */
2405 double ps;
2407 INTPOL_2D(ps, 1);
2408
2409 /* Check pressure... */
2410 if (ctl->bound_dps > 0 && atm->p[ip] < ps - ctl->bound_dps)
2411 continue;
2412
2413 /* Check height... */
2414 if (ctl->bound_dzs > 0 && Z(atm->p[ip]) > Z(ps) + ctl->bound_dzs)
2415 continue;
2416
2417 /* Check zeta range... */
2418 if (ctl->bound_zetas > 0) {
2419 double t;
2420 INTPOL_3D(t, 1);
2421 if (ZETA(ps, atm->p[ip], t) > ctl->bound_zetas)
2422 continue;
2423 }
2424
2425 /* Check planetary boundary layer... */
2426 if (ctl->bound_pbl) {
2427 double pbl;
2428 INTPOL_2D(pbl, 0);
2429 if (atm->p[ip] < pbl)
2430 continue;
2431 }
2432 }
2433
2434 /* Set mass and volume mixing ratio... */
2435 if (ctl->qnt_m >= 0 && ctl->bound_mass >= 0)
2436 atm->q[ctl->qnt_m][ip] =
2437 ctl->bound_mass + ctl->bound_mass_trend * atm->time[ip];
2438 if (ctl->qnt_vmr >= 0 && ctl->bound_vmr >= 0)
2439 atm->q[ctl->qnt_vmr][ip] =
2440 ctl->bound_vmr + ctl->bound_vmr_trend * atm->time[ip];
2441
2442 /* Set CFC-10 volume mixing ratio... */
2443 if (ctl->qnt_Cccl4 >= 0 && ctl->clim_ccl4_timeseries[0] != '-')
2444 atm->q[ctl->qnt_Cccl4][ip] = clim_ts(&clim->ccl4, atm->time[ip]);
2445
2446 /* Set CFC-11 volume mixing ratio... */
2447 if (ctl->qnt_Cccl3f >= 0 && ctl->clim_ccl3f_timeseries[0] != '-')
2448 atm->q[ctl->qnt_Cccl3f][ip] = clim_ts(&clim->ccl3f, atm->time[ip]);
2449
2450 /* Set CFC-12 volume mixing ratio... */
2451 if (ctl->qnt_Cccl2f2 >= 0 && ctl->clim_ccl2f2_timeseries[0] != '-')
2452 atm->q[ctl->qnt_Cccl2f2][ip] = clim_ts(&clim->ccl2f2, atm->time[ip]);
2453
2454 /* Set N2O volume mixing ratio... */
2455 if (ctl->qnt_Cn2o >= 0 && ctl->clim_n2o_timeseries[0] != '-')
2456 atm->q[ctl->qnt_Cn2o][ip] = clim_ts(&clim->n2o, atm->time[ip]);
2457
2458 /* Set SF6 volume mixing ratio... */
2459 if (ctl->qnt_Csf6 >= 0 && ctl->clim_sf6_timeseries[0] != '-')
2460 atm->q[ctl->qnt_Csf6][ip] = clim_ts(&clim->sf6, atm->time[ip]);
2461
2462 /* Set age of air... */
2463 if (ctl->qnt_aoa >= 0)
2464 atm->q[ctl->qnt_aoa][ip] = atm->time[ip];
2465 }
2466}
double clim_ts(const clim_ts_t *ts, const double t)
Interpolates a time series of climatological variables.
Definition: mptrac.c:388
#define INTPOL_3D(var, init)
Perform 3D interpolation for a meteorological variable.
Definition: mptrac.h:852
#define ZETA(ps, p, t)
Computes the value of the zeta vertical coordinate.
Definition: mptrac.h:1915
#define INTPOL_2D(var, init)
Perform 2D interpolation for a meteorological variable.
Definition: mptrac.h:835
clim_ts_t ccl2f2
CFC-12 time series.
Definition: mptrac.h:3525
clim_ts_t sf6
SF6 time series.
Definition: mptrac.h:3531
clim_ts_t ccl4
CFC-10 time series.
Definition: mptrac.h:3519
clim_ts_t ccl3f
CFC-11 time series.
Definition: mptrac.h:3522
clim_ts_t n2o
N2O time series.
Definition: mptrac.h:3528
int qnt_Cccl2f2
Quantity array index for CFC-12 volume mixing ratio (chemistry code).
Definition: mptrac.h:2535
int qnt_m
Quantity array index for mass.
Definition: mptrac.h:2280
int qnt_aoa
Quantity array index for age of air.
Definition: mptrac.h:2544
char clim_n2o_timeseries[LEN]
Filename of N2O time series.
Definition: mptrac.h:2882
double bound_dzs
Boundary conditions surface layer depth [km].
Definition: mptrac.h:2831
int qnt_Cccl4
Quantity array index for CFC-10 volume mixing ratio (chemistry code).
Definition: mptrac.h:2529
double bound_mass
Boundary conditions mass per particle [kg].
Definition: mptrac.h:2804
int qnt_vmr
Quantity array index for volume mixing ratio.
Definition: mptrac.h:2283
double bound_lat1
Boundary conditions maximum longitude [deg].
Definition: mptrac.h:2819
int bound_pbl
Boundary conditions planetary boundary layer (0=no, 1=yes).
Definition: mptrac.h:2837
double bound_p1
Boundary conditions top pressure [hPa].
Definition: mptrac.h:2825
double bound_vmr
Boundary conditions volume mixing ratio [ppv].
Definition: mptrac.h:2810
double bound_lat0
Boundary conditions minimum longitude [deg].
Definition: mptrac.h:2816
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
Definition: mptrac.h:2813
int qnt_Cn2o
Quantity array index for N2O volume mixing ratio (chemistry code).
Definition: mptrac.h:2538
int qnt_Cccl3f
Quantity array index for CFC-11 volume mixing ratio (chemistry code).
Definition: mptrac.h:2532
int qnt_Csf6
Quantity array index for SF6 volume mixing ratio (chemistry code).
Definition: mptrac.h:2541
double bound_dps
Boundary conditions surface layer depth [hPa].
Definition: mptrac.h:2828
double bound_mass_trend
Boundary conditions mass per particle trend [kg/s].
Definition: mptrac.h:2807
double bound_p0
Boundary conditions bottom pressure [hPa].
Definition: mptrac.h:2822
char clim_ccl4_timeseries[LEN]
Filename of CFC-10 time series.
Definition: mptrac.h:2873
char clim_sf6_timeseries[LEN]
Filename of SF6 time series.
Definition: mptrac.h:2885
char clim_ccl3f_timeseries[LEN]
Filename of CFC-11 time series.
Definition: mptrac.h:2876
char clim_ccl2f2_timeseries[LEN]
Filename of CFC-12 time series.
Definition: mptrac.h:2879
double bound_zetas
Boundary conditions surface layer zeta [K].
Definition: mptrac.h:2834
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
Author
Mingzhao Liu
Lars Hoffmann

Definition at line 2470 of file mptrac.c.

2475 {
2476
2477 /* Check quantities... */
2478 if (ctl->qnt_m < 0 || ctl->qnt_Cx < 0)
2479 return;
2480 if (ctl->molmass <= 0)
2481 ERRMSG("Molar mass is not defined!");
2482
2483 /* Set timer... */
2484 SELECT_TIMER("MODULE_CHEM_GRID", "PHYSICS", NVTX_GPU);
2485
2486 /* Allocate... */
2487 const int ensemble_mode = (ctl->nens > 0);
2488 const int np = atm->np;
2489 const int nz = ctl->chemgrid_nz;
2490 const int nx = ctl->chemgrid_nx;
2491 const int ny = ctl->chemgrid_ny;
2492 const int ngrid = nx * ny * nz;
2493 const int nens = ensemble_mode ? ctl->nens : 1;
2494
2495 double *restrict const z = (double *) malloc((size_t) nz * sizeof(double));
2496 double *restrict const press =
2497 (double *) malloc((size_t) nz * sizeof(double));
2498 double *restrict const mass =
2499 (double *) calloc((size_t) ngrid * (size_t) nens, sizeof(double));
2500 double *restrict const area =
2501 (double *) malloc((size_t) ny * sizeof(double));
2502 double *restrict const lon =
2503 (double *) malloc((size_t) nx * sizeof(double));
2504 double *restrict const lat =
2505 (double *) malloc((size_t) ny * sizeof(double));
2506
2507 int *restrict const ixs = (int *) malloc((size_t) np * sizeof(int));
2508 int *restrict const iys = (int *) malloc((size_t) np * sizeof(int));
2509 int *restrict const izs = (int *) malloc((size_t) np * sizeof(int));
2510
2511 /* Set grid box size... */
2512 const double dz = (ctl->chemgrid_z1 - ctl->chemgrid_z0) / nz;
2513 const double dlon = (ctl->chemgrid_lon1 - ctl->chemgrid_lon0) / nx;
2514 const double dlat = (ctl->chemgrid_lat1 - ctl->chemgrid_lat0) / ny;
2515
2516 /* Set vertical coordinates... */
2517#ifdef _OPENACC
2518#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])
2519#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
2520#pragma acc parallel loop independent gang vector
2521#else
2522#pragma omp parallel for default(shared)
2523#endif
2524 for (int iz = 0; iz < nz; iz++) {
2525 z[iz] = ctl->chemgrid_z0 + dz * (iz + 0.5);
2526 press[iz] = P(z[iz]);
2527 }
2528
2529 /* Set time interval for output... */
2530 const double t0 = tt - 0.5 * ctl->dt_mod;
2531 const double t1 = tt + 0.5 * ctl->dt_mod;
2532
2533 /* Get indices... */
2534#ifdef _OPENACC
2535#pragma acc parallel loop independent gang vector
2536#else
2537#pragma omp parallel for default(shared)
2538#endif
2539 for (int ip = 0; ip < np; ip++) {
2540 ixs[ip] = (int) ((atm->lon[ip] - ctl->chemgrid_lon0) / dlon);
2541 iys[ip] = (int) ((atm->lat[ip] - ctl->chemgrid_lat0) / dlat);
2542 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->chemgrid_z0) / dz);
2543 if (atm->time[ip] < t0 || atm->time[ip] > t1
2544 || ixs[ip] < 0 || ixs[ip] >= nx
2545 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
2546 izs[ip] = -1;
2547 }
2548
2549 /* Set horizontal coordinates... */
2550#ifdef _OPENACC
2551#pragma acc parallel loop independent gang vector
2552#else
2553#pragma omp parallel for default(shared)
2554#endif
2555 for (int ix = 0; ix < nx; ix++)
2556 lon[ix] = ctl->chemgrid_lon0 + dlon * (ix + 0.5);
2557
2558#ifdef _OPENACC
2559#pragma acc parallel loop independent gang vector
2560#else
2561#pragma omp parallel for default(shared)
2562#endif
2563 for (int iy = 0; iy < ny; iy++) {
2564 lat[iy] = ctl->chemgrid_lat0 + dlat * (iy + 0.5);
2565 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
2566 }
2567
2568 /* Get mass per grid box... */
2569#ifdef _OPENACC
2570#pragma acc parallel loop independent gang vector
2571#endif
2572 for (int ip = 0; ip < np; ip++) {
2573 if (izs[ip] >= 0) {
2574 int mass_idx = ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
2575 if (ensemble_mode) {
2576 const int ens = (int) atm->q[ctl->qnt_ens][ip];
2577 mass_idx += ens * ngrid;
2578 }
2579#ifdef _OPENACC
2580#pragma acc atomic update
2581#endif
2582 mass[mass_idx] += atm->q[ctl->qnt_m][ip];
2583 }
2584 }
2585
2586 /* Assign grid data to air parcels ... */
2587#ifdef _OPENACC
2588#pragma acc parallel loop independent gang vector
2589#else
2590#pragma omp parallel for default(shared)
2591#endif
2592 for (int ip = 0; ip < np; ip++)
2593 if (izs[ip] >= 0) {
2594
2595 /* Interpolate temperature... */
2596 double temp;
2598 intpol_met_time_3d(met0, met0->t, met1, met1->t, tt,
2599 press[izs[ip]],
2600 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
2601
2602 /* Set mass... */
2603 int mass_idx = ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
2604 if (ensemble_mode) {
2605 const int ens = (int) atm->q[ctl->qnt_ens][ip];
2606 mass_idx += ens * ngrid;
2607 }
2608
2609 /* Calculate volume mixing ratio... */
2610 const double m = mass[mass_idx];
2611 atm->q[ctl->qnt_Cx][ip] = MA / ctl->molmass * m
2612 / (RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
2613 }
2614
2615 /* Free... */
2616#ifdef _OPENACC
2617#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
2618#endif
2619 free(mass);
2620 free(lon);
2621 free(lat);
2622 free(area);
2623 free(z);
2624 free(press);
2625 free(ixs);
2626 free(iys);
2627 free(izs);
2628}
#define ARRAY_3D(ix, iy, ny, iz, nz)
Compute the linear index of a 3D array element.
Definition: mptrac.h:468
#define P(z)
Compute pressure at given altitude.
Definition: mptrac.h:1428
#define RHO(p, t)
Compute density of air.
Definition: mptrac.h:1605
double molmass
Molar mass [g/mol].
Definition: mptrac.h:2843
double chemgrid_z1
Upper altitude of chemistry grid [km].
Definition: mptrac.h:2930
double chemgrid_z0
Lower altitude of chemistry grid [km].
Definition: mptrac.h:2927
double chemgrid_lat0
Lower latitude of chemistry grid [deg].
Definition: mptrac.h:2945
double chemgrid_lat1
Upper latitude of chemistry grid [deg].
Definition: mptrac.h:2948
double chemgrid_lon0
Lower longitude of chemistry grid [deg].
Definition: mptrac.h:2936
double chemgrid_lon1
Upper longitude of chemistry grid [deg].
Definition: mptrac.h:2939
double dt_mod
Time step of simulation [s].
Definition: mptrac.h:2562
int nens
Number of ensembles.
Definition: mptrac.h:3096
int chemgrid_nz
Number of altitudes of chemistry grid.
Definition: mptrac.h:2924
int chemgrid_nx
Number of longitudes of chemistry grid.
Definition: mptrac.h:2933
int chemgrid_ny
Number of latitudes of chemistry grid.
Definition: mptrac.h:2942
int qnt_ens
Quantity array index for ensemble IDs.
Definition: mptrac.h:2274
int qnt_Cx
Quantity array index for trace species x volume mixing ratio (chemistry code).
Definition: mptrac.h:2499
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.
Author
Mingzhao Liu

Definition at line 2632 of file mptrac.c.

2638 {
2639
2640 /* Set timer... */
2641 SELECT_TIMER("MODULE_CHEM_INIT", "PHYSICS", NVTX_GPU);
2642
2643 /* Loop over particles... */
2644 PARTICLE_LOOP(0, atm->np, 0,
2645 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2646
2647 /* Set H2O and O3 using meteo data... */
2649 if (ctl->qnt_Ch2o >= 0) {
2650 double h2o;
2651 INTPOL_3D(h2o, 1);
2652 SET_ATM(qnt_Ch2o, h2o);
2653 }
2654 if (ctl->qnt_Co3 >= 0) {
2655 double o3;
2656 INTPOL_3D(o3, 1);
2657 SET_ATM(qnt_Co3, o3);
2658 }
2659
2660 /* Set radical species... */
2661 SET_ATM(qnt_Coh, clim_oh(ctl, clim, atm->time[ip],
2662 atm->lon[ip], atm->lat[ip], atm->p[ip]));
2663 SET_ATM(qnt_Cho2, clim_zm(&clim->ho2, atm->time[ip],
2664 atm->lat[ip], atm->p[ip]));
2665 SET_ATM(qnt_Ch2o2, clim_zm(&clim->h2o2, atm->time[ip],
2666 atm->lat[ip], atm->p[ip]));
2667 SET_ATM(qnt_Co1d, clim_zm(&clim->o1d, atm->time[ip],
2668 atm->lat[ip], atm->p[ip]));
2669 }
2670}
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:1624
clim_zm_t ho2
HO2 zonal means.
Definition: mptrac.h:3513
clim_zm_t o1d
O(1D) zonal means.
Definition: mptrac.h:3516
clim_zm_t h2o2
H2O2 zonal means.
Definition: mptrac.h:3510
int qnt_Ch2o
Quantity array index for H2O volume mixing ratio (chemistry code).
Definition: mptrac.h:2502
int qnt_Co3
Quantity array index for O3 volume mixing ratio (chemistry code).
Definition: mptrac.h:2505
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 2674 of file mptrac.c.

2679 {
2680
2681 /* Set timer... */
2682 SELECT_TIMER("MODULE_CONVECTION", "PHYSICS", NVTX_GPU);
2683
2684 /* Create random numbers... */
2685 module_rng(ctl, cache->rs, (size_t) atm->np, 0);
2686
2687 /* Loop over particles... */
2688 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2689
2690 /* Interpolate CAPE... */
2691 double ps;
2693 INTPOL_2D(ps, 1);
2694
2695 /* Initialize pressure range for vertical mixing... */
2696 double pbot = ps, ptop = ps;
2697
2698 /* Mixing in the PBL... */
2699 if (ctl->conv_mix_pbl) {
2700
2701 /* Interpolate PBL... */
2702 double pbl;
2703 INTPOL_2D(pbl, 0);
2704
2705 /* Set pressure range... */
2706 ptop = pbl - ctl->conv_pbl_trans * (ps - pbl);
2707 }
2708
2709 /* Convective mixing... */
2710 if (ctl->conv_cape >= 0) {
2711
2712 /* Interpolate CAPE, CIN, and equilibrium level... */
2713 double cape, cin, pel;
2714 INTPOL_2D(cape, 0);
2715 INTPOL_2D(cin, 0);
2716 INTPOL_2D(pel, 0);
2717
2718 /* Set pressure range... */
2719 if (isfinite(cape) && cape >= ctl->conv_cape
2720 && (ctl->conv_cin <= 0 || (isfinite(cin) && cin >= ctl->conv_cin)))
2721 ptop = GSL_MIN(ptop, pel);
2722 }
2723
2724 /* Apply vertical mixing... */
2725 if (ptop != pbot && atm->p[ip] >= ptop) {
2726
2727 /* Get density range... */
2728 double tbot, ttop;
2729 intpol_met_time_3d(met0, met0->t, met1, met1->t, atm->time[ip],
2730 pbot, atm->lon[ip], atm->lat[ip], &tbot, ci, cw, 1);
2731 intpol_met_time_3d(met0, met0->t, met1, met1->t, atm->time[ip], ptop,
2732 atm->lon[ip], atm->lat[ip], &ttop, ci, cw, 1);
2733 const double rhobot = pbot / tbot;
2734 const double rhotop = ptop / ttop;
2735
2736 /* Get new density... */
2737 const double rho = rhobot + (rhotop - rhobot) * cache->rs[ip];
2738
2739 /* Get pressure... */
2740 atm->p[ip] = LIN(rhobot, pbot, rhotop, ptop, rho);
2741 }
2742 }
2743}
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:3805
double rs[3 *NP+1]
Random numbers.
Definition: mptrac.h:3361
double conv_cape
CAPE threshold for convection module [J/kg].
Definition: mptrac.h:2795
double conv_pbl_trans
Depth of PBL transition layer (fraction of PBL depth).
Definition: mptrac.h:2792
int conv_mix_pbl
Vertical mixing in the PBL (0=off, 1=on).
Definition: mptrac.h:2789
double conv_cin
CIN threshold for convection module [J/kg].
Definition: mptrac.h:2798
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 2747 of file mptrac.c.

2751 {
2752
2753 /* Set timer... */
2754 SELECT_TIMER("MODULE_DECAY", "PHYSICS", NVTX_GPU);
2755
2756 /* Check quantity flags... */
2757 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
2758 ERRMSG("Module needs quantity mass or volume mixing ratio!");
2759
2760 /* Loop over particles... */
2761 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,clim,atm)") {
2762
2763 /* Get weighting factor... */
2764 const double w = tropo_weight(clim, atm, ip);
2765
2766 /* Set lifetime... */
2767 const double tdec = w * ctl->tdec_trop + (1 - w) * ctl->tdec_strat;
2768
2769 /* Calculate exponential decay... */
2770 const double aux = exp(-cache->dt[ip] / tdec);
2771 if (ctl->qnt_m >= 0) {
2772 if (ctl->qnt_mloss_decay >= 0)
2773 atm->q[ctl->qnt_mloss_decay][ip]
2774 += atm->q[ctl->qnt_m][ip] * (1 - aux);
2775 atm->q[ctl->qnt_m][ip] *= aux;
2776 if (ctl->qnt_loss_rate >= 0)
2777 atm->q[ctl->qnt_loss_rate][ip] += 1. / tdec;
2778 }
2779 if (ctl->qnt_vmr >= 0)
2780 atm->q[ctl->qnt_vmr][ip] *= aux;
2781 }
2782}
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:11015
int qnt_loss_rate
Quantity array index for total loss rate.
Definition: mptrac.h:2439
int qnt_mloss_decay
Quantity array index for total mass loss due to exponential decay.
Definition: mptrac.h:2436
double tdec_strat
Life time of particles in the stratosphere [s].
Definition: mptrac.h:2849
double tdec_trop
Life time of particles in the troposphere [s].
Definition: mptrac.h:2846
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 2786 of file mptrac.c.

2791 {
2792
2793 /* Set timer... */
2794 SELECT_TIMER("MODULE_DIFF_MESO", "PHYSICS", NVTX_GPU);
2795
2796 /* Create random numbers... */
2797 module_rng(ctl, cache->rs, 3 * (size_t) atm->np, 1);
2798
2799 /* Loop over particles... */
2800 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2801
2802 /* Get indices... */
2803 const int ix = locate_reg(met0->lon, met0->nx, atm->lon[ip]);
2804 const int iy = locate_irr(met0->lat, met0->ny, atm->lat[ip]);
2805 const int iz = locate_irr(met0->p, met0->np, atm->p[ip]);
2806
2807 /* Get standard deviations of local wind data... */
2808 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
2809 for (int i = 0; i < 2; i++)
2810 for (int j = 0; j < 2; j++)
2811 for (int k = 0; k < 2; k++) {
2812 umean += met0->u[ix + i][iy + j][iz + k];
2813 usig += SQR(met0->u[ix + i][iy + j][iz + k]);
2814 vmean += met0->v[ix + i][iy + j][iz + k];
2815 vsig += SQR(met0->v[ix + i][iy + j][iz + k]);
2816 wmean += met0->w[ix + i][iy + j][iz + k];
2817 wsig += SQR(met0->w[ix + i][iy + j][iz + k]);
2818
2819 umean += met1->u[ix + i][iy + j][iz + k];
2820 usig += SQR(met1->u[ix + i][iy + j][iz + k]);
2821 vmean += met1->v[ix + i][iy + j][iz + k];
2822 vsig += SQR(met1->v[ix + i][iy + j][iz + k]);
2823 wmean += met1->w[ix + i][iy + j][iz + k];
2824 wsig += SQR(met1->w[ix + i][iy + j][iz + k]);
2825 }
2826 usig = usig / 16.f - SQR(umean / 16.f);
2827 usig = (usig > 0 ? sqrtf(usig) : 0);
2828 vsig = vsig / 16.f - SQR(vmean / 16.f);
2829 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
2830 wsig = wsig / 16.f - SQR(wmean / 16.f);
2831 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
2832
2833 /* Set temporal correlations for mesoscale fluctuations... */
2834 const double r = 1 - 2 * fabs(cache->dt[ip]) / ctl->dt_met;
2835 const double r2 = sqrt(1 - r * r);
2836
2837 /* Calculate horizontal mesoscale wind fluctuations... */
2838 if (ctl->turb_mesox > 0) {
2839 cache->uvwp[ip][0] =
2840 (float) (r * cache->uvwp[ip][0] +
2841 r2 * cache->rs[3 * ip] * ctl->turb_mesox * usig);
2842 atm->lon[ip] +=
2843 DX2DEG(cache->uvwp[ip][0] * cache->dt[ip] / 1000., atm->lat[ip]);
2844
2845 cache->uvwp[ip][1] =
2846 (float) (r * cache->uvwp[ip][1] +
2847 r2 * cache->rs[3 * ip + 1] * ctl->turb_mesox * vsig);
2848 atm->lat[ip] += DY2DEG(cache->uvwp[ip][1] * cache->dt[ip] / 1000.);
2849 }
2850
2851 /* Calculate vertical mesoscale wind fluctuations... */
2852 if (ctl->turb_mesoz > 0) {
2853 cache->uvwp[ip][2] =
2854 (float) (r * cache->uvwp[ip][2] +
2855 r2 * cache->rs[3 * ip + 2] * ctl->turb_mesoz * wsig);
2856 atm->p[ip] += cache->uvwp[ip][2] * cache->dt[ip];
2857 }
2858 }
2859}
float uvwp[NP][3]
Wind perturbations [m/s].
Definition: mptrac.h:3358
double turb_mesoz
Vertical scaling factor for mesoscale wind fluctuations.
Definition: mptrac.h:2786
double dt_met
Time step of meteo data [s].
Definition: mptrac.h:2572
double turb_mesox
Horizontal scaling factor for mesoscale wind fluctuations.
Definition: mptrac.h:2783
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 2863 of file mptrac.c.

2868 {
2869
2870 /* Set timer... */
2871 SELECT_TIMER("MODULE_DIFF_PBL", "PHYSICS", NVTX_GPU);
2872
2873 /* Create random numbers... */
2874 module_rng(ctl, cache->rs, 3 * (size_t) atm->np, 1);
2875
2876 /* Loop over particles... */
2877 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2878
2879 double dsigw_dz = 0.0, sig_u = 0.25, sig_w = 0.1,
2880 tau_u = 300., tau_w = 100.;
2881
2882 /* Get surface and PBL pressure... */
2883 double pbl, ps;
2885 INTPOL_2D(ps, 1);
2886 INTPOL_2D(pbl, 0);
2887
2888 /* Boundary layer... */
2889 if (atm->p[ip] >= pbl) {
2890
2891 /* Calculate heights... */
2892 const double p = MIN(atm->p[ip], ps);
2893 const double zs = Z(ps);
2894 const double z = 1e3 * (Z(p) - zs);
2895 const double zi = 1e3 * (Z(pbl) - zs);
2896 const double zratio = z / zi;
2897
2898 /* Calculate friction velocity... */
2899 double ess, nss, h2o, t;
2900 INTPOL_2D(ess, 0);
2901 INTPOL_2D(nss, 0);
2902 INTPOL_3D(t, 1);
2903 INTPOL_3D(h2o, 0);
2904 const double rho = RHO(p, TVIRT(t, h2o));
2905 const double tau = sqrt(SQR(ess) + SQR(nss));
2906 const double ustar = sqrt(tau / rho);
2907
2908 /* Get surface sensible heat flux... */
2909 double shf;
2910 INTPOL_2D(shf, 1);
2911
2912 /* Stable or neutral conditions... */
2913 if (shf <= 0) {
2914
2915 /* Calcalute turbulent velocity variances... */
2916 sig_u = 1e-2 + 2.0 * ustar * (1.0 - zratio);
2917 sig_w = 1e-2 + 1.3 * ustar * (1.0 - zratio);
2918
2919 /* Calculate derivative dsig_w/dz... */
2920 dsigw_dz = -1.3 * ustar / zi;
2921
2922 /* Calcalute Lagrangian timescales... */
2923 tau_u = 0.07 * zi / sig_u * sqrt(zratio);
2924 tau_w = 0.1 * zi / sig_w * pow(zratio, 0.8);
2925 }
2926
2927 /* Unstable conditions... */
2928 else {
2929
2930 /* Convective velocity... */
2931 const double wstar =
2932 pow(G0 / THETAVIRT(p, t, h2o) * shf / (rho * CPD) * zi, 1. / 3.);
2933
2934 /* Calcalute turbulent velocity variances... */
2935 sig_u = 1e-2
2936 + sqrt(0.4 * SQR(wstar) + (5.0 - 4.0 * zratio) * SQR(ustar));
2937 sig_w = 1e-2 + sqrt(1.2 * SQR(wstar) * (1.0 - 0.9 * zratio)
2938 * pow(zratio, 2.0 / 3.0)
2939 + (1.8 - 1.4 * zratio) * SQR(ustar));
2940
2941 /* Calculate derivative dsig_w/dz... */
2942 dsigw_dz = 0.5 / sig_w / zi * (-1.4 * SQR(ustar) + SQR(wstar)
2943 * (0.8 *
2944 pow(MAX(zratio, 1e-3), -1.0 / 3.0)
2945 - 1.8 * pow(zratio, 2.0 / 3.0)));
2946
2947 /* Calcalute Lagrangian timescales... */
2948 const double C0 = 3.0; // TODO: typically 3...6, NAME model uses 3?
2949 const double eps =
2950 (1.5 - 1.2 * pow(zratio, 1.0 / 3.0)) * SQR(wstar) * wstar / zi
2951 + SQR(ustar) * ustar * (1.0 - 0.8 * zratio) / (KARMAN * z);
2952 tau_u = 2 * SQR(sig_u) / (C0 * eps);
2953 tau_w = 2 * SQR(sig_w) / (C0 * eps);
2954 }
2955 }
2956
2957 /* Set minimum values... */
2958 sig_u = MAX(sig_u, 0.25);
2959 sig_w = MAX(sig_w, 0.1);
2960 tau_u = MAX(tau_u, 300.);
2961 tau_w = MAX(tau_w, 100.);
2962
2963 /* Update perturbations... */
2964 const double ru = exp(-fabs(cache->dt[ip]) / tau_u);
2965 const double ru2 = sqrt(1.0 - SQR(ru));
2966 cache->uvwp[ip][0]
2967 = (float) (cache->uvwp[ip][0] * ru + ru2 * cache->rs[3 * ip]);
2968 cache->uvwp[ip][1]
2969 = (float) (cache->uvwp[ip][1] * ru + ru2 * cache->rs[3 * ip + 1]);
2970
2971 const double rw = exp(-fabs(cache->dt[ip]) / tau_w);
2972 const double rw2 = sqrt(1.0 - SQR(rw));
2973 cache->uvwp[ip][2]
2974 = (float) (cache->uvwp[ip][2] * rw + rw2 * cache->rs[3 * ip + 2]
2975 + sig_w * dsigw_dz * cache->dt[ip]); // TODO: check approx for density correction?
2976
2977 /* Calculate new air parcel position... */
2978 atm->lon[ip] +=
2979 DX2DEG(cache->uvwp[ip][0] * cache->dt[ip] / 1000., atm->lat[ip]);
2980 atm->lat[ip] += DY2DEG(cache->uvwp[ip][1] * cache->dt[ip] / 1000.);
2981 atm->p[ip] +=
2982 DZ2DP(cache->uvwp[ip][2] * cache->dt[ip] / 1000., atm->p[ip]);
2983 }
2984}
#define KARMAN
Karman's constant.
Definition: mptrac.h:223
#define THETAVIRT(p, t, h2o)
Compute virtual potential temperature.
Definition: mptrac.h:1797
#define DZ2DP(dz, p)
Convert a change in altitude to a change in pressure.
Definition: mptrac.h:639
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 2988 of file mptrac.c.

2994 {
2995
2996 /* Set timer... */
2997 SELECT_TIMER("MODULE_DIFF_TURB", "PHYSICS", NVTX_GPU);
2998
2999 /* Create random numbers... */
3000 module_rng(ctl, cache->rs, 3 * (size_t) atm->np, 1);
3001
3002 /* Loop over particles... */
3003 PARTICLE_LOOP(0, atm->np, 1,
3004 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3005
3006 /* Get PBL and surface pressure... */
3007 double pbl, ps;
3009 INTPOL_2D(pbl, 1);
3010 INTPOL_2D(ps, 0);
3011
3012 /* Get weighting factors... */
3013 const double wpbl = pbl_weight(ctl, atm, ip, pbl, ps);
3014 const double wtrop = tropo_weight(clim, atm, ip) * (1.0 - wpbl);
3015 const double wstrat = 1.0 - wpbl - wtrop;
3016
3017 /* Set diffusivity... */
3018 const double dx = wpbl * ctl->turb_dx_pbl + wtrop * ctl->turb_dx_trop
3019 + wstrat * ctl->turb_dx_strat;
3020 const double dz = wpbl * ctl->turb_dz_pbl + wtrop * ctl->turb_dz_trop
3021 + wstrat * ctl->turb_dz_strat;
3022
3023 /* Horizontal turbulent diffusion... */
3024 if (dx > 0) {
3025 const double sigma = sqrt(2.0 * dx * fabs(cache->dt[ip])) / 1000.;
3026 atm->lon[ip] += DX2DEG(cache->rs[3 * ip] * sigma, atm->lat[ip]);
3027 atm->lat[ip] += DY2DEG(cache->rs[3 * ip + 1] * sigma);
3028 }
3029
3030 /* Vertical turbulent diffusion... */
3031 if (dz > 0) {
3032 const double sigma = sqrt(2.0 * dz * fabs(cache->dt[ip])) / 1000.;
3033 atm->p[ip] += DZ2DP(cache->rs[3 * ip + 2] * sigma, atm->p[ip]);
3034 }
3035 }
3036}
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:6158
double turb_dz_trop
Vertical turbulent diffusion coefficient (troposphere) [m^2/s].
Definition: mptrac.h:2777
double turb_dx_strat
Horizontal turbulent diffusion coefficient (stratosphere) [m^2/s].
Definition: mptrac.h:2771
double turb_dx_trop
Horizontal turbulent diffusion coefficient (troposphere) [m^2/s].
Definition: mptrac.h:2768
double turb_dx_pbl
Horizontal turbulent diffusion coefficient (PBL) [m^2/s].
Definition: mptrac.h:2765
double turb_dz_strat
Vertical turbulent diffusion coefficient (stratosphere) [m^2/s].
Definition: mptrac.h:2780
double turb_dz_pbl
Vertical turbulent diffusion coefficient (PBL) [m^2/s].
Definition: mptrac.h:2774
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 3040 of file mptrac.c.

3045 {
3046
3047 /* Set timer... */
3048 SELECT_TIMER("MODULE_DRY_DEPO", "PHYSICS", NVTX_GPU);
3049
3050 /* Check quantity flags... */
3051 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
3052 ERRMSG("Module needs quantity mass or volume mixing ratio!");
3053
3054 /* Loop over particles... */
3055 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
3056
3057 /* Get surface pressure... */
3058 double ps;
3060 INTPOL_2D(ps, 1);
3061
3062 /* Check whether particle is above the surface layer... */
3063 if (atm->p[ip] < ps - ctl->dry_depo_dp)
3064 continue;
3065
3066 /* Set depth of surface layer... */
3067 const double dz = 1000. * (Z(ps - ctl->dry_depo_dp) - Z(ps));
3068
3069 /* Calculate sedimentation velocity for particles... */
3070 double v_dep;
3071 if (ctl->qnt_rp > 0 && ctl->qnt_rhop > 0) {
3072
3073 /* Get temperature... */
3074 double t;
3075 INTPOL_3D(t, 1);
3076
3077 /* Set deposition velocity... */
3078 v_dep = sedi(atm->p[ip], t, atm->q[ctl->qnt_rp][ip],
3079 atm->q[ctl->qnt_rhop][ip]);
3080 }
3081
3082 /* Use explicit sedimentation velocity for gases... */
3083 else
3084 v_dep = ctl->dry_depo_vdep;
3085
3086 /* Calculate loss of mass based on deposition velocity... */
3087 const double aux = exp(-cache->dt[ip] * v_dep / dz);
3088 if (ctl->qnt_m >= 0) {
3089 if (ctl->qnt_mloss_dry >= 0)
3090 atm->q[ctl->qnt_mloss_dry][ip]
3091 += atm->q[ctl->qnt_m][ip] * (1 - aux);
3092 atm->q[ctl->qnt_m][ip] *= aux;
3093 if (ctl->qnt_loss_rate >= 0)
3094 atm->q[ctl->qnt_loss_rate][ip] += v_dep / dz;
3095 }
3096 if (ctl->qnt_vmr >= 0)
3097 atm->q[ctl->qnt_vmr][ip] *= aux;
3098 }
3099}
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:10739
int qnt_rhop
Quantity array index for particle density.
Definition: mptrac.h:2289
int qnt_rp
Quantity array index for particle radius.
Definition: mptrac.h:2286
double dry_depo_dp
Dry deposition surface layer [hPa].
Definition: mptrac.h:3002
int qnt_mloss_dry
Quantity array index for total mass loss due to dry deposition.
Definition: mptrac.h:2433
double dry_depo_vdep
Dry deposition velocity [m/s].
Definition: mptrac.h:3005
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 3103 of file mptrac.c.

3109 {
3110
3111 /* Set timer... */
3112 SELECT_TIMER("MODULE_H2O2_CHEM", "PHYSICS", NVTX_GPU);
3113
3114 /* Check quantity flags... */
3115 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
3116 ERRMSG("Module needs quantity mass or volume mixing ratio!");
3117
3118 /* Parameter of SO2 correction... */
3119 const double a = 3.12541941e-06;
3120 const double b = -5.72532259e-01;
3121 const double low = pow(1. / a, 1. / b);
3122
3123 /* Loop over particles... */
3124 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
3125
3126 /* Check whether particle is inside cloud... */
3127 double lwc, rwc;
3129 INTPOL_3D(lwc, 1);
3130 INTPOL_3D(rwc, 0);
3131 if (!(lwc > 0 || rwc > 0))
3132 continue;
3133
3134 /* Get temperature... */
3135 double t;
3136 INTPOL_3D(t, 0);
3137
3138 /* Get molecular density... */
3139 const double M = MOLEC_DENS(atm->p[ip], t);
3140
3141 /* Reaction rate (Berglen et al., 2004)... */
3142 const double k = 9.1e7 * exp(-29700. / RI * (1. / t - 1. / 298.15)); /* (Maass, 1999), unit: M^(-2) */
3143
3144 /* Henry constant of SO2... */
3145 const double H_SO2 =
3146 1.3e-2 * exp(2900. * (1. / t - 1. / 298.15)) * RI * t;
3147 const double K_1S = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15)); /* unit: mol/L */
3148
3149 /* Henry constant of H2O2... */
3150 const double H_h2o2 =
3151 8.3e2 * exp(7600. * (1. / t - 1. / 298.15)) * RI * t;
3152
3153 /* Correction factor for high SO2 concentration
3154 (if qnt_Cx is defined, the correction is switched on)... */
3155 double cor = 1.0;
3156 if (ctl->qnt_Cx >= 0)
3157 cor = atm->q[ctl->qnt_Cx][ip] >
3158 low ? a * pow(atm->q[ctl->qnt_Cx][ip], b) : 1;
3159
3160 const double h2o2 = H_h2o2
3161 * clim_zm(&clim->h2o2, atm->time[ip], atm->lat[ip], atm->p[ip])
3162 * M * cor * 1000. / AVO; /* unit: mol/L */
3163
3164 /* Volume water content in cloud [m^3 m^(-3)]... */
3165 const double rho_air = atm->p[ip] / (RI * t) * MA / 10.;
3166 const double CWC = (lwc + rwc) * rho_air / 1e3;
3167
3168 /* Calculate exponential decay (Rolph et al., 1992)... */
3169 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
3170 const double aux = exp(-cache->dt[ip] * rate_coef);
3171 if (ctl->qnt_m >= 0) {
3172 if (ctl->qnt_mloss_h2o2 >= 0)
3173 atm->q[ctl->qnt_mloss_h2o2][ip] += atm->q[ctl->qnt_m][ip] * (1 - aux);
3174 atm->q[ctl->qnt_m][ip] *= aux;
3175 if (ctl->qnt_loss_rate >= 0)
3176 atm->q[ctl->qnt_loss_rate][ip] += rate_coef;
3177 }
3178 if (ctl->qnt_vmr >= 0)
3179 atm->q[ctl->qnt_vmr][ip] *= aux;
3180 }
3181}
#define AVO
Avogadro constant [1/mol].
Definition: mptrac.h:193
#define MOLEC_DENS(p, t)
Calculate the density of a gas molecule.
Definition: mptrac.h:1141
int qnt_mloss_h2o2
Quantity array index for total mass loss due to H2O2 chemistry.
Definition: mptrac.h:2424
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 3185 of file mptrac.c.

3190 {
3191
3192 double t;
3193
3194 /* Set timer... */
3195 SELECT_TIMER("MODULE_ISOSURF_INIT", "PHYSICS", NVTX_GPU);
3196
3197 /* Save pressure... */
3198 if (ctl->isosurf == 1) {
3199 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,atm)") {
3200 cache->iso_var[ip] = atm->p[ip];
3201 }
3202 }
3203
3204 /* Save density... */
3205 else if (ctl->isosurf == 2) {
3206 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,met0,met1,atm)") {
3208 INTPOL_3D(t, 1);
3209 cache->iso_var[ip] = atm->p[ip] / t;
3210 }
3211 }
3212
3213 /* Save potential temperature... */
3214 else if (ctl->isosurf == 3) {
3215 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,met0,met1,atm)") {
3217 INTPOL_3D(t, 1);
3218 cache->iso_var[ip] = THETA(atm->p[ip], t);
3219 }
3220 }
3221
3222 /* Read balloon pressure data... */
3223 else if (ctl->isosurf == 4) {
3224
3225 /* Write info... */
3226 LOG(1, "Read balloon pressure data: %s", ctl->balloon);
3227
3228 /* Open file... */
3229 FILE *in;
3230 if (!(in = fopen(ctl->balloon, "r")))
3231 ERRMSG("Cannot open file!");
3232
3233 /* Read pressure time series... */
3234 char line[LEN];
3235 while (fgets(line, LEN, in))
3236 if (sscanf(line, "%lg %lg", &(cache->iso_ts[cache->iso_n]),
3237 &(cache->iso_ps[cache->iso_n])) == 2)
3238 if ((++cache->iso_n) > NP)
3239 ERRMSG("Too many data points!");
3240
3241 /* Check number of points... */
3242 if (cache->iso_n < 1)
3243 ERRMSG("Could not read any data!");
3244
3245 /* Close file... */
3246 fclose(in);
3247
3248 /* Update of cache data on device... */
3249 mptrac_update_device(NULL, cache, NULL, NULL, NULL, NULL);
3250 }
3251}
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:5827
#define NP
Maximum number of atmospheric data points.
Definition: mptrac.h:328
double iso_ts[NP]
Isosurface balloon time [s].
Definition: mptrac.h:3352
int iso_n
Isosurface balloon number of data points.
Definition: mptrac.h:3355
double iso_ps[NP]
Isosurface balloon pressure [hPa].
Definition: mptrac.h:3349
double iso_var[NP]
Isosurface variables.
Definition: mptrac.h:3346
char balloon[LEN]
Balloon position filename.
Definition: mptrac.h:2749
int isosurf
Isosurface parameter (0=none, 1=pressure, 2=density, 3=theta, 4=balloon).
Definition: mptrac.h:2746
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 3255 of file mptrac.c.

3260 {
3261
3262 /* Set timer... */
3263 SELECT_TIMER("MODULE_ISOSURF", "PHYSICS", NVTX_GPU);
3264
3265 /* Loop over particles... */
3266 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,cache,met0,met1,atm)") {
3267
3268 /* Init... */
3269 double t;
3271
3272 /* Restore pressure... */
3273 if (ctl->isosurf == 1)
3274 atm->p[ip] = cache->iso_var[ip];
3275
3276 /* Restore density... */
3277 else if (ctl->isosurf == 2) {
3278 INTPOL_3D(t, 1);
3279 atm->p[ip] = cache->iso_var[ip] * t;
3280 }
3281
3282 /* Restore potential temperature... */
3283 else if (ctl->isosurf == 3) {
3284 INTPOL_3D(t, 1);
3285 atm->p[ip] = 1000. * pow(cache->iso_var[ip] / t, -1. / 0.286);
3286 }
3287
3288 /* Interpolate pressure... */
3289 else if (ctl->isosurf == 4) {
3290 if (atm->time[ip] <= cache->iso_ts[0])
3291 atm->p[ip] = cache->iso_ps[0];
3292 else if (atm->time[ip] >= cache->iso_ts[cache->iso_n - 1])
3293 atm->p[ip] = cache->iso_ps[cache->iso_n - 1];
3294 else {
3295 const int idx =
3296 locate_irr(cache->iso_ts, cache->iso_n, atm->time[ip]);
3297 atm->p[ip] =
3298 LIN(cache->iso_ts[idx], cache->iso_ps[idx], cache->iso_ts[idx + 1],
3299 cache->iso_ps[idx + 1], atm->time[ip]);
3300 }
3301 }
3302 }
3303}
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 3361 of file mptrac.c.

3367 {
3368
3369 /* Set timer... */
3370 SELECT_TIMER("MODULE_METEO", "PHYSICS", NVTX_GPU);
3371
3372 /* Check quantity flags... */
3373 if (ctl->qnt_tsts >= 0)
3374 if (ctl->qnt_tice < 0 || ctl->qnt_tnat < 0)
3375 ERRMSG("Need T_ice and T_NAT to calculate T_STS!");
3376
3377 /* Loop over particles... */
3378 PARTICLE_LOOP(0, atm->np, 0,
3379 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3380
3381 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
3382 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
3383 o3, lwc, rwc, iwc, swc, cc, z, zt;
3384
3385 /* Interpolate meteo data... */
3387 INTPOL_TIME_ALL(atm->time[ip], atm->p[ip], atm->lon[ip], atm->lat[ip]);
3388
3389 /* Set quantities... */
3390 SET_ATM(qnt_ps, ps);
3391 SET_ATM(qnt_ts, ts);
3392 SET_ATM(qnt_zs, zs);
3393 SET_ATM(qnt_us, us);
3394 SET_ATM(qnt_vs, vs);
3395 SET_ATM(qnt_ess, ess);
3396 SET_ATM(qnt_nss, nss);
3397 SET_ATM(qnt_shf, shf);
3398 SET_ATM(qnt_lsm, lsm);
3399 SET_ATM(qnt_sst, sst);
3400 SET_ATM(qnt_pbl, pbl);
3401 SET_ATM(qnt_pt, pt);
3402 SET_ATM(qnt_tt, tt);
3403 SET_ATM(qnt_zt, zt);
3404 SET_ATM(qnt_h2ot, h2ot);
3405 SET_ATM(qnt_zg, z);
3406 SET_ATM(qnt_p, atm->p[ip]);
3407 SET_ATM(qnt_t, t);
3408 SET_ATM(qnt_rho, RHO(atm->p[ip], t));
3409 SET_ATM(qnt_u, u);
3410 SET_ATM(qnt_v, v);
3411 SET_ATM(qnt_w, w);
3412 SET_ATM(qnt_h2o, h2o);
3413 SET_ATM(qnt_o3, o3);
3414 SET_ATM(qnt_lwc, lwc);
3415 SET_ATM(qnt_rwc, rwc);
3416 SET_ATM(qnt_iwc, iwc);
3417 SET_ATM(qnt_swc, swc);
3418 SET_ATM(qnt_cc, cc);
3419 SET_ATM(qnt_pct, pct);
3420 SET_ATM(qnt_pcb, pcb);
3421 SET_ATM(qnt_cl, cl);
3422 SET_ATM(qnt_plcl, plcl);
3423 SET_ATM(qnt_plfc, plfc);
3424 SET_ATM(qnt_pel, pel);
3425 SET_ATM(qnt_cape, cape);
3426 SET_ATM(qnt_cin, cin);
3427 SET_ATM(qnt_o3c, o3c);
3428 SET_ATM(qnt_hno3,
3429 clim_zm(&clim->hno3, atm->time[ip], atm->lat[ip], atm->p[ip]));
3430 SET_ATM(qnt_oh, clim_oh(ctl, clim, atm->time[ip],
3431 atm->lon[ip], atm->lat[ip], atm->p[ip]));
3432 SET_ATM(qnt_h2o2, clim_zm(&clim->h2o2, atm->time[ip],
3433 atm->lat[ip], atm->p[ip]));
3434 SET_ATM(qnt_ho2, clim_zm(&clim->ho2, atm->time[ip],
3435 atm->lat[ip], atm->p[ip]));
3436 SET_ATM(qnt_o1d, clim_zm(&clim->o1d, atm->time[ip],
3437 atm->lat[ip], atm->p[ip]));
3438 SET_ATM(qnt_vh, sqrt(u * u + v * v));
3439 SET_ATM(qnt_vz, -1e3 * H0 / atm->p[ip] * w);
3440 SET_ATM(qnt_psat, PSAT(t));
3441 SET_ATM(qnt_psice, PSICE(t));
3442 SET_ATM(qnt_pw, PW(atm->p[ip], h2o));
3443 SET_ATM(qnt_sh, SH(h2o));
3444 SET_ATM(qnt_rh, RH(atm->p[ip], t, h2o));
3445 SET_ATM(qnt_rhice, RHICE(atm->p[ip], t, h2o));
3446 SET_ATM(qnt_theta, THETA(atm->p[ip], t));
3447 SET_ATM(qnt_zeta, atm->q[ctl->qnt_zeta][ip]);
3448 SET_ATM(qnt_zeta_d, ZETA(ps, atm->p[ip], t));
3449 SET_ATM(qnt_zeta_dot, atm->q[ctl->qnt_zeta_dot][ip]);
3450 SET_ATM(qnt_tvirt, TVIRT(t, h2o));
3451 SET_ATM(qnt_lapse, lapse_rate(t, h2o));
3452 SET_ATM(qnt_pv, pv);
3453 SET_ATM(qnt_tdew, TDEW(atm->p[ip], h2o));
3454 SET_ATM(qnt_tice, TICE(atm->p[ip], h2o));
3455 SET_ATM(qnt_tnat,
3456 nat_temperature(atm->p[ip], h2o,
3457 clim_zm(&clim->hno3, atm->time[ip],
3458 atm->lat[ip], atm->p[ip])));
3459 SET_ATM(qnt_tsts,
3460 0.5 * (atm->q[ctl->qnt_tice][ip] + atm->q[ctl->qnt_tnat][ip]));
3461 }
3462}
double nat_temperature(const double p, const double h2o, const double hno3)
Calculates the nitric acid trihydrate (NAT) temperature.
Definition: mptrac.c:6134
double lapse_rate(const double t, const double h2o)
Calculates the moist adiabatic lapse rate in Kelvin per kilometer.
Definition: mptrac.c:1863
#define H0
Scale height [km].
Definition: mptrac.h:213
#define PSICE(t)
Compute saturation pressure over ice (WMO, 2018).
Definition: mptrac.h:1476
#define TICE(p, h2o)
Calculate frost point temperature (WMO, 2018).
Definition: mptrac.h:1744
#define RHICE(p, t, h2o)
Compute relative humidity over ice.
Definition: mptrac.h:1580
#define INTPOL_TIME_ALL(time, p, lon, lat)
Interpolate multiple meteorological variables in time.
Definition: mptrac.h:925
#define RH(p, t, h2o)
Compute relative humidity over water.
Definition: mptrac.h:1550
#define TDEW(p, h2o)
Calculate dew point temperature.
Definition: mptrac.h:1719
#define PSAT(t)
Compute saturation pressure over water.
Definition: mptrac.h:1452
clim_zm_t hno3
HNO3 zonal means.
Definition: mptrac.h:3504
int qnt_tnat
Quantity array index for T_NAT.
Definition: mptrac.h:2496
int qnt_tice
Quantity array index for T_ice.
Definition: mptrac.h:2490
int qnt_zeta_dot
Quantity array index forvelocity of zeta vertical coordinate.
Definition: mptrac.h:2469
int qnt_tsts
Quantity array index for T_STS.
Definition: mptrac.h:2493
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.
Author
Mingzhao Liu
Lars Hoffmann

Definition at line 3466 of file mptrac.c.

3470 {
3471
3472 /* Set timer... */
3473 SELECT_TIMER("MODULE_MIXING", "PHYSICS", NVTX_GPU);
3474
3475 /* Allocate... */
3476 const int np = atm->np;
3477 int *restrict const ixs = (int *) malloc((size_t) np * sizeof(int));
3478 int *restrict const iys = (int *) malloc((size_t) np * sizeof(int));
3479 int *restrict const izs = (int *) malloc((size_t) np * sizeof(int));
3480
3481 /* Set grid box size... */
3482 const double dz = (ctl->mixing_z1 - ctl->mixing_z0) / ctl->mixing_nz;
3483 const double dlon = (ctl->mixing_lon1 - ctl->mixing_lon0) / ctl->mixing_nx;
3484 const double dlat = (ctl->mixing_lat1 - ctl->mixing_lat0) / ctl->mixing_ny;
3485
3486 /* Set time interval... */
3487 const double t0 = t - 0.5 * ctl->dt_mod;
3488 const double t1 = t + 0.5 * ctl->dt_mod;
3489
3490 /* Get indices... */
3491#ifdef _OPENACC
3492#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
3493#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
3494#pragma acc parallel loop independent gang vector
3495#else
3496#pragma omp parallel for default(shared)
3497#endif
3498 for (int ip = 0; ip < np; ip++) {
3499 ixs[ip] = (int) ((atm->lon[ip] - ctl->mixing_lon0) / dlon);
3500 iys[ip] = (int) ((atm->lat[ip] - ctl->mixing_lat0) / dlat);
3501 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->mixing_z0) / dz);
3502 if (atm->time[ip] < t0 || atm->time[ip] > t1
3503 || ixs[ip] < 0 || ixs[ip] >= ctl->mixing_nx
3504 || iys[ip] < 0 || iys[ip] >= ctl->mixing_ny
3505 || izs[ip] < 0 || izs[ip] >= ctl->mixing_nz)
3506 izs[ip] = -1;
3507 }
3508
3509 /* Calculate interparcel mixing... */
3510 const int use_ensemble = (ctl->nens > 0);
3511
3512 const int quantities[] = {
3513 ctl->qnt_m, ctl->qnt_vmr, ctl->qnt_Ch2o, ctl->qnt_Co3,
3514 ctl->qnt_Cco, ctl->qnt_Coh, ctl->qnt_Ch, ctl->qnt_Cho2,
3515 ctl->qnt_Ch2o2, ctl->qnt_Co1d, ctl->qnt_Co3p, ctl->qnt_Cccl4,
3516 ctl->qnt_Cccl3f, ctl->qnt_Cccl2f2, ctl->qnt_Cn2o,
3517 ctl->qnt_Csf6, ctl->qnt_aoa
3518 };
3519 const int n_qnt = sizeof(quantities) / sizeof(quantities[0]);
3520
3521 for (int i = 0; i < n_qnt; i++)
3522 if (quantities[i] >= 0)
3523 module_mixing_help(ctl, clim, atm, ixs, iys, izs, quantities[i],
3524 use_ensemble);
3525
3526 /* Free... */
3527#ifdef _OPENACC
3528#pragma acc exit data delete(ixs,iys,izs)
3529#endif
3530 free(ixs);
3531 free(iys);
3532 free(izs);
3533}
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:3537
int qnt_Coh
Quantity array index for OH volume mixing ratio (chemistry code).
Definition: mptrac.h:2511
int mixing_nx
Number of longitudes of mixing grid.
Definition: mptrac.h:2906
double mixing_z1
Upper altitude of mixing grid [km].
Definition: mptrac.h:2903
int qnt_Co1d
Quantity array index for O(1D) volume mixing ratio (chemistry code).
Definition: mptrac.h:2523
double mixing_z0
Lower altitude of mixing grid [km].
Definition: mptrac.h:2900
int qnt_Cco
Quantity array index for CO volume mixing ratio (chemistry code).
Definition: mptrac.h:2508
int mixing_ny
Number of latitudes of mixing grid.
Definition: mptrac.h:2915
int qnt_Ch
Quantity array index for H volume mixing ratio (chemistry code).
Definition: mptrac.h:2514
double mixing_lat0
Lower latitude of mixing grid [deg].
Definition: mptrac.h:2918
int qnt_Cho2
Quantity array index for HO2 volume mixing ratio (chemistry code).
Definition: mptrac.h:2517
int mixing_nz
Number of altitudes of mixing grid.
Definition: mptrac.h:2897
double mixing_lon0
Lower longitude of mixing grid [deg].
Definition: mptrac.h:2909
double mixing_lat1
Upper latitude of mixing grid [deg].
Definition: mptrac.h:2921
int qnt_Co3p
Quantity array index for O(3P) volume mixing ratio (chemistry code).
Definition: mptrac.h:2526
int qnt_Ch2o2
Quantity array index for H2O2 volume mixing ratio (chemistry code).
Definition: mptrac.h:2520
double mixing_lon1
Upper longitude of mixing grid [deg].
Definition: mptrac.h:2912
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.
Author
Mingzhao Liu
Lars Hoffmann

Definition at line 3537 of file mptrac.c.

3545 {
3546
3547 const int np = atm->np;
3548 const int ngrid = ctl->mixing_nx * ctl->mixing_ny * ctl->mixing_nz;
3549 const int nens = use_ensemble ? ctl->nens : 1;
3550 const int total_grid = ngrid * nens;
3551
3552 double *restrict const cmean =
3553 (double *) malloc((size_t) total_grid * sizeof(double));
3554 int *restrict const count =
3555 (int *) malloc((size_t) total_grid * sizeof(int));
3556
3557 /* Init... */
3558#ifdef _OPENACC
3559#pragma acc enter data create(cmean[0:total_grid],count[0:total_grid])
3560#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
3561#pragma acc parallel loop independent gang vector
3562#else
3563#ifdef __NVCOMPILER
3564#pragma novector
3565#endif
3566#pragma omp parallel for
3567#endif
3568 for (int i = 0; i < total_grid; i++) {
3569 count[i] = 0;
3570 cmean[i] = 0.0;
3571 }
3572
3573 /* Loop over particles... */
3574#ifdef _OPENACC
3575#pragma acc parallel loop independent gang vector
3576#endif
3577 for (int ip = 0; ip < np; ip++)
3578 if (izs[ip] >= 0) {
3579 const int ens = use_ensemble ? (int) atm->q[ctl->qnt_ens][ip] : 0;
3580 const int idx =
3581 ens * ngrid + ARRAY_3D(ixs[ip], iys[ip], ctl->mixing_ny, izs[ip],
3582 ctl->mixing_nz);
3583#ifdef _OPENACC
3584#pragma acc atomic update
3585#endif
3586 cmean[idx] += atm->q[qnt_idx][ip];
3587#ifdef _OPENACC
3588#pragma acc atomic update
3589#endif
3590 count[idx]++;
3591 }
3592
3593 /* Compute means... */
3594#ifdef _OPENACC
3595#pragma acc parallel loop independent gang vector
3596#else
3597#ifdef __NVCOMPILER
3598#pragma novector
3599#endif
3600#pragma omp parallel for
3601#endif
3602 for (int i = 0; i < total_grid; i++)
3603 if (count[i] > 0)
3604 cmean[i] /= count[i];
3605
3606 /* Interparcel mixing... */
3607#ifdef _OPENACC
3608#pragma acc parallel loop independent gang vector
3609#else
3610#pragma omp parallel for
3611#endif
3612 for (int ip = 0; ip < np; ip++) {
3613 if (izs[ip] >= 0) {
3614 const int ens = use_ensemble ? (int) atm->q[ctl->qnt_ens][ip] : 0;
3615
3616 double mixparam = 1.0;
3617 if (ctl->mixing_trop < 1 || ctl->mixing_strat < 1) {
3618 const double w = tropo_weight(clim, atm, ip);
3619 mixparam = w * ctl->mixing_trop + (1.0 - w) * ctl->mixing_strat;
3620 }
3621
3622 const int idx =
3623 ens * ngrid + ARRAY_3D(ixs[ip], iys[ip], ctl->mixing_ny, izs[ip],
3624 ctl->mixing_nz);
3625 atm->q[qnt_idx][ip] += (cmean[idx] - atm->q[qnt_idx][ip]) * mixparam;
3626 }
3627 }
3628
3629 /* Free... */
3630#ifdef _OPENACC
3631#pragma acc exit data delete(cmean,count)
3632#endif
3633 free(cmean);
3634 free(count);
3635}
double mixing_trop
Interparcel exchange parameter for mixing in the troposphere.
Definition: mptrac.h:2891
double mixing_strat
Interparcel exchange parameter for mixing in the stratosphere.
Definition: mptrac.h:2894
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).
Author
Lars Hoffmann
Mingzhao Liu

Definition at line 3639 of file mptrac.c.

3645 {
3646
3647 /* Set timer... */
3648 SELECT_TIMER("MODULE_OH_CHEM", "PHYSICS", NVTX_GPU);
3649
3650 /* Check quantity flags... */
3651 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
3652 ERRMSG("Module needs quantity mass or volume mixing ratio!");
3653
3654 /* Parameter of SO2 correction... */
3655 const double a = 4.71572206e-08;
3656 const double b = -8.28782867e-01;
3657 const double low = pow(1. / a, 1. / b);
3658
3659 /* Loop over particles... */
3660 PARTICLE_LOOP(0, atm->np, 1,
3661 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3662
3663 /* Get temperature... */
3664 double t;
3666 INTPOL_3D(t, 1);
3667
3668 /* Calculate molecular density... */
3669 const double M = MOLEC_DENS(atm->p[ip], t);
3670
3671 /* Use constant reaction rate... */
3672 double k = NAN;
3673 if (ctl->oh_chem_reaction == 1)
3674 k = ctl->oh_chem[0];
3675
3676 /* Calculate bimolecular reaction rate... */
3677 else if (ctl->oh_chem_reaction == 2)
3678 k = ctl->oh_chem[0] * exp(-ctl->oh_chem[1] / t);
3679
3680 /* Calculate termolecular reaction rate... */
3681 if (ctl->oh_chem_reaction == 3) {
3682
3683 /* Calculate rate coefficient for X + OH + M -> XOH + M
3684 (JPL Publication 19-05) ... */
3685 const double k0 =
3686 ctl->oh_chem[0] * (ctl->oh_chem[1] !=
3687 0 ? pow(298. / t, ctl->oh_chem[1]) : 1.);
3688 const double ki =
3689 ctl->oh_chem[2] * (ctl->oh_chem[3] !=
3690 0 ? pow(298. / t, ctl->oh_chem[3]) : 1.);
3691 const double c = log10(k0 * M / ki);
3692 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
3693 }
3694
3695 /* Correction factor for high SO2 concentration
3696 (if qnt_Cx is defined, the correction is switched on)... */
3697 double cor = 1;
3698 if (ctl->qnt_Cx >= 0)
3699 cor =
3700 atm->q[ctl->qnt_Cx][ip] >
3701 low ? a * pow(atm->q[ctl->qnt_Cx][ip], b) : 1;
3702
3703 /* Calculate exponential decay... */
3704 const double rate_coef =
3705 k * clim_oh(ctl, clim, atm->time[ip], atm->lon[ip],
3706 atm->lat[ip], atm->p[ip]) * M * cor;
3707 const double aux = exp(-cache->dt[ip] * rate_coef);
3708 if (ctl->qnt_m >= 0) {
3709 if (ctl->qnt_mloss_oh >= 0)
3710 atm->q[ctl->qnt_mloss_oh][ip]
3711 += atm->q[ctl->qnt_m][ip] * (1 - aux);
3712 atm->q[ctl->qnt_m][ip] *= aux;
3713 if (ctl->qnt_loss_rate >= 0)
3714 atm->q[ctl->qnt_loss_rate][ip] += rate_coef;
3715 }
3716 if (ctl->qnt_vmr >= 0)
3717 atm->q[ctl->qnt_vmr][ip] *= aux;
3718 }
3719}
double oh_chem[4]
Coefficients for OH reaction rate (A, E/R or k0, n, kinf, m).
Definition: mptrac.h:2954
int oh_chem_reaction
Reaction type for OH chemistry (0=none, 2=bimolecular, 3=termolecular).
Definition: mptrac.h:2951
int qnt_mloss_oh
Quantity array index for total mass loss due to OH chemistry.
Definition: mptrac.h:2421
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 3723 of file mptrac.c.

3727 {
3728
3729 /* Set timer... */
3730 SELECT_TIMER("MODULE_POSITION", "PHYSICS", NVTX_GPU);
3731
3732 /* Loop over particles... */
3733 PARTICLE_LOOP(0, atm->np, 1, "acc data present(cache,met0,met1,atm)") {
3734
3735 /* Init... */
3736 double ps;
3738
3739 /* Calculate modulo... */
3740 atm->lon[ip] = FMOD(atm->lon[ip], 360.);
3741 atm->lat[ip] = FMOD(atm->lat[ip], 360.);
3742
3743 /* Check latitude... */
3744 while (atm->lat[ip] < -90 || atm->lat[ip] > 90) {
3745 if (atm->lat[ip] > 90) {
3746 atm->lat[ip] = 180 - atm->lat[ip];
3747 atm->lon[ip] += 180;
3748 }
3749 if (atm->lat[ip] < -90) {
3750 atm->lat[ip] = -180 - atm->lat[ip];
3751 atm->lon[ip] += 180;
3752 }
3753 }
3754
3755 /* Check longitude... */
3756 while (atm->lon[ip] < -180)
3757 atm->lon[ip] += 360;
3758 while (atm->lon[ip] >= 180)
3759 atm->lon[ip] -= 360;
3760
3761 /* Check pressure... */
3762 if (atm->p[ip] < met0->p[met0->np - 1]) {
3763 atm->p[ip] = met0->p[met0->np - 1];
3764 } else if (atm->p[ip] > 300.) {
3765 INTPOL_2D(ps, 1);
3766 if (atm->p[ip] > ps)
3767 atm->p[ip] = ps;
3768 }
3769 }
3770}

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

3775 {
3776
3777 /* Initialize GSL random number generators... */
3778 gsl_rng_env_setup();
3779 if (omp_get_max_threads() > NTHREADS)
3780 ERRMSG("Too many threads!");
3781 for (int i = 0; i < NTHREADS; i++) {
3782 rng[i] = gsl_rng_alloc(gsl_rng_default);
3783 gsl_rng_set(rng[i], gsl_rng_default_seed
3784 + (long unsigned) (ntask * NTHREADS + i));
3785 }
3786
3787 /* Initialize cuRAND random number generators... */
3788#ifdef CURAND
3789 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
3790 CURAND_STATUS_SUCCESS)
3791 ERRMSG("Cannot create random number generator!");
3792 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
3793 CURAND_STATUS_SUCCESS)
3794 ERRMSG("Cannot set seed for random number generator!");
3795 if (curandSetStream
3796 (rng_curand,
3797 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
3798 CURAND_STATUS_SUCCESS)
3799 ERRMSG("Cannot set stream for random number generator!");
3800#endif
3801}
#define NTHREADS
Maximum number of OpenMP threads.
Definition: mptrac.h:353

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

3809 {
3810
3811 /* Use GSL random number generators... */
3812 if (ctl->rng_type == 0) {
3813
3814 /* Uniform distribution... */
3815 if (method == 0) {
3816#pragma omp parallel for default(shared)
3817 for (size_t i = 0; i < n; ++i)
3818 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
3819 }
3820
3821 /* Normal distribution... */
3822 else if (method == 1) {
3823#pragma omp parallel for default(shared)
3824 for (size_t i = 0; i < n; ++i)
3825 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
3826 }
3827
3828 /* Update of random numbers on device... */
3829#ifdef _OPENACC
3830 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
3831#pragma acc update device(rs[:n])
3832#endif
3833 }
3834
3835 /* Use Squares random number generator (Widynski, 2022)... */
3836 else if (ctl->rng_type == 1) {
3837
3838 /* Set key (don't change this!)... */
3839 const uint64_t key = 0xc8e4fd154ce32f6d;
3840
3841 /* Uniform distribution... */
3842#ifdef _OPENACC
3843#pragma acc data present(rs)
3844#pragma acc parallel loop independent gang vector
3845#else
3846#pragma omp parallel for default(shared)
3847#endif
3848 for (size_t i = 0; i < n + 1; ++i) {
3849 uint64_t r, t, x, y, z;
3850 y = x = (rng_ctr + i) * key;
3851 z = y + key;
3852 x = x * x + y;
3853 x = (x >> 32) | (x << 32);
3854 x = x * x + z;
3855 x = (x >> 32) | (x << 32);
3856 x = x * x + y;
3857 x = (x >> 32) | (x << 32);
3858 t = x = x * x + z;
3859 x = (x >> 32) | (x << 32);
3860 r = t ^ ((x * x + y) >> 32);
3861 rs[i] = (double) r / (double) UINT64_MAX;
3862 }
3863 rng_ctr += n + 1;
3864
3865 /* Normal distribution... */
3866 if (method == 1) {
3867#ifdef _OPENACC
3868#pragma acc parallel loop independent gang vector
3869#else
3870#pragma omp parallel for default(shared)
3871#endif
3872 for (size_t i = 0; i < n; i += 2) {
3873 const double r = sqrt(-2.0 * log(rs[i]));
3874 const double phi = 2.0 * M_PI * rs[i + 1];
3875 rs[i] = r * cosf((float) phi);
3876 rs[i + 1] = r * sinf((float) phi);
3877 }
3878 }
3879 }
3880
3881 /* Use cuRAND random number generators... */
3882 else if (ctl->rng_type == 2) {
3883#ifdef CURAND
3884#pragma acc host_data use_device(rs)
3885 {
3886
3887 /* Uniform distribution... */
3888 if (method == 0) {
3889 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
3890 CURAND_STATUS_SUCCESS)
3891 ERRMSG("Cannot create random numbers!");
3892 }
3893
3894 /* Normal distribution... */
3895 else if (method == 1) {
3896 if (curandGenerateNormalDouble
3897 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
3898 1.0) != CURAND_STATUS_SUCCESS)
3899 ERRMSG("Cannot create random numbers!");
3900 }
3901 }
3902#else
3903 ERRMSG("MPTRAC was compiled without cuRAND!");
3904#endif
3905 }
3906}
int rng_type
Random number generator (0=GSL, 1=Squares, 2=cuRAND).
Definition: mptrac.h:2759

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

3915 {
3916
3917 /* Set timer... */
3918 SELECT_TIMER("MODULE_SEDI", "PHYSICS", NVTX_GPU);
3919
3920 /* Loop over particles... */
3921 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
3922
3923 /* Get temperature... */
3924 double t;
3926 INTPOL_3D(t, 1);
3927
3928 /* Sedimentation velocity... */
3929 const double v_s = sedi(atm->p[ip], t, atm->q[ctl->qnt_rp][ip],
3930 atm->q[ctl->qnt_rhop][ip]);
3931
3932 /* Calculate pressure change... */
3933 atm->p[ip] += DZ2DP(v_s * cache->dt[ip] / 1000., atm->p[ip]);
3934 }
3935}
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 3939 of file mptrac.c.

3942 {
3943
3944 /* Set timer... */
3945 SELECT_TIMER("MODULE_SORT", "PHYSICS", NVTX_GPU);
3946
3947 /* Allocate... */
3948 const int np = atm->np;
3949 double *restrict const a = (double *) malloc((size_t) np * sizeof(double));
3950 int *restrict const p = (int *) malloc((size_t) np * sizeof(int));
3951 if (a == NULL || p == NULL)
3952 ERRMSG("Out of memory!");
3953
3954#ifdef _OPENACC
3955#pragma acc enter data create(a[0:np],p[0:np])
3956#pragma acc data present(ctl,met0,atm,a,p)
3957#endif
3958
3959 /* Get box index... */
3960#ifdef _OPENACC
3961#pragma acc parallel loop independent gang vector
3962#else
3963#pragma omp parallel for default(shared)
3964#endif
3965 for (int ip = 0; ip < np; ip++) {
3966 a[ip] =
3967 (double) ((locate_reg(met0->lon, met0->nx, atm->lon[ip]) * met0->ny +
3968 locate_irr(met0->lat, met0->ny, atm->lat[ip]))
3969 * met0->np + locate_irr(met0->p, met0->np, atm->p[ip]));
3970 p[ip] = ip;
3971 }
3972
3973 /* Sorting... */
3974#ifdef THRUST
3975#ifdef _OPENACC
3976#pragma acc host_data use_device(a,p)
3977#endif
3978 thrustSortWrapper(a, np, p);
3979#else
3980#ifdef _OPENACC
3981 ERRMSG("GSL sort fallback not available on GPU, use THRUST!");
3982#endif
3983 gsl_sort_index((size_t *) p, a, 1, (size_t) np);
3984#endif
3985
3986 /* Sort data... */
3987 module_sort_help(atm->time, p, np);
3988 module_sort_help(atm->p, p, np);
3989 module_sort_help(atm->lon, p, np);
3990 module_sort_help(atm->lat, p, np);
3991 for (int iq = 0; iq < ctl->nq; iq++)
3992 module_sort_help(atm->q[iq], p, np);
3993
3994 /* Free... */
3995#ifdef _OPENACC
3996#pragma acc exit data delete(a,p)
3997#endif
3998 free(a);
3999 free(p);
4000}
void module_sort_help(double *a, const int *p, const int np)
Reorder an array based on a given permutation.
Definition: mptrac.c:4004
int nq
Number of quantities.
Definition: mptrac.h:2256
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 4004 of file mptrac.c.

4007 {
4008
4009 /* Allocate... */
4010 double *restrict const help =
4011 (double *) malloc((size_t) np * sizeof(double));
4012 if (help == NULL)
4013 ERRMSG("Out of memory!");
4014
4015 /* Reordering of array... */
4016#ifdef _OPENACC
4017#pragma acc enter data create(help[0:np])
4018#pragma acc data present(a,p,help)
4019#pragma acc parallel loop independent gang vector
4020#else
4021#pragma omp parallel for default(shared)
4022#endif
4023 for (int ip = 0; ip < np; ip++)
4024 help[ip] = a[p[ip]];
4025#ifdef _OPENACC
4026#pragma acc parallel loop independent gang vector
4027#else
4028#pragma omp parallel for default(shared)
4029#endif
4030 for (int ip = 0; ip < np; ip++)
4031 a[ip] = help[ip];
4032
4033 /* Free... */
4034#ifdef _OPENACC
4035#pragma acc exit data delete(help)
4036#endif
4037 free(help);
4038}

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

4047 {
4048
4049 /* Set timer... */
4050 SELECT_TIMER("MODULE_TIMESTEPS", "PHYSICS", NVTX_GPU);
4051
4052 const double latmin = gsl_stats_min(met0->lat, 1, (size_t) met0->ny),
4053 latmax = gsl_stats_max(met0->lat, 1, (size_t) met0->ny);
4054
4055 const int local =
4056 (fabs(met0->lon[met0->nx - 1] - met0->lon[0] - 360.0) >= 0.01);
4057
4058 /* Loop over particles... */
4059 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,cache,met0,atm)") {
4060
4061 /* Set time step for each air parcel... */
4062 if ((ctl->direction * (atm->time[ip] - ctl->t_start) >= 0
4063 && ctl->direction * (atm->time[ip] - ctl->t_stop) <= 0
4064 && ctl->direction * (atm->time[ip] - t) < 0))
4065 cache->dt[ip] = t - atm->time[ip];
4066 else
4067 cache->dt[ip] = 0.0;
4068
4069 /* Check horizontal boundaries of local meteo data... */
4070#ifndef DD
4071 int dd = 1;
4072#else
4073 int dd = 0;
4074#endif
4075 if (dd) {
4076 if (local && (atm->lon[ip] <= met0->lon[0]
4077 || atm->lon[ip] >= met0->lon[met0->nx - 1]
4078 || atm->lat[ip] <= latmin || atm->lat[ip] >= latmax))
4079 cache->dt[ip] = 0.0;
4080 } else {
4081 if ((int) atm->q[ctl->qnt_subdomain][ip] == -1)
4082 cache->dt[ip] = 0;
4083 }
4084 }
4085}
int direction
Direction flag (1=forward calculation, -1=backward calculation).
Definition: mptrac.h:2553
double t_stop
Stop time of simulation [s].
Definition: mptrac.h:2559
int qnt_subdomain
Quantity array index for current subdomain in domain decomposition.
Definition: mptrac.h:2547
double t_start
Start time of simulation [s].
Definition: mptrac.h:2556

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

4091 {
4092
4093 /* Set timer... */
4094 SELECT_TIMER("MODULE_TIMESTEPS_INIT", "PHYSICS", NVTX_GPU);
4095
4096 /* Set start time... */
4097 if (ctl->direction == 1) {
4098 ctl->t_start = gsl_stats_min(atm->time, 1, (size_t) atm->np);
4099 if (ctl->t_stop > 1e99)
4100 ctl->t_stop = gsl_stats_max(atm->time, 1, (size_t) atm->np);
4101 } else {
4102 ctl->t_start = gsl_stats_max(atm->time, 1, (size_t) atm->np);
4103 if (ctl->t_stop > 1e99)
4104 ctl->t_stop = gsl_stats_min(atm->time, 1, (size_t) atm->np);
4105 }
4106
4107 /* Check time interval... */
4108 if (ctl->direction * (ctl->t_stop - ctl->t_start) <= 0)
4109 ERRMSG("Nothing to do! Check T_STOP and DIRECTION!");
4110
4111 /* Round start time... */
4112 if (ctl->direction == 1)
4113 ctl->t_start = floor(ctl->t_start / ctl->dt_mod) * ctl->dt_mod;
4114 else
4115 ctl->t_start = ceil(ctl->t_start / ctl->dt_mod) * ctl->dt_mod;
4116}

◆ 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.
Author
Mingzhao Liu
Lars Hoffmann

Definition at line 4120 of file mptrac.c.

4126 {
4127
4128 /* Set timer... */
4129 SELECT_TIMER("MODULE_TRACER_CHEM", "PHYSICS", NVTX_GPU);
4130
4131 /* Loop over particles... */
4132 PARTICLE_LOOP(0, atm->np, 1,
4133 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4134
4135 /* Get temperature... */
4136 double t;
4138 INTPOL_3D(t, 1);
4139
4140 /* Get molecular density... */
4141 const double M = MOLEC_DENS(atm->p[ip], t);
4142
4143 /* Get total column ozone... */
4144 double o3c;
4145 INTPOL_2D(o3c, 1);
4146
4147 /* Get solar zenith angle... */
4148 const double sza = sza_calc(atm->time[ip], atm->lon[ip], atm->lat[ip]);
4149
4150 /* Get O(1D) volume mixing ratio... */
4151 const double o1d =
4152 clim_zm(&clim->o1d, atm->time[ip], atm->lat[ip], atm->p[ip]);
4153
4154 /* Reactions for CFC-10... */
4155 if (ctl->qnt_Cccl4 >= 0) {
4156 const double K_o1d = ARRHENIUS(3.30e-10, 0, t) * o1d * M;
4157 const double K_hv = clim_photo(clim->photo.ccl4, &(clim->photo),
4158 atm->p[ip], sza, o3c);
4159 atm->q[ctl->qnt_Cccl4][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4160 }
4161
4162 /* Reactions for CFC-11... */
4163 if (ctl->qnt_Cccl3f >= 0) {
4164 const double K_o1d = ARRHENIUS(2.30e-10, 0, t) * o1d * M;
4165 const double K_hv = clim_photo(clim->photo.ccl3f, &(clim->photo),
4166 atm->p[ip], sza, o3c);
4167 atm->q[ctl->qnt_Cccl3f][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4168 }
4169
4170 /* Reactions for CFC-12... */
4171 if (ctl->qnt_Cccl2f2 >= 0) {
4172 const double K_o1d = ARRHENIUS(1.40e-10, -25, t) * o1d * M;
4173 const double K_hv = clim_photo(clim->photo.ccl2f2, &(clim->photo),
4174 atm->p[ip], sza, o3c);
4175 atm->q[ctl->qnt_Cccl2f2][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4176 }
4177
4178 /* Reactions for N2O... */
4179 if (ctl->qnt_Cn2o >= 0) {
4180 const double K_o1d = ARRHENIUS(1.19e-10, -20, t) * o1d * M;
4181 const double K_hv = clim_photo(clim->photo.n2o, &(clim->photo),
4182 atm->p[ip], sza, o3c);
4183 atm->q[ctl->qnt_Cn2o][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4184 }
4185 }
4186}
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:148
#define ARRHENIUS(a, b, t)
Calculate the Arrhenius rate constant.
Definition: mptrac.h:493
double ccl2f2[CP][CSZA][CO3]
CCl2F2 photolysis rate [1/s].
Definition: mptrac.h:3405
double ccl3f[CP][CSZA][CO3]
CCl3F photolysis rate [1/s].
Definition: mptrac.h:3402
double n2o[CP][CSZA][CO3]
N2O photolysis rate [1/s].
Definition: mptrac.h:3396
double ccl4[CP][CSZA][CO3]
CCl4 photolysis rate [1/s].
Definition: mptrac.h:3399
clim_photo_t photo
Photolysis rates.
Definition: mptrac.h:3501
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.
Author
Lars Hoffmann
Mingzhao Liu

Definition at line 4190 of file mptrac.c.

4195 {
4196
4197 /* Set timer... */
4198 SELECT_TIMER("MODULE_WET_DEPO", "PHYSICS", NVTX_GPU);
4199
4200 /* Check quantity flags... */
4201 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
4202 ERRMSG("Module needs quantity mass or volume mixing ratio!");
4203
4204 /* Loop over particles... */
4205 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
4206
4207 /* Check whether particle is below cloud top... */
4208 double pct;
4210 INTPOL_2D(pct, 1);
4211 if (!isfinite(pct) || atm->p[ip] <= pct)
4212 continue;
4213
4214 /* Get cloud bottom pressure... */
4215 double pcb;
4216 INTPOL_2D(pcb, 0);
4217
4218 /* Estimate precipitation rate (Pisso et al., 2019)... */
4219 double cl;
4220 INTPOL_2D(cl, 0);
4221 const double Is =
4222 pow(1. / ctl->wet_depo_pre[0] * cl, 1. / ctl->wet_depo_pre[1]);
4223 if (Is < 0.01)
4224 continue;
4225
4226 /* Check whether particle is inside or below cloud... */
4227 double lwc, rwc, iwc, swc;
4228 INTPOL_3D(lwc, 1);
4229 INTPOL_3D(rwc, 0);
4230 INTPOL_3D(iwc, 0);
4231 INTPOL_3D(swc, 0);
4232 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
4233
4234 /* Get temperature... */
4235 double t;
4236 INTPOL_3D(t, 0);
4237
4238 /* Calculate in-cloud scavenging coefficient... */
4239 double lambda = 0;
4240 if (inside) {
4241
4242 /* Calculate retention factor... */
4243 double eta;
4244 if (t > 273.15)
4245 eta = 1;
4246 else if (t <= 238.15)
4247 eta = ctl->wet_depo_ic_ret_ratio;
4248 else
4249 eta = LIN(273.15, 1, 238.15, ctl->wet_depo_ic_ret_ratio, t);
4250
4251 /* Use exponential dependency for particles (Bakels et al., 2024)... */
4252 if (ctl->wet_depo_ic_a > 0)
4253 lambda = ctl->wet_depo_ic_a * pow(Is, ctl->wet_depo_ic_b) * eta;
4254
4255 /* Use Henry's law for gases... */
4256 else if (ctl->wet_depo_ic_h[0] > 0) {
4257
4258 /* Get Henry's constant (Burkholder et al., 2019; Sander, 2023)... */
4259 double h = ctl->wet_depo_ic_h[0]
4260 * exp(ctl->wet_depo_ic_h[1] * (1. / t - 1. / 298.15));
4261
4262 /* Use effective Henry's constant for SO2
4263 (Berglen, 2004; Simpson, 2012)... */
4264 if (ctl->wet_depo_so2_ph > 0) {
4265 const double H_ion = pow(10., -ctl->wet_depo_so2_ph);
4266 const double K_1 = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
4267 const double K_2 = 6e-8 * exp(1.12e3 * (1. / t - 1. / 298.15));
4268 h *= (1. + K_1 / H_ion + K_1 * K_2 / SQR(H_ion));
4269 }
4270
4271 /* Estimate depth of cloud layer... */
4272 const double dz = 1e3 * (Z(pct) - Z(pcb));
4273
4274 /* Calculate scavenging coefficient... */
4275 lambda = h * RI * t * Is / 3.6e6 / dz * eta;
4276 }
4277 }
4278
4279 /* Calculate below-cloud scavenging coefficient... */
4280 else {
4281
4282 /* Calculate retention factor... */
4283 double eta;
4284 if (t > 270)
4285 eta = 1;
4286 else
4287 eta = ctl->wet_depo_bc_ret_ratio;
4288
4289 /* Use exponential dependency for particles (Bakels et al., 2024)... */
4290 if (ctl->wet_depo_bc_a > 0)
4291 lambda = ctl->wet_depo_bc_a * pow(Is, ctl->wet_depo_bc_b) * eta;
4292
4293 /* Use Henry's law for gases... */
4294 else if (ctl->wet_depo_bc_h[0] > 0) {
4295
4296 /* Get Henry's constant (Burkholder et al., 2019; Sander, 2023)... */
4297 const double h = ctl->wet_depo_bc_h[0]
4298 * exp(ctl->wet_depo_bc_h[1] * (1. / t - 1. / 298.15));
4299
4300 /* Estimate depth of cloud layer... */
4301 const double dz = 1e3 * (Z(pct) - Z(pcb));
4302
4303 /* Calculate scavenging coefficient... */
4304 lambda = h * RI * t * Is / 3.6e6 / dz * eta;
4305 }
4306 }
4307
4308 /* Calculate exponential decay of mass... */
4309 const double aux = exp(-cache->dt[ip] * lambda);
4310 if (ctl->qnt_m >= 0) {
4311 if (ctl->qnt_mloss_wet >= 0)
4312 atm->q[ctl->qnt_mloss_wet][ip]
4313 += atm->q[ctl->qnt_m][ip] * (1 - aux);
4314 atm->q[ctl->qnt_m][ip] *= aux;
4315 if (ctl->qnt_loss_rate >= 0)
4316 atm->q[ctl->qnt_loss_rate][ip] += lambda;
4317 }
4318 if (ctl->qnt_vmr >= 0)
4319 atm->q[ctl->qnt_vmr][ip] *= aux;
4320 }
4321}
double wet_depo_ic_a
Coefficient A for wet deposition in cloud (exponential form).
Definition: mptrac.h:2981
double wet_depo_bc_a
Coefficient A for wet deposition below cloud (exponential form).
Definition: mptrac.h:2975
int qnt_mloss_wet
Quantity array index for total mass loss due to wet deposition.
Definition: mptrac.h:2430
double wet_depo_so2_ph
pH value used to calculate effective Henry constant of SO2.
Definition: mptrac.h:2993
double wet_depo_pre[2]
Coefficients for precipitation calculation.
Definition: mptrac.h:2972
double wet_depo_bc_h[2]
Coefficients for wet deposition below cloud (Henry's law: Hb, Cb).
Definition: mptrac.h:2990
double wet_depo_bc_ret_ratio
Coefficients for wet deposition below cloud: retention ratio.
Definition: mptrac.h:2999
double wet_depo_ic_h[2]
Coefficients for wet deposition in cloud (Henry's law: Hb, Cb).
Definition: mptrac.h:2987
double wet_depo_ic_ret_ratio
Coefficients for wet deposition in cloud: retention ratio.
Definition: mptrac.h:2996
double wet_depo_ic_b
Coefficient B for wet deposition in cloud (exponential form).
Definition: mptrac.h:2984
double wet_depo_bc_b
Coefficient B for wet deposition below cloud (exponential form).
Definition: mptrac.h:2978

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

4331 {
4332
4333 /* Initialize GPU... */
4334#ifdef _OPENACC
4335 SELECT_TIMER("ACC_INIT", "INIT", NVTX_GPU);
4336 int rank = 0;
4337#ifdef MPI
4338 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
4339#endif
4340 if (acc_get_num_devices(acc_device_nvidia) <= 0)
4341 ERRMSG("Not running on a GPU device!");
4342 acc_set_device_num(rank % acc_get_num_devices(acc_device_nvidia),
4343 acc_device_nvidia);
4344 acc_device_t device_type = acc_get_device_type();
4345 acc_init(device_type);
4346#endif
4347
4348 /* Allocate... */
4349 SELECT_TIMER("ALLOC", "MEMORY", NVTX_CPU);
4350 ALLOC(*ctl, ctl_t, 1);
4351 ALLOC(*cache, cache_t, 1);
4352 ALLOC(*clim, clim_t, 1);
4353 ALLOC(*met0, met_t, 1);
4354 ALLOC(*met1, met_t, 1);
4355 ALLOC(*atm, atm_t, 1);
4356
4357 /* Create data region on GPU... */
4358#ifdef _OPENACC
4359 SELECT_TIMER("CREATE_DATA_REGION", "MEMORY", NVTX_GPU);
4360 ctl_t *ctlup = *ctl;
4361 cache_t *cacheup = *cache;
4362 clim_t *climup = *clim;
4363 met_t *met0up = *met0;
4364 met_t *met1up = *met1;
4365 atm_t *atmup = *atm;
4366#pragma acc enter data create(ctlup[:1],cacheup[:1],climup[:1],met0up[:1],met1up[:1],atmup[:1])
4367#endif
4368}
Air parcel data.
Definition: mptrac.h:3264
Cache data structure.
Definition: mptrac.h:3343
Climatological data.
Definition: mptrac.h:3483
Control parameters.
Definition: mptrac.h:2249
Meteo data structure.
Definition: mptrac.h:3542

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

4388 {
4389#endif
4390
4391 /* Delete data region on GPU... */
4392#ifdef _OPENACC
4393 SELECT_TIMER("DELETE_DATA_REGION", "MEMORY", NVTX_GPU);
4394#pragma acc exit data delete (ctl,cache,clim,met0,met1,atm)
4395#endif
4396
4397 /* Free... */
4398 SELECT_TIMER("FREE", "MEMORY", NVTX_CPU);
4399 free(atm);
4400 free(ctl);
4401 free(cache);
4402 free(clim);
4403 free(met0);
4404 free(met1);
4405
4406 /* Free MPI datatype... */
4407#ifdef DD
4408 MPI_Type_free(&mpi_info->MPI_Particle);
4409#endif
4410}

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

4419 {
4420
4421 static int init;
4422
4423 met_t *mets;
4424
4425 char cachefile[LEN], cmd[2 * LEN], filename[LEN];
4426
4427 /* Set timer... */
4428 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4429
4430 /* Init... */
4431 if (t == ctl->t_start || !init) {
4432 init = 1;
4433
4434 /* Read meteo data... */
4435 get_met_help(ctl, t + (ctl->direction == -1 ? -1 : 0), -1,
4436 ctl->metbase, ctl->dt_met, filename);
4437 if (!mptrac_read_met(filename, ctl, clim, *met0))
4438 ERRMSG("Cannot open file!");
4439
4440 get_met_help(ctl, t + (ctl->direction == 1 ? 1 : 0), 1,
4441 ctl->metbase, ctl->dt_met, filename);
4442 if (!mptrac_read_met(filename, ctl, clim, *met1))
4443 ERRMSG("Cannot open file!");
4444
4445 /* Update GPU... */
4446 mptrac_update_device(NULL, NULL, NULL, met0, met1, NULL);
4447 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4448
4449 /* Caching... */
4450 if (ctl->met_cache && t != ctl->t_stop) {
4451 get_met_help(ctl, t + 1.1 * ctl->dt_met * ctl->direction,
4452 ctl->direction, ctl->metbase, ctl->dt_met, cachefile);
4453 sprintf(cmd, "cat %s > /dev/null &", cachefile);
4454 LOG(1, "Caching: %s", cachefile);
4455 if (system(cmd) != 0)
4456 WARN("Caching command failed!");
4457 }
4458 }
4459
4460 /* Read new data for forward trajectories... */
4461 if (t > (*met1)->time) {
4462
4463 /* Pointer swap... */
4464 mets = *met1;
4465 *met1 = *met0;
4466 *met0 = mets;
4467
4468 /* Read new meteo data... */
4469 get_met_help(ctl, t, 1, ctl->metbase, ctl->dt_met, filename);
4470 if (!mptrac_read_met(filename, ctl, clim, *met1))
4471 ERRMSG("Cannot open file!");
4472
4473 /* Update GPU... */
4474 mptrac_update_device(NULL, NULL, NULL, NULL, met1, NULL);
4475 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4476
4477 /* Caching... */
4478 if (ctl->met_cache && t != ctl->t_stop) {
4479 get_met_help(ctl, t + ctl->dt_met, 1, ctl->metbase, ctl->dt_met,
4480 cachefile);
4481 sprintf(cmd, "cat %s > /dev/null &", cachefile);
4482 LOG(1, "Caching: %s", cachefile);
4483 if (system(cmd) != 0)
4484 WARN("Caching command failed!");
4485 }
4486 }
4487
4488 /* Read new data for backward trajectories... */
4489 if (t < (*met0)->time) {
4490
4491 /* Pointer swap... */
4492 mets = *met1;
4493 *met1 = *met0;
4494 *met0 = mets;
4495
4496 /* Read new meteo data... */
4497 get_met_help(ctl, t, -1, ctl->metbase, ctl->dt_met, filename);
4498 if (!mptrac_read_met(filename, ctl, clim, *met0))
4499 ERRMSG("Cannot open file!");
4500
4501 /* Update GPU... */
4502 mptrac_update_device(NULL, NULL, NULL, met0, NULL, NULL);
4503 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4504
4505 /* Caching... */
4506 if (ctl->met_cache && t != ctl->t_stop) {
4507 get_met_help(ctl, t - ctl->dt_met, -1, ctl->metbase, ctl->dt_met,
4508 cachefile);
4509 sprintf(cmd, "cat %s > /dev/null &", cachefile);
4510 LOG(1, "Caching: %s", cachefile);
4511 if (system(cmd) != 0)
4512 WARN("Caching command failed!");
4513 }
4514 }
4515
4516 /* Check that grids are consistent... */
4517 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
4518 if ((*met0)->nx != (*met1)->nx
4519 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
4520 ERRMSG("Meteo grid dimensions do not match!");
4521 for (int ix = 0; ix < (*met0)->nx; ix++)
4522 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
4523 ERRMSG("Meteo grid longitudes do not match!");
4524 for (int iy = 0; iy < (*met0)->ny; iy++)
4525 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
4526 ERRMSG("Meteo grid latitudes do not match!");
4527 for (int ip = 0; ip < (*met0)->np; ip++)
4528 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
4529 ERRMSG("Meteo grid pressure levels do not match!");
4530 }
4531}
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:5558
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:1110
int met_cache
Preload meteo data into disk cache (0=no, 1=yes).
Definition: mptrac.h:2732
char metbase[LEN]
Basename for meteo data.
Definition: mptrac.h:2569
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 4535 of file mptrac.c.

4540 {
4541
4542 /* Initialize timesteps... */
4543 module_timesteps_init(ctl, atm);
4544
4545 /* Initialize random number generator... */
4546 module_rng_init(ntask);
4547
4548 /* Update GPU memory... */
4549 mptrac_update_device(ctl, cache, clim, NULL, NULL, atm);
4550}
void module_timesteps_init(ctl_t *ctl, const atm_t *atm)
Initialize start time and time interval for time-stepping.
Definition: mptrac.c:4089
void module_rng_init(const int ntask)
Initialize random number generators for parallel tasks.
Definition: mptrac.c:3774
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 4554 of file mptrac.c.

4557 {
4558
4559 int result;
4560
4561 /* Set timer... */
4562 SELECT_TIMER("READ_ATM", "INPUT", NVTX_READ);
4563
4564 /* Init... */
4565 atm->np = 0;
4566
4567 /* Write info... */
4568 LOG(1, "Read atmospheric data: %s", filename);
4569
4570 /* Read ASCII data... */
4571 if (ctl->atm_type == 0)
4572 result = read_atm_asc(filename, ctl, atm);
4573
4574 /* Read binary data... */
4575 else if (ctl->atm_type == 1)
4576 result = read_atm_bin(filename, ctl, atm);
4577
4578 /* Read netCDF data... */
4579 else if (ctl->atm_type == 2)
4580 result = read_atm_nc(filename, ctl, atm);
4581
4582 /* Read CLaMS data... */
4583 else if (ctl->atm_type == 3 || ctl->atm_type == 4)
4584 result = read_atm_clams(filename, ctl, atm);
4585
4586 /* Error... */
4587 else
4588 ERRMSG("Atmospheric data type not supported!");
4589
4590 /* Check result... */
4591 if (result != 1)
4592 return 0;
4593
4594 /* Check number of air parcels... */
4595 if (atm->np < 1)
4596 ERRMSG("Can not read any data!");
4597
4598 /* Write info... */
4599 double mini, maxi;
4600 LOG(2, "Number of particles: %d", atm->np);
4601 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
4602 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
4603 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
4604 LOG(2, "Altitude range: %g ... %g km", Z(maxi), Z(mini));
4605 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
4606 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
4607 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
4608 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
4609 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
4610 for (int iq = 0; iq < ctl->nq; iq++) {
4611 char msg[5 * LEN];
4612 sprintf(msg, "Quantity %s range: %s ... %s %s",
4613 ctl->qnt_name[iq], ctl->qnt_format[iq],
4614 ctl->qnt_format[iq], ctl->qnt_unit[iq]);
4615 gsl_stats_minmax(&mini, &maxi, atm->q[iq], 1, (size_t) atm->np);
4616 LOG(2, msg, mini, maxi);
4617 }
4618
4619 /* Return success... */
4620 return 1;
4621}
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:6338
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:6222
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:6278
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:6180
char qnt_format[NQ][LEN]
Quantity output format.
Definition: mptrac.h:2268
int atm_type
Type of atmospheric data files (0=ASCII, 1=binary, 2=netCDF, 3=CLaMS_traj, 4=CLaMS_pos).
Definition: mptrac.h:3034
char qnt_unit[NQ][LEN]
Quantity units.
Definition: mptrac.h:2265
char qnt_name[NQ][LEN]
Quantity names.
Definition: mptrac.h:2259
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.
Author
Lars Hoffmann
Mingzhao Liu

Definition at line 4625 of file mptrac.c.

4627 {
4628
4629 /* Set timer... */
4630 SELECT_TIMER("READ_CLIM", "INPUT", NVTX_READ);
4631
4632 /* Init tropopause climatology... */
4633 clim_tropo_init(clim);
4634
4635 /* Read photolysis rates... */
4636 if (ctl->clim_photo[0] != '-')
4637 read_clim_photo(ctl->clim_photo, &clim->photo);
4638
4639 /* Read HNO3 climatology... */
4640 if (ctl->clim_hno3_filename[0] != '-')
4641 read_clim_zm(ctl->clim_hno3_filename, "HNO3", &clim->hno3);
4642
4643 /* Read OH climatology... */
4644 if (ctl->clim_oh_filename[0] != '-') {
4645 read_clim_zm(ctl->clim_oh_filename, "OH", &clim->oh);
4646 if (ctl->oh_chem_beta > 0)
4647 clim_oh_diurnal_correction(ctl, clim);
4648 }
4649
4650 /* Read H2O2 climatology... */
4651 if (ctl->clim_h2o2_filename[0] != '-')
4652 read_clim_zm(ctl->clim_h2o2_filename, "H2O2", &clim->h2o2);
4653
4654 /* Read HO2 climatology... */
4655 if (ctl->clim_ho2_filename[0] != '-')
4656 read_clim_zm(ctl->clim_ho2_filename, "HO2", &clim->ho2);
4657
4658 /* Read O(1D) climatology... */
4659 if (ctl->clim_o1d_filename[0] != '-')
4660 read_clim_zm(ctl->clim_o1d_filename, "O1D", &clim->o1d);
4661
4662 /* Read CFC-10 time series... */
4663 if (ctl->clim_ccl4_timeseries[0] != '-')
4665
4666 /* Read CFC-11 time series... */
4667 if (ctl->clim_ccl3f_timeseries[0] != '-')
4669
4670 /* Read CFC-12 time series... */
4671 if (ctl->clim_ccl2f2_timeseries[0] != '-')
4673
4674 /* Read N2O time series... */
4675 if (ctl->clim_n2o_timeseries[0] != '-')
4676 read_clim_ts(ctl->clim_n2o_timeseries, &clim->n2o);
4677
4678 /* Read SF6 time series... */
4679 if (ctl->clim_sf6_timeseries[0] != '-')
4680 read_clim_ts(ctl->clim_sf6_timeseries, &clim->sf6);
4681}
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:6371
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:6490
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:6544
void clim_tropo_init(clim_t *clim)
Initializes the tropopause data in the climatology structure.
Definition: mptrac.c:233
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:115
char clim_ho2_filename[LEN]
Filename of HO2 climatology.
Definition: mptrac.h:2864
char clim_o1d_filename[LEN]
Filename of O(1D) climatology.
Definition: mptrac.h:2867
char clim_photo[LEN]
Filename of photolysis rates climatology.
Definition: mptrac.h:2852
char clim_h2o2_filename[LEN]
Filename of H2O2 climatology.
Definition: mptrac.h:2861
char clim_oh_filename[LEN]
Filename of OH climatology.
Definition: mptrac.h:2858
char clim_hno3_filename[LEN]
Filename of HNO3 climatology.
Definition: mptrac.h:2855
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 4685 of file mptrac.c.

4689 {
4690
4691 /* Set timer... */
4692 SELECT_TIMER("READ_CTL", "INPUT", NVTX_READ);
4693
4694 /* Write info... */
4695 LOG(1, "\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
4696 "(executable: %s | version: %s | compiled: %s, %s)\n",
4697 argv[0], VERSION, __DATE__, __TIME__);
4698
4699 /* Initialize quantity indices... */
4700 ctl->qnt_idx = -1;
4701 ctl->qnt_ens = -1;
4702 ctl->qnt_stat = -1;
4703 ctl->qnt_m = -1;
4704 ctl->qnt_vmr = -1;
4705 ctl->qnt_rp = -1;
4706 ctl->qnt_rhop = -1;
4707 ctl->qnt_ps = -1;
4708 ctl->qnt_ts = -1;
4709 ctl->qnt_zs = -1;
4710 ctl->qnt_us = -1;
4711 ctl->qnt_vs = -1;
4712 ctl->qnt_ess = -1;
4713 ctl->qnt_nss = -1;
4714 ctl->qnt_shf = -1;
4715 ctl->qnt_lsm = -1;
4716 ctl->qnt_sst = -1;
4717 ctl->qnt_pbl = -1;
4718 ctl->qnt_pt = -1;
4719 ctl->qnt_tt = -1;
4720 ctl->qnt_zt = -1;
4721 ctl->qnt_h2ot = -1;
4722 ctl->qnt_zg = -1;
4723 ctl->qnt_p = -1;
4724 ctl->qnt_t = -1;
4725 ctl->qnt_rho = -1;
4726 ctl->qnt_u = -1;
4727 ctl->qnt_v = -1;
4728 ctl->qnt_w = -1;
4729 ctl->qnt_h2o = -1;
4730 ctl->qnt_o3 = -1;
4731 ctl->qnt_lwc = -1;
4732 ctl->qnt_rwc = -1;
4733 ctl->qnt_iwc = -1;
4734 ctl->qnt_swc = -1;
4735 ctl->qnt_cc = -1;
4736 ctl->qnt_pct = -1;
4737 ctl->qnt_pcb = -1;
4738 ctl->qnt_cl = -1;
4739 ctl->qnt_plcl = -1;
4740 ctl->qnt_plfc = -1;
4741 ctl->qnt_pel = -1;
4742 ctl->qnt_cape = -1;
4743 ctl->qnt_cin = -1;
4744 ctl->qnt_o3c = -1;
4745 ctl->qnt_hno3 = -1;
4746 ctl->qnt_oh = -1;
4747 ctl->qnt_h2o2 = -1;
4748 ctl->qnt_ho2 = -1;
4749 ctl->qnt_o1d = -1;
4750 ctl->qnt_mloss_oh = -1;
4751 ctl->qnt_mloss_h2o2 = -1;
4752 ctl->qnt_mloss_kpp = -1;
4753 ctl->qnt_mloss_wet = -1;
4754 ctl->qnt_mloss_dry = -1;
4755 ctl->qnt_mloss_decay = -1;
4756 ctl->qnt_loss_rate = -1;
4757 ctl->qnt_psat = -1;
4758 ctl->qnt_psice = -1;
4759 ctl->qnt_pw = -1;
4760 ctl->qnt_sh = -1;
4761 ctl->qnt_rh = -1;
4762 ctl->qnt_rhice = -1;
4763 ctl->qnt_theta = -1;
4764 ctl->qnt_zeta = -1;
4765 ctl->qnt_zeta_d = -1;
4766 ctl->qnt_zeta_dot = -1;
4767 ctl->qnt_tvirt = -1;
4768 ctl->qnt_lapse = -1;
4769 ctl->qnt_vh = -1;
4770 ctl->qnt_vz = -1;
4771 ctl->qnt_pv = -1;
4772 ctl->qnt_tdew = -1;
4773 ctl->qnt_tice = -1;
4774 ctl->qnt_tsts = -1;
4775 ctl->qnt_tnat = -1;
4776 ctl->qnt_Cx = -1;
4777 ctl->qnt_Ch2o = -1;
4778 ctl->qnt_Co3 = -1;
4779 ctl->qnt_Cco = -1;
4780 ctl->qnt_Coh = -1;
4781 ctl->qnt_Ch = -1;
4782 ctl->qnt_Cho2 = -1;
4783 ctl->qnt_Ch2o2 = -1;
4784 ctl->qnt_Co1d = -1;
4785 ctl->qnt_Co3p = -1;
4786 ctl->qnt_Cccl4 = -1;
4787 ctl->qnt_Cccl3f = -1;
4788 ctl->qnt_Cccl2f2 = -1;
4789 ctl->qnt_Cn2o = -1;
4790 ctl->qnt_Csf6 = -1;
4791 ctl->qnt_aoa = -1;
4792
4793#ifdef DD
4794 ctl->qnt_destination = -1;
4795 ctl->qnt_subdomain = -1;
4796#endif
4797
4798 /* Read quantities... */
4799 ctl->nq = (int) scan_ctl(filename, argc, argv, "NQ", -1, "0", NULL);
4800 if (ctl->nq > NQ)
4801 ERRMSG("Too many quantities!");
4802 for (int iq = 0; iq < ctl->nq; iq++) {
4803
4804 /* Read quantity name and format... */
4805 scan_ctl(filename, argc, argv, "QNT_NAME", iq, "", ctl->qnt_name[iq]);
4806 scan_ctl(filename, argc, argv, "QNT_LONGNAME", iq, ctl->qnt_name[iq],
4807 ctl->qnt_longname[iq]);
4808 scan_ctl(filename, argc, argv, "QNT_FORMAT", iq, "%g",
4809 ctl->qnt_format[iq]);
4810 if (strcasecmp(ctl->qnt_name[iq], "aoa") == 0)
4811 sprintf(ctl->qnt_format[iq], "%%.2f");
4812
4813 /* Try to identify quantity... */
4814 SET_QNT(qnt_idx, "idx", "particle index", "-")
4815 SET_QNT(qnt_ens, "ens", "ensemble index", "-")
4816 SET_QNT(qnt_stat, "stat", "station flag", "-")
4817 SET_QNT(qnt_m, "m", "mass", "kg")
4818 SET_QNT(qnt_vmr, "vmr", "volume mixing ratio", "ppv")
4819 SET_QNT(qnt_rp, "rp", "particle radius", "microns")
4820 SET_QNT(qnt_rhop, "rhop", "particle density", "kg/m^3")
4821 SET_QNT(qnt_ps, "ps", "surface pressure", "hPa")
4822 SET_QNT(qnt_ts, "ts", "surface temperature", "K")
4823 SET_QNT(qnt_zs, "zs", "surface height", "km")
4824 SET_QNT(qnt_us, "us", "surface zonal wind", "m/s")
4825 SET_QNT(qnt_vs, "vs", "surface meridional wind", "m/s")
4826 SET_QNT(qnt_ess, "ess", "eastward turbulent surface stress", "N/m^2")
4827 SET_QNT(qnt_nss, "nss", "northward turbulent surface stress", "N/m^2")
4828 SET_QNT(qnt_shf, "shf", "surface sensible heat flux", "W/m^2")
4829 SET_QNT(qnt_lsm, "lsm", "land-sea mask", "1")
4830 SET_QNT(qnt_sst, "sst", "sea surface temperature", "K")
4831 SET_QNT(qnt_pbl, "pbl", "planetary boundary layer", "hPa")
4832 SET_QNT(qnt_pt, "pt", "tropopause pressure", "hPa")
4833 SET_QNT(qnt_tt, "tt", "tropopause temperature", "K")
4834 SET_QNT(qnt_zt, "zt", "tropopause geopotential height", "km")
4835 SET_QNT(qnt_h2ot, "h2ot", "tropopause water vapor", "ppv")
4836 SET_QNT(qnt_zg, "zg", "geopotential height", "km")
4837 SET_QNT(qnt_p, "p", "pressure", "hPa")
4838 SET_QNT(qnt_t, "t", "temperature", "K")
4839 SET_QNT(qnt_rho, "rho", "air density", "kg/m^3")
4840 SET_QNT(qnt_u, "u", "zonal wind", "m/s")
4841 SET_QNT(qnt_v, "v", "meridional wind", "m/s")
4842 SET_QNT(qnt_w, "w", "vertical velocity", "hPa/s")
4843 SET_QNT(qnt_h2o, "h2o", "water vapor", "ppv")
4844 SET_QNT(qnt_o3, "o3", "ozone", "ppv")
4845 SET_QNT(qnt_lwc, "lwc", "cloud liquid water content", "kg/kg")
4846 SET_QNT(qnt_rwc, "rwc", "cloud rain water content", "kg/kg")
4847 SET_QNT(qnt_iwc, "iwc", "cloud ice water content", "kg/kg")
4848 SET_QNT(qnt_swc, "swc", "cloud snow water content", "kg/kg")
4849 SET_QNT(qnt_cc, "cc", "cloud cover", "1")
4850 SET_QNT(qnt_pct, "pct", "cloud top pressure", "hPa")
4851 SET_QNT(qnt_pcb, "pcb", "cloud bottom pressure", "hPa")
4852 SET_QNT(qnt_cl, "cl", "total column cloud water", "kg/m^2")
4853 SET_QNT(qnt_plcl, "plcl", "lifted condensation level", "hPa")
4854 SET_QNT(qnt_plfc, "plfc", "level of free convection", "hPa")
4855 SET_QNT(qnt_pel, "pel", "equilibrium level", "hPa")
4856 SET_QNT(qnt_cape, "cape", "convective available potential energy",
4857 "J/kg")
4858 SET_QNT(qnt_cin, "cin", "convective inhibition", "J/kg")
4859 SET_QNT(qnt_o3c, "o3c", "total column ozone", "DU")
4860 SET_QNT(qnt_hno3, "hno3", "nitric acid", "ppv")
4861 SET_QNT(qnt_oh, "oh", "hydroxyl radical", "ppv")
4862 SET_QNT(qnt_h2o2, "h2o2", "hydrogen peroxide", "ppv")
4863 SET_QNT(qnt_ho2, "ho2", "hydroperoxyl radical", "ppv")
4864 SET_QNT(qnt_o1d, "o1d", "atomic oxygen", "ppv")
4865 SET_QNT(qnt_mloss_oh, "mloss_oh", "mass loss due to OH chemistry", "kg")
4866 SET_QNT(qnt_mloss_h2o2, "mloss_h2o2",
4867 "mass loss due to H2O2 chemistry", "kg")
4868 SET_QNT(qnt_mloss_kpp, "mloss_kpp", "mass loss due to kpp chemistry",
4869 "kg")
4870 SET_QNT(qnt_mloss_wet, "mloss_wet", "mass loss due to wet deposition",
4871 "kg")
4872 SET_QNT(qnt_mloss_dry, "mloss_dry", "mass loss due to dry deposition",
4873 "kg")
4874 SET_QNT(qnt_mloss_decay, "mloss_decay",
4875 "mass loss due to exponential decay", "kg")
4876 SET_QNT(qnt_loss_rate, "loss_rate", "total loss rate", "s^-1")
4877 SET_QNT(qnt_psat, "psat", "saturation pressure over water", "hPa")
4878 SET_QNT(qnt_psice, "psice", "saturation pressure over ice", "hPa")
4879 SET_QNT(qnt_pw, "pw", "partial water vapor pressure", "hPa")
4880 SET_QNT(qnt_sh, "sh", "specific humidity", "kg/kg")
4881 SET_QNT(qnt_rh, "rh", "relative humidity", "%%")
4882 SET_QNT(qnt_rhice, "rhice", "relative humidity over ice", "%%")
4883 SET_QNT(qnt_theta, "theta", "potential temperature", "K")
4884 SET_QNT(qnt_zeta, "zeta", "zeta coordinate", "K")
4885 SET_QNT(qnt_zeta_d, "zeta_d", "diagnosed zeta coordinate", "K")
4886 SET_QNT(qnt_zeta_dot, "zeta_dot", "velocity of zeta coordinate",
4887 "K/day")
4888 SET_QNT(qnt_tvirt, "tvirt", "virtual temperature", "K")
4889 SET_QNT(qnt_lapse, "lapse", "temperature lapse rate", "K/km")
4890 SET_QNT(qnt_vh, "vh", "horizontal velocity", "m/s")
4891 SET_QNT(qnt_vz, "vz", "vertical velocity", "m/s")
4892 SET_QNT(qnt_pv, "pv", "potential vorticity", "PVU")
4893 SET_QNT(qnt_tdew, "tdew", "dew point temperature", "K")
4894 SET_QNT(qnt_tice, "tice", "frost point temperature", "K")
4895 SET_QNT(qnt_tsts, "tsts", "STS existence temperature", "K")
4896 SET_QNT(qnt_tnat, "tnat", "NAT existence temperature", "K")
4897 SET_QNT(qnt_Cx, "Cx", "Trace species x volume mixing ratio", "ppv")
4898 SET_QNT(qnt_Ch2o, "Ch2o", "H2O volume mixing ratio", "ppv")
4899 SET_QNT(qnt_Co3, "Co3", "O3 volume mixing ratio", "ppv")
4900 SET_QNT(qnt_Cco, "Cco", "CO volume mixing ratio", "ppv")
4901 SET_QNT(qnt_Coh, "Coh", "HO volume mixing ratio", "ppv")
4902 SET_QNT(qnt_Ch, "Ch", "H radical volume mixing ratio", "ppv")
4903 SET_QNT(qnt_Cho2, "Cho2", "HO2 volume mixing ratio", "ppv")
4904 SET_QNT(qnt_Ch2o2, "Ch2o2", "H2O2 volume mixing ratio", "ppv")
4905 SET_QNT(qnt_Co1d, "Co1d", "O(1D) volume mixing ratio", "ppv")
4906 SET_QNT(qnt_Co3p, "Co3p", "O(3P) radical volume mixing ratio", "ppv")
4907 SET_QNT(qnt_Cccl4, "Cccl4", "CCl4 (CFC-10) volume mixing ratio", "ppv")
4908 SET_QNT(qnt_Cccl3f, "Cccl3f", "CCl3F (CFC-11) volume mixing ratio",
4909 "ppv")
4910 SET_QNT(qnt_Cccl2f2, "Cccl2f2", "CCl2F2 (CFC-12) volume mixing ratio",
4911 "ppv")
4912 SET_QNT(qnt_Cn2o, "Cn2o", "N2O volume mixing ratio", "ppv")
4913 SET_QNT(qnt_Csf6, "Csf6", "SF6 volume mixing ratio", "ppv")
4914 SET_QNT(qnt_aoa, "aoa", "age of air", "s")
4915#ifdef DD
4916 SET_QNT(qnt_destination, "destination",
4917 "subdomain index of destination", "-")
4918 SET_QNT(qnt_subdomain, "subdomain", "current subdomain index", "-")
4919#endif
4920 scan_ctl(filename, argc, argv, "QNT_UNIT", iq, "", ctl->qnt_unit[iq]);
4921 }
4922
4923 /* Vertical coordinates and velocities... */
4924 ctl->advect_vert_coord =
4925 (int) scan_ctl(filename, argc, argv, "ADVECT_VERT_COORD", -1, "0", NULL);
4926 if (ctl->advect_vert_coord < 0 || ctl->advect_vert_coord > 2)
4927 ERRMSG("Set ADVECT_VERT_COORD to 0, 1, or 2!");
4928 ctl->met_vert_coord =
4929 (int) scan_ctl(filename, argc, argv, "MET_VERT_COORD", -1, "0", NULL);
4930 if (ctl->met_vert_coord < 0 || ctl->met_vert_coord > 4)
4931 ERRMSG("Set MET_VERT_COORD to 0, 1, 2, 3, or 4!");
4932 if (ctl->advect_vert_coord == 1 && ctl->qnt_zeta < 0)
4933 ERRMSG("Please add zeta to your quantities for diabatic calculations!");
4934 if (ctl->advect_vert_coord == 2 && ctl->met_vert_coord == 0)
4935 ERRMSG
4936 ("Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
4937
4938 /* Time steps of simulation... */
4939 ctl->direction =
4940 (int) scan_ctl(filename, argc, argv, "DIRECTION", -1, "1", NULL);
4941 if (ctl->direction != -1 && ctl->direction != 1)
4942 ERRMSG("Set DIRECTION to -1 or 1!");
4943 ctl->t_stop = scan_ctl(filename, argc, argv, "T_STOP", -1, "1e100", NULL);
4944 ctl->dt_mod = scan_ctl(filename, argc, argv, "DT_MOD", -1, "180", NULL);
4945
4946 /* Meteo data... */
4947 scan_ctl(filename, argc, argv, "METBASE", -1, "-", ctl->metbase);
4948 ctl->dt_met = scan_ctl(filename, argc, argv, "DT_MET", -1, "3600", NULL);
4949 ctl->met_convention =
4950 (int) scan_ctl(filename, argc, argv, "MET_CONVENTION", -1, "0", NULL);
4951 ctl->met_type =
4952 (int) scan_ctl(filename, argc, argv, "MET_TYPE", -1, "0", NULL);
4953 if (ctl->advect_vert_coord == 1 && ctl->met_type != 0)
4954 ERRMSG
4955 ("Please use meteo files in netcdf format for diabatic calculations.");
4956 ctl->met_clams =
4957 (int) scan_ctl(filename, argc, argv, "MET_CLAMS", -1, "0", NULL);
4958 ctl->met_nc_scale =
4959 (int) scan_ctl(filename, argc, argv, "MET_NC_SCALE", -1, "1", NULL);
4960 ctl->met_nc_level =
4961 (int) scan_ctl(filename, argc, argv, "MET_NC_LEVEL", -1, "0", NULL);
4962 ctl->met_nc_quant =
4963 (int) scan_ctl(filename, argc, argv, "MET_NC_QUANT", -1, "0", NULL);
4964 ctl->met_zstd_level =
4965 (int) scan_ctl(filename, argc, argv, "MET_ZSTD_LEVEL", -1, "0", NULL);
4966 for (int i = 0; i < METVAR; i++) {
4967 char defprec[LEN] = "0", deftol[LEN] = "0.0";
4968 if (i == 0) /* geopotential height */
4969 sprintf(deftol, "0.5");
4970 else if (i == 1) /* temperature */
4971 sprintf(deftol, "5.0");
4972 else /* other variables */
4973 sprintf(defprec, "8");
4974 ctl->met_comp_prec[i] =
4975 (int) scan_ctl(filename, argc, argv, "MET_COMP_PREC", i, defprec, NULL);
4976 ctl->met_comp_tol[i] =
4977 scan_ctl(filename, argc, argv, "MET_COMP_TOL", i, deftol, NULL);
4978 }
4979 ctl->met_cms_batch =
4980 (int) scan_ctl(filename, argc, argv, "MET_CMS_BATCH", -1, "-1", NULL);
4981 ctl->met_cms_zstd =
4982 (int) scan_ctl(filename, argc, argv, "MET_CMS_ZSTD", -1, "1", NULL);
4983 ctl->met_cms_heur =
4984 (int) scan_ctl(filename, argc, argv, "MET_CMS_HEUR", -1, "1", NULL);
4985 ctl->met_cms_eps_z =
4986 scan_ctl(filename, argc, argv, "MET_CMS_EPS_Z", -1, "1.0", NULL);
4987 ctl->met_cms_eps_t =
4988 scan_ctl(filename, argc, argv, "MET_CMS_EPS_T", -1, "0.05", NULL);
4989 ctl->met_cms_eps_u =
4990 scan_ctl(filename, argc, argv, "MET_CMS_EPS_U", -1, "0.05", NULL);
4991 ctl->met_cms_eps_v =
4992 scan_ctl(filename, argc, argv, "MET_CMS_EPS_V", -1, "0.05", NULL);
4993 ctl->met_cms_eps_w =
4994 scan_ctl(filename, argc, argv, "MET_CMS_EPS_W", -1, "1.0", NULL);
4995 ctl->met_cms_eps_pv =
4996 scan_ctl(filename, argc, argv, "MET_CMS_EPS_PV", -1, "1.0", NULL);
4997 ctl->met_cms_eps_h2o =
4998 scan_ctl(filename, argc, argv, "MET_CMS_EPS_H2O", -1, "1.0", NULL);
4999 ctl->met_cms_eps_o3 =
5000 scan_ctl(filename, argc, argv, "MET_CMS_EPS_O3", -1, "1.0", NULL);
5001 ctl->met_cms_eps_lwc =
5002 scan_ctl(filename, argc, argv, "MET_CMS_EPS_LWC", -1, "1.0", NULL);
5003 ctl->met_cms_eps_rwc =
5004 scan_ctl(filename, argc, argv, "MET_CMS_EPS_RWC", -1, "1.0", NULL);
5005 ctl->met_cms_eps_iwc =
5006 scan_ctl(filename, argc, argv, "MET_CMS_EPS_IWC", -1, "1.0", NULL);
5007 ctl->met_cms_eps_swc =
5008 scan_ctl(filename, argc, argv, "MET_CMS_EPS_SWC", -1, "1.0", NULL);
5009 ctl->met_cms_eps_cc =
5010 scan_ctl(filename, argc, argv, "MET_CMS_EPS_CC", -1, "1.0", NULL);
5011 ctl->met_dx = (int) scan_ctl(filename, argc, argv, "MET_DX", -1, "1", NULL);
5012 ctl->met_dy = (int) scan_ctl(filename, argc, argv, "MET_DY", -1, "1", NULL);
5013 ctl->met_dp = (int) scan_ctl(filename, argc, argv, "MET_DP", -1, "1", NULL);
5014 if (ctl->met_dx < 1 || ctl->met_dy < 1 || ctl->met_dp < 1)
5015 ERRMSG("MET_DX, MET_DY, and MET_DP need to be greater than zero!");
5016 ctl->met_sx = (int) scan_ctl(filename, argc, argv, "MET_SX", -1, "1", NULL);
5017 ctl->met_sy = (int) scan_ctl(filename, argc, argv, "MET_SY", -1, "1", NULL);
5018 ctl->met_sp = (int) scan_ctl(filename, argc, argv, "MET_SP", -1, "1", NULL);
5019 if (ctl->met_sx < 1 || ctl->met_sy < 1 || ctl->met_sp < 1)
5020 ERRMSG("MET_SX, MET_SY, and MET_SP need to be greater than zero!");
5021 ctl->met_detrend =
5022 scan_ctl(filename, argc, argv, "MET_DETREND", -1, "-999", NULL);
5023 ctl->met_np = (int) scan_ctl(filename, argc, argv, "MET_NP", -1, "0", NULL);
5024 if (ctl->met_np > EP)
5025 ERRMSG("Too many pressure levels!");
5026 ctl->met_press_level_def =
5027 (int) scan_ctl(filename, argc, argv, "MET_PRESS_LEVEL_DEF", -1, "-1",
5028 NULL);
5029 if (ctl->met_press_level_def >= 0) {
5030 level_definitions(ctl);
5031 } else {
5032 if (ctl->met_np > 0) {
5033 for (int ip = 0; ip < ctl->met_np; ip++)
5034 ctl->met_p[ip] =
5035 scan_ctl(filename, argc, argv, "MET_P", ip, "", NULL);
5036 }
5037 }
5038 ctl->met_nlev =
5039 (int) scan_ctl(filename, argc, argv, "MET_NLEV", -1, "0", NULL);
5040 if (ctl->met_nlev > EP)
5041 ERRMSG("Too many model levels!");
5042 for (int ip = 0; ip < ctl->met_nlev; ip++) {
5043 ctl->met_lev_hyam[ip] =
5044 scan_ctl(filename, argc, argv, "MET_LEV_HYAM", ip, "", NULL);
5045 ctl->met_lev_hybm[ip] =
5046 scan_ctl(filename, argc, argv, "MET_LEV_HYBM", ip, "", NULL);
5047 }
5048 ctl->met_geopot_sx =
5049 (int) scan_ctl(filename, argc, argv, "MET_GEOPOT_SX", -1, "-1", NULL);
5050 ctl->met_geopot_sy =
5051 (int) scan_ctl(filename, argc, argv, "MET_GEOPOT_SY", -1, "-1", NULL);
5052 ctl->met_relhum =
5053 (int) scan_ctl(filename, argc, argv, "MET_RELHUM", -1, "0", NULL);
5054 ctl->met_cape =
5055 (int) scan_ctl(filename, argc, argv, "MET_CAPE", -1, "1", NULL);
5056 if (ctl->met_cape < 0 || ctl->met_cape > 1)
5057 ERRMSG("Set MET_CAPE to 0 or 1!");
5058 ctl->met_pbl =
5059 (int) scan_ctl(filename, argc, argv, "MET_PBL", -1, "3", NULL);
5060 if (ctl->met_pbl < 0 || ctl->met_pbl > 3)
5061 ERRMSG("Set MET_PBL to 0 ... 3!");
5062 ctl->met_pbl_min =
5063 scan_ctl(filename, argc, argv, "MET_PBL_MIN", -1, "0.1", NULL);
5064 ctl->met_pbl_max =
5065 scan_ctl(filename, argc, argv, "MET_PBL_MAX", -1, "5.0", NULL);
5066 ctl->met_tropo =
5067 (int) scan_ctl(filename, argc, argv, "MET_TROPO", -1, "3", NULL);
5068 if (ctl->met_tropo < 0 || ctl->met_tropo > 5)
5069 ERRMSG("Set MET_TROPO to 0 ... 5!");
5070 ctl->met_tropo_pv =
5071 scan_ctl(filename, argc, argv, "MET_TROPO_PV", -1, "3.5", NULL);
5072 ctl->met_tropo_theta =
5073 scan_ctl(filename, argc, argv, "MET_TROPO_THETA", -1, "380", NULL);
5074 ctl->met_tropo_spline =
5075 (int) scan_ctl(filename, argc, argv, "MET_TROPO_SPLINE", -1, "1", NULL);
5076 ctl->met_dt_out =
5077 scan_ctl(filename, argc, argv, "MET_DT_OUT", -1, "0.1", NULL);
5078 ctl->met_cache =
5079 (int) scan_ctl(filename, argc, argv, "MET_CACHE", -1, "0", NULL);
5080 ctl->met_mpi_share =
5081 (int) scan_ctl(filename, argc, argv, "MET_MPI_SHARE", -1, "0", NULL);
5082
5083 /* Sorting... */
5084 ctl->sort_dt = scan_ctl(filename, argc, argv, "SORT_DT", -1, "-999", NULL);
5085
5086 /* Isosurface parameters... */
5087 ctl->isosurf =
5088 (int) scan_ctl(filename, argc, argv, "ISOSURF", -1, "0", NULL);
5089 scan_ctl(filename, argc, argv, "BALLOON", -1, "-", ctl->balloon);
5090
5091 /* Random number generator... */
5092 ctl->rng_type =
5093 (int) scan_ctl(filename, argc, argv, "RNG_TYPE", -1, "1", NULL);
5094 if (ctl->rng_type < 0 || ctl->rng_type > 2)
5095 ERRMSG("Set RNG_TYPE to 0, 1, or 2!");
5096
5097 /* Advection parameters... */
5098 ctl->advect = (int) scan_ctl(filename, argc, argv, "ADVECT", -1, "2", NULL);
5099 if (!
5100 (ctl->advect == 0 || ctl->advect == 1 || ctl->advect == 2
5101 || ctl->advect == 4))
5102 ERRMSG("Set ADVECT to 0, 1, 2, or 4!");
5103
5104 /* Diffusion parameters... */
5105 ctl->diffusion
5106 = (int) scan_ctl(filename, argc, argv, "DIFFUSION", -1, "0", NULL);
5107 if (ctl->diffusion < 0 || ctl->diffusion > 2)
5108 ERRMSG("Set DIFFUSION to 0, 1 or 2!");
5109 ctl->turb_dx_pbl =
5110 scan_ctl(filename, argc, argv, "TURB_DX_PBL", -1, "50", NULL);
5111 ctl->turb_dx_trop =
5112 scan_ctl(filename, argc, argv, "TURB_DX_TROP", -1, "50", NULL);
5113 ctl->turb_dx_strat =
5114 scan_ctl(filename, argc, argv, "TURB_DX_STRAT", -1, "0", NULL);
5115 ctl->turb_dz_pbl =
5116 scan_ctl(filename, argc, argv, "TURB_DZ_PBL", -1, "0", NULL);
5117 ctl->turb_dz_trop =
5118 scan_ctl(filename, argc, argv, "TURB_DZ_TROP", -1, "0", NULL);
5119 ctl->turb_dz_strat =
5120 scan_ctl(filename, argc, argv, "TURB_DZ_STRAT", -1, "0.1", NULL);
5121 ctl->turb_mesox =
5122 scan_ctl(filename, argc, argv, "TURB_MESOX", -1, "0.16", NULL);
5123 ctl->turb_mesoz =
5124 scan_ctl(filename, argc, argv, "TURB_MESOZ", -1, "0.16", NULL);
5125
5126 /* Convection... */
5127 ctl->conv_mix_pbl
5128 = (int) scan_ctl(filename, argc, argv, "CONV_MIX_PBL", -1, "0", NULL);
5129 ctl->conv_pbl_trans
5130 = scan_ctl(filename, argc, argv, "CONV_PBL_TRANS", -1, "0", NULL);
5131 ctl->conv_cape
5132 = scan_ctl(filename, argc, argv, "CONV_CAPE", -1, "-999", NULL);
5133 ctl->conv_cin
5134 = scan_ctl(filename, argc, argv, "CONV_CIN", -1, "-999", NULL);
5135 ctl->conv_dt = scan_ctl(filename, argc, argv, "CONV_DT", -1, "-999", NULL);
5136
5137 /* Boundary conditions... */
5138 ctl->bound_mass =
5139 scan_ctl(filename, argc, argv, "BOUND_MASS", -1, "-999", NULL);
5140 ctl->bound_mass_trend =
5141 scan_ctl(filename, argc, argv, "BOUND_MASS_TREND", -1, "0", NULL);
5142 ctl->bound_vmr =
5143 scan_ctl(filename, argc, argv, "BOUND_VMR", -1, "-999", NULL);
5144 ctl->bound_vmr_trend =
5145 scan_ctl(filename, argc, argv, "BOUND_VMR_TREND", -1, "0", NULL);
5146 ctl->bound_lat0 =
5147 scan_ctl(filename, argc, argv, "BOUND_LAT0", -1, "-999", NULL);
5148 ctl->bound_lat1 =
5149 scan_ctl(filename, argc, argv, "BOUND_LAT1", -1, "-999", NULL);
5150 ctl->bound_p0 =
5151 scan_ctl(filename, argc, argv, "BOUND_P0", -1, "-999", NULL);
5152 ctl->bound_p1 =
5153 scan_ctl(filename, argc, argv, "BOUND_P1", -1, "-999", NULL);
5154 ctl->bound_dps =
5155 scan_ctl(filename, argc, argv, "BOUND_DPS", -1, "-999", NULL);
5156 ctl->bound_dzs =
5157 scan_ctl(filename, argc, argv, "BOUND_DZS", -1, "-999", NULL);
5158 ctl->bound_zetas =
5159 scan_ctl(filename, argc, argv, "BOUND_ZETAS", -1, "-999", NULL);
5160 ctl->bound_pbl =
5161 (int) scan_ctl(filename, argc, argv, "BOUND_PBL", -1, "0", NULL);
5162
5163 /* Species parameters... */
5164 scan_ctl(filename, argc, argv, "SPECIES", -1, "-", ctl->species);
5165 if (strcasecmp(ctl->species, "CF2Cl2") == 0) {
5166 ctl->molmass = 120.907;
5167 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 3e-5;
5168 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3500.0;
5169 } else if (strcasecmp(ctl->species, "CFCl3") == 0) {
5170 ctl->molmass = 137.359;
5171 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.1e-4;
5172 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3300.0;
5173 } else if (strcasecmp(ctl->species, "CH4") == 0) {
5174 ctl->molmass = 16.043;
5175 ctl->oh_chem_reaction = 2;
5176 ctl->oh_chem[0] = 2.45e-12;
5177 ctl->oh_chem[1] = 1775;
5178 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.4e-5;
5179 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1600.0;
5180 } else if (strcasecmp(ctl->species, "CO") == 0) {
5181 ctl->molmass = 28.01;
5182 ctl->oh_chem_reaction = 3;
5183 ctl->oh_chem[0] = 6.9e-33;
5184 ctl->oh_chem[1] = 2.1;
5185 ctl->oh_chem[2] = 1.1e-12;
5186 ctl->oh_chem[3] = -1.3;
5187 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 9.7e-6;
5188 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1300.0;
5189 } else if (strcasecmp(ctl->species, "CO2") == 0) {
5190 ctl->molmass = 44.009;
5191 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 3.3e-4;
5192 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2400.0;
5193 } else if (strcasecmp(ctl->species, "H2O") == 0) {
5194 ctl->molmass = 18.01528;
5195 } else if (strcasecmp(ctl->species, "N2O") == 0) {
5196 ctl->molmass = 44.013;
5197 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.4e-4;
5198 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2600.;
5199 } else if (strcasecmp(ctl->species, "NH3") == 0) {
5200 ctl->molmass = 17.031;
5201 ctl->oh_chem_reaction = 2;
5202 ctl->oh_chem[0] = 1.7e-12;
5203 ctl->oh_chem[1] = 710;
5204 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 5.9e-1;
5205 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 4200.0;
5206 } else if (strcasecmp(ctl->species, "HNO3") == 0) {
5207 ctl->molmass = 63.012;
5208 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.1e3;
5209 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 8700.0;
5210 } else if (strcasecmp(ctl->species, "NO") == 0) {
5211 ctl->molmass = 30.006;
5212 ctl->oh_chem_reaction = 3;
5213 ctl->oh_chem[0] = 7.1e-31;
5214 ctl->oh_chem[1] = 2.6;
5215 ctl->oh_chem[2] = 3.6e-11;
5216 ctl->oh_chem[3] = 0.1;
5217 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.9e-5;
5218 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1600.0;
5219 } else if (strcasecmp(ctl->species, "NO2") == 0) {
5220 ctl->molmass = 46.005;
5221 ctl->oh_chem_reaction = 3;
5222 ctl->oh_chem[0] = 1.8e-30;
5223 ctl->oh_chem[1] = 3.0;
5224 ctl->oh_chem[2] = 2.8e-11;
5225 ctl->oh_chem[3] = 0.0;
5226 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.2e-4;
5227 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2400.0;
5228 } else if (strcasecmp(ctl->species, "O3") == 0) {
5229 ctl->molmass = 47.997;
5230 ctl->oh_chem_reaction = 2;
5231 ctl->oh_chem[0] = 1.7e-12;
5232 ctl->oh_chem[1] = 940;
5233 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1e-4;
5234 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2800.0;
5235 } else if (strcasecmp(ctl->species, "SF6") == 0) {
5236 ctl->molmass = 146.048;
5237 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.4e-6;
5238 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3100.0;
5239 } else if (strcasecmp(ctl->species, "SO2") == 0) {
5240 ctl->molmass = 64.066;
5241 ctl->oh_chem_reaction = 3;
5242 ctl->oh_chem[0] = 2.9e-31;
5243 ctl->oh_chem[1] = 4.1;
5244 ctl->oh_chem[2] = 1.7e-12;
5245 ctl->oh_chem[3] = -0.2;
5246 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.3e-2;
5247 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2900.0;
5248 }
5249
5250 /* Molar mass... */
5251 char defstr[LEN];
5252 sprintf(defstr, "%g", ctl->molmass);
5253 ctl->molmass = scan_ctl(filename, argc, argv, "MOLMASS", -1, defstr, NULL);
5254
5255 /* OH chemistry... */
5256 sprintf(defstr, "%d", ctl->oh_chem_reaction);
5257 ctl->oh_chem_reaction =
5258 (int) scan_ctl(filename, argc, argv, "OH_CHEM_REACTION", -1, defstr,
5259 NULL);
5260 for (int ip = 0; ip < 4; ip++) {
5261 sprintf(defstr, "%g", ctl->oh_chem[ip]);
5262 ctl->oh_chem[ip] =
5263 scan_ctl(filename, argc, argv, "OH_CHEM", ip, defstr, NULL);
5264 }
5265 ctl->oh_chem_beta =
5266 scan_ctl(filename, argc, argv, "OH_CHEM_BETA", -1, "0", NULL);
5267
5268 /* H2O2 chemistry... */
5269 ctl->h2o2_chem_reaction =
5270 (int) scan_ctl(filename, argc, argv, "H2O2_CHEM_REACTION", -1, "0", NULL);
5271
5272 /* KPP chemistry... */
5273 ctl->kpp_chem =
5274 (int) scan_ctl(filename, argc, argv, "KPP_CHEM", -1, "0", NULL);
5275 ctl->dt_kpp = scan_ctl(filename, argc, argv, "DT_KPP", -1, "1800", NULL);
5276
5277 /* First order tracer chemistry... */
5278 ctl->tracer_chem =
5279 (int) scan_ctl(filename, argc, argv, "TRACER_CHEM", -1, "0", NULL);
5280
5281 /* Wet deposition... */
5282 for (int ip = 0; ip < 2; ip++) {
5283 sprintf(defstr, "%g", ctl->wet_depo_ic_h[ip]);
5284 ctl->wet_depo_ic_h[ip] =
5285 scan_ctl(filename, argc, argv, "WET_DEPO_IC_H", ip, defstr, NULL);
5286 }
5287 for (int ip = 0; ip < 1; ip++) {
5288 sprintf(defstr, "%g", ctl->wet_depo_bc_h[ip]);
5289 ctl->wet_depo_bc_h[ip] =
5290 scan_ctl(filename, argc, argv, "WET_DEPO_BC_H", ip, defstr, NULL);
5291 }
5292 ctl->wet_depo_so2_ph =
5293 scan_ctl(filename, argc, argv, "WET_DEPO_SO2_PH", -1, "0", NULL);
5294 ctl->wet_depo_ic_a =
5295 scan_ctl(filename, argc, argv, "WET_DEPO_IC_A", -1, "0", NULL);
5296 ctl->wet_depo_ic_b =
5297 scan_ctl(filename, argc, argv, "WET_DEPO_IC_B", -1, "0", NULL);
5298 ctl->wet_depo_bc_a =
5299 scan_ctl(filename, argc, argv, "WET_DEPO_BC_A", -1, "0", NULL);
5300 ctl->wet_depo_bc_b =
5301 scan_ctl(filename, argc, argv, "WET_DEPO_BC_B", -1, "0", NULL);
5302 ctl->wet_depo_pre[0] =
5303 scan_ctl(filename, argc, argv, "WET_DEPO_PRE", 0, "0.5", NULL);
5304 ctl->wet_depo_pre[1] =
5305 scan_ctl(filename, argc, argv, "WET_DEPO_PRE", 1, "0.36", NULL);
5307 scan_ctl(filename, argc, argv, "WET_DEPO_IC_RET_RATIO", -1, "1", NULL);
5309 scan_ctl(filename, argc, argv, "WET_DEPO_BC_RET_RATIO", -1, "1", NULL);
5310
5311 /* Dry deposition... */
5312 ctl->dry_depo_vdep =
5313 scan_ctl(filename, argc, argv, "DRY_DEPO_VDEP", -1, "0", NULL);
5314 ctl->dry_depo_dp =
5315 scan_ctl(filename, argc, argv, "DRY_DEPO_DP", -1, "30", NULL);
5316
5317 /* Climatological data... */
5318 scan_ctl(filename, argc, argv, "CLIM_PHOTO", -1,
5319 "../../data/clams_photolysis_rates.nc", ctl->clim_photo);
5320 scan_ctl(filename, argc, argv, "CLIM_HNO3_FILENAME", -1,
5321 "../../data/gozcards_HNO3.nc", ctl->clim_hno3_filename);
5322 scan_ctl(filename, argc, argv, "CLIM_OH_FILENAME", -1,
5323 "../../data/clams_radical_species_vmr.nc", ctl->clim_oh_filename);
5324 scan_ctl(filename, argc, argv, "CLIM_H2O2_FILENAME", -1,
5325 "../../data/cams_H2O2.nc", ctl->clim_h2o2_filename);
5326 scan_ctl(filename, argc, argv, "CLIM_HO2_FILENAME", -1,
5327 "../../data/clams_radical_species_vmr.nc", ctl->clim_ho2_filename);
5328 scan_ctl(filename, argc, argv, "CLIM_O1D_FILENAME", -1,
5329 "../../data/clams_radical_species_vmr.nc", ctl->clim_o1d_filename);
5330 scan_ctl(filename, argc, argv, "CLIM_CCL4_TIMESERIES", -1,
5331 "../../data/noaa_gml_ccl4.tab", ctl->clim_ccl4_timeseries);
5332 scan_ctl(filename, argc, argv, "CLIM_CCL3F_TIMESERIES", -1,
5333 "../../data/noaa_gml_cfc11.tab", ctl->clim_ccl3f_timeseries);
5334 scan_ctl(filename, argc, argv, "CLIM_CCL2F2_TIMESERIES", -1,
5335 "../../data/noaa_gml_cfc12.tab", ctl->clim_ccl2f2_timeseries);
5336 scan_ctl(filename, argc, argv, "CLIM_N2O_TIMESERIES", -1,
5337 "../../data/noaa_gml_n2o.tab", ctl->clim_n2o_timeseries);
5338 scan_ctl(filename, argc, argv, "CLIM_SF6_TIMESERIES", -1,
5339 "../../data/noaa_gml_sf6.tab", ctl->clim_sf6_timeseries);
5340
5341 /* Mixing... */
5342 ctl->mixing_dt =
5343 scan_ctl(filename, argc, argv, "MIXING_DT", -1, "3600.", NULL);
5344 ctl->mixing_trop =
5345 scan_ctl(filename, argc, argv, "MIXING_TROP", -1, "-999", NULL);
5346 ctl->mixing_strat =
5347 scan_ctl(filename, argc, argv, "MIXING_STRAT", -1, "-999", NULL);
5348 ctl->mixing_z0 =
5349 scan_ctl(filename, argc, argv, "MIXING_Z0", -1, "-5", NULL);
5350 ctl->mixing_z1 =
5351 scan_ctl(filename, argc, argv, "MIXING_Z1", -1, "85", NULL);
5352 ctl->mixing_nz =
5353 (int) scan_ctl(filename, argc, argv, "MIXING_NZ", -1, "90", NULL);
5354 ctl->mixing_lon0 =
5355 scan_ctl(filename, argc, argv, "MIXING_LON0", -1, "-180", NULL);
5356 ctl->mixing_lon1 =
5357 scan_ctl(filename, argc, argv, "MIXING_LON1", -1, "180", NULL);
5358 ctl->mixing_nx =
5359 (int) scan_ctl(filename, argc, argv, "MIXING_NX", -1, "360", NULL);
5360 ctl->mixing_lat0 =
5361 scan_ctl(filename, argc, argv, "MIXING_LAT0", -1, "-90", NULL);
5362 ctl->mixing_lat1 =
5363 scan_ctl(filename, argc, argv, "MIXING_LAT1", -1, "90", NULL);
5364 ctl->mixing_ny =
5365 (int) scan_ctl(filename, argc, argv, "MIXING_NY", -1, "180", NULL);
5366
5367 /* Chemistry grid... */
5368 ctl->chemgrid_z0 =
5369 scan_ctl(filename, argc, argv, "CHEMGRID_Z0", -1, "-5", NULL);
5370 ctl->chemgrid_z1 =
5371 scan_ctl(filename, argc, argv, "CHEMGRID_Z1", -1, "85", NULL);
5372 ctl->chemgrid_nz =
5373 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NZ", -1, "90", NULL);
5374 ctl->chemgrid_lon0 =
5375 scan_ctl(filename, argc, argv, "CHEMGRID_LON0", -1, "-180", NULL);
5376 ctl->chemgrid_lon1 =
5377 scan_ctl(filename, argc, argv, "CHEMGRID_LON1", -1, "180", NULL);
5378 ctl->chemgrid_nx =
5379 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NX", -1, "360", NULL);
5380 ctl->chemgrid_lat0 =
5381 scan_ctl(filename, argc, argv, "CHEMGRID_LAT0", -1, "-90", NULL);
5382 ctl->chemgrid_lat1 =
5383 scan_ctl(filename, argc, argv, "CHEMGRID_LAT1", -1, "90", NULL);
5384 ctl->chemgrid_ny =
5385 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NY", -1, "180", NULL);
5386
5387 /* Exponential decay... */
5388 ctl->tdec_trop = scan_ctl(filename, argc, argv, "TDEC_TROP", -1, "0", NULL);
5389 ctl->tdec_strat =
5390 scan_ctl(filename, argc, argv, "TDEC_STRAT", -1, "0", NULL);
5391
5392 /* PSC analysis... */
5393 ctl->psc_h2o = scan_ctl(filename, argc, argv, "PSC_H2O", -1, "4e-6", NULL);
5394 ctl->psc_hno3 =
5395 scan_ctl(filename, argc, argv, "PSC_HNO3", -1, "9e-9", NULL);
5396
5397 /* Output of atmospheric data... */
5398 scan_ctl(filename, argc, argv, "ATM_BASENAME", -1, "-", ctl->atm_basename);
5399 scan_ctl(filename, argc, argv, "ATM_GPFILE", -1, "-", ctl->atm_gpfile);
5400 ctl->atm_dt_out =
5401 scan_ctl(filename, argc, argv, "ATM_DT_OUT", -1, "86400", NULL);
5402 ctl->atm_filter =
5403 (int) scan_ctl(filename, argc, argv, "ATM_FILTER", -1, "0", NULL);
5404 ctl->atm_stride =
5405 (int) scan_ctl(filename, argc, argv, "ATM_STRIDE", -1, "1", NULL);
5406 ctl->atm_type =
5407 (int) scan_ctl(filename, argc, argv, "ATM_TYPE", -1, "0", NULL);
5408 ctl->atm_type_out =
5409 (int) scan_ctl(filename, argc, argv, "ATM_TYPE_OUT", -1, "-1", NULL);
5410 if (ctl->atm_type_out == -1)
5411 ctl->atm_type_out = ctl->atm_type;
5412 ctl->atm_nc_level =
5413 (int) scan_ctl(filename, argc, argv, "ATM_NC_LEVEL", -1, "0", NULL);
5414 for (int iq = 0; iq < ctl->nq; iq++)
5415 ctl->atm_nc_quant[iq] =
5416 (int) scan_ctl(filename, argc, argv, "ATM_NC_QUANT", iq, "0", NULL);
5417 ctl->obs_type =
5418 (int) scan_ctl(filename, argc, argv, "OBS_TYPE", -1, "0", NULL);
5419
5420 /* Output of CSI data... */
5421 scan_ctl(filename, argc, argv, "CSI_BASENAME", -1, "-", ctl->csi_basename);
5422 scan_ctl(filename, argc, argv, "CSI_KERNEL", -1, "-", ctl->csi_kernel);
5423 ctl->csi_dt_out =
5424 scan_ctl(filename, argc, argv, "CSI_DT_OUT", -1, "86400", NULL);
5425 scan_ctl(filename, argc, argv, "CSI_OBSFILE", -1, "-", ctl->csi_obsfile);
5426 ctl->csi_obsmin =
5427 scan_ctl(filename, argc, argv, "CSI_OBSMIN", -1, "0", NULL);
5428 ctl->csi_modmin =
5429 scan_ctl(filename, argc, argv, "CSI_MODMIN", -1, "0", NULL);
5430 ctl->csi_z0 = scan_ctl(filename, argc, argv, "CSI_Z0", -1, "-5", NULL);
5431 ctl->csi_z1 = scan_ctl(filename, argc, argv, "CSI_Z1", -1, "85", NULL);
5432 ctl->csi_nz = (int) scan_ctl(filename, argc, argv, "CSI_NZ", -1, "1", NULL);
5433 ctl->csi_lon0 =
5434 scan_ctl(filename, argc, argv, "CSI_LON0", -1, "-180", NULL);
5435 ctl->csi_lon1 = scan_ctl(filename, argc, argv, "CSI_LON1", -1, "180", NULL);
5436 ctl->csi_nx =
5437 (int) scan_ctl(filename, argc, argv, "CSI_NX", -1, "360", NULL);
5438 ctl->csi_lat0 = scan_ctl(filename, argc, argv, "CSI_LAT0", -1, "-90", NULL);
5439 ctl->csi_lat1 = scan_ctl(filename, argc, argv, "CSI_LAT1", -1, "90", NULL);
5440 ctl->csi_ny =
5441 (int) scan_ctl(filename, argc, argv, "CSI_NY", -1, "180", NULL);
5442
5443 /* Output of ensemble data... */
5444 ctl->nens = (int) scan_ctl(filename, argc, argv, "NENS", -1, "0", NULL);
5445 scan_ctl(filename, argc, argv, "ENS_BASENAME", -1, "-", ctl->ens_basename);
5446 ctl->ens_dt_out =
5447 scan_ctl(filename, argc, argv, "ENS_DT_OUT", -1, "86400", NULL);
5448
5449 /* Output of grid data... */
5450 scan_ctl(filename, argc, argv, "GRID_BASENAME", -1, "-",
5451 ctl->grid_basename);
5452 scan_ctl(filename, argc, argv, "GRID_KERNEL", -1, "-", ctl->grid_kernel);
5453 scan_ctl(filename, argc, argv, "GRID_GPFILE", -1, "-", ctl->grid_gpfile);
5454 ctl->grid_dt_out =
5455 scan_ctl(filename, argc, argv, "GRID_DT_OUT", -1, "86400", NULL);
5456 ctl->grid_sparse =
5457 (int) scan_ctl(filename, argc, argv, "GRID_SPARSE", -1, "0", NULL);
5458 ctl->grid_nc_level =
5459 (int) scan_ctl(filename, argc, argv, "GRID_NC_LEVEL", -1, "0", NULL);
5460 for (int iq = 0; iq < ctl->nq; iq++)
5461 ctl->grid_nc_quant[iq] =
5462 (int) scan_ctl(filename, argc, argv, "GRID_NC_QUANT", iq, "0", NULL);
5463 ctl->grid_stddev =
5464 (int) scan_ctl(filename, argc, argv, "GRID_STDDEV", -1, "0", NULL);
5465 ctl->grid_z0 = scan_ctl(filename, argc, argv, "GRID_Z0", -1, "-5", NULL);
5466 ctl->grid_z1 = scan_ctl(filename, argc, argv, "GRID_Z1", -1, "85", NULL);
5467 ctl->grid_nz =
5468 (int) scan_ctl(filename, argc, argv, "GRID_NZ", -1, "1", NULL);
5469 ctl->grid_lon0 =
5470 scan_ctl(filename, argc, argv, "GRID_LON0", -1, "-180", NULL);
5471 ctl->grid_lon1 =
5472 scan_ctl(filename, argc, argv, "GRID_LON1", -1, "180", NULL);
5473 ctl->grid_nx =
5474 (int) scan_ctl(filename, argc, argv, "GRID_NX", -1, "360", NULL);
5475 ctl->grid_lat0 =
5476 scan_ctl(filename, argc, argv, "GRID_LAT0", -1, "-90", NULL);
5477 ctl->grid_lat1 =
5478 scan_ctl(filename, argc, argv, "GRID_LAT1", -1, "90", NULL);
5479 ctl->grid_ny =
5480 (int) scan_ctl(filename, argc, argv, "GRID_NY", -1, "180", NULL);
5481 ctl->grid_type =
5482 (int) scan_ctl(filename, argc, argv, "GRID_TYPE", -1, "0", NULL);
5483
5484 /* Output of profile data... */
5485 scan_ctl(filename, argc, argv, "PROF_BASENAME", -1, "-",
5486 ctl->prof_basename);
5487 scan_ctl(filename, argc, argv, "PROF_OBSFILE", -1, "-", ctl->prof_obsfile);
5488 ctl->prof_z0 = scan_ctl(filename, argc, argv, "PROF_Z0", -1, "0", NULL);
5489 ctl->prof_z1 = scan_ctl(filename, argc, argv, "PROF_Z1", -1, "60", NULL);
5490 ctl->prof_nz =
5491 (int) scan_ctl(filename, argc, argv, "PROF_NZ", -1, "60", NULL);
5492 ctl->prof_lon0 =
5493 scan_ctl(filename, argc, argv, "PROF_LON0", -1, "-180", NULL);
5494 ctl->prof_lon1 =
5495 scan_ctl(filename, argc, argv, "PROF_LON1", -1, "180", NULL);
5496 ctl->prof_nx =
5497 (int) scan_ctl(filename, argc, argv, "PROF_NX", -1, "360", NULL);
5498 ctl->prof_lat0 =
5499 scan_ctl(filename, argc, argv, "PROF_LAT0", -1, "-90", NULL);
5500 ctl->prof_lat1 =
5501 scan_ctl(filename, argc, argv, "PROF_LAT1", -1, "90", NULL);
5502 ctl->prof_ny =
5503 (int) scan_ctl(filename, argc, argv, "PROF_NY", -1, "180", NULL);
5504
5505 /* Output of sample data... */
5506 scan_ctl(filename, argc, argv, "SAMPLE_BASENAME", -1, "-",
5507 ctl->sample_basename);
5508 scan_ctl(filename, argc, argv, "SAMPLE_KERNEL", -1, "-",
5509 ctl->sample_kernel);
5510 scan_ctl(filename, argc, argv, "SAMPLE_OBSFILE", -1, "-",
5511 ctl->sample_obsfile);
5512 ctl->sample_dx =
5513 scan_ctl(filename, argc, argv, "SAMPLE_DX", -1, "50", NULL);
5514 ctl->sample_dz =
5515 scan_ctl(filename, argc, argv, "SAMPLE_DZ", -1, "-999", NULL);
5516
5517 /* Output of station data... */
5518 scan_ctl(filename, argc, argv, "STAT_BASENAME", -1, "-",
5519 ctl->stat_basename);
5520 ctl->stat_lon = scan_ctl(filename, argc, argv, "STAT_LON", -1, "0", NULL);
5521 ctl->stat_lat = scan_ctl(filename, argc, argv, "STAT_LAT", -1, "0", NULL);
5522 ctl->stat_r = scan_ctl(filename, argc, argv, "STAT_R", -1, "50", NULL);
5523 ctl->stat_t0 =
5524 scan_ctl(filename, argc, argv, "STAT_T0", -1, "-1e100", NULL);
5525 ctl->stat_t1 = scan_ctl(filename, argc, argv, "STAT_T1", -1, "1e100", NULL);
5526
5527 /* Output of VTK data... */
5528 scan_ctl(filename, argc, argv, "VTK_BASENAME", -1, "-", ctl->vtk_basename);
5529 ctl->vtk_dt_out =
5530 scan_ctl(filename, argc, argv, "VTK_DT_OUT", -1, "86400", NULL);
5531 ctl->vtk_stride =
5532 (int) scan_ctl(filename, argc, argv, "VTK_STRIDE", -1, "1", NULL);
5533 ctl->vtk_scale =
5534 scan_ctl(filename, argc, argv, "VTK_SCALE", -1, "1.0", NULL);
5535 ctl->vtk_offset =
5536 scan_ctl(filename, argc, argv, "VTK_OFFSET", -1, "0.0", NULL);
5537 ctl->vtk_sphere =
5538 (int) scan_ctl(filename, argc, argv, "VTK_SPHERE", -1, "0", NULL);
5539
5540#ifdef DD
5541 /* Controle of domain decomposition... */
5543 (int) scan_ctl(filename, argc, argv, "DD_SUBDOMAINS_MERIDIONAL", -1, "1",
5544 NULL);
5545 ctl->dd_subdomains_zonal =
5546 (int) scan_ctl(filename, argc, argv, "DD_SUBDOMAINS_ZONAL", -1, "1",
5547 NULL);
5548 ctl->dd_nbr_neighbours =
5549 (int) scan_ctl(filename, argc, argv, "DD_NBR_NEIGHBOURS", -1, "8", NULL);
5550 ctl->dd_halos_size =
5551 (int) scan_ctl(filename, argc, argv, "DD_HALOS_SIZE", -1, "1", NULL);
5552#endif
5553
5554}
void level_definitions(ctl_t *ctl)
Defines pressure levels for meteorological data.
Definition: mptrac.c:1881
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:10667
#define METVAR
Number of 3-D meteorological variables.
Definition: mptrac.h:323
#define NQ
Maximum number of quantities per data point.
Definition: mptrac.h:333
#define SET_QNT(qnt, name, longname, unit)
Set atmospheric quantity index.
Definition: mptrac.h:1647
double grid_z0
Lower altitude of gridded data [km].
Definition: mptrac.h:3132
int qnt_o3
Quantity array index for ozone volume mixing ratio.
Definition: mptrac.h:2361
double csi_lat1
Upper latitude of gridded CSI data [deg].
Definition: mptrac.h:3093
char csi_obsfile[LEN]
Observation data file for CSI analysis.
Definition: mptrac.h:3060
int met_nc_scale
Check netCDF scaling factors (0=no, 1=yes).
Definition: mptrac.h:2589
int qnt_pel
Quantity array index for pressure at equilibrium level (EL).
Definition: mptrac.h:2394
int csi_nz
Number of altitudes of gridded CSI data.
Definition: mptrac.h:3069
int qnt_p
Quantity array index for pressure.
Definition: mptrac.h:2340
int dd_halos_size
Size of halos given in grid-points.
Definition: mptrac.h:3252
char atm_gpfile[LEN]
Gnuplot file for atmospheric data.
Definition: mptrac.h:3021
int qnt_swc
Quantity array index for cloud snow water content.
Definition: mptrac.h:2373
double csi_obsmin
Minimum observation index to trigger detection.
Definition: mptrac.h:3063
int qnt_pcb
Quantity array index for cloud bottom pressure.
Definition: mptrac.h:2382
double csi_lon1
Upper longitude of gridded CSI data [deg].
Definition: mptrac.h:3084
int qnt_u
Quantity array index for zonal wind.
Definition: mptrac.h:2349
double stat_lon
Longitude of station [deg].
Definition: mptrac.h:3210
double sort_dt
Time step for sorting of particle data [s].
Definition: mptrac.h:2742
double stat_r
Search radius around station [km].
Definition: mptrac.h:3216
int met_zstd_level
ZSTD compression level (from -5 to 22).
Definition: mptrac.h:2598
int csi_ny
Number of latitudes of gridded CSI data.
Definition: mptrac.h:3087
int vtk_sphere
Spherical projection for VTK data (0=no, 1=yes).
Definition: mptrac.h:3240
double met_pbl_min
Minimum depth of planetary boundary layer [km].
Definition: mptrac.h:2710
int qnt_iwc
Quantity array index for cloud ice water content.
Definition: mptrac.h:2370
double met_cms_eps_pv
cmultiscale compression epsilon for potential vorticity.
Definition: mptrac.h:2632
int qnt_pw
Quantity array index for partial water vapor pressure.
Definition: mptrac.h:2448
char prof_basename[LEN]
Basename for profile output file.
Definition: mptrac.h:3159
double grid_z1
Upper altitude of gridded data [km].
Definition: mptrac.h:3135
int met_dp
Stride for pressure levels.
Definition: mptrac.h:2662
double met_dt_out
Time step for sampling of meteo data along trajectories [s].
Definition: mptrac.h:2729
int qnt_h2o2
Quantity array index for H2O2 volume mixing ratio (climatology).
Definition: mptrac.h:2412
int qnt_vh
Quantity array index for horizontal wind.
Definition: mptrac.h:2478
char species[LEN]
Species.
Definition: mptrac.h:2840
int csi_nx
Number of longitudes of gridded CSI data.
Definition: mptrac.h:3078
double csi_lat0
Lower latitude of gridded CSI data [deg].
Definition: mptrac.h:3090
int met_pbl
Planetary boundary layer data (0=file, 1=z2p, 2=Richardson, 3=theta).
Definition: mptrac.h:2707
double met_comp_tol[METVAR]
Compression tolerance for SZ3 or ZFP.
Definition: mptrac.h:2604
int qnt_lwc
Quantity array index for cloud liquid water content.
Definition: mptrac.h:2364
int grid_nc_level
zlib compression level of netCDF grid data files (0=off).
Definition: mptrac.h:3120
int grid_nx
Number of longitudes of gridded data.
Definition: mptrac.h:3138
double grid_lat0
Lower latitude of gridded data [deg].
Definition: mptrac.h:3150
int qnt_ts
Quantity array index for surface temperature.
Definition: mptrac.h:2295
double met_cms_eps_h2o
cmultiscale compression epsilon for water vapor.
Definition: mptrac.h:2635
int qnt_plfc
Quantity array index for pressure at level of free convection (LCF).
Definition: mptrac.h:2391
double grid_lon0
Lower longitude of gridded data [deg].
Definition: mptrac.h:3141
int qnt_o1d
Quantity array index for O(1D) volume mixing ratio (climatology).
Definition: mptrac.h:2418
int met_tropo_spline
Tropopause interpolation method (0=linear, 1=spline).
Definition: mptrac.h:2726
char sample_kernel[LEN]
Kernel data file for sample output.
Definition: mptrac.h:3195
int qnt_tvirt
Quantity array index for virtual temperature.
Definition: mptrac.h:2472
int met_geopot_sy
Latitudinal smoothing of geopotential heights.
Definition: mptrac.h:2698
char grid_gpfile[LEN]
Gnuplot file for gridded data.
Definition: mptrac.h:3111
double met_cms_eps_u
cmultiscale compression epsilon for zonal wind.
Definition: mptrac.h:2623
int qnt_lsm
Quantity array index for land-sea mask.
Definition: mptrac.h:2316
int qnt_theta
Quantity array index for potential temperature.
Definition: mptrac.h:2460
double stat_t1
Stop time for station output [s].
Definition: mptrac.h:3222
char csi_kernel[LEN]
Kernel data file for CSI output.
Definition: mptrac.h:3054
int grid_type
Type of grid data files (0=ASCII, 1=netCDF).
Definition: mptrac.h:3156
double csi_lon0
Lower longitude of gridded CSI data [deg].
Definition: mptrac.h:3081
int qnt_pbl
Quantity array index for boundary layer pressure.
Definition: mptrac.h:2322
int grid_stddev
Include standard deviations in grid output (0=no, 1=yes).
Definition: mptrac.h:3126
int qnt_psice
Quantity array index for saturation pressure over ice.
Definition: mptrac.h:2445
int met_geopot_sx
Longitudinal smoothing of geopotential heights.
Definition: mptrac.h:2695
int met_sy
Smoothing for latitudes.
Definition: mptrac.h:2668
int qnt_ps
Quantity array index for surface pressure.
Definition: mptrac.h:2292
char prof_obsfile[LEN]
Observation data file for profile output.
Definition: mptrac.h:3162
int qnt_zs
Quantity array index for surface geopotential height.
Definition: mptrac.h:2298
int prof_nz
Number of altitudes of gridded profile data.
Definition: mptrac.h:3165
double csi_dt_out
Time step for CSI output [s].
Definition: mptrac.h:3057
int met_cape
Convective available potential energy data (0=file, 1=calculate).
Definition: mptrac.h:2704
double csi_modmin
Minimum column density to trigger detection [kg/m^2].
Definition: mptrac.h:3066
int met_sx
Smoothing for longitudes.
Definition: mptrac.h:2665
double met_cms_eps_iwc
cmultiscale compression epsilon for cloud ice water content.
Definition: mptrac.h:2647
double met_cms_eps_swc
cmultiscale compression epsilon for cloud snow water content.
Definition: mptrac.h:2650
char grid_kernel[LEN]
Kernel data file for grid output.
Definition: mptrac.h:3108
double met_cms_eps_v
cmultiscale compression epsilon for meridional wind.
Definition: mptrac.h:2626
double prof_z0
Lower altitude of gridded profile data [km].
Definition: mptrac.h:3168
int qnt_w
Quantity array index for vertical velocity.
Definition: mptrac.h:2355
double met_tropo_pv
Dynamical tropopause potential vorticity threshold [PVU].
Definition: mptrac.h:2720
int prof_nx
Number of longitudes of gridded profile data.
Definition: mptrac.h:3174
int qnt_stat
Quantity array index for station flag.
Definition: mptrac.h:2277
int met_mpi_share
Use MPI to share meteo (0=no, 1=yes).
Definition: mptrac.h:2735
int qnt_vz
Quantity array index for vertical velocity.
Definition: mptrac.h:2481
int qnt_ho2
Quantity array index for HO2 volume mixing ratio (climatology).
Definition: mptrac.h:2415
double csi_z1
Upper altitude of gridded CSI data [km].
Definition: mptrac.h:3075
double stat_t0
Start time for station output [s].
Definition: mptrac.h:3219
int atm_type_out
Type of atmospheric data files for output (-1=same as ATM_TYPE, 0=ASCII, 1=binary,...
Definition: mptrac.h:3039
int met_nlev
Number of meteo data model levels.
Definition: mptrac.h:2686
double dt_kpp
Time step for KPP chemistry [s].
Definition: mptrac.h:2966
char csi_basename[LEN]
Basename of CSI data files.
Definition: mptrac.h:3051
int qnt_shf
Quantity array index for surface sensible heat flux.
Definition: mptrac.h:2313
int qnt_vs
Quantity array index for surface meridional wind.
Definition: mptrac.h:2304
double vtk_dt_out
Time step for VTK data output [s].
Definition: mptrac.h:3228
double conv_dt
Time interval for convection module [s].
Definition: mptrac.h:2801
char sample_obsfile[LEN]
Observation data file for sample output.
Definition: mptrac.h:3198
int qnt_hno3
Quantity array index for HNO3 volume mixing ratio (climatology).
Definition: mptrac.h:2406
char grid_basename[LEN]
Basename of grid data files.
Definition: mptrac.h:3105
int met_comp_prec[METVAR]
Compression precision for SZ3 or ZFP.
Definition: mptrac.h:2601
int qnt_h2ot
Quantity array index for tropopause water vapor volume mixing ratio.
Definition: mptrac.h:2334
int qnt_rh
Quantity array index for relative humidity over water.
Definition: mptrac.h:2454
double met_cms_eps_cc
cmultiscale compression epsilon for cloud cover.
Definition: mptrac.h:2653
double met_pbl_max
Maximum depth of planetary boundary layer [km].
Definition: mptrac.h:2713
int met_dx
Stride for longitudes.
Definition: mptrac.h:2656
int qnt_destination
Quantity array index for destination subdomain in domain decomposition.
Definition: mptrac.h:2550
int met_convention
Meteo data layout (0=[lev, lat, lon], 1=[lon, lat, lev]).
Definition: mptrac.h:2575
int qnt_zeta_d
Quantity array index for diagnosed zeta vertical coordinate.
Definition: mptrac.h:2466
int tracer_chem
Switch for first order tracer chemistry module (0=off, 1=on).
Definition: mptrac.h:2969
int diffusion
Diffusion scheme (0=off, 1=fixed-K, 2=PBL).
Definition: mptrac.h:2762
int qnt_zg
Quantity array index for geopotential height.
Definition: mptrac.h:2337
double vtk_offset
Vertical offset for VTK data [km].
Definition: mptrac.h:3237
int qnt_v
Quantity array index for meridional wind.
Definition: mptrac.h:2352
int qnt_oh
Quantity array index for OH volume mixing ratio (climatology).
Definition: mptrac.h:2409
int qnt_h2o
Quantity array index for water vapor volume mixing ratio.
Definition: mptrac.h:2358
int prof_ny
Number of latitudes of gridded profile data.
Definition: mptrac.h:3183
int qnt_rhice
Quantity array index for relative humidity over ice.
Definition: mptrac.h:2457
int qnt_rho
Quantity array index for density of air.
Definition: mptrac.h:2346
double sample_dz
Layer depth for sample output [km].
Definition: mptrac.h:3204
int obs_type
Type of observation data files (0=ASCII, 1=netCDF).
Definition: mptrac.h:3048
int grid_nc_quant[NQ]
Number of digits for quantization of netCDF grid data files (0=off).
Definition: mptrac.h:3123
double met_cms_eps_lwc
cmultiscale compression epsilon for cloud liquid water content.
Definition: mptrac.h:2641
int qnt_us
Quantity array index for surface zonal wind.
Definition: mptrac.h:2301
double met_cms_eps_z
cmultiscale compression epsilon for geopotential height.
Definition: mptrac.h:2617
double grid_lon1
Upper longitude of gridded data [deg].
Definition: mptrac.h:3144
char atm_basename[LEN]
Basename of atmospheric data files.
Definition: mptrac.h:3018
int qnt_pt
Quantity array index for tropopause pressure.
Definition: mptrac.h:2325
int qnt_cl
Quantity array index for total column cloud water.
Definition: mptrac.h:2385
double prof_z1
Upper altitude of gridded profile data [km].
Definition: mptrac.h:3171
double met_lev_hyam[EP]
Meteo data model level a coefficients.
Definition: mptrac.h:2689
int qnt_t
Quantity array index for temperature.
Definition: mptrac.h:2343
int atm_filter
Time filter for atmospheric data output (0=none, 1=missval, 2=remove).
Definition: mptrac.h:3027
int kpp_chem
Switch for KPP chemistry module (0=off, 1=on).
Definition: mptrac.h:2963
char ens_basename[LEN]
Basename of ensemble data file.
Definition: mptrac.h:3099
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:2579
double csi_z0
Lower altitude of gridded CSI data [km].
Definition: mptrac.h:3072
int qnt_lapse
Quantity array index for lapse rate.
Definition: mptrac.h:2475
double stat_lat
Latitude of station [deg].
Definition: mptrac.h:3213
int grid_ny
Number of latitudes of gridded data.
Definition: mptrac.h:3147
double met_detrend
FWHM of horizontal Gaussian used for detrending [km].
Definition: mptrac.h:2674
int dd_nbr_neighbours
Number of neighbours to communicate with.
Definition: mptrac.h:3249
double met_cms_eps_t
cmultiscale compression epsilon for temperature.
Definition: mptrac.h:2620
int qnt_cape
Quantity array index for convective available potential energy (CAPE).
Definition: mptrac.h:2397
int qnt_o3c
Quantity array index for total column ozone.
Definition: mptrac.h:2403
int grid_nz
Number of altitudes of gridded data.
Definition: mptrac.h:3129
int qnt_nss
Quantity array index for northward turbulent surface stress.
Definition: mptrac.h:2310
double ens_dt_out
Time step for ensemble output [s].
Definition: mptrac.h:3102
char sample_basename[LEN]
Basename of sample data file.
Definition: mptrac.h:3192
int atm_stride
Particle index stride for atmospheric data files.
Definition: mptrac.h:3030
int met_relhum
Try to read relative humidity (0=no, 1=yes).
Definition: mptrac.h:2701
double atm_dt_out
Time step for atmospheric data output [s].
Definition: mptrac.h:3024
double prof_lat1
Upper latitude of gridded profile data [deg].
Definition: mptrac.h:3189
int met_cms_batch
cmultiscale batch size.
Definition: mptrac.h:2607
double psc_h2o
H2O volume mixing ratio for PSC analysis.
Definition: mptrac.h:3008
int met_sp
Smoothing for pressure levels.
Definition: mptrac.h:2671
double prof_lon0
Lower longitude of gridded profile data [deg].
Definition: mptrac.h:3177
int qnt_pct
Quantity array index for cloud top pressure.
Definition: mptrac.h:2379
int qnt_mloss_kpp
Quantity array index for total mass loss due to KPP chemistry.
Definition: mptrac.h:2427
int qnt_psat
Quantity array index for saturation pressure over water.
Definition: mptrac.h:2442
double met_lev_hybm[EP]
Meteo data model level b coefficients.
Definition: mptrac.h:2692
double prof_lat0
Lower latitude of gridded profile data [deg].
Definition: mptrac.h:3186
int qnt_cin
Quantity array index for convective inhibition (CIN).
Definition: mptrac.h:2400
double psc_hno3
HNO3 volume mixing ratio for PSC analysis.
Definition: mptrac.h:3011
double prof_lon1
Upper longitude of gridded profile data [deg].
Definition: mptrac.h:3180
double met_cms_eps_rwc
cmultiscale compression epsilon for cloud rain water content.
Definition: mptrac.h:2644
int met_nc_quant
Number of digits for quantization of netCDF meteo files (0=off).
Definition: mptrac.h:2595
int h2o2_chem_reaction
Reaction type for H2O2 chemistry (0=none, 1=SO2).
Definition: mptrac.h:2960
int atm_nc_quant[NQ]
Number of digits for quantization of netCDF atmospheric data files (0=off).
Definition: mptrac.h:3045
double met_cms_eps_o3
cmultiscale compression epsilon for ozone.
Definition: mptrac.h:2638
int met_cms_zstd
cmultiscale ZSTD compression (0=off, 1=on).
Definition: mptrac.h:2610
int grid_sparse
Sparse output in grid data files (0=no, 1=yes).
Definition: mptrac.h:3117
char vtk_basename[LEN]
Basename of VTK data files.
Definition: mptrac.h:3225
int qnt_tt
Quantity array index for tropopause temperature.
Definition: mptrac.h:2328
int met_nc_level
zlib compression level of netCDF meteo files (0=off).
Definition: mptrac.h:2592
double mixing_dt
Time interval for mixing [s].
Definition: mptrac.h:2888
double vtk_scale
Vertical scaling factor for VTK data.
Definition: mptrac.h:3234
double met_cms_eps_w
cmultiscale compression epsilon for vertical velocity.
Definition: mptrac.h:2629
int qnt_pv
Quantity array index for potential vorticity.
Definition: mptrac.h:2484
int qnt_sst
Quantity array index for sea surface temperature.
Definition: mptrac.h:2319
int atm_nc_level
zlib compression level of netCDF atmospheric data files (0=off).
Definition: mptrac.h:3042
int met_cms_heur
cmultiscale coarsening heuristics (0=default, 1=mean diff, 2=median diff, 3=max diff).
Definition: mptrac.h:2614
int qnt_sh
Quantity array index for specific humidity.
Definition: mptrac.h:2451
int qnt_ess
Quantity array index for eastward turbulent surface stress.
Definition: mptrac.h:2307
int met_dy
Stride for latitudes.
Definition: mptrac.h:2659
int dd_subdomains_zonal
Zonal subdomain number.
Definition: mptrac.h:3243
int qnt_idx
Quantity array index for air parcel IDs.
Definition: mptrac.h:2271
double met_tropo_theta
Dynamical tropopause potential temperature threshold [K].
Definition: mptrac.h:2723
int qnt_rwc
Quantity array index for cloud rain water content.
Definition: mptrac.h:2367
char qnt_longname[NQ][LEN]
Quantity long names.
Definition: mptrac.h:2262
double sample_dx
Horizontal radius for sample output [km].
Definition: mptrac.h:3201
int vtk_stride
Particle index stride for VTK data.
Definition: mptrac.h:3231
char stat_basename[LEN]
Basename of station data file.
Definition: mptrac.h:3207
double grid_lat1
Upper latitude of gridded data [deg].
Definition: mptrac.h:3153
int dd_subdomains_meridional
Meridional subdomain number.
Definition: mptrac.h:3246
int qnt_zt
Quantity array index for tropopause geopotential height.
Definition: mptrac.h:2331
int qnt_cc
Quantity array index for cloud cover.
Definition: mptrac.h:2376
int qnt_plcl
Quantity array index for pressure at lifted condensation level (LCL).
Definition: mptrac.h:2388
double grid_dt_out
Time step for gridded data output [s].
Definition: mptrac.h:3114
int qnt_tdew
Quantity array index for dew point temperature.
Definition: mptrac.h:2487
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 or 7, 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 5558 of file mptrac.c.

5562 {
5563
5564 /* Write info... */
5565 LOG(1, "Read meteo data: %s", filename);
5566
5567 /* Set rank... */
5568 int rank = 0;
5569#ifdef MPI
5570 if (ctl->met_mpi_share)
5571 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5572#endif
5573
5574 /* Check rank... */
5575 if (!ctl->met_mpi_share || rank == 0) {
5576
5577 /* Read netCDF data... */
5578 if (ctl->met_type == 0) {
5579#ifdef DD
5580 if (read_met_nc_dd(filename, ctl, met) != 1)
5581 return 0;
5582#else
5583 if (read_met_nc(filename, ctl, met) != 1)
5584 return 0;
5585#endif
5586 }
5587
5588 /* Read binary data... */
5589 else if ((ctl->met_type >= 1 && ctl->met_type <= 5) || ctl->met_type == 7) {
5590 if (read_met_bin(filename, ctl, met) != 1)
5591 return 0;
5592 }
5593
5594#ifdef ECCODES
5595 /* Read grib data... */
5596 else if (ctl->met_type == 6) {
5597 if (read_met_grib(filename, ctl, met) != 1)
5598 return 0;
5599 }
5600#endif
5601
5602 /* Not implemented... */
5603 else
5604 ERRMSG("MET_TYPE not implemented!");
5605
5606 /* Preprocessing for netCDF and grib files... */
5607 if (ctl->met_type == 0 || ctl->met_type == 6) {
5608
5609 /* Extrapolate data for lower boundary... */
5611
5612 /* Fix polar winds... */
5614
5615 /* Create periodic boundary conditions... */
5616#ifndef DD
5617 read_met_periodic(met);
5618#endif
5619
5620 /* Downsampling... */
5621 read_met_sample(ctl, met);
5622
5623 /* Calculate geopotential heights... */
5624 read_met_geopot(ctl, met);
5625
5626 /* Calculate potential vorticity... */
5627 read_met_pv(met);
5628
5629 /* Calculate boundary layer data... */
5630 read_met_pbl(ctl, met);
5631
5632 /* Calculate tropopause data... */
5633 read_met_tropo(ctl, clim, met);
5634
5635 /* Calculate cloud properties... */
5636 read_met_cloud(met);
5637
5638 /* Calculate convective available potential energy... */
5639 read_met_cape(ctl, clim, met);
5640
5641 /* Calculate total column ozone... */
5642 read_met_ozone(met);
5643
5644 /* Detrending... */
5645 read_met_detrend(ctl, met);
5646
5647 /* Check meteo data and smooth zeta profiles ... */
5648 read_met_monotonize(ctl, met);
5649 }
5650 }
5651
5652 /* Broadcast data via MPI... */
5653#ifdef MPI
5654 if (ctl->met_mpi_share) {
5655
5656 /* Set timer... */
5657 SELECT_TIMER("READ_MET_MPI_BCAST", "COMM", NVTX_SEND);
5658 LOG(2, "Broadcast data on rank %d...", rank);
5659
5660 /* Broadcast... */
5661 broadcast_large_data(met, sizeof(met_t));
5662 }
5663#endif
5664
5665 /* Return success... */
5666 return 1;
5667}
void read_met_geopot(const ctl_t *ctl, met_t *met)
Calculates geopotential heights from meteorological data.
Definition: mptrac.c:7283
void read_met_extrapolate(met_t *met)
Extrapolates meteorological data.
Definition: mptrac.c:7243
void read_met_sample(const ctl_t *ctl, met_t *met)
Downsamples meteorological data based on specified parameters.
Definition: mptrac.c:10221
void read_met_cloud(met_t *met)
Calculates cloud-related variables for each grid point.
Definition: mptrac.c:7082
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:9829
void read_met_detrend(const ctl_t *ctl, met_t *met)
Detrends meteorological data.
Definition: mptrac.c:7139
void read_met_monotonize(const ctl_t *ctl, met_t *met)
Makes zeta and pressure profiles monotone.
Definition: mptrac.c:8913
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
Definition: mptrac.c:9966
void read_met_ozone(met_t *met)
Calculates the total column ozone from meteorological ozone data.
Definition: mptrac.c:10192
void read_met_pv(met_t *met)
Calculates potential vorticity (PV) from meteorological data.
Definition: mptrac.c:10086
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:8998
int read_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a binary file.
Definition: mptrac.c:6684
void read_met_polar_winds(met_t *met)
Applies a fix for polar winds in meteorological data.
Definition: mptrac.c:10027
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:6967
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.
Author
Lars Hoffmann

Definition at line 5682 of file mptrac.c.

5689 {
5690#endif
5691 /* Initialize modules... */
5692 if (t == ctl->t_start) {
5693
5694 /* Initialize isosurface data... */
5695 if (ctl->isosurf >= 1 && ctl->isosurf <= 4)
5696 module_isosurf_init(ctl, cache, *met0, *met1, atm);
5697
5698 /* Initialize advection... */
5699 module_advect_init(ctl, cache, *met0, *met1, atm);
5700
5701 /* Initialize chemistry... */
5702 module_chem_init(ctl, cache, clim, *met0, *met1, atm);
5703 }
5704
5705 /* Set time steps of air parcels... */
5706 module_timesteps(ctl, cache, *met0, atm, t);
5707
5708#ifndef DD
5709 /* Sort particles... */
5710 if (ctl->sort_dt > 0 && fmod(t, ctl->sort_dt) == 0)
5711 module_sort(ctl, *met0, atm);
5712#endif
5713
5714 /* Check positions (initial)... */
5715 module_position(cache, *met0, *met1, atm);
5716
5717 /* Advection... */
5718 if (ctl->advect > 0)
5719 module_advect(ctl, cache, *met0, *met1, atm);
5720
5721 /* Turbulent diffusion... */
5722 if (ctl->diffusion == 1
5723 && (ctl->turb_dx_pbl > 0 || ctl->turb_dz_pbl > 0
5724 || ctl->turb_dx_trop > 0 || ctl->turb_dz_trop > 0
5725 || ctl->turb_dx_strat > 0 || ctl->turb_dz_strat > 0))
5726 module_diff_turb(ctl, cache, clim, *met0, *met1, atm);
5727
5728 /* Mesoscale diffusion... */
5729 if (ctl->diffusion == 1 && (ctl->turb_mesox > 0 || ctl->turb_mesoz > 0))
5730 module_diff_meso(ctl, cache, *met0, *met1, atm);
5731
5732 /* Diffusion... */
5733 if (ctl->diffusion == 2)
5734 module_diff_pbl(ctl, cache, *met0, *met1, atm);
5735
5736 /* Convection... */
5737 if ((ctl->conv_mix_pbl || ctl->conv_cape >= 0)
5738 && (ctl->conv_dt <= 0 || fmod(t, ctl->conv_dt) == 0))
5739 module_convection(ctl, cache, *met0, *met1, atm);
5740
5741 /* Sedimentation... */
5742 if (ctl->qnt_rp >= 0 && ctl->qnt_rhop >= 0)
5743 module_sedi(ctl, cache, *met0, *met1, atm);
5744
5745 /* Isosurface... */
5746 if (ctl->isosurf >= 1 && ctl->isosurf <= 4)
5747 module_isosurf(ctl, cache, *met0, *met1, atm);
5748
5749 /* Check positions (final)... */
5750 module_position(cache, *met0, *met1, atm);
5751
5752 /* Interpolate meteo data... */
5753 if (ctl->met_dt_out > 0
5754 && (ctl->met_dt_out < ctl->dt_mod || fmod(t, ctl->met_dt_out) == 0))
5755 module_meteo(ctl, cache, clim, *met0, *met1, atm);
5756
5757 /* Check boundary conditions (initial)... */
5758 if ((ctl->bound_lat0 < ctl->bound_lat1)
5759 && (ctl->bound_p0 > ctl->bound_p1))
5760 module_bound_cond(ctl, cache, clim, *met0, *met1, atm);
5761
5762 /* Initialize quantity of total loss rate... */
5763 if (ctl->qnt_loss_rate >= 0) {
5764 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,atm)") {
5765 atm->q[ctl->qnt_loss_rate][ip] = 0;
5766 }
5767 }
5768
5769 /* Decay of particle mass... */
5770 if (ctl->tdec_trop > 0 && ctl->tdec_strat > 0)
5771 module_decay(ctl, cache, clim, atm);
5772
5773 /* Interparcel mixing... */
5774 if (ctl->mixing_trop >= 0 && ctl->mixing_strat >= 0
5775 && (ctl->mixing_dt <= 0 || fmod(t, ctl->mixing_dt) == 0))
5776 module_mixing(ctl, clim, atm, t);
5777
5778 /* Calculate the tracer vmr in the chemistry grid... */
5779 if (ctl->oh_chem_reaction != 0 || ctl->h2o2_chem_reaction != 0
5780 || (ctl->kpp_chem && fmod(t, ctl->dt_kpp) == 0))
5781 module_chem_grid(ctl, *met0, *met1, atm, t);
5782
5783 /* OH chemistry... */
5784 if (ctl->oh_chem_reaction != 0)
5785 module_oh_chem(ctl, cache, clim, *met0, *met1, atm);
5786
5787 /* H2O2 chemistry (for SO2 aqueous phase oxidation)... */
5788 if (ctl->h2o2_chem_reaction != 0)
5789 module_h2o2_chem(ctl, cache, clim, *met0, *met1, atm);
5790
5791 /* First-order tracer chemistry... */
5792 if (ctl->tracer_chem)
5793 module_tracer_chem(ctl, cache, clim, *met0, *met1, atm);
5794
5795 /* Domain decomposition... */
5796#ifdef DD
5798 module_dd(ctl, atm, cache, mpi_info, met0);
5799#endif
5800
5801 /* KPP chemistry... */
5802 if (ctl->kpp_chem && fmod(t, ctl->dt_kpp) == 0) {
5803#ifdef KPP
5804 module_kpp_chem(ctl, cache, clim, *met0, *met1, atm);
5805#else
5806 ERRMSG("Code was compiled without KPP!");
5807#endif
5808 }
5809
5810 /* Wet deposition... */
5811 if ((ctl->wet_depo_ic_a > 0 || ctl->wet_depo_ic_h[0] > 0)
5812 && (ctl->wet_depo_bc_a > 0 || ctl->wet_depo_bc_h[0] > 0))
5813 module_wet_depo(ctl, cache, *met0, *met1, atm);
5814
5815 /* Dry deposition... */
5816 if (ctl->dry_depo_vdep > 0)
5817 module_dry_depo(ctl, cache, *met0, *met1, atm);
5818
5819 /* Check boundary conditions (final)... */
5820 if ((ctl->bound_lat0 < ctl->bound_lat1)
5821 && (ctl->bound_p0 > ctl->bound_p1))
5822 module_bound_cond(ctl, cache, clim, *met0, *met1, atm);
5823}
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:2194
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:4042
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:3361
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:2747
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:2632
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:3466
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:3185
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:4190
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:2470
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:3910
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:2674
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:2374
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:2347
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:3723
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:2786
void module_sort(const ctl_t *ctl, met_t *met0, atm_t *atm)
Sort particles according to box index.
Definition: mptrac.c:3939
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:2988
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:4120
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:3103
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:2863
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:3255
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:3639
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:3040
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 5939 of file mptrac.c.

5943 {
5944
5945 /* Set timer... */
5946 SELECT_TIMER("WRITE_ATM", "OUTPUT", NVTX_WRITE);
5947
5948 /* Write info... */
5949 LOG(1, "Write atmospheric data: %s", filename);
5950
5951 /* Write ASCII data... */
5952 if (ctl->atm_type_out == 0)
5953 write_atm_asc(filename, ctl, atm, t);
5954
5955 /* Write binary data... */
5956 else if (ctl->atm_type_out == 1)
5957 write_atm_bin(filename, ctl, atm);
5958
5959 /* Write netCDF data... */
5960 else if (ctl->atm_type_out == 2)
5961 write_atm_nc(filename, ctl, atm);
5962
5963 /* Write CLaMS trajectory data... */
5964 else if (ctl->atm_type_out == 3)
5965 write_atm_clams_traj(filename, ctl, atm, t);
5966
5967 /* Write CLaMS pos data... */
5968 else if (ctl->atm_type_out == 4)
5969 write_atm_clams(filename, ctl, atm);
5970
5971 /* Error... */
5972 else
5973 ERRMSG("Atmospheric data type not supported!");
5974
5975 /* Write info... */
5976 double mini, maxi;
5977 LOG(2, "Number of particles: %d", atm->np);
5978 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
5979 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
5980 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
5981 LOG(2, "Altitude range: %g ... %g km", Z(maxi), Z(mini));
5982 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
5983 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
5984 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
5985 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
5986 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
5987 for (int iq = 0; iq < ctl->nq; iq++) {
5988 char msg[5 * LEN];
5989 sprintf(msg, "Quantity %s range: %s ... %s %s",
5990 ctl->qnt_name[iq], ctl->qnt_format[iq],
5991 ctl->qnt_format[iq], ctl->qnt_unit[iq]);
5992 gsl_stats_minmax(&mini, &maxi, atm->q[iq], 1, (size_t) atm->np);
5993 LOG(2, msg, mini, maxi);
5994 }
5995}
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:11223
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:11038
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:11170
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:11120
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:11381
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.
  • If ctl->met_type is 7, SZ3 compression is required, and the function will generate an error if compiled without SZ3 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 or 7, 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 5999 of file mptrac.c.

6002 {
6003
6004 /* Set timer... */
6005 SELECT_TIMER("WRITE_MET", "OUTPUT", NVTX_WRITE);
6006
6007 /* Write info... */
6008 LOG(1, "Write meteo data: %s", filename);
6009
6010 /* Check compression flags... */
6011#ifndef ZFP
6012 if (ctl->met_type == 3)
6013 ERRMSG("MPTRAC was compiled without ZFP compression!");
6014#endif
6015#ifndef ZSTD
6016 if (ctl->met_type == 4)
6017 ERRMSG("MPTRAC was compiled without ZSTD compression!");
6018#endif
6019#ifndef CMS
6020 if (ctl->met_type == 5)
6021 ERRMSG("MPTRAC was compiled without cmultiscale compression!");
6022#endif
6023#ifndef SZ3
6024 if (ctl->met_type == 7)
6025 ERRMSG("MPTRAC was compiled without SZ3 compression!");
6026#endif
6027
6028 /* Write netCDF data... */
6029 if (ctl->met_type == 0)
6030 write_met_nc(filename, ctl, met);
6031
6032 /* Write binary data... */
6033 else if (ctl->met_type >= 1 && ctl->met_type <= 7)
6034 write_met_bin(filename, ctl, met);
6035
6036 /* Not implemented... */
6037 else
6038 ERRMSG("MET_TYPE not implemented!");
6039}
void write_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a NetCDF file.
Definition: mptrac.c:12462
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:12231
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 6043 of file mptrac.c.

6049 {
6050
6051 char ext[10], filename[2 * LEN];
6052
6053 double r;
6054
6055 int year, mon, day, hour, min, sec;
6056
6057 /* Get time... */
6058 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
6059
6060 /* Update host... */
6061 if ((ctl->atm_basename[0] != '-' && fmod(t, ctl->atm_dt_out) == 0)
6062 || (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0)
6063 || (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0)
6064 || ctl->csi_basename[0] != '-' || ctl->prof_basename[0] != '-'
6065 || ctl->sample_basename[0] != '-' || ctl->stat_basename[0] != '-'
6066 || (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0))
6067 mptrac_update_host(NULL, NULL, NULL, NULL, NULL, atm);
6068
6069 /* Write atmospheric data... */
6070 if (ctl->atm_basename[0] != '-' &&
6071 (fmod(t, ctl->atm_dt_out) == 0 || t == ctl->t_stop)) {
6072 if (ctl->atm_type_out == 0)
6073 sprintf(ext, "tab");
6074 else if (ctl->atm_type_out == 1)
6075 sprintf(ext, "bin");
6076 else if (ctl->atm_type_out == 2)
6077 sprintf(ext, "nc");
6078 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6079 dirname, ctl->atm_basename, year, mon, day, hour, min, ext);
6080 mptrac_write_atm(filename, ctl, atm, t);
6081 }
6082
6083 /* Write gridded data... */
6084 if (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0) {
6085 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6086 dirname, ctl->grid_basename, year, mon, day, hour, min,
6087 ctl->grid_type == 0 ? "tab" : "nc");
6088 write_grid(filename, ctl, met0, met1, atm, t);
6089 }
6090
6091 /* Write CSI data... */
6092 if (ctl->csi_basename[0] != '-') {
6093 sprintf(filename, "%s/%s.tab", dirname, ctl->csi_basename);
6094 write_csi(filename, ctl, atm, t);
6095 }
6096
6097 /* Write ensemble data... */
6098 if (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0) {
6099 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
6100 dirname, ctl->ens_basename, year, mon, day, hour, min);
6101 write_ens(filename, ctl, atm, t);
6102 }
6103
6104 /* Write profile data... */
6105 if (ctl->prof_basename[0] != '-') {
6106 sprintf(filename, "%s/%s.tab", dirname, ctl->prof_basename);
6107 write_prof(filename, ctl, met0, met1, atm, t);
6108 }
6109
6110 /* Write sample data... */
6111 if (ctl->sample_basename[0] != '-') {
6112 sprintf(filename, "%s/%s.tab", dirname, ctl->sample_basename);
6113 write_sample(filename, ctl, met0, met1, atm, t);
6114 }
6115
6116 /* Write station data... */
6117 if (ctl->stat_basename[0] != '-') {
6118 sprintf(filename, "%s/%s.tab", dirname, ctl->stat_basename);
6119 write_station(filename, ctl, atm, t);
6120 }
6121
6122 /* Write VTK data... */
6123 if (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0) {
6124 static int nvtk;
6125 if (t == ctl->t_start)
6126 nvtk = 0;
6127 sprintf(filename, "%s/%s_%05d.vtk", dirname, ctl->vtk_basename, ++nvtk);
6128 write_vtk(filename, ctl, atm, t);
6129 }
6130}
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:5939
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:11709
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:12685
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:5883
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:13074
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:13160
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:12912
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:11806
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:11430
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 5827 of file mptrac.c.

5833 {
5834
5835 /* Update GPU... */
5836 if (ctl != NULL) {
5837#ifdef _OPENACC
5838 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5839#pragma acc update device(ctl[:1])
5840#endif
5841 }
5842
5843 if (cache != NULL) {
5844#ifdef _OPENACC
5845 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5846#pragma acc update device(cache[:1])
5847#endif
5848 }
5849
5850 if (clim != NULL) {
5851#ifdef _OPENACC
5852 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5853#pragma acc update device(clim[:1])
5854#endif
5855 }
5856
5857 if (met0 != NULL) {
5858#ifdef _OPENACC
5859 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5860 met_t *met0up = *met0;
5861#pragma acc update device(met0up[:1])
5862#endif
5863 }
5864
5865 if (met1 != NULL) {
5866#ifdef _OPENACC
5867 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5868 met_t *met1up = *met1;
5869#pragma acc update device(met1up[:1])
5870#endif
5871 }
5872
5873 if (atm != NULL) {
5874#ifdef _OPENACC
5875 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5876#pragma acc update device(atm[:1])
5877#endif
5878 }
5879}

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

5889 {
5890
5891 /* Update GPU... */
5892 if (ctl != NULL) {
5893#ifdef _OPENACC
5894 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5895#pragma acc update host(ctl[:1])
5896#endif
5897 }
5898
5899 if (cache != NULL) {
5900#ifdef _OPENACC
5901 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5902#pragma acc update host(cache[:1])
5903#endif
5904 }
5905
5906 if (clim != NULL) {
5907#ifdef _OPENACC
5908 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5909#pragma acc update host(clim[:1])
5910#endif
5911 }
5912
5913 if (met0 != NULL) {
5914#ifdef _OPENACC
5915 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5916 met_t *met0up = *met0;
5917#pragma acc update host(met0up[:1])
5918#endif
5919 }
5920
5921 if (met1 != NULL) {
5922#ifdef _OPENACC
5923 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5924 met_t *met1up = *met1;
5925#pragma acc update host(met1up[:1])
5926#endif
5927 }
5928
5929 if (atm != NULL) {
5930#ifdef _OPENACC
5931 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5932#pragma acc update host(atm[:1])
5933#endif
5934 }
5935}

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

6137 {
6138
6139 /* Check water vapor volume mixing ratio... */
6140 const double h2o_help = MAX(h2o, 0.1e-6);
6141
6142 /* Calculate T_NAT... */
6143 const double p_hno3 = hno3 * p / 1.333224;
6144 const double p_h2o = h2o_help * p / 1.333224;
6145 const double a = 0.009179 - 0.00088 * log10(p_h2o);
6146 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
6147 const double c = -11397.0 / a;
6148 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
6149 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
6150 if (x2 > 0)
6151 tnat = x2;
6152
6153 return tnat;
6154}

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

6163 {
6164
6165 /* Get pressure range... */
6166 const double p1 = pbl - ctl->conv_pbl_trans * (ps - pbl);
6167 const double p0 = pbl;
6168
6169 /* Get weighting factor... */
6170 if (atm->p[ip] > p0)
6171 return 1;
6172 else if (atm->p[ip] < p1)
6173 return 0;
6174 else
6175 return LIN(p0, 1.0, p1, 0.0, atm->p[ip]);
6176}

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

6183 {
6184
6185 /* Open file... */
6186 FILE *in;
6187 if (!(in = fopen(filename, "r"))) {
6188 WARN("Cannot open file!");
6189 return 0;
6190 }
6191
6192 /* Read line... */
6193 char line[LEN];
6194 while (fgets(line, LEN, in)) {
6195
6196 /* Read data... */
6197 char *tok;
6198 TOK(line, tok, "%lg", atm->time[atm->np]);
6199 TOK(NULL, tok, "%lg", atm->p[atm->np]);
6200 TOK(NULL, tok, "%lg", atm->lon[atm->np]);
6201 TOK(NULL, tok, "%lg", atm->lat[atm->np]);
6202 for (int iq = 0; iq < ctl->nq; iq++)
6203 TOK(NULL, tok, "%lg", atm->q[iq][atm->np]);
6204
6205 /* Convert altitude to pressure... */
6206 atm->p[atm->np] = P(atm->p[atm->np]);
6207
6208 /* Increment data point counter... */
6209 if ((++atm->np) > NP)
6210 ERRMSG("Too many data points!");
6211 }
6212
6213 /* Close file... */
6214 fclose(in);
6215
6216 /* Return success... */
6217 return 1;
6218}
#define TOK(line, tok, format, var)
Get string tokens.
Definition: mptrac.h:1818

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

6225 {
6226
6227 /* Open file... */
6228 FILE *in;
6229 if (!(in = fopen(filename, "r")))
6230 return 0;
6231
6232 /* Check version of binary data... */
6233 int version;
6234 FREAD(&version, int,
6235 1,
6236 in);
6237 if (version != 100)
6238 ERRMSG("Wrong version of binary data!");
6239
6240 /* Read data... */
6241 FREAD(&atm->np, int,
6242 1,
6243 in);
6244 FREAD(atm->time, double,
6245 (size_t) atm->np,
6246 in);
6247 FREAD(atm->p, double,
6248 (size_t) atm->np,
6249 in);
6250 FREAD(atm->lon, double,
6251 (size_t) atm->np,
6252 in);
6253 FREAD(atm->lat, double,
6254 (size_t) atm->np,
6255 in);
6256 for (int iq = 0; iq < ctl->nq; iq++)
6257 FREAD(atm->q[iq], double,
6258 (size_t) atm->np,
6259 in);
6260
6261 /* Read final flag... */
6262 int final;
6263 FREAD(&final, int,
6264 1,
6265 in);
6266 if (final != 999)
6267 ERRMSG("Error while reading binary data!");
6268
6269 /* Close file... */
6270 fclose(in);
6271
6272 /* Return success... */
6273 return 1;
6274}

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

6281 {
6282
6283 int ncid, varid;
6284
6285 /* Open file... */
6286 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6287 return 0;
6288
6289 /* Get dimensions... */
6290 NC_INQ_DIM("NPARTS", &atm->np, 1, NP);
6291
6292 /* Get time... */
6293 if (nc_inq_varid(ncid, "TIME_INIT", &varid) == NC_NOERR) {
6294 NC(nc_get_var_double(ncid, varid, atm->time));
6295 } else {
6296 WARN("TIME_INIT not found use time instead!");
6297 double time_init;
6298 NC_GET_DOUBLE("time", &time_init, 1);
6299 for (int ip = 0; ip < atm->np; ip++) {
6300 atm->time[ip] = time_init;
6301 }
6302 }
6303
6304 /* Read zeta coordinate, pressure is optional... */
6305 if (ctl->advect_vert_coord == 1) {
6306 NC_GET_DOUBLE("ZETA", atm->q[ctl->qnt_zeta], 1);
6307 NC_GET_DOUBLE("PRESS", atm->p, 0);
6308 }
6309
6310 /* Read pressure, zeta coordinate is optional... */
6311 else {
6312 if (nc_inq_varid(ncid, "PRESS_INIT", &varid) == NC_NOERR) {
6313 NC(nc_get_var_double(ncid, varid, atm->p));
6314 } else {
6315 WARN("PRESS_INIT not found use PRESS instead!");
6316 nc_inq_varid(ncid, "PRESS", &varid);
6317 NC(nc_get_var_double(ncid, varid, atm->p));
6318 }
6319 }
6320
6321 /* Read further quantities if requested... */
6322 for (int iq = 0; iq < ctl->nq; iq++)
6323 NC_GET_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
6324
6325 /* Read longitude and latitude... */
6326 NC_GET_DOUBLE("LON", atm->lon, 1);
6327 NC_GET_DOUBLE("LAT", atm->lat, 1);
6328
6329 /* Close file... */
6330 NC(nc_close(ncid));
6331
6332 /* Return success... */
6333 return 1;
6334}
#define NC(cmd)
Execute a NetCDF command and check for errors.
Definition: mptrac.h:1155
#define NC_INQ_DIM(dimname, ptr, min, max)
Inquire the length of a dimension in a NetCDF file.
Definition: mptrac.h:1242
#define NC_GET_DOUBLE(varname, ptr, force)
Retrieve a double-precision variable from a NetCDF file.
Definition: mptrac.h:1214

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

6341 {
6342
6343 int ncid, varid;
6344
6345 /* Open file... */
6346 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6347 return 0;
6348
6349 /* Get dimensions... */
6350 NC_INQ_DIM("obs", &atm->np, 1, NP);
6351
6352 /* Read geolocations... */
6353 NC_GET_DOUBLE("time", atm->time, 1);
6354 NC_GET_DOUBLE("press", atm->p, 1);
6355 NC_GET_DOUBLE("lon", atm->lon, 1);
6356 NC_GET_DOUBLE("lat", atm->lat, 1);
6357
6358 /* Read variables... */
6359 for (int iq = 0; iq < ctl->nq; iq++)
6360 NC_GET_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
6361
6362 /* Close file... */
6363 NC(nc_close(ncid));
6364
6365 /* Return success... */
6366 return 1;
6367}

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

6373 {
6374
6375 int ncid, varid;
6376
6377 /* Write info... */
6378 LOG(1, "Read photolysis rates: %s", filename);
6379
6380 /* Open netCDF file... */
6381 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
6382 WARN("Photolysis rate data are missing!");
6383 return;
6384 }
6385
6386 /* Read pressure data... */
6387 NC_INQ_DIM("press", &photo->np, 2, CP);
6388 NC_GET_DOUBLE("press", photo->p, 1);
6389 if (photo->p[0] < photo->p[1])
6390 ERRMSG("Pressure data are not descending!");
6391
6392 /* Read total column ozone data... */
6393 NC_INQ_DIM("total_o3col", &photo->no3c, 2, CO3);
6394 NC_GET_DOUBLE("total_o3col", photo->o3c, 1);
6395 if (photo->o3c[0] > photo->o3c[1])
6396 ERRMSG("Total column ozone data are not ascending!");
6397
6398 /* Read solar zenith angle data... */
6399 NC_INQ_DIM("sza", &photo->nsza, 2, CSZA);
6400 NC_GET_DOUBLE("sza", photo->sza, 1);
6401 if (photo->sza[0] > photo->sza[1])
6402 ERRMSG("Solar zenith angle data are not ascending!");
6403
6404 /* Read data... */
6405 read_clim_photo_help(ncid, "J_N2O", photo, photo->n2o);
6406 read_clim_photo_help(ncid, "J_CCl4", photo, photo->ccl4);
6407 read_clim_photo_help(ncid, "J_CFC-11", photo, photo->ccl3f);
6408 read_clim_photo_help(ncid, "J_CFC-12", photo, photo->ccl2f2);
6409 read_clim_photo_help(ncid, "J_O2", photo, photo->o2);
6410 read_clim_photo_help(ncid, "J_O3b", photo, photo->o3_1);
6411 read_clim_photo_help(ncid, "J_O3a", photo, photo->o3_2);
6412 read_clim_photo_help(ncid, "J_H2O2", photo, photo->h2o2);
6413 read_clim_photo_help(ncid, "J_H2O", photo, photo->h2o);
6414
6415 /* Close netCDF file... */
6416 NC(nc_close(ncid));
6417
6418 /* Write info... */
6419 LOG(2, "Number of pressure levels: %d", photo->np);
6420 LOG(2, "Altitude levels: %g, %g ... %g km",
6421 Z(photo->p[0]), Z(photo->p[1]), Z(photo->p[photo->np - 1]));
6422 LOG(2, "Pressure levels: %g, %g ... %g hPa",
6423 photo->p[0], photo->p[1], photo->p[photo->np - 1]);
6424 LOG(2, "Number of solar zenith angles: %d", photo->nsza);
6425 LOG(2, "Solar zenith angles: %g, %g ... %g deg",
6426 RAD2DEG(photo->sza[0]), RAD2DEG(photo->sza[1]),
6427 RAD2DEG(photo->sza[photo->nsza - 1]));
6428 LOG(2, "Number of total column ozone values: %d", photo->no3c);
6429 LOG(2, "Total column ozone: %g, %g ... %g DU",
6430 photo->o3c[0], photo->o3c[1], photo->o3c[photo->no3c - 1]);
6431 LOG(2, "N2O photolysis rate: %g, %g ... %g s**-1",
6432 photo->n2o[0][0][0], photo->n2o[1][0][0],
6433 photo->n2o[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6434 LOG(2, "CCl4 photolysis rate: %g, %g ... %g s**-1",
6435 photo->ccl4[0][0][0], photo->ccl4[1][0][0],
6436 photo->ccl4[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6437 LOG(2, "CFC-11 photolysis rate: %g, %g ... %g s**-1",
6438 photo->ccl3f[0][0][0], photo->ccl3f[1][0][0],
6439 photo->ccl3f[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6440 LOG(2, "CFC-12 photolysis rate: %g, %g ... %g s**-1",
6441 photo->ccl2f2[0][0][0], photo->ccl2f2[1][0][0],
6442 photo->ccl2f2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6443 LOG(2, "O2 photolysis rate: %g, %g ... %g s**-1",
6444 photo->o2[0][0][0], photo->o2[1][0][0],
6445 photo->o2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6446 LOG(2, "O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
6447 photo->o3_1[0][0][0], photo->o3_1[1][0][0],
6448 photo->o3_1[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6449 LOG(2, "O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
6450 photo->o3_2[0][0][0], photo->o3_2[1][0][0],
6451 photo->o3_2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6452 LOG(2, "H2O2 photolysis rate: %g, %g ... %g s**-1",
6453 photo->h2o2[0][0][0], photo->h2o2[1][0][0],
6454 photo->h2o2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6455 LOG(2, "H2O photolysis rate: %g, %g ... %g s**-1",
6456 photo->h2o[0][0][0], photo->h2o[1][0][0],
6457 photo->h2o[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6458}
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:6462
#define CP
Maximum number of pressure levels for climatological data.
Definition: mptrac.h:368
#define CO3
Maximum number of total column ozone data for climatological data.
Definition: mptrac.h:363
#define CSZA
Maximum number of solar zenith angles for climatological data.
Definition: mptrac.h:373
double o3_1[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O1d + O2) [1/s].
Definition: mptrac.h:3411
double o2[CP][CSZA][CO3]
O2 photolysis rate [1/s].
Definition: mptrac.h:3408
double h2o2[CP][CSZA][CO3]
H2O2 photolysis rate [1/s].
Definition: mptrac.h:3417
double h2o[CP][CSZA][CO3]
H2O photolysis rate [1/s].
Definition: mptrac.h:3420
double o3_2[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O3p + O2) [1/s].
Definition: mptrac.h:3414
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 6462 of file mptrac.c.

6466 {
6467
6468 /* Allocate... */
6469 double *help;
6470 ALLOC(help, double,
6471 photo->np * photo->nsza * photo->no3c);
6472
6473 /* Read varible... */
6474 int varid;
6475 NC_GET_DOUBLE(varname, help, 1);
6476
6477 /* Copy data... */
6478 for (int ip = 0; ip < photo->np; ip++)
6479 for (int is = 0; is < photo->nsza; is++)
6480 for (int io = 0; io < photo->no3c; io++)
6481 var[ip][is][io] =
6482 help[ARRAY_3D(ip, is, photo->nsza, io, photo->no3c)];
6483
6484 /* Free... */
6485 free(help);
6486}

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

6492 {
6493
6494 /* Write info... */
6495 LOG(1, "Read climatological time series: %s", filename);
6496
6497 /* Open file... */
6498 FILE *in;
6499 if (!(in = fopen(filename, "r"))) {
6500 WARN("Cannot open file!");
6501 return 0;
6502 }
6503
6504 /* Read data... */
6505 char line[LEN];
6506 int nh = 0;
6507 while (fgets(line, LEN, in))
6508 if (sscanf(line, "%lg %lg", &ts->time[nh], &ts->vmr[nh]) == 2) {
6509
6510 /* Convert years to seconds... */
6511 ts->time[nh] = (ts->time[nh] - 2000.0) * 365.25 * 86400.;
6512
6513 /* Check data... */
6514 if (nh > 0 && ts->time[nh] <= ts->time[nh - 1])
6515 ERRMSG("Time series must be ascending!");
6516
6517 /* Count time steps... */
6518 if ((++nh) >= CTS)
6519 ERRMSG("Too many data points!");
6520 }
6521
6522 /* Close file... */
6523 fclose(in);
6524
6525 /* Check number of data points... */
6526 ts->ntime = nh;
6527 if (nh < 2)
6528 ERRMSG("Not enough data points!");
6529
6530 /* Write info... */
6531 LOG(2, "Number of time steps: %d", ts->ntime);
6532 LOG(2, "Time steps: %.2f, %.2f ... %.2f s", ts->time[0], ts->time[1],
6533 ts->time[nh - 1]);
6534 LOG(2, "Volume mixing ratio range: %g ... %g ppv",
6535 gsl_stats_min(ts->vmr, 1, (size_t) nh), gsl_stats_max(ts->vmr, 1,
6536 (size_t) nh));
6537
6538 /* Exit success... */
6539 return 1;
6540}
#define CTS
Maximum number of data points of climatological time series.
Definition: mptrac.h:383

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

6547 {
6548
6549 int ncid, varid, it, iy, iz, iz2, nt;
6550
6551 double *help, varmin = 1e99, varmax = -1e99;
6552
6553 /* Write info... */
6554 LOG(1, "Read %s data: %s", varname, filename);
6555
6556 /* Open netCDF file... */
6557 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
6558 WARN("%s climatology data are missing!", varname);
6559 return;
6560 }
6561
6562 /* Read pressure data... */
6563 NC_INQ_DIM("press", &zm->np, 2, CP);
6564 NC_GET_DOUBLE("press", zm->p, 1);
6565 if (zm->p[0] < zm->p[1])
6566 ERRMSG("Pressure data are not descending!");
6567
6568 /* Read latitudes... */
6569 NC_INQ_DIM("lat", &zm->nlat, 2, CY);
6570 NC_GET_DOUBLE("lat", zm->lat, 1);
6571 if (zm->lat[0] > zm->lat[1])
6572 ERRMSG("Latitude data are not ascending!");
6573
6574 /* Set time data (for monthly means)... */
6575 zm->ntime = 12;
6576 zm->time[0] = 1209600.00;
6577 zm->time[1] = 3888000.00;
6578 zm->time[2] = 6393600.00;
6579 zm->time[3] = 9072000.00;
6580 zm->time[4] = 11664000.00;
6581 zm->time[5] = 14342400.00;
6582 zm->time[6] = 16934400.00;
6583 zm->time[7] = 19612800.00;
6584 zm->time[8] = 22291200.00;
6585 zm->time[9] = 24883200.00;
6586 zm->time[10] = 27561600.00;
6587 zm->time[11] = 30153600.00;
6588
6589 /* Check number of timesteps... */
6590 NC_INQ_DIM("time", &nt, 12, 12);
6591
6592 /* Read data... */
6593 ALLOC(help, double,
6594 zm->nlat * zm->np * zm->ntime);
6595 NC_GET_DOUBLE(varname, help, 1);
6596 for (it = 0; it < zm->ntime; it++)
6597 for (iz = 0; iz < zm->np; iz++)
6598 for (iy = 0; iy < zm->nlat; iy++)
6599 zm->vmr[it][iz][iy] = help[ARRAY_3D(it, iz, zm->np, iy, zm->nlat)];
6600 free(help);
6601
6602 /* Fix data gaps... */
6603 for (it = 0; it < zm->ntime; it++)
6604 for (iy = 0; iy < zm->nlat; iy++)
6605 for (iz = 0; iz < zm->np; iz++) {
6606 if (zm->vmr[it][iz][iy] < 0) {
6607 for (iz2 = 0; iz2 < zm->np; iz2++)
6608 if (zm->vmr[it][iz2][iy] >= 0) {
6609 zm->vmr[it][iz][iy] = zm->vmr[it][iz2][iy];
6610 break;
6611 }
6612 for (iz2 = zm->np - 1; iz2 >= 0; iz2--)
6613 if (zm->vmr[it][iz2][iy] >= 0) {
6614 zm->vmr[it][iz][iy] = zm->vmr[it][iz2][iy];
6615 break;
6616 }
6617 }
6618 varmin = MIN(varmin, zm->vmr[it][iz][iy]);
6619 varmax = MAX(varmax, zm->vmr[it][iz][iy]);
6620 }
6621
6622 /* Close netCDF file... */
6623 NC(nc_close(ncid));
6624
6625 /* Write info... */
6626 LOG(2, "Number of time steps: %d", zm->ntime);
6627 LOG(2, "Time steps: %.2f, %.2f ... %.2f s",
6628 zm->time[0], zm->time[1], zm->time[zm->ntime - 1]);
6629 LOG(2, "Number of pressure levels: %d", zm->np);
6630 LOG(2, "Altitude levels: %g, %g ... %g km",
6631 Z(zm->p[0]), Z(zm->p[1]), Z(zm->p[zm->np - 1]));
6632 LOG(2, "Pressure levels: %g, %g ... %g hPa", zm->p[0],
6633 zm->p[1], zm->p[zm->np - 1]);
6634 LOG(2, "Number of latitudes: %d", zm->nlat);
6635 LOG(2, "Latitudes: %g, %g ... %g deg",
6636 zm->lat[0], zm->lat[1], zm->lat[zm->nlat - 1]);
6637 LOG(2, "%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
6638 varmax);
6639}
#define CY
Maximum number of latitudes for climatological data.
Definition: mptrac.h:358

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

6647 {
6648
6649 /* Write info... */
6650 LOG(1, "Read kernel function: %s", filename);
6651
6652 /* Open file... */
6653 FILE *in;
6654 if (!(in = fopen(filename, "r")))
6655 ERRMSG("Cannot open file!");
6656
6657 /* Read data... */
6658 char line[LEN];
6659 int n = 0;
6660 while (fgets(line, LEN, in))
6661 if (sscanf(line, "%lg %lg", &kz[n], &kw[n]) == 2) {
6662 if (n > 0 && kz[n] < kz[n - 1])
6663 ERRMSG("Height levels must be ascending!");
6664 if ((++n) >= EP)
6665 ERRMSG("Too many height levels!");
6666 }
6667
6668 /* Close file... */
6669 fclose(in);
6670
6671 /* Check number of data points... */
6672 *nk = n;
6673 if (n < 2)
6674 ERRMSG("Not enough height levels!");
6675
6676 /* Normalize kernel function... */
6677 const double kmax = gsl_stats_max(kw, 1, (size_t) n);
6678 for (int iz = 0; iz < n; iz++)
6679 kw[iz] /= kmax;
6680}

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

6687 {
6688
6689 FILE *in;
6690
6691 double r;
6692
6693 int year, mon, day, hour, min, sec;
6694
6695 /* Set timer... */
6696 SELECT_TIMER("READ_MET_BIN", "INPUT", NVTX_READ);
6697
6698 /* Open file... */
6699 if (!(in = fopen(filename, "r"))) {
6700 WARN("Cannot open file!");
6701 return 0;
6702 }
6703
6704 /* Check type of binary data... */
6705 int met_type;
6706 FREAD(&met_type, int,
6707 1,
6708 in);
6709 if (met_type != ctl->met_type)
6710 ERRMSG("Wrong MET_TYPE of binary data!");
6711
6712 /* Check version of binary data... */
6713 int version;
6714 FREAD(&version, int,
6715 1,
6716 in);
6717 if (version != 103)
6718 ERRMSG("Wrong version of binary data!");
6719
6720 /* Read time... */
6721 FREAD(&met->time, double,
6722 1,
6723 in);
6724 jsec2time(met->time, &year, &mon, &day, &hour, &min, &sec, &r);
6725 LOG(2, "Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
6726 met->time, year, mon, day, hour, min);
6727 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
6728 || day < 1 || day > 31 || hour < 0 || hour > 23)
6729 ERRMSG("Error while reading time!");
6730
6731 /* Read dimensions... */
6732 FREAD(&met->nx, int,
6733 1,
6734 in);
6735 LOG(2, "Number of longitudes: %d", met->nx);
6736 if (met->nx < 2 || met->nx > EX)
6737 ERRMSG("Number of longitudes out of range!");
6738
6739 FREAD(&met->ny, int,
6740 1,
6741 in);
6742 LOG(2, "Number of latitudes: %d", met->ny);
6743 if (met->ny < 2 || met->ny > EY)
6744 ERRMSG("Number of latitudes out of range!");
6745
6746 FREAD(&met->np, int,
6747 1,
6748 in);
6749 LOG(2, "Number of levels: %d", met->np);
6750 if (met->np < 2 || met->np > EP)
6751 ERRMSG("Number of levels out of range!");
6752
6753 /* Read grid... */
6754 FREAD(met->lon, double,
6755 (size_t) met->nx,
6756 in);
6757 LOG(2, "Longitudes: %g, %g ... %g deg",
6758 met->lon[0], met->lon[1], met->lon[met->nx - 1]);
6759
6760 FREAD(met->lat, double,
6761 (size_t) met->ny,
6762 in);
6763 LOG(2, "Latitudes: %g, %g ... %g deg",
6764 met->lat[0], met->lat[1], met->lat[met->ny - 1]);
6765
6766 FREAD(met->p, double,
6767 (size_t) met->np,
6768 in);
6769 LOG(2, "Altitude levels: %g, %g ... %g km",
6770 Z(met->p[0]), Z(met->p[1]), Z(met->p[met->np - 1]));
6771 LOG(2, "Pressure levels: %g, %g ... %g hPa",
6772 met->p[0], met->p[1], met->p[met->np - 1]);
6773
6774 /* Read surface data... */
6775 read_met_bin_2d(in, met, met->ps, "PS");
6776 read_met_bin_2d(in, met, met->ts, "TS");
6777 read_met_bin_2d(in, met, met->zs, "ZS");
6778 read_met_bin_2d(in, met, met->us, "US");
6779 read_met_bin_2d(in, met, met->vs, "VS");
6780 read_met_bin_2d(in, met, met->ess, "ESS");
6781 read_met_bin_2d(in, met, met->nss, "NSS");
6782 read_met_bin_2d(in, met, met->shf, "SHF");
6783 read_met_bin_2d(in, met, met->lsm, "LSM");
6784 read_met_bin_2d(in, met, met->sst, "SST");
6785 read_met_bin_2d(in, met, met->pbl, "PBL");
6786 read_met_bin_2d(in, met, met->pt, "PT");
6787 read_met_bin_2d(in, met, met->tt, "TT");
6788 read_met_bin_2d(in, met, met->zt, "ZT");
6789 read_met_bin_2d(in, met, met->h2ot, "H2OT");
6790 read_met_bin_2d(in, met, met->pct, "PCT");
6791 read_met_bin_2d(in, met, met->pcb, "PCB");
6792 read_met_bin_2d(in, met, met->cl, "CL");
6793 read_met_bin_2d(in, met, met->plcl, "PLCL");
6794 read_met_bin_2d(in, met, met->plfc, "PLFC");
6795 read_met_bin_2d(in, met, met->pel, "PEL");
6796 read_met_bin_2d(in, met, met->cape, "CAPE");
6797 read_met_bin_2d(in, met, met->cin, "CIN");
6798 read_met_bin_2d(in, met, met->o3c, "O3C");
6799
6800 /* Read level data... */
6801 read_met_bin_3d(in, ctl, met, met->z, "Z", -1e34f, 1e34f);
6802 read_met_bin_3d(in, ctl, met, met->t, "T", 0, 1e34f);
6803 read_met_bin_3d(in, ctl, met, met->u, "U", -1e34f, 1e34f);
6804 read_met_bin_3d(in, ctl, met, met->v, "V", -1e34f, 1e34f);
6805 read_met_bin_3d(in, ctl, met, met->w, "W", -1e34f, 1e34f);
6806 read_met_bin_3d(in, ctl, met, met->pv, "PV", -1e34f, 1e34f);
6807 read_met_bin_3d(in, ctl, met, met->h2o, "H2O", 0, 1e34f);
6808 read_met_bin_3d(in, ctl, met, met->o3, "O3", 0, 1e34f);
6809 read_met_bin_3d(in, ctl, met, met->lwc, "LWC", 0, 1e34f);
6810 read_met_bin_3d(in, ctl, met, met->rwc, "RWC", 0, 1e34f);
6811 read_met_bin_3d(in, ctl, met, met->iwc, "IWC", 0, 1e34f);
6812 read_met_bin_3d(in, ctl, met, met->swc, "SWC", 0, 1e34f);
6813 read_met_bin_3d(in, ctl, met, met->cc, "CC", 0, 1);
6814
6815 /* Read final flag... */
6816 int final;
6817 FREAD(&final, int,
6818 1,
6819 in);
6820 if (final != 999)
6821 ERRMSG("Error while reading binary data!");
6822
6823 /* Close file... */
6824 fclose(in);
6825
6826 /* Return success... */
6827 return 1;
6828}
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:6832
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:6861
#define EY
Maximum number of latitudes for meteo data.
Definition: mptrac.h:298
float zt[EX][EY]
Tropopause geopotential height [km].
Definition: mptrac.h:3627
float sst[EX][EY]
Sea surface temperature [K].
Definition: mptrac.h:3615
float rwc[EX][EY][EP]
Cloud rain water content [kg/kg].
Definition: mptrac.h:3687
float o3c[EX][EY]
Total column ozone [DU].
Definition: mptrac.h:3657
float cape[EX][EY]
Convective available potential energy [J/kg].
Definition: mptrac.h:3651
float pct[EX][EY]
Cloud top pressure [hPa].
Definition: mptrac.h:3633
float shf[EX][EY]
Surface sensible heat flux [W/m^2].
Definition: mptrac.h:3609
float lwc[EX][EY][EP]
Cloud liquid water content [kg/kg].
Definition: mptrac.h:3684
float us[EX][EY]
Surface zonal wind [m/s].
Definition: mptrac.h:3597
float cc[EX][EY][EP]
Cloud cover [1].
Definition: mptrac.h:3696
float ts[EX][EY]
Surface temperature [K].
Definition: mptrac.h:3591
float ess[EX][EY]
Eastward turbulent surface stress [N/m^2].
Definition: mptrac.h:3603
float pcb[EX][EY]
Cloud bottom pressure [hPa].
Definition: mptrac.h:3636
float pel[EX][EY]
Pressure at equilibrium level (EL) [hPa].
Definition: mptrac.h:3648
float cin[EX][EY]
Convective inhibition [J/kg].
Definition: mptrac.h:3654
float plcl[EX][EY]
Pressure at lifted condensation level (LCL) [hPa].
Definition: mptrac.h:3642
float tt[EX][EY]
Tropopause temperature [K].
Definition: mptrac.h:3624
float pbl[EX][EY]
Boundary layer pressure [hPa].
Definition: mptrac.h:3618
float vs[EX][EY]
Surface meridional wind [m/s].
Definition: mptrac.h:3600
float lsm[EX][EY]
Land-sea mask [1].
Definition: mptrac.h:3612
float iwc[EX][EY][EP]
Cloud ice water content [kg/kg].
Definition: mptrac.h:3690
float h2ot[EX][EY]
Tropopause water vapor volume mixing ratio [ppv].
Definition: mptrac.h:3630
float pv[EX][EY][EP]
Potential vorticity [PVU].
Definition: mptrac.h:3675
float cl[EX][EY]
Total column cloud water [kg/m^2].
Definition: mptrac.h:3639
float nss[EX][EY]
Northward turbulent surface stress [N/m^2].
Definition: mptrac.h:3606
float plfc[EX][EY]
Pressure at level of free convection (LFC) [hPa].
Definition: mptrac.h:3645
float swc[EX][EY][EP]
Cloud snow water content [kg/kg].
Definition: mptrac.h:3693
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 6832 of file mptrac.c.

6836 {
6837
6838 float *help;
6839
6840 /* Allocate... */
6841 ALLOC(help, float,
6842 EX * EY);
6843
6844 /* Read uncompressed... */
6845 LOG(2, "Read 2-D variable: %s (uncompressed)", varname);
6846 FREAD(help, float,
6847 (size_t) (met->nx * met->ny),
6848 in);
6849
6850 /* Copy data... */
6851 for (int ix = 0; ix < met->nx; ix++)
6852 for (int iy = 0; iy < met->ny; iy++)
6853 var[ix][iy] = help[ARRAY_2D(ix, iy, met->ny)];
6854
6855 /* Free... */
6856 free(help);
6857}
#define ARRAY_2D(ix, iy, ny)
Macro for computing the linear index of a 2D array element.
Definition: mptrac.h:449

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

6868 {
6869
6870 float *help;
6871
6872 /* Allocate... */
6873 ALLOC(help, float,
6874 EX * EY * EP);
6875
6876 /* Read uncompressed data... */
6877 if (ctl->met_type == 1) {
6878 LOG(2, "Read 3-D variable: %s (uncompressed)", varname);
6879 FREAD(help, float,
6880 (size_t) (met->nx * met->ny * met->np),
6881 in);
6882 }
6883
6884 /* Read packed data... */
6885 else if (ctl->met_type == 2)
6886 compress_pck(varname, help, (size_t) (met->ny * met->nx),
6887 (size_t) met->np, 1, in);
6888
6889 /* Read ZFP data... */
6890 else if (ctl->met_type == 3) {
6891#ifdef ZFP
6892 int precision;
6893 FREAD(&precision, int,
6894 1,
6895 in);
6896
6897 double tolerance;
6898 FREAD(&tolerance, double,
6899 1,
6900 in);
6901
6902 compress_zfp(varname, help, met->np, met->ny, met->nx, precision,
6903 tolerance, 1, in);
6904#else
6905 ERRMSG("MPTRAC was compiled without ZFP compression!");
6906#endif
6907 }
6908
6909 /* Read zstd data... */
6910 else if (ctl->met_type == 4) {
6911#ifdef ZSTD
6912 compress_zstd(varname, help, (size_t) (met->np * met->ny * met->nx), 1,
6913 ctl->met_zstd_level, in);
6914#else
6915 ERRMSG("MPTRAC was compiled without ZSTD compression!");
6916#endif
6917 }
6918
6919 /* Read cmultiscale data... */
6920 else if (ctl->met_type == 5) {
6921#ifdef CMS
6922 compress_cms(ctl, varname, help, (size_t) met->nx, (size_t) met->ny,
6923 (size_t) met->np, 1, in);
6924#else
6925 ERRMSG("MPTRAC was compiled without cmultiscale compression!");
6926#endif
6927 }
6928
6929 /* Read SZ3 data... */
6930 else if (ctl->met_type == 7) {
6931#ifdef SZ3
6932 int precision;
6933 FREAD(&precision, int,
6934 1,
6935 in);
6936
6937 double tolerance;
6938 FREAD(&tolerance, double,
6939 1,
6940 in);
6941
6942 compress_sz3(varname, help, met->np, met->ny, met->nx, precision,
6943 tolerance, 1, in);
6944#else
6945 ERRMSG("MPTRAC was compiled without sz3 compression!");
6946#endif
6947 }
6948
6949 /* Copy data... */
6950#pragma omp parallel for default(shared) collapse(2)
6951 for (int ix = 0; ix < met->nx; ix++)
6952 for (int iy = 0; iy < met->ny; iy++)
6953 for (int ip = 0; ip < met->np; ip++) {
6954 var[ix][iy][ip] = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
6955 if (var[ix][iy][ip] < bound_min)
6956 var[ix][iy][ip] = bound_min;
6957 else if (var[ix][iy][ip] > bound_max)
6958 var[ix][iy][ip] = bound_max;
6959 }
6960
6961 /* Free... */
6962 free(help);
6963}
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:673
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.
void compress_sz3(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 3-D float array using the SZ3 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 6967 of file mptrac.c.

6970 {
6971
6972 /* Check parameters... */
6973 if (ctl->met_cape != 1)
6974 return;
6975
6976 /* Set timer... */
6977 SELECT_TIMER("READ_MET_CAPE", "METPROC", NVTX_READ);
6978 LOG(2, "Calculate CAPE...");
6979
6980 /* Vertical spacing (about 100 m)... */
6981 const double pfac = 1.01439, dz0 = RI / MA / G0 * log(pfac);
6982
6983 /* Loop over columns... */
6984#pragma omp parallel for default(shared) collapse(2)
6985 for (int ix = 0; ix < met->nx; ix++)
6986 for (int iy = 0; iy < met->ny; iy++) {
6987
6988 /* Get potential temperature and water vapor at lowest 50 hPa... */
6989 int n = 0;
6990 double h2o = 0, t, theta = 0;
6991 double pbot = MIN(met->ps[ix][iy], met->p[0]);
6992 double ptop = pbot - 50.;
6993 for (int ip = 0; ip < met->np; ip++) {
6994 if (met->p[ip] <= pbot) {
6995 theta += THETA(met->p[ip], met->t[ix][iy][ip]);
6996 h2o += met->h2o[ix][iy][ip];
6997 n++;
6998 }
6999 if (met->p[ip] < ptop && n > 0)
7000 break;
7001 }
7002 theta /= n;
7003 h2o /= n;
7004
7005 /* Cannot compute anything if water vapor is missing... */
7006 met->plcl[ix][iy] = NAN;
7007 met->plfc[ix][iy] = NAN;
7008 met->pel[ix][iy] = NAN;
7009 met->cape[ix][iy] = NAN;
7010 met->cin[ix][iy] = NAN;
7011 if (h2o <= 0)
7012 continue;
7013
7014 /* Find lifted condensation level (LCL)... */
7015 ptop = P(20.);
7016 pbot = met->ps[ix][iy];
7017 do {
7018 met->plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
7019 t = theta / pow(1000. / met->plcl[ix][iy], 0.286);
7020 if (RH(met->plcl[ix][iy], t, h2o) > 100.)
7021 ptop = met->plcl[ix][iy];
7022 else
7023 pbot = met->plcl[ix][iy];
7024 } while (pbot - ptop > 0.1);
7025
7026 /* Calculate CIN up to LCL... */
7028 double dcape, dz, h2o_env, t_env;
7029 double p = met->ps[ix][iy];
7030 met->cape[ix][iy] = met->cin[ix][iy] = 0;
7031 do {
7032 dz = dz0 * TVIRT(t, h2o);
7033 p /= pfac;
7034 t = theta / pow(1000. / p, 0.286);
7035 intpol_met_space_3d(met, met->t, p, met->lon[ix], met->lat[iy],
7036 &t_env, ci, cw, 1);
7037 intpol_met_space_3d(met, met->h2o, p, met->lon[ix], met->lat[iy],
7038 &h2o_env, ci, cw, 0);
7039 dcape = 1e3 * G0 * (TVIRT(t, h2o) - TVIRT(t_env, h2o_env)) /
7040 TVIRT(t_env, h2o_env) * dz;
7041 if (dcape < 0)
7042 met->cin[ix][iy] += fabsf((float) dcape);
7043 } while (p > met->plcl[ix][iy]);
7044
7045 /* Calculate level of free convection (LFC), equilibrium level (EL),
7046 and convective available potential energy (CAPE)... */
7047 dcape = 0;
7048 p = met->plcl[ix][iy];
7049 t = theta / pow(1000. / p, 0.286);
7050 ptop = 0.75 * clim_tropo(clim, met->time, met->lat[iy]);
7051 do {
7052 dz = dz0 * TVIRT(t, h2o);
7053 p /= pfac;
7054 t -= lapse_rate(t, h2o) * dz;
7055 double psat = PSAT(t);
7056 h2o = psat / (p - (1. - EPS) * psat);
7057 intpol_met_space_3d(met, met->t, p, met->lon[ix], met->lat[iy],
7058 &t_env, ci, cw, 1);
7059 intpol_met_space_3d(met, met->h2o, p, met->lon[ix], met->lat[iy],
7060 &h2o_env, ci, cw, 0);
7061 double dcape_old = dcape;
7062 dcape = 1e3 * G0 * (TVIRT(t, h2o) - TVIRT(t_env, h2o_env)) /
7063 TVIRT(t_env, h2o_env) * dz;
7064 if (dcape > 0) {
7065 met->cape[ix][iy] += (float) dcape;
7066 if (!isfinite(met->plfc[ix][iy]))
7067 met->plfc[ix][iy] = (float) p;
7068 } else if (dcape_old > 0)
7069 met->pel[ix][iy] = (float) p;
7070 if (dcape < 0 && !isfinite(met->plfc[ix][iy]))
7071 met->cin[ix][iy] += fabsf((float) dcape);
7072 } while (p > ptop);
7073
7074 /* Check results... */
7075 if (!isfinite(met->plfc[ix][iy]))
7076 met->cin[ix][iy] = NAN;
7077 }
7078}
double clim_tropo(const clim_t *clim, const double t, const double lat)
Calculates the tropopause pressure based on climatological data.
Definition: mptrac.c:205
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 7082 of file mptrac.c.

7083 {
7084
7085 /* Set timer... */
7086 SELECT_TIMER("READ_MET_CLOUD", "METPROC", NVTX_READ);
7087 LOG(2, "Calculate cloud data...");
7088
7089 /* Thresholds for cloud detection... */
7090 const double ccmin = 0.01, cwmin = 1e-6;
7091
7092 /* Loop over columns... */
7093#pragma omp parallel for default(shared) collapse(2)
7094 for (int ix = 0; ix < met->nx; ix++)
7095 for (int iy = 0; iy < met->ny; iy++) {
7096
7097 /* Init... */
7098 met->pct[ix][iy] = NAN;
7099 met->pcb[ix][iy] = NAN;
7100 met->cl[ix][iy] = 0;
7101
7102 /* Loop over pressure levels... */
7103 for (int ip = 0; ip < met->np - 1; ip++) {
7104
7105 /* Check pressure... */
7106 if (met->p[ip] > met->ps[ix][iy] || met->p[ip] < P(20.))
7107 continue;
7108
7109 /* Check ice water and liquid water content... */
7110 if (met->cc[ix][iy][ip] > ccmin
7111 && (met->lwc[ix][iy][ip] > cwmin
7112 || met->rwc[ix][iy][ip] > cwmin
7113 || met->iwc[ix][iy][ip] > cwmin
7114 || met->swc[ix][iy][ip] > cwmin)) {
7115
7116 /* Get cloud top pressure ... */
7117 met->pct[ix][iy]
7118 = (float) (0.5 * (met->p[ip] + (float) met->p[ip + 1]));
7119
7120 /* Get cloud bottom pressure ... */
7121 if (!isfinite(met->pcb[ix][iy]))
7122 met->pcb[ix][iy]
7123 = (float) (0.5 * (met->p[ip] + met->p[MAX(ip - 1, 0)]));
7124 }
7125
7126 /* Get cloud water... */
7127 met->cl[ix][iy] += (float)
7128 (0.5 * (met->lwc[ix][iy][ip] + met->lwc[ix][iy][ip + 1]
7129 + met->rwc[ix][iy][ip] + met->rwc[ix][iy][ip + 1]
7130 + met->iwc[ix][iy][ip] + met->iwc[ix][iy][ip + 1]
7131 + met->swc[ix][iy][ip] + met->swc[ix][iy][ip + 1])
7132 * 100. * (met->p[ip] - met->p[ip + 1]) / G0);
7133 }
7134 }
7135}

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

7141 {
7142
7143 met_t *help;
7144
7145 /* Check parameters... */
7146 if (ctl->met_detrend <= 0)
7147 return;
7148
7149 /* Set timer... */
7150 SELECT_TIMER("READ_MET_DETREND", "METPROC", NVTX_READ);
7151 LOG(2, "Detrend meteo data...");
7152
7153 /* Allocate... */
7154 ALLOC(help, met_t, 1);
7155
7156 /* Calculate standard deviation... */
7157 const double sigma = ctl->met_detrend / 2.355;
7158 const double tssq = 2. * SQR(sigma);
7159
7160 /* Calculate box size in latitude... */
7161 int sy = (int) (3. * DY2DEG(sigma) / fabs(met->lat[1] - met->lat[0]));
7162 sy = MIN(MAX(1, sy), met->ny / 2);
7163
7164 /* Calculate background... */
7165#pragma omp parallel for default(shared) collapse(2)
7166 for (int ix = 0; ix < met->nx; ix++) {
7167 for (int iy = 0; iy < met->ny; iy++) {
7168
7169 /* Calculate Cartesian coordinates... */
7170 double x0[3];
7171 geo2cart(0.0, met->lon[ix], met->lat[iy], x0);
7172
7173 /* Calculate box size in longitude... */
7174 int sx =
7175 (int) (3. * DX2DEG(sigma, met->lat[iy]) /
7176 fabs(met->lon[1] - met->lon[0]));
7177 sx = MIN(MAX(1, sx), met->nx / 2);
7178
7179 /* Init... */
7180 float wsum = 0;
7181 for (int ip = 0; ip < met->np; ip++) {
7182 help->t[ix][iy][ip] = 0;
7183 help->u[ix][iy][ip] = 0;
7184 help->v[ix][iy][ip] = 0;
7185 help->w[ix][iy][ip] = 0;
7186 }
7187
7188 /* Loop over neighboring grid points... */
7189 for (int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
7190 int ix3 = ix2;
7191 if (ix3 < 0)
7192 ix3 += met->nx;
7193 else if (ix3 >= met->nx)
7194 ix3 -= met->nx;
7195 for (int iy2 = MAX(iy - sy, 0);
7196 iy2 <= MIN(iy + sy, met->ny - 1); iy2++) {
7197
7198 /* Calculate Cartesian coordinates... */
7199 double x1[3];
7200 geo2cart(0.0, met->lon[ix3], met->lat[iy2], x1);
7201
7202 /* Calculate weighting factor... */
7203 const float w = (float) exp(-DIST2(x0, x1) / tssq);
7204
7205 /* Add data... */
7206 wsum += w;
7207 for (int ip = 0; ip < met->np; ip++) {
7208 help->t[ix][iy][ip] += w * met->t[ix3][iy2][ip];
7209 help->u[ix][iy][ip] += w * met->u[ix3][iy2][ip];
7210 help->v[ix][iy][ip] += w * met->v[ix3][iy2][ip];
7211 help->w[ix][iy][ip] += w * met->w[ix3][iy2][ip];
7212 }
7213 }
7214 }
7215
7216 /* Normalize... */
7217 for (int ip = 0; ip < met->np; ip++) {
7218 help->t[ix][iy][ip] /= wsum;
7219 help->u[ix][iy][ip] /= wsum;
7220 help->v[ix][iy][ip] /= wsum;
7221 help->w[ix][iy][ip] /= wsum;
7222 }
7223 }
7224 }
7225
7226 /* Subtract background... */
7227#pragma omp parallel for default(shared) collapse(3)
7228 for (int ix = 0; ix < met->nx; ix++)
7229 for (int iy = 0; iy < met->ny; iy++)
7230 for (int ip = 0; ip < met->np; ip++) {
7231 met->t[ix][iy][ip] -= help->t[ix][iy][ip];
7232 met->u[ix][iy][ip] -= help->u[ix][iy][ip];
7233 met->v[ix][iy][ip] -= help->v[ix][iy][ip];
7234 met->w[ix][iy][ip] -= help->w[ix][iy][ip];
7235 }
7236
7237 /* Free... */
7238 free(help);
7239}
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:1092
#define DIST2(a, b)
Calculate the squared Euclidean distance between two points in Cartesian coordinates.
Definition: mptrac.h:671
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 7243 of file mptrac.c.

7244 {
7245
7246 /* Set timer... */
7247 SELECT_TIMER("READ_MET_EXTRAPOLATE", "METPROC", NVTX_READ);
7248 LOG(2, "Extrapolate meteo data...");
7249
7250 /* Loop over columns... */
7251#pragma omp parallel for default(shared) collapse(2)
7252 for (int ix = 0; ix < met->nx; ix++)
7253 for (int iy = 0; iy < met->ny; iy++) {
7254
7255 /* Find lowest valid data point... */
7256 int ip0;
7257 for (ip0 = met->np - 1; ip0 >= 0; ip0--)
7258 if (!isfinite(met->t[ix][iy][ip0])
7259 || !isfinite(met->u[ix][iy][ip0])
7260 || !isfinite(met->v[ix][iy][ip0])
7261 || !isfinite(met->w[ix][iy][ip0]))
7262 break;
7263
7264 /* Extrapolate... */
7265 for (int ip = ip0; ip >= 0; ip--) {
7266 met->t[ix][iy][ip] = met->t[ix][iy][ip + 1];
7267 met->u[ix][iy][ip] = met->u[ix][iy][ip + 1];
7268 met->v[ix][iy][ip] = met->v[ix][iy][ip + 1];
7269 met->w[ix][iy][ip] = met->w[ix][iy][ip + 1];
7270 met->h2o[ix][iy][ip] = met->h2o[ix][iy][ip + 1];
7271 met->o3[ix][iy][ip] = met->o3[ix][iy][ip + 1];
7272 met->lwc[ix][iy][ip] = met->lwc[ix][iy][ip + 1];
7273 met->rwc[ix][iy][ip] = met->rwc[ix][iy][ip + 1];
7274 met->iwc[ix][iy][ip] = met->iwc[ix][iy][ip + 1];
7275 met->swc[ix][iy][ip] = met->swc[ix][iy][ip + 1];
7276 met->cc[ix][iy][ip] = met->cc[ix][iy][ip + 1];
7277 }
7278 }
7279}

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

7285 {
7286
7287 float *help;
7288
7289 double logp[EP];
7290
7291 int dx = ctl->met_geopot_sx, dy = ctl->met_geopot_sy;
7292
7293 /* Set timer... */
7294 SELECT_TIMER("READ_MET_GEOPOT", "METPROC", NVTX_READ);
7295 LOG(2, "Calculate geopotential heights...");
7296
7297 /* Allocate... */
7298 ALLOC(help, float,
7299 EX * EY * EP);
7300
7301 /* Calculate log pressure... */
7302#pragma omp parallel for default(shared)
7303 for (int ip = 0; ip < met->np; ip++)
7304 logp[ip] = log(met->p[ip]);
7305
7306 /* Apply hydrostatic equation to calculate geopotential heights... */
7307#pragma omp parallel for default(shared) collapse(2)
7308 for (int ix = 0; ix < met->nx; ix++)
7309 for (int iy = 0; iy < met->ny; iy++) {
7310
7311 /* Get surface height and pressure... */
7312 const double zs = met->zs[ix][iy];
7313 const double lnps = log(met->ps[ix][iy]);
7314
7315 /* Get temperature and water vapor at the surface... */
7316 const int ip0 = locate_irr(met->p, met->np, met->ps[ix][iy]);
7317 const double ts = LIN(met->p[ip0], met->t[ix][iy][ip0], met->p[ip0 + 1],
7318 met->t[ix][iy][ip0 + 1], met->ps[ix][iy]);
7319 const double h2os =
7320 LIN(met->p[ip0], met->h2o[ix][iy][ip0], met->p[ip0 + 1],
7321 met->h2o[ix][iy][ip0 + 1], met->ps[ix][iy]);
7322
7323 /* Upper part of profile... */
7324 met->z[ix][iy][ip0 + 1]
7325 = (float) (zs +
7326 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
7327 met->t[ix][iy][ip0 + 1], met->h2o[ix][iy][ip0 + 1]));
7328 for (int ip = ip0 + 2; ip < met->np; ip++)
7329 met->z[ix][iy][ip]
7330 = (float) (met->z[ix][iy][ip - 1] +
7331 ZDIFF(logp[ip - 1], met->t[ix][iy][ip - 1],
7332 met->h2o[ix][iy][ip - 1], logp[ip],
7333 met->t[ix][iy][ip], met->h2o[ix][iy][ip]));
7334
7335 /* Lower part of profile... */
7336 met->z[ix][iy][ip0]
7337 = (float) (zs +
7338 ZDIFF(lnps, ts, h2os, logp[ip0],
7339 met->t[ix][iy][ip0], met->h2o[ix][iy][ip0]));
7340 for (int ip = ip0 - 1; ip >= 0; ip--)
7341 met->z[ix][iy][ip]
7342 = (float) (met->z[ix][iy][ip + 1] +
7343 ZDIFF(logp[ip + 1], met->t[ix][iy][ip + 1],
7344 met->h2o[ix][iy][ip + 1], logp[ip],
7345 met->t[ix][iy][ip], met->h2o[ix][iy][ip]));
7346 }
7347
7348 /* Check control parameters... */
7349 if (dx == 0 || dy == 0)
7350 return;
7351
7352 /* Default smoothing parameters... */
7353 if (dx < 0 || dy < 0) {
7354 if (fabs(met->lon[1] - met->lon[0]) < 0.5) {
7355 dx = 3;
7356 dy = 2;
7357 } else {
7358 dx = 6;
7359 dy = 4;
7360 }
7361 }
7362
7363 /* Calculate weights for smoothing... */
7364 float ws[dx + 1][dy + 1];
7365#pragma omp parallel for default(shared) collapse(2)
7366 for (int ix = 0; ix <= dx; ix++)
7367 for (int iy = 0; iy < dy; iy++)
7368 ws[ix][iy] = (1.0f - (float) ix / (float) dx)
7369 * (1.0f - (float) iy / (float) dy);
7370
7371 /* Copy data... */
7372#pragma omp parallel for default(shared) collapse(3)
7373 for (int ix = 0; ix < met->nx; ix++)
7374 for (int iy = 0; iy < met->ny; iy++)
7375 for (int ip = 0; ip < met->np; ip++)
7376 help[ARRAY_3D(ip, ix, met->nx, iy, met->ny)] = met->z[ix][iy][ip];
7377
7378 /* Horizontal smoothing... */
7379#pragma omp parallel for default(shared) collapse(3)
7380 for (int ip = 0; ip < met->np; ip++)
7381 for (int ix = 0; ix < met->nx; ix++)
7382 for (int iy = 0; iy < met->ny; iy++) {
7383 float res = 0, wsum = 0;
7384 int iy0 = MAX(iy - dy + 1, 0);
7385 int iy1 = MIN(iy + dy - 1, met->ny - 1);
7386 for (int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
7387 int ix3 = ix2;
7388 if (ix3 < 0)
7389 ix3 += met->nx;
7390 else if (ix3 >= met->nx)
7391 ix3 -= met->nx;
7392 for (int iy2 = iy0; iy2 <= iy1; ++iy2)
7393 if (isfinite(help[ARRAY_3D(ip, ix3, met->nx, iy2, met->ny)])) {
7394 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
7395 res += w * help[ARRAY_3D(ip, ix3, met->nx, iy2, met->ny)];
7396 wsum += w;
7397 }
7398 }
7399 if (wsum > 0)
7400 met->z[ix][iy][ip] = res / wsum;
7401 else
7402 met->z[ix][iy][ip] = NAN;
7403 }
7404
7405 /* Free... */
7406 free(help);
7407}
#define ZDIFF(lnp0, t0, h2o0, lnp1, t1, h2o1)
Calculate geopotential height difference.
Definition: mptrac.h:1896
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 increment 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.
Author
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.
Author
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.
Author
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 8871 of file mptrac.c.

8875 {
8876
8877 double aux[EP], p[EP];
8878
8879 /* Set timer... */
8880 SELECT_TIMER("READ_MET_ML2PL", "METPROC", NVTX_READ);
8881 LOG(2, "Interpolate meteo data to pressure levels: %s", varname);
8882
8883 /* Loop over columns... */
8884#pragma omp parallel for default(shared) private(aux,p) collapse(2)
8885 for (int ix = 0; ix < met->nx; ix++)
8886 for (int iy = 0; iy < met->ny; iy++) {
8887
8888 /* Copy pressure profile... */
8889 for (int ip = 0; ip < met->np; ip++)
8890 p[ip] = met->pl[ix][iy][ip];
8891
8892 /* Interpolate... */
8893 for (int ip = 0; ip < ctl->met_np; ip++) {
8894 double pt = ctl->met_p[ip];
8895 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
8896 pt = p[0];
8897 else if ((pt > p[met->np - 1] && p[1] > p[0])
8898 || (pt < p[met->np - 1] && p[1] < p[0]))
8899 pt = p[met->np - 1];
8900 const int ip2 = locate_irr(p, met->np, pt);
8901 aux[ip] = LIN(p[ip2], var[ix][iy][ip2],
8902 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
8903 }
8904
8905 /* Copy data... */
8906 for (int ip = 0; ip < ctl->met_np; ip++)
8907 var[ix][iy][ip] = (float) aux[ip];
8908 }
8909}
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 8913 of file mptrac.c.

8915 {
8916
8917 /* Check parameters... */
8918 if (ctl->advect_vert_coord != 1)
8919 return;
8920
8921 /* Set timer... */
8922 SELECT_TIMER("READ_MET_MONOTONIZE", "METPROC", NVTX_READ);
8923 LOG(2, "Make zeta profiles monotone...");
8924
8925 /* Create monotone zeta profiles... */
8926#pragma omp parallel for default(shared) collapse(2)
8927 for (int i = 0; i < met->nx; i++)
8928 for (int j = 0; j < met->ny; j++) {
8929 int k = 1;
8930
8931 while (k < met->npl) { /* Check if there is an inversion at level k... */
8932 if ((met->zetal[i][j][k - 1] >= met->zetal[i][j][k])) {
8933 /* Find the upper level k+l over the inversion... */
8934 int l = 0;
8935 do {
8936 l++;
8937 }
8938 while ((met->zetal[i][j][k - 1] >=
8939 met->zetal[i][j][k + l]) & (k + l < met->npl));
8940
8941 /* Interpolate linear between the top and bottom
8942 of the inversion... */
8943 float s =
8944 (float) (met->zetal[i][j][k + l] - met->zetal[i][j][k - 1])
8945 / (float) (met->hybrid[k + l] - met->hybrid[k - 1]);
8946
8947 for (int m = k; m < k + l; m++) {
8948 float d = (float) (met->hybrid[m] - met->hybrid[k - 1]);
8949 met->zetal[i][j][m] = s * d + met->zetal[i][j][k - 1];
8950 }
8951
8952 /* Search for more inversions above the last inversion ... */
8953 k = k + l;
8954 } else {
8955 k++;
8956 }
8957 }
8958 }
8959
8960 /* Create monotone pressure profiles... */
8961#pragma omp parallel for default(shared) collapse(2)
8962 for (int i = 0; i < met->nx; i++)
8963 for (int j = 0; j < met->ny; j++) {
8964 int k = 1;
8965
8966 while (k < met->npl) { /* Check if there is an inversion at level k... */
8967 if ((met->pl[i][j][k - 1] <= met->pl[i][j][k])) {
8968
8969 /* Find the upper level k+l over the inversion... */
8970 int l = 0;
8971 do {
8972 l++;
8973 }
8974 while ((met->pl[i][j][k - 1] <= met->pl[i][j][k + l]) & (k + l <
8975 met->npl));
8976
8977 /* Interpolate linear between the top and bottom
8978 of the inversion... */
8979 float s = (float) (met->pl[i][j][k + l] - met->pl[i][j][k - 1])
8980 / (float) (met->hybrid[k + l] - met->hybrid[k - 1]);
8981
8982 for (int m = k; m < k + l; m++) {
8983 float d = (float) (met->hybrid[m] - met->hybrid[k - 1]);
8984 met->pl[i][j][m] = s * d + met->pl[i][j][k - 1];
8985 }
8986
8987 /* Search for more inversions above the last inversion ... */
8988 k += l;
8989 } else {
8990 k++;
8991 }
8992 }
8993 }
8994}
double hybrid[EP]
Model hybrid levels.
Definition: mptrac.h:3585

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

9001 {
9002
9003 int ncid;
9004
9005 /* Open netCDF file... */
9006 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
9007 WARN("Cannot open file!");
9008 return 0;
9009 }
9010
9011 /* Read coordinates of meteo data... */
9012 read_met_nc_grid(filename, ncid, ctl, met);
9013
9014 /* Read surface data... */
9015 read_met_nc_surface(ncid, ctl, met);
9016
9017 /* Read meteo data on vertical levels... */
9018 read_met_nc_levels(ncid, ctl, met);
9019
9020 /* Close file... */
9021 NC(nc_close(ncid));
9022
9023 /* Return success... */
9024 return 1;
9025}
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:9693
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:9345
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:9479
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.
Author
Lars Hoffmann
Jan Clemens

Definition at line 9479 of file mptrac.c.

9482 {
9483
9484 /* Set timer... */
9485 SELECT_TIMER("READ_MET_NC_LEVELS", "INPUT", NVTX_READ);
9486 LOG(2, "Read level data...");
9487
9488 /* Read temperature... */
9489 if (!read_met_nc_3d(ncid, "t", "T", "temp", "TEMP", ctl, met, met->t, 1.0))
9490 ERRMSG("Cannot read temperature!");
9491
9492 /* Read horizontal wind and vertical velocity... */
9493 if (!read_met_nc_3d(ncid, "u", "U", NULL, NULL, ctl, met, met->u, 1.0))
9494 ERRMSG("Cannot read zonal wind!");
9495 if (!read_met_nc_3d(ncid, "v", "V", NULL, NULL, ctl, met, met->v, 1.0))
9496 ERRMSG("Cannot read meridional wind!");
9497 if (!read_met_nc_3d
9498 (ncid, "w", "W", "omega", "OMEGA", ctl, met, met->w, 0.01f))
9499 WARN("Cannot read vertical velocity!");
9500
9501 /* Read water vapor... */
9502 if (!ctl->met_relhum) {
9503 if (!read_met_nc_3d
9504 (ncid, "q", "Q", "sh", "SH", ctl, met, met->h2o, (float) (MA / MH2O)))
9505 WARN("Cannot read specific humidity!");
9506 } else {
9507 if (!read_met_nc_3d
9508 (ncid, "rh", "RH", NULL, NULL, ctl, met, met->h2o, 0.01f))
9509 WARN("Cannot read relative humidity!");
9510#pragma omp parallel for default(shared) collapse(2)
9511 for (int ix = 0; ix < met->nx; ix++)
9512 for (int iy = 0; iy < met->ny; iy++)
9513 for (int ip = 0; ip < met->np; ip++) {
9514 double pw = met->h2o[ix][iy][ip] * PSAT(met->t[ix][iy][ip]);
9515 met->h2o[ix][iy][ip] =
9516 (float) (pw / (met->p[ip] - (1.0 - EPS) * pw));
9517 }
9518 }
9519
9520 /* Read ozone... */
9521 if (!read_met_nc_3d
9522 (ncid, "o3", "O3", NULL, NULL, ctl, met, met->o3, (float) (MA / MO3)))
9523 WARN("Cannot read ozone data!");
9524
9525 /* Read cloud data... */
9526 if (!read_met_nc_3d
9527 (ncid, "clwc", "CLWC", NULL, NULL, ctl, met, met->lwc, 1.0))
9528 WARN("Cannot read cloud liquid water content!");
9529 if (!read_met_nc_3d
9530 (ncid, "crwc", "CRWC", NULL, NULL, ctl, met, met->rwc, 1.0))
9531 WARN("Cannot read cloud rain water content!");
9532 if (!read_met_nc_3d
9533 (ncid, "ciwc", "CIWC", NULL, NULL, ctl, met, met->iwc, 1.0))
9534 WARN("Cannot read cloud ice water content!");
9535 if (!read_met_nc_3d
9536 (ncid, "cswc", "CSWC", NULL, NULL, ctl, met, met->swc, 1.0))
9537 WARN("Cannot read cloud snow water content!");
9538 if (!read_met_nc_3d(ncid, "cc", "CC", NULL, NULL, ctl, met, met->cc, 1.0))
9539 WARN("Cannot read cloud cover!");
9540
9541 /* Read zeta and zeta_dot... */
9542 if (!read_met_nc_3d
9543 (ncid, "ZETA", "zeta", NULL, NULL, ctl, met, met->zetal, 1.0))
9544 WARN("Cannot read ZETA!");
9545 if (!read_met_nc_3d
9546 (ncid, "ZETA_DOT_TOT", "ZETA_DOT_clr", "zeta_dot_clr",
9547 NULL, ctl, met, met->zeta_dotl, 0.00001157407f))
9548 WARN("Cannot read ZETA_DOT!");
9549
9550 /* Store velocities on model levels... */
9551 if (ctl->met_vert_coord != 0) {
9552 for (int ix = 0; ix < met->nx; ix++)
9553 for (int iy = 0; iy < met->ny; iy++)
9554 for (int ip = 0; ip < met->np; ip++) {
9555 met->ul[ix][iy][ip] = met->u[ix][iy][ip];
9556 met->vl[ix][iy][ip] = met->v[ix][iy][ip];
9557 met->wl[ix][iy][ip] = met->w[ix][iy][ip];
9558 }
9559
9560 /* Save number of model levels... */
9561 met->npl = met->np;
9562 }
9563
9564 /* Get pressure on model levels... */
9565 if (ctl->met_np > 0 || ctl->met_vert_coord != 0) {
9566
9567 /* Read 3-D pressure field... */
9568 if (ctl->met_vert_coord == 1) {
9569 if (!read_met_nc_3d
9570 (ncid, "pl", "PL", "pressure", "PRESSURE", ctl, met, met->pl,
9571 0.01f))
9572 if (!read_met_nc_3d
9573 (ncid, "press", "PRESS", NULL, NULL, ctl, met, met->pl, 1.0))
9574 ERRMSG("Cannot read pressure on model levels!");
9575 }
9576
9577 /* Use a and b coefficients for full levels... */
9578 else if (ctl->met_vert_coord == 2 || ctl->met_vert_coord == 3) {
9579
9580 /* Grid level coefficients... */
9581 double hyam[EP], hybm[EP];
9582
9583 /* Read coefficients from file... */
9584 if (ctl->met_vert_coord == 2) {
9585 int varid;
9586 if (nc_inq_varid(ncid, "hyam", &varid) == NC_NOERR
9587 && nc_inq_varid(ncid, "hybm", &varid) == NC_NOERR) {
9588 NC_GET_DOUBLE("hyam", hyam, 1);
9589 NC_GET_DOUBLE("hybm", hybm, 1);
9590 } else if (nc_inq_varid(ncid, "a_hybrid_level", &varid) == NC_NOERR
9591 && nc_inq_varid(ncid, "b_hybrid_level",
9592 &varid) == NC_NOERR) {
9593 NC_GET_DOUBLE("a_hybrid_level", hyam, 1);
9594 NC_GET_DOUBLE("b_hybrid_level", hybm, 1);
9595 } else
9596 ERRMSG("Cannot read a and b level coefficients from netCDF file!");
9597 }
9598
9599 /* Use control parameters... */
9600 else if (ctl->met_vert_coord == 3) {
9601
9602 /* Check number of levels... */
9603 if (met->np != ctl->met_nlev)
9604 ERRMSG("Mismatch in number of model levels!");
9605
9606 /* Copy parameters... */
9607 for (int ip = 0; ip < met->np; ip++) {
9608 hyam[ip] = ctl->met_lev_hyam[ip];
9609 hybm[ip] = ctl->met_lev_hybm[ip];
9610 }
9611 }
9612
9613 /* Calculate pressure... */
9614 for (int ix = 0; ix < met->nx; ix++)
9615 for (int iy = 0; iy < met->ny; iy++)
9616 for (int ip = 0; ip < met->np; ip++)
9617 met->pl[ix][iy][ip] =
9618 (float) (hyam[ip] / 100. + hybm[ip] * met->ps[ix][iy]);
9619 }
9620
9621 /* Use a and b coefficients for half levels... */
9622 else if (ctl->met_vert_coord == 4) {
9623
9624 /* Grid level coefficients... */
9625 double hyam[EP], hybm[EP];
9626
9627 /* Use control parameters... */
9628 for (int ip = 0; ip < met->np + 1; ip++) {
9629 hyam[ip] = ctl->met_lev_hyam[ip];
9630 hybm[ip] = ctl->met_lev_hybm[ip];
9631 }
9632
9633 /* Check number of levels... */
9634 if (met->np + 1 != ctl->met_nlev)
9635 ERRMSG("Mismatch in number of model levels!");
9636
9637 /* Calculate pressure... */
9638#pragma omp parallel for default(shared) collapse(2)
9639 for (int ix = 0; ix < met->nx; ix++)
9640 for (int iy = 0; iy < met->ny; iy++)
9641 for (int ip = 0; ip < met->np; ip++) {
9642 double p0 = hyam[ip] / 100. + hybm[ip] * met->ps[ix][iy];
9643 double p1 = hyam[ip + 1] / 100. + hybm[ip + 1] * met->ps[ix][iy];
9644 met->pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
9645 }
9646 }
9647
9648 /* Check ordering of pressure levels... */
9649 for (int ix = 0; ix < met->nx; ix++)
9650 for (int iy = 0; iy < met->ny; iy++)
9651 for (int ip = 1; ip < met->np; ip++)
9652 if ((met->pl[ix][iy][0] > met->pl[ix][iy][1]
9653 && met->pl[ix][iy][ip - 1] <= met->pl[ix][iy][ip])
9654 || (met->pl[ix][iy][0] < met->pl[ix][iy][1]
9655 && met->pl[ix][iy][ip - 1] >= met->pl[ix][iy][ip]))
9656 ERRMSG("Pressure profiles are not monotonic!");
9657 }
9658
9659 /* Interpolate from model levels to pressure levels... */
9660 if (ctl->met_np > 0) {
9661
9662 /* Check pressure on model levels... */
9663 if (met->pl[0][0][0] <= 0)
9664 ERRMSG("Pressure on model levels is missing, check MET_VERT_COORD!");
9665
9666 /* Interpolate variables... */
9667 read_met_ml2pl(ctl, met, met->t, "T");
9668 read_met_ml2pl(ctl, met, met->u, "U");
9669 read_met_ml2pl(ctl, met, met->v, "V");
9670 read_met_ml2pl(ctl, met, met->w, "W");
9671 read_met_ml2pl(ctl, met, met->h2o, "H2O");
9672 read_met_ml2pl(ctl, met, met->o3, "O3");
9673 read_met_ml2pl(ctl, met, met->lwc, "LWC");
9674 read_met_ml2pl(ctl, met, met->rwc, "RWC");
9675 read_met_ml2pl(ctl, met, met->iwc, "IWC");
9676 read_met_ml2pl(ctl, met, met->swc, "SWC");
9677 read_met_ml2pl(ctl, met, met->cc, "CC");
9678
9679 /* Set new pressure levels... */
9680 met->np = ctl->met_np;
9681 for (int ip = 0; ip < met->np; ip++)
9682 met->p[ip] = ctl->met_p[ip];
9683 }
9684
9685 /* Check ordering of pressure levels... */
9686 for (int ip = 1; ip < met->np; ip++)
9687 if (met->p[ip - 1] < met->p[ip])
9688 ERRMSG("Pressure levels must be descending!");
9689}
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:8871
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:9193
#define MH2O
Molar mass of water vapor [g/mol].
Definition: mptrac.h:238
#define MO3
Molar mass of ozone [g/mol].
Definition: mptrac.h:243
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).
Author
Lars Hoffmann
Jan Clemens

Definition at line 9693 of file mptrac.c.

9696 {
9697
9698 /* Set timer... */
9699 SELECT_TIMER("READ_MET_NC_SURFACE", "INPUT", NVTX_READ);
9700 LOG(2, "Read surface data...");
9701
9702 /* Read surface pressure... */
9703 if (read_met_nc_2d
9704 (ncid, "lnsp", "LNSP", NULL, NULL, NULL, NULL, ctl, met, met->ps,
9705 1.0f, 1)) {
9706 for (int ix = 0; ix < met->nx; ix++)
9707 for (int iy = 0; iy < met->ny; iy++)
9708 met->ps[ix][iy] = (float) (exp(met->ps[ix][iy]) / 100.);
9709 } else
9710 if (!read_met_nc_2d
9711 (ncid, "ps", "PS", "sp", "SP", NULL, NULL, ctl, met, met->ps, 0.01f,
9712 1)) {
9713 WARN("Cannot not read surface pressure data (use lowest level)!");
9714 for (int ix = 0; ix < met->nx; ix++)
9715 for (int iy = 0; iy < met->ny; iy++)
9716 met->ps[ix][iy]
9717 = (ctl->met_np > 0 ? (float) ctl->met_p[0] : (float) met->p[0]);
9718 }
9719
9720 /* MPTRAC meteo data... */
9721 if (ctl->met_clams == 0) {
9722
9723 /* Read geopotential height at the surface... */
9724 if (!read_met_nc_2d
9725 (ncid, "z", "Z", NULL, NULL, NULL, NULL, ctl, met, met->zs,
9726 (float) (1. / (1000. * G0)), 1))
9727 if (!read_met_nc_2d
9728 (ncid, "zm", "ZM", NULL, NULL, NULL, NULL, ctl, met, met->zs,
9729 (float) (1. / 1000.), 1))
9730 WARN("Cannot read surface geopotential height!");
9731 }
9732
9733 /* CLaMS meteo data... */
9734 else {
9735
9736 /* Read geopotential height at the surface
9737 (use lowermost level of 3-D data field)... */
9738 float *help;
9739 ALLOC(help, float,
9740 EX * EY * EP);
9741 memcpy(help, met->pl, sizeof(met->pl));
9742 if (!read_met_nc_3d
9743 (ncid, "gph", "GPH", NULL, NULL, ctl, met, met->pl,
9744 (float) (1e-3 / G0)))
9745 ERRMSG("Cannot read geopotential height!");
9746 for (int ix = 0; ix < met->nx; ix++)
9747 for (int iy = 0; iy < met->ny; iy++)
9748 met->zs[ix][iy] = met->pl[ix][iy][0];
9749 memcpy(met->pl, help, sizeof(met->pl));
9750 free(help);
9751 }
9752
9753 /* Read temperature at the surface... */
9754 if (!read_met_nc_2d
9755 (ncid, "t2m", "T2M", "2t", "2T", "t2", "T2", ctl, met, met->ts, 1.0, 1))
9756 WARN("Cannot read surface temperature!");
9757
9758 /* Read zonal wind at the surface... */
9759 if (!read_met_nc_2d
9760 (ncid, "u10m", "U10M", "10u", "10U", "u10", "U10", ctl, met, met->us,
9761 1.0, 1))
9762 WARN("Cannot read surface zonal wind!");
9763
9764 /* Read meridional wind at the surface... */
9765 if (!read_met_nc_2d
9766 (ncid, "v10m", "V10M", "10v", "10V", "v10", "V10", ctl, met, met->vs,
9767 1.0, 1))
9768 WARN("Cannot read surface meridional wind!");
9769
9770 /* Read eastward turbulent surface stress... */
9771 if (!read_met_nc_2d
9772 (ncid, "iews", "IEWS", NULL, NULL, NULL, NULL, ctl, met, met->ess,
9773 1.0, 1))
9774 WARN("Cannot read eastward turbulent surface stress!");
9775
9776 /* Read northward turbulent surface stress... */
9777 if (!read_met_nc_2d
9778 (ncid, "inss", "INSS", NULL, NULL, NULL, NULL, ctl, met, met->nss,
9779 1.0, 1))
9780 WARN("Cannot read nothward turbulent surface stress!");
9781
9782 /* Read surface sensible heat flux... */
9783 if (!read_met_nc_2d
9784 (ncid, "ishf", "ISHF", NULL, NULL, NULL, NULL, ctl, met, met->shf,
9785 1.0, 1))
9786 WARN("Cannot read surface sensible heat flux!");
9787
9788 /* Read land-sea mask... */
9789 if (!read_met_nc_2d
9790 (ncid, "lsm", "LSM", NULL, NULL, NULL, NULL, ctl, met, met->lsm, 1.0,
9791 1))
9792 WARN("Cannot read land-sea mask!");
9793
9794 /* Read sea surface temperature... */
9795 if (!read_met_nc_2d
9796 (ncid, "sstk", "SSTK", "sst", "SST", NULL, NULL, ctl, met, met->sst,
9797 1.0, 1))
9798 WARN("Cannot read sea surface temperature!");
9799
9800 /* Read PBL... */
9801 if (ctl->met_pbl == 0)
9802 if (!read_met_nc_2d
9803 (ncid, "blp", "BLP", NULL, NULL, NULL, NULL, ctl, met, met->pbl,
9804 0.01f, 1))
9805 WARN("Cannot read planetary boundary layer pressure!");
9806 if (ctl->met_pbl == 1)
9807 if (!read_met_nc_2d
9808 (ncid, "blh", "BLH", NULL, NULL, NULL, NULL, ctl, met, met->pbl,
9809 0.001f, 1))
9810 WARN("Cannot read planetary boundary layer height!");
9811
9812 /* Read CAPE... */
9813 if (ctl->met_cape == 0)
9814 if (!read_met_nc_2d
9815 (ncid, "cape", "CAPE", NULL, NULL, NULL, NULL, ctl, met, met->cape,
9816 1.0, 1))
9817 WARN("Cannot read CAPE!");
9818
9819 /* Read CIN... */
9820 if (ctl->met_cape == 0)
9821 if (!read_met_nc_2d
9822 (ncid, "cin", "CIN", NULL, NULL, NULL, NULL, ctl, met, met->cin,
9823 1.0, 1))
9824 WARN("Cannot read convective inhibition!");
9825}
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:9029
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.
Author
Lars Hoffmann
Jan Clemens

Definition at line 9345 of file mptrac.c.

9349 {
9350
9351 char levname[LEN], tstr[10];
9352
9353 double rtime = 0, r, r2;
9354
9355 int varid, ndims, dimids[NC_MAX_DIMS], year2, mon2, day2, hour2, min2, sec2,
9356 year, mon, day, hour, min, sec;
9357
9358 size_t dimlen;
9359
9360 /* Set timer... */
9361 SELECT_TIMER("READ_MET_NC_GRID", "INPUT", NVTX_READ);
9362 LOG(2, "Read meteo grid information...");
9363
9364 /* MPTRAC meteo files... */
9365 if (ctl->met_clams == 0) {
9366
9367 /* Get time from filename... */
9368 met->time = time_from_filename(filename, 16);
9369
9370 /* Check time information from data file... */
9371 jsec2time(met->time, &year, &mon, &day, &hour, &min, &sec, &r);
9372 if (nc_inq_varid(ncid, "time", &varid) == NC_NOERR) {
9373 NC(nc_get_var_double(ncid, varid, &rtime));
9374 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
9375 WARN("Time information in meteo file does not match filename!");
9376 } else
9377 WARN("Time information in meteo file is missing!");
9378 }
9379
9380 /* CLaMS meteo files... */
9381 else {
9382
9383 /* Read time from file... */
9384 NC_GET_DOUBLE("time", &rtime, 0);
9385
9386 /* Get time from filename (considering the century)... */
9387 if (rtime < 0)
9388 sprintf(tstr, "19%.2s", &filename[strlen(filename) - 11]);
9389 else
9390 sprintf(tstr, "20%.2s", &filename[strlen(filename) - 11]);
9391 year = atoi(tstr);
9392 sprintf(tstr, "%.2s", &filename[strlen(filename) - 9]);
9393 mon = atoi(tstr);
9394 sprintf(tstr, "%.2s", &filename[strlen(filename) - 7]);
9395 day = atoi(tstr);
9396 sprintf(tstr, "%.2s", &filename[strlen(filename) - 5]);
9397 hour = atoi(tstr);
9398 time2jsec(year, mon, day, hour, 0, 0, 0, &met->time);
9399 }
9400
9401 /* Check time... */
9402 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
9403 || day < 1 || day > 31 || hour < 0 || hour > 23)
9404 ERRMSG("Cannot read time from filename!");
9405 jsec2time(met->time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
9406 LOG(2, "Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
9407 met->time, year2, mon2, day2, hour2, min2);
9408
9409 /* Get grid dimensions... */
9410 NC_INQ_DIM("lon", &met->nx, 2, EX);
9411 LOG(2, "Number of longitudes: %d", met->nx);
9412
9413 NC_INQ_DIM("lat", &met->ny, 2, EY);
9414 LOG(2, "Number of latitudes: %d", met->ny);
9415
9416 /* Read longitudes and latitudes... */
9417 NC_GET_DOUBLE("lon", met->lon, 1);
9418 LOG(2, "Longitudes: %g, %g ... %g deg",
9419 met->lon[0], met->lon[1], met->lon[met->nx - 1]);
9420 NC_GET_DOUBLE("lat", met->lat, 1);
9421 LOG(2, "Latitudes: %g, %g ... %g deg",
9422 met->lat[0], met->lat[1], met->lat[met->ny - 1]);
9423
9424 /* Check grid spacing... */
9425 for (int ix = 2; ix < met->nx; ix++)
9426 if (fabs
9427 (fabs(met->lon[ix] - met->lon[ix - 1]) -
9428 fabs(met->lon[1] - met->lon[0])) > 0.001)
9429 ERRMSG("No regular grid spacing in longitudes!");
9430 for (int iy = 2; iy < met->ny; iy++)
9431 if (fabs
9432 (fabs(met->lat[iy] - met->lat[iy - 1]) -
9433 fabs(met->lat[1] - met->lat[0])) > 0.001) {
9434 WARN("No regular grid spacing in latitudes!");
9435 break;
9436 }
9437
9438 /* Get vertical dimension... */
9439 if (nc_inq_varid(ncid, "u", &varid) != NC_NOERR)
9440 if (nc_inq_varid(ncid, "U", &varid) != NC_NOERR)
9441 ERRMSG
9442 ("Variable 'u' or 'U' not found, cannot determine vertical dimension!");
9443
9444 NC(nc_inq_varndims(ncid, varid, &ndims));
9445 NC(nc_inq_vardimid(ncid, varid, dimids));
9446
9447 if (ndims == 4) {
9448 NC(nc_inq_dim
9449 (ncid, dimids[ctl->met_convention == 0 ? 1 : 3], levname, &dimlen));
9450 } else if (ndims == 3) {
9451 NC(nc_inq_dim
9452 (ncid, dimids[ctl->met_convention == 0 ? 0 : 2], levname, &dimlen));
9453 } else
9454 ERRMSG("Cannot determine vertical dimension!")
9455 met->np = (int) dimlen;
9456
9457 LOG(2, "Number of levels: %d", met->np);
9458 if (met->np < 2 || met->np > EP)
9459 ERRMSG("Number of levels out of range!");
9460
9461 /* Read pressure levels... */
9462 if (ctl->met_np <= 0) {
9463 NC_GET_DOUBLE(levname, met->p, 1);
9464 for (int ip = 0; ip < met->np; ip++)
9465 met->p[ip] /= 100.;
9466 LOG(2, "Altitude levels: %g, %g ... %g km",
9467 Z(met->p[0]), Z(met->p[1]), Z(met->p[met->np - 1]));
9468 LOG(2, "Pressure levels: %g, %g ... %g hPa",
9469 met->p[0], met->p[1], met->p[met->np - 1]);
9470 }
9471
9472 /* Read hybrid levels... */
9473 if (strcasecmp(levname, "hybrid") == 0)
9474 NC_GET_DOUBLE("hybrid", met->hybrid, 1);
9475}
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:10881
double time_from_filename(const char *filename, const int offset)
Extracts and converts a timestamp from a filename to Julian seconds.
Definition: mptrac.c:10980
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 9029 of file mptrac.c.

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

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

9202 {
9203
9204 char varsel[LEN];
9205
9206 float offset, scalfac;
9207
9208 int varid;
9209
9210 /* Check if variable exists... */
9211 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
9212 sprintf(varsel, "%s", varname);
9213 else if (varname2 != NULL
9214 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
9215 sprintf(varsel, "%s", varname2);
9216 else if (varname3 != NULL
9217 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
9218 sprintf(varsel, "%s", varname3);
9219 else if (varname4 != NULL
9220 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
9221 sprintf(varsel, "%s", varname4);
9222 else
9223 return 0;
9224
9225 /* Read packed data... */
9226 if (ctl->met_nc_scale
9227 && nc_get_att_float(ncid, varid, "add_offset", &offset) == NC_NOERR
9228 && nc_get_att_float(ncid, varid, "scale_factor",
9229 &scalfac) == NC_NOERR) {
9230
9231 /* Allocate... */
9232 short *help;
9233 ALLOC(help, short,
9234 EX * EY * EP);
9235
9236 /* Read fill value and missing value... */
9237 short fillval, missval;
9238 if (nc_get_att_short(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
9239 fillval = 0;
9240 if (nc_get_att_short(ncid, varid, "missing_value", &missval) != NC_NOERR)
9241 missval = 0;
9242
9243 /* Write info... */
9244 LOG(2, "Read 3-D variable: %s "
9245 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
9246 varsel, fillval, missval, scalfac, offset);
9247
9248 /* Read data... */
9249 NC(nc_get_var_short(ncid, varid, help));
9250
9251 /* Check meteo data layout... */
9252 if (ctl->met_convention != 0)
9253 ERRMSG("Meteo data layout not implemented for packed netCDF files!");
9254
9255 /* Copy and check data... */
9256 omp_set_dynamic(1);
9257#pragma omp parallel for default(shared)
9258 for (int ix = 0; ix < met->nx; ix++)
9259 for (int iy = 0; iy < met->ny; iy++)
9260 for (int ip = 0; ip < met->np; ip++) {
9261 const short aux = help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)];
9262 if ((fillval == 0 || aux != fillval)
9263 && (missval == 0 || aux != missval)
9264 && fabsf(aux * scalfac + offset) < 1e14f)
9265 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
9266 else
9267 dest[ix][iy][ip] = NAN;
9268 }
9269 omp_set_dynamic(0);
9270
9271 /* Free... */
9272 free(help);
9273 }
9274
9275 /* Unpacked data... */
9276 else {
9277
9278 /* Allocate... */
9279 float *help;
9280 ALLOC(help, float,
9281 EX * EY * EP);
9282
9283 /* Read fill value and missing value... */
9284 float fillval, missval;
9285 if (nc_get_att_float(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
9286 fillval = 0;
9287 if (nc_get_att_float(ncid, varid, "missing_value", &missval) != NC_NOERR)
9288 missval = 0;
9289
9290 /* Write info... */
9291 LOG(2, "Read 3-D variable: %s (FILL = %g, MISS = %g)",
9292 varsel, fillval, missval);
9293
9294 /* Read data... */
9295 NC(nc_get_var_float(ncid, varid, help));
9296
9297 /* Check meteo data layout... */
9298 if (ctl->met_convention == 0) {
9299
9300 /* Copy and check data (ordering: lev, lat, lon)... */
9301 omp_set_dynamic(1);
9302#pragma omp parallel for default(shared)
9303 for (int ix = 0; ix < met->nx; ix++)
9304 for (int iy = 0; iy < met->ny; iy++)
9305 for (int ip = 0; ip < met->np; ip++) {
9306 const float aux = help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)];
9307 if ((fillval == 0 || aux != fillval)
9308 && (missval == 0 || aux != missval)
9309 && fabsf(aux) < 1e14f)
9310 dest[ix][iy][ip] = scl * aux;
9311 else
9312 dest[ix][iy][ip] = NAN;
9313 }
9314 omp_set_dynamic(0);
9315
9316 } else {
9317
9318 /* Copy and check data (ordering: lon, lat, lev)... */
9319 omp_set_dynamic(1);
9320#pragma omp parallel for default(shared)
9321 for (int ip = 0; ip < met->np; ip++)
9322 for (int iy = 0; iy < met->ny; iy++)
9323 for (int ix = 0; ix < met->nx; ix++) {
9324 const float aux = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
9325 if ((fillval == 0 || aux != fillval)
9326 && (missval == 0 || aux != missval)
9327 && fabsf(aux) < 1e14f)
9328 dest[ix][iy][ip] = scl * aux;
9329 else
9330 dest[ix][iy][ip] = NAN;
9331 }
9332 omp_set_dynamic(0);
9333 }
9334
9335 /* Free... */
9336 free(help);
9337 }
9338
9339 /* Return... */
9340 return 1;
9341}

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

9831 {
9832
9833 /* Set timer... */
9834 SELECT_TIMER("READ_MET_PBL", "METPROC", NVTX_READ);
9835 LOG(2, "Calculate planetary boundary layer...");
9836
9837 /* Convert PBL height from meteo file to pressure... */
9838 if (ctl->met_pbl == 1) {
9839
9840 /* Loop over grid points... */
9841#pragma omp parallel for default(shared) collapse(2)
9842 for (int ix = 0; ix < met->nx; ix++)
9843 for (int iy = 0; iy < met->ny; iy++) {
9844
9845 /* Get pressure at top of PBL... */
9846 const float z = met->zs[ix][iy] + met->pbl[ix][iy];
9847 const int ip = locate_irr_float(met->z[ix][iy], met->np, z, 0);
9848 met->pbl[ix][iy] =
9849 (float) (LIN(met->z[ix][iy][ip], met->p[ip],
9850 met->z[ix][iy][ip + 1], met->p[ip + 1], z));
9851 }
9852 }
9853
9854 /* Determine PBL based on Richardson number... */
9855 else if (ctl->met_pbl == 2) {
9856
9857 /* Parameters used to estimate the height of the PBL
9858 (e.g., Vogelezang and Holtslag, 1996; Seidel et al., 2012)... */
9859 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
9860
9861 /* Loop over grid points... */
9862#pragma omp parallel for default(shared) collapse(2)
9863 for (int ix = 0; ix < met->nx; ix++)
9864 for (int iy = 0; iy < met->ny; iy++) {
9865
9866 /* Set bottom level of PBL... */
9867 const double pbl_bot = met->ps[ix][iy] * exp(-dz / H0);
9868
9869 /* Find lowest level near the bottom... */
9870 int ip;
9871 for (ip = 1; ip < met->np; ip++)
9872 if (met->p[ip] < pbl_bot)
9873 break;
9874
9875 /* Get near surface data... */
9876 const double h2os = LIN(met->p[ip - 1], met->h2o[ix][iy][ip - 1],
9877 met->p[ip], met->h2o[ix][iy][ip], pbl_bot);
9878 const double tvs = THETAVIRT(pbl_bot, met->ts[ix][iy], h2os);
9879
9880 /* Init... */
9881 double rib_old = 0;
9882
9883 /* Loop over levels... */
9884 for (; ip < met->np; ip++) {
9885
9886 /* Get squared horizontal wind speed... */
9887 double vh2 = SQR(met->u[ix][iy][ip] - met->us[ix][iy])
9888 + SQR(met->v[ix][iy][ip] - met->vs[ix][iy]);
9889 vh2 = MAX(vh2, SQR(umin));
9890
9891 /* Calculate bulk Richardson number... */
9892 const double rib =
9893 G0 * 1e3 * (met->z[ix][iy][ip] - met->zs[ix][iy]) / tvs
9894 * (THETAVIRT(met->p[ip], met->t[ix][iy][ip],
9895 met->h2o[ix][iy][ip]) - tvs) / vh2;
9896
9897 /* Check for critical value... */
9898 if (rib >= rib_crit) {
9899 met->pbl[ix][iy] = (float) (LIN(rib_old, met->p[ip - 1],
9900 rib, met->p[ip], rib_crit));
9901 if (met->pbl[ix][iy] > pbl_bot)
9902 met->pbl[ix][iy] = (float) pbl_bot;
9903 break;
9904 }
9905
9906 /* Save Richardson number... */
9907 rib_old = rib;
9908 }
9909 }
9910 }
9911
9912 /* Determine PBL based on potential temperature... */
9913 if (ctl->met_pbl == 3) {
9914
9915 /* Parameters used to estimate the height of the PBL
9916 (following HYSPLIT model)... */
9917 const double dtheta = 2.0, zmin = 0.1;
9918
9919 /* Loop over grid points... */
9920#pragma omp parallel for default(shared) collapse(2)
9921 for (int ix = 0; ix < met->nx; ix++)
9922 for (int iy = 0; iy < met->ny; iy++) {
9923
9924 /* Potential temperature at the surface... */
9925 const double theta0 = THETA(met->ps[ix][iy], met->ts[ix][iy]);
9926
9927 /* Find topmost level where theta exceeds surface value by 2 K... */
9928 int ip;
9929 for (ip = met->np - 2; ip > 0; ip--)
9930 if (met->p[ip] >= 300.)
9931 if (met->p[ip] > met->ps[ix][iy]
9932 || THETA(met->p[ip], met->t[ix][iy][ip]) <= theta0 + dtheta)
9933 break;
9934
9935 /* Interpolate... */
9936 met->pbl[ix][iy]
9937 = (float) (LIN(THETA(met->p[ip + 1], met->t[ix][iy][ip + 1]),
9938 met->p[ip + 1],
9939 THETA(met->p[ip], met->t[ix][iy][ip]),
9940 met->p[ip], theta0 + dtheta));
9941
9942 /* Check minimum value... */
9943 double pbl_min = met->ps[ix][iy] * exp(-zmin / H0);
9944 if (met->pbl[ix][iy] > pbl_min || met->p[ip] > met->ps[ix][iy])
9945 met->pbl[ix][iy] = (float) pbl_min;
9946 }
9947 }
9948
9949 /* Loop over grid points... */
9950#pragma omp parallel for default(shared) collapse(2)
9951 for (int ix = 0; ix < met->nx; ix++)
9952 for (int iy = 0; iy < met->ny; iy++) {
9953
9954 /* Check minimum value... */
9955 double pbl_min = met->ps[ix][iy] * exp(-ctl->met_pbl_min / H0);
9956 met->pbl[ix][iy] = MIN(met->pbl[ix][iy], (float) pbl_min);
9957
9958 /* Check maximum value... */
9959 double pbl_max = met->ps[ix][iy] * exp(-ctl->met_pbl_max / H0);
9960 met->pbl[ix][iy] = MAX(met->pbl[ix][iy], (float) pbl_max);
9961 }
9962}
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 9966 of file mptrac.c.

9967 {
9968
9969 /* Set timer... */
9970 SELECT_TIMER("READ_MET_PERIODIC", "METPROC", NVTX_READ);
9971 LOG(2, "Apply periodic boundary conditions...");
9972
9973 /* Check longitudes... */
9974 if (!(fabs(met->lon[met->nx - 1] - met->lon[0]
9975 + met->lon[1] - met->lon[0] - 360) < 0.01))
9976 return;
9977
9978 /* Increase longitude counter... */
9979 if ((++met->nx) >= EX)
9980 ERRMSG("Cannot create periodic boundary conditions!");
9981
9982 /* Set longitude... */
9983 met->lon[met->nx - 1] = met->lon[met->nx - 2] + met->lon[1] - met->lon[0];
9984
9985 /* Loop over latitudes and pressure levels... */
9986#pragma omp parallel for default(shared)
9987 for (int iy = 0; iy < met->ny; iy++) {
9988 met->ps[met->nx - 1][iy] = met->ps[0][iy];
9989 met->zs[met->nx - 1][iy] = met->zs[0][iy];
9990 met->ts[met->nx - 1][iy] = met->ts[0][iy];
9991 met->us[met->nx - 1][iy] = met->us[0][iy];
9992 met->vs[met->nx - 1][iy] = met->vs[0][iy];
9993 met->ess[met->nx - 1][iy] = met->ess[0][iy];
9994 met->nss[met->nx - 1][iy] = met->nss[0][iy];
9995 met->shf[met->nx - 1][iy] = met->shf[0][iy];
9996 met->lsm[met->nx - 1][iy] = met->lsm[0][iy];
9997 met->sst[met->nx - 1][iy] = met->sst[0][iy];
9998 met->pbl[met->nx - 1][iy] = met->pbl[0][iy];
9999 met->cape[met->nx - 1][iy] = met->cape[0][iy];
10000 met->cin[met->nx - 1][iy] = met->cin[0][iy];
10001 for (int ip = 0; ip < met->np; ip++) {
10002 met->t[met->nx - 1][iy][ip] = met->t[0][iy][ip];
10003 met->u[met->nx - 1][iy][ip] = met->u[0][iy][ip];
10004 met->v[met->nx - 1][iy][ip] = met->v[0][iy][ip];
10005 met->w[met->nx - 1][iy][ip] = met->w[0][iy][ip];
10006 met->h2o[met->nx - 1][iy][ip] = met->h2o[0][iy][ip];
10007 met->o3[met->nx - 1][iy][ip] = met->o3[0][iy][ip];
10008 met->lwc[met->nx - 1][iy][ip] = met->lwc[0][iy][ip];
10009 met->rwc[met->nx - 1][iy][ip] = met->rwc[0][iy][ip];
10010 met->iwc[met->nx - 1][iy][ip] = met->iwc[0][iy][ip];
10011 met->swc[met->nx - 1][iy][ip] = met->swc[0][iy][ip];
10012 met->cc[met->nx - 1][iy][ip] = met->cc[0][iy][ip];
10013 }
10014 for (int ip = 0; ip < met->npl; ip++) {
10015 met->ul[met->nx - 1][iy][ip] = met->ul[0][iy][ip];
10016 met->vl[met->nx - 1][iy][ip] = met->vl[0][iy][ip];
10017 met->wl[met->nx - 1][iy][ip] = met->wl[0][iy][ip];
10018 met->pl[met->nx - 1][iy][ip] = met->pl[0][iy][ip];
10019 met->zetal[met->nx - 1][iy][ip] = met->zetal[0][iy][ip];
10020 met->zeta_dotl[met->nx - 1][iy][ip] = met->zeta_dotl[0][iy][ip];
10021 }
10022 }
10023}

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

10028 {
10029
10030 /* Set timer... */
10031 SELECT_TIMER("READ_MET_POLAR_WINDS", "METPROC", NVTX_READ);
10032 LOG(2, "Apply fix for polar winds...");
10033
10034 /* Check latitudes... */
10035 if (fabs(met->lat[0]) < 89.999 || fabs(met->lat[met->ny - 1]) < 89.999)
10036 return;
10037
10038 /* Loop over hemispheres... */
10039 for (int ihem = 0; ihem < 2; ihem++) {
10040
10041 /* Set latitude indices... */
10042 int i89 = 1, i90 = 0, sign = 1;
10043 if (ihem == 1) {
10044 i89 = met->ny - 2;
10045 i90 = met->ny - 1;
10046 }
10047 if (met->lat[i90] < 0)
10048 sign = -1;
10049
10050 /* Look-up table of cosinus and sinus... */
10051 double clon[EX], slon[EX];
10052#pragma omp parallel for default(shared)
10053 for (int ix = 0; ix < met->nx; ix++) {
10054 clon[ix] = cos(sign * DEG2RAD(met->lon[ix]));
10055 slon[ix] = sin(sign * DEG2RAD(met->lon[ix]));
10056 }
10057
10058 /* Loop over levels... */
10059#pragma omp parallel for default(shared)
10060 for (int ip = 0; ip < met->np; ip++) {
10061
10062 /* Transform 89 degree u and v winds into Cartesian coordinates and take the mean... */
10063 double vel89x = 0, vel89y = 0;
10064 for (int ix = 0; ix < met->nx; ix++) {
10065 vel89x +=
10066 (met->u[ix][i89][ip] * clon[ix] -
10067 met->v[ix][i89][ip] * slon[ix]) / met->nx;
10068 vel89y +=
10069 (met->u[ix][i89][ip] * slon[ix] +
10070 met->v[ix][i89][ip] * clon[ix]) / met->nx;
10071 }
10072
10073 /* Replace 90 degree winds by 89 degree mean... */
10074 for (int ix = 0; ix < met->nx; ix++) {
10075 met->u[ix][i90][ip]
10076 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
10077 met->v[ix][i90][ip]
10078 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
10079 }
10080 }
10081 }
10082}

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

10087 {
10088
10089 double pows[EP];
10090
10091 /* Set timer... */
10092 SELECT_TIMER("READ_MET_PV", "METPROC", NVTX_READ);
10093 LOG(2, "Calculate potential vorticity...");
10094
10095 /* Set powers... */
10096#pragma omp parallel for default(shared)
10097 for (int ip = 0; ip < met->np; ip++)
10098 pows[ip] = pow(1000. / met->p[ip], 0.286);
10099
10100 /* Loop over grid points... */
10101#pragma omp parallel for default(shared)
10102 for (int ix = 0; ix < met->nx; ix++) {
10103
10104 /* Set indices... */
10105 const int ix0 = MAX(ix - 1, 0);
10106 const int ix1 = MIN(ix + 1, met->nx - 1);
10107
10108 /* Loop over grid points... */
10109 for (int iy = 0; iy < met->ny; iy++) {
10110
10111 /* Set indices... */
10112 const int iy0 = MAX(iy - 1, 0);
10113 const int iy1 = MIN(iy + 1, met->ny - 1);
10114
10115 /* Set auxiliary variables... */
10116 const double latr = 0.5 * (met->lat[iy1] + met->lat[iy0]);
10117 const double dx = 1000. * DEG2DX(met->lon[ix1] - met->lon[ix0], latr);
10118 const double dy = 1000. * DEG2DY(met->lat[iy1] - met->lat[iy0]);
10119 const double c0 = cos(DEG2RAD(met->lat[iy0]));
10120 const double c1 = cos(DEG2RAD(met->lat[iy1]));
10121 const double cr = cos(DEG2RAD(latr));
10122 const double vort = 2 * 7.2921e-5 * sin(DEG2RAD(latr));
10123
10124 /* Loop over grid points... */
10125 for (int ip = 0; ip < met->np; ip++) {
10126
10127 /* Get gradients in longitude... */
10128 const double dtdx
10129 = (met->t[ix1][iy][ip] - met->t[ix0][iy][ip]) * pows[ip] / dx;
10130 const double dvdx = (met->v[ix1][iy][ip] - met->v[ix0][iy][ip]) / dx;
10131
10132 /* Get gradients in latitude... */
10133 const double dtdy
10134 = (met->t[ix][iy1][ip] - met->t[ix][iy0][ip]) * pows[ip] / dy;
10135 const double dudy
10136 = (met->u[ix][iy1][ip] * c1 - met->u[ix][iy0][ip] * c0) / dy;
10137
10138 /* Set indices... */
10139 const int ip0 = MAX(ip - 1, 0);
10140 const int ip1 = MIN(ip + 1, met->np - 1);
10141
10142 /* Get gradients in pressure... */
10143 double dtdp, dudp, dvdp;
10144 const double dp0 = 100. * (met->p[ip] - met->p[ip0]);
10145 const double dp1 = 100. * (met->p[ip1] - met->p[ip]);
10146 if (ip != ip0 && ip != ip1) {
10147 double denom = dp0 * dp1 * (dp0 + dp1);
10148 dtdp = (dp0 * dp0 * met->t[ix][iy][ip1] * pows[ip1]
10149 - dp1 * dp1 * met->t[ix][iy][ip0] * pows[ip0]
10150 + (dp1 * dp1 - dp0 * dp0) * met->t[ix][iy][ip] * pows[ip])
10151 / denom;
10152 dudp = (dp0 * dp0 * met->u[ix][iy][ip1]
10153 - dp1 * dp1 * met->u[ix][iy][ip0]
10154 + (dp1 * dp1 - dp0 * dp0) * met->u[ix][iy][ip])
10155 / denom;
10156 dvdp = (dp0 * dp0 * met->v[ix][iy][ip1]
10157 - dp1 * dp1 * met->v[ix][iy][ip0]
10158 + (dp1 * dp1 - dp0 * dp0) * met->v[ix][iy][ip])
10159 / denom;
10160 } else {
10161 const double denom = dp0 + dp1;
10162 dtdp =
10163 (met->t[ix][iy][ip1] * pows[ip1] -
10164 met->t[ix][iy][ip0] * pows[ip0]) / denom;
10165 dudp = (met->u[ix][iy][ip1] - met->u[ix][iy][ip0]) / denom;
10166 dvdp = (met->v[ix][iy][ip1] - met->v[ix][iy][ip0]) / denom;
10167 }
10168
10169 /* Calculate PV... */
10170 met->pv[ix][iy][ip] = (float)
10171 (1e6 * G0 *
10172 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
10173 }
10174 }
10175 }
10176
10177 /* Fix for polar regions... */
10178#pragma omp parallel for default(shared)
10179 for (int ix = 0; ix < met->nx; ix++)
10180 for (int ip = 0; ip < met->np; ip++) {
10181 met->pv[ix][0][ip]
10182 = met->pv[ix][1][ip]
10183 = met->pv[ix][2][ip];
10184 met->pv[ix][met->ny - 1][ip]
10185 = met->pv[ix][met->ny - 2][ip]
10186 = met->pv[ix][met->ny - 3][ip];
10187 }
10188}
#define DEG2DY(dlat)
Convert a latitude difference to a distance in the y-direction (north-south).
Definition: mptrac.h:538
#define DEG2DX(dlon, lat)
Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude.
Definition: mptrac.h:517

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

10193 {
10194
10195 /* Set timer... */
10196 SELECT_TIMER("READ_MET_OZONE", "METPROC", NVTX_READ);
10197 LOG(2, "Calculate total column ozone...");
10198
10199 /* Loop over columns... */
10200#pragma omp parallel for default(shared) collapse(2)
10201 for (int ix = 0; ix < met->nx; ix++)
10202 for (int iy = 0; iy < met->ny; iy++) {
10203
10204 /* Integrate... */
10205 double cd = 0;
10206 for (int ip = 1; ip < met->np; ip++)
10207 if (met->p[ip - 1] <= met->ps[ix][iy]) {
10208 const double vmr =
10209 0.5 * (met->o3[ix][iy][ip - 1] + met->o3[ix][iy][ip]);
10210 const double dp = met->p[ip - 1] - met->p[ip];
10211 cd += vmr * MO3 / MA * dp * 1e2 / G0;
10212 }
10213
10214 /* Convert to Dobson units... */
10215 met->o3c[ix][iy] = (float) (cd / 2.1415e-5);
10216 }
10217}

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

10223 {
10224
10225 met_t *help;
10226
10227 /* Check parameters... */
10228 if (ctl->met_dp <= 1 && ctl->met_dx <= 1 && ctl->met_dy <= 1
10229 && ctl->met_sp <= 1 && ctl->met_sx <= 1 && ctl->met_sy <= 1)
10230 return;
10231
10232 /* Set timer... */
10233 SELECT_TIMER("READ_MET_SAMPLE", "METPROC", NVTX_READ);
10234 LOG(2, "Downsampling of meteo data...");
10235
10236 /* Allocate... */
10237 ALLOC(help, met_t, 1);
10238
10239 /* Copy data... */
10240 help->nx = met->nx;
10241 help->ny = met->ny;
10242 help->np = met->np;
10243 memcpy(help->lon, met->lon, sizeof(met->lon));
10244 memcpy(help->lat, met->lat, sizeof(met->lat));
10245 memcpy(help->p, met->p, sizeof(met->p));
10246
10247 /* Smoothing... */
10248 for (int ix = 0; ix < met->nx; ix += ctl->met_dx) {
10249 for (int iy = 0; iy < met->ny; iy += ctl->met_dy) {
10250 for (int ip = 0; ip < met->np; ip += ctl->met_dp) {
10251 help->ps[ix][iy] = 0;
10252 help->zs[ix][iy] = 0;
10253 help->ts[ix][iy] = 0;
10254 help->us[ix][iy] = 0;
10255 help->vs[ix][iy] = 0;
10256 help->ess[ix][iy] = 0;
10257 help->nss[ix][iy] = 0;
10258 help->shf[ix][iy] = 0;
10259 help->lsm[ix][iy] = 0;
10260 help->sst[ix][iy] = 0;
10261 help->pbl[ix][iy] = 0;
10262 help->cape[ix][iy] = 0;
10263 help->cin[ix][iy] = 0;
10264 help->t[ix][iy][ip] = 0;
10265 help->u[ix][iy][ip] = 0;
10266 help->v[ix][iy][ip] = 0;
10267 help->w[ix][iy][ip] = 0;
10268 help->h2o[ix][iy][ip] = 0;
10269 help->o3[ix][iy][ip] = 0;
10270 help->lwc[ix][iy][ip] = 0;
10271 help->rwc[ix][iy][ip] = 0;
10272 help->iwc[ix][iy][ip] = 0;
10273 help->swc[ix][iy][ip] = 0;
10274 help->cc[ix][iy][ip] = 0;
10275 float wsum = 0;
10276 for (int ix2 = ix - ctl->met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
10277 ix2++) {
10278 int ix3 = ix2;
10279 if (ix3 < 0)
10280 ix3 += met->nx;
10281 else if (ix3 >= met->nx)
10282 ix3 -= met->nx;
10283
10284 for (int iy2 = MAX(iy - ctl->met_sy + 1, 0);
10285 iy2 <= MIN(iy + ctl->met_sy - 1, met->ny - 1); iy2++)
10286 for (int ip2 = MAX(ip - ctl->met_sp + 1, 0);
10287 ip2 <= MIN(ip + ctl->met_sp - 1, met->np - 1); ip2++) {
10288 const float w =
10289 (1.0f - (float) abs(ix - ix2) / (float) ctl->met_sx)
10290 * (1.0f - (float) abs(iy - iy2) / (float) ctl->met_sy)
10291 * (1.0f - (float) abs(ip - ip2) / (float) ctl->met_sp);
10292 help->ps[ix][iy] += w * met->ps[ix3][iy2];
10293 help->zs[ix][iy] += w * met->zs[ix3][iy2];
10294 help->ts[ix][iy] += w * met->ts[ix3][iy2];
10295 help->us[ix][iy] += w * met->us[ix3][iy2];
10296 help->vs[ix][iy] += w * met->vs[ix3][iy2];
10297 help->ess[ix][iy] += w * met->ess[ix3][iy2];
10298 help->nss[ix][iy] += w * met->nss[ix3][iy2];
10299 help->shf[ix][iy] += w * met->shf[ix3][iy2];
10300 help->lsm[ix][iy] += w * met->lsm[ix3][iy2];
10301 help->sst[ix][iy] += w * met->sst[ix3][iy2];
10302 help->pbl[ix][iy] += w * met->pbl[ix3][iy2];
10303 help->cape[ix][iy] += w * met->cape[ix3][iy2];
10304 help->cin[ix][iy] += w * met->cin[ix3][iy2];
10305 help->t[ix][iy][ip] += w * met->t[ix3][iy2][ip2];
10306 help->u[ix][iy][ip] += w * met->u[ix3][iy2][ip2];
10307 help->v[ix][iy][ip] += w * met->v[ix3][iy2][ip2];
10308 help->w[ix][iy][ip] += w * met->w[ix3][iy2][ip2];
10309 help->h2o[ix][iy][ip] += w * met->h2o[ix3][iy2][ip2];
10310 help->o3[ix][iy][ip] += w * met->o3[ix3][iy2][ip2];
10311 help->lwc[ix][iy][ip] += w * met->lwc[ix3][iy2][ip2];
10312 help->rwc[ix][iy][ip] += w * met->rwc[ix3][iy2][ip2];
10313 help->iwc[ix][iy][ip] += w * met->iwc[ix3][iy2][ip2];
10314 help->swc[ix][iy][ip] += w * met->swc[ix3][iy2][ip2];
10315 help->cc[ix][iy][ip] += w * met->cc[ix3][iy2][ip2];
10316 wsum += w;
10317 }
10318 }
10319 help->ps[ix][iy] /= wsum;
10320 help->zs[ix][iy] /= wsum;
10321 help->ts[ix][iy] /= wsum;
10322 help->us[ix][iy] /= wsum;
10323 help->vs[ix][iy] /= wsum;
10324 help->ess[ix][iy] /= wsum;
10325 help->nss[ix][iy] /= wsum;
10326 help->shf[ix][iy] /= wsum;
10327 help->lsm[ix][iy] /= wsum;
10328 help->sst[ix][iy] /= wsum;
10329 help->pbl[ix][iy] /= wsum;
10330 help->cape[ix][iy] /= wsum;
10331 help->cin[ix][iy] /= wsum;
10332 help->t[ix][iy][ip] /= wsum;
10333 help->u[ix][iy][ip] /= wsum;
10334 help->v[ix][iy][ip] /= wsum;
10335 help->w[ix][iy][ip] /= wsum;
10336 help->h2o[ix][iy][ip] /= wsum;
10337 help->o3[ix][iy][ip] /= wsum;
10338 help->lwc[ix][iy][ip] /= wsum;
10339 help->rwc[ix][iy][ip] /= wsum;
10340 help->iwc[ix][iy][ip] /= wsum;
10341 help->swc[ix][iy][ip] /= wsum;
10342 help->cc[ix][iy][ip] /= wsum;
10343 }
10344 }
10345 }
10346
10347 /* Downsampling... */
10348 met->nx = 0;
10349 for (int ix = 0; ix < help->nx; ix += ctl->met_dx) {
10350 met->lon[met->nx] = help->lon[ix];
10351 met->ny = 0;
10352 for (int iy = 0; iy < help->ny; iy += ctl->met_dy) {
10353 met->lat[met->ny] = help->lat[iy];
10354 met->ps[met->nx][met->ny] = help->ps[ix][iy];
10355 met->zs[met->nx][met->ny] = help->zs[ix][iy];
10356 met->ts[met->nx][met->ny] = help->ts[ix][iy];
10357 met->us[met->nx][met->ny] = help->us[ix][iy];
10358 met->vs[met->nx][met->ny] = help->vs[ix][iy];
10359 met->ess[met->nx][met->ny] = help->ess[ix][iy];
10360 met->nss[met->nx][met->ny] = help->nss[ix][iy];
10361 met->shf[met->nx][met->ny] = help->shf[ix][iy];
10362 met->lsm[met->nx][met->ny] = help->lsm[ix][iy];
10363 met->sst[met->nx][met->ny] = help->sst[ix][iy];
10364 met->pbl[met->nx][met->ny] = help->pbl[ix][iy];
10365 met->cape[met->nx][met->ny] = help->cape[ix][iy];
10366 met->cin[met->nx][met->ny] = help->cin[ix][iy];
10367 met->np = 0;
10368 for (int ip = 0; ip < help->np; ip += ctl->met_dp) {
10369 met->p[met->np] = help->p[ip];
10370 met->t[met->nx][met->ny][met->np] = help->t[ix][iy][ip];
10371 met->u[met->nx][met->ny][met->np] = help->u[ix][iy][ip];
10372 met->v[met->nx][met->ny][met->np] = help->v[ix][iy][ip];
10373 met->w[met->nx][met->ny][met->np] = help->w[ix][iy][ip];
10374 met->h2o[met->nx][met->ny][met->np] = help->h2o[ix][iy][ip];
10375 met->o3[met->nx][met->ny][met->np] = help->o3[ix][iy][ip];
10376 met->lwc[met->nx][met->ny][met->np] = help->lwc[ix][iy][ip];
10377 met->rwc[met->nx][met->ny][met->np] = help->rwc[ix][iy][ip];
10378 met->iwc[met->nx][met->ny][met->np] = help->iwc[ix][iy][ip];
10379 met->swc[met->nx][met->ny][met->np] = help->swc[ix][iy][ip];
10380 met->cc[met->nx][met->ny][met->np] = help->cc[ix][iy][ip];
10381 met->np++;
10382 }
10383 met->ny++;
10384 }
10385 met->nx++;
10386 }
10387
10388 /* Free... */
10389 free(help);
10390}

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

10397 {
10398
10399 double p2[200], pv[EP], pv2[200], t[EP], t2[200], th[EP],
10400 th2[200], z[EP], z2[200];
10401
10402 /* Set timer... */
10403 SELECT_TIMER("READ_MET_TROPO", "METPROC", NVTX_READ);
10404 LOG(2, "Calculate tropopause...");
10405
10406 /* Get altitude and pressure profiles... */
10407#pragma omp parallel for default(shared)
10408 for (int iz = 0; iz < met->np; iz++)
10409 z[iz] = Z(met->p[iz]);
10410#pragma omp parallel for default(shared)
10411 for (int iz = 0; iz <= 190; iz++) {
10412 z2[iz] = 4.5 + 0.1 * iz;
10413 p2[iz] = P(z2[iz]);
10414 }
10415
10416 /* Do not calculate tropopause... */
10417 if (ctl->met_tropo == 0)
10418#pragma omp parallel for default(shared) collapse(2)
10419 for (int ix = 0; ix < met->nx; ix++)
10420 for (int iy = 0; iy < met->ny; iy++)
10421 met->pt[ix][iy] = NAN;
10422
10423 /* Use tropopause climatology... */
10424 else if (ctl->met_tropo == 1) {
10425#pragma omp parallel for default(shared) collapse(2)
10426 for (int ix = 0; ix < met->nx; ix++)
10427 for (int iy = 0; iy < met->ny; iy++)
10428 met->pt[ix][iy] = (float) clim_tropo(clim, met->time, met->lat[iy]);
10429 }
10430
10431 /* Use cold point... */
10432 else if (ctl->met_tropo == 2) {
10433
10434 /* Loop over grid points... */
10435#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10436 for (int ix = 0; ix < met->nx; ix++)
10437 for (int iy = 0; iy < met->ny; iy++) {
10438
10439 /* Interpolate temperature profile... */
10440 for (int iz = 0; iz < met->np; iz++)
10441 t[iz] = met->t[ix][iy][iz];
10442 spline(z, t, met->np, z2, t2, 171, ctl->met_tropo_spline);
10443
10444 /* Find minimum... */
10445 int iz = (int) gsl_stats_min_index(t2, 1, 171);
10446 if (iz > 0 && iz < 170)
10447 met->pt[ix][iy] = (float) p2[iz];
10448 else
10449 met->pt[ix][iy] = NAN;
10450 }
10451 }
10452
10453 /* Use WMO definition... */
10454 else if (ctl->met_tropo == 3 || ctl->met_tropo == 4) {
10455
10456 /* Loop over grid points... */
10457#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10458 for (int ix = 0; ix < met->nx; ix++)
10459 for (int iy = 0; iy < met->ny; iy++) {
10460
10461 /* Interpolate temperature profile... */
10462 int iz;
10463 for (iz = 0; iz < met->np; iz++)
10464 t[iz] = met->t[ix][iy][iz];
10465 spline(z, t, met->np, z2, t2, 191, ctl->met_tropo_spline);
10466
10467 /* Find 1st tropopause... */
10468 met->pt[ix][iy] = NAN;
10469 for (iz = 0; iz <= 170; iz++) {
10470 int found = 1;
10471 for (int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10472 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10473 found = 0;
10474 break;
10475 }
10476 if (found) {
10477 if (iz > 0 && iz < 170)
10478 met->pt[ix][iy] = (float) p2[iz];
10479 break;
10480 }
10481 }
10482
10483 /* Find 2nd tropopause... */
10484 if (ctl->met_tropo == 4) {
10485 met->pt[ix][iy] = NAN;
10486 for (; iz <= 170; iz++) {
10487 int found = 1;
10488 for (int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
10489 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
10490 found = 0;
10491 break;
10492 }
10493 if (found)
10494 break;
10495 }
10496 for (; iz <= 170; iz++) {
10497 int found = 1;
10498 for (int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10499 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10500 found = 0;
10501 break;
10502 }
10503 if (found) {
10504 if (iz > 0 && iz < 170)
10505 met->pt[ix][iy] = (float) p2[iz];
10506 break;
10507 }
10508 }
10509 }
10510 }
10511 }
10512
10513 /* Use dynamical tropopause... */
10514 else if (ctl->met_tropo == 5) {
10515
10516 /* Loop over grid points... */
10517#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
10518 for (int ix = 0; ix < met->nx; ix++)
10519 for (int iy = 0; iy < met->ny; iy++) {
10520
10521 /* Interpolate potential vorticity profile... */
10522 for (int iz = 0; iz < met->np; iz++)
10523 pv[iz] = met->pv[ix][iy][iz];
10524 spline(z, pv, met->np, z2, pv2, 171, ctl->met_tropo_spline);
10525
10526 /* Interpolate potential temperature profile... */
10527 for (int iz = 0; iz < met->np; iz++)
10528 th[iz] = THETA(met->p[iz], met->t[ix][iy][iz]);
10529 spline(z, th, met->np, z2, th2, 171, ctl->met_tropo_spline);
10530
10531 /* Find dynamical tropopause... */
10532 met->pt[ix][iy] = NAN;
10533 for (int iz = 0; iz <= 170; iz++)
10534 if (fabs(pv2[iz]) >= ctl->met_tropo_pv
10535 || th2[iz] >= ctl->met_tropo_theta) {
10536 if (iz > 0 && iz < 170)
10537 met->pt[ix][iy] = (float) p2[iz];
10538 break;
10539 }
10540 }
10541 }
10542
10543 else
10544 ERRMSG("Cannot calculate tropopause!");
10545
10546 /* Interpolate temperature, geopotential height, and water vapor... */
10547#pragma omp parallel for default(shared) collapse(2)
10548 for (int ix = 0; ix < met->nx; ix++)
10549 for (int iy = 0; iy < met->ny; iy++) {
10550 double h2ot, tt, zt;
10552 intpol_met_space_3d(met, met->t, met->pt[ix][iy], met->lon[ix],
10553 met->lat[iy], &tt, ci, cw, 1);
10554 intpol_met_space_3d(met, met->z, met->pt[ix][iy], met->lon[ix],
10555 met->lat[iy], &zt, ci, cw, 0);
10556 intpol_met_space_3d(met, met->h2o, met->pt[ix][iy], met->lon[ix],
10557 met->lat[iy], &h2ot, ci, cw, 0);
10558 met->tt[ix][iy] = (float) tt;
10559 met->zt[ix][iy] = (float) zt;
10560 met->h2ot[ix][iy] = (float) h2ot;
10561 }
10562}
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:10772
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
Definition: mptrac.h:979
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 10566 of file mptrac.c.

10574 {
10575
10576 /* Write info... */
10577 LOG(1, "Read observation data: %s", filename);
10578
10579 /* Read data... */
10580 if (ctl->obs_type == 0)
10581 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
10582 else if (ctl->obs_type == 1)
10583 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
10584 else
10585 ERRMSG("Set OBS_TYPE to 0 or 1!");
10586
10587 /* Check time... */
10588 for (int i = 1; i < *nobs; i++)
10589 if (rt[i] < rt[i - 1])
10590 ERRMSG("Time must be ascending!");
10591
10592 /* Write info... */
10593 int n = *nobs;
10594 double mini, maxi;
10595 LOG(2, "Number of observations: %d", *nobs);
10596 gsl_stats_minmax(&mini, &maxi, rt, 1, (size_t) n);
10597 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
10598 gsl_stats_minmax(&mini, &maxi, rz, 1, (size_t) n);
10599 LOG(2, "Altitude range: %g ... %g km", mini, maxi);
10600 gsl_stats_minmax(&mini, &maxi, rlon, 1, (size_t) n);
10601 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
10602 gsl_stats_minmax(&mini, &maxi, rlat, 1, (size_t) n);
10603 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
10604 gsl_stats_minmax(&mini, &maxi, robs, 1, (size_t) n);
10605 LOG(2, "Observation range: %g ... %g", mini, maxi);
10606}
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:10610
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:10638
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 10610 of file mptrac.c.

10617 {
10618
10619 /* Open observation data file... */
10620 FILE *in;
10621 if (!(in = fopen(filename, "r")))
10622 ERRMSG("Cannot open file!");
10623
10624 /* Read observations... */
10625 char line[LEN];
10626 while (fgets(line, LEN, in))
10627 if (sscanf(line, "%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
10628 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
10629 if ((++(*nobs)) >= NOBS)
10630 ERRMSG("Too many observations!");
10631
10632 /* Close observation data file... */
10633 fclose(in);
10634}
#define NOBS
Maximum number of observation data points.
Definition: mptrac.h:348

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

10645 {
10646
10647 int ncid, varid;
10648
10649 /* Open netCDF file... */
10650 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
10651 ERRMSG("Cannot open file!");
10652
10653 /* Read the observations from the NetCDF file... */
10654 NC_INQ_DIM("nobs", nobs, 1, NOBS);
10655 NC_GET_DOUBLE("time", rt, 1);
10656 NC_GET_DOUBLE("alt", rz, 1);
10657 NC_GET_DOUBLE("lon", rlon, 1);
10658 NC_GET_DOUBLE("lat", rlat, 1);
10659 NC_GET_DOUBLE("obs", robs, 1);
10660
10661 /* Close file... */
10662 NC(nc_close(ncid));
10663}

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

10674 {
10675
10676 FILE *in = NULL;
10677
10678 char fullname1[LEN], fullname2[LEN], rval[LEN];
10679
10680 int contain = 0, i;
10681
10682 /* Open file... */
10683 if (filename[strlen(filename) - 1] != '-')
10684 if (!(in = fopen(filename, "r")))
10685 ERRMSG("Cannot open file!");
10686
10687 /* Set full variable name... */
10688 if (arridx >= 0) {
10689 sprintf(fullname1, "%s[%d]", varname, arridx);
10690 sprintf(fullname2, "%s[*]", varname);
10691 } else {
10692 sprintf(fullname1, "%s", varname);
10693 sprintf(fullname2, "%s", varname);
10694 }
10695
10696 /* Read data... */
10697 if (in != NULL) {
10698 char dummy[LEN], line[LEN], rvarname[LEN];
10699 while (fgets(line, LEN, in)) {
10700 if (sscanf(line, "%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
10701 if (strcasecmp(rvarname, fullname1) == 0 ||
10702 strcasecmp(rvarname, fullname2) == 0) {
10703 contain = 1;
10704 break;
10705 }
10706 }
10707 }
10708 for (i = 1; i < argc - 1; i++)
10709 if (strcasecmp(argv[i], fullname1) == 0 ||
10710 strcasecmp(argv[i], fullname2) == 0) {
10711 sprintf(rval, "%s", argv[i + 1]);
10712 contain = 1;
10713 break;
10714 }
10715
10716 /* Close file... */
10717 if (in != NULL)
10718 fclose(in);
10719
10720 /* Check for missing variables... */
10721 if (!contain) {
10722 if (strlen(defvalue) > 0)
10723 sprintf(rval, "%s", defvalue);
10724 else
10725 ERRMSG("Missing variable %s!\n", fullname1);
10726 }
10727
10728 /* Write info... */
10729 LOG(1, "%s = %s", fullname1, rval);
10730
10731 /* Return values... */
10732 if (value != NULL)
10733 sprintf(value, "%s", rval);
10734 return atof(rval);
10735}

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

10743 {
10744
10745 /* Convert particle radius from microns to m... */
10746 const double rp_help = rp * 1e-6;
10747
10748 /* Density of dry air [kg / m^3]... */
10749 const double rho = RHO(p, T);
10750
10751 /* Dynamic viscosity of air [kg / (m s)]... */
10752 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
10753
10754 /* Thermal velocity of an air molecule [m / s]... */
10755 const double v = sqrt(8. * KB * T / (M_PI * 4.8096e-26));
10756
10757 /* Mean free path of an air molecule [m]... */
10758 const double lambda = 2. * eta / (rho * v);
10759
10760 /* Knudsen number for air (dimensionless)... */
10761 const double K = lambda / rp_help;
10762
10763 /* Cunningham slip-flow correction (dimensionless)... */
10764 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
10765
10766 /* Sedimentation velocity [m / s]... */
10767 return 2. * SQR(rp_help) * (rhop - rho) * G0 / (9. * eta) * G;
10768}
#define KB
Boltzmann constant [kg m^2/(K s^2)].
Definition: mptrac.h:228

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

10779 {
10780
10781 /* Cubic spline interpolation... */
10782 if (method == 1) {
10783
10784 /* Allocate... */
10785 gsl_interp_accel *acc = gsl_interp_accel_alloc();
10786 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (size_t) n);
10787
10788 /* Interpolate profile... */
10789 gsl_spline_init(s, x, y, (size_t) n);
10790 for (int i = 0; i < n2; i++)
10791 if (x2[i] <= x[0])
10792 y2[i] = y[0];
10793 else if (x2[i] >= x[n - 1])
10794 y2[i] = y[n - 1];
10795 else
10796 y2[i] = gsl_spline_eval(s, x2[i], acc);
10797
10798 /* Free... */
10799 gsl_spline_free(s);
10800 gsl_interp_accel_free(acc);
10801 }
10802
10803 /* Linear interpolation... */
10804 else {
10805 for (int i = 0; i < n2; i++)
10806 if (x2[i] <= x[0])
10807 y2[i] = y[0];
10808 else if (x2[i] >= x[n - 1])
10809 y2[i] = y[n - 1];
10810 else {
10811 const int idx = locate_irr(x, n, x2[i]);
10812 y2[i] = LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
10813 }
10814 }
10815}
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 10819 of file mptrac.c.

10821 {
10822
10823 if (n <= 0)
10824 return 0;
10825
10826 float mean = 0, var = 0;
10827
10828 for (int i = 0; i < n; ++i) {
10829 mean += data[i];
10830 var += SQR(data[i]);
10831 }
10832
10833 var = var / (float) n - SQR(mean / (float) n);
10834
10835 return (var > 0 ? sqrtf(var) : 0);
10836}

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

10843 {
10844
10845 /* Number of days and fraction with respect to 2000-01-01T12:00Z... */
10846 const double D = sec / 86400 - 0.5;
10847
10848 /* Geocentric apparent ecliptic longitude [rad]... */
10849 const double g = DEG2RAD(357.529 + 0.98560028 * D);
10850 const double q = 280.459 + 0.98564736 * D;
10851 const double L = DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
10852
10853 /* Mean obliquity of the ecliptic [rad]... */
10854 const double e = DEG2RAD(23.439 - 0.00000036 * D);
10855
10856 /* Declination [rad]... */
10857 const double sindec = sin(e) * sin(L);
10858
10859 /* Right ascension [rad]... */
10860 const double ra = atan2(cos(e) * sin(L), cos(L));
10861
10862 /* Greenwich Mean Sidereal Time [h]... */
10863 const double GMST = 18.697374558 + 24.06570982441908 * D;
10864
10865 /* Local Sidereal Time [h]... */
10866 const double LST = GMST + lon / 15;
10867
10868 /* Hour angle [rad]... */
10869 const double h = LST / 12 * M_PI - ra;
10870
10871 /* Convert latitude... */
10872 const double lat_help = DEG2RAD(lat);
10873
10874 /* Return solar zenith angle [rad]... */
10875 return acos(sin(lat_help) * sindec +
10876 cos(lat_help) * sqrt(1 - SQR(sindec)) * cos(h));
10877}

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

10889 {
10890
10891 struct tm t0, t1;
10892
10893 t0.tm_year = 100;
10894 t0.tm_mon = 0;
10895 t0.tm_mday = 1;
10896 t0.tm_hour = 0;
10897 t0.tm_min = 0;
10898 t0.tm_sec = 0;
10899
10900 t1.tm_year = year - 1900;
10901 t1.tm_mon = mon - 1;
10902 t1.tm_mday = day;
10903 t1.tm_hour = hour;
10904 t1.tm_min = min;
10905 t1.tm_sec = sec;
10906
10907 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
10908}

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

10915 {
10916
10917 static char names[NTIMER][100], groups[NTIMER][100];
10918
10919 static double rt_name[NTIMER], rt_group[NTIMER],
10920 rt_min[NTIMER], rt_max[NTIMER], dt, t0, t1;
10921
10922 static int iname = -1, igroup = -1, nname, ngroup, ct_name[NTIMER];
10923
10924 /* Get time... */
10925 t1 = omp_get_wtime();
10926 dt = t1 - t0;
10927
10928 /* Add elapsed time to current timers... */
10929 if (iname >= 0) {
10930 rt_name[iname] += dt;
10931 rt_min[iname] = (ct_name[iname] <= 0 ? dt : MIN(rt_min[iname], dt));
10932 rt_max[iname] = (ct_name[iname] <= 0 ? dt : MAX(rt_max[iname], dt));
10933 ct_name[iname]++;
10934 }
10935 if (igroup >= 0)
10936 rt_group[igroup] += t1 - t0;
10937
10938 /* Report timers... */
10939 if (output) {
10940 for (int i = 0; i < nname; i++)
10941 LOG(1, "TIMER_%s = %.3f s (min= %g s, mean= %g s,"
10942 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
10943 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
10944 for (int i = 0; i < ngroup; i++)
10945 LOG(1, "TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
10946 double total = 0.0;
10947 for (int i = 0; i < nname; i++)
10948 total += rt_name[i];
10949 LOG(1, "TIMER_TOTAL = %.3f s", total);
10950 }
10951
10952 /* Identify IDs of next timer... */
10953 for (iname = 0; iname < nname; iname++)
10954 if (strcasecmp(name, names[iname]) == 0)
10955 break;
10956 for (igroup = 0; igroup < ngroup; igroup++)
10957 if (strcasecmp(group, groups[igroup]) == 0)
10958 break;
10959
10960 /* Check whether this is a new timer... */
10961 if (iname >= nname) {
10962 sprintf(names[iname], "%s", name);
10963 if ((++nname) >= NTIMER)
10964 ERRMSG("Too many timers!");
10965 }
10966
10967 /* Check whether this is a new group... */
10968 if (igroup >= ngroup) {
10969 sprintf(groups[igroup], "%s", group);
10970 if ((++ngroup) >= NTIMER)
10971 ERRMSG("Too many groups!");
10972 }
10973
10974 /* Save starting time... */
10975 t0 = t1;
10976}
#define NTIMER
Maximum number of timers.
Definition: mptrac.h:2072

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

10982 {
10983
10984 char tstr[10];
10985
10986 double t;
10987
10988 /* Get time from filename... */
10989 int len = (int) strlen(filename);
10990 sprintf(tstr, "%.4s", &filename[len - offset]);
10991 int year = atoi(tstr);
10992 sprintf(tstr, "%.2s", &filename[len - offset + 5]);
10993 int mon = atoi(tstr);
10994 sprintf(tstr, "%.2s", &filename[len - offset + 8]);
10995 int day = atoi(tstr);
10996 sprintf(tstr, "%.2s", &filename[len - offset + 11]);
10997 int hour = atoi(tstr);
10998 sprintf(tstr, "%.2s", &filename[len - offset + 14]);
10999 int min = atoi(tstr);
11000
11001 /* Check time... */
11002 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
11003 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
11004 ERRMSG("Cannot read time from filename!");
11005
11006 /* Convert time to Julian seconds... */
11007 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
11008
11009 /* Return time... */
11010 return t;
11011}
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 11015 of file mptrac.c.

11018 {
11019
11020 /* Get tropopause pressure... */
11021 const double pt = clim_tropo(clim, atm->time[ip], atm->lat[ip]);
11022
11023 /* Get pressure range... */
11024 const double p1 = pt * 0.866877899;
11025 const double p0 = pt / 0.866877899;
11026
11027 /* Get weighting factor... */
11028 if (atm->p[ip] > p0)
11029 return 1;
11030 else if (atm->p[ip] < p1)
11031 return 0;
11032 else
11033 return LIN(p0, 1.0, p1, 0.0, atm->p[ip]);
11034}
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 11038 of file mptrac.c.

11042 {
11043
11044 FILE *out;
11045
11046 /* Set time interval for output... */
11047 const double t0 = t - 0.5 * ctl->dt_mod;
11048 const double t1 = t + 0.5 * ctl->dt_mod;
11049
11050 /* Check if gnuplot output is requested... */
11051 if (ctl->atm_gpfile[0] != '-') {
11052
11053 /* Create gnuplot pipe... */
11054 if (!(out = popen("gnuplot", "w")))
11055 ERRMSG("Cannot create pipe to gnuplot!");
11056
11057 /* Set plot filename... */
11058 fprintf(out, "set out \"%s.png\"\n", filename);
11059
11060 /* Set time string... */
11061 double r;
11062 int year, mon, day, hour, min, sec;
11063 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11064 fprintf(out, "timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
11065 year, mon, day, hour, min);
11066
11067 /* Dump gnuplot file to pipe... */
11068 FILE *in;
11069 if (!(in = fopen(ctl->atm_gpfile, "r")))
11070 ERRMSG("Cannot open file!");
11071 char line[LEN];
11072 while (fgets(line, LEN, in))
11073 fprintf(out, "%s", line);
11074 fclose(in);
11075 }
11076
11077 else {
11078
11079 /* Create file... */
11080 if (!(out = fopen(filename, "w")))
11081 ERRMSG("Cannot create file!");
11082 }
11083
11084 /* Write header... */
11085 fprintf(out,
11086 "# $1 = time [s]\n"
11087 "# $2 = altitude [km]\n"
11088 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11089 for (int iq = 0; iq < ctl->nq; iq++)
11090 fprintf(out, "# $%i = %s [%s]\n", iq + 5, ctl->qnt_name[iq],
11091 ctl->qnt_unit[iq]);
11092 fprintf(out, "\n");
11093
11094 /* Write data... */
11095 for (int ip = 0; ip < atm->np; ip += ctl->atm_stride) {
11096
11097 /* Check time... */
11098 if (ctl->atm_filter == 2 && (atm->time[ip] < t0 || atm->time[ip] > t1))
11099 continue;
11100
11101 /* Write output... */
11102 fprintf(out, "%.2f %g %g %g", atm->time[ip], Z(atm->p[ip]),
11103 atm->lon[ip], atm->lat[ip]);
11104 for (int iq = 0; iq < ctl->nq; iq++) {
11105 fprintf(out, " ");
11106 if (ctl->atm_filter == 1 && (atm->time[ip] < t0 || atm->time[ip] > t1))
11107 fprintf(out, ctl->qnt_format[iq], NAN);
11108 else
11109 fprintf(out, ctl->qnt_format[iq], atm->q[iq][ip]);
11110 }
11111 fprintf(out, "\n");
11112 }
11113
11114 /* Close file... */
11115 fclose(out);
11116}
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 11120 of file mptrac.c.

11123 {
11124
11125 FILE *out;
11126
11127 /* Create file... */
11128 if (!(out = fopen(filename, "w")))
11129 ERRMSG("Cannot create file!");
11130
11131 /* Write version of binary data... */
11132 int version = 100;
11133 FWRITE(&version, int,
11134 1,
11135 out);
11136
11137 /* Write data... */
11138 FWRITE(&atm->np, int,
11139 1,
11140 out);
11141 FWRITE(atm->time, double,
11142 (size_t) atm->np,
11143 out);
11144 FWRITE(atm->p, double,
11145 (size_t) atm->np,
11146 out);
11147 FWRITE(atm->lon, double,
11148 (size_t) atm->np,
11149 out);
11150 FWRITE(atm->lat, double,
11151 (size_t) atm->np,
11152 out);
11153 for (int iq = 0; iq < ctl->nq; iq++)
11154 FWRITE(atm->q[iq], double,
11155 (size_t) atm->np,
11156 out);
11157
11158 /* Write final flag... */
11159 int final = 999;
11160 FWRITE(&final, int,
11161 1,
11162 out);
11163
11164 /* Close file... */
11165 fclose(out);
11166}

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

11173 {
11174
11175 int tid, pid, ncid, varid;
11176 size_t start[2], count[2];
11177
11178 /* Create file... */
11179 nc_create(filename, NC_NETCDF4, &ncid);
11180
11181 /* Define dimensions... */
11182 NC(nc_def_dim(ncid, "time", 1, &tid));
11183 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
11184
11185 /* Define variables and their attributes... */
11186 int dim_ids[2] = { tid, pid };
11187 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
11188 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
11189 NC_DEF_VAR("LAT", NC_DOUBLE, 1, &pid, "Latitude", "deg",
11190 ctl->atm_nc_level, 0);
11191 NC_DEF_VAR("LON", NC_DOUBLE, 1, &pid, "Longitude", "deg",
11192 ctl->atm_nc_level, 0);
11193 NC_DEF_VAR("PRESS", NC_DOUBLE, 1, &pid, "Pressure", "hPa",
11194 ctl->atm_nc_level, 0);
11195 NC_DEF_VAR("ZETA", NC_DOUBLE, 1, &pid, "Zeta", "K", ctl->atm_nc_level, 0);
11196 for (int iq = 0; iq < ctl->nq; iq++)
11197 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
11198 ctl->qnt_name[iq], ctl->qnt_unit[iq],
11199 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
11200
11201 /* Define global attributes... */
11202 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
11203 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
11204
11205 /* End definitions... */
11206 NC(nc_enddef(ncid));
11207
11208 /* Write data... */
11209 NC_PUT_DOUBLE("time", atm->time, 0);
11210 NC_PUT_DOUBLE("LAT", atm->lat, 0);
11211 NC_PUT_DOUBLE("LON", atm->lon, 0);
11212 NC_PUT_DOUBLE("PRESS", atm->p, 0);
11213 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 0);
11214 for (int iq = 0; iq < ctl->nq; iq++)
11215 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
11216
11217 /* Close file... */
11218 NC(nc_close(ncid));
11219}
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
Definition: mptrac.h:1351
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units, level, quant)
Define a NetCDF variable with attributes.
Definition: mptrac.h:1184
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
Write double precision data to a NetCDF variable.
Definition: mptrac.h:1265

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

11227 {
11228
11229 /* Global Counter... */
11230 static size_t out_cnt = 0;
11231
11232 double r, r_start, r_stop;
11233 int year, mon, day, hour, min, sec;
11234 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
11235 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
11236 char filename_out[2 * LEN] = "traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
11237
11238 int ncid, varid, tid, pid, cid;
11239 int dim_ids[2];
11240
11241 /* time, nparc */
11242 size_t start[2];
11243 size_t count[2];
11244
11245 /* Determine start and stop times of calculation... */
11246 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11247 jsec2time(ctl->t_start, &year_start, &mon_start, &day_start, &hour_start,
11248 &min_start, &sec_start, &r_start);
11249 jsec2time(ctl->t_stop, &year_stop, &mon_stop, &day_stop, &hour_stop,
11250 &min_stop, &sec_stop, &r_stop);
11251
11252 sprintf(filename_out,
11253 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
11254 year_start % 100, mon_start, day_start, hour_start,
11255 year_stop % 100, mon_stop, day_stop, hour_stop);
11256 LOG(1, "Write traj file: %s", filename_out);
11257
11258 /* Define hyperslap for the traj_file... */
11259 start[0] = out_cnt;
11260 start[1] = 0;
11261 count[0] = 1;
11262 count[1] = (size_t) atm->np;
11263
11264 /* Create the file at the first timestep... */
11265 if (out_cnt == 0) {
11266
11267 /* Create file... */
11268 NC(nc_create(filename_out, NC_NETCDF4, &ncid));
11269
11270 /* Define dimensions... */
11271 NC(nc_def_dim(ncid, "time", NC_UNLIMITED, &tid));
11272 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
11273 NC(nc_def_dim(ncid, "TMDT", 7, &cid));
11274 dim_ids[0] = tid;
11275 dim_ids[1] = pid;
11276
11277 /* Define variables and their attributes... */
11278 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
11279 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
11280 NC_DEF_VAR("LAT", NC_DOUBLE, 2, dim_ids, "Latitude", "deg",
11281 ctl->atm_nc_level, 0);
11282 NC_DEF_VAR("LON", NC_DOUBLE, 2, dim_ids, "Longitude", "deg",
11283 ctl->atm_nc_level, 0);
11284 NC_DEF_VAR("PRESS", NC_DOUBLE, 2, dim_ids, "Pressure", "hPa",
11285 ctl->atm_nc_level, 0);
11286 NC_DEF_VAR("ZETA", NC_DOUBLE, 2, dim_ids, "Zeta", "K",
11287 ctl->atm_nc_level, 0);
11288 for (int iq = 0; iq < ctl->nq; iq++)
11289 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
11290 ctl->qnt_name[iq], ctl->qnt_unit[iq],
11291 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
11292
11293 /* Define global attributes... */
11294 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
11295 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
11296
11297 /* End definitions... */
11298 NC(nc_enddef(ncid));
11299 NC(nc_close(ncid));
11300 }
11301
11302 /* Increment global counter to change hyperslap... */
11303 out_cnt++;
11304
11305 /* Open file... */
11306 NC(nc_open(filename_out, NC_WRITE, &ncid));
11307
11308 /* Write data... */
11309 NC_PUT_DOUBLE("time", atm->time, 1);
11310 NC_PUT_DOUBLE("LAT", atm->lat, 1);
11311 NC_PUT_DOUBLE("LON", atm->lon, 1);
11312 NC_PUT_DOUBLE("PRESS", atm->p, 1);
11313 if (ctl->advect_vert_coord == 1) {
11314 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta], 1);
11315 } else if (ctl->qnt_zeta >= 0) {
11316 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 1);
11317 }
11318 for (int iq = 0; iq < ctl->nq; iq++)
11319 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 1);
11320
11321 /* Close file... */
11322 NC(nc_close(ncid));
11323
11324 /* At the last time step create the init_fix_YYYYMMDDHH file... */
11325 if ((year == year_stop) && (mon == mon_stop)
11326 && (day == day_stop) && (hour == hour_stop)) {
11327
11328 /* Set filename... */
11329 char filename_init[2 * LEN] = "./init_fix_YYYYMMDDHH.nc";
11330 sprintf(filename_init, "%s/init_fix_%02d%02d%02d%02d.nc",
11331 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
11332 LOG(1, "Write init file: %s", filename_init);
11333
11334 /* Create file... */
11335 nc_create(filename_init, NC_NETCDF4, &ncid);
11336
11337 /* Define dimensions... */
11338 NC(nc_def_dim(ncid, "time", 1, &tid));
11339 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
11340 dim_ids[0] = tid;
11341 dim_ids[1] = pid;
11342
11343 /* Define variables and their attributes... */
11344 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
11345 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
11346 NC_DEF_VAR("LAT", NC_DOUBLE, 1, &pid, "Latitude", "deg",
11347 ctl->atm_nc_level, 0);
11348 NC_DEF_VAR("LON", NC_DOUBLE, 1, &pid, "Longitude", "deg",
11349 ctl->atm_nc_level, 0);
11350 NC_DEF_VAR("PRESS", NC_DOUBLE, 1, &pid, "Pressure", "hPa",
11351 ctl->atm_nc_level, 0);
11352 NC_DEF_VAR("ZETA", NC_DOUBLE, 1, &pid, "Zeta", "K", ctl->atm_nc_level, 0);
11353 for (int iq = 0; iq < ctl->nq; iq++)
11354 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
11355 ctl->qnt_name[iq], ctl->qnt_unit[iq],
11356 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
11357
11358 /* Define global attributes... */
11359 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
11360 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
11361
11362 /* End definitions... */
11363 NC(nc_enddef(ncid));
11364
11365 /* Write data... */
11366 NC_PUT_DOUBLE("time", atm->time, 0);
11367 NC_PUT_DOUBLE("LAT", atm->lat, 0);
11368 NC_PUT_DOUBLE("LON", atm->lon, 0);
11369 NC_PUT_DOUBLE("PRESS", atm->p, 0);
11370 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 0);
11371 for (int iq = 0; iq < ctl->nq; iq++)
11372 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
11373
11374 /* Close file... */
11375 NC(nc_close(ncid));
11376 }
11377}
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 11381 of file mptrac.c.

11384 {
11385
11386 int ncid, obsid, varid;
11387
11388 size_t start[2], count[2];
11389
11390 /* Create file... */
11391 NC(nc_create(filename, NC_NETCDF4, &ncid));
11392
11393 /* Define dimensions... */
11394 NC(nc_def_dim(ncid, "obs", (size_t) atm->np, &obsid));
11395
11396 /* Define variables and their attributes... */
11397 NC_DEF_VAR("time", NC_DOUBLE, 1, &obsid, "time",
11398 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
11399 NC_DEF_VAR("press", NC_DOUBLE, 1, &obsid, "pressure", "hPa",
11400 ctl->atm_nc_level, 0);
11401 NC_DEF_VAR("lon", NC_DOUBLE, 1, &obsid, "longitude", "degrees_east",
11402 ctl->atm_nc_level, 0);
11403 NC_DEF_VAR("lat", NC_DOUBLE, 1, &obsid, "latitude", "degrees_north",
11404 ctl->atm_nc_level, 0);
11405 for (int iq = 0; iq < ctl->nq; iq++)
11406 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 1, &obsid,
11407 ctl->qnt_longname[iq], ctl->qnt_unit[iq],
11408 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
11409
11410 /* Define global attributes... */
11411 NC_PUT_ATT_GLOBAL("featureType", "point");
11412
11413 /* End definitions... */
11414 NC(nc_enddef(ncid));
11415
11416 /* Write data... */
11417 NC_PUT_DOUBLE("time", atm->time, 0);
11418 NC_PUT_DOUBLE("press", atm->p, 0);
11419 NC_PUT_DOUBLE("lon", atm->lon, 0);
11420 NC_PUT_DOUBLE("lat", atm->lat, 0);
11421 for (int iq = 0; iq < ctl->nq; iq++)
11422 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
11423
11424 /* Close file... */
11425 NC(nc_close(ncid));
11426}

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

11434 {
11435
11436 static FILE *out;
11437
11438 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
11439 *area, dlon, dlat, dz, x[NCSI], y[NCSI], obsstdn[NCSI], kz[EP], kw[EP];
11440
11441 static int *obscount, nobs, nk;
11442
11443 static int ct[NENS], cx[NENS], cy[NENS], cz[NENS], n[NENS];
11444
11445 const int ensemble = (ctl->nens > 0);
11446
11447 /* Set timer */
11448 SELECT_TIMER("WRITE_CSI", "OUTPUT", NVTX_WRITE);
11449
11450 /* Check quantities... */
11451 if (ctl->qnt_m < 0)
11452 ERRMSG("Need quantity mass!");
11453 if (ensemble) {
11454 if (ctl->qnt_ens < 0)
11455 ERRMSG("Missing ensemble IDs!");
11456 if (ctl->nens > NENS)
11457 ERRMSG("Too many ensembles!");
11458 }
11459
11460 /* Init... */
11461 if (t == ctl->t_start) {
11462
11463 /* Allocate.. */
11464 ALLOC(area, double,
11465 ctl->csi_ny);
11466 ALLOC(rt, double,
11467 NOBS);
11468 ALLOC(rz, double,
11469 NOBS);
11470 ALLOC(rlon, double,
11471 NOBS);
11472 ALLOC(rlat, double,
11473 NOBS);
11474 ALLOC(robs, double,
11475 NOBS);
11476
11477 /* Read observation data... */
11478 read_obs(ctl->csi_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
11479
11480 /* Read kernel data... */
11481 if (ctl->csi_kernel[0] != '-')
11482 read_kernel(ctl->csi_kernel, kz, kw, &nk);
11483
11484 /* Create new file... */
11485 LOG(1, "Write CSI%s data: %s", ensemble ? " ensemble" : "", filename);
11486 if (!(out = fopen(filename, "w")))
11487 ERRMSG("Cannot create file!");
11488
11489 /* Write header... */
11490 fprintf(out,
11491 "# $1 = time [s]\n"
11492 "# $2 = ensemble ID\n"
11493 "# $3 = number of hits (cx)\n"
11494 "# $4 = number of misses (cy)\n"
11495 "# $5 = number of false alarms (cz)\n"
11496 "# $6 = number of observations (cx + cy)\n"
11497 "# $7 = number of forecasts (cx + cz)\n"
11498 "# $8 = bias (%%)\n"
11499 "# $9 = POD (%%)\n"
11500 "# $10 = FAR (%%)\n"
11501 "# $11 = CSI (%%)\n"
11502 "# $12 = hits by random chance\n"
11503 "# $13 = ETS (%%)\n"
11504 "# $14 = Pearson R\n"
11505 "# $15 = Spearman R\n"
11506 "# $16 = mean error [kg/m²]\n"
11507 "# $17 = RMSE [kg/m²]\n"
11508 "# $18 = MAE [kg/m²]\n"
11509 "# $19 = log-likelihood\n" "# $20 = number of points\n\n");
11510
11511 /* Set grid box size... */
11512 dz = (ctl->csi_z1 - ctl->csi_z0) / ctl->csi_nz;
11513 dlon = (ctl->csi_lon1 - ctl->csi_lon0) / ctl->csi_nx;
11514 dlat = (ctl->csi_lat1 - ctl->csi_lat0) / ctl->csi_ny;
11515
11516 /* Set horizontal coordinates... */
11517 for (int iy = 0; iy < ctl->csi_ny; iy++) {
11518 const double lat = ctl->csi_lat0 + dlat * (iy + 0.5);
11519 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.0) * cos(DEG2RAD(lat));
11520 }
11521 }
11522
11523 /* Set time interval... */
11524 const double t0 = t - 0.5 * ctl->dt_mod;
11525 const double t1 = t + 0.5 * ctl->dt_mod;
11526
11527 /* Allocate... */
11528 int grid_size = ctl->csi_nx * ctl->csi_ny * ctl->csi_nz;
11529 ALLOC(modmean, double,
11530 (ensemble ? ctl->nens : 1) * grid_size);
11531 ALLOC(obsmean, double,
11532 grid_size);
11533 ALLOC(obscount, int,
11534 grid_size);
11535 ALLOC(obsstd, double,
11536 grid_size);
11537
11538 /* Init... */
11539 for (int i = 0; i < (ensemble ? ctl->nens : 1); i++)
11540 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
11541
11542 /* Loop over observations... */
11543 for (int i = 0; i < nobs; i++) {
11544 if (rt[i] < t0 || rt[i] >= t1 || !isfinite(robs[i]))
11545 continue;
11546
11547 /* Calculate indices... */
11548 const int ix = (int) ((rlon[i] - ctl->csi_lon0) / dlon);
11549 const int iy = (int) ((rlat[i] - ctl->csi_lat0) / dlat);
11550 const int iz = (int) ((rz[i] - ctl->csi_z0) / dz);
11551 if (ix < 0 || ix >= ctl->csi_nx || iy < 0 || iy >= ctl->csi_ny || iz < 0
11552 || iz >= ctl->csi_nz)
11553 continue;
11554
11555 /* Get mean observation index... */
11556 const int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
11557 obsmean[idx] += robs[i];
11558 obsstd[idx] += SQR(robs[i]);
11559 obscount[idx]++;
11560 }
11561
11562 /* Analyze model data... */
11563 for (int ip = 0; ip < atm->np; ip++) {
11564
11565 /* Check time... */
11566 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11567 continue;
11568
11569 /* Get ensemble ID... */
11570 int ens_id = ensemble ? (int) atm->q[ctl->qnt_ens][ip] : 0;
11571 if (ens_id < 0 || ens_id >= (ensemble ? ctl->nens : 1))
11572 ERRMSG("Ensemble ID out of range!");
11573
11574 /* Get indices... */
11575 const int ix = (int) ((atm->lon[ip] - ctl->csi_lon0) / dlon);
11576 const int iy = (int) ((atm->lat[ip] - ctl->csi_lat0) / dlat);
11577 const int iz = (int) ((Z(atm->p[ip]) - ctl->csi_z0) / dz);
11578 if (ix < 0 || ix >= ctl->csi_nx || iy < 0 || iy >= ctl->csi_ny || iz < 0
11579 || iz >= ctl->csi_nz)
11580 continue;
11581
11582 /* Get total mass in grid cell... */
11583 const int idx =
11584 ens_id * grid_size + ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
11585 modmean[idx] +=
11586 kernel_weight(kz, kw, nk, atm->p[ip]) * atm->q[ctl->qnt_m][ip];
11587 }
11588
11589 /* Analyze all grid cells... */
11590 for (int ix = 0; ix < ctl->csi_nx; ix++)
11591 for (int iy = 0; iy < ctl->csi_ny; iy++)
11592 for (int iz = 0; iz < ctl->csi_nz; iz++) {
11593
11594 /* Calculate mean observation index... */
11595 const int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
11596 if (obscount[idx]) {
11597 obsmean[idx] /= obscount[idx];
11598 obsstd[idx] = sqrt(obsstd[idx] - SQR(obsmean[idx]));
11599 }
11600
11601 /* Calculate model mean per ensemble... */
11602 for (int e = 0; e < (ensemble ? ctl->nens : 1); e++) {
11603 const int midx = e * grid_size + idx;
11604 if (modmean[midx] > 0)
11605 modmean[midx] /= (1e6 * area[iy]);
11606 }
11607
11608 /* Check number of observations... */
11609 if (obscount[idx]) {
11610
11611 /* Calculate CSI... */
11612 for (int e = 0; e < (ensemble ? ctl->nens : 1); e++) {
11613 const int midx = e * grid_size + idx;
11614 ct[e]++;
11615 if (obsmean[idx] >= ctl->csi_obsmin
11616 && modmean[midx] >= ctl->csi_modmin)
11617 cx[e]++;
11618 else if (obsmean[idx] >= ctl->csi_obsmin)
11619 cy[e]++;
11620 else if (modmean[midx] >= ctl->csi_modmin)
11621 cz[e]++;
11622
11623 /* Save data for other verification statistics... */
11624 if (obsmean[idx] >= ctl->csi_obsmin
11625 || modmean[midx] >= ctl->csi_modmin) {
11626 x[n[e]] = modmean[midx];
11627 y[n[e]] = obsmean[idx];
11628 if (modmean[midx] >= ctl->csi_modmin)
11629 obsstdn[n[e]] = obsstd[idx];
11630 if ((++n[e]) >= NCSI)
11631 ERRMSG("Too many points for statistics!");
11632 }
11633 }
11634 }
11635 }
11636
11637 /* Write output... */
11638 if (fmod(t, ctl->csi_dt_out) == 0) {
11639 for (int e = 0; e < (ensemble ? ctl->nens : 1); e++) {
11640
11641 if (n[e] == 0)
11642 continue;
11643
11644 /* Calculate verification statistics
11645 (https://www.cawcr.gov.au/projects/verification/) ... */
11646 static double work[2 * NCSI], work2[2 * NCSI];
11647 const int n_obs = cx[e] + cy[e];
11648 const int n_for = cx[e] + cz[e];
11649 const double cx_rd = (ct[e] > 0) ? (1. * n_obs * n_for) / ct[e] : NAN;
11650 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
11651 const double pod = (n_obs > 0) ? 100. * cx[e] / n_obs : NAN;
11652 const double far = (n_for > 0) ? 100. * cz[e] / n_for : NAN;
11653 const double csi =
11654 (cx[e] + cy[e] + cz[e] >
11655 0) ? 100. * cx[e] / (cx[e] + cy[e] + cz[e]) : NAN;
11656 const double ets =
11657 (cx[e] + cy[e] + cz[e] - cx_rd >
11658 0) ? 100. * (cx[e] - cx_rd) / (cx[e] + cy[e] + cz[e] - cx_rd) : NAN;
11659 const double rho_p = gsl_stats_correlation(x, 1, y, 1, (size_t) n[e]);
11660 const double rho_s =
11661 gsl_stats_spearman(x, 1, y, 1, (size_t) n[e], work);
11662 for (int i = 0; i < n[e]; i++) {
11663 work[i] = x[i] - y[i];
11664 work2[i] = (obsstdn[i] != 0) ? work[i] / obsstdn[i] : 0;
11665 }
11666 const double mean = gsl_stats_mean(work, 1, (size_t) n[e]);
11667 const double rmse =
11668 gsl_stats_sd_with_fixed_mean(work, 1, (size_t) n[e], 0.0);
11669 const double absdev = gsl_stats_absdev_m(work, 1, (size_t) n[e], 0.0);
11670 const double loglikelihood =
11671 gsl_stats_tss(work2, 1, (size_t) n[e]) * -0.5;
11672
11673 /* Write... */
11674 fprintf(out,
11675 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
11676 t, ensemble ? e : -999, cx[e], cy[e], cz[e], n_obs, n_for, bias,
11677 pod, far, csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
11678 loglikelihood, n[e]);
11679
11680 /* Set counters to zero... */
11681 ct[e] = cx[e] = cy[e] = cz[e] = n[e] = 0;
11682 }
11683 }
11684
11685 /* Free... */
11686 free(modmean);
11687 free(obsmean);
11688 free(obscount);
11689 free(obsstd);
11690
11691 /* Finalize... */
11692 if (t == ctl->t_stop) {
11693
11694 /* Close output file... */
11695 fclose(out);
11696
11697 /* Free... */
11698 free(area);
11699 free(rt);
11700 free(rz);
11701 free(rlon);
11702 free(rlat);
11703 free(robs);
11704 }
11705}
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:10566
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:6643
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:1837
#define NENS
Maximum number of data points for ensemble analysis.
Definition: mptrac.h:343
#define NCSI
Maximum number of data points for CSI calculation.
Definition: mptrac.h:338
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 11709 of file mptrac.c.

11713 {
11714
11715 static FILE *out;
11716
11717 static double dummy, lat, lon, qm[NQ][NENS], qs[NQ][NENS], xm[NENS][3],
11718 x[3], zm[NENS];
11719
11720 static int n[NENS];
11721
11722 /* Set timer... */
11723 SELECT_TIMER("WRITE_ENS", "OUTPUT", NVTX_WRITE);
11724
11725 /* Check quantities... */
11726 if (ctl->qnt_ens < 0)
11727 ERRMSG("Missing ensemble IDs!");
11728
11729 /* Set time interval... */
11730 const double t0 = t - 0.5 * ctl->dt_mod;
11731 const double t1 = t + 0.5 * ctl->dt_mod;
11732
11733 /* Init... */
11734 for (int i = 0; i < NENS; i++) {
11735 for (int iq = 0; iq < ctl->nq; iq++)
11736 qm[iq][i] = qs[iq][i] = 0;
11737 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
11738 n[i] = 0;
11739 }
11740
11741 /* Loop over air parcels... */
11742 for (int ip = 0; ip < atm->np; ip++) {
11743
11744 /* Check time... */
11745 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11746 continue;
11747
11748 /* Check ensemble ID... */
11749 if (atm->q[ctl->qnt_ens][ip] < 0 || atm->q[ctl->qnt_ens][ip] >= NENS)
11750 ERRMSG("Ensemble ID is out of range!");
11751
11752 /* Get means... */
11753 geo2cart(0, atm->lon[ip], atm->lat[ip], x);
11754 for (int iq = 0; iq < ctl->nq; iq++) {
11755 qm[iq][ctl->qnt_ens] += atm->q[iq][ip];
11756 qs[iq][ctl->qnt_ens] += SQR(atm->q[iq][ip]);
11757 }
11758 xm[ctl->qnt_ens][0] += x[0];
11759 xm[ctl->qnt_ens][1] += x[1];
11760 xm[ctl->qnt_ens][2] += x[2];
11761 zm[ctl->qnt_ens] += Z(atm->p[ip]);
11762 n[ctl->qnt_ens]++;
11763 }
11764
11765 /* Create file... */
11766 LOG(1, "Write ensemble data: %s", filename);
11767 if (!(out = fopen(filename, "w")))
11768 ERRMSG("Cannot create file!");
11769
11770 /* Write header... */
11771 fprintf(out,
11772 "# $1 = time [s]\n"
11773 "# $2 = altitude [km]\n"
11774 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11775 for (int iq = 0; iq < ctl->nq; iq++)
11776 fprintf(out, "# $%d = %s (mean) [%s]\n", 5 + iq,
11777 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
11778 for (int iq = 0; iq < ctl->nq; iq++)
11779 fprintf(out, "# $%d = %s (sigma) [%s]\n", 5 + ctl->nq + iq,
11780 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
11781 fprintf(out, "# $%d = number of members\n\n", 5 + 2 * ctl->nq);
11782
11783 /* Write data... */
11784 for (int i = 0; i < NENS; i++)
11785 if (n[i] > 0) {
11786 cart2geo(xm[i], &dummy, &lon, &lat);
11787 fprintf(out, "%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
11788 for (int iq = 0; iq < ctl->nq; iq++) {
11789 fprintf(out, " ");
11790 fprintf(out, ctl->qnt_format[iq], qm[iq][i] / n[i]);
11791 }
11792 for (int iq = 0; iq < ctl->nq; iq++) {
11793 fprintf(out, " ");
11794 double var = qs[iq][i] / n[i] - SQR(qm[iq][i] / n[i]);
11795 fprintf(out, ctl->qnt_format[iq], (var > 0 ? sqrt(var) : 0));
11796 }
11797 fprintf(out, " %d\n", n[i]);
11798 }
11799
11800 /* Close file... */
11801 fclose(out);
11802}
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 11806 of file mptrac.c.

11812 {
11813
11814 static double kz[EP], kw[EP];
11815
11816 static int nk;
11817
11818 double *cd, *mean[NQ], *sigma[NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
11819
11820 int *ixs, *iys, *izs, *np;
11821
11822 /* Set timer... */
11823 SELECT_TIMER("WRITE_GRID", "OUTPUT", NVTX_WRITE);
11824
11825 /* Write info... */
11826 LOG(1, "Write grid data: %s", filename);
11827
11828 /* Init... */
11829 if (t == ctl->t_start) {
11830
11831 /* Read kernel data... */
11832 if (ctl->grid_kernel[0] != '-')
11833 read_kernel(ctl->grid_kernel, kz, kw, &nk);
11834 }
11835
11836 /* Allocate... */
11837 ALLOC(cd, double,
11838 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
11839 for (int iq = 0; iq < ctl->nq; iq++) {
11840 ALLOC(mean[iq], double,
11841 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
11842 ALLOC(sigma[iq], double,
11843 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
11844 }
11845 ALLOC(vmr_impl, double,
11846 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
11847 ALLOC(z, double,
11848 ctl->grid_nz);
11849 ALLOC(lon, double,
11850 ctl->grid_nx);
11851 ALLOC(lat, double,
11852 ctl->grid_ny);
11853 ALLOC(area, double,
11854 ctl->grid_ny);
11855 ALLOC(press, double,
11856 ctl->grid_nz);
11857 ALLOC(np, int,
11858 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
11859 ALLOC(ixs, int,
11860 atm->np);
11861 ALLOC(iys, int,
11862 atm->np);
11863 ALLOC(izs, int,
11864 atm->np);
11865
11866 /* Set grid box size... */
11867 const double dz = (ctl->grid_z1 - ctl->grid_z0) / ctl->grid_nz;
11868 const double dlon = (ctl->grid_lon1 - ctl->grid_lon0) / ctl->grid_nx;
11869 const double dlat = (ctl->grid_lat1 - ctl->grid_lat0) / ctl->grid_ny;
11870
11871 /* Set vertical coordinates... */
11872#pragma omp parallel for default(shared)
11873 for (int iz = 0; iz < ctl->grid_nz; iz++) {
11874 z[iz] = ctl->grid_z0 + dz * (iz + 0.5);
11875 press[iz] = P(z[iz]);
11876 }
11877
11878 /* Set horizontal coordinates... */
11879 for (int ix = 0; ix < ctl->grid_nx; ix++)
11880 lon[ix] = ctl->grid_lon0 + dlon * (ix + 0.5);
11881#pragma omp parallel for default(shared)
11882 for (int iy = 0; iy < ctl->grid_ny; iy++) {
11883 lat[iy] = ctl->grid_lat0 + dlat * (iy + 0.5);
11884 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
11885 }
11886
11887 /* Set time interval for output... */
11888 const double t0 = t - 0.5 * ctl->dt_mod;
11889 const double t1 = t + 0.5 * ctl->dt_mod;
11890
11891 /* Get grid box indices... */
11892#pragma omp parallel for default(shared)
11893 for (int ip = 0; ip < atm->np; ip++) {
11894 ixs[ip] = (int) ((atm->lon[ip] - ctl->grid_lon0) / dlon);
11895 iys[ip] = (int) ((atm->lat[ip] - ctl->grid_lat0) / dlat);
11896 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->grid_z0) / dz);
11897 if (atm->time[ip] < t0 || atm->time[ip] > t1
11898 || ixs[ip] < 0 || ixs[ip] >= ctl->grid_nx
11899 || iys[ip] < 0 || iys[ip] >= ctl->grid_ny
11900 || izs[ip] < 0 || izs[ip] >= ctl->grid_nz)
11901 izs[ip] = -1;
11902 }
11903
11904 /* Average data... */
11905 for (int ip = 0; ip < atm->np; ip++)
11906 if (izs[ip] >= 0) {
11907 const int idx =
11908 ARRAY_3D(ixs[ip], iys[ip], ctl->grid_ny, izs[ip], ctl->grid_nz);
11909 const double kernel = kernel_weight(kz, kw, nk, atm->p[ip]);
11910 np[idx]++;
11911 for (int iq = 0; iq < ctl->nq; iq++) {
11912 mean[iq][idx] += kernel * atm->q[iq][ip];
11913 sigma[iq][idx] += SQR(kernel * atm->q[iq][ip]);
11914 }
11915 }
11916
11917 /* Calculate column density and volume mixing ratio... */
11918#pragma omp parallel for default(shared)
11919 for (int ix = 0; ix < ctl->grid_nx; ix++)
11920 for (int iy = 0; iy < ctl->grid_ny; iy++)
11921 for (int iz = 0; iz < ctl->grid_nz; iz++) {
11922
11923 /* Get grid index... */
11924 const int idx = ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz);
11925
11926 /* Calculate column density... */
11927 cd[idx] = NAN;
11928 if (ctl->qnt_m >= 0)
11929 cd[idx] = mean[ctl->qnt_m][idx] / (1e6 * area[iy]);
11930
11931 /* Calculate volume mixing ratio (implicit)... */
11932 vmr_impl[idx] = NAN;
11933 if (ctl->qnt_m >= 0 && ctl->molmass > 0 && met0 != NULL
11934 && met1 != NULL) {
11935 vmr_impl[idx] = 0;
11936 if (mean[ctl->qnt_m][idx] > 0) {
11937
11938 /* Get temperature... */
11939 double temp;
11941 intpol_met_time_3d(met0, met0->t, met1, met1->t, t, press[iz],
11942 lon[ix], lat[iy], &temp, ci, cw, 1);
11943
11944 /* Calculate volume mixing ratio... */
11945 vmr_impl[idx] =
11946 MA / ctl->molmass * cd[idx] / (RHO(press[iz], temp) * dz * 1e3);
11947 }
11948 }
11949
11950 /* Calculate mean... */
11951 if (np[idx] > 0)
11952 for (int iq = 0; iq < ctl->nq; iq++) {
11953 mean[iq][idx] /= np[idx];
11954 const double var = sigma[iq][idx] / np[idx] - SQR(mean[iq][idx]);
11955 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
11956 } else
11957 for (int iq = 0; iq < ctl->nq; iq++) {
11958 mean[iq][idx] = NAN;
11959 sigma[iq][idx] = NAN;
11960 }
11961 }
11962
11963 /* Write ASCII data... */
11964 if (ctl->grid_type == 0)
11965 write_grid_asc(filename, ctl, cd, mean, sigma, vmr_impl,
11966 t, z, lon, lat, area, dz, np);
11967
11968 /* Write netCDF data... */
11969 else if (ctl->grid_type == 1)
11970 write_grid_nc(filename, ctl, cd, mean, sigma, vmr_impl,
11971 t, z, lon, lat, area, dz, np);
11972
11973 /* Error message... */
11974 else
11975 ERRMSG("Grid data format GRID_TYPE unknown!");
11976
11977 /* Free... */
11978 free(cd);
11979 for (int iq = 0; iq < ctl->nq; iq++) {
11980 free(mean[iq]);
11981 free(sigma[iq]);
11982 }
11983 free(vmr_impl);
11984 free(z);
11985 free(lon);
11986 free(lat);
11987 free(area);
11988 free(press);
11989 free(np);
11990 free(ixs);
11991 free(iys);
11992 free(izs);
11993}
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:11997
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:12101
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 11997 of file mptrac.c.

12010 {
12011
12012 FILE *out;
12013
12014 /* Check if gnuplot output is requested... */
12015 if (ctl->grid_gpfile[0] != '-') {
12016
12017 /* Create gnuplot pipe... */
12018 if (!(out = popen("gnuplot", "w")))
12019 ERRMSG("Cannot create pipe to gnuplot!");
12020
12021 /* Set plot filename... */
12022 fprintf(out, "set out \"%s.png\"\n", filename);
12023
12024 /* Set time string... */
12025 double r;
12026 int year, mon, day, hour, min, sec;
12027 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
12028 fprintf(out, "timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
12029 year, mon, day, hour, min);
12030
12031 /* Dump gnuplot file to pipe... */
12032 FILE *in;
12033 char line[LEN];
12034 if (!(in = fopen(ctl->grid_gpfile, "r")))
12035 ERRMSG("Cannot open file!");
12036 while (fgets(line, LEN, in))
12037 fprintf(out, "%s", line);
12038 fclose(in);
12039 }
12040
12041 else {
12042
12043 /* Create file... */
12044 if (!(out = fopen(filename, "w")))
12045 ERRMSG("Cannot create file!");
12046 }
12047
12048 /* Write header... */
12049 fprintf(out,
12050 "# $1 = time [s]\n"
12051 "# $2 = altitude [km]\n"
12052 "# $3 = longitude [deg]\n"
12053 "# $4 = latitude [deg]\n"
12054 "# $5 = surface area [km^2]\n"
12055 "# $6 = layer depth [km]\n"
12056 "# $7 = column density (implicit) [kg/m^2]\n"
12057 "# $8 = volume mixing ratio (implicit) [ppv]\n"
12058 "# $9 = number of particles [1]\n");
12059 for (int iq = 0; iq < ctl->nq; iq++)
12060 fprintf(out, "# $%i = %s (mean) [%s]\n", 10 + iq, ctl->qnt_name[iq],
12061 ctl->qnt_unit[iq]);
12062 if (ctl->grid_stddev)
12063 for (int iq = 0; iq < ctl->nq; iq++)
12064 fprintf(out, "# $%i = %s (stddev) [%s]\n", 10 + ctl->nq + iq,
12065 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
12066 fprintf(out, "\n");
12067
12068 /* Write data... */
12069 for (int ix = 0; ix < ctl->grid_nx; ix++) {
12070 if (ix > 0 && ctl->grid_ny > 1 && !ctl->grid_sparse)
12071 fprintf(out, "\n");
12072 for (int iy = 0; iy < ctl->grid_ny; iy++) {
12073 if (iy > 0 && ctl->grid_nz > 1 && !ctl->grid_sparse)
12074 fprintf(out, "\n");
12075 for (int iz = 0; iz < ctl->grid_nz; iz++) {
12076 int idx = ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz);
12077 if (!ctl->grid_sparse || vmr_impl[idx] > 0) {
12078 fprintf(out, "%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
12079 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
12080 for (int iq = 0; iq < ctl->nq; iq++) {
12081 fprintf(out, " ");
12082 fprintf(out, ctl->qnt_format[iq], mean[iq][idx]);
12083 }
12084 if (ctl->grid_stddev)
12085 for (int iq = 0; iq < ctl->nq; iq++) {
12086 fprintf(out, " ");
12087 fprintf(out, ctl->qnt_format[iq], sigma[iq][idx]);
12088 }
12089 fprintf(out, "\n");
12090 }
12091 }
12092 }
12093 }
12094
12095 /* Close file... */
12096 fclose(out);
12097}
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 12101 of file mptrac.c.

12114 {
12115
12116 char longname[2 * LEN], varname[2 * LEN];
12117
12118 double *help;
12119
12120 int *help2, ncid, dimid[10], varid;
12121
12122 size_t start[2], count[2];
12123
12124 /* Allocate... */
12125 ALLOC(help, double,
12126 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
12127 ALLOC(help2, int,
12128 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
12129
12130 /* Create file... */
12131 NC(nc_create(filename, NC_NETCDF4, &ncid));
12132
12133 /* Define dimensions... */
12134 NC(nc_def_dim(ncid, "time", 1, &dimid[0]));
12135 NC(nc_def_dim(ncid, "z", (size_t) ctl->grid_nz, &dimid[1]));
12136 NC(nc_def_dim(ncid, "lat", (size_t) ctl->grid_ny, &dimid[2]));
12137 NC(nc_def_dim(ncid, "lon", (size_t) ctl->grid_nx, &dimid[3]));
12138 NC(nc_def_dim(ncid, "dz", 1, &dimid[4]));
12139
12140 /* Define variables and their attributes... */
12141 NC_DEF_VAR("time", NC_DOUBLE, 1, &dimid[0], "time",
12142 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12143 NC_DEF_VAR("z", NC_DOUBLE, 1, &dimid[1], "altitude", "km", 0, 0);
12144 NC_DEF_VAR("lat", NC_DOUBLE, 1, &dimid[2], "latitude", "degrees_north", 0,
12145 0);
12146 NC_DEF_VAR("lon", NC_DOUBLE, 1, &dimid[3], "longitude", "degrees_east", 0,
12147 0);
12148 NC_DEF_VAR("dz", NC_DOUBLE, 1, &dimid[1], "layer depth", "km", 0, 0);
12149 NC_DEF_VAR("area", NC_DOUBLE, 1, &dimid[2], "surface area", "km**2", 0, 0);
12150
12151 NC_DEF_VAR("cd", NC_FLOAT, 4, dimid, "column density", "kg m**-2",
12152 ctl->grid_nc_level, 0);
12153 NC_DEF_VAR("vmr_impl", NC_FLOAT, 4, dimid,
12154 "volume mixing ratio (implicit)", "ppv", ctl->grid_nc_level, 0);
12155 NC_DEF_VAR("np", NC_INT, 4, dimid, "number of particles", "1", 0, 0);
12156 for (int iq = 0; iq < ctl->nq; iq++) {
12157 sprintf(varname, "%s_mean", ctl->qnt_name[iq]);
12158 sprintf(longname, "%s (mean)", ctl->qnt_longname[iq]);
12159 NC_DEF_VAR(varname, NC_DOUBLE, 4, dimid, longname, ctl->qnt_unit[iq],
12160 ctl->grid_nc_level, ctl->grid_nc_quant[iq]);
12161 if (ctl->grid_stddev) {
12162 sprintf(varname, "%s_stddev", ctl->qnt_name[iq]);
12163 sprintf(longname, "%s (stddev)", ctl->qnt_longname[iq]);
12164 NC_DEF_VAR(varname, NC_DOUBLE, 4, dimid, longname, ctl->qnt_unit[iq],
12165 ctl->grid_nc_level, ctl->grid_nc_quant[iq]);
12166 }
12167 }
12168 /* End definitions... */
12169 NC(nc_enddef(ncid));
12170
12171 /* Write data... */
12172 NC_PUT_DOUBLE("time", &t, 0);
12173 NC_PUT_DOUBLE("lon", lon, 0);
12174 NC_PUT_DOUBLE("lat", lat, 0);
12175 NC_PUT_DOUBLE("z", z, 0);
12176 NC_PUT_DOUBLE("area", area, 0);
12177 NC_PUT_DOUBLE("dz", &dz, 0);
12178
12179 for (int ix = 0; ix < ctl->grid_nx; ix++)
12180 for (int iy = 0; iy < ctl->grid_ny; iy++)
12181 for (int iz = 0; iz < ctl->grid_nz; iz++)
12182 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
12183 cd[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
12184 NC_PUT_DOUBLE("cd", help, 0);
12185
12186 for (int ix = 0; ix < ctl->grid_nx; ix++)
12187 for (int iy = 0; iy < ctl->grid_ny; iy++)
12188 for (int iz = 0; iz < ctl->grid_nz; iz++)
12189 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
12190 vmr_impl[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
12191 NC_PUT_DOUBLE("vmr_impl", help, 0);
12192
12193 for (int ix = 0; ix < ctl->grid_nx; ix++)
12194 for (int iy = 0; iy < ctl->grid_ny; iy++)
12195 for (int iz = 0; iz < ctl->grid_nz; iz++)
12196 help2[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
12197 np[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
12198 NC_PUT_INT("np", help2, 0);
12199
12200 for (int iq = 0; iq < ctl->nq; iq++) {
12201 sprintf(varname, "%s_mean", ctl->qnt_name[iq]);
12202 for (int ix = 0; ix < ctl->grid_nx; ix++)
12203 for (int iy = 0; iy < ctl->grid_ny; iy++)
12204 for (int iz = 0; iz < ctl->grid_nz; iz++)
12205 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
12206 mean[iq][ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
12207 NC_PUT_DOUBLE(varname, help, 0);
12208 }
12209
12210 if (ctl->grid_stddev)
12211 for (int iq = 0; iq < ctl->nq; iq++) {
12212 sprintf(varname, "%s_stddev", ctl->qnt_name[iq]);
12213 for (int ix = 0; ix < ctl->grid_nx; ix++)
12214 for (int iy = 0; iy < ctl->grid_ny; iy++)
12215 for (int iz = 0; iz < ctl->grid_nz; iz++)
12216 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
12217 sigma[iq][ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
12218 NC_PUT_DOUBLE(varname, help, 0);
12219 }
12220
12221 /* Close file... */
12222 NC(nc_close(ncid));
12223
12224 /* Free... */
12225 free(help);
12226 free(help2);
12227}
#define NC_PUT_INT(varname, ptr, hyperslab)
Write integer data to a NetCDF variable.
Definition: mptrac.h:1312

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

12234 {
12235
12236 /* Create file... */
12237 FILE *out;
12238 if (!(out = fopen(filename, "w")))
12239 ERRMSG("Cannot create file!");
12240
12241 /* Write type of binary data... */
12242 FWRITE(&ctl->met_type, int,
12243 1,
12244 out);
12245
12246 /* Write version of binary data... */
12247 int version = 103;
12248 FWRITE(&version, int,
12249 1,
12250 out);
12251
12252 /* Write grid data... */
12253 FWRITE(&met->time, double,
12254 1,
12255 out);
12256 FWRITE(&met->nx, int,
12257 1,
12258 out);
12259 FWRITE(&met->ny, int,
12260 1,
12261 out);
12262 FWRITE(&met->np, int,
12263 1,
12264 out);
12265 FWRITE(met->lon, double,
12266 (size_t) met->nx,
12267 out);
12268 FWRITE(met->lat, double,
12269 (size_t) met->ny,
12270 out);
12271 FWRITE(met->p, double,
12272 (size_t) met->np,
12273 out);
12274
12275 /* Write surface data... */
12276 write_met_bin_2d(out, met, met->ps, "PS");
12277 write_met_bin_2d(out, met, met->ts, "TS");
12278 write_met_bin_2d(out, met, met->zs, "ZS");
12279 write_met_bin_2d(out, met, met->us, "US");
12280 write_met_bin_2d(out, met, met->vs, "VS");
12281 write_met_bin_2d(out, met, met->ess, "ESS");
12282 write_met_bin_2d(out, met, met->nss, "NSS");
12283 write_met_bin_2d(out, met, met->shf, "SHF");
12284 write_met_bin_2d(out, met, met->lsm, "LSM");
12285 write_met_bin_2d(out, met, met->sst, "SST");
12286 write_met_bin_2d(out, met, met->pbl, "PBL");
12287 write_met_bin_2d(out, met, met->pt, "PT");
12288 write_met_bin_2d(out, met, met->tt, "TT");
12289 write_met_bin_2d(out, met, met->zt, "ZT");
12290 write_met_bin_2d(out, met, met->h2ot, "H2OT");
12291 write_met_bin_2d(out, met, met->pct, "PCT");
12292 write_met_bin_2d(out, met, met->pcb, "PCB");
12293 write_met_bin_2d(out, met, met->cl, "CL");
12294 write_met_bin_2d(out, met, met->plcl, "PLCL");
12295 write_met_bin_2d(out, met, met->plfc, "PLFC");
12296 write_met_bin_2d(out, met, met->pel, "PEL");
12297 write_met_bin_2d(out, met, met->cape, "CAPE");
12298 write_met_bin_2d(out, met, met->cin, "CIN");
12299 write_met_bin_2d(out, met, met->o3c, "O3C");
12300
12301 /* Write level data... */
12302 write_met_bin_3d(out, ctl, met, met->z, "Z",
12303 ctl->met_comp_prec[0], ctl->met_comp_tol[0]);
12304 write_met_bin_3d(out, ctl, met, met->t, "T",
12305 ctl->met_comp_prec[1], ctl->met_comp_tol[1]);
12306 write_met_bin_3d(out, ctl, met, met->u, "U",
12307 ctl->met_comp_prec[2], ctl->met_comp_tol[2]);
12308 write_met_bin_3d(out, ctl, met, met->v, "V",
12309 ctl->met_comp_prec[3], ctl->met_comp_tol[3]);
12310 write_met_bin_3d(out, ctl, met, met->w, "W",
12311 ctl->met_comp_prec[4], ctl->met_comp_tol[4]);
12312 write_met_bin_3d(out, ctl, met, met->pv, "PV",
12313 ctl->met_comp_prec[5], ctl->met_comp_tol[5]);
12314 write_met_bin_3d(out, ctl, met, met->h2o, "H2O",
12315 ctl->met_comp_prec[6], ctl->met_comp_tol[6]);
12316 write_met_bin_3d(out, ctl, met, met->o3, "O3",
12317 ctl->met_comp_prec[7], ctl->met_comp_tol[7]);
12318 write_met_bin_3d(out, ctl, met, met->lwc, "LWC",
12319 ctl->met_comp_prec[8], ctl->met_comp_tol[8]);
12320 write_met_bin_3d(out, ctl, met, met->rwc, "RWC",
12321 ctl->met_comp_prec[9], ctl->met_comp_tol[9]);
12322 write_met_bin_3d(out, ctl, met, met->iwc, "IWC",
12323 ctl->met_comp_prec[10], ctl->met_comp_tol[10]);
12324 write_met_bin_3d(out, ctl, met, met->swc, "SWC",
12325 ctl->met_comp_prec[11], ctl->met_comp_tol[11]);
12326 write_met_bin_3d(out, ctl, met, met->cc, "CC",
12327 ctl->met_comp_prec[12], ctl->met_comp_tol[12]);
12328 if (METVAR != 13)
12329 ERRMSG("Number of meteo variables doesn't match!");
12330
12331 /* Write final flag... */
12332 int final = 999;
12333 FWRITE(&final, int,
12334 1,
12335 out);
12336
12337 /* Close file... */
12338 fclose(out);
12339}
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:12372
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:12343
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 12343 of file mptrac.c.

12347 {
12348
12349 float *help;
12350
12351 /* Allocate... */
12352 ALLOC(help, float,
12353 EX * EY);
12354
12355 /* Copy data... */
12356 for (int ix = 0; ix < met->nx; ix++)
12357 for (int iy = 0; iy < met->ny; iy++)
12358 help[ARRAY_2D(ix, iy, met->ny)] = var[ix][iy];
12359
12360 /* Write uncompressed data... */
12361 LOG(2, "Write 2-D variable: %s (uncompressed)", varname);
12362 FWRITE(help, float,
12363 (size_t) (met->nx * met->ny),
12364 out);
12365
12366 /* Free... */
12367 free(help);
12368}

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

12379 {
12380
12381 float *help;
12382
12383 /* Allocate... */
12384 ALLOC(help, float,
12385 EX * EY * EP);
12386
12387 /* Copy data... */
12388#pragma omp parallel for default(shared) collapse(2)
12389 for (int ix = 0; ix < met->nx; ix++)
12390 for (int iy = 0; iy < met->ny; iy++)
12391 for (int ip = 0; ip < met->np; ip++)
12392 help[ARRAY_3D(ix, iy, met->ny, ip, met->np)] = var[ix][iy][ip];
12393
12394 /* Write uncompressed data... */
12395 if (ctl->met_type == 1) {
12396 LOG(2, "Write 3-D variable: %s (uncompressed)", varname);
12397 FWRITE(help, float,
12398 (size_t) (met->nx * met->ny * met->np),
12399 out);
12400 }
12401
12402 /* Write packed data... */
12403 else if (ctl->met_type == 2)
12404 compress_pck(varname, help, (size_t) (met->ny * met->nx),
12405 (size_t) met->np, 0, out);
12406
12407 /* Write ZFP data... */
12408#ifdef ZFP
12409 else if (ctl->met_type == 3) {
12410 FWRITE(&precision, int,
12411 1,
12412 out);
12413 FWRITE(&tolerance, double,
12414 1,
12415 out);
12416 compress_zfp(varname, help, met->np, met->ny, met->nx, precision,
12417 tolerance, 0, out);
12418 }
12419#endif
12420
12421 /* Write zstd data... */
12422#ifdef ZSTD
12423 else if (ctl->met_type == 4)
12424 compress_zstd(varname, help, (size_t) (met->np * met->ny * met->nx), 0,
12425 ctl->met_zstd_level, out);
12426#endif
12427
12428 /* Write cmultiscale data... */
12429#ifdef CMS
12430 else if (ctl->met_type == 5) {
12431 compress_cms(ctl, varname, help, (size_t) met->nx, (size_t) met->ny,
12432 (size_t) met->np, 0, out);
12433 }
12434#endif
12435
12436 /* Write SZ3 data... */
12437#ifdef SZ3
12438 else if (ctl->met_type == 7) {
12439 FWRITE(&precision, int,
12440 1,
12441 out);
12442 FWRITE(&tolerance, double,
12443 1,
12444 out);
12445 compress_sz3(varname, help, met->np, met->ny, met->nx, precision,
12446 tolerance, 0, out);
12447 }
12448#endif
12449
12450 /* Unknown method... */
12451 else {
12452 ERRMSG("MET_TYPE not supported!");
12453 LOG(3, "%d %g", precision, tolerance);
12454 }
12455
12456 /* Free... */
12457 free(help);
12458}
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 12462 of file mptrac.c.

12465 {
12466
12467 /* Create file... */
12468 int ncid, varid;
12469 size_t start[4], count[4];
12470 nc_create(filename, NC_NETCDF4, &ncid);
12471
12472 /* Define dimensions... */
12473 int tid, lonid, latid, levid;
12474 NC(nc_def_dim(ncid, "time", 1, &tid));
12475 NC(nc_def_dim(ncid, "lon", (size_t) met->nx, &lonid));
12476 NC(nc_def_dim(ncid, "lat", (size_t) met->ny, &latid));
12477 NC(nc_def_dim(ncid, "lev", (size_t) met->np, &levid));
12478
12479 /* Define grid... */
12480 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "time",
12481 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12482 NC_DEF_VAR("lon", NC_DOUBLE, 1, &lonid, "longitude", "degrees_east", 0, 0);
12483 NC_DEF_VAR("lat", NC_DOUBLE, 1, &latid, "latitude", "degrees_north", 0, 0);
12484 NC_DEF_VAR("lev", NC_DOUBLE, 1, &levid, "pressure", "Pa", 0, 0);
12485
12486 /* Define surface variables... */
12487 int dimid2[2] = { latid, lonid };
12488 NC_DEF_VAR("sp", NC_FLOAT, 2, dimid2, "Surface pressure", "Pa",
12489 ctl->met_nc_level, 0);
12490 NC_DEF_VAR("z", NC_FLOAT, 2, dimid2, "Geopotential", "m**2 s**-2",
12491 ctl->met_nc_level, 0);
12492 NC_DEF_VAR("t2m", NC_FLOAT, 2, dimid2, "2 metre temperature", "K",
12493 ctl->met_nc_level, 0);
12494 NC_DEF_VAR("u10m", NC_FLOAT, 2, dimid2, "10 metre U wind component",
12495 "m s**-1", ctl->met_nc_level, 0);
12496 NC_DEF_VAR("v10m", NC_FLOAT, 2, dimid2, "10 metre V wind component",
12497 "m s**-1", ctl->met_nc_level, 0);
12498 NC_DEF_VAR("iews", NC_FLOAT, 2, dimid2,
12499 "Instantaneous eastward turbulent surface stress", "N m**-2",
12500 ctl->met_nc_level, 0);
12501 NC_DEF_VAR("inss", NC_FLOAT, 2, dimid2,
12502 "Instantaneous northward turbulent surface stress", "N m**-2",
12503 ctl->met_nc_level, 0);
12504 NC_DEF_VAR("ishf", NC_FLOAT, 2, dimid2,
12505 "Instantaneous surface sensible heat flux", "W m**-1",
12506 ctl->met_nc_level, 0);
12507 NC_DEF_VAR("lsm", NC_FLOAT, 2, dimid2, "Land/sea mask", "-",
12508 ctl->met_nc_level, 0);
12509 NC_DEF_VAR("sstk", NC_FLOAT, 2, dimid2, "Sea surface temperature", "K",
12510 ctl->met_nc_level, 0);
12511 NC_DEF_VAR("blp", NC_FLOAT, 2, dimid2, "Boundary layer pressure", "Pa",
12512 ctl->met_nc_level, 0);
12513 NC_DEF_VAR("pt", NC_FLOAT, 2, dimid2, "Tropopause pressure", "Pa",
12514 ctl->met_nc_level, 0);
12515 NC_DEF_VAR("tt", NC_FLOAT, 2, dimid2, "Tropopause temperature", "K",
12516 ctl->met_nc_level, 0);
12517 NC_DEF_VAR("zt", NC_FLOAT, 2, dimid2, "Tropopause height", "m",
12518 ctl->met_nc_level, 0);
12519 NC_DEF_VAR("h2ot", NC_FLOAT, 2, dimid2, "Tropopause water vapor", "ppv",
12520 ctl->met_nc_level, 0);
12521 NC_DEF_VAR("pct", NC_FLOAT, 2, dimid2, "Cloud top pressure", "Pa",
12522 ctl->met_nc_level, 0);
12523 NC_DEF_VAR("pcb", NC_FLOAT, 2, dimid2, "Cloud bottom pressure", "Pa",
12524 ctl->met_nc_level, 0);
12525 NC_DEF_VAR("cl", NC_FLOAT, 2, dimid2, "Total column cloud water",
12526 "kg m**2", ctl->met_nc_level, 0);
12527 NC_DEF_VAR("plcl", NC_FLOAT, 2, dimid2,
12528 "Pressure at lifted condensation level (LCL)", "Pa",
12529 ctl->met_nc_level, 0);
12530 NC_DEF_VAR("plfc", NC_FLOAT, 2, dimid2,
12531 "Pressure at level of free convection (LFC)", "Pa",
12532 ctl->met_nc_level, 0);
12533 NC_DEF_VAR("pel", NC_FLOAT, 2, dimid2,
12534 "Pressure at equilibrium level (EL)", "Pa", ctl->met_nc_level,
12535 0);
12536 NC_DEF_VAR("cape", NC_FLOAT, 2, dimid2,
12537 "Convective available potential energy", "J kg**-1",
12538 ctl->met_nc_level, 0);
12539 NC_DEF_VAR("cin", NC_FLOAT, 2, dimid2, "Convective inhibition",
12540 "J kg**-1", ctl->met_nc_level, 0);
12541 NC_DEF_VAR("o3c", NC_FLOAT, 2, dimid2, "Total column ozone", "DU",
12542 ctl->met_nc_level, 0);
12543
12544 /* Define level data... */
12545 int dimid3[3] = { levid, latid, lonid };
12546 NC_DEF_VAR("t", NC_FLOAT, 3, dimid3, "Temperature", "K",
12547 ctl->met_nc_level, ctl->met_nc_quant);
12548 NC_DEF_VAR("u", NC_FLOAT, 3, dimid3, "U velocity", "m s**-1",
12549 ctl->met_nc_level, ctl->met_nc_quant);
12550 NC_DEF_VAR("v", NC_FLOAT, 3, dimid3, "V velocity", "m s**-1",
12551 ctl->met_nc_level, ctl->met_nc_quant);
12552 NC_DEF_VAR("w", NC_FLOAT, 3, dimid3, "Vertical velocity", "Pa s**-1",
12553 ctl->met_nc_level, ctl->met_nc_quant);
12554 NC_DEF_VAR("q", NC_FLOAT, 3, dimid3, "Specific humidity", "kg kg**-1",
12555 ctl->met_nc_level, ctl->met_nc_quant);
12556 NC_DEF_VAR("o3", NC_FLOAT, 3, dimid3, "Ozone mass mixing ratio",
12557 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
12558 NC_DEF_VAR("clwc", NC_FLOAT, 3, dimid3, "Cloud liquid water content",
12559 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
12560 NC_DEF_VAR("crwc", NC_FLOAT, 3, dimid3, "Cloud rain water content",
12561 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
12562 NC_DEF_VAR("ciwc", NC_FLOAT, 3, dimid3, "Cloud ice water content",
12563 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
12564 NC_DEF_VAR("cswc", NC_FLOAT, 3, dimid3, "Cloud snow water content",
12565 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
12566 NC_DEF_VAR("cc", NC_FLOAT, 3, dimid3, "Cloud cover", "-",
12567 ctl->met_nc_level, ctl->met_nc_quant);
12568
12569 /* End definitions... */
12570 NC(nc_enddef(ncid));
12571
12572 /* Write grid data... */
12573 NC_PUT_DOUBLE("time", &met->time, 0);
12574 NC_PUT_DOUBLE("lon", met->lon, 0);
12575 NC_PUT_DOUBLE("lat", met->lat, 0);
12576 double phelp[EP];
12577 for (int ip = 0; ip < met->np; ip++)
12578 phelp[ip] = 100. * met->p[ip];
12579 NC_PUT_DOUBLE("lev", phelp, 0);
12580
12581 /* Write surface data... */
12582 write_met_nc_2d(ncid, "sp", met, met->ps, 100.0f);
12583 write_met_nc_2d(ncid, "z", met, met->zs, (float) (1000. * G0));
12584 write_met_nc_2d(ncid, "t2m", met, met->ts, 1.0f);
12585 write_met_nc_2d(ncid, "u10m", met, met->us, 1.0f);
12586 write_met_nc_2d(ncid, "v10m", met, met->vs, 1.0f);
12587 write_met_nc_2d(ncid, "iews", met, met->ess, 1.0f);
12588 write_met_nc_2d(ncid, "inss", met, met->nss, 1.0f);
12589 write_met_nc_2d(ncid, "ishf", met, met->shf, 1.0f);
12590 write_met_nc_2d(ncid, "lsm", met, met->lsm, 1.0f);
12591 write_met_nc_2d(ncid, "sstk", met, met->sst, 1.0f);
12592 write_met_nc_2d(ncid, "blp", met, met->pbl, 100.0f);
12593 write_met_nc_2d(ncid, "pt", met, met->pt, 100.0f);
12594 write_met_nc_2d(ncid, "tt", met, met->tt, 1.0f);
12595 write_met_nc_2d(ncid, "zt", met, met->zt, 1000.0f);
12596 write_met_nc_2d(ncid, "h2ot", met, met->h2ot, 1.0f);
12597 write_met_nc_2d(ncid, "pct", met, met->pct, 100.0f);
12598 write_met_nc_2d(ncid, "pcb", met, met->pcb, 100.0f);
12599 write_met_nc_2d(ncid, "cl", met, met->cl, 1.0f);
12600 write_met_nc_2d(ncid, "plcl", met, met->plcl, 100.0f);
12601 write_met_nc_2d(ncid, "plfc", met, met->plfc, 100.0f);
12602 write_met_nc_2d(ncid, "pel", met, met->pel, 100.0f);
12603 write_met_nc_2d(ncid, "cape", met, met->cape, 1.0f);
12604 write_met_nc_2d(ncid, "cin", met, met->cin, 1.0f);
12605 write_met_nc_2d(ncid, "o3c", met, met->o3c, 1.0f);
12606
12607 /* Write level data... */
12608 write_met_nc_3d(ncid, "t", met, met->t, 1.0f);
12609 write_met_nc_3d(ncid, "u", met, met->u, 1.0f);
12610 write_met_nc_3d(ncid, "v", met, met->v, 1.0f);
12611 write_met_nc_3d(ncid, "w", met, met->w, 100.0f);
12612 write_met_nc_3d(ncid, "q", met, met->h2o, (float) (MH2O / MA));
12613 write_met_nc_3d(ncid, "o3", met, met->o3, (float) (MO3 / MA));
12614 write_met_nc_3d(ncid, "clwc", met, met->lwc, 1.0f);
12615 write_met_nc_3d(ncid, "crwc", met, met->rwc, 1.0f);
12616 write_met_nc_3d(ncid, "ciwc", met, met->iwc, 1.0f);
12617 write_met_nc_3d(ncid, "cswc", met, met->swc, 1.0f);
12618 write_met_nc_3d(ncid, "cc", met, met->cc, 1.0f);
12619
12620 /* Close file... */
12621 NC(nc_close(ncid));
12622}
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:12626
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:12655
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 12626 of file mptrac.c.

12631 {
12632
12633 int varid;
12634 size_t start[4], count[4];
12635
12636 /* Allocate... */
12637 float *help;
12638 ALLOC(help, float,
12639 EX * EY);
12640
12641 /* Copy data... */
12642 for (int ix = 0; ix < met->nx; ix++)
12643 for (int iy = 0; iy < met->ny; iy++)
12644 help[ARRAY_2D(iy, ix, met->nx)] = scl * var[ix][iy];
12645
12646 /* Write data... */
12647 NC_PUT_FLOAT(varname, help, 0);
12648
12649 /* Free... */
12650 free(help);
12651}
#define NC_PUT_FLOAT(varname, ptr, hyperslab)
Write a float array to a NetCDF file.
Definition: mptrac.h:1289

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

12660 {
12661
12662 int varid;
12663 size_t start[4], count[4];
12664
12665 /* Allocate... */
12666 float *help;
12667 ALLOC(help, float,
12668 EX * EY * EP);
12669
12670 /* Copy data... */
12671 for (int ix = 0; ix < met->nx; ix++)
12672 for (int iy = 0; iy < met->ny; iy++)
12673 for (int ip = 0; ip < met->np; ip++)
12674 help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)] = scl * var[ix][iy][ip];
12675
12676 /* Write data... */
12677 NC_PUT_FLOAT(varname, help, 0);
12678
12679 /* Free... */
12680 free(help);
12681}

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

12691 {
12692
12693 static FILE *out;
12694
12695 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
12696 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
12697
12698 static int nobs, *obscount, ip, okay;
12699
12700 /* Set timer... */
12701 SELECT_TIMER("WRITE_PROF", "OUTPUT", NVTX_WRITE);
12702
12703 /* Init... */
12704 if (t == ctl->t_start) {
12705
12706 /* Check quantity index for mass... */
12707 if (ctl->qnt_m < 0)
12708 ERRMSG("Need quantity mass!");
12709
12710 /* Check molar mass... */
12711 if (ctl->molmass <= 0)
12712 ERRMSG("Specify molar mass!");
12713
12714 /* Allocate... */
12715 ALLOC(lon, double,
12716 ctl->prof_nx);
12717 ALLOC(lat, double,
12718 ctl->prof_ny);
12719 ALLOC(area, double,
12720 ctl->prof_ny);
12721 ALLOC(z, double,
12722 ctl->prof_nz);
12723 ALLOC(press, double,
12724 ctl->prof_nz);
12725 ALLOC(rt, double,
12726 NOBS);
12727 ALLOC(rz, double,
12728 NOBS);
12729 ALLOC(rlon, double,
12730 NOBS);
12731 ALLOC(rlat, double,
12732 NOBS);
12733 ALLOC(robs, double,
12734 NOBS);
12735
12736 /* Read observation data... */
12737 read_obs(ctl->prof_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
12738
12739 /* Create new output file... */
12740 LOG(1, "Write profile data: %s", filename);
12741 if (!(out = fopen(filename, "w")))
12742 ERRMSG("Cannot create file!");
12743
12744 /* Write header... */
12745 fprintf(out,
12746 "# $1 = time [s]\n"
12747 "# $2 = altitude [km]\n"
12748 "# $3 = longitude [deg]\n"
12749 "# $4 = latitude [deg]\n"
12750 "# $5 = pressure [hPa]\n"
12751 "# $6 = temperature [K]\n"
12752 "# $7 = volume mixing ratio [ppv]\n"
12753 "# $8 = H2O volume mixing ratio [ppv]\n"
12754 "# $9 = O3 volume mixing ratio [ppv]\n"
12755 "# $10 = observed BT index [K]\n"
12756 "# $11 = number of observations\n");
12757
12758 /* Set grid box size... */
12759 dz = (ctl->prof_z1 - ctl->prof_z0) / ctl->prof_nz;
12760 dlon = (ctl->prof_lon1 - ctl->prof_lon0) / ctl->prof_nx;
12761 dlat = (ctl->prof_lat1 - ctl->prof_lat0) / ctl->prof_ny;
12762
12763 /* Set vertical coordinates... */
12764 for (int iz = 0; iz < ctl->prof_nz; iz++) {
12765 z[iz] = ctl->prof_z0 + dz * (iz + 0.5);
12766 press[iz] = P(z[iz]);
12767 }
12768
12769 /* Set horizontal coordinates... */
12770 for (int ix = 0; ix < ctl->prof_nx; ix++)
12771 lon[ix] = ctl->prof_lon0 + dlon * (ix + 0.5);
12772 for (int iy = 0; iy < ctl->prof_ny; iy++) {
12773 lat[iy] = ctl->prof_lat0 + dlat * (iy + 0.5);
12774 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
12775 }
12776 }
12777
12778 /* Set time interval... */
12779 const double t0 = t - 0.5 * ctl->dt_mod;
12780 const double t1 = t + 0.5 * ctl->dt_mod;
12781
12782 /* Allocate... */
12783 ALLOC(mass, double,
12784 ctl->prof_nx * ctl->prof_ny * ctl->prof_nz);
12785 ALLOC(obsmean, double,
12786 ctl->prof_nx * ctl->prof_ny);
12787 ALLOC(obscount, int,
12788 ctl->prof_nx * ctl->prof_ny);
12789
12790 /* Loop over observations... */
12791 for (int i = 0; i < nobs; i++) {
12792
12793 /* Check time... */
12794 if (rt[i] < t0)
12795 continue;
12796 else if (rt[i] >= t1)
12797 break;
12798
12799 /* Check observation data... */
12800 if (!isfinite(robs[i]))
12801 continue;
12802
12803 /* Calculate indices... */
12804 const int ix = (int) ((rlon[i] - ctl->prof_lon0) / dlon);
12805 const int iy = (int) ((rlat[i] - ctl->prof_lat0) / dlat);
12806
12807 /* Check indices... */
12808 if (ix < 0 || ix >= ctl->prof_nx || iy < 0 || iy >= ctl->prof_ny)
12809 continue;
12810
12811 /* Get mean observation index... */
12812 const int idx = ARRAY_2D(ix, iy, ctl->prof_ny);
12813 obsmean[idx] += robs[i];
12814 obscount[idx]++;
12815 }
12816
12817 /* Analyze model data... */
12818 for (ip = 0; ip < atm->np; ip++) {
12819
12820 /* Check time... */
12821 if (atm->time[ip] < t0 || atm->time[ip] > t1)
12822 continue;
12823
12824 /* Get indices... */
12825 const int ix = (int) ((atm->lon[ip] - ctl->prof_lon0) / dlon);
12826 const int iy = (int) ((atm->lat[ip] - ctl->prof_lat0) / dlat);
12827 const int iz = (int) ((Z(atm->p[ip]) - ctl->prof_z0) / dz);
12828
12829 /* Check indices... */
12830 if (ix < 0 || ix >= ctl->prof_nx ||
12831 iy < 0 || iy >= ctl->prof_ny || iz < 0 || iz >= ctl->prof_nz)
12832 continue;
12833
12834 /* Get total mass in grid cell... */
12835 const int idx = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
12836 mass[idx] += atm->q[ctl->qnt_m][ip];
12837 }
12838
12839 /* Extract profiles... */
12840 for (int ix = 0; ix < ctl->prof_nx; ix++)
12841 for (int iy = 0; iy < ctl->prof_ny; iy++) {
12842 int idx2 = ARRAY_2D(ix, iy, ctl->prof_ny);
12843 if (obscount[idx2] > 0) {
12844
12845 /* Check profile... */
12846 okay = 0;
12847 for (int iz = 0; iz < ctl->prof_nz; iz++) {
12848 int idx3 = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
12849 if (mass[idx3] > 0) {
12850 okay = 1;
12851 break;
12852 }
12853 }
12854 if (!okay)
12855 continue;
12856
12857 /* Write output... */
12858 fprintf(out, "\n");
12859
12860 /* Loop over altitudes... */
12861 for (int iz = 0; iz < ctl->prof_nz; iz++) {
12862
12863 /* Get temperature, water vapor, and ozone... */
12865 intpol_met_time_3d(met0, met0->t, met1, met1->t, t, press[iz],
12866 lon[ix], lat[iy], &temp, ci, cw, 1);
12867 intpol_met_time_3d(met0, met0->h2o, met1, met1->h2o, t, press[iz],
12868 lon[ix], lat[iy], &h2o, ci, cw, 0);
12869 intpol_met_time_3d(met0, met0->o3, met1, met1->o3, t, press[iz],
12870 lon[ix], lat[iy], &o3, ci, cw, 0);
12871
12872 /* Calculate volume mixing ratio... */
12873 const int idx3 = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
12874 vmr = MA / ctl->molmass * mass[idx3]
12875 / (RHO(press[iz], temp) * area[iy] * dz * 1e9);
12876
12877 /* Write output... */
12878 fprintf(out, "%.2f %g %g %g %g %g %g %g %g %g %d\n",
12879 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
12880 obsmean[idx2] / obscount[idx2], obscount[idx2]);
12881 }
12882 }
12883 }
12884
12885 /* Free... */
12886 free(mass);
12887 free(obsmean);
12888 free(obscount);
12889
12890 /* Finalize... */
12891 if (t == ctl->t_stop) {
12892
12893 /* Close output file... */
12894 fclose(out);
12895
12896 /* Free... */
12897 free(lon);
12898 free(lat);
12899 free(area);
12900 free(z);
12901 free(press);
12902 free(rt);
12903 free(rz);
12904 free(rlon);
12905 free(rlat);
12906 free(robs);
12907 }
12908}
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 12912 of file mptrac.c.

12918 {
12919
12920 static FILE *out;
12921
12922 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[EP],
12923 kw[EP];
12924
12925 static int nobs, nk;
12926
12927 /* Set timer... */
12928 SELECT_TIMER("WRITE_SAMPLE", "OUTPUT", NVTX_WRITE);
12929
12930 /* Init... */
12931 if (t == ctl->t_start) {
12932
12933 /* Allocate... */
12934 ALLOC(rt, double,
12935 NOBS);
12936 ALLOC(rz, double,
12937 NOBS);
12938 ALLOC(rlon, double,
12939 NOBS);
12940 ALLOC(rlat, double,
12941 NOBS);
12942 ALLOC(robs, double,
12943 NOBS);
12944
12945 /* Read observation data... */
12946 read_obs(ctl->sample_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
12947
12948 /* Read kernel data... */
12949 if (ctl->sample_kernel[0] != '-')
12950 read_kernel(ctl->sample_kernel, kz, kw, &nk);
12951
12952 /* Create output file... */
12953 LOG(1, "Write sample data: %s", filename);
12954 if (!(out = fopen(filename, "w")))
12955 ERRMSG("Cannot create file!");
12956
12957 /* Write header... */
12958 fprintf(out,
12959 "# $1 = time [s]\n"
12960 "# $2 = altitude [km]\n"
12961 "# $3 = longitude [deg]\n"
12962 "# $4 = latitude [deg]\n"
12963 "# $5 = surface area [km^2]\n"
12964 "# $6 = layer depth [km]\n"
12965 "# $7 = number of particles [1]\n"
12966 "# $8 = column density [kg/m^2]\n"
12967 "# $9 = volume mixing ratio [ppv]\n"
12968 "# $10 = observed BT index [K]\n\n");
12969
12970 /* Set latitude range, squared radius, and area... */
12971 dlat = DY2DEG(ctl->sample_dx);
12972 rmax2 = SQR(ctl->sample_dx);
12973 area = M_PI * rmax2;
12974 }
12975
12976 /* Set time interval for output... */
12977 const double t0 = t - 0.5 * ctl->dt_mod;
12978 const double t1 = t + 0.5 * ctl->dt_mod;
12979
12980 /* Loop over observations... */
12981 for (int i = 0; i < nobs; i++) {
12982
12983 /* Check time... */
12984 if (rt[i] < t0)
12985 continue;
12986 else if (rt[i] >= t1)
12987 break;
12988
12989 /* Calculate Cartesian coordinates... */
12990 double x0[3];
12991 geo2cart(0, rlon[i], rlat[i], x0);
12992
12993 /* Set pressure range... */
12994 const double rp = P(rz[i]);
12995 const double ptop = P(rz[i] + ctl->sample_dz);
12996 const double pbot = P(rz[i] - ctl->sample_dz);
12997
12998 /* Init... */
12999 double mass = 0;
13000 int np = 0;
13001
13002 /* Loop over air parcels... */
13003 //#pragma omp parallel for default(shared) reduction(+:mass,np)
13004 for (int ip = 0; ip < atm->np; ip++) {
13005
13006 /* Check time... */
13007 if (atm->time[ip] < t0 || atm->time[ip] > t1)
13008 continue;
13009
13010 /* Check latitude... */
13011 if (fabs(rlat[i] - atm->lat[ip]) > dlat)
13012 continue;
13013
13014 /* Check horizontal distance... */
13015 double x1[3];
13016 geo2cart(0, atm->lon[ip], atm->lat[ip], x1);
13017 if (DIST2(x0, x1) > rmax2)
13018 continue;
13019
13020 /* Check pressure... */
13021 if (ctl->sample_dz > 0)
13022 if (atm->p[ip] > pbot || atm->p[ip] < ptop)
13023 continue;
13024
13025 /* Add mass... */
13026 if (ctl->qnt_m >= 0)
13027 mass +=
13028 kernel_weight(kz, kw, nk, atm->p[ip]) * atm->q[ctl->qnt_m][ip];
13029 np++;
13030 }
13031
13032 /* Calculate column density... */
13033 const double cd = mass / (1e6 * area);
13034
13035 /* Calculate volume mixing ratio... */
13036 double vmr = 0;
13037 if (ctl->molmass > 0 && ctl->sample_dz > 0) {
13038 if (mass > 0) {
13039
13040 /* Get temperature... */
13041 double temp;
13043 intpol_met_time_3d(met0, met0->t, met1, met1->t, rt[i], rp,
13044 rlon[i], rlat[i], &temp, ci, cw, 1);
13045
13046 /* Calculate volume mixing ratio... */
13047 vmr = MA / ctl->molmass * cd / (RHO(rp, temp) * ctl->sample_dz * 1e3);
13048 }
13049 } else
13050 vmr = NAN;
13051
13052 /* Write output... */
13053 fprintf(out, "%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
13054 rlon[i], rlat[i], area, ctl->sample_dz, np, cd, vmr, robs[i]);
13055 }
13056
13057 /* Finalize...... */
13058 if (t == ctl->t_stop) {
13059
13060 /* Close output file... */
13061 fclose(out);
13062
13063 /* Free... */
13064 free(rt);
13065 free(rz);
13066 free(rlon);
13067 free(rlat);
13068 free(robs);
13069 }
13070}
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 13074 of file mptrac.c.

13078 {
13079
13080 static FILE *out;
13081
13082 static double rmax2, x0[3], x1[3];
13083
13084 /* Set timer... */
13085 SELECT_TIMER("WRITE_STATION", "OUTPUT", NVTX_WRITE);
13086
13087 /* Init... */
13088 if (t == ctl->t_start) {
13089
13090 /* Write info... */
13091 LOG(1, "Write station data: %s", filename);
13092
13093 /* Create new file... */
13094 if (!(out = fopen(filename, "w")))
13095 ERRMSG("Cannot create file!");
13096
13097 /* Write header... */
13098 fprintf(out,
13099 "# $1 = time [s]\n"
13100 "# $2 = altitude [km]\n"
13101 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
13102 for (int iq = 0; iq < ctl->nq; iq++)
13103 fprintf(out, "# $%i = %s [%s]\n", (iq + 5),
13104 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
13105 fprintf(out, "\n");
13106
13107 /* Set geolocation and search radius... */
13108 geo2cart(0, ctl->stat_lon, ctl->stat_lat, x0);
13109 rmax2 = SQR(ctl->stat_r);
13110 }
13111
13112 /* Set time interval for output... */
13113 const double t0 = t - 0.5 * ctl->dt_mod;
13114 const double t1 = t + 0.5 * ctl->dt_mod;
13115
13116 /* Loop over air parcels... */
13117 for (int ip = 0; ip < atm->np; ip++) {
13118
13119 /* Check time... */
13120 if (atm->time[ip] < t0 || atm->time[ip] > t1)
13121 continue;
13122
13123 /* Check time range for station output... */
13124 if (atm->time[ip] < ctl->stat_t0 || atm->time[ip] > ctl->stat_t1)
13125 continue;
13126
13127 /* Check station flag... */
13128 if (ctl->qnt_stat >= 0)
13129 if ((int) atm->q[ctl->qnt_stat][ip])
13130 continue;
13131
13132 /* Get Cartesian coordinates... */
13133 geo2cart(0, atm->lon[ip], atm->lat[ip], x1);
13134
13135 /* Check horizontal distance... */
13136 if (DIST2(x0, x1) > rmax2)
13137 continue;
13138
13139 /* Set station flag... */
13140 if (ctl->qnt_stat >= 0)
13141 atm->q[ctl->qnt_stat][ip] = 1;
13142
13143 /* Write data... */
13144 fprintf(out, "%.2f %g %g %g",
13145 atm->time[ip], Z(atm->p[ip]), atm->lon[ip], atm->lat[ip]);
13146 for (int iq = 0; iq < ctl->nq; iq++) {
13147 fprintf(out, " ");
13148 fprintf(out, ctl->qnt_format[iq], atm->q[iq][ip]);
13149 }
13150 fprintf(out, "\n");
13151 }
13152
13153 /* Close file... */
13154 if (t == ctl->t_stop)
13155 fclose(out);
13156}
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 13160 of file mptrac.c.

13164 {
13165
13166 FILE *out;
13167
13168 /* Set timer... */
13169 SELECT_TIMER("WRITE_VTK", "OUTPUT", NVTX_WRITE);
13170
13171 /* Write info... */
13172 LOG(1, "Write VTK data: %s", filename);
13173
13174 /* Set time interval for output... */
13175 const double t0 = t - 0.5 * ctl->dt_mod;
13176 const double t1 = t + 0.5 * ctl->dt_mod;
13177
13178 /* Create file... */
13179 if (!(out = fopen(filename, "w")))
13180 ERRMSG("Cannot create file!");
13181
13182 /* Count data points... */
13183 int np = 0;
13184 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
13185 if (atm->time[ip] < t0 || atm->time[ip] > t1)
13186 continue;
13187 np++;
13188 }
13189
13190 /* Write header... */
13191 fprintf(out,
13192 "# vtk DataFile Version 3.0\n"
13193 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
13194
13195 /* Write point coordinates... */
13196 fprintf(out, "POINTS %d float\n", np);
13197 if (ctl->vtk_sphere) {
13198 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
13199 if (atm->time[ip] < t0 || atm->time[ip] > t1)
13200 continue;
13201 const double radius = (RE + Z(atm->p[ip]) * ctl->vtk_scale
13202 + ctl->vtk_offset) / RE;
13203 const double coslat = cos(DEG2RAD(atm->lat[ip]));
13204 const double x = radius * coslat * cos(DEG2RAD(atm->lon[ip]));
13205 const double y = radius * coslat * sin(DEG2RAD(atm->lon[ip]));
13206 const double z = radius * sin(DEG2RAD(atm->lat[ip]));
13207 fprintf(out, "%g %g %g\n", x, y, z);
13208 }
13209 } else
13210 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
13211 if (atm->time[ip] < t0 || atm->time[ip] > t1)
13212 continue;
13213 fprintf(out, "%g %g %g\n", atm->lon[ip], atm->lat[ip],
13214 Z(atm->p[ip]) * ctl->vtk_scale + ctl->vtk_offset);
13215 }
13216
13217 /* Write point data... */
13218 fprintf(out, "POINT_DATA %d\n", np);
13219 for (int iq = 0; iq < ctl->nq; iq++) {
13220 fprintf(out, "SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
13221 ctl->qnt_name[iq]);
13222 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
13223 if (atm->time[ip] < t0 || atm->time[ip] > t1)
13224 continue;
13225 fprintf(out, "%g\n", atm->q[iq][ip]);
13226 }
13227 }
13228
13229 /* Close file... */
13230 fclose(out);
13231}

◆ 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