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

MPTRAC library declarations. More...

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

Go to the source code of this file.

Data Structures

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

Macros

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

Functions

void thrustSortWrapper (double *__restrict__ c, int n, int *__restrict__ index)
 Wrapper to Thrust sorting function. More...
 
void broadcast_large_data (void *data, size_t N)
 Broadcasts large data across all processes in an MPI communicator. More...
 
void cart2geo (const double *x, double *z, double *lon, double *lat)
 Converts Cartesian coordinates to geographic coordinates. More...
 
double clim_oh (const ctl_t *ctl, const clim_t *clim, const double t, const double lon, const double lat, const double p)
 Calculates the hydroxyl radical (OH) concentration from climatology data, with an optional diurnal correction based on solar zenith angle. More...
 
void clim_oh_diurnal_correction (const ctl_t *ctl, clim_t *clim)
 Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data. More...
 
double clim_photo (const double rate[CP][CSZA][CO3], const clim_photo_t *photo, const double p, const double sza, const double o3c)
 Calculates the photolysis rate for a given set of atmospheric conditions. More...
 
double clim_tropo (const clim_t *clim, const double t, const double lat)
 Calculates the tropopause pressure based on climatological data. More...
 
void clim_tropo_init (clim_t *clim)
 Initializes the tropopause data in the climatology structure. More...
 
double clim_ts (const clim_ts_t *ts, const double t)
 Interpolates a time series of climatological variables. More...
 
double clim_zm (const clim_zm_t *zm, const double t, const double lat, const double p)
 Interpolates monthly mean zonal mean climatological variables. More...
 
void compress_cms (const ctl_t *ctl, const char *varname, float *array, const size_t nx, const size_t ny, const size_t np, const int decompress, FILE *inout)
 Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm. More...
 
void compress_pck (const char *varname, float *array, const size_t nxy, const size_t nz, const int decompress, FILE *inout)
 Compresses or decompresses a 3D array of floats. More...
 
void compress_zfp (const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
 Compresses or decompresses a 3D array of floats using the ZFP library. More...
 
void compress_zstd (const char *varname, float *array, const size_t n, const int decompress, FILE *inout)
 Compresses or decompresses an array of floats using the Zstandard (ZSTD) library. More...
 
void day2doy (const int year, const int mon, const int day, int *doy)
 Get day of year from date. More...
 
void doy2day (const int year, const int doy, int *mon, int *day)
 Converts a given day of the year (DOY) to a date (month and day). More...
 
void fft_help (double *fcReal, double *fcImag, const int n)
 Computes the Fast Fourier Transform (FFT) of a complex sequence. More...
 
void geo2cart (const double z, const double lon, const double lat, double *x)
 Converts geographic coordinates (longitude, latitude, altitude) to Cartesian coordinates. More...
 
void get_met (ctl_t *ctl, clim_t *clim, const double t, met_t **met0, met_t **met1)
 Retrieves meteorological data for the specified time. More...
 
void get_met_help (const ctl_t *ctl, const double t, const int direct, const char *metbase, const double dt_met, char *filename)
 Generates a formatted filename for meteorological data files based on the input parameters. More...
 
void get_met_replace (char *orig, char *search, char *repl)
 Replaces occurrences of a substring in a string with another substring. More...
 
void get_tropo (const int met_tropo, ctl_t *ctl, clim_t *clim, met_t *met, const double *lons, const int nx, const double *lats, const int ny, double *pt, double *zt, double *tt, double *qt, double *o3t, double *ps, double *zs)
 Calculate tropopause data. More...
 
void intpol_met_4d_coord (const met_t *met0, float height0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float height1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double height, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
 Interpolates meteorological variables to a given position and time. More...
 
void intpol_met_space_3d (const met_t *met, float array[EX][EY][EP], const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
 Interpolates meteorological variables in 3D space. More...
 
void intpol_met_space_3d_ml (const met_t *met, float array[EX][EY][EP], const double p, const double lon, const double lat, double *var)
 Interpolates a meteorological variable in 3D space (longitude, latitude, pressure). 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 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)
 Interpolates a meteorological variable in time and 3D space (longitude, latitude, pressure). More...
 
void intpol_met_time_2d (const met_t *met0, float array0[EX][EY], const met_t *met1, float array1[EX][EY], const double ts, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
 Interpolates meteorological data in 2D space and time. More...
 
void intpol_tropo_3d (const double time0, float array0[EX][EY], const double time1, float array1[EX][EY], const double lons[EX], const double lats[EY], const int nlon, const int nlat, const double time, const double lon, const double lat, const int method, double *var, double *sigma)
 Interpolates tropopause data in 3D (latitude, longitude, and time). More...
 
void jsec2time (const double jsec, int *year, int *mon, int *day, int *hour, int *min, int *sec, double *remain)
 Converts Julian seconds to calendar date and time components. More...
 
double kernel_weight (const double kz[EP], const double kw[EP], const int nk, const double p)
 Calculates the kernel weight based on altitude and given kernel data. More...
 
double lapse_rate (const double t, const double h2o)
 Calculates the moist adiabatic lapse rate in Kelvin per kilometer. More...
 
void level_definitions (ctl_t *ctl)
 Defines pressure levels for meteorological data. More...
 
int locate_irr (const double *xx, const int n, const double x)
 Locate the index of the interval containing a given value in a sorted array. More...
 
int locate_irr_float (const float *xx, const int n, const double x, const int ig)
 Locate the index of the interval containing a given value in an irregularly spaced array. More...
 
int locate_reg (const double *xx, const int n, const double x)
 Locate the index of the interval containing a given value in a regular grid. More...
 
void locate_vert (float profiles[EX][EY][EP], const int np, const int lon_ap_ind, const int lat_ap_ind, const double alt_ap, int *ind)
 Locate the four vertical indizes of a box for a given height value. More...
 
void module_advect (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Performs the advection of atmospheric particles using meteorological data. More...
 
void module_advect_init (const ctl_t *ctl, 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_chemgrid (const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double t)
 Calculate grid data for chemistry modules. More...
 
void module_chem_init (const ctl_t *ctl, const 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_diffusion_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_diffusion_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_diffusion_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_deposition (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Simulate dry deposition of atmospheric particles. More...
 
void module_h2o2_chem (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Perform chemical reactions involving H2O2 within cloud particles. More...
 
void module_isosurf_init (const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Initialize the isosurface module based on atmospheric data. More...
 
void module_isosurf (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Apply the isosurface module to adjust atmospheric properties. More...
 
void module_kpp_chem (ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 KPP chemistry module. More...
 
void module_meteo (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Update atmospheric properties using meteorological data. More...
 
void module_mixing (const ctl_t *ctl, const clim_t *clim, atm_t *atm, const double t)
 Update atmospheric properties through interparcel mixing. More...
 
void module_mixing_help (const ctl_t *ctl, const clim_t *clim, atm_t *atm, const int *ixs, const int *iys, const int *izs, const int qnt_idx)
 Perform interparcel mixing for a specific quantity. More...
 
void module_oh_chem (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Perform hydroxyl chemistry calculations for atmospheric particles. More...
 
void module_position (const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Update the positions and pressure levels of atmospheric particles. More...
 
void module_rng_init (const int ntask)
 Initialize random number generators for parallel tasks. More...
 
void module_rng (const ctl_t *ctl, double *rs, const size_t n, const int method)
 Generate random numbers using various methods and distributions. More...
 
void module_sedi (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Simulate sedimentation of particles in the atmosphere. More...
 
void module_sort (const ctl_t *ctl, met_t *met0, atm_t *atm)
 Sort particles according to box index. More...
 
void module_sort_help (double *a, const int *p, const int np)
 Reorder an array based on a given permutation. More...
 
void module_timesteps (const ctl_t *ctl, cache_t *cache, met_t *met0, atm_t *atm, const double t)
 Calculate time steps for air parcels based on specified conditions. More...
 
void module_timesteps_init (ctl_t *ctl, const atm_t *atm)
 Initialize start time and time interval for time-stepping. More...
 
void module_tracer_chem (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Simulate chemical reactions involving long-lived atmospheric tracers. More...
 
void module_wet_deposition (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_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...
 
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 (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads air parcel data from a specified file into the given atmospheric structure. More...
 
int read_atm_asc (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads air parcel data from an ASCII file and populates the given atmospheric structure. More...
 
int read_atm_bin (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads air parcel data from a binary file and populates the given atmospheric structure. More...
 
int read_atm_clams (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads air parcel data from a CLaMS netCDF file and populates the given atmospheric structure. More...
 
int read_atm_nc (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads air parcel data from a generic netCDF file and populates the given atmospheric structure. More...
 
void read_clim (const ctl_t *ctl, clim_t *clim)
 Reads various climatological data and populates the given climatology 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_ctl (const char *filename, int argc, char *argv[], ctl_t *ctl)
 Reads control parameters from a configuration 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 (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...
 
int read_met_bin (const char *filename, const ctl_t *ctl, met_t *met)
 Reads meteorological data from a binary file. More...
 
void read_met_bin_2d (FILE *in, const met_t *met, float var[EX][EY], const char *varname)
 Reads a 2-dimensional meteorological variable from a binary file and stores it in the provided array. More...
 
void read_met_bin_3d (FILE *in, const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname, const float bound_min, const float bound_max)
 Reads 3D meteorological data from a binary file, potentially using different compression methods. More...
 
void read_met_cape (const ctl_t *ctl, const clim_t *clim, met_t *met)
 Calculates Convective Available Potential Energy (CAPE) for each grid point. More...
 
void read_met_cloud (met_t *met)
 Calculates cloud-related variables for each grid point. More...
 
void read_met_detrend (const ctl_t *ctl, met_t *met)
 Detrends meteorological data. More...
 
void read_met_extrapolate (met_t *met)
 Extrapolates meteorological data. More...
 
void read_met_geopot (const ctl_t *ctl, met_t *met)
 Calculates geopotential heights from meteorological data. More...
 
void read_met_grid (const char *filename, const int ncid, const ctl_t *ctl, met_t *met)
 Reads meteorological grid information from a NetCDF file. More...
 
void read_met_levels (const int ncid, const ctl_t *ctl, met_t *met)
 Reads meteorological variables at different vertical levels from a NetCDF file. More...
 
void read_met_ml2pl (const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname)
 Interpolates meteorological data to specified pressure levels. More...
 
void read_met_monotonize (met_t *met)
 Makes zeta and pressure profiles monotone. More...
 
int read_met_nc (const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met)
 Reads meteorological data from a NetCDF file and processes it. More...
 
int read_met_nc_2d (const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const char *varname5, const char *varname6, const ctl_t *ctl, const met_t *met, float dest[EX][EY], const float scl, const int init)
 Reads a 2-dimensional meteorological variable from a NetCDF file. More...
 
int read_met_nc_3d (const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const ctl_t *ctl, const met_t *met, float dest[EX][EY][EP], const float scl)
 Reads a 3-dimensional meteorological variable from a NetCDF file. More...
 
void read_met_pbl (const ctl_t *ctl, met_t *met)
 Computes the planetary boundary layer (PBL) pressure based on meteorological data. More...
 
void read_met_periodic (met_t *met)
 Applies periodic boundary conditions to meteorological data along longitudinal axis. More...
 
void read_met_polar_winds (met_t *met)
 Applies a fix for polar winds in meteorological data. More...
 
void read_met_pv (met_t *met)
 Calculates potential vorticity (PV) from meteorological data. More...
 
void read_met_ozone (met_t *met)
 Calculates the total column ozone from meteorological ozone data. More...
 
void read_met_sample (const ctl_t *ctl, met_t *met)
 Downsamples meteorological data based on specified parameters. More...
 
void read_met_surface (const int ncid, const ctl_t *ctl, met_t *met)
 Reads surface meteorological data from a netCDF file and stores it in the meteorological data structure. More...
 
void read_met_tropo (const ctl_t *ctl, const clim_t *clim, met_t *met)
 Calculates the tropopause and related meteorological variables based on various methods and stores the results in the meteorological data structure. More...
 
void read_obs (const char *filename, const ctl_t *ctl, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
 Reads observation data from a file and stores it in arrays. More...
 
void read_obs_asc (const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
 Reads observation data from an ASCII file. More...
 
void read_obs_nc (const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
 Reads observation data from a NetCDF file. More...
 
double scan_ctl (const char *filename, int argc, char *argv[], const char *varname, const int arridx, const char *defvalue, char *value)
 Scans a control file or command-line arguments for a specified variable. More...
 
double sedi (const double p, const double T, const double rp, const double rhop)
 Calculates the sedimentation velocity of a particle in air. More...
 
void spline (const double *x, const double *y, const int n, const double *x2, double *y2, const int n2, const int method)
 Performs spline interpolation or linear interpolation. More...
 
float stddev (const float *data, const int n)
 Calculates the standard deviation of a set of data. More...
 
double sza_calc (const double sec, const double lon, const double lat)
 Calculates the solar zenith angle. More...
 
void time2jsec (const int year, const int mon, const int day, const int hour, const int min, const int sec, const double remain, double *jsec)
 Converts time components to seconds since January 1, 2000, 12:00:00 UTC. More...
 
void timer (const char *name, const char *group, const int output)
 Measures and reports elapsed time for named and grouped timers. More...
 
double time_from_filename (const char *filename, const int offset)
 Extracts and converts a timestamp from a filename to Julian seconds. More...
 
double tropo_weight (const clim_t *clim, const atm_t *atm, const int ip)
 Computes a weighting factor based on tropopause pressure. More...
 
void write_atm (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 write_atm_asc (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes air parcel data to an ASCII file or gnuplot. More...
 
void write_atm_bin (const char *filename, const ctl_t *ctl, const atm_t *atm)
 Writes air parcel data to a binary file. More...
 
void write_atm_clams (const char *filename, const ctl_t *ctl, const atm_t *atm)
 Writes air parcel data to a NetCDF file in the CLaMS format. More...
 
void write_atm_clams_traj (const char *dirname, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes CLaMS trajectory data to a NetCDF file. More...
 
void write_atm_nc (const char *filename, const ctl_t *ctl, const atm_t *atm)
 Writes air parcel data to a NetCDF file. More...
 
void write_csi (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes Critical Success Index (CSI) data to a file. More...
 
void write_ens (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes ensemble data to a file. More...
 
void write_grid (const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
 Writes grid data to a file in ASCII or netCDF format. More...
 
void write_grid_asc (const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
 Writes grid data to an ASCII file. More...
 
void write_grid_nc (const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
 Writes grid data to a NetCDF file. More...
 
void write_met (const char *filename, const ctl_t *ctl, met_t *met)
 Writes meteorological data to a file, supporting multiple formats and compression options. 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_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 write_prof (const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
 Writes profile data to a specified file. More...
 
void write_sample (const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
 Writes sample data to a specified file. More...
 
void write_station (const char *filename, const ctl_t *ctl, atm_t *atm, const double t)
 Writes station data to a specified file. More...
 
void write_vtk (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes VTK (Visualization Toolkit) data to a specified file. More...
 

Detailed Description

MPTRAC library declarations.

Definition in file mptrac.h.

Macro Definition Documentation

◆ AVO

#define AVO   6.02214076e23

Avogadro constant [1/mol].

Definition at line 157 of file mptrac.h.

◆ CPD

#define CPD   1003.5

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

Definition at line 162 of file mptrac.h.

◆ EPS

#define EPS   (MH2O / MA)

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

Definition at line 167 of file mptrac.h.

◆ G0

#define G0   9.80665

Standard gravity [m/s^2].

Definition at line 172 of file mptrac.h.

◆ H0

#define H0   7.0

Scale height [km].

Definition at line 177 of file mptrac.h.

◆ LV

#define LV   2501000.

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

Definition at line 182 of file mptrac.h.

◆ KARMAN

#define KARMAN   0.40

Karman's constant.

Definition at line 187 of file mptrac.h.

◆ KB

#define KB   1.3806504e-23

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

Definition at line 192 of file mptrac.h.

◆ MA

#define MA   28.9644

Molar mass of dry air [g/mol].

Definition at line 197 of file mptrac.h.

◆ MH2O

#define MH2O   18.01528

Molar mass of water vapor [g/mol].

Definition at line 202 of file mptrac.h.

◆ MO3

#define MO3   48.00

Molar mass of ozone [g/mol].

Definition at line 207 of file mptrac.h.

◆ P0

#define P0   1013.25

Standard pressure [hPa].

Definition at line 212 of file mptrac.h.

◆ RA

#define RA   (1e3 * RI / MA)

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

Definition at line 217 of file mptrac.h.

◆ RE

#define RE   6367.421

Mean radius of Earth [km].

Definition at line 222 of file mptrac.h.

◆ RI

#define RI   8.3144598

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

Definition at line 227 of file mptrac.h.

◆ T0

#define T0   273.15

Standard temperature [K].

Definition at line 232 of file mptrac.h.

◆ LEN

#define LEN   5000

Maximum length of ASCII data lines.

Definition at line 241 of file mptrac.h.

◆ NP

#define NP   10000000

Maximum number of atmospheric data points.

Definition at line 246 of file mptrac.h.

◆ NQ

#define NQ   15

Maximum number of quantities per data point.

Definition at line 251 of file mptrac.h.

◆ NCSI

#define NCSI   1000000

Maximum number of data points for CSI calculation.

Definition at line 256 of file mptrac.h.

◆ EP

#define EP   140

Maximum number of pressure levels for meteo data.

Definition at line 261 of file mptrac.h.

◆ EX

#define EX   1202

Maximum number of longitudes for meteo data.

Definition at line 266 of file mptrac.h.

◆ EY

#define EY   602

Maximum number of latitudes for meteo data.

Definition at line 271 of file mptrac.h.

◆ NENS

#define NENS   2000

Maximum number of data points for ensemble analysis.

Definition at line 276 of file mptrac.h.

◆ NOBS

#define NOBS   10000000

Maximum number of observation data points.

Definition at line 281 of file mptrac.h.

◆ NTHREADS

#define NTHREADS   512

Maximum number of OpenMP threads.

Definition at line 286 of file mptrac.h.

◆ CY

#define CY   250

Maximum number of latitudes for climatological data.

Definition at line 291 of file mptrac.h.

◆ CO3

#define CO3   30

Maximum number of total column ozone data for climatological data.

Definition at line 296 of file mptrac.h.

◆ CP

#define CP   70

Maximum number of pressure levels for climatological data.

Definition at line 301 of file mptrac.h.

◆ CSZA

#define CSZA   50

Maximum number of solar zenith angles for climatological data.

Definition at line 306 of file mptrac.h.

◆ CT

#define CT   12

Maximum number of time steps for climatological data.

Definition at line 311 of file mptrac.h.

◆ CTS

#define CTS   1000

Maximum number of data points of climatological time series.

Definition at line 316 of file mptrac.h.

◆ ALLOC

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

Allocate memory for a pointer with error handling.

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

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

Definition at line 349 of file mptrac.h.

◆ ARRAY_2D

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

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

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

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

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

Author
Lars Hoffmann

Definition at line 372 of file mptrac.h.

◆ ARRAY_3D

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

Compute the linear index of a 3D array element.

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

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

Definition at line 391 of file mptrac.h.

◆ ARRHENIUS

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

Calculate the Arrhenius rate constant.

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

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

where:

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

Definition at line 416 of file mptrac.h.

◆ DEG2DX

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

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

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

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

where:

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

Definition at line 440 of file mptrac.h.

◆ DEG2DY

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

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

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

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

where:

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

Definition at line 461 of file mptrac.h.

◆ DEG2RAD

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

Converts degrees to radians.

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

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

Definition at line 478 of file mptrac.h.

◆ DP2DZ

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

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

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

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

where:

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

Definition at line 503 of file mptrac.h.

◆ DX2DEG

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

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

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

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

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

Definition at line 525 of file mptrac.h.

◆ DY2DEG

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

Convert a distance in kilometers to degrees latitude.

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

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

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

Definition at line 543 of file mptrac.h.

◆ DZ2DP

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

Convert a change in altitude to a change in pressure.

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

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

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

Definition at line 562 of file mptrac.h.

◆ DIST

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

Calculate the distance between two points in Cartesian coordinates.

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

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

Definition at line 578 of file mptrac.h.

◆ DIST2

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

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

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

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

Definition at line 594 of file mptrac.h.

◆ DOTP

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

Calculate the dot product of two vectors.

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

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

Definition at line 610 of file mptrac.h.

◆ FMOD

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

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

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

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

Definition at line 629 of file mptrac.h.

◆ FREAD

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

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

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

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

Definition at line 647 of file mptrac.h.

◆ FWRITE

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

Write data from memory to a file stream.

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

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

Definition at line 667 of file mptrac.h.

◆ INTPOL_INIT

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

Initialize arrays for interpolation.

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

Author
Lars Hoffmann

Definition at line 682 of file mptrac.h.

◆ INTPOL_2D

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

Perform 2D interpolation for a meteorological variable.

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

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

Definition at line 696 of file mptrac.h.

◆ INTPOL_3D

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

Perform 3D interpolation for a meteorological variable.

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

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

Definition at line 713 of file mptrac.h.

◆ INTPOL_SPACE_ALL

#define INTPOL_SPACE_ALL (   p,
  lon,
  lat 
)

Interpolate multiple meteorological variables in space.

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

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

Definition at line 732 of file mptrac.h.

◆ INTPOL_TIME_ALL

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

Interpolate multiple meteorological variables in time.

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

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

Definition at line 786 of file mptrac.h.

◆ LAPSE

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

Calculate lapse rate.

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

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

Definition at line 840 of file mptrac.h.

◆ LIN

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

Linear interpolation.

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

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

Definition at line 859 of file mptrac.h.

◆ MAX

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

Macro to determine the maximum of two values.

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

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

Definition at line 886 of file mptrac.h.

◆ MET_HEADER

#define MET_HEADER

Write header for meteorological data file.

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

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

Definition at line 900 of file mptrac.h.

◆ MIN

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

Macro to determine the minimum of two values.

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

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

Definition at line 987 of file mptrac.h.

◆ MOLEC_DENS

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

Calculate the density of a gas molecule.

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

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

Definition at line 1002 of file mptrac.h.

◆ NC

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

Execute a NetCDF command and check for errors.

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

Parameters
cmdNetCDF command to execute.
Author
Lars Hoffmann

Definition at line 1016 of file mptrac.h.

◆ NC_DEF_VAR

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

Define a NetCDF variable with attributes.

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

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

Definition at line 1045 of file mptrac.h.

◆ NC_GET_DOUBLE

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

Retrieve a double-precision variable from a NetCDF file.

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

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

Definition at line 1075 of file mptrac.h.

◆ NC_INQ_DIM

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

Inquire the length of a dimension in a NetCDF file.

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

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

Definition at line 1103 of file mptrac.h.

◆ NC_PUT_DOUBLE

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

Write double precision data to a NetCDF variable.

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

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

Definition at line 1126 of file mptrac.h.

◆ NC_PUT_FLOAT

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

Write a float array to a NetCDF file.

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

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

Definition at line 1150 of file mptrac.h.

◆ NC_PUT_INT

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

Write integer data to a NetCDF variable.

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

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

Definition at line 1173 of file mptrac.h.

◆ NC_PUT_ATT

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

Add a text attribute to a NetCDF variable.

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

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

Definition at line 1195 of file mptrac.h.

◆ NC_PUT_ATT_GLOBAL

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

Add a global text attribute to a NetCDF file.

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

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

Definition at line 1212 of file mptrac.h.

◆ NN

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

Perform nearest-neighbor interpolation.

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

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

Definition at line 1232 of file mptrac.h.

◆ NORM

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

Compute the norm (magnitude) of a vector.

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

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

Definition at line 1247 of file mptrac.h.

◆ PARTICLE_LOOP

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

Loop over particle indices with OpenACC acceleration.

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

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

Definition at line 1274 of file mptrac.h.

◆ P

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

Compute pressure at given altitude.

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

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

The barometric formula used for this calculation is:

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

where:

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

Definition at line 1304 of file mptrac.h.

◆ PSAT

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

Compute saturation pressure over water.

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

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

The saturation pressure over water is calculated using the formula:

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

where:

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

Definition at line 1328 of file mptrac.h.

◆ PSICE

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

Compute saturation pressure over ice (WMO, 2018).

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

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

The saturation pressure over ice is calculated using the formula:

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

where:

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

Definition at line 1352 of file mptrac.h.

◆ PW

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

Calculate partial water vapor pressure.

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

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

The partial water vapor pressure is calculated using the formula:

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

where:

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

Definition at line 1379 of file mptrac.h.

◆ RAD2DEG

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

Converts radians to degrees.

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

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

Definition at line 1396 of file mptrac.h.

◆ RH

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

Compute relative humidity over water.

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

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

The relative humidity over water is calculated using the formula:

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

where:

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

Definition at line 1426 of file mptrac.h.

◆ RHICE

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

Compute relative humidity over ice.

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

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

The relative humidity over ice is calculated using the formula:

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

where:

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

Definition at line 1456 of file mptrac.h.

◆ RHO

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

Compute density of air.

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

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

The density of air is calculated using the formula:

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

where:

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

Definition at line 1481 of file mptrac.h.

◆ SET_ATM

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

Set atmospheric quantity value.

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

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

Definition at line 1500 of file mptrac.h.

◆ SET_QNT

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

Set atmospheric quantity index.

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

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

Definition at line 1523 of file mptrac.h.

◆ SH

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

Compute specific humidity from water vapor volume mixing ratio.

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

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

Definition at line 1544 of file mptrac.h.

◆ SQR

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

Compute the square of a value.

This macro computes the square of the input value.

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

Definition at line 1557 of file mptrac.h.

◆ SWAP

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

Swap two values.

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

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

Definition at line 1571 of file mptrac.h.

◆ TDEW

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

Calculate dew point temperature.

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

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

Formula:

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

where:

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

Definition at line 1595 of file mptrac.h.

◆ TICE

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

Calculate frost point temperature (WMO, 2018).

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

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

Formula:

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

where:

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

Definition at line 1620 of file mptrac.h.

◆ THETA

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

Compute potential temperature.

This macro calculates the potential temperature of the atmosphere.

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

Formula:

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

where:

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

Definition at line 1644 of file mptrac.h.

◆ THETAVIRT

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

Compute virtual potential temperature.

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

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

Formula:

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

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

where:

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

Definition at line 1673 of file mptrac.h.

◆ TOK

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

Get string tokens.

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

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

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

Author
Lars Hoffmann

Definition at line 1694 of file mptrac.h.

◆ TVIRT

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

Compute virtual temperature.

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

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

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

Note
EPS is typically defined as 0.622.
Author
Lars Hoffmann

Definition at line 1719 of file mptrac.h.

◆ Z

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

Convert pressure to altitude.

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

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

Formula:

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

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

Definition at line 1741 of file mptrac.h.

◆ ZDIFF

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

Calculate geopotential height difference.

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

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

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

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

Definition at line 1772 of file mptrac.h.

◆ ZETA

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

Calculate potential vorticity using the Zeta approximation.

This macro calculates the potential vorticity using the Zeta approximation, which is a function of pressure, surface pressure, and temperature.

Parameters
psSurface pressure in hPa.
pPressure at the given level in hPa.
tTemperature at the given level in Kelvin (K).
Returns
The potential vorticity.

Formula: The potential vorticity (Zeta) is computed based on the given pressure (p), surface pressure (ps), and temperature (t). It involves the potential temperature (Theta) at the given pressure level.

Note
The potential vorticity is approximated using the Zeta approximation, which includes conditions based on pressure ratio and a sinusoidal function. Adjust the constants if the approximation or conditions differ from the standard Zeta approximation formula.
Author
Lars Hoffmann

Definition at line 1803 of file mptrac.h.

◆ LOGLEV

#define LOGLEV   2

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

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

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 1846 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 1883 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 1916 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 1951 of file mptrac.h.

◆ NTIMER

#define NTIMER   100

Maximum number of timers.

Definition at line 1960 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 1975 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 1996 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 2015 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 2030 of file mptrac.h.

◆ NVTX_PUSH

#define NVTX_PUSH (   range_title,
  range_color 
)    {}

Definition at line 2122 of file mptrac.h.

◆ NVTX_POP

#define NVTX_POP   {}

Definition at line 2123 of file mptrac.h.

Function Documentation

◆ thrustSortWrapper()

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

Wrapper to Thrust sorting function.

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

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

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

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

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

◆ broadcast_large_data()

void broadcast_large_data ( void *  data,
size_t  N 
)

Broadcasts large data across all processes in an MPI communicator.

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

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

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

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

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

◆ cart2geo()

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

Converts Cartesian coordinates to geographic coordinates.

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

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

Converts Cartesian coordinates to geographic coordinates.

Definition at line 74 of file mptrac.c.

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

◆ clim_oh()

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

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

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

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

Definition at line 89 of file mptrac.c.

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

◆ clim_oh_diurnal_correction()

void clim_oh_diurnal_correction ( const ctl_t ctl,
clim_t clim 
)

Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data.

This function iterates over the climatology data points for OH concentration and integrates the day/night correction factor over longitude. The correction factor is based on the solar zenith angle, and it adjusts the OH data to account for diurnal variations. The corrected OH data is scaled accordingly.

Parameters
ctlPointer to the control structure containing configuration parameters, including the correction factor (oh_chem_beta).
climPointer to the climatology structure containing OH data that will be corrected.
Authors
Lars Hoffmann
Mingzhao Liu

Definition at line 116 of file mptrac.c.

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

◆ clim_photo()

double clim_photo ( const double  rate[CP][CSZA][CO3],
const clim_photo_t photo,
const double  p,
const double  sza,
const double  o3c 
)

Calculates the photolysis rate for a given set of atmospheric conditions.

This function computes the photolysis rate based on provided climatology data and input parameters such as pressure, solar zenith angle (SZA), and ozone column. It ensures that the input parameters are within the valid range of the climatology data and interpolates the photolysis rate accordingly.

Parameters
rate3D array containing the photolysis rates for different combinations of pressure, SZA, and ozone column.
photoPointer to the climatology data structure containing arrays of valid pressure levels, SZAs, and ozone columns.
pPressure at which the photolysis rate is to be calculated.
szaSolar zenith angle at which the photolysis rate is to be calculated.
o3cOzone column at which the photolysis rate is to be calculated.
Returns
The interpolated photolysis rate for the specified conditions. If the calculated rate is negative, it returns 0.0.

This function performs the following steps:

  1. Checks and adjusts the input parameters (pressure, SZA, and ozone column) to ensure they are within the valid range.
  2. Determines the appropriate indices in the climatology data for interpolation.
  3. Performs trilinear interpolation to calculate the photolysis rate based on the input parameters.
Authors
Lars Hoffmann
Mingzhao Liu

Definition at line 149 of file mptrac.c.

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

◆ clim_tropo()

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

Calculates the tropopause pressure based on climatological data.

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

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

This function performs the following steps:

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

Definition at line 200 of file mptrac.c.

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

◆ clim_tropo_init()

void clim_tropo_init ( clim_t clim)

Initializes the tropopause data in the climatology structure.

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

Parameters
climPointer to the climatology structure to be initialized.

This function performs the following steps:

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

Definition at line 228 of file mptrac.c.

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

◆ clim_ts()

double clim_ts ( const clim_ts_t ts,
const double  t 
)

Interpolates a time series of climatological variables.

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

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

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

Author
Lars Hoffmann

Definition at line 383 of file mptrac.c.

385 {
386
387 /* Interpolate... */
388 if (t <= ts->time[0])
389 return ts->vmr[0];
390 else if (t >= ts->time[ts->ntime - 1])
391 return ts->vmr[ts->ntime - 1];
392 else {
393 int idx = locate_irr(ts->time, ts->ntime, t);
394 return LIN(ts->time[idx], ts->vmr[idx],
395 ts->time[idx + 1], ts->vmr[idx + 1], t);
396 }
397}
double vmr[CTS]
Volume mixing ratio [ppv].
Definition: mptrac.h:3272
double time[CTS]
Time [s].
Definition: mptrac.h:3269
int ntime
Number of timesteps.
Definition: mptrac.h:3266
Here is the call graph for this function:

◆ clim_zm()

double clim_zm ( const clim_zm_t zm,
const double  t,
const double  lat,
const double  p 
)

Interpolates monthly mean zonal mean climatological variables.

This function interpolates climatological variables based on pressure, latitude, and time. The climatological data is provided in the form of monthly mean zonal mean values.

Parameters
zmPointer to the climatological zonal mean structure containing data points.
tTime at which to interpolate the climatological variable (in seconds since the beginning of the year).
latLatitude at which to interpolate the climatological variable (in degrees).
pPressure at which to interpolate the climatological variable (in hPa).
Returns
Interpolated value of the climatological variable at the given pressure, latitude, and time.

This function performs trilinear interpolation between the nearest data points to the input time t, latitude lat, and pressure or altitude p. If the input values are outside the range of the provided data, the function extrapolates by using the nearest boundary values.

Author
Lars Hoffmann

Definition at line 401 of file mptrac.c.

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

◆ compress_cms()

void compress_cms ( const ctl_t ctl,
const char *  varname,
float *  array,
const size_t  nx,
const size_t  ny,
const size_t  np,
const int  decompress,
FILE *  inout 
)

Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm.

This function either compresses or decompresses a 3D array of floats based on the value of the decompress parameter. The compression and decompression are performed using a custom multiscale module.

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

The function performs the following steps:

  • Determines grid properties from the input data dimensions.
  • Initializes the multiscale module with the specified grid properties.
  • Sets up longitude and latitude grids for the data.
  • If decompressing:
    • Reads compressed data for each level and decompresses it.
    • Evaluates the decompressed data and stores it in the array.
  • If compressing:
    • Copies data for each level into a temporary array.
    • Compresses the data and writes the compressed data to the file.

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

Note
Ensure that the input array is already allocated and can hold the decompressed data.
Warning
Ensure that the file pointer inout is correctly opened for reading or writing as required.
See also
get_2d_grid_from_meteo_data, init_multiscale, read_sol, save_sol, eval, coarsening, delete_solution, delete_multiscale
Author
Lars Hoffmann

◆ compress_pck()

void compress_pck ( const char *  varname,
float *  array,
const size_t  nxy,
const size_t  nz,
const int  decompress,
FILE *  inout 
)

Compresses or decompresses a 3D array of floats.

This function either compresses or decompresses a 3D array of floats based on the value of the decompress parameter. Compression reduces the storage size by converting float values (4 bytes) to unsigned short values (2 bytes) with scaling and offset. Decompression restores the original float values from the compressed unsigned short representation.

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

The function performs the following steps:

  • If decompressing:
    • Reads scaling factors, offsets, and compressed data from the file.
    • Decompresses the data and stores it in the array.
  • If compressing:
    • Computes the minimum and maximum values for each slice in the third dimension.
    • Calculates scaling factors and offsets based on these values.
    • Compresses the data by converting floats to unsigned shorts using the scaling factors and offsets.
    • Writes the scaling factors, offsets, and compressed data to the file.

The function allocates memory for the compressed data array and frees it before returning.

Author
Lars Hoffmann

Definition at line 657 of file mptrac.c.

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

◆ compress_zfp()

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

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

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

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

The function performs the following steps:

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

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

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

◆ compress_zstd()

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

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

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

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

The function performs the following steps:

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

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

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

◆ day2doy()

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

Get day of year from date.

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

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

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

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

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

Definition at line 897 of file mptrac.c.

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

◆ doy2day()

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

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

This function computes the month and day for a given day of the year (DOY) and year. It accounts for whether the given year is a leap year or not.

Parameters
yearThe year corresponding to the DOY.
doyThe day of the year (1-365 or 1-366).
monPointer to an integer where the computed month will be stored.
dayPointer to an integer where the computed day of the month will be stored.

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

Note
The function assumes that the input DOY is valid for the given year.
Author
Lars Hoffmann

Definition at line 916 of file mptrac.c.

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

◆ fft_help()

void fft_help ( double *  fcReal,
double *  fcImag,
const int  n 
)

Computes the Fast Fourier Transform (FFT) of a complex sequence.

This function calculates the FFT of a complex sequence represented by separate arrays for the real and imaginary parts. The input arrays fcReal and fcImag are modified in place to contain the transformed data.

Parameters
fcRealPointer to an array of doubles representing the real part of the input sequence. The array should have at least n elements.
fcImagPointer to an array of doubles representing the imaginary part of the input sequence. The array should have at least n elements.
nThe number of complex data points in the input sequence. This value should not exceed PMAX.
Precondition
fcReal and fcImag must point to arrays of at least n elements.
n must be less than or equal to PMAX.
Postcondition
The arrays fcReal and fcImag will contain the real and imaginary parts of the FFT result, respectively.
Note
This function uses the GNU Scientific Library (GSL) for computing the FFT. Ensure that GSL is properly installed and linked in your project.
Warning
If n exceeds PMAX, the function will trigger an error message and terminate.
Author
Lars Hoffmann

Definition at line 946 of file mptrac.c.

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

◆ geo2cart()

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

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

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

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

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

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

Definition at line 985 of file mptrac.c.

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

◆ get_met()

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

1008 {
1009
1010 static int init;
1011
1012 met_t *mets;
1013
1014 char cachefile[LEN], cmd[2 * LEN], filename[LEN];
1015
1016 /* Set timer... */
1017 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
1018
1019 /* Init... */
1020 if (t == ctl->t_start || !init) {
1021 init = 1;
1022
1023 /* Read meteo data... */
1024 get_met_help(ctl, t + (ctl->direction == -1 ? -1 : 0), -1,
1025 ctl->metbase, ctl->dt_met, filename);
1026 if (!read_met(filename, ctl, clim, *met0))
1027 ERRMSG("Cannot open file!");
1028
1029 get_met_help(ctl, t + (ctl->direction == 1 ? 1 : 0), 1,
1030 ctl->metbase, ctl->dt_met, filename);
1031 if (!read_met(filename, ctl, clim, *met1))
1032 ERRMSG("Cannot open file!");
1033
1034 /* Update GPU... */
1035#ifdef _OPENACC
1036 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
1037 met_t *met0up = *met0;
1038 met_t *met1up = *met1;
1039#ifdef ASYNCIO
1040#pragma acc update device(met0up[:1],met1up[:1]) async(5)
1041#else
1042#pragma acc update device(met0up[:1],met1up[:1])
1043#endif
1044 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
1045#endif
1046
1047 /* Caching... */
1048 if (ctl->met_cache && t != ctl->t_stop) {
1049 get_met_help(ctl, t + 1.1 * ctl->dt_met * ctl->direction,
1050 ctl->direction, ctl->metbase, ctl->dt_met, cachefile);
1051 sprintf(cmd, "cat %s > /dev/null &", cachefile);
1052 LOG(1, "Caching: %s", cachefile);
1053 if (system(cmd) != 0)
1054 WARN("Caching command failed!");
1055 }
1056 }
1057
1058 /* Read new data for forward trajectories... */
1059 if (t > (*met1)->time) {
1060
1061 /* Pointer swap... */
1062 mets = *met1;
1063 *met1 = *met0;
1064 *met0 = mets;
1065
1066 /* Read new meteo data... */
1067 get_met_help(ctl, t, 1, ctl->metbase, ctl->dt_met, filename);
1068 if (!read_met(filename, ctl, clim, *met1))
1069 ERRMSG("Cannot open file!");
1070
1071 /* Update GPU... */
1072#ifdef _OPENACC
1073 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
1074 met_t *met1up = *met1;
1075#ifdef ASYNCIO
1076#pragma acc update device(met1up[:1]) async(5)
1077#else
1078#pragma acc update device(met1up[:1])
1079#endif
1080 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
1081#endif
1082
1083 /* Caching... */
1084 if (ctl->met_cache && t != ctl->t_stop) {
1085 get_met_help(ctl, t + ctl->dt_met, 1, ctl->metbase, ctl->dt_met,
1086 cachefile);
1087 sprintf(cmd, "cat %s > /dev/null &", cachefile);
1088 LOG(1, "Caching: %s", cachefile);
1089 if (system(cmd) != 0)
1090 WARN("Caching command failed!");
1091 }
1092 }
1093
1094 /* Read new data for backward trajectories... */
1095 if (t < (*met0)->time) {
1096
1097 /* Pointer swap... */
1098 mets = *met1;
1099 *met1 = *met0;
1100 *met0 = mets;
1101
1102 /* Read new meteo data... */
1103 get_met_help(ctl, t, -1, ctl->metbase, ctl->dt_met, filename);
1104 if (!read_met(filename, ctl, clim, *met0))
1105 ERRMSG("Cannot open file!");
1106
1107 /* Update GPU... */
1108#ifdef _OPENACC
1109 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
1110 met_t *met0up = *met0;
1111#ifdef ASYNCIO
1112#pragma acc update device(met0up[:1]) async(5)
1113#else
1114#pragma acc update device(met0up[:1])
1115#endif
1116 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
1117#endif
1118
1119 /* Caching... */
1120 if (ctl->met_cache && t != ctl->t_stop) {
1121 get_met_help(ctl, t - ctl->dt_met, -1, ctl->metbase, ctl->dt_met,
1122 cachefile);
1123 sprintf(cmd, "cat %s > /dev/null &", cachefile);
1124 LOG(1, "Caching: %s", cachefile);
1125 if (system(cmd) != 0)
1126 WARN("Caching command failed!");
1127 }
1128 }
1129
1130 /* Check that grids are consistent... */
1131 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
1132 if ((*met0)->nx != (*met1)->nx
1133 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
1134 ERRMSG("Meteo grid dimensions do not match!");
1135 for (int ix = 0; ix < (*met0)->nx; ix++)
1136 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
1137 ERRMSG("Meteo grid longitudes do not match!");
1138 for (int iy = 0; iy < (*met0)->ny; iy++)
1139 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
1140 ERRMSG("Meteo grid latitudes do not match!");
1141 for (int ip = 0; ip < (*met0)->np; ip++)
1142 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
1143 ERRMSG("Meteo grid pressure levels do not match!");
1144 }
1145}
int 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:5944
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:1149
#define SELECT_TIMER(id, group, color)
Select and start a timer with specific attributes.
Definition: mptrac.h:1996
int direction
Direction flag (1=forward calculation, -1=backward calculation).
Definition: mptrac.h:2465
double dt_met
Time step of meteo data [s].
Definition: mptrac.h:2484
double t_stop
Stop time of simulation [s].
Definition: mptrac.h:2471
int met_cache
Preload meteo data into disk cache (0=no, 1=yes).
Definition: mptrac.h:2631
char metbase[LEN]
Basename for meteo data.
Definition: mptrac.h:2481
double t_start
Start time of simulation [s].
Definition: mptrac.h:2468
Meteo data structure.
Definition: mptrac.h:3374
Here is the call graph for this function:

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

1155 {
1156
1157 char repl[LEN];
1158
1159 double t6, r;
1160
1161 int year, mon, day, hour, min, sec;
1162
1163 /* Round time to fixed intervals... */
1164 if (direct == -1)
1165 t6 = floor(t / dt_met) * dt_met;
1166 else
1167 t6 = ceil(t / dt_met) * dt_met;
1168
1169 /* Decode time... */
1170 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
1171
1172 /* Set filename of MPTRAC meteo files... */
1173 if (ctl->met_clams == 0) {
1174 if (ctl->met_type == 0)
1175 sprintf(filename, "%s_YYYY_MM_DD_HH.nc", metbase);
1176 else if (ctl->met_type == 1)
1177 sprintf(filename, "%s_YYYY_MM_DD_HH.bin", metbase);
1178 else if (ctl->met_type == 2)
1179 sprintf(filename, "%s_YYYY_MM_DD_HH.pck", metbase);
1180 else if (ctl->met_type == 3)
1181 sprintf(filename, "%s_YYYY_MM_DD_HH.zfp", metbase);
1182 else if (ctl->met_type == 4)
1183 sprintf(filename, "%s_YYYY_MM_DD_HH.zstd", metbase);
1184 else if (ctl->met_type == 5)
1185 sprintf(filename, "%s_YYYY_MM_DD_HH.cms", metbase);
1186 sprintf(repl, "%d", year);
1187 get_met_replace(filename, "YYYY", repl);
1188 sprintf(repl, "%02d", mon);
1189 get_met_replace(filename, "MM", repl);
1190 sprintf(repl, "%02d", day);
1191 get_met_replace(filename, "DD", repl);
1192 sprintf(repl, "%02d", hour);
1193 get_met_replace(filename, "HH", repl);
1194 }
1195
1196 /* Set filename of CLaMS meteo files... */
1197 else {
1198 sprintf(filename, "%s_YYMMDDHH.nc", metbase);
1199 sprintf(repl, "%d", year);
1200 get_met_replace(filename, "YYYY", repl);
1201 sprintf(repl, "%02d", year % 100);
1202 get_met_replace(filename, "YY", repl);
1203 sprintf(repl, "%02d", mon);
1204 get_met_replace(filename, "MM", repl);
1205 sprintf(repl, "%02d", day);
1206 get_met_replace(filename, "DD", repl);
1207 sprintf(repl, "%02d", hour);
1208 get_met_replace(filename, "HH", repl);
1209 }
1210}
void get_met_replace(char *orig, char *search, char *repl)
Replaces occurrences of a substring in a string with another substring.
Definition: mptrac.c:1214
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:1831
int met_clams
Read MPTRAC or CLaMS meteo data (0=MPTRAC, 1=CLaMS).
Definition: mptrac.h:2497
int met_type
Type of meteo data files (0=netCDF, 1=binary, 2=pck, 3=zfp, 4=zstd, 5=cms).
Definition: mptrac.h:2494
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 1214 of file mptrac.c.

1217 {
1218
1219 char buffer[LEN];
1220
1221 /* Iterate... */
1222 for (int i = 0; i < 3; i++) {
1223
1224 /* Replace sub-string... */
1225 char *ch;
1226 if (!(ch = strstr(orig, search)))
1227 return;
1228 strncpy(buffer, orig, (size_t) (ch - orig));
1229 buffer[ch - orig] = 0;
1230 sprintf(buffer + (ch - orig), "%s%s", repl, ch + strlen(search));
1231 orig[0] = 0;
1232 strcpy(orig, buffer);
1233 }
1234}

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

1253 {
1254
1256
1257 ctl->met_tropo = met_tropo;
1258 read_met_tropo(ctl, clim, met);
1259#pragma omp parallel for default(shared) private(ci,cw)
1260 for (int ix = 0; ix < nx; ix++)
1261 for (int iy = 0; iy < ny; iy++) {
1262 intpol_met_space_2d(met, met->pt, lons[ix], lats[iy],
1263 &pt[iy * nx + ix], ci, cw, 1);
1264 intpol_met_space_2d(met, met->ps, lons[ix], lats[iy],
1265 &ps[iy * nx + ix], ci, cw, 0);
1266 intpol_met_space_2d(met, met->zs, lons[ix], lats[iy],
1267 &zs[iy * nx + ix], ci, cw, 0);
1268 intpol_met_space_3d(met, met->z, pt[iy * nx + ix], lons[ix],
1269 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
1270 intpol_met_space_3d(met, met->t, pt[iy * nx + ix], lons[ix],
1271 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
1272 intpol_met_space_3d(met, met->h2o, pt[iy * nx + ix], lons[ix],
1273 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
1274 intpol_met_space_3d(met, met->o3, pt[iy * nx + ix], lons[ix],
1275 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
1276 }
1277}
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:1592
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:8157
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:1459
#define INTPOL_INIT
Initialize arrays for interpolation.
Definition: mptrac.h:682
int met_tropo
Tropopause definition (0=none, 1=clim, 2=cold point, 3=WMO_1st, 4=WMO_2nd, 5=dynamical).
Definition: mptrac.h:2616
float h2o[EX][EY][EP]
Water vapor volume mixing ratio [1].
Definition: mptrac.h:3494
float ps[EX][EY]
Surface pressure [hPa].
Definition: mptrac.h:3404
float zs[EX][EY]
Surface geopotential height [km].
Definition: mptrac.h:3410
float o3[EX][EY][EP]
Ozone volume mixing ratio [1].
Definition: mptrac.h:3497
float t[EX][EY][EP]
Temperature [K].
Definition: mptrac.h:3479
float pt[EX][EY]
Tropopause pressure [hPa].
Definition: mptrac.h:3437
float z[EX][EY][EP]
Geopotential height [km].
Definition: mptrac.h:3476
Here is the call graph for this function:

◆ intpol_met_4d_coord()

void intpol_met_4d_coord ( const met_t met0,
float  height0[EX][EY][EP],
float  array0[EX][EY][EP],
const met_t met1,
float  height1[EX][EY][EP],
float  array1[EX][EY][EP],
const double  ts,
const double  height,
const double  lon,
const double  lat,
double *  var,
int *  ci,
double *  cw,
const int  init 
)

Interpolates meteorological variables to a given position and time.

This function interpolates meteorological variables to a specified position and time. It calculates the interpolated value based on the values provided at two time steps and performs interpolation in time, longitude, latitude, and altitude dimensions.

Parameters
met0Pointer to the meteorological data at the first time step.
height0Array containing heights at the first time step.
array0Array containing meteorological variable values at the first time step.
met1Pointer to the meteorological data at the second time step.
height1Array containing heights at the second time step.
array1Array containing meteorological variable values at the second time step.
tsInterpolation time (fractional time between met0 and met1).
heightAltitude at which to interpolate.
lonLongitude at which to interpolate.
latLatitude at which to interpolate.
varPointer to store the interpolated variable value.
ciArray to store the calculated indices.
cwArray to store the weighting factors.
initFlag indicating if it's the first call (1) or not (0).

The function first restricts the longitude within the range [0, 360) degrees. It then calculates the horizontal indices (ci[0] and ci[1]) based on the provided longitude and latitude. Next, it locates the vertical indices for each edge of the column based on the provided height.

The function then calculates the weighting factors for time, longitude, latitude, and altitude. It iterates over the interpolation process to determine the altitude weighting factor. After initializing the interpolation parameters, it calculates the interpolated variable value and stores it in the memory location pointed to by var.

Note
Ensure that all arrays (height0, array0, height1, array1, ci, cw) have sufficient memory allocated before calling this function.
Author
Jan Clemens

Definition at line 1281 of file mptrac.c.

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

1468 {
1469
1470 /* Initialize interpolation... */
1471 if (init) {
1472
1473 /* Check longitude... */
1474 double lon2 = FMOD(lon, 360.);
1475 if (lon2 < met->lon[0])
1476 lon2 += 360;
1477 else if (lon2 > met->lon[met->nx - 1])
1478 lon2 -= 360;
1479
1480 /* Get interpolation indices... */
1481 ci[0] = locate_irr(met->p, met->np, p);
1482 ci[1] = locate_reg(met->lon, met->nx, lon2);
1483 ci[2] = locate_reg(met->lat, met->ny, lat);
1484
1485 /* Get interpolation weights... */
1486 cw[0] = (met->p[ci[0] + 1] - p)
1487 / (met->p[ci[0] + 1] - met->p[ci[0]]);
1488 cw[1] = (met->lon[ci[1] + 1] - lon2)
1489 / (met->lon[ci[1] + 1] - met->lon[ci[1]]);
1490 cw[2] = (met->lat[ci[2] + 1] - lat)
1491 / (met->lat[ci[2] + 1] - met->lat[ci[2]]);
1492 }
1493
1494 /* Interpolate vertically... */
1495 double aux00 =
1496 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
1497 + array[ci[1]][ci[2]][ci[0] + 1];
1498 double aux01 =
1499 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
1500 array[ci[1]][ci[2] + 1][ci[0] + 1])
1501 + array[ci[1]][ci[2] + 1][ci[0] + 1];
1502 double aux10 =
1503 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
1504 array[ci[1] + 1][ci[2]][ci[0] + 1])
1505 + array[ci[1] + 1][ci[2]][ci[0] + 1];
1506 double aux11 =
1507 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
1508 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
1509 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
1510
1511 /* Interpolate horizontally... */
1512 aux00 = cw[2] * (aux00 - aux01) + aux01;
1513 aux11 = cw[2] * (aux10 - aux11) + aux11;
1514 *var = cw[1] * (aux00 - aux11) + aux11;
1515}
int np
Number of pressure levels.
Definition: mptrac.h:3386
double p[EP]
Pressure levels [hPa].
Definition: mptrac.h:3398
Here is the call graph for this function:

◆ intpol_met_space_3d_ml()

void intpol_met_space_3d_ml ( const met_t met,
float  array[EX][EY][EP],
const double  p,
const double  lon,
const double  lat,
double *  var 
)

Interpolates a meteorological variable in 3D space (longitude, latitude, pressure).

This function performs trilinear interpolation of a meteorological variable based on the provided longitude, latitude, and pressure coordinates. The meteorological data is given in a 3D array, and the function calculates the interpolated value and stores it in the variable pointed to by var. The function operates on model level data.

Parameters
[in]metPointer to a met_t structure containing the meteorological data.
[in]array3D array of meteorological data with dimensions [EX][EY][EP].
[in]pPressure coordinate at which to interpolate.
[in]lonLongitude coordinate at which to interpolate.
[in]latLatitude coordinate at which to interpolate.
[out]varPointer to a double where the interpolated value will be stored.
Author
Lars Hoffmann

Definition at line 1519 of file mptrac.c.

1525 {
1526
1527 /* Check longitude... */
1528 double lon2 = FMOD(lon, 360.);
1529 if (lon2 < met->lon[0])
1530 lon2 += 360;
1531 else if (lon2 > met->lon[met->nx - 1])
1532 lon2 -= 360;
1533
1534 /* Get horizontal indices... */
1535 int ix = locate_reg(met->lon, met->nx, lon2);
1536 int iy = locate_reg(met->lat, met->ny, lat);
1537
1538 /* Interpolate vertically... */
1539 int iz = locate_irr_float(met->pl[ix][iy], met->npl, p, 0);
1540 double aux00;
1541 if (p >= met->pl[ix][iy][iz + 1])
1542 aux00 = array[ix][iy][iz + 1];
1543 else if (p <= met->pl[ix][iy][iz])
1544 aux00 = array[ix][iy][iz];
1545 else
1546 aux00 = LIN(met->pl[ix][iy][iz],
1547 array[ix][iy][iz],
1548 met->pl[ix][iy][iz + 1], array[ix][iy][iz + 1], p);
1549
1550 iz = locate_irr_float(met->pl[ix][iy + 1], met->npl, p, iz);
1551 double aux01;
1552 if (p >= met->pl[ix][iy + 1][iz + 1])
1553 aux01 = array[ix][iy + 1][iz + 1];
1554 else if (p <= met->pl[ix][iy + 1][iz])
1555 aux01 = array[ix][iy + 1][iz];
1556 else
1557 aux01 = LIN(met->pl[ix][iy + 1][iz],
1558 array[ix][iy + 1][iz],
1559 met->pl[ix][iy + 1][iz + 1], array[ix][iy + 1][iz + 1], p);
1560
1561 iz = locate_irr_float(met->pl[ix + 1][iy], met->npl, p, iz);
1562 double aux10;
1563 if (p >= met->pl[ix + 1][iy][iz + 1])
1564 aux10 = array[ix + 1][iy][iz + 1];
1565 else if (p <= met->pl[ix + 1][iy][iz])
1566 aux10 = array[ix + 1][iy][iz];
1567 else
1568 aux10 = LIN(met->pl[ix + 1][iy][iz],
1569 array[ix + 1][iy][iz],
1570 met->pl[ix + 1][iy][iz + 1], array[ix + 1][iy][iz + 1], p);
1571
1572 iz = locate_irr_float(met->pl[ix + 1][iy + 1], met->npl, p, iz);
1573 double aux11;
1574 if (p >= met->pl[ix + 1][iy + 1][iz + 1])
1575 aux11 = array[ix + 1][iy + 1][iz + 1];
1576 else if (p <= met->pl[ix + 1][iy + 1][iz])
1577 aux11 = array[ix + 1][iy + 1][iz];
1578 else
1579 aux11 = LIN(met->pl[ix + 1][iy + 1][iz],
1580 array[ix + 1][iy + 1][iz],
1581 met->pl[ix + 1][iy + 1][iz + 1],
1582 array[ix + 1][iy + 1][iz + 1], p);
1583
1584 /* Interpolate horizontally... */
1585 double aux0 = LIN(met->lat[iy], aux00, met->lat[iy + 1], aux01, lat);
1586 double aux1 = LIN(met->lat[iy], aux10, met->lat[iy + 1], aux11, lat);
1587 *var = LIN(met->lon[ix], aux0, met->lon[ix + 1], aux1, lon2);
1588}
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:2144
float pl[EX][EY][EP]
Pressure on model levels [hPa].
Definition: mptrac.h:3515
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 1592 of file mptrac.c.

1600 {
1601
1602 /* Initialize interpolation... */
1603 if (init) {
1604
1605 /* Check longitude... */
1606 double lon2 = FMOD(lon, 360.);
1607 if (lon2 < met->lon[0])
1608 lon2 += 360;
1609 else if (lon2 > met->lon[met->nx - 1])
1610 lon2 -= 360;
1611
1612 /* Get interpolation indices... */
1613 ci[1] = locate_reg(met->lon, met->nx, lon2);
1614 ci[2] = locate_reg(met->lat, met->ny, lat);
1615
1616 /* Get interpolation weights... */
1617 cw[1] = (met->lon[ci[1] + 1] - lon2)
1618 / (met->lon[ci[1] + 1] - met->lon[ci[1]]);
1619 cw[2] = (met->lat[ci[2] + 1] - lat)
1620 / (met->lat[ci[2] + 1] - met->lat[ci[2]]);
1621 }
1622
1623 /* Set variables... */
1624 double aux00 = array[ci[1]][ci[2]];
1625 double aux01 = array[ci[1]][ci[2] + 1];
1626 double aux10 = array[ci[1] + 1][ci[2]];
1627 double aux11 = array[ci[1] + 1][ci[2] + 1];
1628
1629 /* Interpolate horizontally... */
1630 if (isfinite(aux00) && isfinite(aux01)
1631 && isfinite(aux10) && isfinite(aux11)) {
1632 aux00 = cw[2] * (aux00 - aux01) + aux01;
1633 aux11 = cw[2] * (aux10 - aux11) + aux11;
1634 *var = cw[1] * (aux00 - aux11) + aux11;
1635 } else {
1636 if (cw[2] < 0.5) {
1637 if (cw[1] < 0.5)
1638 *var = aux11;
1639 else
1640 *var = aux01;
1641 } else {
1642 if (cw[1] < 0.5)
1643 *var = aux10;
1644 else
1645 *var = aux00;
1646 }
1647 }
1648}
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 1652 of file mptrac.c.

1664 {
1665
1666 double var0, var1;
1667
1668 /* Spatial interpolation... */
1669 intpol_met_space_3d(met0, array0, p, lon, lat, &var0, ci, cw, init);
1670 intpol_met_space_3d(met1, array1, p, lon, lat, &var1, ci, cw, 0);
1671
1672 /* Get weighting factor... */
1673 const double wt = (met1->time - ts) / (met1->time - met0->time);
1674
1675 /* Interpolate... */
1676 *var = wt * (var0 - var1) + var1;
1677}
Here is the call graph for this function:

◆ intpol_met_time_3d_ml()

void intpol_met_time_3d_ml ( 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 
)

Interpolates a meteorological variable in time and 3D space (longitude, latitude, pressure).

This function performs spatiotemporal interpolation of a meteorological variable based on the provided longitude, latitude, pressure, and timestamp. The meteorological data is given in two 3D arrays corresponding to two different time steps, and the function calculates the interpolated value and stores it in the variable pointed to by var. The function operates on model level data.

Parameters
[in]met0Pointer to a met_t structure containing the meteorological data for the first time step.
[in]array03D array of meteorological data for the first time step with dimensions [EX][EY][EP].
[in]met1Pointer to a met_t structure containing the meteorological data for the second time step.
[in]array13D array of meteorological data for the second time step with dimensions [EX][EY][EP].
[in]tsTimestamp at which to interpolate.
[in]pPressure coordinate at which to interpolate.
[in]lonLongitude coordinate at which to interpolate.
[in]latLatitude coordinate at which to interpolate.
[out]varPointer to a double where the interpolated value will be stored.
Author
Lars Hoffmann

Definition at line 1681 of file mptrac.c.

1690 {
1691
1692 double var0, var1;
1693
1694 /* Spatial interpolation... */
1695 intpol_met_space_3d_ml(met0, array0, p, lon, lat, &var0);
1696 intpol_met_space_3d_ml(met1, array1, p, lon, lat, &var1);
1697
1698 /* Interpolate... */
1699 *var = LIN(met0->time, var0, met1->time, var1, ts);
1700}
void intpol_met_space_3d_ml(const met_t *met, float array[EX][EY][EP], const double p, const double lon, const double lat, double *var)
Interpolates a meteorological variable in 3D space (longitude, latitude, pressure).
Definition: mptrac.c:1519
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 1704 of file mptrac.c.

1715 {
1716
1717 double var0, var1;
1718
1719 /* Spatial interpolation... */
1720 intpol_met_space_2d(met0, array0, lon, lat, &var0, ci, cw, init);
1721 intpol_met_space_2d(met1, array1, lon, lat, &var1, ci, cw, 0);
1722
1723 /* Get weighting factor... */
1724 const double wt = (met1->time - ts) / (met1->time - met0->time);
1725
1726 /* Interpolate... */
1727 if (isfinite(var0) && isfinite(var1))
1728 *var = wt * (var0 - var1) + var1;
1729 else if (wt < 0.5)
1730 *var = var1;
1731 else
1732 *var = var0;
1733}
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 1737 of file mptrac.c.

1751 {
1752
1753 double aux0, aux1, aux00, aux01, aux10, aux11, mean = 0;
1754
1755 int n = 0;
1756
1757 /* Check longitude... */
1758 double lon2 = FMOD(lon, 360.);
1759 if (lon2 < lons[0])
1760 lon2 += 360;
1761 else if (lon2 > lons[nlon - 1])
1762 lon2 -= 360;
1763
1764 /* Get indices... */
1765 const int ix = locate_reg(lons, (int) nlon, lon2);
1766 const int iy = locate_reg(lats, (int) nlat, lat);
1767
1768 /* Calculate standard deviation... */
1769 *sigma = 0;
1770 for (int dx = 0; dx < 2; dx++)
1771 for (int dy = 0; dy < 2; dy++) {
1772 if (isfinite(array0[ix + dx][iy + dy])) {
1773 mean += array0[ix + dx][iy + dy];
1774 *sigma += SQR(array0[ix + dx][iy + dy]);
1775 n++;
1776 }
1777 if (isfinite(array1[ix + dx][iy + dy])) {
1778 mean += array1[ix + dx][iy + dy];
1779 *sigma += SQR(array1[ix + dx][iy + dy]);
1780 n++;
1781 }
1782 }
1783 if (n > 0)
1784 *sigma = sqrt(MAX(*sigma / n - SQR(mean / n), 0.0));
1785
1786 /* Linear interpolation... */
1787 if (method == 1 && isfinite(array0[ix][iy])
1788 && isfinite(array0[ix][iy + 1])
1789 && isfinite(array0[ix + 1][iy])
1790 && isfinite(array0[ix + 1][iy + 1])
1791 && isfinite(array1[ix][iy])
1792 && isfinite(array1[ix][iy + 1])
1793 && isfinite(array1[ix + 1][iy])
1794 && isfinite(array1[ix + 1][iy + 1])) {
1795
1796 aux00 = LIN(lons[ix], array0[ix][iy],
1797 lons[ix + 1], array0[ix + 1][iy], lon2);
1798 aux01 = LIN(lons[ix], array0[ix][iy + 1],
1799 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
1800 aux0 = LIN(lats[iy], aux00, lats[iy + 1], aux01, lat);
1801
1802 aux10 = LIN(lons[ix], array1[ix][iy],
1803 lons[ix + 1], array1[ix + 1][iy], lon2);
1804 aux11 = LIN(lons[ix], array1[ix][iy + 1],
1805 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
1806 aux1 = LIN(lats[iy], aux10, lats[iy + 1], aux11, lat);
1807
1808 *var = LIN(time0, aux0, time1, aux1, time);
1809 }
1810
1811 /* Nearest neighbor interpolation... */
1812 else {
1813 aux00 = NN(lons[ix], array0[ix][iy],
1814 lons[ix + 1], array0[ix + 1][iy], lon2);
1815 aux01 = NN(lons[ix], array0[ix][iy + 1],
1816 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
1817 aux0 = NN(lats[iy], aux00, lats[iy + 1], aux01, lat);
1818
1819 aux10 = NN(lons[ix], array1[ix][iy],
1820 lons[ix + 1], array1[ix + 1][iy], lon2);
1821 aux11 = NN(lons[ix], array1[ix][iy + 1],
1822 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
1823 aux1 = NN(lats[iy], aux10, lats[iy + 1], aux11, lat);
1824
1825 *var = NN(time0, aux0, time1, aux1, time);
1826 }
1827}
#define NN(x0, y0, x1, y1, x)
Perform nearest-neighbor interpolation.
Definition: mptrac.h:1232
#define SQR(x)
Compute the square of a value.
Definition: mptrac.h:1557
Here is the call graph for this function:

◆ jsec2time()

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

Converts Julian seconds to calendar date and time components.

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

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

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

Author
Lars Hoffmann

Definition at line 1831 of file mptrac.c.

1839 {
1840
1841 struct tm t0, *t1;
1842
1843 t0.tm_year = 100;
1844 t0.tm_mon = 0;
1845 t0.tm_mday = 1;
1846 t0.tm_hour = 0;
1847 t0.tm_min = 0;
1848 t0.tm_sec = 0;
1849
1850 const time_t jsec0 = (time_t) jsec + timegm(&t0);
1851 t1 = gmtime(&jsec0);
1852
1853 *year = t1->tm_year + 1900;
1854 *mon = t1->tm_mon + 1;
1855 *day = t1->tm_mday;
1856 *hour = t1->tm_hour;
1857 *min = t1->tm_min;
1858 *sec = t1->tm_sec;
1859 *remain = jsec - floor(jsec);
1860}

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

1868 {
1869
1870 /* Check number of data points... */
1871 if (nk < 2)
1872 return 1.0;
1873
1874 /* Get altitude... */
1875 const double z = Z(p);
1876
1877 /* Get weighting factor... */
1878 if (z < kz[0])
1879 return kw[0];
1880 else if (z > kz[nk - 1])
1881 return kw[nk - 1];
1882 else {
1883 int idx = locate_irr(kz, nk, z);
1884 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
1885 }
1886}
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 1890 of file mptrac.c.

1892 {
1893
1894 /*
1895 Calculate moist adiabatic lapse rate [K/km] from temperature [K]
1896 and water vapor volume mixing ratio [1].
1897
1898 Reference: https://en.wikipedia.org/wiki/Lapse_rate
1899 */
1900
1901 const double a = RA * SQR(t), r = SH(h2o) / (1. - SH(h2o));
1902
1903 return 1e3 * G0 * (a + LV * r * t) / (CPD * a + SQR(LV) * r * EPS);
1904}
#define SH(h2o)
Compute specific humidity from water vapor volume mixing ratio.
Definition: mptrac.h:1544
#define LV
Latent heat of vaporization of water [J/kg].
Definition: mptrac.h:182
#define EPS
Ratio of the specific gas constant of dry air and water vapor [1].
Definition: mptrac.h:167
#define CPD
Specific heat of dry air at constant pressure [J/(kg K)].
Definition: mptrac.h:162

◆ level_definitions()

void level_definitions ( ctl_t ctl)

Defines pressure levels for meteorological data.

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

Parameters
ctlControl structure containing information about pressure level definitions.

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

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

Definition at line 1908 of file mptrac.c.

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

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

2117 {
2118
2119 int ilo = 0;
2120 int ihi = n - 1;
2121 int i = (ihi + ilo) >> 1;
2122
2123 if (xx[i] < xx[i + 1])
2124 while (ihi > ilo + 1) {
2125 i = (ihi + ilo) >> 1;
2126 if (xx[i] > x)
2127 ihi = i;
2128 else
2129 ilo = i;
2130 } else
2131 while (ihi > ilo + 1) {
2132 i = (ihi + ilo) >> 1;
2133 if (xx[i] <= x)
2134 ihi = i;
2135 else
2136 ilo = i;
2137 }
2138
2139 return ilo;
2140}

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

2148 {
2149
2150 int ilo = 0;
2151 int ihi = n - 1;
2152 int i = (ihi + ilo) >> 1;
2153
2154 if (x >= xx[ig] && x < xx[ig + 1])
2155 return ig;
2156
2157 if (xx[i] < xx[i + 1])
2158 while (ihi > ilo + 1) {
2159 i = (ihi + ilo) >> 1;
2160 if (xx[i] > x)
2161 ihi = i;
2162 else
2163 ilo = i;
2164 } else
2165 while (ihi > ilo + 1) {
2166 i = (ihi + ilo) >> 1;
2167 if (xx[i] <= x)
2168 ihi = i;
2169 else
2170 ilo = i;
2171 }
2172
2173 return ilo;
2174}

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

2181 {
2182
2183 /* Calculate index... */
2184 int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2185
2186 /* Check range... */
2187 if (i < 0)
2188 return 0;
2189 else if (i > n - 2)
2190 return n - 2;
2191 else
2192 return i;
2193}

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

2203 {
2204
2205 ind[0] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind],
2206 np, height_ap, 0);
2207 ind[1] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind],
2208 np, height_ap, ind[0]);
2209 ind[2] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind + 1],
2210 np, height_ap, ind[1]);
2211 ind[3] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind + 1],
2212 np, height_ap, ind[2]);
2213}
Here is the call graph for this function:

◆ module_advect()

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

Performs the advection of atmospheric particles using meteorological data.

This function advects particles in the atmosphere using meteorological data from two time steps, updating their positions and interpolating necessary data. It supports both pressure and zeta vertical coordinate systems.

Parameters
ctlPointer to the control structure containing configuration flags.
cachePointer to the cache structure for temporary data and random numbers.
met0Pointer to the initial meteorological data structure.
met1Pointer to the final meteorological data structure.
atmPointer to the air parcel data structure.

The function performs the following operations:

  • Sets up a timer labeled "MODULE_ADVECTION" within the "PHYSICS" category for GPU profiling using NVTX.
  • Depending on the vertical coordinate system (pressure or zeta), it loops over each particle in the atmosphere (atm->np), initializing and updating their positions and velocities using meteorological data interpolation.

Pressure Coordinate System (ctl->vert_coord_ap == 0)

  • Initializes particle positions and velocities.
  • Performs integration over a specified number of nodes (ctl->advect) to update particle positions.
  • Interpolates meteorological data for velocity components (u, v, w).
  • Computes mean velocities and updates particle positions in longitude, latitude, and pressure.

Zeta Coordinate System (ctl->vert_coord_ap == 1)

  • Translates pressure into zeta coordinate if other modules have modified the pressure.
  • Initializes particle positions and velocities in zeta coordinates.
  • Performs integration over a specified number of nodes (ctl->advect) to update particle positions.
  • Interpolates meteorological data for velocity components (u, v) and zeta_dot.
  • Computes mean velocities and updates particle positions in longitude, latitude, and zeta.
  • Checks and corrects if zeta is below zero.
  • Translates updated zeta back into pressure coordinates.
Note
The function assumes that the atmospheric data structure (atm) contains arrays for time, longitude, latitude, and pressure for each point. The specific quantification of zeta is stored in atm->q[ctl.qnt_zeta].
Authors
Lars Hoffmann
Jan Clemens

Definition at line 2217 of file mptrac.c.

2222 {
2223
2224 /* Set timer... */
2225 SELECT_TIMER("MODULE_ADVECTION", "PHYSICS", NVTX_GPU);
2226
2227 /* Pressure coordinate... */
2228 if (ctl->advect_vert_coord == 0 || ctl->advect_vert_coord == 2) {
2229
2230 /* Loop over particles... */
2231 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2232
2233 /* Init... */
2235 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
2236 x[3] = { 0, 0, 0 };
2237
2238 /* Loop over integration nodes... */
2239 for (int i = 0; i < ctl->advect; i++) {
2240
2241 /* Set position... */
2242 if (i == 0) {
2243 dts = 0.0;
2244 x[0] = atm->lon[ip];
2245 x[1] = atm->lat[ip];
2246 x[2] = atm->p[ip];
2247 } else {
2248 dts = (i == 3 ? 1.0 : 0.5) * cache->dt[ip];
2249 x[0] = atm->lon[ip] + DX2DEG(dts * u[i - 1] / 1000., atm->lat[ip]);
2250 x[1] = atm->lat[ip] + DY2DEG(dts * v[i - 1] / 1000.);
2251 x[2] = atm->p[ip] + dts * w[i - 1];
2252 }
2253 const double tm = atm->time[ip] + dts;
2254
2255 /* Interpolate meteo data on pressure levels... */
2256 if (ctl->advect_vert_coord == 0) {
2257 intpol_met_time_3d(met0, met0->u, met1, met1->u,
2258 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2259 intpol_met_time_3d(met0, met0->v, met1, met1->v,
2260 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2261 intpol_met_time_3d(met0, met0->w, met1, met1->w,
2262 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
2263 }
2264
2265 /* Interpolate meteo data on model levels... */
2266 else {
2267 intpol_met_time_3d_ml(met0, met0->ul, met1, met1->ul, tm, x[2],
2268 x[0], x[1], &u[i]);
2269 intpol_met_time_3d_ml(met0, met0->vl, met1, met1->vl, tm, x[2],
2270 x[0], x[1], &v[i]);
2271 intpol_met_time_3d_ml(met0, met0->wl, met1, met1->wl, tm, x[2],
2272 x[0], x[1], &w[i]);
2273 }
2274
2275 /* Get mean wind... */
2276 double k = 1.0;
2277 if (ctl->advect == 2)
2278 k = (i == 0 ? 0.0 : 1.0);
2279 else if (ctl->advect == 4)
2280 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2281 um += k * u[i];
2282 vm += k * v[i];
2283 wm += k * w[i];
2284 }
2285
2286 /* Set new position... */
2287 atm->time[ip] += cache->dt[ip];
2288 atm->lon[ip] += DX2DEG(cache->dt[ip] * um / 1000.,
2289 (ctl->advect == 2 ? x[1] : atm->lat[ip]));
2290 atm->lat[ip] += DY2DEG(cache->dt[ip] * vm / 1000.);
2291 atm->p[ip] += cache->dt[ip] * wm;
2292 }
2293 }
2294
2295 /* Zeta coordinate... */
2296 else if (ctl->advect_vert_coord == 1) {
2297
2298 /* Loop over particles... */
2299 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2300
2301 /* Convert pressure to zeta... */
2303 intpol_met_4d_coord(met0, met0->pl, met0->zetal, met1,
2304 met1->pl, met1->zetal, atm->time[ip], atm->p[ip],
2305 atm->lon[ip], atm->lat[ip],
2306 &atm->q[ctl->qnt_zeta][ip], ci, cw, 1);
2307
2308 /* Init... */
2309 double dts, u[4], um = 0, v[4], vm = 0, zeta_dot[4],
2310 zeta_dotm = 0, x[3] = { 0, 0, 0 };
2311
2312 /* Loop over integration nodes... */
2313 for (int i = 0; i < ctl->advect; i++) {
2314
2315 /* Set position... */
2316 if (i == 0) {
2317 dts = 0.0;
2318 x[0] = atm->lon[ip];
2319 x[1] = atm->lat[ip];
2320 x[2] = atm->q[ctl->qnt_zeta][ip];
2321 } else {
2322 dts = (i == 3 ? 1.0 : 0.5) * cache->dt[ip];
2323 x[0] = atm->lon[ip] + DX2DEG(dts * u[i - 1] / 1000., atm->lat[ip]);
2324 x[1] = atm->lat[ip] + DY2DEG(dts * v[i - 1] / 1000.);
2325 x[2] = atm->q[ctl->qnt_zeta][ip] + dts * zeta_dot[i - 1];
2326 }
2327 const double tm = atm->time[ip] + dts;
2328
2329 /* Interpolate meteo data... */
2330 intpol_met_4d_coord(met0, met0->zetal, met0->ul, met1, met1->zetal,
2331 met1->ul, tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2332 intpol_met_4d_coord(met0, met0->zetal, met0->vl, met1, met0->zetal,
2333 met1->vl, tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2334 intpol_met_4d_coord(met0, met0->zetal, met0->zeta_dotl, met1,
2335 met1->zetal, met1->zeta_dotl, tm, x[2], x[0],
2336 x[1], &zeta_dot[i], ci, cw, 0);
2337
2338 /* Get mean wind... */
2339 double k = 1.0;
2340 if (ctl->advect == 2)
2341 k = (i == 0 ? 0.0 : 1.0);
2342 else if (ctl->advect == 4)
2343 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2344 um += k * u[i];
2345 vm += k * v[i];
2346 zeta_dotm += k * zeta_dot[i];
2347 }
2348
2349 /* Set new position... */
2350 atm->time[ip] += cache->dt[ip];
2351 atm->lon[ip] += DX2DEG(cache->dt[ip] * um / 1000.,
2352 (ctl->advect == 2 ? x[1] : atm->lat[ip]));
2353 atm->lat[ip] += DY2DEG(cache->dt[ip] * vm / 1000.);
2354 atm->q[ctl->qnt_zeta][ip] += cache->dt[ip] * zeta_dotm;
2355
2356 /* Check if zeta is below zero... */
2357 if (atm->q[ctl->qnt_zeta][ip] < 0)
2358 atm->q[ctl->qnt_zeta][ip] = 0; /* TODO: reflect particle, or skip this test (use module_position) */
2359
2360 /* Convert zeta to pressure... */
2361 intpol_met_4d_coord(met0, met0->zetal, met0->pl, met1, met1->zetal,
2362 met1->pl, atm->time[ip], atm->q[ctl->qnt_zeta][ip],
2363 atm->lon[ip], atm->lat[ip], &atm->p[ip], ci, cw, 1);
2364 }
2365 }
2366}
void intpol_met_time_3d_ml(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)
Interpolates a meteorological variable in time and 3D space (longitude, latitude, pressure).
Definition: mptrac.c:1681
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:1281
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:1652
#define PARTICLE_LOOP(ip0, ip1, check_dt,...)
Loop over particle indices with OpenACC acceleration.
Definition: mptrac.h:1274
#define DX2DEG(dx, lat)
Convert a distance in kilometers to degrees longitude at a given latitude.
Definition: mptrac.h:525
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
Definition: mptrac.h:543
double time[NP]
Time [s].
Definition: mptrac.h:3153
double lat[NP]
Latitude [deg].
Definition: mptrac.h:3162
double lon[NP]
Longitude [deg].
Definition: mptrac.h:3159
int np
Number of air parcels.
Definition: mptrac.h:3150
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
Definition: mptrac.h:3165
double p[NP]
Pressure [hPa].
Definition: mptrac.h:3156
double dt[NP]
Timesteps [s].
Definition: mptrac.h:3196
int advect
Advection scheme (0=off, 1=Euler, 2=midpoint, 4=Runge-Kutta).
Definition: mptrac.h:2651
int qnt_zeta
Quantity array index for zeta vertical coordinate.
Definition: mptrac.h:2384
int advect_vert_coord
Vertical coordinate of air parcels (0=pressure, 1=zeta, 2=eta).
Definition: mptrac.h:2654
float zeta_dotl[EX][EY][EP]
Vertical velocity on model levels [K/s].
Definition: mptrac.h:3530
float w[EX][EY][EP]
Vertical velocity [hPa/s].
Definition: mptrac.h:3488
float wl[EX][EY][EP]
Vertical velocity on model levels [hPa/s].
Definition: mptrac.h:3524
float vl[EX][EY][EP]
Meridional wind on model levels [m/s].
Definition: mptrac.h:3521
float u[EX][EY][EP]
Zonal wind [m/s].
Definition: mptrac.h:3482
float ul[EX][EY][EP]
Zonal wind on model levels [m/s].
Definition: mptrac.h:3518
float v[EX][EY][EP]
Meridional wind [m/s].
Definition: mptrac.h:3485
float zetal[EX][EY][EP]
Zeta on model levels [K].
Definition: mptrac.h:3527
Here is the call graph for this function:

◆ module_advect_init()

void module_advect_init ( const ctl_t ctl,
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_ADVECTION" 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 2370 of file mptrac.c.

2374 {
2375
2376 /* Initialize pressure consistent with zeta... */
2377 if (ctl->advect_vert_coord == 1) {
2378#pragma omp parallel for default(shared)
2379 for (int ip = 0; ip < atm->np; ip++) {
2380
2381 /* Check time... */
2382 if (atm->time[ip] < met0->time || atm->time[ip] > met1->time)
2383 ERRMSG("Time of air parcel is out of range!");
2384
2385 /* Interpolate pressure... */
2387 intpol_met_4d_coord(met0, met0->zetal, met0->pl, met1, met1->zetal,
2388 met1->pl, atm->time[ip], atm->q[ctl->qnt_zeta][ip],
2389 atm->lon[ip], atm->lat[ip], &atm->p[ip], ci, cw, 1);
2390 }
2391 }
2392}
Here is the call graph for this function:

◆ module_bound_cond()

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

Apply boundary conditions to particles based on meteorological and climatological data.

This function applies boundary conditions to particles based on specified criteria, including latitude, pressure, surface layer parameters, and climatological data. It loops over each particle and checks whether it satisfies the specified boundary conditions. If a particle satisfies the conditions, its properties such as mass, volume mixing ratio, and age of air are updated accordingly.

It checks for quantity flags to determine which properties need to be updated. If the latitude or pressure of a particle falls outside the specified ranges, it skips the particle. It also considers surface layer parameters such as surface pressure, height, zeta range, and planetary boundary layer. If a particle is within the specified surface layer boundaries, its properties are updated accordingly.

The function updates properties such as mass and volume mixing ratio if the corresponding flags are set. It retrieves volume mixing ratio values for various trace gases (e.g., CFC-10, CFC-11, N2O, SF6) from climatological time series data and updates the particle properties accordingly. Additionally, it updates the age of air for each particle based on the current simulation time.

Parameters
ctlPointer to the control structure containing simulation parameters.
cachePointer to the cache structure for temporary data and random numbers.
climPointer to the climatological data structure containing time series data.
met0Pointer to the meteorological data structure at the initial time step.
met1Pointer to the meteorological data structure at the next time step.
atmPointer to the atmospheric data structure containing particle information.
Authors
Lars Hoffmann
Mingzhao Liu

Definition at line 2396 of file mptrac.c.

2402 {
2403
2404 /* Set timer... */
2405 SELECT_TIMER("MODULE_BOUNDCOND", "PHYSICS", NVTX_GPU);
2406
2407 /* Check quantity flags... */
2408 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0 && ctl->qnt_Cccl4
2409 && ctl->qnt_Cccl3f < 0 && ctl->qnt_Cccl2f2 < 0
2410 && ctl->qnt_Cn2o < 0 && ctl->qnt_Csf6 < 0 && ctl->qnt_aoa < 0)
2411 return;
2412
2413 /* Loop over particles... */
2414 PARTICLE_LOOP(0, atm->np, 1,
2415 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2416
2417 /* Check latitude and pressure range... */
2418 if (atm->lat[ip] < ctl->bound_lat0 || atm->lat[ip] > ctl->bound_lat1
2419 || atm->p[ip] > ctl->bound_p0 || atm->p[ip] < ctl->bound_p1)
2420 continue;
2421
2422 /* Check surface layer... */
2423 if (ctl->bound_dps > 0 || ctl->bound_dzs > 0
2424 || ctl->bound_zetas > 0 || ctl->bound_pbl) {
2425
2426 /* Get surface pressure... */
2427 double ps;
2429 INTPOL_2D(ps, 1);
2430
2431 /* Check pressure... */
2432 if (ctl->bound_dps > 0 && atm->p[ip] < ps - ctl->bound_dps)
2433 continue;
2434
2435 /* Check height... */
2436 if (ctl->bound_dzs > 0 && Z(atm->p[ip]) > Z(ps) + ctl->bound_dzs)
2437 continue;
2438
2439 /* Check zeta range... */
2440 if (ctl->bound_zetas > 0) {
2441 double t;
2442 INTPOL_3D(t, 1);
2443 if (ZETA(ps, atm->p[ip], t) > ctl->bound_zetas)
2444 continue;
2445 }
2446
2447 /* Check planetary boundary layer... */
2448 if (ctl->bound_pbl) {
2449 double pbl;
2450 INTPOL_2D(pbl, 0);
2451 if (atm->p[ip] < pbl)
2452 continue;
2453 }
2454 }
2455
2456 /* Set mass and volume mixing ratio... */
2457 if (ctl->qnt_m >= 0 && ctl->bound_mass >= 0)
2458 atm->q[ctl->qnt_m][ip] =
2459 ctl->bound_mass + ctl->bound_mass_trend * atm->time[ip];
2460 if (ctl->qnt_vmr >= 0 && ctl->bound_vmr >= 0)
2461 atm->q[ctl->qnt_vmr][ip] =
2462 ctl->bound_vmr + ctl->bound_vmr_trend * atm->time[ip];
2463
2464 /* Set CFC-10 volume mixing ratio... */
2465 if (ctl->qnt_Cccl4 >= 0 && ctl->clim_ccl4_timeseries[0] != '-')
2466 atm->q[ctl->qnt_Cccl4][ip] = clim_ts(&clim->ccl4, atm->time[ip]);
2467
2468 /* Set CFC-11 volume mixing ratio... */
2469 if (ctl->qnt_Cccl3f >= 0 && ctl->clim_ccl3f_timeseries[0] != '-')
2470 atm->q[ctl->qnt_Cccl3f][ip] = clim_ts(&clim->ccl3f, atm->time[ip]);
2471
2472 /* Set CFC-12 volume mixing ratio... */
2473 if (ctl->qnt_Cccl2f2 >= 0 && ctl->clim_ccl2f2_timeseries[0] != '-')
2474 atm->q[ctl->qnt_Cccl2f2][ip] = clim_ts(&clim->ccl2f2, atm->time[ip]);
2475
2476 /* Set N2O volume mixing ratio... */
2477 if (ctl->qnt_Cn2o >= 0 && ctl->clim_n2o_timeseries[0] != '-')
2478 atm->q[ctl->qnt_Cn2o][ip] = clim_ts(&clim->n2o, atm->time[ip]);
2479
2480 /* Set SF6 volume mixing ratio... */
2481 if (ctl->qnt_Csf6 >= 0 && ctl->clim_sf6_timeseries[0] != '-')
2482 atm->q[ctl->qnt_Csf6][ip] = clim_ts(&clim->sf6, atm->time[ip]);
2483
2484 /* Set age of air... */
2485 if (ctl->qnt_aoa >= 0)
2486 atm->q[ctl->qnt_aoa][ip] = atm->time[ip];
2487 }
2488}
double clim_ts(const clim_ts_t *ts, const double t)
Interpolates a time series of climatological variables.
Definition: mptrac.c:383
#define INTPOL_3D(var, init)
Perform 3D interpolation for a meteorological variable.
Definition: mptrac.h:713
#define ZETA(ps, p, t)
Calculate potential vorticity using the Zeta approximation.
Definition: mptrac.h:1803
#define INTPOL_2D(var, init)
Perform 2D interpolation for a meteorological variable.
Definition: mptrac.h:696
clim_ts_t ccl2f2
CFC-12 time series.
Definition: mptrac.h:3357
clim_ts_t sf6
SF6 time series.
Definition: mptrac.h:3363
clim_ts_t ccl4
CFC-10 time series.
Definition: mptrac.h:3351
clim_ts_t ccl3f
CFC-11 time series.
Definition: mptrac.h:3354
clim_ts_t n2o
N2O time series.
Definition: mptrac.h:3360
int qnt_Cccl2f2
Quantity array index for CFC-12 volume mixing ratio (chemistry code).
Definition: mptrac.h:2453
int qnt_m
Quantity array index for mass.
Definition: mptrac.h:2201
int qnt_aoa
Quantity array index for age of air.
Definition: mptrac.h:2462
char clim_n2o_timeseries[LEN]
Filename of N2O time series.
Definition: mptrac.h:2780
double bound_dzs
Boundary conditions surface layer depth [km].
Definition: mptrac.h:2729
int qnt_Cccl4
Quantity array index for CFC-10 volume mixing ratio (chemistry code).
Definition: mptrac.h:2447
double bound_mass
Boundary conditions mass per particle [kg].
Definition: mptrac.h:2702
int qnt_vmr
Quantity array index for volume mixing ratio.
Definition: mptrac.h:2204
double bound_lat1
Boundary conditions maximum longitude [deg].
Definition: mptrac.h:2717
int bound_pbl
Boundary conditions planetary boundary layer (0=no, 1=yes).
Definition: mptrac.h:2735
double bound_p1
Boundary conditions top pressure [hPa].
Definition: mptrac.h:2723
double bound_vmr
Boundary conditions volume mixing ratio [ppv].
Definition: mptrac.h:2708
double bound_lat0
Boundary conditions minimum longitude [deg].
Definition: mptrac.h:2714
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
Definition: mptrac.h:2711
int qnt_Cn2o
Quantity array index for N2O volume mixing ratio (chemistry code).
Definition: mptrac.h:2456
int qnt_Cccl3f
Quantity array index for CFC-11 volume mixing ratio (chemistry code).
Definition: mptrac.h:2450
int qnt_Csf6
Quantity array index for SF6 volume mixing ratio (chemistry code).
Definition: mptrac.h:2459
double bound_dps
Boundary conditions surface layer depth [hPa].
Definition: mptrac.h:2726
double bound_mass_trend
Boundary conditions mass per particle trend [kg/s].
Definition: mptrac.h:2705
double bound_p0
Boundary conditions bottom pressure [hPa].
Definition: mptrac.h:2720
char clim_ccl4_timeseries[LEN]
Filename of CFC-10 time series.
Definition: mptrac.h:2771
char clim_sf6_timeseries[LEN]
Filename of SF6 time series.
Definition: mptrac.h:2783
char clim_ccl3f_timeseries[LEN]
Filename of CFC-11 time series.
Definition: mptrac.h:2774
char clim_ccl2f2_timeseries[LEN]
Filename of CFC-12 time series.
Definition: mptrac.h:2777
double bound_zetas
Boundary conditions surface layer zeta [K].
Definition: mptrac.h:2732
Here is the call graph for this function:

◆ module_chemgrid()

void module_chemgrid ( const ctl_t ctl,
met_t met0,
met_t met1,
atm_t atm,
const double  t 
)

Calculate grid data for chemistry modules.

This function initializes and updates chemical grid quantities based on atmospheric data and interpolation of meteorological variables.

Parameters
ctlPointer to the control structure containing simulation parameters.
climPointer to the climate data structure containing climatological data.
met0Pointer to the first meteorological data structure.
met1Pointer to the second meteorological data structure.
atmPointer to the atmospheric data structure containing particle information.
tTime for which chemical grid is updated.
Authors
Mingzhao Liu
Lars Hoffmann

Definition at line 2492 of file mptrac.c.

2497 {
2498
2499 /* Check quantities... */
2500 if (ctl->qnt_m < 0 || ctl->qnt_Cx < 0)
2501 return;
2502 if (ctl->molmass <= 0)
2503 ERRMSG("Molar mass is not defined!");
2504
2505 /* Set timer... */
2506 SELECT_TIMER("MODULE_CHEMGRID", "PHYSICS", NVTX_GPU);
2507
2508 /* Allocate... */
2509 const int np = atm->np;
2510 const int nz = ctl->chemgrid_nz;
2511 const int nx = ctl->chemgrid_nx;
2512 const int ny = ctl->chemgrid_ny;
2513 const int ngrid = nx * ny * nz;
2514
2515 double *restrict const z = (double *) malloc((size_t) nz * sizeof(double));
2516 double *restrict const press =
2517 (double *) malloc((size_t) nz * sizeof(double));
2518 double *restrict const mass =
2519 (double *) calloc((size_t) ngrid, sizeof(double));
2520 double *restrict const area =
2521 (double *) malloc((size_t) ny * sizeof(double));
2522 double *restrict const lon =
2523 (double *) malloc((size_t) nx * sizeof(double));
2524 double *restrict const lat =
2525 (double *) malloc((size_t) ny * sizeof(double));
2526
2527 int *restrict const ixs = (int *) malloc((size_t) np * sizeof(int));
2528 int *restrict const iys = (int *) malloc((size_t) np * sizeof(int));
2529 int *restrict const izs = (int *) malloc((size_t) np * sizeof(int));
2530
2531 /* Set grid box size... */
2532 const double dz = (ctl->chemgrid_z1 - ctl->chemgrid_z0) / nz;
2533 const double dlon = (ctl->chemgrid_lon1 - ctl->chemgrid_lon0) / nx;
2534 const double dlat = (ctl->chemgrid_lat1 - ctl->chemgrid_lat0) / ny;
2535
2536 /* Set vertical coordinates... */
2537#ifdef _OPENACC
2538#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np],z[0:nz],press[0:nz],mass[0:ngrid],area[0:ny],lon[0:nx],lat[0:ny])
2539#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
2540#pragma acc parallel loop independent gang vector
2541#else
2542#pragma omp parallel for default(shared)
2543#endif
2544 for (int iz = 0; iz < nz; iz++) {
2545 z[iz] = ctl->chemgrid_z0 + dz * (iz + 0.5);
2546 press[iz] = P(z[iz]);
2547 }
2548
2549 /* Set time interval for output... */
2550 const double t0 = tt - 0.5 * ctl->dt_mod;
2551 const double t1 = tt + 0.5 * ctl->dt_mod;
2552
2553 /* Get indices... */
2554#ifdef _OPENACC
2555#pragma acc parallel loop independent gang vector
2556#else
2557#pragma omp parallel for default(shared)
2558#endif
2559 for (int ip = 0; ip < np; ip++) {
2560 ixs[ip] = (int) ((atm->lon[ip] - ctl->chemgrid_lon0) / dlon);
2561 iys[ip] = (int) ((atm->lat[ip] - ctl->chemgrid_lat0) / dlat);
2562 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->chemgrid_z0) / dz);
2563 if (atm->time[ip] < t0 || atm->time[ip] > t1
2564 || ixs[ip] < 0 || ixs[ip] >= nx
2565 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
2566 izs[ip] = -1;
2567 }
2568
2569 /* Set horizontal coordinates... */
2570#ifdef _OPENACC
2571#pragma acc parallel loop independent gang vector
2572#else
2573#pragma omp parallel for default(shared)
2574#endif
2575 for (int ix = 0; ix < nx; ix++)
2576 lon[ix] = ctl->chemgrid_lon0 + dlon * (ix + 0.5);
2577#ifdef _OPENACC
2578#pragma acc parallel loop independent gang vector
2579#else
2580#pragma omp parallel for default(shared)
2581#endif
2582 for (int iy = 0; iy < ny; iy++) {
2583 lat[iy] = ctl->chemgrid_lat0 + dlat * (iy + 0.5);
2584 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
2585 }
2586
2587 /* Get mass per grid box... */
2588#ifdef _OPENACC
2589#pragma acc parallel loop independent gang vector
2590#endif
2591 for (int ip = 0; ip < np; ip++)
2592 if (izs[ip] >= 0)
2593#ifdef _OPENACC
2594#pragma acc atomic update
2595#endif
2596 mass[ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz)]
2597 += atm->q[ctl->qnt_m][ip];
2598
2599 /* Assign grid data to air parcels ... */
2600#ifdef _OPENACC
2601#pragma acc parallel loop independent gang vector
2602#else
2603#pragma omp parallel for default(shared)
2604#endif
2605 for (int ip = 0; ip < np; ip++)
2606 if (izs[ip] >= 0) {
2607
2608 /* Interpolate temperature... */
2609 double temp;
2611 intpol_met_time_3d(met0, met0->t, met1, met1->t, tt, press[izs[ip]],
2612 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
2613
2614 /* Set mass... */
2615 const double m = mass[ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz)];
2616
2617 /* Calculate volume mixing ratio... */
2618 atm->q[ctl->qnt_Cx][ip] = MA / ctl->molmass * m
2619 / (RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
2620 }
2621#ifdef _OPENACC
2622#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
2623#endif
2624
2625 /* Free... */
2626 free(mass);
2627 free(lon);
2628 free(lat);
2629 free(area);
2630 free(z);
2631 free(press);
2632 free(ixs);
2633 free(iys);
2634 free(izs);
2635}
#define ARRAY_3D(ix, iy, ny, iz, nz)
Compute the linear index of a 3D array element.
Definition: mptrac.h:391
#define P(z)
Compute pressure at given altitude.
Definition: mptrac.h:1304
#define RHO(p, t)
Compute density of air.
Definition: mptrac.h:1481
double molmass
Molar mass [g/mol].
Definition: mptrac.h:2741
double chemgrid_z1
Upper altitude of chemistry grid [km].
Definition: mptrac.h:2828
double chemgrid_z0
Lower altitude of chemistry grid [km].
Definition: mptrac.h:2825
double chemgrid_lat0
Lower latitude of chemistry grid [deg].
Definition: mptrac.h:2843
double chemgrid_lat1
Upper latitude of chemistry grid [deg].
Definition: mptrac.h:2846
double chemgrid_lon0
Lower longitude of chemistry grid [deg].
Definition: mptrac.h:2834
double chemgrid_lon1
Upper longitude of chemistry grid [deg].
Definition: mptrac.h:2837
double dt_mod
Time step of simulation [s].
Definition: mptrac.h:2474
int chemgrid_nz
Number of altitudes of chemistry grid.
Definition: mptrac.h:2822
int chemgrid_nx
Number of longitudes of chemistry grid.
Definition: mptrac.h:2831
int chemgrid_ny
Number of latitudes of chemistry grid.
Definition: mptrac.h:2840
int qnt_Cx
Quantity array index for trace species x volume mixing ratio (chemistry code).
Definition: mptrac.h:2417
Here is the call graph for this function:

◆ module_chem_init()

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

Initializes the chemistry modules by setting atmospheric composition.

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

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

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

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

Definition at line 2639 of file mptrac.c.

2644 {
2645
2646#pragma omp parallel for default(shared)
2647 for (int ip = 0; ip < atm->np; ip++) {
2648
2649 /* Check time... */
2650 if (atm->time[ip] < met0->time || atm->time[ip] > met1->time)
2651 ERRMSG("Time of air parcel is out of range!");
2652
2653 /* Set H2O and O3 using meteo data... */
2655 if (ctl->qnt_Ch2o >= 0) {
2656 double h2o;
2657 INTPOL_3D(h2o, 1);
2658 SET_ATM(qnt_Ch2o, h2o);
2659 }
2660 if (ctl->qnt_Co3 >= 0) {
2661 double o3;
2662 INTPOL_3D(o3, 1);
2663 SET_ATM(qnt_Co3, o3);
2664 }
2665
2666 /* Set radical species... */
2667 SET_ATM(qnt_Coh, clim_oh(ctl, clim, atm->time[ip],
2668 atm->lon[ip], atm->lat[ip], atm->p[ip]));
2669 SET_ATM(qnt_Cho2, clim_zm(&clim->ho2, atm->time[ip],
2670 atm->lat[ip], atm->p[ip]));
2671 SET_ATM(qnt_Ch2o2, clim_zm(&clim->h2o2, atm->time[ip],
2672 atm->lat[ip], atm->p[ip]));
2673 SET_ATM(qnt_Co1d, clim_zm(&clim->o1d, atm->time[ip],
2674 atm->lat[ip], atm->p[ip]));
2675 }
2676}
double clim_oh(const ctl_t *ctl, const clim_t *clim, const double t, const double lon, const double lat, const double p)
Calculates the hydroxyl radical (OH) concentration from climatology data, with an optional diurnal co...
Definition: mptrac.c:89
#define SET_ATM(qnt, val)
Set atmospheric quantity value.
Definition: mptrac.h:1500
clim_zm_t ho2
HO2 zonal means.
Definition: mptrac.h:3345
clim_zm_t o1d
O(1D) zonal means.
Definition: mptrac.h:3348
clim_zm_t h2o2
H2O2 zonal means.
Definition: mptrac.h:3342
int qnt_Ch2o
Quantity array index for H2O volume mixing ratio (chemistry code).
Definition: mptrac.h:2420
int qnt_Co3
Quantity array index for O3 volume mixing ratio (chemistry code).
Definition: mptrac.h:2423
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 2680 of file mptrac.c.

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

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

◆ module_diffusion_meso()

void module_diffusion_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 2792 of file mptrac.c.

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

◆ module_diffusion_pbl()

void module_diffusion_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 2869 of file mptrac.c.

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

◆ module_diffusion_turb()

void module_diffusion_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 2994 of file mptrac.c.

3000 {
3001
3002 /* Set timer... */
3003 SELECT_TIMER("MODULE_DIFFTURB", "PHYSICS", NVTX_GPU);
3004
3005 /* Create random numbers... */
3006 module_rng(ctl, cache->rs, 3 * (size_t) atm->np, 1);
3007
3008 /* Loop over particles... */
3009 PARTICLE_LOOP(0, atm->np, 1,
3010 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3011
3012 /* Get PBL and surface pressure... */
3013 double pbl, ps;
3015 INTPOL_2D(pbl, 1);
3016 INTPOL_2D(ps, 0);
3017
3018 /* Get weighting factors... */
3019 const double wpbl = pbl_weight(ctl, atm, ip, pbl, ps);
3020 const double wtrop = tropo_weight(clim, atm, ip) * (1.0 - wpbl);
3021 const double wstrat = 1.0 - wpbl - wtrop;
3022
3023 /* Set diffusivity... */
3024 const double dx = wpbl * ctl->turb_dx_pbl + wtrop * ctl->turb_dx_trop
3025 + wstrat * ctl->turb_dx_strat;
3026 const double dz = wpbl * ctl->turb_dz_pbl + wtrop * ctl->turb_dz_trop
3027 + wstrat * ctl->turb_dz_strat;
3028
3029 /* Horizontal turbulent diffusion... */
3030 if (dx > 0) {
3031 const double sigma = sqrt(2.0 * dx * fabs(cache->dt[ip])) / 1000.;
3032 atm->lon[ip] += DX2DEG(cache->rs[3 * ip] * sigma, atm->lat[ip]);
3033 atm->lat[ip] += DY2DEG(cache->rs[3 * ip + 1] * sigma);
3034 }
3035
3036 /* Vertical turbulent diffusion... */
3037 if (dz > 0) {
3038 const double sigma = sqrt(2.0 * dz * fabs(cache->dt[ip])) / 1000.;
3039 atm->p[ip] += DZ2DP(cache->rs[3 * ip + 2] * sigma, atm->p[ip]);
3040 }
3041 }
3042}
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:4471
double turb_dz_trop
Vertical turbulent diffusion coefficient (troposphere) [m^2/s].
Definition: mptrac.h:2675
double turb_dx_strat
Horizontal turbulent diffusion coefficient (stratosphere) [m^2/s].
Definition: mptrac.h:2669
double turb_dx_trop
Horizontal turbulent diffusion coefficient (troposphere) [m^2/s].
Definition: mptrac.h:2666
double turb_dx_pbl
Horizontal turbulent diffusion coefficient (PBL) [m^2/s].
Definition: mptrac.h:2663
double turb_dz_strat
Vertical turbulent diffusion coefficient (stratosphere) [m^2/s].
Definition: mptrac.h:2678
double turb_dz_pbl
Vertical turbulent diffusion coefficient (PBL) [m^2/s].
Definition: mptrac.h:2672
Here is the call graph for this function:

◆ module_dry_deposition()

void module_dry_deposition ( 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 3046 of file mptrac.c.

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

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

3197 {
3198
3199 double t;
3200
3201 /* Set timer... */
3202 SELECT_TIMER("MODULE_ISOSURF", "PHYSICS", NVTX_GPU);
3203
3204 /* Init... */
3206
3207 /* Save pressure... */
3208 if (ctl->isosurf == 1)
3209 for (int ip = 0; ip < atm->np; ip++)
3210 cache->iso_var[ip] = atm->p[ip];
3211
3212 /* Save density... */
3213 else if (ctl->isosurf == 2)
3214 for (int ip = 0; ip < atm->np; ip++) {
3215 INTPOL_3D(t, 1);
3216 cache->iso_var[ip] = atm->p[ip] / t;
3217 }
3218
3219 /* Save potential temperature... */
3220 else if (ctl->isosurf == 3)
3221 for (int ip = 0; ip < atm->np; ip++) {
3222 INTPOL_3D(t, 1);
3223 cache->iso_var[ip] = THETA(atm->p[ip], t);
3224 }
3225
3226 /* Read balloon pressure data... */
3227 else if (ctl->isosurf == 4) {
3228
3229 /* Write info... */
3230 LOG(1, "Read balloon pressure data: %s", ctl->balloon);
3231
3232 /* Open file... */
3233 FILE *in;
3234 if (!(in = fopen(ctl->balloon, "r")))
3235 ERRMSG("Cannot open file!");
3236
3237 /* Read pressure time series... */
3238 char line[LEN];
3239 while (fgets(line, LEN, in))
3240 if (sscanf(line, "%lg %lg", &(cache->iso_ts[cache->iso_n]),
3241 &(cache->iso_ps[cache->iso_n])) == 2)
3242 if ((++cache->iso_n) > NP)
3243 ERRMSG("Too many data points!");
3244
3245 /* Check number of points... */
3246 if (cache->iso_n < 1)
3247 ERRMSG("Could not read any data!");
3248
3249 /* Close file... */
3250 fclose(in);
3251 }
3252}
#define NP
Maximum number of atmospheric data points.
Definition: mptrac.h:246
double iso_ts[NP]
Isosurface balloon time [s].
Definition: mptrac.h:3184
int iso_n
Isosurface balloon number of data points.
Definition: mptrac.h:3187
double iso_ps[NP]
Isosurface balloon pressure [hPa].
Definition: mptrac.h:3181
double iso_var[NP]
Isosurface variables.
Definition: mptrac.h:3178
char balloon[LEN]
Balloon position filename.
Definition: mptrac.h:2648
int isosurf
Isosurface parameter (0=none, 1=pressure, 2=density, 3=theta, 4=balloon).
Definition: mptrac.h:2645

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

3261 {
3262
3263 /* Set timer... */
3264 SELECT_TIMER("MODULE_ISOSURF", "PHYSICS", NVTX_GPU);
3265
3266 /* Loop over particles... */
3267 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,cache,met0,met1,atm)") {
3268
3269 /* Init... */
3270 double t;
3272
3273 /* Restore pressure... */
3274 if (ctl->isosurf == 1)
3275 atm->p[ip] = cache->iso_var[ip];
3276
3277 /* Restore density... */
3278 else if (ctl->isosurf == 2) {
3279 INTPOL_3D(t, 1);
3280 atm->p[ip] = cache->iso_var[ip] * t;
3281 }
3282
3283 /* Restore potential temperature... */
3284 else if (ctl->isosurf == 3) {
3285 INTPOL_3D(t, 1);
3286 atm->p[ip] = 1000. * pow(cache->iso_var[ip] / t, -1. / 0.286);
3287 }
3288
3289 /* Interpolate pressure... */
3290 else if (ctl->isosurf == 4) {
3291 if (atm->time[ip] <= cache->iso_ts[0])
3292 atm->p[ip] = cache->iso_ps[0];
3293 else if (atm->time[ip] >= cache->iso_ts[cache->iso_n - 1])
3294 atm->p[ip] = cache->iso_ps[cache->iso_n - 1];
3295 else {
3296 int idx = locate_irr(cache->iso_ts, cache->iso_n, atm->time[ip]);
3297 atm->p[ip] = LIN(cache->iso_ts[idx], cache->iso_ps[idx],
3298 cache->iso_ts[idx + 1], cache->iso_ps[idx + 1],
3299 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, cl,
3382 plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot, o3, lwc,
3383 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_tvirt, TVIRT(t, h2o));
3450 SET_ATM(qnt_lapse, lapse_rate(t, h2o));
3451 SET_ATM(qnt_pv, pv);
3452 SET_ATM(qnt_tdew, TDEW(atm->p[ip], h2o));
3453 SET_ATM(qnt_tice, TICE(atm->p[ip], h2o));
3454 SET_ATM(qnt_tnat,
3455 nat_temperature(atm->p[ip], h2o,
3456 clim_zm(&clim->hno3, atm->time[ip],
3457 atm->lat[ip], atm->p[ip])));
3458 SET_ATM(qnt_tsts,
3459 0.5 * (atm->q[ctl->qnt_tice][ip] + atm->q[ctl->qnt_tnat][ip]));
3460 }
3461}
double nat_temperature(const double p, const double h2o, const double hno3)
Calculates the nitric acid trihydrate (NAT) temperature.
Definition: mptrac.c:4447
double lapse_rate(const double t, const double h2o)
Calculates the moist adiabatic lapse rate in Kelvin per kilometer.
Definition: mptrac.c:1890
#define H0
Scale height [km].
Definition: mptrac.h:177
#define PSICE(t)
Compute saturation pressure over ice (WMO, 2018).
Definition: mptrac.h:1352
#define TICE(p, h2o)
Calculate frost point temperature (WMO, 2018).
Definition: mptrac.h:1620
#define RHICE(p, t, h2o)
Compute relative humidity over ice.
Definition: mptrac.h:1456
#define INTPOL_TIME_ALL(time, p, lon, lat)
Interpolate multiple meteorological variables in time.
Definition: mptrac.h:786
#define RH(p, t, h2o)
Compute relative humidity over water.
Definition: mptrac.h:1426
#define TDEW(p, h2o)
Calculate dew point temperature.
Definition: mptrac.h:1595
#define PSAT(t)
Compute saturation pressure over water.
Definition: mptrac.h:1328
clim_zm_t hno3
HNO3 zonal means.
Definition: mptrac.h:3336
int qnt_tnat
Quantity array index for T_NAT.
Definition: mptrac.h:2414
int qnt_tice
Quantity array index for T_ice.
Definition: mptrac.h:2408
int qnt_tsts
Quantity array index for T_STS.
Definition: mptrac.h:2411
Here is the call graph for this function:

◆ module_mixing()

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

Update atmospheric properties through interparcel mixing.

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

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

Definition at line 3465 of file mptrac.c.

3469 {
3470
3471 /* Set timer... */
3472 SELECT_TIMER("MODULE_MIXING", "PHYSICS", NVTX_GPU);
3473
3474 /* Allocate... */
3475 const int np = atm->np;
3476 int *restrict const ixs = (int *) malloc((size_t) np * sizeof(int));
3477 int *restrict const iys = (int *) malloc((size_t) np * sizeof(int));
3478 int *restrict const izs = (int *) malloc((size_t) np * sizeof(int));
3479
3480 /* Set grid box size... */
3481 const double dz = (ctl->mixing_z1 - ctl->mixing_z0) / ctl->mixing_nz;
3482 const double dlon = (ctl->mixing_lon1 - ctl->mixing_lon0) / ctl->mixing_nx;
3483 const double dlat = (ctl->mixing_lat1 - ctl->mixing_lat0) / ctl->mixing_ny;
3484
3485 /* Set time interval... */
3486 const double t0 = t - 0.5 * ctl->dt_mod;
3487 const double t1 = t + 0.5 * ctl->dt_mod;
3488
3489 /* Get indices... */
3490#ifdef _OPENACC
3491#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
3492#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
3493#pragma acc parallel loop independent gang vector
3494#else
3495#pragma omp parallel for default(shared)
3496#endif
3497 for (int ip = 0; ip < np; ip++) {
3498 ixs[ip] = (int) ((atm->lon[ip] - ctl->mixing_lon0) / dlon);
3499 iys[ip] = (int) ((atm->lat[ip] - ctl->mixing_lat0) / dlat);
3500 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->mixing_z0) / dz);
3501 if (atm->time[ip] < t0 || atm->time[ip] > t1
3502 || ixs[ip] < 0 || ixs[ip] >= ctl->mixing_nx
3503 || iys[ip] < 0 || iys[ip] >= ctl->mixing_ny
3504 || izs[ip] < 0 || izs[ip] >= ctl->mixing_nz)
3505 izs[ip] = -1;
3506 }
3507
3508 /* Calculate interparcel mixing... */
3509 if (ctl->qnt_m >= 0)
3510 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_m);
3511 if (ctl->qnt_vmr >= 0)
3512 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_vmr);
3513 if (ctl->qnt_Ch2o >= 0)
3514 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Ch2o);
3515 if (ctl->qnt_Co3 >= 0)
3516 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Co3);
3517 if (ctl->qnt_Cco >= 0)
3518 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cco);
3519 if (ctl->qnt_Coh >= 0)
3520 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Coh);
3521 if (ctl->qnt_Ch >= 0)
3522 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Ch);
3523 if (ctl->qnt_Cho2 >= 0)
3524 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cho2);
3525 if (ctl->qnt_Ch2o2 >= 0)
3526 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Ch2o2);
3527 if (ctl->qnt_Co1d >= 0)
3528 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Co1d);
3529 if (ctl->qnt_Co3p >= 0)
3530 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Co3p);
3531 if (ctl->qnt_Cccl4 >= 0)
3532 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cccl4);
3533 if (ctl->qnt_Cccl3f >= 0)
3534 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cccl3f);
3535 if (ctl->qnt_Cccl2f2 >= 0)
3536 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cccl2f2);
3537 if (ctl->qnt_Cn2o >= 0)
3538 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Cn2o);
3539 if (ctl->qnt_Csf6 >= 0)
3540 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_Csf6);
3541 if (ctl->qnt_aoa >= 0)
3542 module_mixing_help(ctl, clim, atm, ixs, iys, izs, ctl->qnt_aoa);
3543
3544 /* Free... */
3545#ifdef _OPENACC
3546#pragma acc exit data delete(ixs,iys,izs)
3547#endif
3548 free(ixs);
3549 free(iys);
3550 free(izs);
3551}
void module_mixing_help(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const int *ixs, const int *iys, const int *izs, const int qnt_idx)
Perform interparcel mixing for a specific quantity.
Definition: mptrac.c:3555
int qnt_Coh
Quantity array index for OH volume mixing ratio (chemistry code).
Definition: mptrac.h:2429
int mixing_nx
Number of longitudes of mixing grid.
Definition: mptrac.h:2804
double mixing_z1
Upper altitude of mixing grid [km].
Definition: mptrac.h:2801
int qnt_Co1d
Quantity array index for O(1D) volume mixing ratio (chemistry code).
Definition: mptrac.h:2441
double mixing_z0
Lower altitude of mixing grid [km].
Definition: mptrac.h:2798
int qnt_Cco
Quantity array index for CO volume mixing ratio (chemistry code).
Definition: mptrac.h:2426
int mixing_ny
Number of latitudes of mixing grid.
Definition: mptrac.h:2813
int qnt_Ch
Quantity array index for H volume mixing ratio (chemistry code).
Definition: mptrac.h:2432
double mixing_lat0
Lower latitude of mixing grid [deg].
Definition: mptrac.h:2816
int qnt_Cho2
Quantity array index for HO2 volume mixing ratio (chemistry code).
Definition: mptrac.h:2435
int mixing_nz
Number of altitudes of mixing grid.
Definition: mptrac.h:2795
double mixing_lon0
Lower longitude of mixing grid [deg].
Definition: mptrac.h:2807
double mixing_lat1
Upper latitude of mixing grid [deg].
Definition: mptrac.h:2819
int qnt_Co3p
Quantity array index for O(3P) volume mixing ratio (chemistry code).
Definition: mptrac.h:2444
int qnt_Ch2o2
Quantity array index for H2O2 volume mixing ratio (chemistry code).
Definition: mptrac.h:2438
double mixing_lon1
Upper longitude of mixing grid [deg].
Definition: mptrac.h:2810
Here is the call graph for this function:

◆ module_mixing_help()

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

Perform interparcel mixing for a specific quantity.

This function performs interparcel mixing for a specific quantity based on the given indices of grid boxes. It calculates the mean concentration within each grid box and adjusts the quantity for each particle accordingly.

Parameters
ctlPointer to the control structure containing simulation parameters.
climPointer to the climate data structure containing climatological data.
atmPointer to the atmospheric data structure containing particle information.
ixsPointer to the array of grid box indices along the longitude direction.
iysPointer to the array of grid box indices along the latitude direction.
izsPointer to the array of grid box indices along the vertical direction.
qnt_idxIndex of the quantity for which mixing is performed.
Authors
Mingzhao Liu
Lars Hoffmann

Definition at line 3555 of file mptrac.c.

3562 {
3563
3564 /* Allocate... */
3565 const int np = atm->np;
3566 const int ngrid = ctl->mixing_nx * ctl->mixing_ny * ctl->mixing_nz;
3567 double *restrict const cmean =
3568 (double *) malloc((size_t) ngrid * sizeof(double));
3569 int *restrict const count = (int *) malloc((size_t) ngrid * sizeof(int));
3570
3571 /* Init... */
3572#ifdef _OPENACC
3573#pragma acc enter data create(cmean[0:ngrid],count[0:ngrid])
3574#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
3575#pragma acc parallel loop independent gang vector
3576#else
3577#ifdef __NVCOMPILER
3578#pragma novector
3579#endif
3580#pragma omp parallel for
3581#endif
3582 for (int i = 0; i < ngrid; i++) {
3583 count[i] = 0;
3584 cmean[i] = 0;
3585 }
3586
3587 /* Loop over particles... */
3588#ifdef _OPENACC
3589#pragma acc parallel loop independent gang vector
3590#endif
3591 for (int ip = 0; ip < np; ip++)
3592 if (izs[ip] >= 0) {
3593 int idx = ARRAY_3D
3594 (ixs[ip], iys[ip], ctl->mixing_ny, izs[ip], ctl->mixing_nz);
3595#ifdef _OPENACC
3596#pragma acc atomic update
3597#endif
3598 cmean[idx] += atm->q[qnt_idx][ip];
3599#ifdef _OPENACC
3600#pragma acc atomic update
3601#endif
3602 count[idx]++;
3603 }
3604#ifdef _OPENACC
3605#pragma acc parallel loop independent gang vector
3606#else
3607#ifdef __NVCOMPILER
3608#pragma novector
3609#endif
3610#pragma omp parallel for
3611#endif
3612 for (int i = 0; i < ngrid; i++)
3613 if (count[i] > 0)
3614 cmean[i] /= count[i];
3615
3616 /* Calculate interparcel mixing... */
3617#ifdef _OPENACC
3618#pragma acc parallel loop independent gang vector
3619#else
3620#pragma omp parallel for
3621#endif
3622 for (int ip = 0; ip < np; ip++)
3623 if (izs[ip] >= 0) {
3624
3625 /* Set mixing parameter... */
3626 double mixparam = 1.0;
3627 if (ctl->mixing_trop < 1 || ctl->mixing_strat < 1) {
3628 double w = tropo_weight(clim, atm, ip);
3629 mixparam = w * ctl->mixing_trop + (1 - w) * ctl->mixing_strat;
3630 }
3631
3632 /* Adjust quantity... */
3633 atm->q[qnt_idx][ip] +=
3634 (cmean
3635 [ARRAY_3D(ixs[ip], iys[ip], ctl->mixing_ny, izs[ip], ctl->mixing_nz)]
3636 - atm->q[qnt_idx][ip]) * mixparam;
3637 }
3638
3639 /* Free... */
3640#ifdef _OPENACC
3641#pragma acc exit data delete(cmean,count)
3642#endif
3643 free(cmean);
3644 free(count);
3645}
double mixing_trop
Interparcel exchange parameter for mixing in the troposphere.
Definition: mptrac.h:2789
double mixing_strat
Interparcel exchange parameter for mixing in the stratosphere.
Definition: mptrac.h:2792
Here is the call graph for this function:

◆ module_oh_chem()

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

Perform hydroxyl chemistry calculations for atmospheric particles.

This function calculates the OH chemistry for each atmospheric particle based on the specified reaction mechanism and updates the particle quantities accordingly. The OH chemistry includes bimolecular and termolecular reactions, and the reaction rates are calculated based on the provided climatological data and atmospheric conditions. The function supports both mass and volume mixing ratio quantities for the particles.

Parameters
ctlPointer to the control structure containing simulation parameters.
cachePointer to the cache structure for temporary data and random numbers.
climPointer to the climate data structure containing climatological data.
met0Pointer to the first meteorological data structure.
met1Pointer to the second meteorological data structure.
atmPointer to the atmospheric data structure containing particle information.
Note
The function assumes that the necessary meteorological and climatological data structures have been initialized and are accessible via the pointers met0, met1, and clim, respectively.
The reaction rates are calculated based on the provided reaction mechanism and atmospheric conditions, including temperature, pressure, and the concentrations of relevant species.
The function updates the particle quantities based on the calculated reaction rates and the specified time steps. The update can include both mass and volume mixing ratio quantities, as determined by the control structure (ctl).
Authors
Lars Hoffmann
Mingzhao Liu

Definition at line 3649 of file mptrac.c.

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

3737 {
3738
3739 /* Set timer... */
3740 SELECT_TIMER("MODULE_POSITION", "PHYSICS", NVTX_GPU);
3741
3742 /* Loop over particles... */
3743 PARTICLE_LOOP(0, atm->np, 1, "acc data present(cache,met0,met1,atm)") {
3744
3745 /* Init... */
3746 double ps;
3748
3749 /* Calculate modulo... */
3750 atm->lon[ip] = FMOD(atm->lon[ip], 360.);
3751 atm->lat[ip] = FMOD(atm->lat[ip], 360.);
3752
3753 /* Check latitude... */
3754 while (atm->lat[ip] < -90 || atm->lat[ip] > 90) {
3755 if (atm->lat[ip] > 90) {
3756 atm->lat[ip] = 180 - atm->lat[ip];
3757 atm->lon[ip] += 180;
3758 }
3759 if (atm->lat[ip] < -90) {
3760 atm->lat[ip] = -180 - atm->lat[ip];
3761 atm->lon[ip] += 180;
3762 }
3763 }
3764
3765 /* Check longitude... */
3766 while (atm->lon[ip] < -180)
3767 atm->lon[ip] += 360;
3768 while (atm->lon[ip] >= 180)
3769 atm->lon[ip] -= 360;
3770
3771 /* Check pressure... */
3772 if (atm->p[ip] < met0->p[met0->np - 1]) {
3773 // TODO: add reflection: atm->p[ip] = 2. * met0->p[met0->np - 1] - atm->p[ip];
3774 atm->p[ip] = met0->p[met0->np - 1];
3775 } else if (atm->p[ip] > 300.) {
3776 INTPOL_2D(ps, 1);
3777 // TODO: add reflection: if (atm->p[ip] > ps)
3778 // atm->p[ip] = 2. * ps - atm->p[ip];
3779 if (atm->p[ip] > ps)
3780 atm->p[ip] = ps;
3781 }
3782 }
3783}

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

3788 {
3789
3790 /* Initialize GSL random number generators... */
3791 gsl_rng_env_setup();
3792 if (omp_get_max_threads() > NTHREADS)
3793 ERRMSG("Too many threads!");
3794 for (int i = 0; i < NTHREADS; i++) {
3795 rng[i] = gsl_rng_alloc(gsl_rng_default);
3796 gsl_rng_set(rng[i], gsl_rng_default_seed
3797 + (long unsigned) (ntask * NTHREADS + i));
3798 }
3799
3800 /* Initialize cuRAND random number generators... */
3801#ifdef CURAND
3802 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
3803 CURAND_STATUS_SUCCESS)
3804 ERRMSG("Cannot create random number generator!");
3805 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
3806 CURAND_STATUS_SUCCESS)
3807 ERRMSG("Cannot set seed for random number generator!");
3808 if (curandSetStream
3809 (rng_curand,
3810 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
3811 CURAND_STATUS_SUCCESS)
3812 ERRMSG("Cannot set stream for random number generator!");
3813#endif
3814}
#define NTHREADS
Maximum number of OpenMP threads.
Definition: mptrac.h:286

◆ module_rng()

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

Generate random numbers using various methods and distributions.

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

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

Definition at line 3818 of file mptrac.c.

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

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

3927 {
3928
3929 /* Set timer... */
3930 SELECT_TIMER("MODULE_SEDI", "PHYSICS", NVTX_GPU);
3931
3932 /* Loop over particles... */
3933 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
3934
3935 /* Get temperature... */
3936 double t;
3938 INTPOL_3D(t, 1);
3939
3940 /* Sedimentation velocity... */
3941 const double v_s = sedi(atm->p[ip], t, atm->q[ctl->qnt_rp][ip],
3942 atm->q[ctl->qnt_rhop][ip]);
3943
3944 /* Calculate pressure change... */
3945 atm->p[ip] += DZ2DP(v_s * cache->dt[ip] / 1000., atm->p[ip]);
3946 }
3947}
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 3951 of file mptrac.c.

3954 {
3955
3956 /* Set timer... */
3957 SELECT_TIMER("MODULE_SORT", "PHYSICS", NVTX_GPU);
3958
3959 /* Allocate... */
3960 const int np = atm->np;
3961 double *restrict const a = (double *) malloc((size_t) np * sizeof(double));
3962 int *restrict const p = (int *) malloc((size_t) np * sizeof(int));
3963
3964#ifdef _OPENACC
3965#pragma acc enter data create(a[0:np],p[0:np])
3966#pragma acc data present(ctl,met0,atm,a,p)
3967#endif
3968
3969 /* Get box index... */
3970#ifdef _OPENACC
3971#pragma acc parallel loop independent gang vector
3972#else
3973#pragma omp parallel for default(shared)
3974#endif
3975 for (int ip = 0; ip < np; ip++) {
3976 a[ip] =
3977 (double) ((locate_reg(met0->lon, met0->nx, atm->lon[ip]) * met0->ny +
3978 locate_reg(met0->lat, met0->ny, atm->lat[ip]))
3979 * met0->np + locate_irr(met0->p, met0->np, atm->p[ip]));
3980 p[ip] = ip;
3981 }
3982
3983 /* Sorting... */
3984#ifdef _OPENACC
3985#pragma acc host_data use_device(a, p)
3986#endif
3987#ifdef THRUST
3988 thrustSortWrapper(a, np, p);
3989#else
3990 ERRMSG("MPTRAC was compiled without Thrust library!");
3991#endif
3992
3993 /* Sort data... */
3994 module_sort_help(atm->time, p, np);
3995 module_sort_help(atm->p, p, np);
3996 module_sort_help(atm->lon, p, np);
3997 module_sort_help(atm->lat, p, np);
3998 for (int iq = 0; iq < ctl->nq; iq++)
3999 module_sort_help(atm->q[iq], p, np);
4000
4001 /* Free... */
4002#ifdef _OPENACC
4003#pragma acc exit data delete(a,p)
4004#endif
4005 free(a);
4006 free(p);
4007}
void module_sort_help(double *a, const int *p, const int np)
Reorder an array based on a given permutation.
Definition: mptrac.c:4011
void thrustSortWrapper(double *__restrict__ c, int n, int *__restrict__ index)
Wrapper to Thrust sorting function.
int nq
Number of quantities.
Definition: mptrac.h:2177
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 4011 of file mptrac.c.

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

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

4052 {
4053
4054 /* Set timer... */
4055 SELECT_TIMER("MODULE_TIMESTEPS", "PHYSICS", NVTX_GPU);
4056
4057 const double latmin = gsl_stats_min(met0->lat, 1, (size_t) met0->ny),
4058 latmax = gsl_stats_max(met0->lat, 1, (size_t) met0->ny);
4059
4060 const int local =
4061 (fabs(met0->lon[met0->nx - 1] - met0->lon[0] - 360.0) >= 0.01);
4062
4063 /* Loop over particles... */
4064 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,cache,met0,atm)") {
4065
4066 /* Set time step for each air parcel... */
4067 if ((ctl->direction * (atm->time[ip] - ctl->t_start) >= 0
4068 && ctl->direction * (atm->time[ip] - ctl->t_stop) <= 0
4069 && ctl->direction * (atm->time[ip] - t) < 0))
4070 cache->dt[ip] = t - atm->time[ip];
4071 else
4072 cache->dt[ip] = 0.0;
4073
4074 /* Check horizontal boundaries of local meteo data... */
4075 if (local && (atm->lon[ip] <= met0->lon[0]
4076 || atm->lon[ip] >= met0->lon[met0->nx - 1]
4077 || atm->lat[ip] <= latmin || atm->lat[ip] >= latmax))
4078 cache->dt[ip] = 0.0;
4079 }
4080}

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

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

◆ module_tracer_chem()

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

Simulate chemical reactions involving long-lived atmospheric tracers.

This function simulates chemical reactions involving atmospheric tracers, such as CFC-10, CFC-11, CFC-12, and N2O. It calculates the change in tracer concentrations over time based on reaction rates and environmental factors such as temperature, ozone concentration, solar zenith angle, and O(1D) volume mixing ratio.

Parameters
ctlPointer to the control structure containing simulation parameters.
cachePointer to the cache structure for temporary data and random numbers.
climPointer to the climatological data structure.
met0Pointer to the first meteorological data structure.
met1Pointer to the second meteorological data structure.
atmPointer to the atmospheric data structure containing particle information.
Note
The function assumes that the necessary control structure (ctl), climatological data structure (clim), meteorological data structures (met0, met1), and atmospheric data structure (atm) have been initialized and are accessible.
Chemical reactions involving CFC-10, CFC-11, CFC-12, and N2O are simulated for each particle in the atmospheric data structure.
The function calculates reaction rates based on temperature, solar zenith angle, total column ozone, and the volume mixing ratio of O(1D).
The exponential decay of tracer concentrations due to chemical reactions is calculated using reaction rate coefficients and the time step (dt) for each particle.
If the particle has a quantity flag for the tracer species (e.g., ctl->qnt_Cccl4, ctl->qnt_Cccl3f, ctl->qnt_Cccl2f2, ctl->qnt_Cn2o), the function updates the concentration of the tracer based on the exponential decay.
Authors
Mingzhao Liu
Lars Hoffmann

Definition at line 4115 of file mptrac.c.

4121 {
4122
4123 /* Set timer... */
4124 SELECT_TIMER("MODULE_TRACERCHEM", "PHYSICS", NVTX_GPU);
4125
4126 /* Loop over particles... */
4127 PARTICLE_LOOP(0, atm->np, 1,
4128 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4129
4130 /* Get temperature... */
4131 double t;
4133 INTPOL_3D(t, 1);
4134
4135 /* Get molecular density... */
4136 const double M = MOLEC_DENS(atm->p[ip], t);
4137
4138 /* Get total column ozone... */
4139 double o3c;
4140 INTPOL_2D(o3c, 1);
4141
4142 /* Get solar zenith angle... */
4143 const double sza = sza_calc(atm->time[ip], atm->lon[ip], atm->lat[ip]);
4144
4145 /* Get O(1D) volume mixing ratio... */
4146 const double o1d =
4147 clim_zm(&clim->o1d, atm->time[ip], atm->lat[ip], atm->p[ip]);
4148
4149 /* Reactions for CFC-10... */
4150 if (ctl->qnt_Cccl4 >= 0) {
4151 const double K_o1d = ARRHENIUS(3.30e-10, 0, t) * o1d * M;
4152 const double K_hv = clim_photo(clim->photo.ccl4, &(clim->photo),
4153 atm->p[ip], sza, o3c);
4154 atm->q[ctl->qnt_Cccl4][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4155 }
4156
4157 /* Reactions for CFC-11... */
4158 if (ctl->qnt_Cccl3f >= 0) {
4159 const double K_o1d = ARRHENIUS(2.30e-10, 0, t) * o1d * M;
4160 const double K_hv = clim_photo(clim->photo.ccl3f, &(clim->photo),
4161 atm->p[ip], sza, o3c);
4162 atm->q[ctl->qnt_Cccl3f][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4163 }
4164
4165 /* Reactions for CFC-12... */
4166 if (ctl->qnt_Cccl2f2 >= 0) {
4167 const double K_o1d = ARRHENIUS(1.40e-10, -25, t) * o1d * M;
4168 const double K_hv = clim_photo(clim->photo.ccl2f2, &(clim->photo),
4169 atm->p[ip], sza, o3c);
4170 atm->q[ctl->qnt_Cccl2f2][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4171 }
4172
4173 /* Reactions for N2O... */
4174 if (ctl->qnt_Cn2o >= 0) {
4175 const double K_o1d = ARRHENIUS(1.19e-10, -20, t) * o1d * M;
4176 const double K_hv = clim_photo(clim->photo.n2o, &(clim->photo),
4177 atm->p[ip], sza, o3c);
4178 atm->q[ctl->qnt_Cn2o][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4179 }
4180 }
4181}
double clim_photo(const double rate[CP][CSZA][CO3], const clim_photo_t *photo, const double p, const double sza, const double o3c)
Calculates the photolysis rate for a given set of atmospheric conditions.
Definition: mptrac.c:149
#define ARRHENIUS(a, b, t)
Calculate the Arrhenius rate constant.
Definition: mptrac.h:416
double ccl2f2[CP][CSZA][CO3]
CCl2F2 photolysis rate [1/s].
Definition: mptrac.h:3237
double ccl3f[CP][CSZA][CO3]
CCl3F photolysis rate [1/s].
Definition: mptrac.h:3234
double n2o[CP][CSZA][CO3]
N2O photolysis rate [1/s].
Definition: mptrac.h:3228
double ccl4[CP][CSZA][CO3]
CCl4 photolysis rate [1/s].
Definition: mptrac.h:3231
clim_photo_t photo
Photolysis rates.
Definition: mptrac.h:3333
Here is the call graph for this function:

◆ module_wet_deposition()

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

Perform wet deposition calculations for air parcels.

This function calculates the wet deposition process for each air parcel based on provided atmospheric and meteorological data. It estimates the precipitation rate and scavenging coefficients for particles and gases inside and below cloud layers. The scavenging coefficients are used to calculate the exponential decay of mass or volume mixing ratio over time due to wet deposition.

Parameters
ctlPointer to the control structure containing simulation parameters.
cachePointer to the cache structure for temporary data and random numbers.
met0Pointer to the initial meteorological data structure.
met1Pointer to the updated meteorological data structure.
atmPointer to the atmospheric data structure containing air parcel information.
Note
The function calculates the wet deposition process for particles and gases based on precipitation rate and scavenging coefficients inside and below cloud layers.
It estimates the exponential decay of mass or volume mixing ratio over time due to wet deposition.
For exponential form A and B coefficients see Bakels et al. (2024, Table B2).
For Henry's law constants see Sander (2023) or https://henrys-law.org/.
Some species (e.g. SO2) require an effective Henry constant to account not only for physical solubility in water but also for chemical reactions, such as hydrolysis and ionization, which significantly enhance dissolution in aqueous solutions.
Authors
Lars Hoffmann
Mingzhao Liu

Definition at line 4185 of file mptrac.c.

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

◆ mptrac_run_timestep()

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

Executes a single timestep of the MPTRAC model simulation.

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

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

Definition at line 4320 of file mptrac.c.

4327 {
4328
4329 /* Set time steps of air parcels... */
4330 module_timesteps(ctl, cache, *met0, atm, t);
4331
4332 /* Get meteo data... */
4333 if (t != ctl->t_start)
4334 get_met(ctl, clim, t, met0, met1);
4335
4336 /* Sort particles... */
4337 if (ctl->sort_dt > 0 && fmod(t, ctl->sort_dt) == 0)
4338 module_sort(ctl, *met0, atm);
4339
4340 /* Check positions (initial)... */
4341 module_position(cache, *met0, *met1, atm);
4342
4343 /* Advection... */
4344 if (ctl->advect > 0)
4345 module_advect(ctl, cache, *met0, *met1, atm);
4346
4347 /* Turbulent diffusion... */
4348 if (ctl->diffusion == 1
4349 && (ctl->turb_dx_pbl > 0 || ctl->turb_dz_pbl > 0
4350 || ctl->turb_dx_trop > 0 || ctl->turb_dz_trop > 0
4351 || ctl->turb_dx_strat > 0 || ctl->turb_dz_strat > 0))
4352 module_diffusion_turb(ctl, cache, clim, *met0, *met1, atm);
4353
4354 /* Mesoscale diffusion... */
4355 if (ctl->diffusion == 1 && (ctl->turb_mesox > 0 || ctl->turb_mesoz > 0))
4356 module_diffusion_meso(ctl, cache, *met0, *met1, atm);
4357
4358 /* Diffusion... */
4359 if (ctl->diffusion == 2)
4360 module_diffusion_pbl(ctl, cache, *met0, *met1, atm);
4361
4362 /* Convection... */
4363 if ((ctl->conv_mix_pbl || ctl->conv_cape >= 0)
4364 && (ctl->conv_dt <= 0 || fmod(t, ctl->conv_dt) == 0))
4365 module_convection(ctl, cache, *met0, *met1, atm);
4366
4367 /* Sedimentation... */
4368 if (ctl->qnt_rp >= 0 && ctl->qnt_rhop >= 0)
4369 module_sedi(ctl, cache, *met0, *met1, atm);
4370
4371 /* Isosurface... */
4372 if (ctl->isosurf >= 1 && ctl->isosurf <= 4)
4373 module_isosurf(ctl, cache, *met0, *met1, atm);
4374
4375 /* Check positions (final)... */
4376 module_position(cache, *met0, *met1, atm);
4377
4378 /* Interpolate meteo data... */
4379 if (ctl->met_dt_out > 0
4380 && (ctl->met_dt_out < ctl->dt_mod || fmod(t, ctl->met_dt_out) == 0))
4381 module_meteo(ctl, cache, clim, *met0, *met1, atm);
4382
4383 /* Check boundary conditions (initial)... */
4384 if ((ctl->bound_lat0 < ctl->bound_lat1)
4385 && (ctl->bound_p0 > ctl->bound_p1))
4386 module_bound_cond(ctl, cache, clim, *met0, *met1, atm);
4387
4388 /* Initialize quantity of total loss rate... */
4389 if (ctl->qnt_loss_rate >= 0) {
4390 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,atm)") {
4391 atm->q[ctl->qnt_loss_rate][ip] = 0;
4392 }
4393 }
4394
4395 /* Decay of particle mass... */
4396 if (ctl->tdec_trop > 0 && ctl->tdec_strat > 0)
4397 module_decay(ctl, cache, clim, atm);
4398
4399 /* Interparcel mixing... */
4400 if (ctl->mixing_trop >= 0 && ctl->mixing_strat >= 0
4401 && (ctl->mixing_dt <= 0 || fmod(t, ctl->mixing_dt) == 0))
4402 module_mixing(ctl, clim, atm, t);
4403
4404 /* Calculate the tracer vmr in the chemistry grid... */
4405 if (ctl->oh_chem_reaction != 0 || ctl->h2o2_chem_reaction != 0
4406 || (ctl->kpp_chem && fmod(t, ctl->dt_kpp) == 0))
4407 module_chemgrid(ctl, *met0, *met1, atm, t);
4408
4409 /* OH chemistry... */
4410 if (ctl->oh_chem_reaction != 0)
4411 module_oh_chem(ctl, cache, clim, *met0, *met1, atm);
4412
4413 /* H2O2 chemistry (for SO2 aqueous phase oxidation)... */
4414 if (ctl->h2o2_chem_reaction != 0)
4415 module_h2o2_chem(ctl, cache, clim, *met0, *met1, atm);
4416
4417 /* First-order tracer chemistry... */
4418 if (ctl->tracer_chem)
4419 module_tracer_chem(ctl, cache, clim, *met0, *met1, atm);
4420
4421 /* KPP chemistry... */
4422 if (ctl->kpp_chem && fmod(t, ctl->dt_kpp) == 0) {
4423#ifdef KPP
4424 module_kpp_chem(ctl, cache, clim, *met0, *met1, atm);
4425#else
4426 ERRMSG("Code was compiled without KPP!");
4427#endif
4428 }
4429
4430 /* Wet deposition... */
4431 if ((ctl->wet_depo_ic_a > 0 || ctl->wet_depo_ic_h[0] > 0)
4432 && (ctl->wet_depo_bc_a > 0 || ctl->wet_depo_bc_h[0] > 0))
4433 module_wet_deposition(ctl, cache, *met0, *met1, atm);
4434
4435 /* Dry deposition... */
4436 if (ctl->dry_depo_vdep > 0)
4437 module_dry_deposition(ctl, cache, *met0, *met1, atm);
4438
4439 /* Check boundary conditions (final)... */
4440 if ((ctl->bound_lat0 < ctl->bound_lat1)
4441 && (ctl->bound_p0 > ctl->bound_p1))
4442 module_bound_cond(ctl, cache, clim, *met0, *met1, atm);
4443}
void module_wet_deposition(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:4185
void get_met(ctl_t *ctl, clim_t *clim, const double t, met_t **met0, met_t **met1)
Retrieves meteorological data for the specified time.
Definition: mptrac.c:1003
void module_advect(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Performs the advection of atmospheric particles using meteorological data.
Definition: mptrac.c:2217
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:4047
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:2753
void module_dry_deposition(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:3046
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:3465
void module_chemgrid(const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double tt)
Calculate grid data for chemistry modules.
Definition: mptrac.c:2492
void module_diffusion_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:2792
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:3922
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:2680
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:2396
void module_diffusion_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:2994
void module_diffusion_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:2869
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:3733
void module_sort(const ctl_t *ctl, met_t *met0, atm_t *atm)
Sort particles according to box index.
Definition: mptrac.c:3951
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:4115
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:3109
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:3256
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:3649
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.
double sort_dt
Time step for sorting of particle data [s].
Definition: mptrac.h:2641
double met_dt_out
Time step for sampling of meteo data along trajectories [s].
Definition: mptrac.h:2628
double dt_kpp
Time step for KPP chemistry [s].
Definition: mptrac.h:2864
double conv_dt
Time interval for convection module [s].
Definition: mptrac.h:2699
int tracer_chem
Switch for first order tracer chemistry module (0=off, 1=on).
Definition: mptrac.h:2867
int diffusion
Diffusion scheme (0=off, 1=fixed-K, 2=PBL).
Definition: mptrac.h:2660
int kpp_chem
Switch for KPP chemistry module (0=off, 1=on).
Definition: mptrac.h:2861
int h2o2_chem_reaction
Reaction type for H2O2 chemistry (0=none, 1=SO2).
Definition: mptrac.h:2858
double mixing_dt
Time interval for mixing [s].
Definition: mptrac.h:2786
Here is the call graph for this function:

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

4450 {
4451
4452 /* Check water vapor volume mixing ratio... */
4453 const double h2o_help = MAX(h2o, 0.1e-6);
4454
4455 /* Calculate T_NAT... */
4456 const double p_hno3 = hno3 * p / 1.333224;
4457 const double p_h2o = h2o_help * p / 1.333224;
4458 const double a = 0.009179 - 0.00088 * log10(p_h2o);
4459 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
4460 const double c = -11397.0 / a;
4461 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
4462 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
4463 if (x2 > 0)
4464 tnat = x2;
4465
4466 return tnat;
4467}

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

4476 {
4477
4478 /* Get pressure range... */
4479 const double p1 = pbl - ctl->conv_pbl_trans * (ps - pbl);
4480 const double p0 = pbl;
4481
4482 /* Get weighting factor... */
4483 if (atm->p[ip] > p0)
4484 return 1;
4485 else if (atm->p[ip] < p1)
4486 return 0;
4487 else
4488 return LIN(p0, 1.0, p1, 0.0, atm->p[ip]);
4489}

◆ read_atm()

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

4496 {
4497
4498 int result;
4499
4500 /* Set timer... */
4501 SELECT_TIMER("READ_ATM", "INPUT", NVTX_READ);
4502
4503 /* Init... */
4504 atm->np = 0;
4505
4506 /* Write info... */
4507 LOG(1, "Read atmospheric data: %s", filename);
4508
4509 /* Read ASCII data... */
4510 if (ctl->atm_type == 0)
4511 result = read_atm_asc(filename, ctl, atm);
4512
4513 /* Read binary data... */
4514 else if (ctl->atm_type == 1)
4515 result = read_atm_bin(filename, ctl, atm);
4516
4517 /* Read netCDF data... */
4518 else if (ctl->atm_type == 2)
4519 result = read_atm_nc(filename, ctl, atm);
4520
4521 /* Read CLaMS data... */
4522 else if (ctl->atm_type == 3 || ctl->atm_type == 4)
4523 result = read_atm_clams(filename, ctl, atm);
4524
4525 /* Error... */
4526 else
4527 ERRMSG("Atmospheric data type not supported!");
4528
4529 /* Check result... */
4530 if (result != 1)
4531 return 0;
4532
4533 /* Check number of air parcels... */
4534 if (atm->np < 1)
4535 ERRMSG("Can not read any data!");
4536
4537 /* Write info... */
4538 double mini, maxi;
4539 LOG(2, "Number of particles: %d", atm->np);
4540 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
4541 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
4542 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
4543 LOG(2, "Altitude range: %g ... %g km", Z(maxi), Z(mini));
4544 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
4545 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
4546 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
4547 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
4548 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
4549 for (int iq = 0; iq < ctl->nq; iq++) {
4550 char msg[5 * LEN];
4551 sprintf(msg, "Quantity %s range: %s ... %s %s",
4552 ctl->qnt_name[iq], ctl->qnt_format[iq],
4553 ctl->qnt_format[iq], ctl->qnt_unit[iq]);
4554 gsl_stats_minmax(&mini, &maxi, atm->q[iq], 1, (size_t) atm->np);
4555 LOG(2, msg, mini, maxi);
4556 }
4557
4558 /* Return success... */
4559 return 1;
4560}
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:4718
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:4606
int read_atm_clams(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a CLaMS netCDF file and populates the given atmospheric structure.
Definition: mptrac.c:4662
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:4564
char qnt_format[NQ][LEN]
Quantity output format.
Definition: mptrac.h:2189
int atm_type
Type of atmospheric data files (0=ASCII, 1=binary, 2=netCDF, 3=CLaMS_traj, 4=CLaMS_pos).
Definition: mptrac.h:2932
char qnt_unit[NQ][LEN]
Quantity units.
Definition: mptrac.h:2186
char qnt_name[NQ][LEN]
Quantity names.
Definition: mptrac.h:2180
Here is the call graph for this function:

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

4567 {
4568
4569 /* Open file... */
4570 FILE *in;
4571 if (!(in = fopen(filename, "r"))) {
4572 WARN("Cannot open file!");
4573 return 0;
4574 }
4575
4576 /* Read line... */
4577 char line[LEN];
4578 while (fgets(line, LEN, in)) {
4579
4580 /* Read data... */
4581 char *tok;
4582 TOK(line, tok, "%lg", atm->time[atm->np]);
4583 TOK(NULL, tok, "%lg", atm->p[atm->np]);
4584 TOK(NULL, tok, "%lg", atm->lon[atm->np]);
4585 TOK(NULL, tok, "%lg", atm->lat[atm->np]);
4586 for (int iq = 0; iq < ctl->nq; iq++)
4587 TOK(NULL, tok, "%lg", atm->q[iq][atm->np]);
4588
4589 /* Convert altitude to pressure... */
4590 atm->p[atm->np] = P(atm->p[atm->np]);
4591
4592 /* Increment data point counter... */
4593 if ((++atm->np) > NP)
4594 ERRMSG("Too many data points!");
4595 }
4596
4597 /* Close file... */
4598 fclose(in);
4599
4600 /* Return success... */
4601 return 1;
4602}
#define TOK(line, tok, format, var)
Get string tokens.
Definition: mptrac.h:1694

◆ read_atm_bin()

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

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

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

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

This function performs the following steps:

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

The function utilizes several macros and helper functions:

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

Definition at line 4606 of file mptrac.c.

4609 {
4610
4611 /* Open file... */
4612 FILE *in;
4613 if (!(in = fopen(filename, "r")))
4614 return 0;
4615
4616 /* Check version of binary data... */
4617 int version;
4618 FREAD(&version, int,
4619 1,
4620 in);
4621 if (version != 100)
4622 ERRMSG("Wrong version of binary data!");
4623
4624 /* Read data... */
4625 FREAD(&atm->np, int,
4626 1,
4627 in);
4628 FREAD(atm->time, double,
4629 (size_t) atm->np,
4630 in);
4631 FREAD(atm->p, double,
4632 (size_t) atm->np,
4633 in);
4634 FREAD(atm->lon, double,
4635 (size_t) atm->np,
4636 in);
4637 FREAD(atm->lat, double,
4638 (size_t) atm->np,
4639 in);
4640 for (int iq = 0; iq < ctl->nq; iq++)
4641 FREAD(atm->q[iq], double,
4642 (size_t) atm->np,
4643 in);
4644
4645 /* Read final flag... */
4646 int final;
4647 FREAD(&final, int,
4648 1,
4649 in);
4650 if (final != 999)
4651 ERRMSG("Error while reading binary data!");
4652
4653 /* Close file... */
4654 fclose(in);
4655
4656 /* Return success... */
4657 return 1;
4658}

◆ read_atm_clams()

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

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

This function reads air parcel data from a CLaMS (Chemical Lagrangian Model of the Stratosphere) netCDF file and stores the data in the provided atm_t structure. It handles various coordinate systems and ensures the necessary data is correctly read and stored.

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

This function performs the following steps:

  • Attempts to open the specified netCDF file for reading.
  • Returns 0 if the file cannot be opened.
  • Retrieves the number of particles (np) from the "NPARTS" dimension.
  • Reads the initial time (TIME_INIT) if available, otherwise uses the "time" variable.
  • Reads the vertical coordinate data based on the specified system (vert_coord_ap):
    • If vert_coord_ap is 1, reads "ZETA" and optionally "PRESS".
    • Otherwise, reads "PRESS_INIT" if available, otherwise uses "PRESS".
  • Reads the longitude ("LON") and latitude ("LAT") data.
  • Closes the netCDF file.
  • Returns 1 to indicate successful data reading.

The function utilizes several macros and helper functions:

  • NC_INQ_DIM for inquiring about dimensions in the netCDF file.
  • NC_GET_DOUBLE for reading double values from the netCDF file.
  • NC for checking netCDF function return values.
  • WARN for logging warnings.
Author
Jan Clemens

Definition at line 4662 of file mptrac.c.

4665 {
4666
4667 int ncid, varid;
4668
4669 /* Open file... */
4670 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
4671 return 0;
4672
4673 /* Get dimensions... */
4674 NC_INQ_DIM("NPARTS", &atm->np, 1, NP);
4675
4676 /* Get time... */
4677 if (nc_inq_varid(ncid, "TIME_INIT", &varid) == NC_NOERR) {
4678 NC(nc_get_var_double(ncid, varid, atm->time));
4679 } else {
4680 WARN("TIME_INIT not found use time instead!");
4681 double time_init;
4682 NC_GET_DOUBLE("time", &time_init, 1);
4683 for (int ip = 0; ip < atm->np; ip++) {
4684 atm->time[ip] = time_init;
4685 }
4686 }
4687
4688 /* Read zeta coordinate, pressure is optional... */
4689 if (ctl->advect_vert_coord == 1) {
4690 NC_GET_DOUBLE("ZETA", atm->q[ctl->qnt_zeta], 1);
4691 NC_GET_DOUBLE("PRESS", atm->p, 0);
4692 }
4693
4694 /* Read pressure, zeta coordinate is optional... */
4695 else {
4696 if (nc_inq_varid(ncid, "PRESS_INIT", &varid) == NC_NOERR) {
4697 NC(nc_get_var_double(ncid, varid, atm->p));
4698 } else {
4699 WARN("PRESS_INIT not found use PRESS instead!");
4700 nc_inq_varid(ncid, "PRESS", &varid);
4701 NC(nc_get_var_double(ncid, varid, atm->p));
4702 }
4703 }
4704
4705 /* Read longitude and latitude... */
4706 NC_GET_DOUBLE("LON", atm->lon, 1);
4707 NC_GET_DOUBLE("LAT", atm->lat, 1);
4708
4709 /* Close file... */
4710 NC(nc_close(ncid));
4711
4712 /* Return success... */
4713 return 1;
4714}
#define NC(cmd)
Execute a NetCDF command and check for errors.
Definition: mptrac.h:1016
#define NC_INQ_DIM(dimname, ptr, min, max)
Inquire the length of a dimension in a NetCDF file.
Definition: mptrac.h:1103
#define NC_GET_DOUBLE(varname, ptr, force)
Retrieve a double-precision variable from a NetCDF file.
Definition: mptrac.h:1075

◆ read_atm_nc()

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

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

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

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

This function performs the following steps:

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

The function utilizes several macros and helper functions:

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

Definition at line 4718 of file mptrac.c.

4721 {
4722
4723 int ncid, varid;
4724
4725 /* Open file... */
4726 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
4727 return 0;
4728
4729 /* Get dimensions... */
4730 NC_INQ_DIM("obs", &atm->np, 1, NP);
4731
4732 /* Read geolocations... */
4733 NC_GET_DOUBLE("time", atm->time, 1);
4734 NC_GET_DOUBLE("press", atm->p, 1);
4735 NC_GET_DOUBLE("lon", atm->lon, 1);
4736 NC_GET_DOUBLE("lat", atm->lat, 1);
4737
4738 /* Read variables... */
4739 for (int iq = 0; iq < ctl->nq; iq++)
4740 NC_GET_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
4741
4742 /* Close file... */
4743 NC(nc_close(ncid));
4744
4745 /* Return success... */
4746 return 1;
4747}

◆ read_clim()

void read_clim ( const ctl_t ctl,
clim_t clim 
)

Reads various climatological data and populates the given climatology structure.

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

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

This function performs the following steps:

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

The function utilizes several helper functions:

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

Definition at line 4751 of file mptrac.c.

4753 {
4754
4755 /* Set timer... */
4756 SELECT_TIMER("READ_CLIM", "INPUT", NVTX_READ);
4757
4758 /* Init tropopause climatology... */
4759 clim_tropo_init(clim);
4760
4761 /* Read photolysis rates... */
4762 if (ctl->clim_photo[0] != '-')
4763 read_clim_photo(ctl->clim_photo, &clim->photo);
4764
4765 /* Read HNO3 climatology... */
4766 if (ctl->clim_hno3_filename[0] != '-')
4767 read_clim_zm(ctl->clim_hno3_filename, "HNO3", &clim->hno3);
4768
4769 /* Read OH climatology... */
4770 if (ctl->clim_oh_filename[0] != '-') {
4771 read_clim_zm(ctl->clim_oh_filename, "OH", &clim->oh);
4772 if (ctl->oh_chem_beta > 0)
4773 clim_oh_diurnal_correction(ctl, clim);
4774 }
4775
4776 /* Read H2O2 climatology... */
4777 if (ctl->clim_h2o2_filename[0] != '-')
4778 read_clim_zm(ctl->clim_h2o2_filename, "H2O2", &clim->h2o2);
4779
4780 /* Read HO2 climatology... */
4781 if (ctl->clim_ho2_filename[0] != '-')
4782 read_clim_zm(ctl->clim_ho2_filename, "HO2", &clim->ho2);
4783
4784 /* Read O(1D) climatology... */
4785 if (ctl->clim_o1d_filename[0] != '-')
4786 read_clim_zm(ctl->clim_o1d_filename, "O1D", &clim->o1d);
4787
4788 /* Read CFC-10 time series... */
4789 if (ctl->clim_ccl4_timeseries[0] != '-')
4791
4792 /* Read CFC-11 time series... */
4793 if (ctl->clim_ccl3f_timeseries[0] != '-')
4795
4796 /* Read CFC-12 time series... */
4797 if (ctl->clim_ccl2f2_timeseries[0] != '-')
4799
4800 /* Read N2O time series... */
4801 if (ctl->clim_n2o_timeseries[0] != '-')
4802 read_clim_ts(ctl->clim_n2o_timeseries, &clim->n2o);
4803
4804 /* Read SF6 time series... */
4805 if (ctl->clim_sf6_timeseries[0] != '-')
4806 read_clim_ts(ctl->clim_sf6_timeseries, &clim->sf6);
4807}
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:4811
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:4930
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:4984
void clim_tropo_init(clim_t *clim)
Initializes the tropopause data in the climatology structure.
Definition: mptrac.c:228
void clim_oh_diurnal_correction(const ctl_t *ctl, clim_t *clim)
Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data.
Definition: mptrac.c:116
char clim_ho2_filename[LEN]
Filename of HO2 climatology.
Definition: mptrac.h:2762
char clim_o1d_filename[LEN]
Filename of O(1D) climatology.
Definition: mptrac.h:2765
char clim_photo[LEN]
Filename of photolysis rates climatology.
Definition: mptrac.h:2750
char clim_h2o2_filename[LEN]
Filename of H2O2 climatology.
Definition: mptrac.h:2759
char clim_oh_filename[LEN]
Filename of OH climatology.
Definition: mptrac.h:2756
char clim_hno3_filename[LEN]
Filename of HNO3 climatology.
Definition: mptrac.h:2753
Here is the call graph for this function:

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

4813 {
4814
4815 int ncid, varid;
4816
4817 /* Write info... */
4818 LOG(1, "Read photolysis rates: %s", filename);
4819
4820 /* Open netCDF file... */
4821 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
4822 WARN("Photolysis rate data are missing!");
4823 return;
4824 }
4825
4826 /* Read pressure data... */
4827 NC_INQ_DIM("press", &photo->np, 2, CP);
4828 NC_GET_DOUBLE("press", photo->p, 1);
4829 if (photo->p[0] < photo->p[1])
4830 ERRMSG("Pressure data are not descending!");
4831
4832 /* Read total column ozone data... */
4833 NC_INQ_DIM("total_o3col", &photo->no3c, 2, CO3);
4834 NC_GET_DOUBLE("total_o3col", photo->o3c, 1);
4835 if (photo->o3c[0] > photo->o3c[1])
4836 ERRMSG("Total column ozone data are not ascending!");
4837
4838 /* Read solar zenith angle data... */
4839 NC_INQ_DIM("sza", &photo->nsza, 2, CSZA);
4840 NC_GET_DOUBLE("sza", photo->sza, 1);
4841 if (photo->sza[0] > photo->sza[1])
4842 ERRMSG("Solar zenith angle data are not ascending!");
4843
4844 /* Read data... */
4845 read_clim_photo_help(ncid, "J_N2O", photo, photo->n2o);
4846 read_clim_photo_help(ncid, "J_CCl4", photo, photo->ccl4);
4847 read_clim_photo_help(ncid, "J_CFC-11", photo, photo->ccl3f);
4848 read_clim_photo_help(ncid, "J_CFC-12", photo, photo->ccl2f2);
4849 read_clim_photo_help(ncid, "J_O2", photo, photo->o2);
4850 read_clim_photo_help(ncid, "J_O3b", photo, photo->o3_1);
4851 read_clim_photo_help(ncid, "J_O3a", photo, photo->o3_2);
4852 read_clim_photo_help(ncid, "J_H2O2", photo, photo->h2o2);
4853 read_clim_photo_help(ncid, "J_H2O", photo, photo->h2o);
4854
4855 /* Close netCDF file... */
4856 NC(nc_close(ncid));
4857
4858 /* Write info... */
4859 LOG(2, "Number of pressure levels: %d", photo->np);
4860 LOG(2, "Altitude levels: %g, %g ... %g km",
4861 Z(photo->p[0]), Z(photo->p[1]), Z(photo->p[photo->np - 1]));
4862 LOG(2, "Pressure levels: %g, %g ... %g hPa",
4863 photo->p[0], photo->p[1], photo->p[photo->np - 1]);
4864 LOG(2, "Number of solar zenith angles: %d", photo->nsza);
4865 LOG(2, "Solar zenith angles: %g, %g ... %g deg",
4866 RAD2DEG(photo->sza[0]), RAD2DEG(photo->sza[1]),
4867 RAD2DEG(photo->sza[photo->nsza - 1]));
4868 LOG(2, "Number of total column ozone values: %d", photo->no3c);
4869 LOG(2, "Total column ozone: %g, %g ... %g DU",
4870 photo->o3c[0], photo->o3c[1], photo->o3c[photo->no3c - 1]);
4871 LOG(2, "N2O photolysis rate: %g, %g ... %g s**-1",
4872 photo->n2o[0][0][0], photo->n2o[1][0][0],
4873 photo->n2o[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
4874 LOG(2, "CCl4 photolysis rate: %g, %g ... %g s**-1",
4875 photo->ccl4[0][0][0], photo->ccl4[1][0][0],
4876 photo->ccl4[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
4877 LOG(2, "CFC-11 photolysis rate: %g, %g ... %g s**-1",
4878 photo->ccl3f[0][0][0], photo->ccl3f[1][0][0],
4879 photo->ccl3f[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
4880 LOG(2, "CFC-12 photolysis rate: %g, %g ... %g s**-1",
4881 photo->ccl2f2[0][0][0], photo->ccl2f2[1][0][0],
4882 photo->ccl2f2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
4883 LOG(2, "O2 photolysis rate: %g, %g ... %g s**-1",
4884 photo->o2[0][0][0], photo->o2[1][0][0],
4885 photo->o2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
4886 LOG(2, "O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
4887 photo->o3_1[0][0][0], photo->o3_1[1][0][0],
4888 photo->o3_1[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
4889 LOG(2, "O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
4890 photo->o3_2[0][0][0], photo->o3_2[1][0][0],
4891 photo->o3_2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
4892 LOG(2, "H2O2 photolysis rate: %g, %g ... %g s**-1",
4893 photo->h2o2[0][0][0], photo->h2o2[1][0][0],
4894 photo->h2o2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
4895 LOG(2, "H2O photolysis rate: %g, %g ... %g s**-1",
4896 photo->h2o[0][0][0], photo->h2o[1][0][0],
4897 photo->h2o[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
4898}
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:4902
#define CP
Maximum number of pressure levels for climatological data.
Definition: mptrac.h:301
#define CO3
Maximum number of total column ozone data for climatological data.
Definition: mptrac.h:296
#define CSZA
Maximum number of solar zenith angles for climatological data.
Definition: mptrac.h:306
double o3_1[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O1d + O2) [1/s].
Definition: mptrac.h:3243
double o2[CP][CSZA][CO3]
O2 photolysis rate [1/s].
Definition: mptrac.h:3240
double h2o2[CP][CSZA][CO3]
H2O2 photolysis rate [1/s].
Definition: mptrac.h:3249
double h2o[CP][CSZA][CO3]
H2O photolysis rate [1/s].
Definition: mptrac.h:3252
double o3_2[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O3p + O2) [1/s].
Definition: mptrac.h:3246
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 4902 of file mptrac.c.

4906 {
4907
4908 /* Allocate... */
4909 double *help;
4910 ALLOC(help, double,
4911 photo->np * photo->nsza * photo->no3c);
4912
4913 /* Read varible... */
4914 int varid;
4915 NC_GET_DOUBLE(varname, help, 1);
4916
4917 /* Copy data... */
4918 for (int ip = 0; ip < photo->np; ip++)
4919 for (int is = 0; is < photo->nsza; is++)
4920 for (int io = 0; io < photo->no3c; io++)
4921 var[ip][is][io] =
4922 help[ARRAY_3D(ip, is, photo->nsza, io, photo->no3c)];
4923
4924 /* Free... */
4925 free(help);
4926}

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

4932 {
4933
4934 /* Write info... */
4935 LOG(1, "Read climatological time series: %s", filename);
4936
4937 /* Open file... */
4938 FILE *in;
4939 if (!(in = fopen(filename, "r"))) {
4940 WARN("Cannot open file!");
4941 return 0;
4942 }
4943
4944 /* Read data... */
4945 char line[LEN];
4946 int nh = 0;
4947 while (fgets(line, LEN, in))
4948 if (sscanf(line, "%lg %lg", &ts->time[nh], &ts->vmr[nh]) == 2) {
4949
4950 /* Convert years to seconds... */
4951 ts->time[nh] = (ts->time[nh] - 2000.0) * 365.25 * 86400.;
4952
4953 /* Check data... */
4954 if (nh > 0 && ts->time[nh] <= ts->time[nh - 1])
4955 ERRMSG("Time series must be ascending!");
4956
4957 /* Count time steps... */
4958 if ((++nh) >= CTS)
4959 ERRMSG("Too many data points!");
4960 }
4961
4962 /* Close file... */
4963 fclose(in);
4964
4965 /* Check number of data points... */
4966 ts->ntime = nh;
4967 if (nh < 2)
4968 ERRMSG("Not enough data points!");
4969
4970 /* Write info... */
4971 LOG(2, "Number of time steps: %d", ts->ntime);
4972 LOG(2, "Time steps: %.2f, %.2f ... %.2f s", ts->time[0], ts->time[1],
4973 ts->time[nh - 1]);
4974 LOG(2, "Volume mixing ratio range: %g ... %g ppv",
4975 gsl_stats_min(ts->vmr, 1, (size_t) nh), gsl_stats_max(ts->vmr, 1,
4976 (size_t) nh));
4977
4978 /* Exit success... */
4979 return 1;
4980}
#define CTS
Maximum number of data points of climatological time series.
Definition: mptrac.h:316

◆ read_clim_zm()

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

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

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

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

The function performs the following steps:

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

Definition at line 4984 of file mptrac.c.

4987 {
4988
4989 int ncid, varid, it, iy, iz, iz2, nt;
4990
4991 double *help, varmin = 1e99, varmax = -1e99;
4992
4993 /* Write info... */
4994 LOG(1, "Read %s data: %s", varname, filename);
4995
4996 /* Open netCDF file... */
4997 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
4998 WARN("%s climatology data are missing!", varname);
4999 return;
5000 }
5001
5002 /* Read pressure data... */
5003 NC_INQ_DIM("press", &zm->np, 2, CP);
5004 NC_GET_DOUBLE("press", zm->p, 1);
5005 if (zm->p[0] < zm->p[1])
5006 ERRMSG("Pressure data are not descending!");
5007
5008 /* Read latitudes... */
5009 NC_INQ_DIM("lat", &zm->nlat, 2, CY);
5010 NC_GET_DOUBLE("lat", zm->lat, 1);
5011 if (zm->lat[0] > zm->lat[1])
5012 ERRMSG("Latitude data are not ascending!");
5013
5014 /* Set time data (for monthly means)... */
5015 zm->ntime = 12;
5016 zm->time[0] = 1209600.00;
5017 zm->time[1] = 3888000.00;
5018 zm->time[2] = 6393600.00;
5019 zm->time[3] = 9072000.00;
5020 zm->time[4] = 11664000.00;
5021 zm->time[5] = 14342400.00;
5022 zm->time[6] = 16934400.00;
5023 zm->time[7] = 19612800.00;
5024 zm->time[8] = 22291200.00;
5025 zm->time[9] = 24883200.00;
5026 zm->time[10] = 27561600.00;
5027 zm->time[11] = 30153600.00;
5028
5029 /* Check number of timesteps... */
5030 NC_INQ_DIM("time", &nt, 12, 12);
5031
5032 /* Read data... */
5033 ALLOC(help, double,
5034 zm->nlat * zm->np * zm->ntime);
5035 NC_GET_DOUBLE(varname, help, 1);
5036 for (it = 0; it < zm->ntime; it++)
5037 for (iz = 0; iz < zm->np; iz++)
5038 for (iy = 0; iy < zm->nlat; iy++)
5039 zm->vmr[it][iz][iy] = help[ARRAY_3D(it, iz, zm->np, iy, zm->nlat)];
5040 free(help);
5041
5042 /* Fix data gaps... */
5043 for (it = 0; it < zm->ntime; it++)
5044 for (iy = 0; iy < zm->nlat; iy++)
5045 for (iz = 0; iz < zm->np; iz++) {
5046 if (zm->vmr[it][iz][iy] < 0) {
5047 for (iz2 = 0; iz2 < zm->np; iz2++)
5048 if (zm->vmr[it][iz2][iy] >= 0) {
5049 zm->vmr[it][iz][iy] = zm->vmr[it][iz2][iy];
5050 break;
5051 }
5052 for (iz2 = zm->np - 1; iz2 >= 0; iz2--)
5053 if (zm->vmr[it][iz2][iy] >= 0) {
5054 zm->vmr[it][iz][iy] = zm->vmr[it][iz2][iy];
5055 break;
5056 }
5057 }
5058 varmin = MIN(varmin, zm->vmr[it][iz][iy]);
5059 varmax = MAX(varmax, zm->vmr[it][iz][iy]);
5060 }
5061
5062 /* Close netCDF file... */
5063 NC(nc_close(ncid));
5064
5065 /* Write info... */
5066 LOG(2, "Number of time steps: %d", zm->ntime);
5067 LOG(2, "Time steps: %.2f, %.2f ... %.2f s",
5068 zm->time[0], zm->time[1], zm->time[zm->ntime - 1]);
5069 LOG(2, "Number of pressure levels: %d", zm->np);
5070 LOG(2, "Altitude levels: %g, %g ... %g km",
5071 Z(zm->p[0]), Z(zm->p[1]), Z(zm->p[zm->np - 1]));
5072 LOG(2, "Pressure levels: %g, %g ... %g hPa", zm->p[0],
5073 zm->p[1], zm->p[zm->np - 1]);
5074 LOG(2, "Number of latitudes: %d", zm->nlat);
5075 LOG(2, "Latitudes: %g, %g ... %g deg",
5076 zm->lat[0], zm->lat[1], zm->lat[zm->nlat - 1]);
5077 LOG(2, "%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
5078 varmax);
5079}
#define CY
Maximum number of latitudes for climatological data.
Definition: mptrac.h:291

◆ read_ctl()

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

5087 {
5088
5089 /* Set timer... */
5090 SELECT_TIMER("READ_CTL", "INPUT", NVTX_READ);
5091
5092 /* Write info... */
5093 LOG(1, "\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
5094 "(executable: %s | version: %s | compiled: %s, %s)\n",
5095 argv[0], VERSION, __DATE__, __TIME__);
5096
5097 /* Initialize quantity indices... */
5098 ctl->qnt_idx = -1;
5099 ctl->qnt_ens = -1;
5100 ctl->qnt_stat = -1;
5101 ctl->qnt_m = -1;
5102 ctl->qnt_vmr = -1;
5103 ctl->qnt_rp = -1;
5104 ctl->qnt_rhop = -1;
5105 ctl->qnt_ps = -1;
5106 ctl->qnt_ts = -1;
5107 ctl->qnt_zs = -1;
5108 ctl->qnt_us = -1;
5109 ctl->qnt_vs = -1;
5110 ctl->qnt_ess = -1;
5111 ctl->qnt_nss = -1;
5112 ctl->qnt_shf = -1;
5113 ctl->qnt_lsm = -1;
5114 ctl->qnt_sst = -1;
5115 ctl->qnt_pbl = -1;
5116 ctl->qnt_pt = -1;
5117 ctl->qnt_tt = -1;
5118 ctl->qnt_zt = -1;
5119 ctl->qnt_h2ot = -1;
5120 ctl->qnt_zg = -1;
5121 ctl->qnt_p = -1;
5122 ctl->qnt_t = -1;
5123 ctl->qnt_rho = -1;
5124 ctl->qnt_u = -1;
5125 ctl->qnt_v = -1;
5126 ctl->qnt_w = -1;
5127 ctl->qnt_h2o = -1;
5128 ctl->qnt_o3 = -1;
5129 ctl->qnt_lwc = -1;
5130 ctl->qnt_rwc = -1;
5131 ctl->qnt_iwc = -1;
5132 ctl->qnt_swc = -1;
5133 ctl->qnt_cc = -1;
5134 ctl->qnt_pct = -1;
5135 ctl->qnt_pcb = -1;
5136 ctl->qnt_cl = -1;
5137 ctl->qnt_plcl = -1;
5138 ctl->qnt_plfc = -1;
5139 ctl->qnt_pel = -1;
5140 ctl->qnt_cape = -1;
5141 ctl->qnt_cin = -1;
5142 ctl->qnt_o3c = -1;
5143 ctl->qnt_hno3 = -1;
5144 ctl->qnt_oh = -1;
5145 ctl->qnt_h2o2 = -1;
5146 ctl->qnt_ho2 = -1;
5147 ctl->qnt_o1d = -1;
5148 ctl->qnt_mloss_oh = -1;
5149 ctl->qnt_mloss_h2o2 = -1;
5150 ctl->qnt_mloss_kpp = -1;
5151 ctl->qnt_mloss_wet = -1;
5152 ctl->qnt_mloss_dry = -1;
5153 ctl->qnt_mloss_decay = -1;
5154 ctl->qnt_loss_rate = -1;
5155 ctl->qnt_psat = -1;
5156 ctl->qnt_psice = -1;
5157 ctl->qnt_pw = -1;
5158 ctl->qnt_sh = -1;
5159 ctl->qnt_rh = -1;
5160 ctl->qnt_rhice = -1;
5161 ctl->qnt_theta = -1;
5162 ctl->qnt_zeta = -1;
5163 ctl->qnt_zeta_d = -1;
5164 ctl->qnt_tvirt = -1;
5165 ctl->qnt_lapse = -1;
5166 ctl->qnt_vh = -1;
5167 ctl->qnt_vz = -1;
5168 ctl->qnt_pv = -1;
5169 ctl->qnt_tdew = -1;
5170 ctl->qnt_tice = -1;
5171 ctl->qnt_tsts = -1;
5172 ctl->qnt_tnat = -1;
5173 ctl->qnt_Cx = -1;
5174 ctl->qnt_Ch2o = -1;
5175 ctl->qnt_Co3 = -1;
5176 ctl->qnt_Cco = -1;
5177 ctl->qnt_Coh = -1;
5178 ctl->qnt_Ch = -1;
5179 ctl->qnt_Cho2 = -1;
5180 ctl->qnt_Ch2o2 = -1;
5181 ctl->qnt_Co1d = -1;
5182 ctl->qnt_Co3p = -1;
5183 ctl->qnt_Cccl4 = -1;
5184 ctl->qnt_Cccl3f = -1;
5185 ctl->qnt_Cccl2f2 = -1;
5186 ctl->qnt_Cn2o = -1;
5187 ctl->qnt_Csf6 = -1;
5188 ctl->qnt_aoa = -1;
5189
5190 /* Read quantities... */
5191 ctl->nq = (int) scan_ctl(filename, argc, argv, "NQ", -1, "0", NULL);
5192 if (ctl->nq > NQ)
5193 ERRMSG("Too many quantities!");
5194 for (int iq = 0; iq < ctl->nq; iq++) {
5195
5196 /* Read quantity name and format... */
5197 scan_ctl(filename, argc, argv, "QNT_NAME", iq, "", ctl->qnt_name[iq]);
5198 scan_ctl(filename, argc, argv, "QNT_LONGNAME", iq, ctl->qnt_name[iq],
5199 ctl->qnt_longname[iq]);
5200 scan_ctl(filename, argc, argv, "QNT_FORMAT", iq, "%g",
5201 ctl->qnt_format[iq]);
5202 if (strcasecmp(ctl->qnt_name[iq], "aoa") == 0)
5203 sprintf(ctl->qnt_format[iq], "%%.2f");
5204
5205 /* Try to identify quantity... */
5206 SET_QNT(qnt_idx, "idx", "particle index", "-")
5207 SET_QNT(qnt_ens, "ens", "ensemble index", "-")
5208 SET_QNT(qnt_stat, "stat", "station flag", "-")
5209 SET_QNT(qnt_m, "m", "mass", "kg")
5210 SET_QNT(qnt_vmr, "vmr", "volume mixing ratio", "ppv")
5211 SET_QNT(qnt_rp, "rp", "particle radius", "microns")
5212 SET_QNT(qnt_rhop, "rhop", "particle density", "kg/m^3")
5213 SET_QNT(qnt_ps, "ps", "surface pressure", "hPa")
5214 SET_QNT(qnt_ts, "ts", "surface temperature", "K")
5215 SET_QNT(qnt_zs, "zs", "surface height", "km")
5216 SET_QNT(qnt_us, "us", "surface zonal wind", "m/s")
5217 SET_QNT(qnt_vs, "vs", "surface meridional wind", "m/s")
5218 SET_QNT(qnt_ess, "ess", "eastward turbulent surface stress", "N/m^2")
5219 SET_QNT(qnt_nss, "nss", "northward turbulent surface stress", "N/m^2")
5220 SET_QNT(qnt_shf, "shf", "surface sensible heat flux", "W/m^2")
5221 SET_QNT(qnt_lsm, "lsm", "land-sea mask", "1")
5222 SET_QNT(qnt_sst, "sst", "sea surface temperature", "K")
5223 SET_QNT(qnt_pbl, "pbl", "planetary boundary layer", "hPa")
5224 SET_QNT(qnt_pt, "pt", "tropopause pressure", "hPa")
5225 SET_QNT(qnt_tt, "tt", "tropopause temperature", "K")
5226 SET_QNT(qnt_zt, "zt", "tropopause geopotential height", "km")
5227 SET_QNT(qnt_h2ot, "h2ot", "tropopause water vapor", "ppv")
5228 SET_QNT(qnt_zg, "zg", "geopotential height", "km")
5229 SET_QNT(qnt_p, "p", "pressure", "hPa")
5230 SET_QNT(qnt_t, "t", "temperature", "K")
5231 SET_QNT(qnt_rho, "rho", "air density", "kg/m^3")
5232 SET_QNT(qnt_u, "u", "zonal wind", "m/s")
5233 SET_QNT(qnt_v, "v", "meridional wind", "m/s")
5234 SET_QNT(qnt_w, "w", "vertical velocity", "hPa/s")
5235 SET_QNT(qnt_h2o, "h2o", "water vapor", "ppv")
5236 SET_QNT(qnt_o3, "o3", "ozone", "ppv")
5237 SET_QNT(qnt_lwc, "lwc", "cloud liquid water content", "kg/kg")
5238 SET_QNT(qnt_rwc, "rwc", "cloud rain water content", "kg/kg")
5239 SET_QNT(qnt_iwc, "iwc", "cloud ice water content", "kg/kg")
5240 SET_QNT(qnt_swc, "iwc", "cloud snow water content", "kg/kg")
5241 SET_QNT(qnt_cc, "cc", "cloud cover", "1")
5242 SET_QNT(qnt_pct, "pct", "cloud top pressure", "hPa")
5243 SET_QNT(qnt_pcb, "pcb", "cloud bottom pressure", "hPa")
5244 SET_QNT(qnt_cl, "cl", "total column cloud water", "kg/m^2")
5245 SET_QNT(qnt_plcl, "plcl", "lifted condensation level", "hPa")
5246 SET_QNT(qnt_plfc, "plfc", "level of free convection", "hPa")
5247 SET_QNT(qnt_pel, "pel", "equilibrium level", "hPa")
5248 SET_QNT(qnt_cape, "cape", "convective available potential energy",
5249 "J/kg")
5250 SET_QNT(qnt_cin, "cin", "convective inhibition", "J/kg")
5251 SET_QNT(qnt_o3c, "o3c", "total column ozone", "DU")
5252 SET_QNT(qnt_hno3, "hno3", "nitric acid", "ppv")
5253 SET_QNT(qnt_oh, "oh", "hydroxyl radical", "ppv")
5254 SET_QNT(qnt_h2o2, "h2o2", "hydrogen peroxide", "ppv")
5255 SET_QNT(qnt_ho2, "ho2", "hydroperoxyl radical", "ppv")
5256 SET_QNT(qnt_o1d, "o1d", "atomic oxygen", "ppv")
5257 SET_QNT(qnt_mloss_oh, "mloss_oh", "mass loss due to OH chemistry", "kg")
5258 SET_QNT(qnt_mloss_h2o2, "mloss_h2o2", "mass loss due to H2O2 chemistry",
5259 "kg")
5260 SET_QNT(qnt_mloss_kpp, "mloss_kpp", "mass loss due to kpp chemistry",
5261 "kg")
5262 SET_QNT(qnt_mloss_wet, "mloss_wet", "mass loss due to wet deposition",
5263 "kg")
5264 SET_QNT(qnt_mloss_dry, "mloss_dry", "mass loss due to dry deposition",
5265 "kg")
5266 SET_QNT(qnt_mloss_decay, "mloss_decay",
5267 "mass loss due to exponential decay", "kg")
5268 SET_QNT(qnt_loss_rate, "loss_rate", "total loss rate", "s^-1")
5269 SET_QNT(qnt_psat, "psat", "saturation pressure over water", "hPa")
5270 SET_QNT(qnt_psice, "psice", "saturation pressure over ice", "hPa")
5271 SET_QNT(qnt_pw, "pw", "partial water vapor pressure", "hPa")
5272 SET_QNT(qnt_sh, "sh", "specific humidity", "kg/kg")
5273 SET_QNT(qnt_rh, "rh", "relative humidity", "%%")
5274 SET_QNT(qnt_rhice, "rhice", "relative humidity over ice", "%%")
5275 SET_QNT(qnt_theta, "theta", "potential temperature", "K")
5276 SET_QNT(qnt_zeta, "zeta", "zeta coordinate", "K")
5277 SET_QNT(qnt_zeta_d, "zeta_d", "diagnosed zeta coordinate", "K")
5278 SET_QNT(qnt_tvirt, "tvirt", "virtual temperature", "K")
5279 SET_QNT(qnt_lapse, "lapse", "temperature lapse rate", "K/km")
5280 SET_QNT(qnt_vh, "vh", "horizontal velocity", "m/s")
5281 SET_QNT(qnt_vz, "vz", "vertical velocity", "m/s")
5282 SET_QNT(qnt_pv, "pv", "potential vorticity", "PVU")
5283 SET_QNT(qnt_tdew, "tdew", "dew point temperature", "K")
5284 SET_QNT(qnt_tice, "tice", "frost point temperature", "K")
5285 SET_QNT(qnt_tsts, "tsts", "STS existence temperature", "K")
5286 SET_QNT(qnt_tnat, "tnat", "NAT existence temperature", "K")
5287 SET_QNT(qnt_Cx, "Cx", "Trace species x volume mixing ratio", "ppv")
5288 SET_QNT(qnt_Ch2o, "Ch2o", "H2O volume mixing ratio", "ppv")
5289 SET_QNT(qnt_Co3, "Co3", "O3 volume mixing ratio", "ppv")
5290 SET_QNT(qnt_Cco, "Cco", "CO volume mixing ratio", "ppv")
5291 SET_QNT(qnt_Coh, "Coh", "HO volume mixing ratio", "ppv")
5292 SET_QNT(qnt_Ch, "Ch", "H radical volume mixing ratio", "ppv")
5293 SET_QNT(qnt_Cho2, "Cho2", "HO2 volume mixing ratio", "ppv")
5294 SET_QNT(qnt_Ch2o2, "Ch2o2", "H2O2 volume mixing ratio", "ppv")
5295 SET_QNT(qnt_Co1d, "Co1d", "O(1D) volume mixing ratio", "ppv")
5296 SET_QNT(qnt_Co3p, "Co3p", "O(3P) radical volume mixing ratio", "ppv")
5297 SET_QNT(qnt_Cccl4, "Cccl4", "CCl4 (CFC-10) volume mixing ratio", "ppv")
5298 SET_QNT(qnt_Cccl3f, "Cccl3f", "CCl3F (CFC-11) volume mixing ratio",
5299 "ppv")
5300 SET_QNT(qnt_Cccl2f2, "Cccl2f2", "CCl2F2 (CFC-12) volume mixing ratio",
5301 "ppv")
5302 SET_QNT(qnt_Cn2o, "Cn2o", "N2O volume mixing ratio", "ppv")
5303 SET_QNT(qnt_Csf6, "Csf6", "SF6 volume mixing ratio", "ppv")
5304 SET_QNT(qnt_aoa, "aoa", "age of air", "s")
5305 scan_ctl(filename, argc, argv, "QNT_UNIT", iq, "", ctl->qnt_unit[iq]);
5306 }
5307
5308 /* Vertical coordinates and velocities... */
5309 ctl->advect_vert_coord =
5310 (int) scan_ctl(filename, argc, argv, "ADVECT_VERT_COORD", -1, "0", NULL);
5311 if (ctl->advect_vert_coord < 0 || ctl->advect_vert_coord > 2)
5312 ERRMSG("Set advect_vert_coord to 0, 1, or 2!");
5313 if (ctl->advect_vert_coord == 1 && ctl->qnt_zeta < 0)
5314 ERRMSG("Please add zeta to your quantities for diabatic calculations!");
5315 ctl->met_vert_coord =
5316 (int) scan_ctl(filename, argc, argv, "MET_VERT_COORD", -1, "0", NULL);
5317 if (ctl->advect_vert_coord == 2 && ctl->met_vert_coord != 1)
5318 ERRMSG
5319 ("Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
5320
5321 /* Time steps of simulation... */
5322 ctl->direction =
5323 (int) scan_ctl(filename, argc, argv, "DIRECTION", -1, "1", NULL);
5324 if (ctl->direction != -1 && ctl->direction != 1)
5325 ERRMSG("Set DIRECTION to -1 or 1!");
5326 ctl->t_stop = scan_ctl(filename, argc, argv, "T_STOP", -1, "1e100", NULL);
5327 ctl->dt_mod = scan_ctl(filename, argc, argv, "DT_MOD", -1, "180", NULL);
5328
5329 /* Meteo data... */
5330 scan_ctl(filename, argc, argv, "METBASE", -1, "-", ctl->metbase);
5331 ctl->dt_met = scan_ctl(filename, argc, argv, "DT_MET", -1, "3600", NULL);
5332 ctl->met_convention =
5333 (int) scan_ctl(filename, argc, argv, "MET_CONVENTION", -1, "0", NULL);
5334 ctl->met_type =
5335 (int) scan_ctl(filename, argc, argv, "MET_TYPE", -1, "0", NULL);
5336 if (ctl->advect_vert_coord == 1 && ctl->met_type != 0)
5337 ERRMSG
5338 ("Please use meteorological files in netcdf format for diabatic calculations.");
5339 ctl->met_clams =
5340 (int) scan_ctl(filename, argc, argv, "MET_CLAMS", -1, "0", NULL);
5341 ctl->met_nc_scale =
5342 (int) scan_ctl(filename, argc, argv, "MET_NC_SCALE", -1, "1", NULL);
5343 ctl->met_nc_level =
5344 (int) scan_ctl(filename, argc, argv, "MET_NC_LEVEL", -1, "0", NULL);
5345 ctl->met_nc_quant =
5346 (int) scan_ctl(filename, argc, argv, "MET_NC_QUANT", -1, "0", NULL);
5347 ctl->met_zfp_prec =
5348 (int) scan_ctl(filename, argc, argv, "MET_ZFP_PREC", -1, "8", NULL);
5349 ctl->met_zfp_tol_t =
5350 scan_ctl(filename, argc, argv, "MET_ZFP_TOL_T", -1, "5.0", NULL);
5351 ctl->met_zfp_tol_z =
5352 scan_ctl(filename, argc, argv, "MET_ZFP_TOL_Z", -1, "0.5", NULL);
5353 ctl->met_cms_batch =
5354 (int) scan_ctl(filename, argc, argv, "MET_CMS_BATCH", -1, "-1", NULL);
5355 ctl->met_cms_heur =
5356 (int) scan_ctl(filename, argc, argv, "MET_CMS_HEUR", -1, "1", NULL);
5357 ctl->met_cms_eps_z =
5358 scan_ctl(filename, argc, argv, "MET_CMS_EPS_Z", -1, "1.0", NULL);
5359 ctl->met_cms_eps_t =
5360 scan_ctl(filename, argc, argv, "MET_CMS_EPS_T", -1, "0.05", NULL);
5361 ctl->met_cms_eps_u =
5362 scan_ctl(filename, argc, argv, "MET_CMS_EPS_U", -1, "0.05", NULL);
5363 ctl->met_cms_eps_v =
5364 scan_ctl(filename, argc, argv, "MET_CMS_EPS_V", -1, "0.05", NULL);
5365 ctl->met_cms_eps_w =
5366 scan_ctl(filename, argc, argv, "MET_CMS_EPS_W", -1, "1.0", NULL);
5367 ctl->met_cms_eps_pv =
5368 scan_ctl(filename, argc, argv, "MET_CMS_EPS_PV", -1, "1.0", NULL);
5369 ctl->met_cms_eps_h2o =
5370 scan_ctl(filename, argc, argv, "MET_CMS_EPS_H2O", -1, "1.0", NULL);
5371 ctl->met_cms_eps_o3 =
5372 scan_ctl(filename, argc, argv, "MET_CMS_EPS_O3", -1, "1.0", NULL);
5373 ctl->met_cms_eps_lwc =
5374 scan_ctl(filename, argc, argv, "MET_CMS_EPS_LWC", -1, "1.0", NULL);
5375 ctl->met_cms_eps_rwc =
5376 scan_ctl(filename, argc, argv, "MET_CMS_EPS_RWC", -1, "1.0", NULL);
5377 ctl->met_cms_eps_iwc =
5378 scan_ctl(filename, argc, argv, "MET_CMS_EPS_IWC", -1, "1.0", NULL);
5379 ctl->met_cms_eps_swc =
5380 scan_ctl(filename, argc, argv, "MET_CMS_EPS_SWC", -1, "1.0", NULL);
5381 ctl->met_cms_eps_cc =
5382 scan_ctl(filename, argc, argv, "MET_CMS_EPS_CC", -1, "1.0", NULL);
5383 ctl->met_dx = (int) scan_ctl(filename, argc, argv, "MET_DX", -1, "1", NULL);
5384 ctl->met_dy = (int) scan_ctl(filename, argc, argv, "MET_DY", -1, "1", NULL);
5385 ctl->met_dp = (int) scan_ctl(filename, argc, argv, "MET_DP", -1, "1", NULL);
5386 if (ctl->met_dx < 1 || ctl->met_dy < 1 || ctl->met_dp < 1)
5387 ERRMSG("MET_DX, MET_DY, and MET_DP need to be greater than zero!");
5388 ctl->met_sx = (int) scan_ctl(filename, argc, argv, "MET_SX", -1, "1", NULL);
5389 ctl->met_sy = (int) scan_ctl(filename, argc, argv, "MET_SY", -1, "1", NULL);
5390 ctl->met_sp = (int) scan_ctl(filename, argc, argv, "MET_SP", -1, "1", NULL);
5391 if (ctl->met_sx < 1 || ctl->met_sy < 1 || ctl->met_sp < 1)
5392 ERRMSG("MET_SX, MET_SY, and MET_SP need to be greater than zero!");
5393 ctl->met_detrend =
5394 scan_ctl(filename, argc, argv, "MET_DETREND", -1, "-999", NULL);
5395 ctl->met_np = (int) scan_ctl(filename, argc, argv, "MET_NP", -1, "0", NULL);
5396 if (ctl->met_np > EP)
5397 ERRMSG("Too many levels!");
5398 ctl->met_press_level_def =
5399 (int) scan_ctl(filename, argc, argv, "MET_PRESS_LEVEL_DEF", -1, "-1",
5400 NULL);
5401 if (ctl->met_press_level_def >= 0) {
5402 level_definitions(ctl);
5403 } else {
5404 if (ctl->met_np > 0) {
5405 for (int ip = 0; ip < ctl->met_np; ip++)
5406 ctl->met_p[ip] =
5407 scan_ctl(filename, argc, argv, "MET_P", ip, "", NULL);
5408 }
5409 }
5410 ctl->met_geopot_sx =
5411 (int) scan_ctl(filename, argc, argv, "MET_GEOPOT_SX", -1, "-1", NULL);
5412 ctl->met_geopot_sy =
5413 (int) scan_ctl(filename, argc, argv, "MET_GEOPOT_SY", -1, "-1", NULL);
5414 ctl->met_relhum =
5415 (int) scan_ctl(filename, argc, argv, "MET_RELHUM", -1, "0", NULL);
5416 ctl->met_cape =
5417 (int) scan_ctl(filename, argc, argv, "MET_CAPE", -1, "1", NULL);
5418 if (ctl->met_cape < 0 || ctl->met_cape > 1)
5419 ERRMSG("Set MET_CAPE to 0 or 1!");
5420 ctl->met_pbl =
5421 (int) scan_ctl(filename, argc, argv, "MET_PBL", -1, "3", NULL);
5422 if (ctl->met_pbl < 0 || ctl->met_pbl > 3)
5423 ERRMSG("Set MET_PBL to 0 ... 3!");
5424 ctl->met_pbl_min =
5425 scan_ctl(filename, argc, argv, "MET_PBL_MIN", -1, "0.1", NULL);
5426 ctl->met_pbl_max =
5427 scan_ctl(filename, argc, argv, "MET_PBL_MAX", -1, "5.0", NULL);
5428 ctl->met_tropo =
5429 (int) scan_ctl(filename, argc, argv, "MET_TROPO", -1, "3", NULL);
5430 if (ctl->met_tropo < 0 || ctl->met_tropo > 5)
5431 ERRMSG("Set MET_TROPO to 0 ... 5!");
5432 ctl->met_tropo_pv =
5433 scan_ctl(filename, argc, argv, "MET_TROPO_PV", -1, "3.5", NULL);
5434 ctl->met_tropo_theta =
5435 scan_ctl(filename, argc, argv, "MET_TROPO_THETA", -1, "380", NULL);
5436 ctl->met_tropo_spline =
5437 (int) scan_ctl(filename, argc, argv, "MET_TROPO_SPLINE", -1, "1", NULL);
5438 ctl->met_dt_out =
5439 scan_ctl(filename, argc, argv, "MET_DT_OUT", -1, "0.1", NULL);
5440 ctl->met_cache =
5441 (int) scan_ctl(filename, argc, argv, "MET_CACHE", -1, "0", NULL);
5442 ctl->met_mpi_share =
5443 (int) scan_ctl(filename, argc, argv, "MET_MPI_SHARE", -1, "0", NULL);
5444
5445 /* Sorting... */
5446 ctl->sort_dt = scan_ctl(filename, argc, argv, "SORT_DT", -1, "-999", NULL);
5447
5448 /* Isosurface parameters... */
5449 ctl->isosurf =
5450 (int) scan_ctl(filename, argc, argv, "ISOSURF", -1, "0", NULL);
5451 scan_ctl(filename, argc, argv, "BALLOON", -1, "-", ctl->balloon);
5452
5453 /* Random number generator... */
5454 ctl->rng_type =
5455 (int) scan_ctl(filename, argc, argv, "RNG_TYPE", -1, "1", NULL);
5456 if (ctl->rng_type < 0 || ctl->rng_type > 2)
5457 ERRMSG("Set RNG_TYPE to 0, 1, or 2!");
5458
5459 /* Advection parameters... */
5460 ctl->advect = (int) scan_ctl(filename, argc, argv, "ADVECT", -1, "2", NULL);
5461 if (!(ctl->advect == 0 || ctl->advect == 1
5462 || ctl->advect == 2 || ctl->advect == 4))
5463 ERRMSG("Set ADVECT to 0, 1, 2, or 4!");
5464
5465 /* Diffusion parameters... */
5466 ctl->diffusion
5467 = (int) scan_ctl(filename, argc, argv, "DIFFUSION", -1, "0", NULL);
5468 if (ctl->diffusion < 0 || ctl->diffusion > 2)
5469 ERRMSG("Set DIFFUSION to 0, 1 or 2!");
5470 ctl->turb_dx_pbl =
5471 scan_ctl(filename, argc, argv, "TURB_DX_PBL", -1, "50", NULL);
5472 ctl->turb_dx_trop =
5473 scan_ctl(filename, argc, argv, "TURB_DX_TROP", -1, "50", NULL);
5474 ctl->turb_dx_strat =
5475 scan_ctl(filename, argc, argv, "TURB_DX_STRAT", -1, "0", NULL);
5476 ctl->turb_dz_pbl =
5477 scan_ctl(filename, argc, argv, "TURB_DZ_PBL", -1, "0", NULL);
5478 ctl->turb_dz_trop =
5479 scan_ctl(filename, argc, argv, "TURB_DZ_TROP", -1, "0", NULL);
5480 ctl->turb_dz_strat =
5481 scan_ctl(filename, argc, argv, "TURB_DZ_STRAT", -1, "0.1", NULL);
5482 ctl->turb_mesox =
5483 scan_ctl(filename, argc, argv, "TURB_MESOX", -1, "0.16", NULL);
5484 ctl->turb_mesoz =
5485 scan_ctl(filename, argc, argv, "TURB_MESOZ", -1, "0.16", NULL);
5486
5487 /* Convection... */
5488 ctl->conv_mix_pbl
5489 = (int) scan_ctl(filename, argc, argv, "CONV_MIX_PBL", -1, "0", NULL);
5490 ctl->conv_pbl_trans
5491 = scan_ctl(filename, argc, argv, "CONV_PBL_TRANS", -1, "0", NULL);
5492 ctl->conv_cape
5493 = scan_ctl(filename, argc, argv, "CONV_CAPE", -1, "-999", NULL);
5494 ctl->conv_cin
5495 = scan_ctl(filename, argc, argv, "CONV_CIN", -1, "-999", NULL);
5496 ctl->conv_dt = scan_ctl(filename, argc, argv, "CONV_DT", -1, "-999", NULL);
5497
5498 /* Boundary conditions... */
5499 ctl->bound_mass =
5500 scan_ctl(filename, argc, argv, "BOUND_MASS", -1, "-999", NULL);
5501 ctl->bound_mass_trend =
5502 scan_ctl(filename, argc, argv, "BOUND_MASS_TREND", -1, "0", NULL);
5503 ctl->bound_vmr =
5504 scan_ctl(filename, argc, argv, "BOUND_VMR", -1, "-999", NULL);
5505 ctl->bound_vmr_trend =
5506 scan_ctl(filename, argc, argv, "BOUND_VMR_TREND", -1, "0", NULL);
5507 ctl->bound_lat0 =
5508 scan_ctl(filename, argc, argv, "BOUND_LAT0", -1, "-999", NULL);
5509 ctl->bound_lat1 =
5510 scan_ctl(filename, argc, argv, "BOUND_LAT1", -1, "-999", NULL);
5511 ctl->bound_p0 =
5512 scan_ctl(filename, argc, argv, "BOUND_P0", -1, "-999", NULL);
5513 ctl->bound_p1 =
5514 scan_ctl(filename, argc, argv, "BOUND_P1", -1, "-999", NULL);
5515 ctl->bound_dps =
5516 scan_ctl(filename, argc, argv, "BOUND_DPS", -1, "-999", NULL);
5517 ctl->bound_dzs =
5518 scan_ctl(filename, argc, argv, "BOUND_DZS", -1, "-999", NULL);
5519 ctl->bound_zetas =
5520 scan_ctl(filename, argc, argv, "BOUND_ZETAS", -1, "-999", NULL);
5521 ctl->bound_pbl =
5522 (int) scan_ctl(filename, argc, argv, "BOUND_PBL", -1, "0", NULL);
5523
5524 /* Species parameters... */
5525 scan_ctl(filename, argc, argv, "SPECIES", -1, "-", ctl->species);
5526 if (strcasecmp(ctl->species, "CF2Cl2") == 0) {
5527 ctl->molmass = 120.907;
5528 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 3e-5;
5529 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3500.0;
5530 } else if (strcasecmp(ctl->species, "CFCl3") == 0) {
5531 ctl->molmass = 137.359;
5532 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.1e-4;
5533 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3300.0;
5534 } else if (strcasecmp(ctl->species, "CH4") == 0) {
5535 ctl->molmass = 16.043;
5536 ctl->oh_chem_reaction = 2;
5537 ctl->oh_chem[0] = 2.45e-12;
5538 ctl->oh_chem[1] = 1775;
5539 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.4e-5;
5540 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1600.0;
5541 } else if (strcasecmp(ctl->species, "CO") == 0) {
5542 ctl->molmass = 28.01;
5543 ctl->oh_chem_reaction = 3;
5544 ctl->oh_chem[0] = 6.9e-33;
5545 ctl->oh_chem[1] = 2.1;
5546 ctl->oh_chem[2] = 1.1e-12;
5547 ctl->oh_chem[3] = -1.3;
5548 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 9.7e-6;
5549 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1300.0;
5550 } else if (strcasecmp(ctl->species, "CO2") == 0) {
5551 ctl->molmass = 44.009;
5552 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 3.3e-4;
5553 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2400.0;
5554 } else if (strcasecmp(ctl->species, "H2O") == 0) {
5555 ctl->molmass = 18.01528;
5556 } else if (strcasecmp(ctl->species, "N2O") == 0) {
5557 ctl->molmass = 44.013;
5558 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.4e-4;
5559 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2600.;
5560 } else if (strcasecmp(ctl->species, "NH3") == 0) {
5561 ctl->molmass = 17.031;
5562 ctl->oh_chem_reaction = 2;
5563 ctl->oh_chem[0] = 1.7e-12;
5564 ctl->oh_chem[1] = 710;
5565 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 5.9e-1;
5566 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 4200.0;
5567 } else if (strcasecmp(ctl->species, "HNO3") == 0) {
5568 ctl->molmass = 63.012;
5569 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.1e3;
5570 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 8700.0;
5571 } else if (strcasecmp(ctl->species, "NO") == 0) {
5572 ctl->molmass = 30.006;
5573 ctl->oh_chem_reaction = 3;
5574 ctl->oh_chem[0] = 7.1e-31;
5575 ctl->oh_chem[1] = 2.6;
5576 ctl->oh_chem[2] = 3.6e-11;
5577 ctl->oh_chem[3] = 0.1;
5578 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.9e-5;
5579 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1600.0;
5580 } else if (strcasecmp(ctl->species, "NO2") == 0) {
5581 ctl->molmass = 46.005;
5582 ctl->oh_chem_reaction = 3;
5583 ctl->oh_chem[0] = 1.8e-30;
5584 ctl->oh_chem[1] = 3.0;
5585 ctl->oh_chem[2] = 2.8e-11;
5586 ctl->oh_chem[3] = 0.0;
5587 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.2e-4;
5588 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2400.0;
5589 } else if (strcasecmp(ctl->species, "O3") == 0) {
5590 ctl->molmass = 47.997;
5591 ctl->oh_chem_reaction = 2;
5592 ctl->oh_chem[0] = 1.7e-12;
5593 ctl->oh_chem[1] = 940;
5594 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1e-4;
5595 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2800.0;
5596 } else if (strcasecmp(ctl->species, "SF6") == 0) {
5597 ctl->molmass = 146.048;
5598 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.4e-6;
5599 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3100.0;
5600 } else if (strcasecmp(ctl->species, "SO2") == 0) {
5601 ctl->molmass = 64.066;
5602 ctl->oh_chem_reaction = 3;
5603 ctl->oh_chem[0] = 2.9e-31;
5604 ctl->oh_chem[1] = 4.1;
5605 ctl->oh_chem[2] = 1.7e-12;
5606 ctl->oh_chem[3] = -0.2;
5607 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.3e-2;
5608 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2900.0;
5609 }
5610
5611 /* Molar mass... */
5612 char defstr[LEN];
5613 sprintf(defstr, "%g", ctl->molmass);
5614 ctl->molmass = scan_ctl(filename, argc, argv, "MOLMASS", -1, defstr, NULL);
5615
5616 /* OH chemistry... */
5617 sprintf(defstr, "%d", ctl->oh_chem_reaction);
5618 ctl->oh_chem_reaction =
5619 (int) scan_ctl(filename, argc, argv, "OH_CHEM_REACTION", -1, defstr,
5620 NULL);
5621 for (int ip = 0; ip < 4; ip++) {
5622 sprintf(defstr, "%g", ctl->oh_chem[ip]);
5623 ctl->oh_chem[ip] =
5624 scan_ctl(filename, argc, argv, "OH_CHEM", ip, defstr, NULL);
5625 }
5626 ctl->oh_chem_beta =
5627 scan_ctl(filename, argc, argv, "OH_CHEM_BETA", -1, "0", NULL);
5628
5629 /* H2O2 chemistry... */
5630 ctl->h2o2_chem_reaction =
5631 (int) scan_ctl(filename, argc, argv, "H2O2_CHEM_REACTION", -1, "0", NULL);
5632
5633 /* KPP chemistry... */
5634 ctl->kpp_chem =
5635 (int) scan_ctl(filename, argc, argv, "KPP_CHEM", -1, "0", NULL);
5636 ctl->dt_kpp = scan_ctl(filename, argc, argv, "DT_KPP", -1, "1800", NULL);
5637
5638 /* First order tracer chemistry... */
5639 ctl->tracer_chem =
5640 (int) scan_ctl(filename, argc, argv, "TRACER_CHEM", -1, "0", NULL);
5641
5642 /* Wet deposition... */
5643 for (int ip = 0; ip < 2; ip++) {
5644 sprintf(defstr, "%g", ctl->wet_depo_ic_h[ip]);
5645 ctl->wet_depo_ic_h[ip] =
5646 scan_ctl(filename, argc, argv, "WET_DEPO_IC_H", ip, defstr, NULL);
5647 }
5648 for (int ip = 0; ip < 1; ip++) {
5649 sprintf(defstr, "%g", ctl->wet_depo_bc_h[ip]);
5650 ctl->wet_depo_bc_h[ip] =
5651 scan_ctl(filename, argc, argv, "WET_DEPO_BC_H", ip, defstr, NULL);
5652 }
5653 ctl->wet_depo_so2_ph =
5654 scan_ctl(filename, argc, argv, "WET_DEPO_SO2_PH", -1, "0", NULL);
5655 ctl->wet_depo_ic_a =
5656 scan_ctl(filename, argc, argv, "WET_DEPO_IC_A", -1, "0", NULL);
5657 ctl->wet_depo_ic_b =
5658 scan_ctl(filename, argc, argv, "WET_DEPO_IC_B", -1, "0", NULL);
5659 ctl->wet_depo_bc_a =
5660 scan_ctl(filename, argc, argv, "WET_DEPO_BC_A", -1, "0", NULL);
5661 ctl->wet_depo_bc_b =
5662 scan_ctl(filename, argc, argv, "WET_DEPO_BC_B", -1, "0", NULL);
5663 ctl->wet_depo_pre[0] =
5664 scan_ctl(filename, argc, argv, "WET_DEPO_PRE", 0, "0.5", NULL);
5665 ctl->wet_depo_pre[1] =
5666 scan_ctl(filename, argc, argv, "WET_DEPO_PRE", 1, "0.36", NULL);
5668 scan_ctl(filename, argc, argv, "WET_DEPO_IC_RET_RATIO", -1, "1", NULL);
5670 scan_ctl(filename, argc, argv, "WET_DEPO_BC_RET_RATIO", -1, "1", NULL);
5671
5672 /* Dry deposition... */
5673 ctl->dry_depo_vdep =
5674 scan_ctl(filename, argc, argv, "DRY_DEPO_VDEP", -1, "0", NULL);
5675 ctl->dry_depo_dp =
5676 scan_ctl(filename, argc, argv, "DRY_DEPO_DP", -1, "30", NULL);
5677
5678 /* Climatological data... */
5679 scan_ctl(filename, argc, argv, "CLIM_PHOTO", -1,
5680 "../../data/clams_photolysis_rates.nc", ctl->clim_photo);
5681 scan_ctl(filename, argc, argv, "CLIM_HNO3_FILENAME", -1,
5682 "../../data/gozcards_HNO3.nc", ctl->clim_hno3_filename);
5683 scan_ctl(filename, argc, argv, "CLIM_OH_FILENAME", -1,
5684 "../../data/clams_radical_species_vmr.nc", ctl->clim_oh_filename);
5685 scan_ctl(filename, argc, argv, "CLIM_H2O2_FILENAME", -1,
5686 "../../data/cams_H2O2.nc", ctl->clim_h2o2_filename);
5687 scan_ctl(filename, argc, argv, "CLIM_HO2_FILENAME", -1,
5688 "../../data/clams_radical_species_vmr.nc", ctl->clim_ho2_filename);
5689 scan_ctl(filename, argc, argv, "CLIM_O1D_FILENAME", -1,
5690 "../../data/clams_radical_species_vmr.nc", ctl->clim_o1d_filename);
5691 scan_ctl(filename, argc, argv, "CLIM_CCL4_TIMESERIES", -1,
5692 "../../data/noaa_gml_ccl4.tab", ctl->clim_ccl4_timeseries);
5693 scan_ctl(filename, argc, argv, "CLIM_CCL3F_TIMESERIES", -1,
5694 "../../data/noaa_gml_cfc11.tab", ctl->clim_ccl3f_timeseries);
5695 scan_ctl(filename, argc, argv, "CLIM_CCL2F2_TIMESERIES", -1,
5696 "../../data/noaa_gml_cfc12.tab", ctl->clim_ccl2f2_timeseries);
5697 scan_ctl(filename, argc, argv, "CLIM_N2O_TIMESERIES", -1,
5698 "../../data/noaa_gml_n2o.tab", ctl->clim_n2o_timeseries);
5699 scan_ctl(filename, argc, argv, "CLIM_SF6_TIMESERIES", -1,
5700 "../../data/noaa_gml_sf6.tab", ctl->clim_sf6_timeseries);
5701
5702 /* Mixing... */
5703 ctl->mixing_dt =
5704 scan_ctl(filename, argc, argv, "MIXING_DT", -1, "3600.", NULL);
5705 ctl->mixing_trop =
5706 scan_ctl(filename, argc, argv, "MIXING_TROP", -1, "-999", NULL);
5707 ctl->mixing_strat =
5708 scan_ctl(filename, argc, argv, "MIXING_STRAT", -1, "-999", NULL);
5709 ctl->mixing_z0 =
5710 scan_ctl(filename, argc, argv, "MIXING_Z0", -1, "-5", NULL);
5711 ctl->mixing_z1 =
5712 scan_ctl(filename, argc, argv, "MIXING_Z1", -1, "85", NULL);
5713 ctl->mixing_nz =
5714 (int) scan_ctl(filename, argc, argv, "MIXING_NZ", -1, "90", NULL);
5715 ctl->mixing_lon0 =
5716 scan_ctl(filename, argc, argv, "MIXING_LON0", -1, "-180", NULL);
5717 ctl->mixing_lon1 =
5718 scan_ctl(filename, argc, argv, "MIXING_LON1", -1, "180", NULL);
5719 ctl->mixing_nx =
5720 (int) scan_ctl(filename, argc, argv, "MIXING_NX", -1, "360", NULL);
5721 ctl->mixing_lat0 =
5722 scan_ctl(filename, argc, argv, "MIXING_LAT0", -1, "-90", NULL);
5723 ctl->mixing_lat1 =
5724 scan_ctl(filename, argc, argv, "MIXING_LAT1", -1, "90", NULL);
5725 ctl->mixing_ny =
5726 (int) scan_ctl(filename, argc, argv, "MIXING_NY", -1, "180", NULL);
5727
5728 /* Chemistry grid... */
5729 ctl->chemgrid_z0 =
5730 scan_ctl(filename, argc, argv, "CHEMGRID_Z0", -1, "-5", NULL);
5731 ctl->chemgrid_z1 =
5732 scan_ctl(filename, argc, argv, "CHEMGRID_Z1", -1, "85", NULL);
5733 ctl->chemgrid_nz =
5734 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NZ", -1, "90", NULL);
5735 ctl->chemgrid_lon0 =
5736 scan_ctl(filename, argc, argv, "CHEMGRID_LON0", -1, "-180", NULL);
5737 ctl->chemgrid_lon1 =
5738 scan_ctl(filename, argc, argv, "CHEMGRID_LON1", -1, "180", NULL);
5739 ctl->chemgrid_nx =
5740 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NX", -1, "360", NULL);
5741 ctl->chemgrid_lat0 =
5742 scan_ctl(filename, argc, argv, "CHEMGRID_LAT0", -1, "-90", NULL);
5743 ctl->chemgrid_lat1 =
5744 scan_ctl(filename, argc, argv, "CHEMGRID_LAT1", -1, "90", NULL);
5745 ctl->chemgrid_ny =
5746 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NY", -1, "180", NULL);
5747
5748 /* Exponential decay... */
5749 ctl->tdec_trop = scan_ctl(filename, argc, argv, "TDEC_TROP", -1, "0", NULL);
5750 ctl->tdec_strat
5751 = scan_ctl(filename, argc, argv, "TDEC_STRAT", -1, "0", NULL);
5752
5753 /* PSC analysis... */
5754 ctl->psc_h2o = scan_ctl(filename, argc, argv, "PSC_H2O", -1, "4e-6", NULL);
5755 ctl->psc_hno3 =
5756 scan_ctl(filename, argc, argv, "PSC_HNO3", -1, "9e-9", NULL);
5757
5758 /* Output of atmospheric data... */
5759 scan_ctl(filename, argc, argv, "ATM_BASENAME", -1, "-", ctl->atm_basename);
5760 scan_ctl(filename, argc, argv, "ATM_GPFILE", -1, "-", ctl->atm_gpfile);
5761 ctl->atm_dt_out =
5762 scan_ctl(filename, argc, argv, "ATM_DT_OUT", -1, "86400", NULL);
5763 ctl->atm_filter =
5764 (int) scan_ctl(filename, argc, argv, "ATM_FILTER", -1, "0", NULL);
5765 ctl->atm_stride =
5766 (int) scan_ctl(filename, argc, argv, "ATM_STRIDE", -1, "1", NULL);
5767 ctl->atm_type =
5768 (int) scan_ctl(filename, argc, argv, "ATM_TYPE", -1, "0", NULL);
5769 ctl->atm_type_out =
5770 (int) scan_ctl(filename, argc, argv, "ATM_TYPE_OUT", -1, "-1", NULL);
5771 if (ctl->atm_type_out == -1)
5772 ctl->atm_type_out = ctl->atm_type;
5773 ctl->atm_nc_level =
5774 (int) scan_ctl(filename, argc, argv, "ATM_NC_LEVEL", -1, "0", NULL);
5775 for (int iq = 0; iq < ctl->nq; iq++)
5776 ctl->atm_nc_quant[iq] =
5777 (int) scan_ctl(filename, argc, argv, "ATM_NC_QUANT", iq, "0", NULL);
5778 ctl->obs_type =
5779 (int) scan_ctl(filename, argc, argv, "OBS_TYPE", -1, "0", NULL);
5780
5781 /* Output of CSI data... */
5782 scan_ctl(filename, argc, argv, "CSI_BASENAME", -1, "-", ctl->csi_basename);
5783 scan_ctl(filename, argc, argv, "CSI_KERNEL", -1, "-", ctl->csi_kernel);
5784 ctl->csi_dt_out =
5785 scan_ctl(filename, argc, argv, "CSI_DT_OUT", -1, "86400", NULL);
5786 scan_ctl(filename, argc, argv, "CSI_OBSFILE", -1, "-", ctl->csi_obsfile);
5787 ctl->csi_obsmin =
5788 scan_ctl(filename, argc, argv, "CSI_OBSMIN", -1, "0", NULL);
5789 ctl->csi_modmin =
5790 scan_ctl(filename, argc, argv, "CSI_MODMIN", -1, "0", NULL);
5791 ctl->csi_z0 = scan_ctl(filename, argc, argv, "CSI_Z0", -1, "-5", NULL);
5792 ctl->csi_z1 = scan_ctl(filename, argc, argv, "CSI_Z1", -1, "85", NULL);
5793 ctl->csi_nz = (int) scan_ctl(filename, argc, argv, "CSI_NZ", -1, "1", NULL);
5794 ctl->csi_lon0 =
5795 scan_ctl(filename, argc, argv, "CSI_LON0", -1, "-180", NULL);
5796 ctl->csi_lon1 = scan_ctl(filename, argc, argv, "CSI_LON1", -1, "180", NULL);
5797 ctl->csi_nx =
5798 (int) scan_ctl(filename, argc, argv, "CSI_NX", -1, "360", NULL);
5799 ctl->csi_lat0 = scan_ctl(filename, argc, argv, "CSI_LAT0", -1, "-90", NULL);
5800 ctl->csi_lat1 = scan_ctl(filename, argc, argv, "CSI_LAT1", -1, "90", NULL);
5801 ctl->csi_ny =
5802 (int) scan_ctl(filename, argc, argv, "CSI_NY", -1, "180", NULL);
5803
5804 /* Output of ensemble data... */
5805 scan_ctl(filename, argc, argv, "ENS_BASENAME", -1, "-", ctl->ens_basename);
5806 ctl->ens_dt_out =
5807 scan_ctl(filename, argc, argv, "ENS_DT_OUT", -1, "86400", NULL);
5808
5809 /* Output of grid data... */
5810 scan_ctl(filename, argc, argv, "GRID_BASENAME", -1, "-",
5811 ctl->grid_basename);
5812 scan_ctl(filename, argc, argv, "GRID_KERNEL", -1, "-", ctl->grid_kernel);
5813 scan_ctl(filename, argc, argv, "GRID_GPFILE", -1, "-", ctl->grid_gpfile);
5814 ctl->grid_dt_out =
5815 scan_ctl(filename, argc, argv, "GRID_DT_OUT", -1, "86400", NULL);
5816 ctl->grid_sparse =
5817 (int) scan_ctl(filename, argc, argv, "GRID_SPARSE", -1, "0", NULL);
5818 ctl->grid_nc_level =
5819 (int) scan_ctl(filename, argc, argv, "GRID_NC_LEVEL", -1, "0", NULL);
5820 for (int iq = 0; iq < ctl->nq; iq++)
5821 ctl->grid_nc_quant[iq] =
5822 (int) scan_ctl(filename, argc, argv, "GRID_NC_QUANT", iq, "0", NULL);
5823 ctl->grid_stddev =
5824 (int) scan_ctl(filename, argc, argv, "GRID_STDDEV", -1, "0", NULL);
5825 ctl->grid_z0 = scan_ctl(filename, argc, argv, "GRID_Z0", -1, "-5", NULL);
5826 ctl->grid_z1 = scan_ctl(filename, argc, argv, "GRID_Z1", -1, "85", NULL);
5827 ctl->grid_nz =
5828 (int) scan_ctl(filename, argc, argv, "GRID_NZ", -1, "1", NULL);
5829 ctl->grid_lon0 =
5830 scan_ctl(filename, argc, argv, "GRID_LON0", -1, "-180", NULL);
5831 ctl->grid_lon1 =
5832 scan_ctl(filename, argc, argv, "GRID_LON1", -1, "180", NULL);
5833 ctl->grid_nx =
5834 (int) scan_ctl(filename, argc, argv, "GRID_NX", -1, "360", NULL);
5835 ctl->grid_lat0 =
5836 scan_ctl(filename, argc, argv, "GRID_LAT0", -1, "-90", NULL);
5837 ctl->grid_lat1 =
5838 scan_ctl(filename, argc, argv, "GRID_LAT1", -1, "90", NULL);
5839 ctl->grid_ny =
5840 (int) scan_ctl(filename, argc, argv, "GRID_NY", -1, "180", NULL);
5841 ctl->grid_type =
5842 (int) scan_ctl(filename, argc, argv, "GRID_TYPE", -1, "0", NULL);
5843
5844 /* Output of profile data... */
5845 scan_ctl(filename, argc, argv, "PROF_BASENAME", -1, "-",
5846 ctl->prof_basename);
5847 scan_ctl(filename, argc, argv, "PROF_OBSFILE", -1, "-", ctl->prof_obsfile);
5848 ctl->prof_z0 = scan_ctl(filename, argc, argv, "PROF_Z0", -1, "0", NULL);
5849 ctl->prof_z1 = scan_ctl(filename, argc, argv, "PROF_Z1", -1, "60", NULL);
5850 ctl->prof_nz =
5851 (int) scan_ctl(filename, argc, argv, "PROF_NZ", -1, "60", NULL);
5852 ctl->prof_lon0 =
5853 scan_ctl(filename, argc, argv, "PROF_LON0", -1, "-180", NULL);
5854 ctl->prof_lon1 =
5855 scan_ctl(filename, argc, argv, "PROF_LON1", -1, "180", NULL);
5856 ctl->prof_nx =
5857 (int) scan_ctl(filename, argc, argv, "PROF_NX", -1, "360", NULL);
5858 ctl->prof_lat0 =
5859 scan_ctl(filename, argc, argv, "PROF_LAT0", -1, "-90", NULL);
5860 ctl->prof_lat1 =
5861 scan_ctl(filename, argc, argv, "PROF_LAT1", -1, "90", NULL);
5862 ctl->prof_ny =
5863 (int) scan_ctl(filename, argc, argv, "PROF_NY", -1, "180", NULL);
5864
5865 /* Output of sample data... */
5866 scan_ctl(filename, argc, argv, "SAMPLE_BASENAME", -1, "-",
5867 ctl->sample_basename);
5868 scan_ctl(filename, argc, argv, "SAMPLE_KERNEL", -1, "-",
5869 ctl->sample_kernel);
5870 scan_ctl(filename, argc, argv, "SAMPLE_OBSFILE", -1, "-",
5871 ctl->sample_obsfile);
5872 ctl->sample_dx =
5873 scan_ctl(filename, argc, argv, "SAMPLE_DX", -1, "50", NULL);
5874 ctl->sample_dz =
5875 scan_ctl(filename, argc, argv, "SAMPLE_DZ", -1, "-999", NULL);
5876
5877 /* Output of station data... */
5878 scan_ctl(filename, argc, argv, "STAT_BASENAME", -1, "-",
5879 ctl->stat_basename);
5880 ctl->stat_lon = scan_ctl(filename, argc, argv, "STAT_LON", -1, "0", NULL);
5881 ctl->stat_lat = scan_ctl(filename, argc, argv, "STAT_LAT", -1, "0", NULL);
5882 ctl->stat_r = scan_ctl(filename, argc, argv, "STAT_R", -1, "50", NULL);
5883 ctl->stat_t0 =
5884 scan_ctl(filename, argc, argv, "STAT_T0", -1, "-1e100", NULL);
5885 ctl->stat_t1 = scan_ctl(filename, argc, argv, "STAT_T1", -1, "1e100", NULL);
5886
5887 /* Output of VTK data... */
5888 scan_ctl(filename, argc, argv, "VTK_BASENAME", -1, "-", ctl->vtk_basename);
5889 ctl->vtk_dt_out =
5890 scan_ctl(filename, argc, argv, "VTK_DT_OUT", -1, "86400", NULL);
5891 ctl->vtk_stride =
5892 (int) scan_ctl(filename, argc, argv, "VTK_STRIDE", -1, "1", NULL);
5893 ctl->vtk_scale =
5894 scan_ctl(filename, argc, argv, "VTK_SCALE", -1, "1.0", NULL);
5895 ctl->vtk_offset =
5896 scan_ctl(filename, argc, argv, "VTK_OFFSET", -1, "0.0", NULL);
5897 ctl->vtk_sphere =
5898 (int) scan_ctl(filename, argc, argv, "VTK_SPHERE", -1, "0", NULL);
5899}
void level_definitions(ctl_t *ctl)
Defines pressure levels for meteorological data.
Definition: mptrac.c:1908
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:8430
#define NQ
Maximum number of quantities per data point.
Definition: mptrac.h:251
#define SET_QNT(qnt, name, longname, unit)
Set atmospheric quantity index.
Definition: mptrac.h:1523
double grid_z0
Lower altitude of gridded data [km].
Definition: mptrac.h:3027
int qnt_o3
Quantity array index for ozone volume mixing ratio.
Definition: mptrac.h:2282
double csi_lat1
Upper latitude of gridded CSI data [deg].
Definition: mptrac.h:2991
char csi_obsfile[LEN]
Observation data file for CSI analysis.
Definition: mptrac.h:2958
int qnt_pel
Quantity array index for pressure at equilibrium level (EL).
Definition: mptrac.h:2315
int csi_nz
Number of altitudes of gridded CSI data.
Definition: mptrac.h:2967
int qnt_p
Quantity array index for pressure.
Definition: mptrac.h:2261
char atm_gpfile[LEN]
Gnuplot file for atmospheric data.
Definition: mptrac.h:2919
int qnt_swc
Quantity array index for cloud snow water content.
Definition: mptrac.h:2294
double csi_obsmin
Minimum observation index to trigger detection.
Definition: mptrac.h:2961
int qnt_pcb
Quantity array index for cloud bottom pressure.
Definition: mptrac.h:2303
double csi_lon1
Upper longitude of gridded CSI data [deg].
Definition: mptrac.h:2982
int qnt_u
Quantity array index for zonal wind.
Definition: mptrac.h:2270
double stat_lon
Longitude of station [deg].
Definition: mptrac.h:3105
double stat_r
Search radius around station [km].
Definition: mptrac.h:3111
int csi_ny
Number of latitudes of gridded CSI data.
Definition: mptrac.h:2985
int vtk_sphere
Spherical projection for VTK data (0=no, 1=yes).
Definition: mptrac.h:3135
double met_pbl_min
Minimum depth of planetary boundary layer [km].
Definition: mptrac.h:2609
int qnt_iwc
Quantity array index for cloud ice water content.
Definition: mptrac.h:2291
int qnt_pw
Quantity array index for partial water vapor pressure.
Definition: mptrac.h:2369
char prof_basename[LEN]
Basename for profile output file.
Definition: mptrac.h:3054
double grid_z1
Upper altitude of gridded data [km].
Definition: mptrac.h:3030
int qnt_h2o2
Quantity array index for H2O2 volume mixing ratio (climatology).
Definition: mptrac.h:2333
int qnt_vh
Quantity array index for horizontal wind.
Definition: mptrac.h:2396
char species[LEN]
Species.
Definition: mptrac.h:2738
int csi_nx
Number of longitudes of gridded CSI data.
Definition: mptrac.h:2976
double csi_lat0
Lower latitude of gridded CSI data [deg].
Definition: mptrac.h:2988
int met_pbl
Planetary boundary layer data (0=file, 1=z2p, 2=Richardson, 3=theta).
Definition: mptrac.h:2606
int qnt_lwc
Quantity array index for cloud liquid water content.
Definition: mptrac.h:2285
int grid_nc_level
zlib compression level of netCDF grid data files (0=off).
Definition: mptrac.h:3015
int grid_nx
Number of longitudes of gridded data.
Definition: mptrac.h:3033
double grid_lat0
Lower latitude of gridded data [deg].
Definition: mptrac.h:3045
int qnt_ts
Quantity array index for surface temperature.
Definition: mptrac.h:2216
int qnt_plfc
Quantity array index for pressure at level of free convection (LCF).
Definition: mptrac.h:2312
double grid_lon0
Lower longitude of gridded data [deg].
Definition: mptrac.h:3036
int qnt_o1d
Quantity array index for O(1D) volume mixing ratio (climatology).
Definition: mptrac.h:2339
int met_tropo_spline
Tropopause interpolation method (0=linear, 1=spline).
Definition: mptrac.h:2625
char sample_kernel[LEN]
Kernel data file for sample output.
Definition: mptrac.h:3090
int qnt_tvirt
Quantity array index for virtual temperature.
Definition: mptrac.h:2390
int met_geopot_sy
Latitudinal smoothing of geopotential heights.
Definition: mptrac.h:2597
char grid_gpfile[LEN]
Gnuplot file for gridded data.
Definition: mptrac.h:3006
int qnt_lsm
Quantity array index for land-sea mask.
Definition: mptrac.h:2237
int qnt_theta
Quantity array index for potential temperature.
Definition: mptrac.h:2381
double stat_t1
Stop time for station output [s].
Definition: mptrac.h:3117
char csi_kernel[LEN]
Kernel data file for CSI output.
Definition: mptrac.h:2952
int grid_type
Type of grid data files (0=ASCII, 1=netCDF).
Definition: mptrac.h:3051
double csi_lon0
Lower longitude of gridded CSI data [deg].
Definition: mptrac.h:2979
int qnt_pbl
Quantity array index for boundary layer pressure.
Definition: mptrac.h:2243
int grid_stddev
Include standard deviations in grid output (0=no, 1=yes).
Definition: mptrac.h:3021
int qnt_psice
Quantity array index for saturation pressure over ice.
Definition: mptrac.h:2366
int met_geopot_sx
Longitudinal smoothing of geopotential heights.
Definition: mptrac.h:2594
int qnt_ps
Quantity array index for surface pressure.
Definition: mptrac.h:2213
char prof_obsfile[LEN]
Observation data file for profile output.
Definition: mptrac.h:3057
int qnt_zs
Quantity array index for surface geopotential height.
Definition: mptrac.h:2219
int prof_nz
Number of altitudes of gridded profile data.
Definition: mptrac.h:3060
double csi_dt_out
Time step for CSI output [s].
Definition: mptrac.h:2955
int met_cape
Convective available potential energy data (0=file, 1=calculate).
Definition: mptrac.h:2603
double csi_modmin
Minimum column density to trigger detection [kg/m^2].
Definition: mptrac.h:2964
char grid_kernel[LEN]
Kernel data file for grid output.
Definition: mptrac.h:3003
double prof_z0
Lower altitude of gridded profile data [km].
Definition: mptrac.h:3063
int qnt_w
Quantity array index for vertical velocity.
Definition: mptrac.h:2276
double met_tropo_pv
Dynamical tropopause potential vorticity threshold [PVU].
Definition: mptrac.h:2619
int prof_nx
Number of longitudes of gridded profile data.
Definition: mptrac.h:3069
int qnt_stat
Quantity array index for station flag.
Definition: mptrac.h:2198
int met_mpi_share
Use MPI to share meteo (0=no, 1=yes).
Definition: mptrac.h:2634
int qnt_vz
Quantity array index for vertical velocity.
Definition: mptrac.h:2399
int qnt_ho2
Quantity array index for HO2 volume mixing ratio (climatology).
Definition: mptrac.h:2336
double csi_z1
Upper altitude of gridded CSI data [km].
Definition: mptrac.h:2973
double stat_t0
Start time for station output [s].
Definition: mptrac.h:3114
int atm_type_out
Type of atmospheric data files for output (-1=same as ATM_TYPE, 0=ASCII, 1=binary,...
Definition: mptrac.h:2937
char csi_basename[LEN]
Basename of CSI data files.
Definition: mptrac.h:2949
int qnt_shf
Quantity array index for surface sensible heat flux.
Definition: mptrac.h:2234
int qnt_vs
Quantity array index for surface meridional wind.
Definition: mptrac.h:2225
double vtk_dt_out
Time step for VTK data output [s].
Definition: mptrac.h:3123
char sample_obsfile[LEN]
Observation data file for sample output.
Definition: mptrac.h:3093
int qnt_hno3
Quantity array index for HNO3 volume mixing ratio (climatology).
Definition: mptrac.h:2327
char grid_basename[LEN]
Basename of grid data files.
Definition: mptrac.h:3000
int qnt_h2ot
Quantity array index for tropopause water vapor volume mixing ratio.
Definition: mptrac.h:2255
int qnt_rh
Quantity array index for relative humidity over water.
Definition: mptrac.h:2375
double met_pbl_max
Maximum depth of planetary boundary layer [km].
Definition: mptrac.h:2612
int qnt_zeta_d
Quantity array index for diagnosed zeta vertical coordinate.
Definition: mptrac.h:2387
int qnt_zg
Quantity array index for geopotential height.
Definition: mptrac.h:2258
double vtk_offset
Vertical offset for VTK data [km].
Definition: mptrac.h:3132
int qnt_v
Quantity array index for meridional wind.
Definition: mptrac.h:2273
int qnt_oh
Quantity array index for OH volume mixing ratio (climatology).
Definition: mptrac.h:2330
int qnt_h2o
Quantity array index for water vapor volume mixing ratio.
Definition: mptrac.h:2279
int prof_ny
Number of latitudes of gridded profile data.
Definition: mptrac.h:3078
int qnt_rhice
Quantity array index for relative humidity over ice.
Definition: mptrac.h:2378
int qnt_rho
Quantity array index for density of air.
Definition: mptrac.h:2267
double sample_dz
Layer depth for sample output [km].
Definition: mptrac.h:3099
int obs_type
Type of observation data files (0=ASCII, 1=netCDF).
Definition: mptrac.h:2946
int grid_nc_quant[NQ]
Number of digits for quantization of netCDF grid data files (0=off).
Definition: mptrac.h:3018
int qnt_us
Quantity array index for surface zonal wind.
Definition: mptrac.h:2222
double grid_lon1
Upper longitude of gridded data [deg].
Definition: mptrac.h:3039
char atm_basename[LEN]
Basename of atmospheric data files.
Definition: mptrac.h:2916
int qnt_pt
Quantity array index for tropopause pressure.
Definition: mptrac.h:2246
int qnt_cl
Quantity array index for total column cloud water.
Definition: mptrac.h:2306
double prof_z1
Upper altitude of gridded profile data [km].
Definition: mptrac.h:3066
int qnt_t
Quantity array index for temperature.
Definition: mptrac.h:2264
int atm_filter
Time filter for atmospheric data output (0=none, 1=missval, 2=remove).
Definition: mptrac.h:2925
char ens_basename[LEN]
Basename of ensemble data file.
Definition: mptrac.h:2994
double csi_z0
Lower altitude of gridded CSI data [km].
Definition: mptrac.h:2970
int qnt_lapse
Quantity array index for lapse rate.
Definition: mptrac.h:2393
double stat_lat
Latitude of station [deg].
Definition: mptrac.h:3108
int grid_ny
Number of latitudes of gridded data.
Definition: mptrac.h:3042
int qnt_cape
Quantity array index for convective available potential energy (CAPE).
Definition: mptrac.h:2318
int qnt_o3c
Quantity array index for total column ozone.
Definition: mptrac.h:2324
int grid_nz
Number of altitudes of gridded data.
Definition: mptrac.h:3024
int qnt_nss
Quantity array index for northward turbulent surface stress.
Definition: mptrac.h:2231
double ens_dt_out
Time step for ensemble output [s].
Definition: mptrac.h:2997
char sample_basename[LEN]
Basename of sample data file.
Definition: mptrac.h:3087
int atm_stride
Particle index stride for atmospheric data files.
Definition: mptrac.h:2928
int met_relhum
Try to read relative humidity (0=no, 1=yes).
Definition: mptrac.h:2600
double atm_dt_out
Time step for atmospheric data output [s].
Definition: mptrac.h:2922
double prof_lat1
Upper latitude of gridded profile data [deg].
Definition: mptrac.h:3084
double psc_h2o
H2O volume mixing ratio for PSC analysis.
Definition: mptrac.h:2906
double prof_lon0
Lower longitude of gridded profile data [deg].
Definition: mptrac.h:3072
int qnt_pct
Quantity array index for cloud top pressure.
Definition: mptrac.h:2300
int qnt_mloss_kpp
Quantity array index for total mass loss due to KPP chemistry.
Definition: mptrac.h:2348
int qnt_psat
Quantity array index for saturation pressure over water.
Definition: mptrac.h:2363
double prof_lat0
Lower latitude of gridded profile data [deg].
Definition: mptrac.h:3081
int qnt_cin
Quantity array index for convective inhibition (CIN).
Definition: mptrac.h:2321
double psc_hno3
HNO3 volume mixing ratio for PSC analysis.
Definition: mptrac.h:2909
double prof_lon1
Upper longitude of gridded profile data [deg].
Definition: mptrac.h:3075
int atm_nc_quant[NQ]
Number of digits for quantization of netCDF atmospheric data files (0=off).
Definition: mptrac.h:2943
int grid_sparse
Sparse output in grid data files (0=no, 1=yes).
Definition: mptrac.h:3012
char vtk_basename[LEN]
Basename of VTK data files.
Definition: mptrac.h:3120
int qnt_tt
Quantity array index for tropopause temperature.
Definition: mptrac.h:2249
int qnt_ens
Quantity array index for ensemble IDs.
Definition: mptrac.h:2195
double vtk_scale
Vertical scaling factor for VTK data.
Definition: mptrac.h:3129
int qnt_pv
Quantity array index for potential vorticity.
Definition: mptrac.h:2402
int qnt_sst
Quantity array index for sea surface temperature.
Definition: mptrac.h:2240
int atm_nc_level
zlib compression level of netCDF atmospheric data files (0=off).
Definition: mptrac.h:2940
int qnt_sh
Quantity array index for specific humidity.
Definition: mptrac.h:2372
int qnt_ess
Quantity array index for eastward turbulent surface stress.
Definition: mptrac.h:2228
int qnt_idx
Quantity array index for air parcel IDs.
Definition: mptrac.h:2192
double met_tropo_theta
Dynamical tropopause potential temperature threshold [K].
Definition: mptrac.h:2622
int qnt_rwc
Quantity array index for cloud rain water content.
Definition: mptrac.h:2288
char qnt_longname[NQ][LEN]
Quantity long names.
Definition: mptrac.h:2183
double sample_dx
Horizontal radius for sample output [km].
Definition: mptrac.h:3096
int vtk_stride
Particle index stride for VTK data.
Definition: mptrac.h:3126
char stat_basename[LEN]
Basename of station data file.
Definition: mptrac.h:3102
double grid_lat1
Upper latitude of gridded data [deg].
Definition: mptrac.h:3048
int qnt_zt
Quantity array index for tropopause geopotential height.
Definition: mptrac.h:2252
int qnt_cc
Quantity array index for cloud cover.
Definition: mptrac.h:2297
int qnt_plcl
Quantity array index for pressure at lifted condensation level (LCL).
Definition: mptrac.h:2309
double grid_dt_out
Time step for gridded data output [s].
Definition: mptrac.h:3009
int qnt_tdew
Quantity array index for dew point temperature.
Definition: mptrac.h:2405
Here is the call graph for this function:

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

5907 {
5908
5909 /* Write info... */
5910 LOG(1, "Read kernel function: %s", filename);
5911
5912 /* Open file... */
5913 FILE *in;
5914 if (!(in = fopen(filename, "r")))
5915 ERRMSG("Cannot open file!");
5916
5917 /* Read data... */
5918 char line[LEN];
5919 int n = 0;
5920 while (fgets(line, LEN, in))
5921 if (sscanf(line, "%lg %lg", &kz[n], &kw[n]) == 2) {
5922 if (n > 0 && kz[n] < kz[n - 1])
5923 ERRMSG("Height levels must be ascending!");
5924 if ((++n) >= EP)
5925 ERRMSG("Too many height levels!");
5926 }
5927
5928 /* Close file... */
5929 fclose(in);
5930
5931 /* Check number of data points... */
5932 *nk = n;
5933 if (n < 2)
5934 ERRMSG("Not enough height levels!");
5935
5936 /* Normalize kernel function... */
5937 const double kmax = gsl_stats_max(kw, 1, (size_t) n);
5938 for (int iz = 0; iz < n; iz++)
5939 kw[iz] /= kmax;
5940}

◆ read_met()

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

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

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

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

Definition at line 5944 of file mptrac.c.

5948 {
5949
5950 /* Write info... */
5951 LOG(1, "Read meteo data: %s", filename);
5952
5953 /* Set rank... */
5954 int rank = 0;
5955#ifdef MPI
5956 if (ctl->met_mpi_share)
5957 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5958#endif
5959
5960 /* Check rank... */
5961 if (!ctl->met_mpi_share || rank == 0) {
5962
5963 /* Read netCDF data... */
5964 if (ctl->met_type == 0) {
5965 if (read_met_nc(filename, ctl, clim, met) != 1)
5966 return 0;
5967 }
5968
5969 /* Read binary data... */
5970 else if (ctl->met_type >= 1 && ctl->met_type <= 5) {
5971 if (read_met_bin(filename, ctl, met) != 1)
5972 return 0;
5973 }
5974
5975 /* Not implemented... */
5976 else
5977 ERRMSG("MET_TYPE not implemented!");
5978 }
5979
5980 /* Broadcast data via MPI... */
5981#ifdef MPI
5982 if (ctl->met_mpi_share) {
5983
5984 /* Set timer... */
5985 SELECT_TIMER("READ_MET_MPI_BCAST", "COMM", NVTX_SEND);
5986 LOG(2, "Broadcast data on rank %d...", rank);
5987
5988 /* Broadcast... */
5989 broadcast_large_data(met, sizeof(met_t));
5990 }
5991#endif
5992
5993 /* Return success... */
5994 return 1;
5995}
int read_met_nc(const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met)
Reads meteorological data from a NetCDF file and processes it.
Definition: mptrac.c:7082
int read_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a binary file.
Definition: mptrac.c:5999
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:

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

6002 {
6003
6004 FILE *in;
6005
6006 double r;
6007
6008 int year, mon, day, hour, min, sec;
6009
6010 /* Set timer... */
6011 SELECT_TIMER("READ_MET_BIN", "INPUT", NVTX_READ);
6012
6013 /* Open file... */
6014 if (!(in = fopen(filename, "r"))) {
6015 WARN("Cannot open file!");
6016 return 0;
6017 }
6018
6019 /* Check type of binary data... */
6020 int met_type;
6021 FREAD(&met_type, int,
6022 1,
6023 in);
6024 if (met_type != ctl->met_type)
6025 ERRMSG("Wrong MET_TYPE of binary data!");
6026
6027 /* Check version of binary data... */
6028 int version;
6029 FREAD(&version, int,
6030 1,
6031 in);
6032 if (version != 103)
6033 ERRMSG("Wrong version of binary data!");
6034
6035 /* Read time... */
6036 FREAD(&met->time, double,
6037 1,
6038 in);
6039 jsec2time(met->time, &year, &mon, &day, &hour, &min, &sec, &r);
6040 LOG(2, "Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
6041 met->time, year, mon, day, hour, min);
6042 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
6043 || day < 1 || day > 31 || hour < 0 || hour > 23)
6044 ERRMSG("Error while reading time!");
6045
6046 /* Read dimensions... */
6047 FREAD(&met->nx, int,
6048 1,
6049 in);
6050 LOG(2, "Number of longitudes: %d", met->nx);
6051 if (met->nx < 2 || met->nx > EX)
6052 ERRMSG("Number of longitudes out of range!");
6053
6054 FREAD(&met->ny, int,
6055 1,
6056 in);
6057 LOG(2, "Number of latitudes: %d", met->ny);
6058 if (met->ny < 2 || met->ny > EY)
6059 ERRMSG("Number of latitudes out of range!");
6060
6061 FREAD(&met->np, int,
6062 1,
6063 in);
6064 LOG(2, "Number of levels: %d", met->np);
6065 if (met->np < 2 || met->np > EP)
6066 ERRMSG("Number of levels out of range!");
6067
6068 /* Read grid... */
6069 FREAD(met->lon, double,
6070 (size_t) met->nx,
6071 in);
6072 LOG(2, "Longitudes: %g, %g ... %g deg",
6073 met->lon[0], met->lon[1], met->lon[met->nx - 1]);
6074
6075 FREAD(met->lat, double,
6076 (size_t) met->ny,
6077 in);
6078 LOG(2, "Latitudes: %g, %g ... %g deg",
6079 met->lat[0], met->lat[1], met->lat[met->ny - 1]);
6080
6081 FREAD(met->p, double,
6082 (size_t) met->np,
6083 in);
6084 LOG(2, "Altitude levels: %g, %g ... %g km",
6085 Z(met->p[0]), Z(met->p[1]), Z(met->p[met->np - 1]));
6086 LOG(2, "Pressure levels: %g, %g ... %g hPa",
6087 met->p[0], met->p[1], met->p[met->np - 1]);
6088
6089 /* Read surface data... */
6090 read_met_bin_2d(in, met, met->ps, "PS");
6091 read_met_bin_2d(in, met, met->ts, "TS");
6092 read_met_bin_2d(in, met, met->zs, "ZS");
6093 read_met_bin_2d(in, met, met->us, "US");
6094 read_met_bin_2d(in, met, met->vs, "VS");
6095 read_met_bin_2d(in, met, met->ess, "ESS");
6096 read_met_bin_2d(in, met, met->nss, "NSS");
6097 read_met_bin_2d(in, met, met->shf, "SHF");
6098 read_met_bin_2d(in, met, met->lsm, "LSM");
6099 read_met_bin_2d(in, met, met->sst, "SST");
6100 read_met_bin_2d(in, met, met->pbl, "PBL");
6101 read_met_bin_2d(in, met, met->pt, "PT");
6102 read_met_bin_2d(in, met, met->tt, "TT");
6103 read_met_bin_2d(in, met, met->zt, "ZT");
6104 read_met_bin_2d(in, met, met->h2ot, "H2OT");
6105 read_met_bin_2d(in, met, met->pct, "PCT");
6106 read_met_bin_2d(in, met, met->pcb, "PCB");
6107 read_met_bin_2d(in, met, met->cl, "CL");
6108 read_met_bin_2d(in, met, met->plcl, "PLCL");
6109 read_met_bin_2d(in, met, met->plfc, "PLFC");
6110 read_met_bin_2d(in, met, met->pel, "PEL");
6111 read_met_bin_2d(in, met, met->cape, "CAPE");
6112 read_met_bin_2d(in, met, met->cin, "CIN");
6113 read_met_bin_2d(in, met, met->o3c, "O3C");
6114
6115 /* Read level data... */
6116 read_met_bin_3d(in, ctl, met, met->z, "Z", -1e34f, 1e34f);
6117 read_met_bin_3d(in, ctl, met, met->t, "T", 0, 1e34f);
6118 read_met_bin_3d(in, ctl, met, met->u, "U", -1e34f, 1e34f);
6119 read_met_bin_3d(in, ctl, met, met->v, "V", -1e34f, 1e34f);
6120 read_met_bin_3d(in, ctl, met, met->w, "W", -1e34f, 1e34f);
6121 read_met_bin_3d(in, ctl, met, met->pv, "PV", -1e34f, 1e34f);
6122 read_met_bin_3d(in, ctl, met, met->h2o, "H2O", 0, 1e34f);
6123 read_met_bin_3d(in, ctl, met, met->o3, "O3", 0, 1e34f);
6124 read_met_bin_3d(in, ctl, met, met->lwc, "LWC", 0, 1e34f);
6125 read_met_bin_3d(in, ctl, met, met->rwc, "RWC", 0, 1e34f);
6126 read_met_bin_3d(in, ctl, met, met->iwc, "IWC", 0, 1e34f);
6127 read_met_bin_3d(in, ctl, met, met->swc, "SWC", 0, 1e34f);
6128 read_met_bin_3d(in, ctl, met, met->cc, "CC", 0, 1);
6129
6130 /* Read final flag... */
6131 int final;
6132 FREAD(&final, int,
6133 1,
6134 in);
6135 if (final != 999)
6136 ERRMSG("Error while reading binary data!");
6137
6138 /* Close file... */
6139 fclose(in);
6140
6141 /* Return success... */
6142 return 1;
6143}
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:6147
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:6176
#define EY
Maximum number of latitudes for meteo data.
Definition: mptrac.h:271
float zt[EX][EY]
Tropopause geopotential height [km].
Definition: mptrac.h:3443
float sst[EX][EY]
Sea surface temperature [K].
Definition: mptrac.h:3431
float rwc[EX][EY][EP]
Cloud rain water content [kg/kg].
Definition: mptrac.h:3503
float o3c[EX][EY]
Total column ozone [DU].
Definition: mptrac.h:3473
float cape[EX][EY]
Convective available potential energy [J/kg].
Definition: mptrac.h:3467
float pct[EX][EY]
Cloud top pressure [hPa].
Definition: mptrac.h:3449
float shf[EX][EY]
Surface sensible heat flux [W/m^2].
Definition: mptrac.h:3425
float lwc[EX][EY][EP]
Cloud liquid water content [kg/kg].
Definition: mptrac.h:3500
float us[EX][EY]
Surface zonal wind [m/s].
Definition: mptrac.h:3413
float cc[EX][EY][EP]
Cloud cover [1].
Definition: mptrac.h:3512
float ts[EX][EY]
Surface temperature [K].
Definition: mptrac.h:3407
float ess[EX][EY]
Eastward turbulent surface stress [N/m^2].
Definition: mptrac.h:3419
float pcb[EX][EY]
Cloud bottom pressure [hPa].
Definition: mptrac.h:3452
float pel[EX][EY]
Pressure at equilibrium level (EL) [hPa].
Definition: mptrac.h:3464
float cin[EX][EY]
Convective inhibition [J/kg].
Definition: mptrac.h:3470
float plcl[EX][EY]
Pressure at lifted condensation level (LCL) [hPa].
Definition: mptrac.h:3458
float tt[EX][EY]
Tropopause temperature [K].
Definition: mptrac.h:3440
float pbl[EX][EY]
Boundary layer pressure [hPa].
Definition: mptrac.h:3434
float vs[EX][EY]
Surface meridional wind [m/s].
Definition: mptrac.h:3416
float lsm[EX][EY]
Land-sea mask [1].
Definition: mptrac.h:3428
float iwc[EX][EY][EP]
Cloud ice water content [kg/kg].
Definition: mptrac.h:3506
float h2ot[EX][EY]
Tropopause water vapor volume mixing ratio [ppv].
Definition: mptrac.h:3446
float pv[EX][EY][EP]
Potential vorticity [PVU].
Definition: mptrac.h:3491
float cl[EX][EY]
Total column cloud water [kg/m^2].
Definition: mptrac.h:3455
float nss[EX][EY]
Northward turbulent surface stress [N/m^2].
Definition: mptrac.h:3422
float plfc[EX][EY]
Pressure at level of free convection (LFC) [hPa].
Definition: mptrac.h:3461
float swc[EX][EY][EP]
Cloud snow water content [kg/kg].
Definition: mptrac.h:3509
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 6147 of file mptrac.c.

6151 {
6152
6153 float *help;
6154
6155 /* Allocate... */
6156 ALLOC(help, float,
6157 EX * EY);
6158
6159 /* Read uncompressed... */
6160 LOG(2, "Read 2-D variable: %s (uncompressed)", varname);
6161 FREAD(help, float,
6162 (size_t) (met->nx * met->ny),
6163 in);
6164
6165 /* Copy data... */
6166 for (int ix = 0; ix < met->nx; ix++)
6167 for (int iy = 0; iy < met->ny; iy++)
6168 var[ix][iy] = help[ARRAY_2D(ix, iy, met->ny)];
6169
6170 /* Free... */
6171 free(help);
6172}
#define ARRAY_2D(ix, iy, ny)
Macro for computing the linear index of a 2D array element.
Definition: mptrac.h:372

◆ read_met_bin_3d()

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

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

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

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

The function supports the following types of data:

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

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

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

Definition at line 6176 of file mptrac.c.

6183 {
6184
6185 float *help;
6186
6187 /* Allocate... */
6188 ALLOC(help, float,
6189 EX * EY * EP);
6190
6191 /* Read uncompressed data... */
6192 if (ctl->met_type == 1) {
6193 LOG(2, "Read 3-D variable: %s (uncompressed)", varname);
6194 FREAD(help, float,
6195 (size_t) (met->nx * met->ny * met->np),
6196 in);
6197 }
6198
6199 /* Read packed data... */
6200 else if (ctl->met_type == 2)
6201 compress_pck(varname, help, (size_t) (met->ny * met->nx),
6202 (size_t) met->np, 1, in);
6203
6204 /* Read zfp data... */
6205 else if (ctl->met_type == 3) {
6206#ifdef ZFP
6207 int precision;
6208 FREAD(&precision, int,
6209 1,
6210 in);
6211
6212 double tolerance;
6213 FREAD(&tolerance, double,
6214 1,
6215 in);
6216
6217 compress_zfp(varname, help, met->np, met->ny, met->nx, precision,
6218 tolerance, 1, in);
6219#else
6220 ERRMSG("MPTRAC was compiled without zfp compression!");
6221#endif
6222 }
6223
6224 /* Read zstd data... */
6225 else if (ctl->met_type == 4) {
6226#ifdef ZSTD
6227 compress_zstd(varname, help, (size_t) (met->np * met->ny * met->nx), 1,
6228 in);
6229#else
6230 ERRMSG("MPTRAC was compiled without zstd compression!");
6231#endif
6232 }
6233
6234 /* Read cmultiscale data... */
6235 else if (ctl->met_type == 5) {
6236#ifdef CMS
6237 compress_cms(ctl, varname, help, (size_t) met->nx, (size_t) met->ny,
6238 (size_t) met->np, 1, in);
6239#else
6240 ERRMSG("MPTRAC was compiled without cmultiscale compression!");
6241#endif
6242 }
6243
6244 /* Copy data... */
6245#pragma omp parallel for default(shared) collapse(2)
6246 for (int ix = 0; ix < met->nx; ix++)
6247 for (int iy = 0; iy < met->ny; iy++)
6248 for (int ip = 0; ip < met->np; ip++) {
6249 var[ix][iy][ip] = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
6250 if (var[ix][iy][ip] < bound_min)
6251 var[ix][iy][ip] = bound_min;
6252 else if (var[ix][iy][ip] > bound_max)
6253 var[ix][iy][ip] = bound_max;
6254 }
6255
6256 /* Free... */
6257 free(help);
6258}
void compress_pck(const char *varname, float *array, const size_t nxy, const size_t nz, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats.
Definition: mptrac.c:657
void compress_cms(const ctl_t *ctl, const char *varname, float *array, const size_t nx, const size_t ny, const size_t np, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm.
void compress_zfp(const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using the ZFP library.
void compress_zstd(const char *varname, float *array, const size_t n, const int decompress, FILE *inout)
Compresses or decompresses an array of floats using the Zstandard (ZSTD) library.
Here is the call graph for this function:

◆ read_met_cape()

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

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

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

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

The function performs the following steps:

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

Definition at line 6262 of file mptrac.c.

6265 {
6266
6267 /* Check parameters... */
6268 if (ctl->met_cape != 1)
6269 return;
6270
6271 /* Set timer... */
6272 SELECT_TIMER("READ_MET_CAPE", "METPROC", NVTX_READ);
6273 LOG(2, "Calculate CAPE...");
6274
6275 /* Vertical spacing (about 100 m)... */
6276 const double pfac = 1.01439, dz0 = RI / MA / G0 * log(pfac);
6277
6278 /* Loop over columns... */
6279#pragma omp parallel for default(shared) collapse(2)
6280 for (int ix = 0; ix < met->nx; ix++)
6281 for (int iy = 0; iy < met->ny; iy++) {
6282
6283 /* Get potential temperature and water vapor at lowest 50 hPa... */
6284 int n = 0;
6285 double h2o = 0, t, theta = 0;
6286 double pbot = MIN(met->ps[ix][iy], met->p[0]);
6287 double ptop = pbot - 50.;
6288 for (int ip = 0; ip < met->np; ip++) {
6289 if (met->p[ip] <= pbot) {
6290 theta += THETA(met->p[ip], met->t[ix][iy][ip]);
6291 h2o += met->h2o[ix][iy][ip];
6292 n++;
6293 }
6294 if (met->p[ip] < ptop && n > 0)
6295 break;
6296 }
6297 theta /= n;
6298 h2o /= n;
6299
6300 /* Cannot compute anything if water vapor is missing... */
6301 met->plcl[ix][iy] = NAN;
6302 met->plfc[ix][iy] = NAN;
6303 met->pel[ix][iy] = NAN;
6304 met->cape[ix][iy] = NAN;
6305 met->cin[ix][iy] = NAN;
6306 if (h2o <= 0)
6307 continue;
6308
6309 /* Find lifted condensation level (LCL)... */
6310 ptop = P(20.);
6311 pbot = met->ps[ix][iy];
6312 do {
6313 met->plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
6314 t = theta / pow(1000. / met->plcl[ix][iy], 0.286);
6315 if (RH(met->plcl[ix][iy], t, h2o) > 100.)
6316 ptop = met->plcl[ix][iy];
6317 else
6318 pbot = met->plcl[ix][iy];
6319 } while (pbot - ptop > 0.1);
6320
6321 /* Calculate CIN up to LCL... */
6323 double dcape, dz, h2o_env, t_env;
6324 double p = met->ps[ix][iy];
6325 met->cape[ix][iy] = met->cin[ix][iy] = 0;
6326 do {
6327 dz = dz0 * TVIRT(t, h2o);
6328 p /= pfac;
6329 t = theta / pow(1000. / p, 0.286);
6330 intpol_met_space_3d(met, met->t, p, met->lon[ix], met->lat[iy],
6331 &t_env, ci, cw, 1);
6332 intpol_met_space_3d(met, met->h2o, p, met->lon[ix], met->lat[iy],
6333 &h2o_env, ci, cw, 0);
6334 dcape = 1e3 * G0 * (TVIRT(t, h2o) - TVIRT(t_env, h2o_env)) /
6335 TVIRT(t_env, h2o_env) * dz;
6336 if (dcape < 0)
6337 met->cin[ix][iy] += fabsf((float) dcape);
6338 } while (p > met->plcl[ix][iy]);
6339
6340 /* Calculate level of free convection (LFC), equilibrium level (EL),
6341 and convective available potential energy (CAPE)... */
6342 dcape = 0;
6343 p = met->plcl[ix][iy];
6344 t = theta / pow(1000. / p, 0.286);
6345 ptop = 0.75 * clim_tropo(clim, met->time, met->lat[iy]);
6346 do {
6347 dz = dz0 * TVIRT(t, h2o);
6348 p /= pfac;
6349 t -= lapse_rate(t, h2o) * dz;
6350 double psat = PSAT(t);
6351 h2o = psat / (p - (1. - EPS) * psat);
6352 intpol_met_space_3d(met, met->t, p, met->lon[ix], met->lat[iy],
6353 &t_env, ci, cw, 1);
6354 intpol_met_space_3d(met, met->h2o, p, met->lon[ix], met->lat[iy],
6355 &h2o_env, ci, cw, 0);
6356 double dcape_old = dcape;
6357 dcape = 1e3 * G0 * (TVIRT(t, h2o) - TVIRT(t_env, h2o_env)) /
6358 TVIRT(t_env, h2o_env) * dz;
6359 if (dcape > 0) {
6360 met->cape[ix][iy] += (float) dcape;
6361 if (!isfinite(met->plfc[ix][iy]))
6362 met->plfc[ix][iy] = (float) p;
6363 } else if (dcape_old > 0)
6364 met->pel[ix][iy] = (float) p;
6365 if (dcape < 0 && !isfinite(met->plfc[ix][iy]))
6366 met->cin[ix][iy] += fabsf((float) dcape);
6367 } while (p > ptop);
6368
6369 /* Check results... */
6370 if (!isfinite(met->plfc[ix][iy]))
6371 met->cin[ix][iy] = NAN;
6372 }
6373}
double clim_tropo(const clim_t *clim, const double t, const double lat)
Calculates the tropopause pressure based on climatological data.
Definition: mptrac.c:200
Here is the call graph for this function:

◆ read_met_cloud()

void read_met_cloud ( met_t met)

Calculates cloud-related variables for each grid point.

This function calculates cloud-related variables, such as cloud cover, cloud top pressure, cloud bottom pressure, and total cloud water content, based on the provided meteorological data.

Parameters
metA pointer to a structure containing meteorological data.

The function performs the following steps:

  • Sets up a timer to monitor the calculation time.
  • Initializes variables and constants required for the computation.
  • Iterates over each grid point in parallel using OpenMP.
  • Determines cloud-related variables based on thresholds for liquid water content (LWC), rain water content (RWC), ice water content (IWC) and snow water content (SWC).
  • Calculates cloud cover, cloud top pressure, cloud bottom pressure, and total cloud water content for each grid point.
  • Updates the corresponding fields in the meteorological data structure.
Note
The function utilizes OpenMP for parallelization to enhance performance by distributing the computation across multiple threads.
Author
Lars Hoffmann

Definition at line 6377 of file mptrac.c.

6378 {
6379
6380 /* Set timer... */
6381 SELECT_TIMER("READ_MET_CLOUD", "METPROC", NVTX_READ);
6382 LOG(2, "Calculate cloud data...");
6383
6384 /* Thresholds for cloud detection... */
6385 const double ccmin = 0.01, cwmin = 1e-6;
6386
6387 /* Loop over columns... */
6388#pragma omp parallel for default(shared) collapse(2)
6389 for (int ix = 0; ix < met->nx; ix++)
6390 for (int iy = 0; iy < met->ny; iy++) {
6391
6392 /* Init... */
6393 met->pct[ix][iy] = NAN;
6394 met->pcb[ix][iy] = NAN;
6395 met->cl[ix][iy] = 0;
6396
6397 /* Loop over pressure levels... */
6398 for (int ip = 0; ip < met->np - 1; ip++) {
6399
6400 /* Check pressure... */
6401 if (met->p[ip] > met->ps[ix][iy] || met->p[ip] < P(20.))
6402 continue;
6403
6404 /* Check ice water and liquid water content... */
6405 if (met->cc[ix][iy][ip] > ccmin
6406 && (met->iwc[ix][iy][ip] > cwmin
6407 || met->rwc[ix][iy][ip] > cwmin
6408 || met->lwc[ix][iy][ip] > cwmin
6409 || met->swc[ix][iy][ip] > cwmin)) {
6410
6411 /* Get cloud top pressure ... */
6412 met->pct[ix][iy]
6413 = (float) (0.5 * (met->p[ip] + (float) met->p[ip + 1]));
6414
6415 /* Get cloud bottom pressure ... */
6416 if (!isfinite(met->pcb[ix][iy]))
6417 met->pcb[ix][iy]
6418 = (float) (0.5 * (met->p[ip] + met->p[MAX(ip - 1, 0)]));
6419 }
6420
6421 /* Get cloud water... */
6422 met->cl[ix][iy] += (float)
6423 (0.5 * (met->lwc[ix][iy][ip] + met->lwc[ix][iy][ip + 1]
6424 + met->rwc[ix][iy][ip] + met->rwc[ix][iy][ip + 1]
6425 + met->iwc[ix][iy][ip] + met->iwc[ix][iy][ip + 1]
6426 + met->swc[ix][iy][ip] + met->swc[ix][iy][ip + 1])
6427 * 100. * (met->p[ip] - met->p[ip + 1]) / G0);
6428 }
6429 }
6430}

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

6436 {
6437
6438 met_t *help;
6439
6440 /* Check parameters... */
6441 if (ctl->met_detrend <= 0)
6442 return;
6443
6444 /* Set timer... */
6445 SELECT_TIMER("READ_MET_DETREND", "METPROC", NVTX_READ);
6446 LOG(2, "Detrend meteo data...");
6447
6448 /* Allocate... */
6449 ALLOC(help, met_t, 1);
6450
6451 /* Calculate standard deviation... */
6452 const double sigma = ctl->met_detrend / 2.355;
6453 const double tssq = 2. * SQR(sigma);
6454
6455 /* Calculate box size in latitude... */
6456 int sy = (int) (3. * DY2DEG(sigma) / fabs(met->lat[1] - met->lat[0]));
6457 sy = MIN(MAX(1, sy), met->ny / 2);
6458
6459 /* Calculate background... */
6460#pragma omp parallel for default(shared) collapse(2)
6461 for (int ix = 0; ix < met->nx; ix++) {
6462 for (int iy = 0; iy < met->ny; iy++) {
6463
6464 /* Calculate Cartesian coordinates... */
6465 double x0[3];
6466 geo2cart(0.0, met->lon[ix], met->lat[iy], x0);
6467
6468 /* Calculate box size in longitude... */
6469 int sx =
6470 (int) (3. * DX2DEG(sigma, met->lat[iy]) /
6471 fabs(met->lon[1] - met->lon[0]));
6472 sx = MIN(MAX(1, sx), met->nx / 2);
6473
6474 /* Init... */
6475 float wsum = 0;
6476 for (int ip = 0; ip < met->np; ip++) {
6477 help->t[ix][iy][ip] = 0;
6478 help->u[ix][iy][ip] = 0;
6479 help->v[ix][iy][ip] = 0;
6480 help->w[ix][iy][ip] = 0;
6481 }
6482
6483 /* Loop over neighboring grid points... */
6484 for (int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
6485 int ix3 = ix2;
6486 if (ix3 < 0)
6487 ix3 += met->nx;
6488 else if (ix3 >= met->nx)
6489 ix3 -= met->nx;
6490 for (int iy2 = MAX(iy - sy, 0);
6491 iy2 <= MIN(iy + sy, met->ny - 1); iy2++) {
6492
6493 /* Calculate Cartesian coordinates... */
6494 double x1[3];
6495 geo2cart(0.0, met->lon[ix3], met->lat[iy2], x1);
6496
6497 /* Calculate weighting factor... */
6498 const float w = (float) exp(-DIST2(x0, x1) / tssq);
6499
6500 /* Add data... */
6501 wsum += w;
6502 for (int ip = 0; ip < met->np; ip++) {
6503 help->t[ix][iy][ip] += w * met->t[ix3][iy2][ip];
6504 help->u[ix][iy][ip] += w * met->u[ix3][iy2][ip];
6505 help->v[ix][iy][ip] += w * met->v[ix3][iy2][ip];
6506 help->w[ix][iy][ip] += w * met->w[ix3][iy2][ip];
6507 }
6508 }
6509 }
6510
6511 /* Normalize... */
6512 for (int ip = 0; ip < met->np; ip++) {
6513 help->t[ix][iy][ip] /= wsum;
6514 help->u[ix][iy][ip] /= wsum;
6515 help->v[ix][iy][ip] /= wsum;
6516 help->w[ix][iy][ip] /= wsum;
6517 }
6518 }
6519 }
6520
6521 /* Subtract background... */
6522#pragma omp parallel for default(shared) collapse(3)
6523 for (int ix = 0; ix < met->nx; ix++)
6524 for (int iy = 0; iy < met->ny; iy++)
6525 for (int ip = 0; ip < met->np; ip++) {
6526 met->t[ix][iy][ip] -= help->t[ix][iy][ip];
6527 met->u[ix][iy][ip] -= help->u[ix][iy][ip];
6528 met->v[ix][iy][ip] -= help->v[ix][iy][ip];
6529 met->w[ix][iy][ip] -= help->w[ix][iy][ip];
6530 }
6531
6532 /* Free... */
6533 free(help);
6534}
void geo2cart(const double z, const double lon, const double lat, double *x)
Converts geographic coordinates (longitude, latitude, altitude) to Cartesian coordinates.
Definition: mptrac.c:985
#define DIST2(a, b)
Calculate the squared Euclidean distance between two points in Cartesian coordinates.
Definition: mptrac.h:594
double met_detrend
FWHM of horizontal Gaussian used for detrending [km].
Definition: mptrac.h:2582
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 6538 of file mptrac.c.

6539 {
6540
6541 /* Set timer... */
6542 SELECT_TIMER("READ_MET_EXTRAPOLATE", "METPROC", NVTX_READ);
6543 LOG(2, "Extrapolate meteo data...");
6544
6545 /* Loop over columns... */
6546#pragma omp parallel for default(shared) collapse(2)
6547 for (int ix = 0; ix < met->nx; ix++)
6548 for (int iy = 0; iy < met->ny; iy++) {
6549
6550 /* Find lowest valid data point... */
6551 int ip0;
6552 for (ip0 = met->np - 1; ip0 >= 0; ip0--)
6553 if (!isfinite(met->t[ix][iy][ip0])
6554 || !isfinite(met->u[ix][iy][ip0])
6555 || !isfinite(met->v[ix][iy][ip0])
6556 || !isfinite(met->w[ix][iy][ip0]))
6557 break;
6558
6559 /* Extrapolate... */
6560 for (int ip = ip0; ip >= 0; ip--) {
6561 met->t[ix][iy][ip] = met->t[ix][iy][ip + 1];
6562 met->u[ix][iy][ip] = met->u[ix][iy][ip + 1];
6563 met->v[ix][iy][ip] = met->v[ix][iy][ip + 1];
6564 met->w[ix][iy][ip] = met->w[ix][iy][ip + 1];
6565 met->h2o[ix][iy][ip] = met->h2o[ix][iy][ip + 1];
6566 met->o3[ix][iy][ip] = met->o3[ix][iy][ip + 1];
6567 met->lwc[ix][iy][ip] = met->lwc[ix][iy][ip + 1];
6568 met->rwc[ix][iy][ip] = met->rwc[ix][iy][ip + 1];
6569 met->iwc[ix][iy][ip] = met->iwc[ix][iy][ip + 1];
6570 met->swc[ix][iy][ip] = met->swc[ix][iy][ip + 1];
6571 met->cc[ix][iy][ip] = met->cc[ix][iy][ip + 1];
6572 }
6573 }
6574}

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

6580 {
6581
6582 float *help;
6583
6584 double logp[EP];
6585
6586 int dx = ctl->met_geopot_sx, dy = ctl->met_geopot_sy;
6587
6588 /* Set timer... */
6589 SELECT_TIMER("READ_MET_GEOPOT", "METPROC", NVTX_READ);
6590 LOG(2, "Calculate geopotential heights...");
6591
6592 /* Allocate... */
6593 ALLOC(help, float,
6594 EX * EY * EP);
6595
6596 /* Calculate log pressure... */
6597#pragma omp parallel for default(shared)
6598 for (int ip = 0; ip < met->np; ip++)
6599 logp[ip] = log(met->p[ip]);
6600
6601 /* Apply hydrostatic equation to calculate geopotential heights... */
6602#pragma omp parallel for default(shared) collapse(2)
6603 for (int ix = 0; ix < met->nx; ix++)
6604 for (int iy = 0; iy < met->ny; iy++) {
6605
6606 /* Get surface height and pressure... */
6607 const double zs = met->zs[ix][iy];
6608 const double lnps = log(met->ps[ix][iy]);
6609
6610 /* Get temperature and water vapor at the surface... */
6611 const int ip0 = locate_irr(met->p, met->np, met->ps[ix][iy]);
6612 const double ts = LIN(met->p[ip0], met->t[ix][iy][ip0], met->p[ip0 + 1],
6613 met->t[ix][iy][ip0 + 1], met->ps[ix][iy]);
6614 const double h2os =
6615 LIN(met->p[ip0], met->h2o[ix][iy][ip0], met->p[ip0 + 1],
6616 met->h2o[ix][iy][ip0 + 1], met->ps[ix][iy]);
6617
6618 /* Upper part of profile... */
6619 met->z[ix][iy][ip0 + 1]
6620 = (float) (zs +
6621 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
6622 met->t[ix][iy][ip0 + 1], met->h2o[ix][iy][ip0 + 1]));
6623 for (int ip = ip0 + 2; ip < met->np; ip++)
6624 met->z[ix][iy][ip]
6625 = (float) (met->z[ix][iy][ip - 1] +
6626 ZDIFF(logp[ip - 1], met->t[ix][iy][ip - 1],
6627 met->h2o[ix][iy][ip - 1], logp[ip],
6628 met->t[ix][iy][ip], met->h2o[ix][iy][ip]));
6629
6630 /* Lower part of profile... */
6631 met->z[ix][iy][ip0]
6632 = (float) (zs +
6633 ZDIFF(lnps, ts, h2os, logp[ip0],
6634 met->t[ix][iy][ip0], met->h2o[ix][iy][ip0]));
6635 for (int ip = ip0 - 1; ip >= 0; ip--)
6636 met->z[ix][iy][ip]
6637 = (float) (met->z[ix][iy][ip + 1] +
6638 ZDIFF(logp[ip + 1], met->t[ix][iy][ip + 1],
6639 met->h2o[ix][iy][ip + 1], logp[ip],
6640 met->t[ix][iy][ip], met->h2o[ix][iy][ip]));
6641 }
6642
6643 /* Check control parameters... */
6644 if (dx == 0 || dy == 0)
6645 return;
6646
6647 /* Default smoothing parameters... */
6648 if (dx < 0 || dy < 0) {
6649 if (fabs(met->lon[1] - met->lon[0]) < 0.5) {
6650 dx = 3;
6651 dy = 2;
6652 } else {
6653 dx = 6;
6654 dy = 4;
6655 }
6656 }
6657
6658 /* Calculate weights for smoothing... */
6659 float ws[dx + 1][dy + 1];
6660#pragma omp parallel for default(shared) collapse(2)
6661 for (int ix = 0; ix <= dx; ix++)
6662 for (int iy = 0; iy < dy; iy++)
6663 ws[ix][iy] = (1.0f - (float) ix / (float) dx)
6664 * (1.0f - (float) iy / (float) dy);
6665
6666 /* Copy data... */
6667#pragma omp parallel for default(shared) collapse(3)
6668 for (int ix = 0; ix < met->nx; ix++)
6669 for (int iy = 0; iy < met->ny; iy++)
6670 for (int ip = 0; ip < met->np; ip++)
6671 help[ARRAY_3D(ip, ix, met->nx, iy, met->ny)] = met->z[ix][iy][ip];
6672
6673 /* Horizontal smoothing... */
6674#pragma omp parallel for default(shared) collapse(3)
6675 for (int ip = 0; ip < met->np; ip++)
6676 for (int ix = 0; ix < met->nx; ix++)
6677 for (int iy = 0; iy < met->ny; iy++) {
6678 float res = 0, wsum = 0;
6679 int iy0 = MAX(iy - dy + 1, 0);
6680 int iy1 = MIN(iy + dy - 1, met->ny - 1);
6681 for (int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
6682 int ix3 = ix2;
6683 if (ix3 < 0)
6684 ix3 += met->nx;
6685 else if (ix3 >= met->nx)
6686 ix3 -= met->nx;
6687 for (int iy2 = iy0; iy2 <= iy1; ++iy2)
6688 if (isfinite(help[ARRAY_3D(ip, ix3, met->nx, iy2, met->ny)])) {
6689 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
6690 res += w * help[ARRAY_3D(ip, ix3, met->nx, iy2, met->ny)];
6691 wsum += w;
6692 }
6693 }
6694 if (wsum > 0)
6695 met->z[ix][iy][ip] = res / wsum;
6696 else
6697 met->z[ix][iy][ip] = NAN;
6698 }
6699
6700 /* Free... */
6701 free(help);
6702}
#define ZDIFF(lnp0, t0, h2o0, lnp1, t1, h2o1)
Calculate geopotential height difference.
Definition: mptrac.h:1772
Here is the call graph for this function:

◆ read_met_grid()

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

Reads meteorological grid information from a NetCDF file.

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

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

The function performs the following steps:

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

Definition at line 6706 of file mptrac.c.

6710 {
6711
6712 char levname[LEN], tstr[10];
6713
6714 double rtime = 0, r, r2;
6715
6716 int varid, year2, mon2, day2, hour2, min2, sec2,
6717 year, mon, day, hour, min, sec;
6718
6719 size_t np;
6720
6721 /* Set timer... */
6722 SELECT_TIMER("READ_MET_GRID", "INPUT", NVTX_READ);
6723 LOG(2, "Read meteo grid information...");
6724
6725 /* MPTRAC meteo files... */
6726 if (ctl->met_clams == 0) {
6727
6728 /* Get time from filename... */
6729 met->time = time_from_filename(filename, 16);
6730
6731 /* Check time information from data file... */
6732 jsec2time(met->time, &year, &mon, &day, &hour, &min, &sec, &r);
6733 if (nc_inq_varid(ncid, "time", &varid) == NC_NOERR) {
6734 NC(nc_get_var_double(ncid, varid, &rtime));
6735 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
6736 WARN("Time information in meteo file does not match filename!");
6737 } else
6738 WARN("Time information in meteo file is missing!");
6739 }
6740
6741 /* CLaMS meteo files... */
6742 else {
6743
6744 /* Read time from file... */
6745 NC_GET_DOUBLE("time", &rtime, 0);
6746
6747 /* Get time from filename (considering the century)... */
6748 if (rtime < 0)
6749 sprintf(tstr, "19%.2s", &filename[strlen(filename) - 11]);
6750 else
6751 sprintf(tstr, "20%.2s", &filename[strlen(filename) - 11]);
6752 year = atoi(tstr);
6753 sprintf(tstr, "%.2s", &filename[strlen(filename) - 9]);
6754 mon = atoi(tstr);
6755 sprintf(tstr, "%.2s", &filename[strlen(filename) - 7]);
6756 day = atoi(tstr);
6757 sprintf(tstr, "%.2s", &filename[strlen(filename) - 5]);
6758 hour = atoi(tstr);
6759 time2jsec(year, mon, day, hour, 0, 0, 0, &met->time);
6760 }
6761
6762 /* Check time... */
6763 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
6764 || day < 1 || day > 31 || hour < 0 || hour > 23)
6765 ERRMSG("Cannot read time from filename!");
6766 jsec2time(met->time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
6767 LOG(2, "Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
6768 met->time, year2, mon2, day2, hour2, min2);
6769
6770 /* Get grid dimensions... */
6771 NC_INQ_DIM("lon", &met->nx, 2, EX);
6772 LOG(2, "Number of longitudes: %d", met->nx);
6773
6774 NC_INQ_DIM("lat", &met->ny, 2, EY);
6775 LOG(2, "Number of latitudes: %d", met->ny);
6776
6777 int dimid2;
6778 sprintf(levname, "lev");
6779 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
6780 sprintf(levname, "plev");
6781 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
6782 sprintf(levname, "hybrid");
6783
6784 NC_INQ_DIM(levname, &met->np, 1, EP);
6785 if (met->np == 1) {
6786 sprintf(levname, "lev_2");
6787 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR) {
6788 sprintf(levname, "plev");
6789 NC(nc_inq_dimid(ncid, levname, &dimid2));
6790 }
6791 NC(nc_inq_dimlen(ncid, dimid2, &np));
6792 met->np = (int) np;
6793 }
6794 LOG(2, "Number of levels: %d", met->np);
6795 if (met->np < 2 || met->np > EP)
6796 ERRMSG("Number of levels out of range!");
6797
6798 /* Read longitudes and latitudes... */
6799 NC_GET_DOUBLE("lon", met->lon, 1);
6800 LOG(2, "Longitudes: %g, %g ... %g deg",
6801 met->lon[0], met->lon[1], met->lon[met->nx - 1]);
6802 NC_GET_DOUBLE("lat", met->lat, 1);
6803 LOG(2, "Latitudes: %g, %g ... %g deg",
6804 met->lat[0], met->lat[1], met->lat[met->ny - 1]);
6805
6806 /* Read pressure levels... */
6807 if (ctl->met_np <= 0) {
6808 NC_GET_DOUBLE(levname, met->p, 1);
6809 for (int ip = 0; ip < met->np; ip++)
6810 met->p[ip] /= 100.;
6811 LOG(2, "Altitude levels: %g, %g ... %g km",
6812 Z(met->p[0]), Z(met->p[1]), Z(met->p[met->np - 1]));
6813 LOG(2, "Pressure levels: %g, %g ... %g hPa",
6814 met->p[0], met->p[1], met->p[met->np - 1]);
6815 }
6816
6817 /* Read hybrid levels... */
6818 if (strcasecmp(levname, "hybrid") == 0)
6819 NC_GET_DOUBLE("hybrid", met->hybrid, 1);
6820}
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:8644
double time_from_filename(const char *filename, const int offset)
Extracts and converts a timestamp from a filename to Julian seconds.
Definition: mptrac.c:8743
double hybrid[EP]
Model hybrid levels.
Definition: mptrac.h:3401
Here is the call graph for this function:

◆ read_met_levels()

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

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

This function reads meteorological variables such as temperature, wind components, specific humidity, ozone data, cloud parameters, and cloud cover at various vertical levels from a NetCDF file. The function supports reading meteorological data from both MPTRAC and CLaMS formats. Depending on the file format, it reads specific variables and performs necessary conversions or interpolations.

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

The function performs the following steps:

  • Sets up a timer to monitor the reading time for meteorological level data.
  • Reads meteorological variables from the NetCDF file based on the specified control parameters and file format.
  • Handles specific variables differently depending on the file format, such as reading temperature, wind components, humidity, ozone data, and cloud parameters.
  • Performs conversions or interpolations if necessary, such as converting specific humidity and ozone data from mixing ratio to volume mixing ratio.
  • Transfers velocity components to model levels for diabatic advection if applicable.
  • Reads pressure on model levels if specified in the control parameters.
  • Performs vertical interpolation from model levels to pressure levels if needed.
  • Checks the ordering of pressure levels to ensure they are in descending order.
Note
This function supports reading meteorological variables from NetCDF files in MPTRAC or CLaMS formats and handles specific variables differently based on the file format and control parameters. It performs necessary conversions or interpolations and ensures the correctness of pressure levels.
Authors
Lars Hoffmann
Jan Clemens

Definition at line 6824 of file mptrac.c.

6827 {
6828
6829 /* Set timer... */
6830 SELECT_TIMER("READ_MET_LEVELS", "INPUT", NVTX_READ);
6831 LOG(2, "Read level data...");
6832
6833 /* Read temperature... */
6834 if (!read_met_nc_3d(ncid, "t", "T", "temp", "TEMP", ctl, met, met->t, 1.0))
6835 ERRMSG("Cannot read temperature!");
6836
6837 /* Read horizontal wind and vertical velocity... */
6838 if (!read_met_nc_3d(ncid, "u", "U", NULL, NULL, ctl, met, met->u, 1.0))
6839 ERRMSG("Cannot read zonal wind!");
6840 if (!read_met_nc_3d(ncid, "v", "V", NULL, NULL, ctl, met, met->v, 1.0))
6841 ERRMSG("Cannot read meridional wind!");
6842 if (!read_met_nc_3d
6843 (ncid, "w", "W", "omega", "OMEGA", ctl, met, met->w, 0.01f))
6844 WARN("Cannot read vertical velocity!");
6845
6846 /* Read water vapor... */
6847 if (!ctl->met_relhum) {
6848 if (!read_met_nc_3d
6849 (ncid, "q", "Q", "sh", "SH", ctl, met, met->h2o, (float) (MA / MH2O)))
6850 WARN("Cannot read specific humidity!");
6851 } else {
6852 if (!read_met_nc_3d
6853 (ncid, "rh", "RH", NULL, NULL, ctl, met, met->h2o, 0.01f))
6854 WARN("Cannot read relative humidity!");
6855#pragma omp parallel for default(shared) collapse(2)
6856 for (int ix = 0; ix < met->nx; ix++)
6857 for (int iy = 0; iy < met->ny; iy++)
6858 for (int ip = 0; ip < met->np; ip++) {
6859 double pw = met->h2o[ix][iy][ip] * PSAT(met->t[ix][iy][ip]);
6860 met->h2o[ix][iy][ip] =
6861 (float) (pw / (met->p[ip] - (1.0 - EPS) * pw));
6862 }
6863 }
6864
6865 /* Read ozone... */
6866 if (!read_met_nc_3d
6867 (ncid, "o3", "O3", NULL, NULL, ctl, met, met->o3, (float) (MA / MO3)))
6868 WARN("Cannot read ozone data!");
6869
6870 /* Read cloud data... */
6871 if (!read_met_nc_3d
6872 (ncid, "clwc", "CLWC", NULL, NULL, ctl, met, met->lwc, 1.0))
6873 WARN("Cannot read cloud liquid water content!");
6874 if (!read_met_nc_3d
6875 (ncid, "crwc", "CRWC", NULL, NULL, ctl, met, met->rwc, 1.0))
6876 WARN("Cannot read cloud rain water content!");
6877 if (!read_met_nc_3d
6878 (ncid, "ciwc", "CIWC", NULL, NULL, ctl, met, met->iwc, 1.0))
6879 WARN("Cannot read cloud ice water content!");
6880 if (!read_met_nc_3d
6881 (ncid, "cswc", "CSWC", NULL, NULL, ctl, met, met->swc, 1.0))
6882 WARN("Cannot read cloud snow water content!");
6883 if (!read_met_nc_3d(ncid, "cc", "CC", NULL, NULL, ctl, met, met->cc, 1.0))
6884 WARN("Cannot read cloud cover!");
6885
6886 /* Read zeta and zeta_dot... */
6887 if (!read_met_nc_3d
6888 (ncid, "ZETA", "zeta", NULL, NULL, ctl, met, met->zetal, 1.0))
6889 WARN("Cannot read ZETA!");
6890 if (!read_met_nc_3d
6891 (ncid, "ZETA_DOT_TOT", "ZETA_DOT_clr", "zeta_dot_clr",
6892 NULL, ctl, met, met->zeta_dotl, 0.00001157407f))
6893 WARN("Cannot read ZETA_DOT!");
6894
6895 /* Store velocities on model levels for diabatic advection... */
6896 if (ctl->met_vert_coord == 1) {
6897 for (int ix = 0; ix < met->nx; ix++)
6898 for (int iy = 0; iy < met->ny; iy++)
6899 for (int ip = 0; ip < met->np; ip++) {
6900 met->ul[ix][iy][ip] = met->u[ix][iy][ip];
6901 met->vl[ix][iy][ip] = met->v[ix][iy][ip];
6902 met->wl[ix][iy][ip] = met->w[ix][iy][ip];
6903 }
6904
6905 /* Original number of vertical levels... */
6906 met->npl = met->np;
6907 }
6908
6909 /* Read pressure on model levels... */
6910 if (ctl->met_np > 0 || ctl->met_vert_coord == 1) {
6911
6912 /* Read data... */
6913 if (!read_met_nc_3d
6914 (ncid, "pl", "PL", "pressure", "PRESSURE", ctl, met, met->pl, 0.01f))
6915 if (!read_met_nc_3d
6916 (ncid, "press", "PRESS", NULL, NULL, ctl, met, met->pl, 1.0))
6917 ERRMSG("Cannot read pressure on model levels!");
6918
6919 /* Check ordering of pressure levels... */
6920 for (int ix = 0; ix < met->nx; ix++)
6921 for (int iy = 0; iy < met->ny; iy++)
6922 for (int ip = 1; ip < met->np; ip++)
6923 if ((met->pl[ix][iy][0] > met->pl[ix][iy][1]
6924 && met->pl[ix][iy][ip - 1] <= met->pl[ix][iy][ip])
6925 || (met->pl[ix][iy][0] < met->pl[ix][iy][1]
6926 && met->pl[ix][iy][ip - 1] >= met->pl[ix][iy][ip]))
6927 ERRMSG("Pressure profiles are not monotonic!");
6928 }
6929
6930 /* Interpolate from model levels to pressure levels... */
6931 if (ctl->met_np > 0) {
6932
6933 /* Interpolate variables... */
6934 read_met_ml2pl(ctl, met, met->t, "T");
6935 read_met_ml2pl(ctl, met, met->u, "U");
6936 read_met_ml2pl(ctl, met, met->v, "V");
6937 read_met_ml2pl(ctl, met, met->w, "W");
6938 read_met_ml2pl(ctl, met, met->h2o, "H2O");
6939 read_met_ml2pl(ctl, met, met->o3, "O3");
6940 read_met_ml2pl(ctl, met, met->lwc, "LWC");
6941 read_met_ml2pl(ctl, met, met->rwc, "RWC");
6942 read_met_ml2pl(ctl, met, met->iwc, "IWC");
6943 read_met_ml2pl(ctl, met, met->swc, "SWC");
6944 read_met_ml2pl(ctl, met, met->cc, "CC");
6945
6946 /* Set new pressure levels... */
6947 met->np = ctl->met_np;
6948 for (int ip = 0; ip < met->np; ip++)
6949 met->p[ip] = ctl->met_p[ip];
6950 }
6951
6952 /* Check ordering of pressure levels... */
6953 for (int ip = 1; ip < met->np; ip++)
6954 if (met->p[ip - 1] < met->p[ip])
6955 ERRMSG("Pressure levels must be descending!");
6956}
void read_met_ml2pl(const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname)
Interpolates meteorological data to specified pressure levels.
Definition: mptrac.c:6960
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:7312
#define MH2O
Molar mass of water vapor [g/mol].
Definition: mptrac.h:202
#define MO3
Molar mass of ozone [g/mol].
Definition: mptrac.h:207
int met_vert_coord
Vertical coordinate of input meteo data (0=pressure-level, 1=model-level).
Definition: mptrac.h:2490
Here is the call graph for this function:

◆ read_met_ml2pl()

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

Interpolates meteorological data to specified pressure levels.

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

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

This function performs the following steps:

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

Definition at line 6960 of file mptrac.c.

6964 {
6965
6966 double aux[EP], p[EP];
6967
6968 /* Set timer... */
6969 SELECT_TIMER("READ_MET_ML2PL", "METPROC", NVTX_READ);
6970 LOG(2, "Interpolate meteo data to pressure levels: %s", varname);
6971
6972 /* Loop over columns... */
6973#pragma omp parallel for default(shared) private(aux,p) collapse(2)
6974 for (int ix = 0; ix < met->nx; ix++)
6975 for (int iy = 0; iy < met->ny; iy++) {
6976
6977 /* Copy pressure profile... */
6978 for (int ip = 0; ip < met->np; ip++)
6979 p[ip] = met->pl[ix][iy][ip];
6980
6981 /* Interpolate... */
6982 for (int ip = 0; ip < ctl->met_np; ip++) {
6983 double pt = ctl->met_p[ip];
6984 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
6985 pt = p[0];
6986 else if ((pt > p[met->np - 1] && p[1] > p[0])
6987 || (pt < p[met->np - 1] && p[1] < p[0]))
6988 pt = p[met->np - 1];
6989 int ip2 = locate_irr(p, met->np, pt);
6990 aux[ip] = LIN(p[ip2], var[ix][iy][ip2],
6991 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
6992 }
6993
6994 /* Copy data... */
6995 for (int ip = 0; ip < ctl->met_np; ip++)
6996 var[ix][iy][ip] = (float) aux[ip];
6997 }
6998}
Here is the call graph for this function:

◆ read_met_monotonize()

void read_met_monotonize ( met_t met)

Makes zeta and pressure profiles monotone.

This function ensures that zeta and pressure profiles are monotone increasing and decreasing with altitude. It iterates over each grid point and each level to identify inversions and linearly interpolate between them to maintain monotonicity. The interpolation is performed for both zeta and pressure profiles.

Parameters
metA pointer to a structure containing meteorological data.

The function performs the following steps:

  • Sets up a timer to monitor the processing time.
  • Iterates over each grid point in parallel using OpenMP.
  • Identifies inversions in both zeta and pressure profiles and interpolates linearly between them to make the profiles monotone increasing.
Note
This function is crucial for maintaining the physical consistency of meteorological profiles, ensuring accurate atmospheric simulations.
Author
Jan Clemens

Definition at line 7002 of file mptrac.c.

7003 {
7004
7005 /* Set timer... */
7006 SELECT_TIMER("READ_MET_MONOTONIZE", "METPROC", NVTX_READ);
7007 LOG(2, "Make zeta profiles monotone...");
7008
7009 /* Create monotone zeta profiles... */
7010#pragma omp parallel for default(shared) collapse(2)
7011 for (int i = 0; i < met->nx; i++)
7012 for (int j = 0; j < met->ny; j++) {
7013 int k = 1;
7014
7015 while (k < met->npl) { /* Check if there is an inversion at level k... */
7016 if ((met->zetal[i][j][k - 1] >= met->zetal[i][j][k])) {
7017 /* Find the upper level k+l over the inversion... */
7018 int l = 0;
7019 do {
7020 l++;
7021 }
7022 while ((met->zetal[i][j][k - 1] >=
7023 met->zetal[i][j][k + l]) & (k + l < met->npl));
7024
7025 /* Interpolate linear between the top and bottom
7026 of the inversion... */
7027 float s =
7028 (float) (met->zetal[i][j][k + l] - met->zetal[i][j][k - 1])
7029 / (float) (met->hybrid[k + l] - met->hybrid[k - 1]);
7030
7031 for (int m = k; m < k + l; m++) {
7032 float d = (float) (met->hybrid[m] - met->hybrid[k - 1]);
7033 met->zetal[i][j][m] = s * d + met->zetal[i][j][k - 1];
7034 }
7035
7036 /* Search for more inversions above the last inversion ... */
7037 k = k + l;
7038 } else {
7039 k++;
7040 }
7041 }
7042 }
7043
7044 /* Create monotone pressure profiles... */
7045#pragma omp parallel for default(shared) collapse(2)
7046 for (int i = 0; i < met->nx; i++)
7047 for (int j = 0; j < met->ny; j++) {
7048 int k = 1;
7049
7050 while (k < met->npl) { /* Check if there is an inversion at level k... */
7051 if ((met->pl[i][j][k - 1] <= met->pl[i][j][k])) {
7052
7053 /* Find the upper level k+l over the inversion... */
7054 int l = 0;
7055 do {
7056 l++;
7057 }
7058 while ((met->pl[i][j][k - 1] <= met->pl[i][j][k + l]) & (k + l <
7059 met->npl));
7060
7061 /* Interpolate linear between the top and bottom
7062 of the inversion... */
7063 float s = (float) (met->pl[i][j][k + l] - met->pl[i][j][k - 1])
7064 / (float) (met->hybrid[k + l] - met->hybrid[k - 1]);
7065
7066 for (int m = k; m < k + l; m++) {
7067 float d = (float) (met->hybrid[m] - met->hybrid[k - 1]);
7068 met->pl[i][j][m] = s * d + met->pl[i][j][k - 1];
7069 }
7070
7071 /* Search for more inversions above the last inversion ... */
7072 k += l;
7073 } else {
7074 k++;
7075 }
7076 }
7077 }
7078}

◆ read_met_nc()

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

Reads meteorological data from a NetCDF file and processes it.

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

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

Definition at line 7082 of file mptrac.c.

7086 {
7087
7088 int ncid;
7089
7090 /* Open netCDF file... */
7091 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7092 WARN("Cannot open file!");
7093 return 0;
7094 }
7095
7096 /* Read coordinates of meteo data... */
7097 read_met_grid(filename, ncid, ctl, met);
7098
7099 /* Read meteo data on vertical levels... */
7100 read_met_levels(ncid, ctl, met);
7101
7102 /* Extrapolate data for lower boundary... */
7104
7105 /* Read surface data... */
7106 read_met_surface(ncid, ctl, met);
7107
7108 /* Fix polar winds... */
7110
7111 /* Create periodic boundary conditions... */
7112 read_met_periodic(met);
7113
7114 /* Downsampling... */
7115 read_met_sample(ctl, met);
7116
7117 /* Calculate geopotential heights... */
7118 read_met_geopot(ctl, met);
7119
7120 /* Calculate potential vorticity... */
7121 read_met_pv(met);
7122
7123 /* Calculate boundary layer data... */
7124 read_met_pbl(ctl, met);
7125
7126 /* Calculate tropopause data... */
7127 read_met_tropo(ctl, clim, met);
7128
7129 /* Calculate cloud properties... */
7130 read_met_cloud(met);
7131
7132 /* Calculate convective available potential energy... */
7133 read_met_cape(ctl, clim, met);
7134
7135 /* Calculate total column ozone... */
7136 read_met_ozone(met);
7137
7138 /* Detrending... */
7139 read_met_detrend(ctl, met);
7140
7141 /* Check meteo data and smooth zeta profiles ... */
7142 if (ctl->advect_vert_coord == 1)
7144
7145 /* Close file... */
7146 NC(nc_close(ncid));
7147
7148 /* Return success... */
7149 return 1;
7150}
void read_met_geopot(const ctl_t *ctl, met_t *met)
Calculates geopotential heights from meteorological data.
Definition: mptrac.c:6578
void read_met_extrapolate(met_t *met)
Extrapolates meteorological data.
Definition: mptrac.c:6538
void read_met_levels(const int ncid, const ctl_t *ctl, met_t *met)
Reads meteorological variables at different vertical levels from a NetCDF file.
Definition: mptrac.c:6824
void read_met_sample(const ctl_t *ctl, met_t *met)
Downsamples meteorological data based on specified parameters.
Definition: mptrac.c:7850
void read_met_cloud(met_t *met)
Calculates cloud-related variables for each grid point.
Definition: mptrac.c:6377
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:7458
void read_met_detrend(const ctl_t *ctl, met_t *met)
Detrends meteorological data.
Definition: mptrac.c:6434
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
Definition: mptrac.c:7595
void read_met_grid(const char *filename, const int ncid, const ctl_t *ctl, met_t *met)
Reads meteorological grid information from a NetCDF file.
Definition: mptrac.c:6706
void read_met_monotonize(met_t *met)
Makes zeta and pressure profiles monotone.
Definition: mptrac.c:7002
void read_met_surface(const int ncid, const ctl_t *ctl, met_t *met)
Reads surface meteorological data from a netCDF file and stores it in the meteorological data structu...
Definition: mptrac.c:8022
void read_met_ozone(met_t *met)
Calculates the total column ozone from meteorological ozone data.
Definition: mptrac.c:7821
void read_met_pv(met_t *met)
Calculates potential vorticity (PV) from meteorological data.
Definition: mptrac.c:7715
void read_met_polar_winds(met_t *met)
Applies a fix for polar winds in meteorological data.
Definition: mptrac.c:7656
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:6262
Here is the call graph for this function:

◆ read_met_nc_2d()

int read_met_nc_2d ( const int  ncid,
const char *  varname,
const char *  varname2,
const char *  varname3,
const char *  varname4,
const char *  varname5,
const char *  varname6,
const ctl_t ctl,
const met_t met,
float  dest[EX][EY],
const float  scl,
const int  init 
)

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

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

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

The function performs the following steps:

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

Definition at line 7154 of file mptrac.c.

7166 {
7167
7168 char varsel[LEN];
7169
7170 float offset, scalfac;
7171
7172 int varid;
7173
7174 /* Check if variable exists... */
7175 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
7176 sprintf(varsel, "%s", varname);
7177 else if (varname2 != NULL
7178 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
7179 sprintf(varsel, "%s", varname2);
7180 else if (varname3 != NULL
7181 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
7182 sprintf(varsel, "%s", varname3);
7183 else if (varname4 != NULL
7184 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
7185 sprintf(varsel, "%s", varname4);
7186 else if (varname5 != NULL
7187 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
7188 sprintf(varsel, "%s", varname5);
7189 else if (varname6 != NULL
7190 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
7191 sprintf(varsel, "%s", varname6);
7192 else
7193 return 0;
7194
7195 /* Read packed data... */
7196 if (ctl->met_nc_scale
7197 && nc_get_att_float(ncid, varid, "add_offset", &offset) == NC_NOERR
7198 && nc_get_att_float(ncid, varid, "scale_factor",
7199 &scalfac) == NC_NOERR) {
7200
7201 /* Allocate... */
7202 short *help;
7203 ALLOC(help, short,
7204 EX * EY * EP);
7205
7206 /* Read fill value and missing value... */
7207 short fillval, missval;
7208 if (nc_get_att_short(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
7209 fillval = 0;
7210 if (nc_get_att_short(ncid, varid, "missing_value", &missval) != NC_NOERR)
7211 missval = 0;
7212
7213 /* Write info... */
7214 LOG(2, "Read 2-D variable: %s"
7215 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
7216 varsel, fillval, missval, scalfac, offset);
7217
7218 /* Read data... */
7219 NC(nc_get_var_short(ncid, varid, help));
7220
7221 /* Check meteo data layout... */
7222 if (ctl->met_convention != 0)
7223 ERRMSG("Meteo data layout not implemented for packed netCDF files!");
7224
7225 /* Copy and check data... */
7226#pragma omp parallel for default(shared) num_threads(12)
7227 for (int ix = 0; ix < met->nx; ix++)
7228 for (int iy = 0; iy < met->ny; iy++) {
7229 if (init)
7230 dest[ix][iy] = 0;
7231 const short aux = help[ARRAY_2D(iy, ix, met->nx)];
7232 if ((fillval == 0 || aux != fillval)
7233 && (missval == 0 || aux != missval)
7234 && fabsf(aux * scalfac + offset) < 1e14f)
7235 dest[ix][iy] += scl * (aux * scalfac + offset);
7236 else
7237 dest[ix][iy] = NAN;
7238 }
7239
7240 /* Free... */
7241 free(help);
7242 }
7243
7244 /* Unpacked data... */
7245 else {
7246
7247 /* Allocate... */
7248 float *help;
7249 ALLOC(help, float,
7250 EX * EY);
7251
7252 /* Read fill value and missing value... */
7253 float fillval, missval;
7254 if (nc_get_att_float(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
7255 fillval = 0;
7256 if (nc_get_att_float(ncid, varid, "missing_value", &missval) != NC_NOERR)
7257 missval = 0;
7258
7259 /* Write info... */
7260 LOG(2, "Read 2-D variable: %s (FILL = %g, MISS = %g)",
7261 varsel, fillval, missval);
7262
7263 /* Read data... */
7264 NC(nc_get_var_float(ncid, varid, help));
7265
7266 /* Check meteo data layout... */
7267 if (ctl->met_convention == 0) {
7268
7269 /* Copy and check data (ordering: lat, lon)... */
7270#pragma omp parallel for default(shared) num_threads(12)
7271 for (int ix = 0; ix < met->nx; ix++)
7272 for (int iy = 0; iy < met->ny; iy++) {
7273 if (init)
7274 dest[ix][iy] = 0;
7275 const float aux = help[ARRAY_2D(iy, ix, met->nx)];
7276 if ((fillval == 0 || aux != fillval)
7277 && (missval == 0 || aux != missval)
7278 && fabsf(aux) < 1e14f)
7279 dest[ix][iy] += scl * aux;
7280 else
7281 dest[ix][iy] = NAN;
7282 }
7283
7284 } else {
7285
7286 /* Copy and check data (ordering: lon, lat)... */
7287#pragma omp parallel for default(shared) num_threads(12)
7288 for (int iy = 0; iy < met->ny; iy++)
7289 for (int ix = 0; ix < met->nx; ix++) {
7290 if (init)
7291 dest[ix][iy] = 0;
7292 const float aux = help[ARRAY_2D(ix, iy, met->ny)];
7293 if ((fillval == 0 || aux != fillval)
7294 && (missval == 0 || aux != missval)
7295 && fabsf(aux) < 1e14f)
7296 dest[ix][iy] += scl * aux;
7297 else
7298 dest[ix][iy] = NAN;
7299 }
7300 }
7301
7302 /* Free... */
7303 free(help);
7304 }
7305
7306 /* Return... */
7307 return 1;
7308}
int met_nc_scale
Check netCDF scaling factors (0=no, 1=yes).
Definition: mptrac.h:2500
int met_convention
Meteo data layout (0=[lev, lat, lon], 1=[lon, lat, lev]).
Definition: mptrac.h:2487

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

7321 {
7322
7323 char varsel[LEN];
7324
7325 float offset, scalfac;
7326
7327 int varid;
7328
7329 /* Check if variable exists... */
7330 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
7331 sprintf(varsel, "%s", varname);
7332 else if (varname2 != NULL
7333 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
7334 sprintf(varsel, "%s", varname2);
7335 else if (varname3 != NULL
7336 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
7337 sprintf(varsel, "%s", varname3);
7338 else if (varname4 != NULL
7339 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
7340 sprintf(varsel, "%s", varname4);
7341 else
7342 return 0;
7343
7344 /* Read packed data... */
7345 if (ctl->met_nc_scale
7346 && nc_get_att_float(ncid, varid, "add_offset", &offset) == NC_NOERR
7347 && nc_get_att_float(ncid, varid, "scale_factor",
7348 &scalfac) == NC_NOERR) {
7349
7350 /* Allocate... */
7351 short *help;
7352 ALLOC(help, short,
7353 EX * EY * EP);
7354
7355 /* Read fill value and missing value... */
7356 short fillval, missval;
7357 if (nc_get_att_short(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
7358 fillval = 0;
7359 if (nc_get_att_short(ncid, varid, "missing_value", &missval) != NC_NOERR)
7360 missval = 0;
7361
7362 /* Write info... */
7363 LOG(2, "Read 3-D variable: %s "
7364 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
7365 varsel, fillval, missval, scalfac, offset);
7366
7367 /* Read data... */
7368 NC(nc_get_var_short(ncid, varid, help));
7369
7370 /* Check meteo data layout... */
7371 if (ctl->met_convention != 0)
7372 ERRMSG("Meteo data layout not implemented for packed netCDF files!");
7373
7374 /* Copy and check data... */
7375#pragma omp parallel for default(shared) num_threads(12)
7376 for (int ix = 0; ix < met->nx; ix++)
7377 for (int iy = 0; iy < met->ny; iy++)
7378 for (int ip = 0; ip < met->np; ip++) {
7379 const short aux = help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)];
7380 if ((fillval == 0 || aux != fillval)
7381 && (missval == 0 || aux != missval)
7382 && fabsf(aux * scalfac + offset) < 1e14f)
7383 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
7384 else
7385 dest[ix][iy][ip] = NAN;
7386 }
7387
7388 /* Free... */
7389 free(help);
7390 }
7391
7392 /* Unpacked data... */
7393 else {
7394
7395 /* Allocate... */
7396 float *help;
7397 ALLOC(help, float,
7398 EX * EY * EP);
7399
7400 /* Read fill value and missing value... */
7401 float fillval, missval;
7402 if (nc_get_att_float(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
7403 fillval = 0;
7404 if (nc_get_att_float(ncid, varid, "missing_value", &missval) != NC_NOERR)
7405 missval = 0;
7406
7407 /* Write info... */
7408 LOG(2, "Read 3-D variable: %s (FILL = %g, MISS = %g)",
7409 varsel, fillval, missval);
7410
7411 /* Read data... */
7412 NC(nc_get_var_float(ncid, varid, help));
7413
7414 /* Check meteo data layout... */
7415 if (ctl->met_convention == 0) {
7416
7417 /* Copy and check data (ordering: lev, lat, lon)... */
7418#pragma omp parallel for default(shared) num_threads(12)
7419 for (int ix = 0; ix < met->nx; ix++)
7420 for (int iy = 0; iy < met->ny; iy++)
7421 for (int ip = 0; ip < met->np; ip++) {
7422 const float aux = help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)];
7423 if ((fillval == 0 || aux != fillval)
7424 && (missval == 0 || aux != missval)
7425 && fabsf(aux) < 1e14f)
7426 dest[ix][iy][ip] = scl * aux;
7427 else
7428 dest[ix][iy][ip] = NAN;
7429 }
7430
7431 } else {
7432
7433 /* Copy and check data (ordering: lon, lat, lev)... */
7434#pragma omp parallel for default(shared) num_threads(12)
7435 for (int ip = 0; ip < met->np; ip++)
7436 for (int iy = 0; iy < met->ny; iy++)
7437 for (int ix = 0; ix < met->nx; ix++) {
7438 const float aux = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
7439 if ((fillval == 0 || aux != fillval)
7440 && (missval == 0 || aux != missval)
7441 && fabsf(aux) < 1e14f)
7442 dest[ix][iy][ip] = scl * aux;
7443 else
7444 dest[ix][iy][ip] = NAN;
7445 }
7446 }
7447
7448 /* Free... */
7449 free(help);
7450 }
7451
7452 /* Return... */
7453 return 1;
7454}

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

7460 {
7461
7462 /* Set timer... */
7463 SELECT_TIMER("READ_MET_PBL", "METPROC", NVTX_READ);
7464 LOG(2, "Calculate planetary boundary layer...");
7465
7466 /* Convert PBL height from meteo file to pressure... */
7467 if (ctl->met_pbl == 1) {
7468
7469 /* Loop over grid points... */
7470#pragma omp parallel for default(shared) collapse(2)
7471 for (int ix = 0; ix < met->nx; ix++)
7472 for (int iy = 0; iy < met->ny; iy++) {
7473
7474 /* Get pressure at top of PBL... */
7475 const float z = met->zs[ix][iy] + met->pbl[ix][iy];
7476 const int ip = locate_irr_float(met->z[ix][iy], met->np, z, 0);
7477 met->pbl[ix][iy] =
7478 (float) (LIN(met->z[ix][iy][ip], met->p[ip],
7479 met->z[ix][iy][ip + 1], met->p[ip + 1], z));
7480 }
7481 }
7482
7483 /* Determine PBL based on Richardson number... */
7484 else if (ctl->met_pbl == 2) {
7485
7486 /* Parameters used to estimate the height of the PBL
7487 (e.g., Vogelezang and Holtslag, 1996; Seidel et al., 2012)... */
7488 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
7489
7490 /* Loop over grid points... */
7491#pragma omp parallel for default(shared) collapse(2)
7492 for (int ix = 0; ix < met->nx; ix++)
7493 for (int iy = 0; iy < met->ny; iy++) {
7494
7495 /* Set bottom level of PBL... */
7496 const double pbl_bot = met->ps[ix][iy] * exp(-dz / H0);
7497
7498 /* Find lowest level near the bottom... */
7499 int ip;
7500 for (ip = 1; ip < met->np; ip++)
7501 if (met->p[ip] < pbl_bot)
7502 break;
7503
7504 /* Get near surface data... */
7505 const double h2os = LIN(met->p[ip - 1], met->h2o[ix][iy][ip - 1],
7506 met->p[ip], met->h2o[ix][iy][ip], pbl_bot);
7507 const double tvs = THETAVIRT(pbl_bot, met->ts[ix][iy], h2os);
7508
7509 /* Init... */
7510 double rib_old = 0;
7511
7512 /* Loop over levels... */
7513 for (; ip < met->np; ip++) {
7514
7515 /* Get squared horizontal wind speed... */
7516 double vh2 = SQR(met->u[ix][iy][ip] - met->us[ix][iy])
7517 + SQR(met->v[ix][iy][ip] - met->vs[ix][iy]);
7518 vh2 = MAX(vh2, SQR(umin));
7519
7520 /* Calculate bulk Richardson number... */
7521 const double rib =
7522 G0 * 1e3 * (met->z[ix][iy][ip] - met->zs[ix][iy]) / tvs
7523 * (THETAVIRT(met->p[ip], met->t[ix][iy][ip],
7524 met->h2o[ix][iy][ip]) - tvs) / vh2;
7525
7526 /* Check for critical value... */
7527 if (rib >= rib_crit) {
7528 met->pbl[ix][iy] = (float) (LIN(rib_old, met->p[ip - 1],
7529 rib, met->p[ip], rib_crit));
7530 if (met->pbl[ix][iy] > pbl_bot)
7531 met->pbl[ix][iy] = (float) pbl_bot;
7532 break;
7533 }
7534
7535 /* Save Richardson number... */
7536 rib_old = rib;
7537 }
7538 }
7539 }
7540
7541 /* Determine PBL based on potential temperature... */
7542 if (ctl->met_pbl == 3) {
7543
7544 /* Parameters used to estimate the height of the PBL
7545 (following HYSPLIT model)... */
7546 const double dtheta = 2.0, zmin = 0.1;
7547
7548 /* Loop over grid points... */
7549#pragma omp parallel for default(shared) collapse(2)
7550 for (int ix = 0; ix < met->nx; ix++)
7551 for (int iy = 0; iy < met->ny; iy++) {
7552
7553 /* Potential temperature at the surface... */
7554 const double theta0 = THETA(met->ps[ix][iy], met->ts[ix][iy]);
7555
7556 /* Find topmost level where theta exceeds surface value by 2 K... */
7557 int ip;
7558 for (ip = met->np - 2; ip > 0; ip--)
7559 if (met->p[ip] >= 300.)
7560 if (met->p[ip] > met->ps[ix][iy]
7561 || THETA(met->p[ip], met->t[ix][iy][ip]) <= theta0 + dtheta)
7562 break;
7563
7564 /* Interpolate... */
7565 met->pbl[ix][iy]
7566 = (float) (LIN(THETA(met->p[ip + 1], met->t[ix][iy][ip + 1]),
7567 met->p[ip + 1],
7568 THETA(met->p[ip], met->t[ix][iy][ip]),
7569 met->p[ip], theta0 + dtheta));
7570
7571 /* Check minimum value... */
7572 double pbl_min = met->ps[ix][iy] * exp(-zmin / H0);
7573 if (met->pbl[ix][iy] > pbl_min || met->p[ip] > met->ps[ix][iy])
7574 met->pbl[ix][iy] = (float) pbl_min;
7575 }
7576 }
7577
7578 /* Loop over grid points... */
7579#pragma omp parallel for default(shared) collapse(2)
7580 for (int ix = 0; ix < met->nx; ix++)
7581 for (int iy = 0; iy < met->ny; iy++) {
7582
7583 /* Check minimum value... */
7584 double pbl_min = met->ps[ix][iy] * exp(-ctl->met_pbl_min / H0);
7585 met->pbl[ix][iy] = MIN(met->pbl[ix][iy], (float) pbl_min);
7586
7587 /* Check maximum value... */
7588 double pbl_max = met->ps[ix][iy] * exp(-ctl->met_pbl_max / H0);
7589 met->pbl[ix][iy] = MAX(met->pbl[ix][iy], (float) pbl_max);
7590 }
7591}
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 7595 of file mptrac.c.

7596 {
7597
7598 /* Set timer... */
7599 SELECT_TIMER("READ_MET_PERIODIC", "METPROC", NVTX_READ);
7600 LOG(2, "Apply periodic boundary conditions...");
7601
7602 /* Check longitudes... */
7603 if (!(fabs(met->lon[met->nx - 1] - met->lon[0]
7604 + met->lon[1] - met->lon[0] - 360) < 0.01))
7605 return;
7606
7607 /* Increase longitude counter... */
7608 if ((++met->nx) >= EX)
7609 ERRMSG("Cannot create periodic boundary conditions!");
7610
7611 /* Set longitude... */
7612 met->lon[met->nx - 1] = met->lon[met->nx - 2] + met->lon[1] - met->lon[0];
7613
7614 /* Loop over latitudes and pressure levels... */
7615#pragma omp parallel for default(shared)
7616 for (int iy = 0; iy < met->ny; iy++) {
7617 met->ps[met->nx - 1][iy] = met->ps[0][iy];
7618 met->zs[met->nx - 1][iy] = met->zs[0][iy];
7619 met->ts[met->nx - 1][iy] = met->ts[0][iy];
7620 met->us[met->nx - 1][iy] = met->us[0][iy];
7621 met->vs[met->nx - 1][iy] = met->vs[0][iy];
7622 met->ess[met->nx - 1][iy] = met->ess[0][iy];
7623 met->nss[met->nx - 1][iy] = met->nss[0][iy];
7624 met->shf[met->nx - 1][iy] = met->shf[0][iy];
7625 met->lsm[met->nx - 1][iy] = met->lsm[0][iy];
7626 met->sst[met->nx - 1][iy] = met->sst[0][iy];
7627 met->pbl[met->nx - 1][iy] = met->pbl[0][iy];
7628 met->cape[met->nx - 1][iy] = met->cape[0][iy];
7629 met->cin[met->nx - 1][iy] = met->cin[0][iy];
7630 for (int ip = 0; ip < met->np; ip++) {
7631 met->t[met->nx - 1][iy][ip] = met->t[0][iy][ip];
7632 met->u[met->nx - 1][iy][ip] = met->u[0][iy][ip];
7633 met->v[met->nx - 1][iy][ip] = met->v[0][iy][ip];
7634 met->w[met->nx - 1][iy][ip] = met->w[0][iy][ip];
7635 met->h2o[met->nx - 1][iy][ip] = met->h2o[0][iy][ip];
7636 met->o3[met->nx - 1][iy][ip] = met->o3[0][iy][ip];
7637 met->lwc[met->nx - 1][iy][ip] = met->lwc[0][iy][ip];
7638 met->rwc[met->nx - 1][iy][ip] = met->rwc[0][iy][ip];
7639 met->iwc[met->nx - 1][iy][ip] = met->iwc[0][iy][ip];
7640 met->swc[met->nx - 1][iy][ip] = met->swc[0][iy][ip];
7641 met->cc[met->nx - 1][iy][ip] = met->cc[0][iy][ip];
7642 }
7643 for (int ip = 0; ip < met->npl; ip++) {
7644 met->ul[met->nx - 1][iy][ip] = met->ul[0][iy][ip];
7645 met->vl[met->nx - 1][iy][ip] = met->vl[0][iy][ip];
7646 met->wl[met->nx - 1][iy][ip] = met->wl[0][iy][ip];
7647 met->pl[met->nx - 1][iy][ip] = met->pl[0][iy][ip];
7648 met->zetal[met->nx - 1][iy][ip] = met->zetal[0][iy][ip];
7649 met->zeta_dotl[met->nx - 1][iy][ip] = met->zeta_dotl[0][iy][ip];
7650 }
7651 }
7652}

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

7657 {
7658
7659 /* Set timer... */
7660 SELECT_TIMER("READ_MET_POLAR_WINDS", "METPROC", NVTX_READ);
7661 LOG(2, "Apply fix for polar winds...");
7662
7663 /* Check latitudes... */
7664 if (fabs(met->lat[0]) < 89.999 || fabs(met->lat[met->ny - 1]) < 89.999)
7665 return;
7666
7667 /* Loop over hemispheres... */
7668 for (int ihem = 0; ihem < 2; ihem++) {
7669
7670 /* Set latitude indices... */
7671 int i89 = 1, i90 = 0, sign = 1;
7672 if (ihem == 1) {
7673 i89 = met->ny - 2;
7674 i90 = met->ny - 1;
7675 }
7676 if (met->lat[i90] < 0)
7677 sign = -1;
7678
7679 /* Look-up table of cosinus and sinus... */
7680 double clon[EX], slon[EX];
7681#pragma omp parallel for default(shared)
7682 for (int ix = 0; ix < met->nx; ix++) {
7683 clon[ix] = cos(sign * DEG2RAD(met->lon[ix]));
7684 slon[ix] = sin(sign * DEG2RAD(met->lon[ix]));
7685 }
7686
7687 /* Loop over levels... */
7688#pragma omp parallel for default(shared)
7689 for (int ip = 0; ip < met->np; ip++) {
7690
7691 /* Transform 89 degree u and v winds into Cartesian coordinates and take the mean... */
7692 double vel89x = 0, vel89y = 0;
7693 for (int ix = 0; ix < met->nx; ix++) {
7694 vel89x +=
7695 (met->u[ix][i89][ip] * clon[ix] -
7696 met->v[ix][i89][ip] * slon[ix]) / met->nx;
7697 vel89y +=
7698 (met->u[ix][i89][ip] * slon[ix] +
7699 met->v[ix][i89][ip] * clon[ix]) / met->nx;
7700 }
7701
7702 /* Replace 90 degree winds by 89 degree mean... */
7703 for (int ix = 0; ix < met->nx; ix++) {
7704 met->u[ix][i90][ip]
7705 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
7706 met->v[ix][i90][ip]
7707 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
7708 }
7709 }
7710 }
7711}

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

7716 {
7717
7718 double pows[EP];
7719
7720 /* Set timer... */
7721 SELECT_TIMER("READ_MET_PV", "METPROC", NVTX_READ);
7722 LOG(2, "Calculate potential vorticity...");
7723
7724 /* Set powers... */
7725#pragma omp parallel for default(shared)
7726 for (int ip = 0; ip < met->np; ip++)
7727 pows[ip] = pow(1000. / met->p[ip], 0.286);
7728
7729 /* Loop over grid points... */
7730#pragma omp parallel for default(shared)
7731 for (int ix = 0; ix < met->nx; ix++) {
7732
7733 /* Set indices... */
7734 const int ix0 = MAX(ix - 1, 0);
7735 const int ix1 = MIN(ix + 1, met->nx - 1);
7736
7737 /* Loop over grid points... */
7738 for (int iy = 0; iy < met->ny; iy++) {
7739
7740 /* Set indices... */
7741 const int iy0 = MAX(iy - 1, 0);
7742 const int iy1 = MIN(iy + 1, met->ny - 1);
7743
7744 /* Set auxiliary variables... */
7745 const double latr = 0.5 * (met->lat[iy1] + met->lat[iy0]);
7746 const double dx = 1000. * DEG2DX(met->lon[ix1] - met->lon[ix0], latr);
7747 const double dy = 1000. * DEG2DY(met->lat[iy1] - met->lat[iy0]);
7748 const double c0 = cos(DEG2RAD(met->lat[iy0]));
7749 const double c1 = cos(DEG2RAD(met->lat[iy1]));
7750 const double cr = cos(DEG2RAD(latr));
7751 const double vort = 2 * 7.2921e-5 * sin(DEG2RAD(latr));
7752
7753 /* Loop over grid points... */
7754 for (int ip = 0; ip < met->np; ip++) {
7755
7756 /* Get gradients in longitude... */
7757 const double dtdx
7758 = (met->t[ix1][iy][ip] - met->t[ix0][iy][ip]) * pows[ip] / dx;
7759 const double dvdx = (met->v[ix1][iy][ip] - met->v[ix0][iy][ip]) / dx;
7760
7761 /* Get gradients in latitude... */
7762 const double dtdy
7763 = (met->t[ix][iy1][ip] - met->t[ix][iy0][ip]) * pows[ip] / dy;
7764 const double dudy
7765 = (met->u[ix][iy1][ip] * c1 - met->u[ix][iy0][ip] * c0) / dy;
7766
7767 /* Set indices... */
7768 const int ip0 = MAX(ip - 1, 0);
7769 const int ip1 = MIN(ip + 1, met->np - 1);
7770
7771 /* Get gradients in pressure... */
7772 double dtdp, dudp, dvdp;
7773 const double dp0 = 100. * (met->p[ip] - met->p[ip0]);
7774 const double dp1 = 100. * (met->p[ip1] - met->p[ip]);
7775 if (ip != ip0 && ip != ip1) {
7776 double denom = dp0 * dp1 * (dp0 + dp1);
7777 dtdp = (dp0 * dp0 * met->t[ix][iy][ip1] * pows[ip1]
7778 - dp1 * dp1 * met->t[ix][iy][ip0] * pows[ip0]
7779 + (dp1 * dp1 - dp0 * dp0) * met->t[ix][iy][ip] * pows[ip])
7780 / denom;
7781 dudp = (dp0 * dp0 * met->u[ix][iy][ip1]
7782 - dp1 * dp1 * met->u[ix][iy][ip0]
7783 + (dp1 * dp1 - dp0 * dp0) * met->u[ix][iy][ip])
7784 / denom;
7785 dvdp = (dp0 * dp0 * met->v[ix][iy][ip1]
7786 - dp1 * dp1 * met->v[ix][iy][ip0]
7787 + (dp1 * dp1 - dp0 * dp0) * met->v[ix][iy][ip])
7788 / denom;
7789 } else {
7790 const double denom = dp0 + dp1;
7791 dtdp =
7792 (met->t[ix][iy][ip1] * pows[ip1] -
7793 met->t[ix][iy][ip0] * pows[ip0]) / denom;
7794 dudp = (met->u[ix][iy][ip1] - met->u[ix][iy][ip0]) / denom;
7795 dvdp = (met->v[ix][iy][ip1] - met->v[ix][iy][ip0]) / denom;
7796 }
7797
7798 /* Calculate PV... */
7799 met->pv[ix][iy][ip] = (float)
7800 (1e6 * G0 *
7801 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
7802 }
7803 }
7804 }
7805
7806 /* Fix for polar regions... */
7807#pragma omp parallel for default(shared)
7808 for (int ix = 0; ix < met->nx; ix++)
7809 for (int ip = 0; ip < met->np; ip++) {
7810 met->pv[ix][0][ip]
7811 = met->pv[ix][1][ip]
7812 = met->pv[ix][2][ip];
7813 met->pv[ix][met->ny - 1][ip]
7814 = met->pv[ix][met->ny - 2][ip]
7815 = met->pv[ix][met->ny - 3][ip];
7816 }
7817}
#define DEG2DY(dlat)
Convert a latitude difference to a distance in the y-direction (north-south).
Definition: mptrac.h:461
#define DEG2DX(dlon, lat)
Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude.
Definition: mptrac.h:440

◆ read_met_ozone()

void read_met_ozone ( met_t met)

Calculates the total column ozone from meteorological ozone data.

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

Parameters
metA pointer to a structure containing meteorological ozone data.

The function performs the following steps:

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

Definition at line 7821 of file mptrac.c.

7822 {
7823
7824 /* Set timer... */
7825 SELECT_TIMER("READ_MET_OZONE", "METPROC", NVTX_READ);
7826 LOG(2, "Calculate total column ozone...");
7827
7828 /* Loop over columns... */
7829#pragma omp parallel for default(shared) collapse(2)
7830 for (int ix = 0; ix < met->nx; ix++)
7831 for (int iy = 0; iy < met->ny; iy++) {
7832
7833 /* Integrate... */
7834 double cd = 0;
7835 for (int ip = 1; ip < met->np; ip++)
7836 if (met->p[ip - 1] <= met->ps[ix][iy]) {
7837 const double vmr =
7838 0.5 * (met->o3[ix][iy][ip - 1] + met->o3[ix][iy][ip]);
7839 const double dp = met->p[ip - 1] - met->p[ip];
7840 cd += vmr * MO3 / MA * dp * 1e2 / G0;
7841 }
7842
7843 /* Convert to Dobson units... */
7844 met->o3c[ix][iy] = (float) (cd / 2.1415e-5);
7845 }
7846}

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

7852 {
7853
7854 met_t *help;
7855
7856 /* Check parameters... */
7857 if (ctl->met_dp <= 1 && ctl->met_dx <= 1 && ctl->met_dy <= 1
7858 && ctl->met_sp <= 1 && ctl->met_sx <= 1 && ctl->met_sy <= 1)
7859 return;
7860
7861 /* Set timer... */
7862 SELECT_TIMER("READ_MET_SAMPLE", "METPROC", NVTX_READ);
7863 LOG(2, "Downsampling of meteo data...");
7864
7865 /* Allocate... */
7866 ALLOC(help, met_t, 1);
7867
7868 /* Copy data... */
7869 help->nx = met->nx;
7870 help->ny = met->ny;
7871 help->np = met->np;
7872 memcpy(help->lon, met->lon, sizeof(met->lon));
7873 memcpy(help->lat, met->lat, sizeof(met->lat));
7874 memcpy(help->p, met->p, sizeof(met->p));
7875
7876 /* Smoothing... */
7877 for (int ix = 0; ix < met->nx; ix += ctl->met_dx) {
7878 for (int iy = 0; iy < met->ny; iy += ctl->met_dy) {
7879 for (int ip = 0; ip < met->np; ip += ctl->met_dp) {
7880 help->ps[ix][iy] = 0;
7881 help->zs[ix][iy] = 0;
7882 help->ts[ix][iy] = 0;
7883 help->us[ix][iy] = 0;
7884 help->vs[ix][iy] = 0;
7885 help->ess[ix][iy] = 0;
7886 help->nss[ix][iy] = 0;
7887 help->shf[ix][iy] = 0;
7888 help->lsm[ix][iy] = 0;
7889 help->sst[ix][iy] = 0;
7890 help->pbl[ix][iy] = 0;
7891 help->cape[ix][iy] = 0;
7892 help->cin[ix][iy] = 0;
7893 help->t[ix][iy][ip] = 0;
7894 help->u[ix][iy][ip] = 0;
7895 help->v[ix][iy][ip] = 0;
7896 help->w[ix][iy][ip] = 0;
7897 help->h2o[ix][iy][ip] = 0;
7898 help->o3[ix][iy][ip] = 0;
7899 help->lwc[ix][iy][ip] = 0;
7900 help->rwc[ix][iy][ip] = 0;
7901 help->iwc[ix][iy][ip] = 0;
7902 help->swc[ix][iy][ip] = 0;
7903 help->cc[ix][iy][ip] = 0;
7904 float wsum = 0;
7905 for (int ix2 = ix - ctl->met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
7906 ix2++) {
7907 int ix3 = ix2;
7908 if (ix3 < 0)
7909 ix3 += met->nx;
7910 else if (ix3 >= met->nx)
7911 ix3 -= met->nx;
7912
7913 for (int iy2 = MAX(iy - ctl->met_sy + 1, 0);
7914 iy2 <= MIN(iy + ctl->met_sy - 1, met->ny - 1); iy2++)
7915 for (int ip2 = MAX(ip - ctl->met_sp + 1, 0);
7916 ip2 <= MIN(ip + ctl->met_sp - 1, met->np - 1); ip2++) {
7917 float w = (1.0f - (float) abs(ix - ix2) / (float) ctl->met_sx)
7918 * (1.0f - (float) abs(iy - iy2) / (float) ctl->met_sy)
7919 * (1.0f - (float) abs(ip - ip2) / (float) ctl->met_sp);
7920 help->ps[ix][iy] += w * met->ps[ix3][iy2];
7921 help->zs[ix][iy] += w * met->zs[ix3][iy2];
7922 help->ts[ix][iy] += w * met->ts[ix3][iy2];
7923 help->us[ix][iy] += w * met->us[ix3][iy2];
7924 help->vs[ix][iy] += w * met->vs[ix3][iy2];
7925 help->ess[ix][iy] += w * met->ess[ix3][iy2];
7926 help->nss[ix][iy] += w * met->nss[ix3][iy2];
7927 help->shf[ix][iy] += w * met->shf[ix3][iy2];
7928 help->lsm[ix][iy] += w * met->lsm[ix3][iy2];
7929 help->sst[ix][iy] += w * met->sst[ix3][iy2];
7930 help->pbl[ix][iy] += w * met->pbl[ix3][iy2];
7931 help->cape[ix][iy] += w * met->cape[ix3][iy2];
7932 help->cin[ix][iy] += w * met->cin[ix3][iy2];
7933 help->t[ix][iy][ip] += w * met->t[ix3][iy2][ip2];
7934 help->u[ix][iy][ip] += w * met->u[ix3][iy2][ip2];
7935 help->v[ix][iy][ip] += w * met->v[ix3][iy2][ip2];
7936 help->w[ix][iy][ip] += w * met->w[ix3][iy2][ip2];
7937 help->h2o[ix][iy][ip] += w * met->h2o[ix3][iy2][ip2];
7938 help->o3[ix][iy][ip] += w * met->o3[ix3][iy2][ip2];
7939 help->lwc[ix][iy][ip] += w * met->lwc[ix3][iy2][ip2];
7940 help->rwc[ix][iy][ip] += w * met->rwc[ix3][iy2][ip2];
7941 help->iwc[ix][iy][ip] += w * met->iwc[ix3][iy2][ip2];
7942 help->swc[ix][iy][ip] += w * met->swc[ix3][iy2][ip2];
7943 help->cc[ix][iy][ip] += w * met->cc[ix3][iy2][ip2];
7944 wsum += w;
7945 }
7946 }
7947 help->ps[ix][iy] /= wsum;
7948 help->zs[ix][iy] /= wsum;
7949 help->ts[ix][iy] /= wsum;
7950 help->us[ix][iy] /= wsum;
7951 help->vs[ix][iy] /= wsum;
7952 help->ess[ix][iy] /= wsum;
7953 help->nss[ix][iy] /= wsum;
7954 help->shf[ix][iy] /= wsum;
7955 help->lsm[ix][iy] /= wsum;
7956 help->sst[ix][iy] /= wsum;
7957 help->pbl[ix][iy] /= wsum;
7958 help->cape[ix][iy] /= wsum;
7959 help->cin[ix][iy] /= wsum;
7960 help->t[ix][iy][ip] /= wsum;
7961 help->u[ix][iy][ip] /= wsum;
7962 help->v[ix][iy][ip] /= wsum;
7963 help->w[ix][iy][ip] /= wsum;
7964 help->h2o[ix][iy][ip] /= wsum;
7965 help->o3[ix][iy][ip] /= wsum;
7966 help->lwc[ix][iy][ip] /= wsum;
7967 help->rwc[ix][iy][ip] /= wsum;
7968 help->iwc[ix][iy][ip] /= wsum;
7969 help->swc[ix][iy][ip] /= wsum;
7970 help->cc[ix][iy][ip] /= wsum;
7971 }
7972 }
7973 }
7974
7975 /* Downsampling... */
7976 met->nx = 0;
7977 for (int ix = 0; ix < help->nx; ix += ctl->met_dx) {
7978 met->lon[met->nx] = help->lon[ix];
7979 met->ny = 0;
7980 for (int iy = 0; iy < help->ny; iy += ctl->met_dy) {
7981 met->lat[met->ny] = help->lat[iy];
7982 met->ps[met->nx][met->ny] = help->ps[ix][iy];
7983 met->zs[met->nx][met->ny] = help->zs[ix][iy];
7984 met->ts[met->nx][met->ny] = help->ts[ix][iy];
7985 met->us[met->nx][met->ny] = help->us[ix][iy];
7986 met->vs[met->nx][met->ny] = help->vs[ix][iy];
7987 met->ess[met->nx][met->ny] = help->ess[ix][iy];
7988 met->nss[met->nx][met->ny] = help->nss[ix][iy];
7989 met->shf[met->nx][met->ny] = help->shf[ix][iy];
7990 met->lsm[met->nx][met->ny] = help->lsm[ix][iy];
7991 met->sst[met->nx][met->ny] = help->sst[ix][iy];
7992 met->pbl[met->nx][met->ny] = help->pbl[ix][iy];
7993 met->cape[met->nx][met->ny] = help->cape[ix][iy];
7994 met->cin[met->nx][met->ny] = help->cin[ix][iy];
7995 met->np = 0;
7996 for (int ip = 0; ip < help->np; ip += ctl->met_dp) {
7997 met->p[met->np] = help->p[ip];
7998 met->t[met->nx][met->ny][met->np] = help->t[ix][iy][ip];
7999 met->u[met->nx][met->ny][met->np] = help->u[ix][iy][ip];
8000 met->v[met->nx][met->ny][met->np] = help->v[ix][iy][ip];
8001 met->w[met->nx][met->ny][met->np] = help->w[ix][iy][ip];
8002 met->h2o[met->nx][met->ny][met->np] = help->h2o[ix][iy][ip];
8003 met->o3[met->nx][met->ny][met->np] = help->o3[ix][iy][ip];
8004 met->lwc[met->nx][met->ny][met->np] = help->lwc[ix][iy][ip];
8005 met->rwc[met->nx][met->ny][met->np] = help->rwc[ix][iy][ip];
8006 met->iwc[met->nx][met->ny][met->np] = help->iwc[ix][iy][ip];
8007 met->swc[met->nx][met->ny][met->np] = help->swc[ix][iy][ip];
8008 met->cc[met->nx][met->ny][met->np] = help->cc[ix][iy][ip];
8009 met->np++;
8010 }
8011 met->ny++;
8012 }
8013 met->nx++;
8014 }
8015
8016 /* Free... */
8017 free(help);
8018}
int met_dp
Stride for pressure levels.
Definition: mptrac.h:2570
int met_sy
Smoothing for latitudes.
Definition: mptrac.h:2576
int met_sx
Smoothing for longitudes.
Definition: mptrac.h:2573
int met_dx
Stride for longitudes.
Definition: mptrac.h:2564
int met_sp
Smoothing for pressure levels.
Definition: mptrac.h:2579
int met_dy
Stride for latitudes.
Definition: mptrac.h:2567

◆ read_met_surface()

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

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

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

Parameters
ncidNetCDF file identifier.
metA pointer to the meteorological data structure to store the read data.
ctlA pointer to a structure containing control parameters.

The function performs the following steps:

  • Sets a timer for performance monitoring.
  • Reads surface meteorological data based on the configuration:
    • For MPTRAC meteorological data:
      • Reads surface pressure from "lnsp", "ps", or "sp" variables.
      • Converts surface pressure to Pa if necessary.
      • Reads geopotential height at the surface from "z" or "zm" variables.
      • Reads surface temperature from "t2m" or "2t" variables.
      • Reads zonal wind at the surface from "u10m" or "10u" variables.
      • Reads meridional wind at the surface from "v10m" or "10v" variables.
      • Reads land-sea mask from "lsm" variable.
      • Reads sea surface temperature from "sstk" or "sst" variables.
    • For CLaMS meteorological data:
      • Reads surface pressure from "ps" variable.
      • Reads geopotential height at the surface using the lowest level of the 3-D data field.
      • Reads surface temperature from "t2" variable.
      • Reads zonal wind at the surface from "u10" variable.
      • Reads meridional wind at the surface from "v10" variable.
      • Reads land-sea mask from "lsm" variable.
      • Reads sea surface temperature from "sstk" variable.
Note
The function handles different variable names and units according to the specified meteorological data source (MPTRAC or CLaMS).
Authors
Lars Hoffmann
Jan Clemens

Definition at line 8022 of file mptrac.c.

8025 {
8026
8027 /* Set timer... */
8028 SELECT_TIMER("READ_MET_SURFACE", "INPUT", NVTX_READ);
8029 LOG(2, "Read surface data...");
8030
8031 /* Read surface pressure... */
8032 if (read_met_nc_2d
8033 (ncid, "lnsp", "LNSP", NULL, NULL, NULL, NULL, ctl, met, met->ps, 1.0f,
8034 1)) {
8035 for (int ix = 0; ix < met->nx; ix++)
8036 for (int iy = 0; iy < met->ny; iy++)
8037 met->ps[ix][iy] = (float) (exp(met->ps[ix][iy]) / 100.);
8038 } else
8039 if (!read_met_nc_2d
8040 (ncid, "ps", "PS", "sp", "SP", NULL, NULL, ctl, met, met->ps, 0.01f,
8041 1)) {
8042 WARN("Cannot not read surface pressure data (use lowest level)!");
8043 for (int ix = 0; ix < met->nx; ix++)
8044 for (int iy = 0; iy < met->ny; iy++)
8045 met->ps[ix][iy] = (float) met->p[0];
8046 }
8047
8048 /* MPTRAC meteo data... */
8049 if (ctl->met_clams == 0) {
8050
8051 /* Read geopotential height at the surface... */
8052 if (!read_met_nc_2d
8053 (ncid, "z", "Z", NULL, NULL, NULL, NULL, ctl, met, met->zs,
8054 (float) (1. / (1000. * G0)), 1))
8055 if (!read_met_nc_2d
8056 (ncid, "zm", "ZM", NULL, NULL, NULL, NULL, ctl, met, met->zs,
8057 (float) (1. / 1000.), 1))
8058 WARN("Cannot read surface geopotential height!");
8059 }
8060
8061 /* CLaMS meteo data... */
8062 else {
8063
8064 /* Read geopotential height at the surface
8065 (use lowermost level of 3-D data field)... */
8066 float *help;
8067 ALLOC(help, float,
8068 EX * EY * EP);
8069 memcpy(help, met->pl, sizeof(met->pl));
8070 if (!read_met_nc_3d
8071 (ncid, "gph", "GPH", NULL, NULL, ctl, met, met->pl,
8072 (float) (1e-3 / G0)))
8073 ERRMSG("Cannot read geopotential height!");
8074 for (int ix = 0; ix < met->nx; ix++)
8075 for (int iy = 0; iy < met->ny; iy++)
8076 met->zs[ix][iy] = met->pl[ix][iy][0];
8077 memcpy(met->pl, help, sizeof(met->pl));
8078 free(help);
8079 }
8080
8081 /* Read temperature at the surface... */
8082 if (!read_met_nc_2d
8083 (ncid, "t2m", "T2M", "2t", "2T", "t2", "T2", ctl, met, met->ts, 1.0, 1))
8084 WARN("Cannot read surface temperature!");
8085
8086 /* Read zonal wind at the surface... */
8087 if (!read_met_nc_2d
8088 (ncid, "u10m", "U10M", "10u", "10U", "u10", "U10", ctl, met, met->us,
8089 1.0, 1))
8090 WARN("Cannot read surface zonal wind!");
8091
8092 /* Read meridional wind at the surface... */
8093 if (!read_met_nc_2d
8094 (ncid, "v10m", "V10M", "10v", "10V", "v10", "V10", ctl, met, met->vs,
8095 1.0, 1))
8096 WARN("Cannot read surface meridional wind!");
8097
8098 /* Read eastward turbulent surface stress... */
8099 if (!read_met_nc_2d
8100 (ncid, "iews", "IEWS", NULL, NULL, NULL, NULL, ctl, met, met->ess, 1.0,
8101 1))
8102 WARN("Cannot read eastward turbulent surface stress!");
8103
8104 /* Read northward turbulent surface stress... */
8105 if (!read_met_nc_2d
8106 (ncid, "inss", "INSS", NULL, NULL, NULL, NULL, ctl, met, met->nss, 1.0,
8107 1))
8108 WARN("Cannot read nothward turbulent surface stress!");
8109
8110 /* Read surface sensible heat flux... */
8111 if (!read_met_nc_2d
8112 (ncid, "ishf", "ISHF", NULL, NULL, NULL, NULL, ctl, met, met->shf, 1.0,
8113 1))
8114 WARN("Cannot read surface sensible heat flux!");
8115
8116 /* Read land-sea mask... */
8117 if (!read_met_nc_2d
8118 (ncid, "lsm", "LSM", NULL, NULL, NULL, NULL, ctl, met, met->lsm, 1.0,
8119 1))
8120 WARN("Cannot read land-sea mask!");
8121
8122 /* Read sea surface temperature... */
8123 if (!read_met_nc_2d
8124 (ncid, "sstk", "SSTK", "sst", "SST", NULL, NULL, ctl, met, met->sst,
8125 1.0, 1))
8126 WARN("Cannot read sea surface temperature!");
8127
8128 /* Read PBL... */
8129 if (ctl->met_pbl == 0)
8130 if (!read_met_nc_2d
8131 (ncid, "blp", "BLP", NULL, NULL, NULL, NULL, ctl, met, met->pbl,
8132 0.01f, 1))
8133 WARN("Cannot read planetary boundary layer pressure!");
8134 if (ctl->met_pbl == 1)
8135 if (!read_met_nc_2d
8136 (ncid, "blh", "BLH", NULL, NULL, NULL, NULL, ctl, met, met->pbl,
8137 0.001f, 1))
8138 WARN("Cannot read planetary boundary layer height!");
8139
8140 /* Read CAPE... */
8141 if (ctl->met_cape == 0)
8142 if (!read_met_nc_2d
8143 (ncid, "cape", "CAPE", NULL, NULL, NULL, NULL, ctl, met, met->cape,
8144 1.0, 1))
8145 WARN("Cannot read CAPE!");
8146
8147 /* Read CIN... */
8148 if (ctl->met_cape == 0)
8149 if (!read_met_nc_2d
8150 (ncid, "cin", "CIN", NULL, NULL, NULL, NULL, ctl, met, met->cin,
8151 1.0, 1))
8152 WARN("Cannot read convective inhibition!");
8153}
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:7154
Here is the call graph for this function:

◆ read_met_tropo()

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

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

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

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

The function performs the following steps:

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

Definition at line 8157 of file mptrac.c.

8160 {
8161
8162 double p2[200], pv[EP], pv2[200], t[EP], t2[200], th[EP],
8163 th2[200], z[EP], z2[200];
8164
8165 /* Set timer... */
8166 SELECT_TIMER("READ_MET_TROPO", "METPROC", NVTX_READ);
8167 LOG(2, "Calculate tropopause...");
8168
8169 /* Get altitude and pressure profiles... */
8170#pragma omp parallel for default(shared)
8171 for (int iz = 0; iz < met->np; iz++)
8172 z[iz] = Z(met->p[iz]);
8173#pragma omp parallel for default(shared)
8174 for (int iz = 0; iz <= 190; iz++) {
8175 z2[iz] = 4.5 + 0.1 * iz;
8176 p2[iz] = P(z2[iz]);
8177 }
8178
8179 /* Do not calculate tropopause... */
8180 if (ctl->met_tropo == 0)
8181#pragma omp parallel for default(shared) collapse(2)
8182 for (int ix = 0; ix < met->nx; ix++)
8183 for (int iy = 0; iy < met->ny; iy++)
8184 met->pt[ix][iy] = NAN;
8185
8186 /* Use tropopause climatology... */
8187 else if (ctl->met_tropo == 1) {
8188#pragma omp parallel for default(shared) collapse(2)
8189 for (int ix = 0; ix < met->nx; ix++)
8190 for (int iy = 0; iy < met->ny; iy++)
8191 met->pt[ix][iy] = (float) clim_tropo(clim, met->time, met->lat[iy]);
8192 }
8193
8194 /* Use cold point... */
8195 else if (ctl->met_tropo == 2) {
8196
8197 /* Loop over grid points... */
8198#pragma omp parallel for default(shared) private(t,t2) collapse(2)
8199 for (int ix = 0; ix < met->nx; ix++)
8200 for (int iy = 0; iy < met->ny; iy++) {
8201
8202 /* Interpolate temperature profile... */
8203 for (int iz = 0; iz < met->np; iz++)
8204 t[iz] = met->t[ix][iy][iz];
8205 spline(z, t, met->np, z2, t2, 171, ctl->met_tropo_spline);
8206
8207 /* Find minimum... */
8208 int iz = (int) gsl_stats_min_index(t2, 1, 171);
8209 if (iz > 0 && iz < 170)
8210 met->pt[ix][iy] = (float) p2[iz];
8211 else
8212 met->pt[ix][iy] = NAN;
8213 }
8214 }
8215
8216 /* Use WMO definition... */
8217 else if (ctl->met_tropo == 3 || ctl->met_tropo == 4) {
8218
8219 /* Loop over grid points... */
8220#pragma omp parallel for default(shared) private(t,t2) collapse(2)
8221 for (int ix = 0; ix < met->nx; ix++)
8222 for (int iy = 0; iy < met->ny; iy++) {
8223
8224 /* Interpolate temperature profile... */
8225 int iz;
8226 for (iz = 0; iz < met->np; iz++)
8227 t[iz] = met->t[ix][iy][iz];
8228 spline(z, t, met->np, z2, t2, 191, ctl->met_tropo_spline);
8229
8230 /* Find 1st tropopause... */
8231 met->pt[ix][iy] = NAN;
8232 for (iz = 0; iz <= 170; iz++) {
8233 int found = 1;
8234 for (int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
8235 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
8236 found = 0;
8237 break;
8238 }
8239 if (found) {
8240 if (iz > 0 && iz < 170)
8241 met->pt[ix][iy] = (float) p2[iz];
8242 break;
8243 }
8244 }
8245
8246 /* Find 2nd tropopause... */
8247 if (ctl->met_tropo == 4) {
8248 met->pt[ix][iy] = NAN;
8249 for (; iz <= 170; iz++) {
8250 int found = 1;
8251 for (int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
8252 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
8253 found = 0;
8254 break;
8255 }
8256 if (found)
8257 break;
8258 }
8259 for (; iz <= 170; iz++) {
8260 int found = 1;
8261 for (int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
8262 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
8263 found = 0;
8264 break;
8265 }
8266 if (found) {
8267 if (iz > 0 && iz < 170)
8268 met->pt[ix][iy] = (float) p2[iz];
8269 break;
8270 }
8271 }
8272 }
8273 }
8274 }
8275
8276 /* Use dynamical tropopause... */
8277 else if (ctl->met_tropo == 5) {
8278
8279 /* Loop over grid points... */
8280#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
8281 for (int ix = 0; ix < met->nx; ix++)
8282 for (int iy = 0; iy < met->ny; iy++) {
8283
8284 /* Interpolate potential vorticity profile... */
8285 for (int iz = 0; iz < met->np; iz++)
8286 pv[iz] = met->pv[ix][iy][iz];
8287 spline(z, pv, met->np, z2, pv2, 171, ctl->met_tropo_spline);
8288
8289 /* Interpolate potential temperature profile... */
8290 for (int iz = 0; iz < met->np; iz++)
8291 th[iz] = THETA(met->p[iz], met->t[ix][iy][iz]);
8292 spline(z, th, met->np, z2, th2, 171, ctl->met_tropo_spline);
8293
8294 /* Find dynamical tropopause... */
8295 met->pt[ix][iy] = NAN;
8296 for (int iz = 0; iz <= 170; iz++)
8297 if (fabs(pv2[iz]) >= ctl->met_tropo_pv
8298 || th2[iz] >= ctl->met_tropo_theta) {
8299 if (iz > 0 && iz < 170)
8300 met->pt[ix][iy] = (float) p2[iz];
8301 break;
8302 }
8303 }
8304 }
8305
8306 else
8307 ERRMSG("Cannot calculate tropopause!");
8308
8309 /* Interpolate temperature, geopotential height, and water vapor... */
8310#pragma omp parallel for default(shared) collapse(2)
8311 for (int ix = 0; ix < met->nx; ix++)
8312 for (int iy = 0; iy < met->ny; iy++) {
8313 double h2ot, tt, zt;
8315 intpol_met_space_3d(met, met->t, met->pt[ix][iy], met->lon[ix],
8316 met->lat[iy], &tt, ci, cw, 1);
8317 intpol_met_space_3d(met, met->z, met->pt[ix][iy], met->lon[ix],
8318 met->lat[iy], &zt, ci, cw, 0);
8319 intpol_met_space_3d(met, met->h2o, met->pt[ix][iy], met->lon[ix],
8320 met->lat[iy], &h2ot, ci, cw, 0);
8321 met->tt[ix][iy] = (float) tt;
8322 met->zt[ix][iy] = (float) zt;
8323 met->h2ot[ix][iy] = (float) h2ot;
8324 }
8325}
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:8535
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
Definition: mptrac.h:840
Here is the call graph for this function:

◆ read_obs()

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

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

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

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

The function performs the following steps:

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

Definition at line 8329 of file mptrac.c.

8337 {
8338
8339 /* Write info... */
8340 LOG(1, "Read observation data: %s", filename);
8341
8342 /* Read data... */
8343 if (ctl->obs_type == 0)
8344 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
8345 else if (ctl->obs_type == 1)
8346 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
8347 else
8348 ERRMSG("Set OBS_TYPE to 0 or 1!");
8349
8350 /* Check time... */
8351 for (int i = 1; i < *nobs; i++)
8352 if (rt[i] < rt[i - 1])
8353 ERRMSG("Time must be ascending!");
8354
8355 /* Write info... */
8356 int n = *nobs;
8357 double mini, maxi;
8358 LOG(2, "Number of observations: %d", *nobs);
8359 gsl_stats_minmax(&mini, &maxi, rt, 1, (size_t) n);
8360 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
8361 gsl_stats_minmax(&mini, &maxi, rz, 1, (size_t) n);
8362 LOG(2, "Altitude range: %g ... %g km", mini, maxi);
8363 gsl_stats_minmax(&mini, &maxi, rlon, 1, (size_t) n);
8364 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
8365 gsl_stats_minmax(&mini, &maxi, rlat, 1, (size_t) n);
8366 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
8367 gsl_stats_minmax(&mini, &maxi, robs, 1, (size_t) n);
8368 LOG(2, "Observation range: %g ... %g", mini, maxi);
8369}
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:8373
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:8401
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 8373 of file mptrac.c.

8380 {
8381
8382 /* Open observation data file... */
8383 FILE *in;
8384 if (!(in = fopen(filename, "r")))
8385 ERRMSG("Cannot open file!");
8386
8387 /* Read observations... */
8388 char line[LEN];
8389 while (fgets(line, LEN, in))
8390 if (sscanf(line, "%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
8391 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
8392 if ((++(*nobs)) >= NOBS)
8393 ERRMSG("Too many observations!");
8394
8395 /* Close observation data file... */
8396 fclose(in);
8397}
#define NOBS
Maximum number of observation data points.
Definition: mptrac.h:281

◆ read_obs_nc()

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

Reads observation data from a NetCDF file.

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

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

The function performs the following steps:

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

Definition at line 8401 of file mptrac.c.

8408 {
8409
8410 int ncid, varid;
8411
8412 /* Open netCDF file... */
8413 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
8414 ERRMSG("Cannot open file!");
8415
8416 /* Read the observations from the NetCDF file... */
8417 NC_INQ_DIM("nobs", nobs, 1, NOBS);
8418 NC_GET_DOUBLE("time", rt, 1);
8419 NC_GET_DOUBLE("alt", rz, 1);
8420 NC_GET_DOUBLE("lon", rlon, 1);
8421 NC_GET_DOUBLE("lat", rlat, 1);
8422 NC_GET_DOUBLE("obs", robs, 1);
8423
8424 /* Close file... */
8425 NC(nc_close(ncid));
8426}

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

8437 {
8438
8439 FILE *in = NULL;
8440
8441 char fullname1[LEN], fullname2[LEN], rval[LEN];
8442
8443 int contain = 0, i;
8444
8445 /* Open file... */
8446 if (filename[strlen(filename) - 1] != '-')
8447 if (!(in = fopen(filename, "r")))
8448 ERRMSG("Cannot open file!");
8449
8450 /* Set full variable name... */
8451 if (arridx >= 0) {
8452 sprintf(fullname1, "%s[%d]", varname, arridx);
8453 sprintf(fullname2, "%s[*]", varname);
8454 } else {
8455 sprintf(fullname1, "%s", varname);
8456 sprintf(fullname2, "%s", varname);
8457 }
8458
8459 /* Read data... */
8460 if (in != NULL) {
8461 char dummy[LEN], line[LEN], rvarname[LEN];
8462 while (fgets(line, LEN, in)) {
8463 if (sscanf(line, "%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
8464 if (strcasecmp(rvarname, fullname1) == 0 ||
8465 strcasecmp(rvarname, fullname2) == 0) {
8466 contain = 1;
8467 break;
8468 }
8469 }
8470 }
8471 for (i = 1; i < argc - 1; i++)
8472 if (strcasecmp(argv[i], fullname1) == 0 ||
8473 strcasecmp(argv[i], fullname2) == 0) {
8474 sprintf(rval, "%s", argv[i + 1]);
8475 contain = 1;
8476 break;
8477 }
8478
8479 /* Close file... */
8480 if (in != NULL)
8481 fclose(in);
8482
8483 /* Check for missing variables... */
8484 if (!contain) {
8485 if (strlen(defvalue) > 0)
8486 sprintf(rval, "%s", defvalue);
8487 else
8488 ERRMSG("Missing variable %s!\n", fullname1);
8489 }
8490
8491 /* Write info... */
8492 LOG(1, "%s = %s", fullname1, rval);
8493
8494 /* Return values... */
8495 if (value != NULL)
8496 sprintf(value, "%s", rval);
8497 return atof(rval);
8498}

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

8506 {
8507
8508 /* Convert particle radius from microns to m... */
8509 const double rp_help = rp * 1e-6;
8510
8511 /* Density of dry air [kg / m^3]... */
8512 const double rho = RHO(p, T);
8513
8514 /* Dynamic viscosity of air [kg / (m s)]... */
8515 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
8516
8517 /* Thermal velocity of an air molecule [m / s]... */
8518 const double v = sqrt(8. * KB * T / (M_PI * 4.8096e-26));
8519
8520 /* Mean free path of an air molecule [m]... */
8521 const double lambda = 2. * eta / (rho * v);
8522
8523 /* Knudsen number for air (dimensionless)... */
8524 const double K = lambda / rp_help;
8525
8526 /* Cunningham slip-flow correction (dimensionless)... */
8527 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
8528
8529 /* Sedimentation velocity [m / s]... */
8530 return 2. * SQR(rp_help) * (rhop - rho) * G0 / (9. * eta) * G;
8531}
#define KB
Boltzmann constant [kg m^2/(K s^2)].
Definition: mptrac.h:192

◆ spline()

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

Performs spline interpolation or linear interpolation.

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

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

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

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

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

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

Definition at line 8535 of file mptrac.c.

8542 {
8543
8544 /* Cubic spline interpolation... */
8545 if (method == 1) {
8546
8547 /* Allocate... */
8548 gsl_interp_accel *acc = gsl_interp_accel_alloc();
8549 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (size_t) n);
8550
8551 /* Interpolate profile... */
8552 gsl_spline_init(s, x, y, (size_t) n);
8553 for (int i = 0; i < n2; i++)
8554 if (x2[i] <= x[0])
8555 y2[i] = y[0];
8556 else if (x2[i] >= x[n - 1])
8557 y2[i] = y[n - 1];
8558 else
8559 y2[i] = gsl_spline_eval(s, x2[i], acc);
8560
8561 /* Free... */
8562 gsl_spline_free(s);
8563 gsl_interp_accel_free(acc);
8564 }
8565
8566 /* Linear interpolation... */
8567 else {
8568 for (int i = 0; i < n2; i++)
8569 if (x2[i] <= x[0])
8570 y2[i] = y[0];
8571 else if (x2[i] >= x[n - 1])
8572 y2[i] = y[n - 1];
8573 else {
8574 int idx = locate_irr(x, n, x2[i]);
8575 y2[i] = LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
8576 }
8577 }
8578}
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 8582 of file mptrac.c.

8584 {
8585
8586 if (n <= 0)
8587 return 0;
8588
8589 float mean = 0, var = 0;
8590
8591 for (int i = 0; i < n; ++i) {
8592 mean += data[i];
8593 var += SQR(data[i]);
8594 }
8595
8596 var = var / (float) n - SQR(mean / (float) n);
8597
8598 return (var > 0 ? sqrtf(var) : 0);
8599}

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

8606 {
8607
8608 /* Number of days and fraction with respect to 2000-01-01T12:00Z... */
8609 const double D = sec / 86400 - 0.5;
8610
8611 /* Geocentric apparent ecliptic longitude [rad]... */
8612 const double g = DEG2RAD(357.529 + 0.98560028 * D);
8613 const double q = 280.459 + 0.98564736 * D;
8614 const double L = DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
8615
8616 /* Mean obliquity of the ecliptic [rad]... */
8617 const double e = DEG2RAD(23.439 - 0.00000036 * D);
8618
8619 /* Declination [rad]... */
8620 const double sindec = sin(e) * sin(L);
8621
8622 /* Right ascension [rad]... */
8623 const double ra = atan2(cos(e) * sin(L), cos(L));
8624
8625 /* Greenwich Mean Sidereal Time [h]... */
8626 const double GMST = 18.697374558 + 24.06570982441908 * D;
8627
8628 /* Local Sidereal Time [h]... */
8629 const double LST = GMST + lon / 15;
8630
8631 /* Hour angle [rad]... */
8632 const double h = LST / 12 * M_PI - ra;
8633
8634 /* Convert latitude... */
8635 const double lat_help = DEG2RAD(lat);
8636
8637 /* Return solar zenith angle [rad]... */
8638 return acos(sin(lat_help) * sindec +
8639 cos(lat_help) * sqrt(1 - SQR(sindec)) * cos(h));
8640}

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

8652 {
8653
8654 struct tm t0, t1;
8655
8656 t0.tm_year = 100;
8657 t0.tm_mon = 0;
8658 t0.tm_mday = 1;
8659 t0.tm_hour = 0;
8660 t0.tm_min = 0;
8661 t0.tm_sec = 0;
8662
8663 t1.tm_year = year - 1900;
8664 t1.tm_mon = mon - 1;
8665 t1.tm_mday = day;
8666 t1.tm_hour = hour;
8667 t1.tm_min = min;
8668 t1.tm_sec = sec;
8669
8670 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
8671}

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

8678 {
8679
8680 static char names[NTIMER][100], groups[NTIMER][100];
8681
8682 static double rt_name[NTIMER], rt_group[NTIMER],
8683 rt_min[NTIMER], rt_max[NTIMER], dt, t0, t1;
8684
8685 static int iname = -1, igroup = -1, nname, ngroup, ct_name[NTIMER];
8686
8687 /* Get time... */
8688 t1 = omp_get_wtime();
8689 dt = t1 - t0;
8690
8691 /* Add elapsed time to current timers... */
8692 if (iname >= 0) {
8693 rt_name[iname] += dt;
8694 rt_min[iname] = (ct_name[iname] <= 0 ? dt : MIN(rt_min[iname], dt));
8695 rt_max[iname] = (ct_name[iname] <= 0 ? dt : MAX(rt_max[iname], dt));
8696 ct_name[iname]++;
8697 }
8698 if (igroup >= 0)
8699 rt_group[igroup] += t1 - t0;
8700
8701 /* Report timers... */
8702 if (output) {
8703 for (int i = 0; i < nname; i++)
8704 LOG(1, "TIMER_%s = %.3f s (min= %g s, mean= %g s,"
8705 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
8706 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
8707 for (int i = 0; i < ngroup; i++)
8708 LOG(1, "TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
8709 double total = 0.0;
8710 for (int i = 0; i < nname; i++)
8711 total += rt_name[i];
8712 LOG(1, "TIMER_TOTAL = %.3f s", total);
8713 }
8714
8715 /* Identify IDs of next timer... */
8716 for (iname = 0; iname < nname; iname++)
8717 if (strcasecmp(name, names[iname]) == 0)
8718 break;
8719 for (igroup = 0; igroup < ngroup; igroup++)
8720 if (strcasecmp(group, groups[igroup]) == 0)
8721 break;
8722
8723 /* Check whether this is a new timer... */
8724 if (iname >= nname) {
8725 sprintf(names[iname], "%s", name);
8726 if ((++nname) >= NTIMER)
8727 ERRMSG("Too many timers!");
8728 }
8729
8730 /* Check whether this is a new group... */
8731 if (igroup >= ngroup) {
8732 sprintf(groups[igroup], "%s", group);
8733 if ((++ngroup) >= NTIMER)
8734 ERRMSG("Too many groups!");
8735 }
8736
8737 /* Save starting time... */
8738 t0 = t1;
8739}
#define NTIMER
Maximum number of timers.
Definition: mptrac.h:1960

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

8745 {
8746
8747 char tstr[10];
8748
8749 double t;
8750
8751 /* Get time from filename... */
8752 int len = (int) strlen(filename);
8753 sprintf(tstr, "%.4s", &filename[len - offset]);
8754 int year = atoi(tstr);
8755 sprintf(tstr, "%.2s", &filename[len - offset + 5]);
8756 int mon = atoi(tstr);
8757 sprintf(tstr, "%.2s", &filename[len - offset + 8]);
8758 int day = atoi(tstr);
8759 sprintf(tstr, "%.2s", &filename[len - offset + 11]);
8760 int hour = atoi(tstr);
8761 sprintf(tstr, "%.2s", &filename[len - offset + 14]);
8762 int min = atoi(tstr);
8763
8764 /* Check time... */
8765 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
8766 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
8767 ERRMSG("Cannot read time from filename!");
8768
8769 /* Convert time to Julian seconds... */
8770 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
8771
8772 /* Return time... */
8773 return t;
8774}
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 8778 of file mptrac.c.

8781 {
8782
8783 /* Get tropopause pressure... */
8784 const double pt = clim_tropo(clim, atm->time[ip], atm->lat[ip]);
8785
8786 /* Get pressure range... */
8787 const double p1 = pt * 0.866877899;
8788 const double p0 = pt / 0.866877899;
8789
8790 /* Get weighting factor... */
8791 if (atm->p[ip] > p0)
8792 return 1;
8793 else if (atm->p[ip] < p1)
8794 return 0;
8795 else
8796 return LIN(p0, 1.0, p1, 0.0, atm->p[ip]);
8797}
Here is the call graph for this function:

◆ write_atm()

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

8805 {
8806
8807 /* Set timer... */
8808 SELECT_TIMER("WRITE_ATM", "OUTPUT", NVTX_WRITE);
8809
8810 /* Write info... */
8811 LOG(1, "Write atmospheric data: %s", filename);
8812
8813 /* Write ASCII data... */
8814 if (ctl->atm_type_out == 0)
8815 write_atm_asc(filename, ctl, atm, t);
8816
8817 /* Write binary data... */
8818 else if (ctl->atm_type_out == 1)
8819 write_atm_bin(filename, ctl, atm);
8820
8821 /* Write netCDF data... */
8822 else if (ctl->atm_type_out == 2)
8823 write_atm_nc(filename, ctl, atm);
8824
8825 /* Write CLaMS trajectory data... */
8826 else if (ctl->atm_type_out == 3)
8827 write_atm_clams_traj(filename, ctl, atm, t);
8828
8829 /* Write CLaMS pos data... */
8830 else if (ctl->atm_type_out == 4)
8831 write_atm_clams(filename, ctl, atm);
8832
8833 /* Error... */
8834 else
8835 ERRMSG("Atmospheric data type not supported!");
8836
8837 /* Write info... */
8838 double mini, maxi;
8839 LOG(2, "Number of particles: %d", atm->np);
8840 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
8841 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
8842 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
8843 LOG(2, "Altitude range: %g ... %g km", Z(maxi), Z(mini));
8844 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
8845 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
8846 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
8847 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
8848 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
8849 for (int iq = 0; iq < ctl->nq; iq++) {
8850 char msg[5 * LEN];
8851 sprintf(msg, "Quantity %s range: %s ... %s %s",
8852 ctl->qnt_name[iq], ctl->qnt_format[iq],
8853 ctl->qnt_format[iq], ctl->qnt_unit[iq]);
8854 gsl_stats_minmax(&mini, &maxi, atm->q[iq], 1, (size_t) atm->np);
8855 LOG(2, msg, mini, maxi);
8856 }
8857}
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:9046
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:8861
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:8993
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:8943
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:9204
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 8861 of file mptrac.c.

8865 {
8866
8867 FILE *out;
8868
8869 /* Set time interval for output... */
8870 const double t0 = t - 0.5 * ctl->dt_mod;
8871 const double t1 = t + 0.5 * ctl->dt_mod;
8872
8873 /* Check if gnuplot output is requested... */
8874 if (ctl->atm_gpfile[0] != '-') {
8875
8876 /* Create gnuplot pipe... */
8877 if (!(out = popen("gnuplot", "w")))
8878 ERRMSG("Cannot create pipe to gnuplot!");
8879
8880 /* Set plot filename... */
8881 fprintf(out, "set out \"%s.png\"\n", filename);
8882
8883 /* Set time string... */
8884 double r;
8885 int year, mon, day, hour, min, sec;
8886 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
8887 fprintf(out, "timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
8888 year, mon, day, hour, min);
8889
8890 /* Dump gnuplot file to pipe... */
8891 FILE *in;
8892 if (!(in = fopen(ctl->atm_gpfile, "r")))
8893 ERRMSG("Cannot open file!");
8894 char line[LEN];
8895 while (fgets(line, LEN, in))
8896 fprintf(out, "%s", line);
8897 fclose(in);
8898 }
8899
8900 else {
8901
8902 /* Create file... */
8903 if (!(out = fopen(filename, "w")))
8904 ERRMSG("Cannot create file!");
8905 }
8906
8907 /* Write header... */
8908 fprintf(out,
8909 "# $1 = time [s]\n"
8910 "# $2 = altitude [km]\n"
8911 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
8912 for (int iq = 0; iq < ctl->nq; iq++)
8913 fprintf(out, "# $%i = %s [%s]\n", iq + 5, ctl->qnt_name[iq],
8914 ctl->qnt_unit[iq]);
8915 fprintf(out, "\n");
8916
8917 /* Write data... */
8918 for (int ip = 0; ip < atm->np; ip += ctl->atm_stride) {
8919
8920 /* Check time... */
8921 if (ctl->atm_filter == 2 && (atm->time[ip] < t0 || atm->time[ip] > t1))
8922 continue;
8923
8924 /* Write output... */
8925 fprintf(out, "%.2f %g %g %g", atm->time[ip], Z(atm->p[ip]),
8926 atm->lon[ip], atm->lat[ip]);
8927 for (int iq = 0; iq < ctl->nq; iq++) {
8928 fprintf(out, " ");
8929 if (ctl->atm_filter == 1 && (atm->time[ip] < t0 || atm->time[ip] > t1))
8930 fprintf(out, ctl->qnt_format[iq], NAN);
8931 else
8932 fprintf(out, ctl->qnt_format[iq], atm->q[iq][ip]);
8933 }
8934 fprintf(out, "\n");
8935 }
8936
8937 /* Close file... */
8938 fclose(out);
8939}
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 8943 of file mptrac.c.

8946 {
8947
8948 FILE *out;
8949
8950 /* Create file... */
8951 if (!(out = fopen(filename, "w")))
8952 ERRMSG("Cannot create file!");
8953
8954 /* Write version of binary data... */
8955 int version = 100;
8956 FWRITE(&version, int,
8957 1,
8958 out);
8959
8960 /* Write data... */
8961 FWRITE(&atm->np, int,
8962 1,
8963 out);
8964 FWRITE(atm->time, double,
8965 (size_t) atm->np,
8966 out);
8967 FWRITE(atm->p, double,
8968 (size_t) atm->np,
8969 out);
8970 FWRITE(atm->lon, double,
8971 (size_t) atm->np,
8972 out);
8973 FWRITE(atm->lat, double,
8974 (size_t) atm->np,
8975 out);
8976 for (int iq = 0; iq < ctl->nq; iq++)
8977 FWRITE(atm->q[iq], double,
8978 (size_t) atm->np,
8979 out);
8980
8981 /* Write final flag... */
8982 int final = 999;
8983 FWRITE(&final, int,
8984 1,
8985 out);
8986
8987 /* Close file... */
8988 fclose(out);
8989}

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

8996 {
8997
8998 int tid, pid, ncid, varid;
8999 size_t start[2], count[2];
9000
9001 /* Create file... */
9002 nc_create(filename, NC_NETCDF4, &ncid);
9003
9004 /* Define dimensions... */
9005 NC(nc_def_dim(ncid, "time", 1, &tid));
9006 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
9007
9008 /* Define variables and their attributes... */
9009 int dim_ids[2] = { tid, pid };
9010 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
9011 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
9012 NC_DEF_VAR("LAT", NC_DOUBLE, 1, &pid, "Latitude", "deg",
9013 ctl->atm_nc_level, 0);
9014 NC_DEF_VAR("LON", NC_DOUBLE, 1, &pid, "Longitude", "deg",
9015 ctl->atm_nc_level, 0);
9016 NC_DEF_VAR("PRESS", NC_DOUBLE, 1, &pid, "Pressure", "hPa",
9017 ctl->atm_nc_level, 0);
9018 NC_DEF_VAR("ZETA", NC_DOUBLE, 1, &pid, "Zeta", "K", ctl->atm_nc_level, 0);
9019 for (int iq = 0; iq < ctl->nq; iq++)
9020 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
9021 ctl->qnt_name[iq], ctl->qnt_unit[iq],
9022 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
9023
9024 /* Define global attributes... */
9025 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
9026 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
9027
9028 /* End definitions... */
9029 NC(nc_enddef(ncid));
9030
9031 /* Write data... */
9032 NC_PUT_DOUBLE("time", atm->time, 0);
9033 NC_PUT_DOUBLE("LAT", atm->lat, 0);
9034 NC_PUT_DOUBLE("LON", atm->lon, 0);
9035 NC_PUT_DOUBLE("PRESS", atm->p, 0);
9036 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 0);
9037 for (int iq = 0; iq < ctl->nq; iq++)
9038 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
9039
9040 /* Close file... */
9041 NC(nc_close(ncid));
9042}
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
Definition: mptrac.h:1212
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units, level, quant)
Define a NetCDF variable with attributes.
Definition: mptrac.h:1045
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
Write double precision data to a NetCDF variable.
Definition: mptrac.h:1126

◆ write_atm_clams_traj()

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

Writes CLaMS trajectory data to a NetCDF file.

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

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

The function performs the following steps:

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

Definition at line 9046 of file mptrac.c.

9050 {
9051
9052 /* Global Counter... */
9053 static size_t out_cnt = 0;
9054
9055 double r, r_start, r_stop;
9056 int year, mon, day, hour, min, sec;
9057 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
9058 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
9059 char filename_out[2 * LEN] = "traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
9060
9061 int ncid, varid, tid, pid, cid;
9062 int dim_ids[2];
9063
9064 /* time, nparc */
9065 size_t start[2];
9066 size_t count[2];
9067
9068 /* Determine start and stop times of calculation... */
9069 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
9070 jsec2time(ctl->t_start, &year_start, &mon_start, &day_start, &hour_start,
9071 &min_start, &sec_start, &r_start);
9072 jsec2time(ctl->t_stop, &year_stop, &mon_stop, &day_stop, &hour_stop,
9073 &min_stop, &sec_stop, &r_stop);
9074
9075 sprintf(filename_out, "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc",
9076 dirname,
9077 year_start % 100, mon_start, day_start, hour_start,
9078 year_stop % 100, mon_stop, day_stop, hour_stop);
9079 LOG(1, "Write traj file: %s", filename_out);
9080
9081 /* Define hyperslap for the traj_file... */
9082 start[0] = out_cnt;
9083 start[1] = 0;
9084 count[0] = 1;
9085 count[1] = (size_t) atm->np;
9086
9087 /* Create the file at the first timestep... */
9088 if (out_cnt == 0) {
9089
9090 /* Create file... */
9091 nc_create(filename_out, NC_NETCDF4, &ncid);
9092
9093 /* Define dimensions... */
9094 NC(nc_def_dim(ncid, "time", NC_UNLIMITED, &tid));
9095 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
9096 NC(nc_def_dim(ncid, "TMDT", 7, &cid));
9097 dim_ids[0] = tid;
9098 dim_ids[1] = pid;
9099
9100 /* Define variables and their attributes... */
9101 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
9102 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
9103 NC_DEF_VAR("LAT", NC_DOUBLE, 2, dim_ids, "Latitude", "deg",
9104 ctl->atm_nc_level, 0);
9105 NC_DEF_VAR("LON", NC_DOUBLE, 2, dim_ids, "Longitude", "deg",
9106 ctl->atm_nc_level, 0);
9107 NC_DEF_VAR("PRESS", NC_DOUBLE, 2, dim_ids, "Pressure", "hPa",
9108 ctl->atm_nc_level, 0);
9109 NC_DEF_VAR("ZETA", NC_DOUBLE, 2, dim_ids, "Zeta", "K",
9110 ctl->atm_nc_level, 0);
9111 for (int iq = 0; iq < ctl->nq; iq++)
9112 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
9113 ctl->qnt_name[iq], ctl->qnt_unit[iq],
9114 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
9115
9116 /* Define global attributes... */
9117 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
9118 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
9119
9120 /* End definitions... */
9121 NC(nc_enddef(ncid));
9122 NC(nc_close(ncid));
9123 }
9124
9125 /* Increment global counter to change hyperslap... */
9126 out_cnt++;
9127
9128 /* Open file... */
9129 NC(nc_open(filename_out, NC_WRITE, &ncid));
9130
9131 /* Write data... */
9132 NC_PUT_DOUBLE("time", atm->time, 1);
9133 NC_PUT_DOUBLE("LAT", atm->lat, 1);
9134 NC_PUT_DOUBLE("LON", atm->lon, 1);
9135 NC_PUT_DOUBLE("PRESS", atm->p, 1);
9136 if (ctl->advect_vert_coord == 1) {
9137 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta], 1);
9138 } else if (ctl->qnt_zeta >= 0) {
9139 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 1);
9140 }
9141 for (int iq = 0; iq < ctl->nq; iq++)
9142 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 1);
9143
9144 /* Close file... */
9145 NC(nc_close(ncid));
9146
9147 /* At the last time step create the init_fix_YYYYMMDDHH file... */
9148 if ((year == year_stop) && (mon == mon_stop)
9149 && (day == day_stop) && (hour == hour_stop)) {
9150
9151 /* Set filename... */
9152 char filename_init[2 * LEN] = "./init_fix_YYYYMMDDHH.nc";
9153 sprintf(filename_init, "%s/init_fix_%02d%02d%02d%02d.nc",
9154 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
9155 LOG(1, "Write init file: %s", filename_init);
9156
9157 /* Create file... */
9158 nc_create(filename_init, NC_NETCDF4, &ncid);
9159
9160 /* Define dimensions... */
9161 NC(nc_def_dim(ncid, "time", 1, &tid));
9162 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
9163 dim_ids[0] = tid;
9164 dim_ids[1] = pid;
9165
9166 /* Define variables and their attributes... */
9167 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
9168 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
9169 NC_DEF_VAR("LAT", NC_DOUBLE, 1, &pid, "Latitude", "deg",
9170 ctl->atm_nc_level, 0);
9171 NC_DEF_VAR("LON", NC_DOUBLE, 1, &pid, "Longitude", "deg",
9172 ctl->atm_nc_level, 0);
9173 NC_DEF_VAR("PRESS", NC_DOUBLE, 1, &pid, "Pressure", "hPa",
9174 ctl->atm_nc_level, 0);
9175 NC_DEF_VAR("ZETA", NC_DOUBLE, 1, &pid, "Zeta", "K", ctl->atm_nc_level, 0);
9176 for (int iq = 0; iq < ctl->nq; iq++)
9177 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
9178 ctl->qnt_name[iq], ctl->qnt_unit[iq],
9179 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
9180
9181 /* Define global attributes... */
9182 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
9183 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
9184
9185 /* End definitions... */
9186 NC(nc_enddef(ncid));
9187
9188 /* Write data... */
9189 NC_PUT_DOUBLE("time", atm->time, 0);
9190 NC_PUT_DOUBLE("LAT", atm->lat, 0);
9191 NC_PUT_DOUBLE("LON", atm->lon, 0);
9192 NC_PUT_DOUBLE("PRESS", atm->p, 0);
9193 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 0);
9194 for (int iq = 0; iq < ctl->nq; iq++)
9195 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
9196
9197 /* Close file... */
9198 NC(nc_close(ncid));
9199 }
9200}
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 9204 of file mptrac.c.

9207 {
9208
9209 int ncid, obsid, varid;
9210
9211 size_t start[2], count[2];
9212
9213 /* Create file... */
9214 NC(nc_create(filename, NC_NETCDF4, &ncid));
9215
9216 /* Define dimensions... */
9217 NC(nc_def_dim(ncid, "obs", (size_t) atm->np, &obsid));
9218
9219 /* Define variables and their attributes... */
9220 NC_DEF_VAR("time", NC_DOUBLE, 1, &obsid, "time",
9221 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
9222 NC_DEF_VAR("press", NC_DOUBLE, 1, &obsid, "pressure", "hPa",
9223 ctl->atm_nc_level, 0);
9224 NC_DEF_VAR("lon", NC_DOUBLE, 1, &obsid, "longitude", "degrees_east",
9225 ctl->atm_nc_level, 0);
9226 NC_DEF_VAR("lat", NC_DOUBLE, 1, &obsid, "latitude", "degrees_north",
9227 ctl->atm_nc_level, 0);
9228 for (int iq = 0; iq < ctl->nq; iq++)
9229 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 1, &obsid,
9230 ctl->qnt_longname[iq], ctl->qnt_unit[iq],
9231 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
9232
9233 /* Define global attributes... */
9234 NC_PUT_ATT_GLOBAL("featureType", "point");
9235
9236 /* End definitions... */
9237 NC(nc_enddef(ncid));
9238
9239 /* Write data... */
9240 NC_PUT_DOUBLE("time", atm->time, 0);
9241 NC_PUT_DOUBLE("press", atm->p, 0);
9242 NC_PUT_DOUBLE("lon", atm->lon, 0);
9243 NC_PUT_DOUBLE("lat", atm->lat, 0);
9244 for (int iq = 0; iq < ctl->nq; iq++)
9245 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
9246
9247 /* Close file... */
9248 NC(nc_close(ncid));
9249}

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

9257 {
9258
9259 static FILE *out;
9260
9261 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
9262 *area, dlon, dlat, dz, x[NCSI], y[NCSI], obsstdn[NCSI], kz[EP], kw[EP];
9263
9264 static int *obscount, ct, cx, cy, cz, ip, ix, iy, iz, n, nobs, nk;
9265
9266 /* Set timer... */
9267 SELECT_TIMER("WRITE_CSI", "OUTPUT", NVTX_WRITE);
9268
9269 /* Init... */
9270 if (t == ctl->t_start) {
9271
9272 /* Check quantity index for mass... */
9273 if (ctl->qnt_m < 0)
9274 ERRMSG("Need quantity mass!");
9275
9276 /* Allocate... */
9277 ALLOC(area, double,
9278 ctl->csi_ny);
9279 ALLOC(rt, double,
9280 NOBS);
9281 ALLOC(rz, double,
9282 NOBS);
9283 ALLOC(rlon, double,
9284 NOBS);
9285 ALLOC(rlat, double,
9286 NOBS);
9287 ALLOC(robs, double,
9288 NOBS);
9289
9290 /* Read observation data... */
9291 read_obs(ctl->csi_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
9292
9293 /* Read kernel data... */
9294 if (ctl->csi_kernel[0] != '-')
9295 read_kernel(ctl->csi_kernel, kz, kw, &nk);
9296
9297 /* Create new file... */
9298 LOG(1, "Write CSI data: %s", filename);
9299 if (!(out = fopen(filename, "w")))
9300 ERRMSG("Cannot create file!");
9301
9302 /* Write header... */
9303 fprintf(out,
9304 "# $1 = time [s]\n"
9305 "# $2 = number of hits (cx)\n"
9306 "# $3 = number of misses (cy)\n"
9307 "# $4 = number of false alarms (cz)\n"
9308 "# $5 = number of observations (cx + cy)\n"
9309 "# $6 = number of forecasts (cx + cz)\n"
9310 "# $7 = bias (ratio of forecasts and observations) [%%]\n"
9311 "# $8 = probability of detection (POD) [%%]\n"
9312 "# $9 = false alarm rate (FAR) [%%]\n"
9313 "# $10 = critical success index (CSI) [%%]\n");
9314 fprintf(out,
9315 "# $11 = hits associated with random chance\n"
9316 "# $12 = equitable threat score (ETS) [%%]\n"
9317 "# $13 = Pearson linear correlation coefficient\n"
9318 "# $14 = Spearman rank-order correlation coefficient\n"
9319 "# $15 = column density mean error (F - O) [kg/m^2]\n"
9320 "# $16 = column density root mean square error (RMSE) [kg/m^2]\n"
9321 "# $17 = column density mean absolute error [kg/m^2]\n"
9322 "# $18 = log-likelihood function\n"
9323 "# $19 = number of data points\n\n");
9324
9325 /* Set grid box size... */
9326 dz = (ctl->csi_z1 - ctl->csi_z0) / ctl->csi_nz;
9327 dlon = (ctl->csi_lon1 - ctl->csi_lon0) / ctl->csi_nx;
9328 dlat = (ctl->csi_lat1 - ctl->csi_lat0) / ctl->csi_ny;
9329
9330 /* Set horizontal coordinates... */
9331 for (iy = 0; iy < ctl->csi_ny; iy++) {
9332 const double lat = ctl->csi_lat0 + dlat * (iy + 0.5);
9333 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat));
9334 }
9335 }
9336
9337 /* Set time interval... */
9338 const double t0 = t - 0.5 * ctl->dt_mod;
9339 const double t1 = t + 0.5 * ctl->dt_mod;
9340
9341 /* Allocate... */
9342 ALLOC(modmean, double,
9343 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
9344 ALLOC(obsmean, double,
9345 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
9346 ALLOC(obscount, int,
9347 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
9348 ALLOC(obsstd, double,
9349 ctl->csi_nx * ctl->csi_ny * ctl->csi_nz);
9350
9351 /* Loop over observations... */
9352 for (int i = 0; i < nobs; i++) {
9353
9354 /* Check time... */
9355 if (rt[i] < t0)
9356 continue;
9357 else if (rt[i] >= t1)
9358 break;
9359
9360 /* Check observation data... */
9361 if (!isfinite(robs[i]))
9362 continue;
9363
9364 /* Calculate indices... */
9365 ix = (int) ((rlon[i] - ctl->csi_lon0) / dlon);
9366 iy = (int) ((rlat[i] - ctl->csi_lat0) / dlat);
9367 iz = (int) ((rz[i] - ctl->csi_z0) / dz);
9368
9369 /* Check indices... */
9370 if (ix < 0 || ix >= ctl->csi_nx ||
9371 iy < 0 || iy >= ctl->csi_ny || iz < 0 || iz >= ctl->csi_nz)
9372 continue;
9373
9374 /* Get mean observation index... */
9375 int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
9376 obsmean[idx] += robs[i];
9377 obsstd[idx] += SQR(robs[i]);
9378 obscount[idx]++;
9379 }
9380
9381 /* Analyze model data... */
9382 for (ip = 0; ip < atm->np; ip++) {
9383
9384 /* Check time... */
9385 if (atm->time[ip] < t0 || atm->time[ip] > t1)
9386 continue;
9387
9388 /* Get indices... */
9389 ix = (int) ((atm->lon[ip] - ctl->csi_lon0) / dlon);
9390 iy = (int) ((atm->lat[ip] - ctl->csi_lat0) / dlat);
9391 iz = (int) ((Z(atm->p[ip]) - ctl->csi_z0) / dz);
9392
9393 /* Check indices... */
9394 if (ix < 0 || ix >= ctl->csi_nx ||
9395 iy < 0 || iy >= ctl->csi_ny || iz < 0 || iz >= ctl->csi_nz)
9396 continue;
9397
9398 /* Get total mass in grid cell... */
9399 int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
9400 modmean[idx] += kernel_weight(kz, kw, nk, atm->p[ip])
9401 * atm->q[ctl->qnt_m][ip];
9402 }
9403
9404 /* Analyze all grid cells... */
9405 for (ix = 0; ix < ctl->csi_nx; ix++)
9406 for (iy = 0; iy < ctl->csi_ny; iy++)
9407 for (iz = 0; iz < ctl->csi_nz; iz++) {
9408
9409 /* Calculate mean observation index... */
9410 int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
9411 if (obscount[idx] > 0) {
9412 obsmean[idx] /= obscount[idx];
9413 obsstd[idx] -= SQR(obsmean[idx]);
9414 obsstd[idx] = sqrt(obsstd[idx]);
9415 }
9416
9417 /* Calculate column density... */
9418 if (modmean[idx] > 0)
9419 modmean[idx] /= (1e6 * area[iy]);
9420
9421 /* Calculate CSI... */
9422 if (obscount[idx] > 0) {
9423 ct++;
9424 if (obsmean[idx] >= ctl->csi_obsmin &&
9425 modmean[idx] >= ctl->csi_modmin)
9426 cx++;
9427 else if (obsmean[idx] >= ctl->csi_obsmin &&
9428 modmean[idx] < ctl->csi_modmin)
9429 cy++;
9430 else if (obsmean[idx] < ctl->csi_obsmin &&
9431 modmean[idx] >= ctl->csi_modmin)
9432 cz++;
9433 }
9434
9435 /* Save data for other verification statistics... */
9436 if (obscount[idx] > 0
9437 && (obsmean[idx] >= ctl->csi_obsmin
9438 || modmean[idx] >= ctl->csi_modmin)) {
9439 x[n] = modmean[idx];
9440 y[n] = obsmean[idx];
9441 if (modmean[idx] >= ctl->csi_modmin)
9442 obsstdn[n] = obsstd[idx];
9443 if ((++n) >= NCSI)
9444 ERRMSG("Too many data points to calculate statistics!");
9445 }
9446 }
9447
9448 /* Write output... */
9449 if (fmod(t, ctl->csi_dt_out) == 0) {
9450
9451 /* Calculate verification statistics
9452 (https://www.cawcr.gov.au/projects/verification/) ... */
9453 static double work[2 * NCSI], work2[2 * NCSI];;
9454 const int n_obs = cx + cy;
9455 const int n_for = cx + cz;
9456 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
9457 const double pod = (n_obs > 0) ? (100. * cx) / n_obs : NAN;
9458 const double far = (n_for > 0) ? (100. * cz) / n_for : NAN;
9459 const double csi =
9460 (cx + cy + cz > 0) ? (100. * cx) / (cx + cy + cz) : NAN;
9461 const double cx_rd = (ct > 0) ? (1. * n_obs * n_for) / ct : NAN;
9462 const double ets = (cx + cy + cz - cx_rd > 0) ?
9463 (100. * (cx - cx_rd)) / (cx + cy + cz - cx_rd) : NAN;
9464 const double rho_p =
9465 (n > 0) ? gsl_stats_correlation(x, 1, y, 1, (size_t) n) : NAN;
9466 const double rho_s =
9467 (n > 0) ? gsl_stats_spearman(x, 1, y, 1, (size_t) n, work) : NAN;
9468 for (int i = 0; i < n; i++) {
9469 work[i] = x[i] - y[i];
9470 work2[i] = (obsstdn[i] != 0) ? (x[i] - y[i]) / obsstdn[i] : 0;
9471 }
9472 const double mean = (n > 0) ? gsl_stats_mean(work, 1, (size_t) n) : NAN;
9473 const double rmse =
9474 (n > 0) ? gsl_stats_sd_with_fixed_mean(work, 1, (size_t) n,
9475 0.0) : NAN;
9476 const double absdev =
9477 (n > 0) ? gsl_stats_absdev_m(work, 1, (size_t) n, 0.0) : NAN;
9478 const double loglikelihood =
9479 (n > 0) ? gsl_stats_tss(work2, 1, (size_t) n) * (-0.5) : GSL_NAN;
9480
9481 /* Write... */
9482 fprintf(out,
9483 "%.2f %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n", t,
9484 cx, cy, cz, n_obs, n_for, bias, pod, far, csi, cx_rd, ets, rho_p,
9485 rho_s, mean, rmse, absdev, loglikelihood, n);
9486
9487 /* Set counters to zero... */
9488 n = ct = cx = cy = cz = 0;
9489 }
9490
9491 /* Free... */
9492 free(modmean);
9493 free(obsmean);
9494 free(obscount);
9495 free(obsstd);
9496
9497 /* Finalize... */
9498 if (t == ctl->t_stop) {
9499
9500 /* Close output file... */
9501 fclose(out);
9502
9503 /* Free... */
9504 free(area);
9505 free(rt);
9506 free(rz);
9507 free(rlon);
9508 free(rlat);
9509 free(robs);
9510 }
9511}
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:8329
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:5903
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:1864
#define NCSI
Maximum number of data points for CSI calculation.
Definition: mptrac.h:256
Here is the call graph for this function:

◆ write_ens()

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

Writes ensemble data to a file.

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

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

The function performs the following steps:

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

Definition at line 9515 of file mptrac.c.

9519 {
9520
9521 static FILE *out;
9522
9523 static double dummy, lat, lon, qm[NQ][NENS], qs[NQ][NENS], xm[NENS][3],
9524 x[3], zm[NENS];
9525
9526 static int n[NENS];
9527
9528 /* Set timer... */
9529 SELECT_TIMER("WRITE_ENS", "OUTPUT", NVTX_WRITE);
9530
9531 /* Check quantities... */
9532 if (ctl->qnt_ens < 0)
9533 ERRMSG("Missing ensemble IDs!");
9534
9535 /* Set time interval... */
9536 const double t0 = t - 0.5 * ctl->dt_mod;
9537 const double t1 = t + 0.5 * ctl->dt_mod;
9538
9539 /* Init... */
9540 for (int i = 0; i < NENS; i++) {
9541 for (int iq = 0; iq < ctl->nq; iq++)
9542 qm[iq][i] = qs[iq][i] = 0;
9543 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
9544 n[i] = 0;
9545 }
9546
9547 /* Loop over air parcels... */
9548 for (int ip = 0; ip < atm->np; ip++) {
9549
9550 /* Check time... */
9551 if (atm->time[ip] < t0 || atm->time[ip] > t1)
9552 continue;
9553
9554 /* Check ensemble ID... */
9555 if (atm->q[ctl->qnt_ens][ip] < 0 || atm->q[ctl->qnt_ens][ip] >= NENS)
9556 ERRMSG("Ensemble ID is out of range!");
9557
9558 /* Get means... */
9559 geo2cart(0, atm->lon[ip], atm->lat[ip], x);
9560 for (int iq = 0; iq < ctl->nq; iq++) {
9561 qm[iq][ctl->qnt_ens] += atm->q[iq][ip];
9562 qs[iq][ctl->qnt_ens] += SQR(atm->q[iq][ip]);
9563 }
9564 xm[ctl->qnt_ens][0] += x[0];
9565 xm[ctl->qnt_ens][1] += x[1];
9566 xm[ctl->qnt_ens][2] += x[2];
9567 zm[ctl->qnt_ens] += Z(atm->p[ip]);
9568 n[ctl->qnt_ens]++;
9569 }
9570
9571 /* Create file... */
9572 LOG(1, "Write ensemble data: %s", filename);
9573 if (!(out = fopen(filename, "w")))
9574 ERRMSG("Cannot create file!");
9575
9576 /* Write header... */
9577 fprintf(out,
9578 "# $1 = time [s]\n"
9579 "# $2 = altitude [km]\n"
9580 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
9581 for (int iq = 0; iq < ctl->nq; iq++)
9582 fprintf(out, "# $%d = %s (mean) [%s]\n", 5 + iq,
9583 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
9584 for (int iq = 0; iq < ctl->nq; iq++)
9585 fprintf(out, "# $%d = %s (sigma) [%s]\n", 5 + ctl->nq + iq,
9586 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
9587 fprintf(out, "# $%d = number of members\n\n", 5 + 2 * ctl->nq);
9588
9589 /* Write data... */
9590 for (int i = 0; i < NENS; i++)
9591 if (n[i] > 0) {
9592 cart2geo(xm[i], &dummy, &lon, &lat);
9593 fprintf(out, "%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
9594 for (int iq = 0; iq < ctl->nq; iq++) {
9595 fprintf(out, " ");
9596 fprintf(out, ctl->qnt_format[iq], qm[iq][i] / n[i]);
9597 }
9598 for (int iq = 0; iq < ctl->nq; iq++) {
9599 fprintf(out, " ");
9600 double var = qs[iq][i] / n[i] - SQR(qm[iq][i] / n[i]);
9601 fprintf(out, ctl->qnt_format[iq], (var > 0 ? sqrt(var) : 0));
9602 }
9603 fprintf(out, " %d\n", n[i]);
9604 }
9605
9606 /* Close file... */
9607 fclose(out);
9608}
void cart2geo(const double *x, double *z, double *lon, double *lat)
State variables of cuRAND random number generator.
Definition: mptrac.c:74
#define NENS
Maximum number of data points for ensemble analysis.
Definition: mptrac.h:276
Here is the call graph for this function:

◆ write_grid()

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

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

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

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

The function performs the following steps:

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

Definition at line 9612 of file mptrac.c.

9618 {
9619
9620 static double kz[EP], kw[EP];
9621
9622 static int nk;
9623
9624 double *cd, *mean[NQ], *sigma[NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
9625
9626 int *ixs, *iys, *izs, *np;
9627
9628 /* Set timer... */
9629 SELECT_TIMER("WRITE_GRID", "OUTPUT", NVTX_WRITE);
9630
9631 /* Write info... */
9632 LOG(1, "Write grid data: %s", filename);
9633
9634 /* Init... */
9635 if (t == ctl->t_start) {
9636
9637 /* Read kernel data... */
9638 if (ctl->grid_kernel[0] != '-')
9639 read_kernel(ctl->grid_kernel, kz, kw, &nk);
9640 }
9641
9642 /* Allocate... */
9643 ALLOC(cd, double,
9644 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
9645 for (int iq = 0; iq < ctl->nq; iq++) {
9646 ALLOC(mean[iq], double,
9647 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
9648 ALLOC(sigma[iq], double,
9649 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
9650 }
9651 ALLOC(vmr_impl, double,
9652 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
9653 ALLOC(z, double,
9654 ctl->grid_nz);
9655 ALLOC(lon, double,
9656 ctl->grid_nx);
9657 ALLOC(lat, double,
9658 ctl->grid_ny);
9659 ALLOC(area, double,
9660 ctl->grid_ny);
9661 ALLOC(press, double,
9662 ctl->grid_nz);
9663 ALLOC(np, int,
9664 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
9665 ALLOC(ixs, int,
9666 atm->np);
9667 ALLOC(iys, int,
9668 atm->np);
9669 ALLOC(izs, int,
9670 atm->np);
9671
9672 /* Set grid box size... */
9673 const double dz = (ctl->grid_z1 - ctl->grid_z0) / ctl->grid_nz;
9674 const double dlon = (ctl->grid_lon1 - ctl->grid_lon0) / ctl->grid_nx;
9675 const double dlat = (ctl->grid_lat1 - ctl->grid_lat0) / ctl->grid_ny;
9676
9677 /* Set vertical coordinates... */
9678#pragma omp parallel for default(shared)
9679 for (int iz = 0; iz < ctl->grid_nz; iz++) {
9680 z[iz] = ctl->grid_z0 + dz * (iz + 0.5);
9681 press[iz] = P(z[iz]);
9682 }
9683
9684 /* Set horizontal coordinates... */
9685 for (int ix = 0; ix < ctl->grid_nx; ix++)
9686 lon[ix] = ctl->grid_lon0 + dlon * (ix + 0.5);
9687#pragma omp parallel for default(shared)
9688 for (int iy = 0; iy < ctl->grid_ny; iy++) {
9689 lat[iy] = ctl->grid_lat0 + dlat * (iy + 0.5);
9690 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
9691 }
9692
9693 /* Set time interval for output... */
9694 const double t0 = t - 0.5 * ctl->dt_mod;
9695 const double t1 = t + 0.5 * ctl->dt_mod;
9696
9697 /* Get grid box indices... */
9698#pragma omp parallel for default(shared)
9699 for (int ip = 0; ip < atm->np; ip++) {
9700 ixs[ip] = (int) ((atm->lon[ip] - ctl->grid_lon0) / dlon);
9701 iys[ip] = (int) ((atm->lat[ip] - ctl->grid_lat0) / dlat);
9702 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->grid_z0) / dz);
9703 if (atm->time[ip] < t0 || atm->time[ip] > t1
9704 || ixs[ip] < 0 || ixs[ip] >= ctl->grid_nx
9705 || iys[ip] < 0 || iys[ip] >= ctl->grid_ny
9706 || izs[ip] < 0 || izs[ip] >= ctl->grid_nz)
9707 izs[ip] = -1;
9708 }
9709
9710 /* Average data... */
9711 for (int ip = 0; ip < atm->np; ip++)
9712 if (izs[ip] >= 0) {
9713 int idx =
9714 ARRAY_3D(ixs[ip], iys[ip], ctl->grid_ny, izs[ip], ctl->grid_nz);
9715 double kernel = kernel_weight(kz, kw, nk, atm->p[ip]);
9716 np[idx]++;
9717 for (int iq = 0; iq < ctl->nq; iq++) {
9718 mean[iq][idx] += kernel * atm->q[iq][ip];
9719 sigma[iq][idx] += SQR(kernel * atm->q[iq][ip]);
9720 }
9721 }
9722
9723 /* Calculate column density and volume mixing ratio... */
9724#pragma omp parallel for default(shared)
9725 for (int ix = 0; ix < ctl->grid_nx; ix++)
9726 for (int iy = 0; iy < ctl->grid_ny; iy++)
9727 for (int iz = 0; iz < ctl->grid_nz; iz++) {
9728
9729 /* Get grid index... */
9730 int idx = ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz);
9731
9732 /* Calculate column density... */
9733 cd[idx] = NAN;
9734 if (ctl->qnt_m >= 0)
9735 cd[idx] = mean[ctl->qnt_m][idx] / (1e6 * area[iy]);
9736
9737 /* Calculate volume mixing ratio (implicit)... */
9738 vmr_impl[idx] = NAN;
9739 if (ctl->qnt_m >= 0 && ctl->molmass > 0 && met0 != NULL
9740 && met1 != NULL) {
9741 vmr_impl[idx] = 0;
9742 if (mean[ctl->qnt_m][idx] > 0) {
9743
9744 /* Get temperature... */
9745 double temp;
9747 intpol_met_time_3d(met0, met0->t, met1, met1->t, t, press[iz],
9748 lon[ix], lat[iy], &temp, ci, cw, 1);
9749
9750 /* Calculate volume mixing ratio... */
9751 vmr_impl[idx] =
9752 MA / ctl->molmass * cd[idx] / (RHO(press[iz], temp) * dz * 1e3);
9753 }
9754 }
9755
9756 /* Calculate mean... */
9757 if (np[idx] > 0)
9758 for (int iq = 0; iq < ctl->nq; iq++) {
9759 mean[iq][idx] /= np[idx];
9760 double var = sigma[iq][idx] / np[idx] - SQR(mean[iq][idx]);
9761 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
9762 } else
9763 for (int iq = 0; iq < ctl->nq; iq++) {
9764 mean[iq][idx] = NAN;
9765 sigma[iq][idx] = NAN;
9766 }
9767 }
9768
9769 /* Write ASCII data... */
9770 if (ctl->grid_type == 0)
9771 write_grid_asc(filename, ctl, cd, mean, sigma, vmr_impl,
9772 t, z, lon, lat, area, dz, np);
9773
9774 /* Write netCDF data... */
9775 else if (ctl->grid_type == 1)
9776 write_grid_nc(filename, ctl, cd, mean, sigma, vmr_impl,
9777 t, z, lon, lat, area, dz, np);
9778
9779 /* Error message... */
9780 else
9781 ERRMSG("Grid data format GRID_TYPE unknown!");
9782
9783 /* Free... */
9784 free(cd);
9785 for (int iq = 0; iq < ctl->nq; iq++) {
9786 free(mean[iq]);
9787 free(sigma[iq]);
9788 }
9789 free(vmr_impl);
9790 free(z);
9791 free(lon);
9792 free(lat);
9793 free(area);
9794 free(press);
9795 free(np);
9796 free(ixs);
9797 free(iys);
9798 free(izs);
9799}
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:9803
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:9907
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 9803 of file mptrac.c.

9816 {
9817
9818 FILE *out;
9819
9820 /* Check if gnuplot output is requested... */
9821 if (ctl->grid_gpfile[0] != '-') {
9822
9823 /* Create gnuplot pipe... */
9824 if (!(out = popen("gnuplot", "w")))
9825 ERRMSG("Cannot create pipe to gnuplot!");
9826
9827 /* Set plot filename... */
9828 fprintf(out, "set out \"%s.png\"\n", filename);
9829
9830 /* Set time string... */
9831 double r;
9832 int year, mon, day, hour, min, sec;
9833 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
9834 fprintf(out, "timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
9835 year, mon, day, hour, min);
9836
9837 /* Dump gnuplot file to pipe... */
9838 FILE *in;
9839 char line[LEN];
9840 if (!(in = fopen(ctl->grid_gpfile, "r")))
9841 ERRMSG("Cannot open file!");
9842 while (fgets(line, LEN, in))
9843 fprintf(out, "%s", line);
9844 fclose(in);
9845 }
9846
9847 else {
9848
9849 /* Create file... */
9850 if (!(out = fopen(filename, "w")))
9851 ERRMSG("Cannot create file!");
9852 }
9853
9854 /* Write header... */
9855 fprintf(out,
9856 "# $1 = time [s]\n"
9857 "# $2 = altitude [km]\n"
9858 "# $3 = longitude [deg]\n"
9859 "# $4 = latitude [deg]\n"
9860 "# $5 = surface area [km^2]\n"
9861 "# $6 = layer depth [km]\n"
9862 "# $7 = column density (implicit) [kg/m^2]\n"
9863 "# $8 = volume mixing ratio (implicit) [ppv]\n"
9864 "# $9 = number of particles [1]\n");
9865 for (int iq = 0; iq < ctl->nq; iq++)
9866 fprintf(out, "# $%i = %s (mean) [%s]\n", 10 + iq, ctl->qnt_name[iq],
9867 ctl->qnt_unit[iq]);
9868 if (ctl->grid_stddev)
9869 for (int iq = 0; iq < ctl->nq; iq++)
9870 fprintf(out, "# $%i = %s (stddev) [%s]\n", 10 + ctl->nq + iq,
9871 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
9872 fprintf(out, "\n");
9873
9874 /* Write data... */
9875 for (int ix = 0; ix < ctl->grid_nx; ix++) {
9876 if (ix > 0 && ctl->grid_ny > 1 && !ctl->grid_sparse)
9877 fprintf(out, "\n");
9878 for (int iy = 0; iy < ctl->grid_ny; iy++) {
9879 if (iy > 0 && ctl->grid_nz > 1 && !ctl->grid_sparse)
9880 fprintf(out, "\n");
9881 for (int iz = 0; iz < ctl->grid_nz; iz++) {
9882 int idx = ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz);
9883 if (!ctl->grid_sparse || vmr_impl[idx] > 0) {
9884 fprintf(out, "%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
9885 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
9886 for (int iq = 0; iq < ctl->nq; iq++) {
9887 fprintf(out, " ");
9888 fprintf(out, ctl->qnt_format[iq], mean[iq][idx]);
9889 }
9890 if (ctl->grid_stddev)
9891 for (int iq = 0; iq < ctl->nq; iq++) {
9892 fprintf(out, " ");
9893 fprintf(out, ctl->qnt_format[iq], sigma[iq][idx]);
9894 }
9895 fprintf(out, "\n");
9896 }
9897 }
9898 }
9899 }
9900
9901 /* Close file... */
9902 fclose(out);
9903}
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 9907 of file mptrac.c.

9920 {
9921
9922 char longname[2 * LEN], varname[2 * LEN];
9923
9924 double *help;
9925
9926 int *help2, ncid, dimid[10], varid;
9927
9928 size_t start[2], count[2];
9929
9930 /* Allocate... */
9931 ALLOC(help, double,
9932 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
9933 ALLOC(help2, int,
9934 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
9935
9936 /* Create file... */
9937 NC(nc_create(filename, NC_NETCDF4, &ncid));
9938
9939 /* Define dimensions... */
9940 NC(nc_def_dim(ncid, "time", 1, &dimid[0]));
9941 NC(nc_def_dim(ncid, "z", (size_t) ctl->grid_nz, &dimid[1]));
9942 NC(nc_def_dim(ncid, "lat", (size_t) ctl->grid_ny, &dimid[2]));
9943 NC(nc_def_dim(ncid, "lon", (size_t) ctl->grid_nx, &dimid[3]));
9944 NC(nc_def_dim(ncid, "dz", 1, &dimid[4]));
9945
9946 /* Define variables and their attributes... */
9947 NC_DEF_VAR("time", NC_DOUBLE, 1, &dimid[0], "time",
9948 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
9949 NC_DEF_VAR("z", NC_DOUBLE, 1, &dimid[1], "altitude", "km", 0, 0);
9950 NC_DEF_VAR("lat", NC_DOUBLE, 1, &dimid[2], "latitude", "degrees_north", 0,
9951 0);
9952 NC_DEF_VAR("lon", NC_DOUBLE, 1, &dimid[3], "longitude", "degrees_east", 0,
9953 0);
9954 NC_DEF_VAR("dz", NC_DOUBLE, 1, &dimid[1], "layer depth", "km", 0, 0);
9955 NC_DEF_VAR("area", NC_DOUBLE, 1, &dimid[2], "surface area", "km**2", 0, 0);
9956
9957 NC_DEF_VAR("cd", NC_FLOAT, 4, dimid, "column density", "kg m**-2",
9958 ctl->grid_nc_level, 0);
9959 NC_DEF_VAR("vmr_impl", NC_FLOAT, 4, dimid, "volume mixing ratio (implicit)",
9960 "ppv", ctl->grid_nc_level, 0);
9961 NC_DEF_VAR("np", NC_INT, 4, dimid, "number of particles", "1", 0, 0);
9962 for (int iq = 0; iq < ctl->nq; iq++) {
9963 sprintf(varname, "%s_mean", ctl->qnt_name[iq]);
9964 sprintf(longname, "%s (mean)", ctl->qnt_longname[iq]);
9965 NC_DEF_VAR(varname, NC_DOUBLE, 4, dimid, longname, ctl->qnt_unit[iq],
9966 ctl->grid_nc_level, ctl->grid_nc_quant[iq]);
9967 if (ctl->grid_stddev) {
9968 sprintf(varname, "%s_stddev", ctl->qnt_name[iq]);
9969 sprintf(longname, "%s (stddev)", ctl->qnt_longname[iq]);
9970 NC_DEF_VAR(varname, NC_DOUBLE, 4, dimid, longname, ctl->qnt_unit[iq],
9971 ctl->grid_nc_level, ctl->grid_nc_quant[iq]);
9972 }
9973 }
9974 /* End definitions... */
9975 NC(nc_enddef(ncid));
9976
9977 /* Write data... */
9978 NC_PUT_DOUBLE("time", &t, 0);
9979 NC_PUT_DOUBLE("lon", lon, 0);
9980 NC_PUT_DOUBLE("lat", lat, 0);
9981 NC_PUT_DOUBLE("z", z, 0);
9982 NC_PUT_DOUBLE("area", area, 0);
9983 NC_PUT_DOUBLE("dz", &dz, 0);
9984
9985 for (int ix = 0; ix < ctl->grid_nx; ix++)
9986 for (int iy = 0; iy < ctl->grid_ny; iy++)
9987 for (int iz = 0; iz < ctl->grid_nz; iz++)
9988 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
9989 cd[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
9990 NC_PUT_DOUBLE("cd", help, 0);
9991
9992 for (int ix = 0; ix < ctl->grid_nx; ix++)
9993 for (int iy = 0; iy < ctl->grid_ny; iy++)
9994 for (int iz = 0; iz < ctl->grid_nz; iz++)
9995 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
9996 vmr_impl[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
9997 NC_PUT_DOUBLE("vmr_impl", help, 0);
9998
9999 for (int ix = 0; ix < ctl->grid_nx; ix++)
10000 for (int iy = 0; iy < ctl->grid_ny; iy++)
10001 for (int iz = 0; iz < ctl->grid_nz; iz++)
10002 help2[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
10003 np[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
10004 NC_PUT_INT("np", help2, 0);
10005
10006 for (int iq = 0; iq < ctl->nq; iq++) {
10007 sprintf(varname, "%s_mean", ctl->qnt_name[iq]);
10008 for (int ix = 0; ix < ctl->grid_nx; ix++)
10009 for (int iy = 0; iy < ctl->grid_ny; iy++)
10010 for (int iz = 0; iz < ctl->grid_nz; iz++)
10011 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
10012 mean[iq][ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
10013 NC_PUT_DOUBLE(varname, help, 0);
10014 }
10015
10016 if (ctl->grid_stddev)
10017 for (int iq = 0; iq < ctl->nq; iq++) {
10018 sprintf(varname, "%s_stddev", ctl->qnt_name[iq]);
10019 for (int ix = 0; ix < ctl->grid_nx; ix++)
10020 for (int iy = 0; iy < ctl->grid_ny; iy++)
10021 for (int iz = 0; iz < ctl->grid_nz; iz++)
10022 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
10023 sigma[iq][ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
10024 NC_PUT_DOUBLE(varname, help, 0);
10025 }
10026
10027 /* Close file... */
10028 NC(nc_close(ncid));
10029
10030 /* Free... */
10031 free(help);
10032 free(help2);
10033}
#define NC_PUT_INT(varname, ptr, hyperslab)
Write integer data to a NetCDF variable.
Definition: mptrac.h:1173

◆ write_met()

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

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

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

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

Definition at line 10037 of file mptrac.c.

10040 {
10041
10042 /* Set timer... */
10043 SELECT_TIMER("WRITE_MET", "OUTPUT", NVTX_WRITE);
10044
10045 /* Write info... */
10046 LOG(1, "Write meteo data: %s", filename);
10047
10048 /* Check compression flags... */
10049#ifndef ZFP
10050 if (ctl->met_type == 3)
10051 ERRMSG("MPTRAC was compiled without zfp compression!");
10052#endif
10053#ifndef ZSTD
10054 if (ctl->met_type == 4)
10055 ERRMSG("MPTRAC was compiled without zstd compression!");
10056#endif
10057#ifndef CMS
10058 if (ctl->met_type == 5)
10059 ERRMSG("MPTRAC was compiled without cmultiscale compression!");
10060#endif
10061
10062 /* Write netCDF data... */
10063 if (ctl->met_type == 0)
10064 write_met_nc(filename, ctl, met);
10065
10066 /* Write binary data... */
10067 else if (ctl->met_type >= 1 && ctl->met_type <= 5)
10068 write_met_bin(filename, ctl, met);
10069
10070 /* Not implemented... */
10071 else
10072 ERRMSG("MET_TYPE not implemented!");
10073}
void write_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a NetCDF file.
Definition: mptrac.c:10283
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:10077
Here is the call graph for this function:

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

10080 {
10081
10082 /* Create file... */
10083 FILE *out;
10084 if (!(out = fopen(filename, "w")))
10085 ERRMSG("Cannot create file!");
10086
10087 /* Write type of binary data... */
10088 FWRITE(&ctl->met_type, int,
10089 1,
10090 out);
10091
10092 /* Write version of binary data... */
10093 int version = 103;
10094 FWRITE(&version, int,
10095 1,
10096 out);
10097
10098 /* Write grid data... */
10099 FWRITE(&met->time, double,
10100 1,
10101 out);
10102 FWRITE(&met->nx, int,
10103 1,
10104 out);
10105 FWRITE(&met->ny, int,
10106 1,
10107 out);
10108 FWRITE(&met->np, int,
10109 1,
10110 out);
10111 FWRITE(met->lon, double,
10112 (size_t) met->nx,
10113 out);
10114 FWRITE(met->lat, double,
10115 (size_t) met->ny,
10116 out);
10117 FWRITE(met->p, double,
10118 (size_t) met->np,
10119 out);
10120
10121 /* Write surface data... */
10122 write_met_bin_2d(out, met, met->ps, "PS");
10123 write_met_bin_2d(out, met, met->ts, "TS");
10124 write_met_bin_2d(out, met, met->zs, "ZS");
10125 write_met_bin_2d(out, met, met->us, "US");
10126 write_met_bin_2d(out, met, met->vs, "VS");
10127 write_met_bin_2d(out, met, met->ess, "ESS");
10128 write_met_bin_2d(out, met, met->nss, "NSS");
10129 write_met_bin_2d(out, met, met->shf, "SHF");
10130 write_met_bin_2d(out, met, met->lsm, "LSM");
10131 write_met_bin_2d(out, met, met->sst, "SST");
10132 write_met_bin_2d(out, met, met->pbl, "PBL");
10133 write_met_bin_2d(out, met, met->pt, "PT");
10134 write_met_bin_2d(out, met, met->tt, "TT");
10135 write_met_bin_2d(out, met, met->zt, "ZT");
10136 write_met_bin_2d(out, met, met->h2ot, "H2OT");
10137 write_met_bin_2d(out, met, met->pct, "PCT");
10138 write_met_bin_2d(out, met, met->pcb, "PCB");
10139 write_met_bin_2d(out, met, met->cl, "CL");
10140 write_met_bin_2d(out, met, met->plcl, "PLCL");
10141 write_met_bin_2d(out, met, met->plfc, "PLFC");
10142 write_met_bin_2d(out, met, met->pel, "PEL");
10143 write_met_bin_2d(out, met, met->cape, "CAPE");
10144 write_met_bin_2d(out, met, met->cin, "CIN");
10145 write_met_bin_2d(out, met, met->o3c, "O3C");
10146
10147 /* Write level data... */
10148 write_met_bin_3d(out, ctl, met, met->z, "Z",
10149 (ctl->met_zfp_tol_z <= 0 ? ctl->met_zfp_prec : 0),
10150 ctl->met_zfp_tol_z);
10151 write_met_bin_3d(out, ctl, met, met->t, "T",
10152 (ctl->met_zfp_tol_t <= 0 ? ctl->met_zfp_prec : 0),
10153 ctl->met_zfp_tol_t);
10154 write_met_bin_3d(out, ctl, met, met->u, "U", ctl->met_zfp_prec, 0);
10155 write_met_bin_3d(out, ctl, met, met->v, "V", ctl->met_zfp_prec, 0);
10156 write_met_bin_3d(out, ctl, met, met->w, "W", ctl->met_zfp_prec, 0);
10157 write_met_bin_3d(out, ctl, met, met->pv, "PV", ctl->met_zfp_prec, 0);
10158 write_met_bin_3d(out, ctl, met, met->h2o, "H2O", ctl->met_zfp_prec, 0);
10159 write_met_bin_3d(out, ctl, met, met->o3, "O3", ctl->met_zfp_prec, 0);
10160 write_met_bin_3d(out, ctl, met, met->lwc, "LWC", ctl->met_zfp_prec, 0);
10161 write_met_bin_3d(out, ctl, met, met->rwc, "RWC", ctl->met_zfp_prec, 0);
10162 write_met_bin_3d(out, ctl, met, met->iwc, "IWC", ctl->met_zfp_prec, 0);
10163 write_met_bin_3d(out, ctl, met, met->swc, "SWC", ctl->met_zfp_prec, 0);
10164 write_met_bin_3d(out, ctl, met, met->cc, "CC", ctl->met_zfp_prec, 0);
10165
10166 /* Write final flag... */
10167 int final = 999;
10168 FWRITE(&final, int,
10169 1,
10170 out);
10171
10172 /* Close file... */
10173 fclose(out);
10174}
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:10207
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:10178
int met_zfp_prec
ZFP compression precision for all variables, except z and T.
Definition: mptrac.h:2509
double met_zfp_tol_t
ZFP compression tolerance for temperature.
Definition: mptrac.h:2512
double met_zfp_tol_z
ZFP compression tolerance for geopotential height.
Definition: mptrac.h:2515
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 10178 of file mptrac.c.

10182 {
10183
10184 float *help;
10185
10186 /* Allocate... */
10187 ALLOC(help, float,
10188 EX * EY);
10189
10190 /* Copy data... */
10191 for (int ix = 0; ix < met->nx; ix++)
10192 for (int iy = 0; iy < met->ny; iy++)
10193 help[ARRAY_2D(ix, iy, met->ny)] = var[ix][iy];
10194
10195 /* Write uncompressed data... */
10196 LOG(2, "Write 2-D variable: %s (uncompressed)", varname);
10197 FWRITE(help, float,
10198 (size_t) (met->nx * met->ny),
10199 out);
10200
10201 /* Free... */
10202 free(help);
10203}

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

10214 {
10215
10216 float *help;
10217
10218 /* Allocate... */
10219 ALLOC(help, float,
10220 EX * EY * EP);
10221
10222 /* Copy data... */
10223#pragma omp parallel for default(shared) collapse(2)
10224 for (int ix = 0; ix < met->nx; ix++)
10225 for (int iy = 0; iy < met->ny; iy++)
10226 for (int ip = 0; ip < met->np; ip++)
10227 help[ARRAY_3D(ix, iy, met->ny, ip, met->np)] = var[ix][iy][ip];
10228
10229 /* Write uncompressed data... */
10230 if (ctl->met_type == 1) {
10231 LOG(2, "Write 3-D variable: %s (uncompressed)", varname);
10232 FWRITE(help, float,
10233 (size_t) (met->nx * met->ny * met->np),
10234 out);
10235 }
10236
10237 /* Write packed data... */
10238 else if (ctl->met_type == 2)
10239 compress_pck(varname, help, (size_t) (met->ny * met->nx),
10240 (size_t) met->np, 0, out);
10241
10242 /* Write zfp data... */
10243#ifdef ZFP
10244 else if (ctl->met_type == 3) {
10245 FWRITE(&precision, int,
10246 1,
10247 out);
10248 FWRITE(&tolerance, double,
10249 1,
10250 out);
10251 compress_zfp(varname, help, met->np, met->ny, met->nx, precision,
10252 tolerance, 0, out);
10253 }
10254#endif
10255
10256 /* Write zstd data... */
10257#ifdef ZSTD
10258 else if (ctl->met_type == 4)
10259 compress_zstd(varname, help, (size_t) (met->np * met->ny * met->nx), 0,
10260 out);
10261#endif
10262
10263 /* Write cmultiscale data... */
10264#ifdef CMS
10265 else if (ctl->met_type == 5) {
10266 compress_cms(ctl, varname, help, (size_t) met->nx, (size_t) met->ny,
10267 (size_t) met->np, 0, out);
10268 }
10269#endif
10270
10271 /* Unknown method... */
10272 else {
10273 ERRMSG("MET_TYPE not supported!");
10274 LOG(3, "%d %g", precision, tolerance);
10275 }
10276
10277 /* Free... */
10278 free(help);
10279}
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 10283 of file mptrac.c.

10286 {
10287
10288 /* Create file... */
10289 int ncid, varid;
10290 size_t start[4], count[4];
10291 nc_create(filename, NC_NETCDF4, &ncid);
10292
10293 /* Define dimensions... */
10294 int tid, lonid, latid, levid;
10295 NC(nc_def_dim(ncid, "time", 1, &tid));
10296 NC(nc_def_dim(ncid, "lon", (size_t) met->nx, &lonid));
10297 NC(nc_def_dim(ncid, "lat", (size_t) met->ny, &latid));
10298 NC(nc_def_dim(ncid, "lev", (size_t) met->np, &levid));
10299
10300 /* Define grid... */
10301 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "time",
10302 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
10303 NC_DEF_VAR("lon", NC_DOUBLE, 1, &lonid, "longitude", "degrees_east", 0, 0);
10304 NC_DEF_VAR("lat", NC_DOUBLE, 1, &latid, "latitude", "degrees_north", 0, 0);
10305 NC_DEF_VAR("lev", NC_DOUBLE, 1, &levid, "pressure", "Pa", 0, 0);
10306
10307 /* Define surface variables... */
10308 int dimid2[2] = { latid, lonid };
10309 NC_DEF_VAR("sp", NC_FLOAT, 2, dimid2, "Surface pressure", "Pa",
10310 ctl->met_nc_level, 0);
10311 NC_DEF_VAR("z", NC_FLOAT, 2, dimid2, "Geopotential", "m**2 s**-2",
10312 ctl->met_nc_level, 0);
10313 NC_DEF_VAR("t2m", NC_FLOAT, 2, dimid2, "2 metre temperature", "K",
10314 ctl->met_nc_level, 0);
10315 NC_DEF_VAR("u10m", NC_FLOAT, 2, dimid2, "10 metre U wind component",
10316 "m s**-1", ctl->met_nc_level, 0);
10317 NC_DEF_VAR("v10m", NC_FLOAT, 2, dimid2, "10 metre V wind component",
10318 "m s**-1", ctl->met_nc_level, 0);
10319 NC_DEF_VAR("iews", NC_FLOAT, 2, dimid2,
10320 "Instantaneous eastward turbulent surface stress", "N m**-2",
10321 ctl->met_nc_level, 0);
10322 NC_DEF_VAR("inss", NC_FLOAT, 2, dimid2,
10323 "Instantaneous northward turbulent surface stress", "N m**-2",
10324 ctl->met_nc_level, 0);
10325 NC_DEF_VAR("ishf", NC_FLOAT, 2, dimid2,
10326 "Instantaneous surface sensible heat flux", "W m**-1",
10327 ctl->met_nc_level, 0);
10328 NC_DEF_VAR("lsm", NC_FLOAT, 2, dimid2, "Land/sea mask", "-",
10329 ctl->met_nc_level, 0);
10330 NC_DEF_VAR("sstk", NC_FLOAT, 2, dimid2, "Sea surface temperature", "K",
10331 ctl->met_nc_level, 0);
10332 NC_DEF_VAR("blp", NC_FLOAT, 2, dimid2, "Boundary layer pressure", "Pa",
10333 ctl->met_nc_level, 0);
10334 NC_DEF_VAR("pt", NC_FLOAT, 2, dimid2, "Tropopause pressure", "Pa",
10335 ctl->met_nc_level, 0);
10336 NC_DEF_VAR("tt", NC_FLOAT, 2, dimid2, "Tropopause temperature", "K",
10337 ctl->met_nc_level, 0);
10338 NC_DEF_VAR("zt", NC_FLOAT, 2, dimid2, "Tropopause height", "m",
10339 ctl->met_nc_level, 0);
10340 NC_DEF_VAR("h2ot", NC_FLOAT, 2, dimid2, "Tropopause water vapor", "ppv",
10341 ctl->met_nc_level, 0);
10342 NC_DEF_VAR("pct", NC_FLOAT, 2, dimid2, "Cloud top pressure", "Pa",
10343 ctl->met_nc_level, 0);
10344 NC_DEF_VAR("pcb", NC_FLOAT, 2, dimid2, "Cloud bottom pressure", "Pa",
10345 ctl->met_nc_level, 0);
10346 NC_DEF_VAR("cl", NC_FLOAT, 2, dimid2, "Total column cloud water", "kg m**2",
10347 ctl->met_nc_level, 0);
10348 NC_DEF_VAR("plcl", NC_FLOAT, 2, dimid2,
10349 "Pressure at lifted condensation level (LCL)", "Pa",
10350 ctl->met_nc_level, 0);
10351 NC_DEF_VAR("plfc", NC_FLOAT, 2, dimid2,
10352 "Pressure at level of free convection (LFC)", "Pa",
10353 ctl->met_nc_level, 0);
10354 NC_DEF_VAR("pel", NC_FLOAT, 2, dimid2, "Pressure at equilibrium level (EL)",
10355 "Pa", ctl->met_nc_level, 0);
10356 NC_DEF_VAR("cape", NC_FLOAT, 2, dimid2,
10357 "Convective available potential energy", "J kg**-1",
10358 ctl->met_nc_level, 0);
10359 NC_DEF_VAR("cin", NC_FLOAT, 2, dimid2, "Convective inhibition", "J kg**-1",
10360 ctl->met_nc_level, 0);
10361 NC_DEF_VAR("o3c", NC_FLOAT, 2, dimid2, "Total column ozone", "DU",
10362 ctl->met_nc_level, 0);
10363
10364 /* Define level data... */
10365 int dimid3[3] = { levid, latid, lonid };
10366 NC_DEF_VAR("t", NC_FLOAT, 3, dimid3, "Temperature", "K",
10367 ctl->met_nc_level, ctl->met_nc_quant);
10368 NC_DEF_VAR("u", NC_FLOAT, 3, dimid3, "U velocity", "m s**-1",
10369 ctl->met_nc_level, ctl->met_nc_quant);
10370 NC_DEF_VAR("v", NC_FLOAT, 3, dimid3, "V velocity", "m s**-1",
10371 ctl->met_nc_level, ctl->met_nc_quant);
10372 NC_DEF_VAR("w", NC_FLOAT, 3, dimid3, "Vertical velocity", "Pa s**-1",
10373 ctl->met_nc_level, ctl->met_nc_quant);
10374 NC_DEF_VAR("q", NC_FLOAT, 3, dimid3, "Specific humidity", "kg kg**-1",
10375 ctl->met_nc_level, ctl->met_nc_quant);
10376 NC_DEF_VAR("o3", NC_FLOAT, 3, dimid3, "Ozone mass mixing ratio",
10377 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
10378 NC_DEF_VAR("clwc", NC_FLOAT, 3, dimid3, "Cloud liquid water content",
10379 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
10380 NC_DEF_VAR("crwc", NC_FLOAT, 3, dimid3, "Cloud rain water content",
10381 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
10382 NC_DEF_VAR("ciwc", NC_FLOAT, 3, dimid3, "Cloud ice water content",
10383 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
10384 NC_DEF_VAR("cswc", NC_FLOAT, 3, dimid3, "Cloud snow water content",
10385 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
10386 NC_DEF_VAR("cc", NC_FLOAT, 3, dimid3, "Cloud cover", "-",
10387 ctl->met_nc_level, ctl->met_nc_quant);
10388
10389 /* End definitions... */
10390 NC(nc_enddef(ncid));
10391
10392 /* Write grid data... */
10393 NC_PUT_DOUBLE("time", &met->time, 0);
10394 NC_PUT_DOUBLE("lon", met->lon, 0);
10395 NC_PUT_DOUBLE("lat", met->lat, 0);
10396 double phelp[EP];
10397 for (int ip = 0; ip < met->np; ip++)
10398 phelp[ip] = 100. * met->p[ip];
10399 NC_PUT_DOUBLE("lev", phelp, 0);
10400
10401 /* Write surface data... */
10402 write_met_nc_2d(ncid, "sp", met, met->ps, 100.0f);
10403 write_met_nc_2d(ncid, "z", met, met->zs, (float) (1000. * G0));
10404 write_met_nc_2d(ncid, "t2m", met, met->ts, 1.0f);
10405 write_met_nc_2d(ncid, "u10m", met, met->us, 1.0f);
10406 write_met_nc_2d(ncid, "v10m", met, met->vs, 1.0f);
10407 write_met_nc_2d(ncid, "iews", met, met->ess, 1.0f);
10408 write_met_nc_2d(ncid, "inss", met, met->nss, 1.0f);
10409 write_met_nc_2d(ncid, "ishf", met, met->shf, 1.0f);
10410 write_met_nc_2d(ncid, "lsm", met, met->lsm, 1.0f);
10411 write_met_nc_2d(ncid, "sstk", met, met->sst, 1.0f);
10412 write_met_nc_2d(ncid, "blp", met, met->pbl, 100.0f);
10413 write_met_nc_2d(ncid, "pt", met, met->pt, 100.0f);
10414 write_met_nc_2d(ncid, "tt", met, met->tt, 1.0f);
10415 write_met_nc_2d(ncid, "zt", met, met->zt, 1000.0f);
10416 write_met_nc_2d(ncid, "h2ot", met, met->h2ot, 1.0f);
10417 write_met_nc_2d(ncid, "pct", met, met->pct, 100.0f);
10418 write_met_nc_2d(ncid, "pcb", met, met->pcb, 100.0f);
10419 write_met_nc_2d(ncid, "cl", met, met->cl, 1.0f);
10420 write_met_nc_2d(ncid, "plcl", met, met->plcl, 100.0f);
10421 write_met_nc_2d(ncid, "plfc", met, met->plfc, 100.0f);
10422 write_met_nc_2d(ncid, "pel", met, met->pel, 100.0f);
10423 write_met_nc_2d(ncid, "cape", met, met->cape, 1.0f);
10424 write_met_nc_2d(ncid, "cin", met, met->cin, 1.0f);
10425 write_met_nc_2d(ncid, "o3c", met, met->o3c, 1.0f);
10426
10427 /* Write level data... */
10428 write_met_nc_3d(ncid, "t", met, met->t, 1.0f);
10429 write_met_nc_3d(ncid, "u", met, met->u, 1.0f);
10430 write_met_nc_3d(ncid, "v", met, met->v, 1.0f);
10431 write_met_nc_3d(ncid, "w", met, met->w, 100.0f);
10432 write_met_nc_3d(ncid, "q", met, met->h2o, (float) (MH2O / MA));
10433 write_met_nc_3d(ncid, "o3", met, met->o3, (float) (MO3 / MA));
10434 write_met_nc_3d(ncid, "clwc", met, met->lwc, 1.0f);
10435 write_met_nc_3d(ncid, "crwc", met, met->rwc, 1.0f);
10436 write_met_nc_3d(ncid, "ciwc", met, met->iwc, 1.0f);
10437 write_met_nc_3d(ncid, "cswc", met, met->swc, 1.0f);
10438 write_met_nc_3d(ncid, "cc", met, met->cc, 1.0f);
10439
10440 /* Close file... */
10441 NC(nc_close(ncid));
10442}
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:10446
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:10475
int met_nc_quant
Number of digits for quantization of netCDF meteo files (0=off).
Definition: mptrac.h:2506
int met_nc_level
zlib compression level of netCDF meteo files (0=off).
Definition: mptrac.h:2503
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 10446 of file mptrac.c.

10451 {
10452
10453 int varid;
10454 size_t start[4], count[4];
10455
10456 /* Allocate... */
10457 float *help;
10458 ALLOC(help, float,
10459 EX * EY);
10460
10461 /* Copy data... */
10462 for (int ix = 0; ix < met->nx; ix++)
10463 for (int iy = 0; iy < met->ny; iy++)
10464 help[ARRAY_2D(iy, ix, met->nx)] = scl * var[ix][iy];
10465
10466 /* Write data... */
10467 NC_PUT_FLOAT(varname, help, 0);
10468
10469 /* Free... */
10470 free(help);
10471}
#define NC_PUT_FLOAT(varname, ptr, hyperslab)
Write a float array to a NetCDF file.
Definition: mptrac.h:1150

◆ write_met_nc_3d()

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

Writes a 3D meteorological variable to a NetCDF file.

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

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

Definition at line 10475 of file mptrac.c.

10480 {
10481
10482 int varid;
10483 size_t start[4], count[4];
10484
10485 /* Allocate... */
10486 float *help;
10487 ALLOC(help, float,
10488 EX * EY * EP);
10489
10490 /* Copy data... */
10491 for (int ix = 0; ix < met->nx; ix++)
10492 for (int iy = 0; iy < met->ny; iy++)
10493 for (int ip = 0; ip < met->np; ip++)
10494 help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)] = scl * var[ix][iy][ip];
10495
10496 /* Write data... */
10497 NC_PUT_FLOAT(varname, help, 0);
10498
10499 /* Free... */
10500 free(help);
10501}

◆ write_output()

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

10511 {
10512
10513 char ext[10], filename[2 * LEN];
10514
10515 double r;
10516
10517 int year, mon, day, hour, min, sec;
10518
10519 /* Get time... */
10520 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
10521
10522 /* Update host... */
10523#ifdef _OPENACC
10524 if ((ctl->atm_basename[0] != '-' && fmod(t, ctl->atm_dt_out) == 0)
10525 || (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0)
10526 || (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0)
10527 || ctl->csi_basename[0] != '-' || ctl->prof_basename[0] != '-'
10528 || ctl->sample_basename[0] != '-' || ctl->stat_basename[0] != '-'
10529 || (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0)) {
10530 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_D2H);
10531#pragma acc update host(atm[:1])
10532 }
10533#endif
10534
10535 /* Write atmospheric data... */
10536 if (ctl->atm_basename[0] != '-' &&
10537 (fmod(t, ctl->atm_dt_out) == 0 || t == ctl->t_stop)) {
10538 if (ctl->atm_type_out == 0)
10539 sprintf(ext, "tab");
10540 else if (ctl->atm_type_out == 1)
10541 sprintf(ext, "bin");
10542 else if (ctl->atm_type_out == 2)
10543 sprintf(ext, "nc");
10544 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
10545 dirname, ctl->atm_basename, year, mon, day, hour, min, ext);
10546 write_atm(filename, ctl, atm, t);
10547 }
10548
10549 /* Write gridded data... */
10550 if (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0) {
10551 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
10552 dirname, ctl->grid_basename, year, mon, day, hour, min,
10553 ctl->grid_type == 0 ? "tab" : "nc");
10554 write_grid(filename, ctl, met0, met1, atm, t);
10555 }
10556
10557 /* Write CSI data... */
10558 if (ctl->csi_basename[0] != '-') {
10559 sprintf(filename, "%s/%s.tab", dirname, ctl->csi_basename);
10560 write_csi(filename, ctl, atm, t);
10561 }
10562
10563 /* Write ensemble data... */
10564 if (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0) {
10565 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
10566 dirname, ctl->ens_basename, year, mon, day, hour, min);
10567 write_ens(filename, ctl, atm, t);
10568 }
10569
10570 /* Write profile data... */
10571 if (ctl->prof_basename[0] != '-') {
10572 sprintf(filename, "%s/%s.tab", dirname, ctl->prof_basename);
10573 write_prof(filename, ctl, met0, met1, atm, t);
10574 }
10575
10576 /* Write sample data... */
10577 if (ctl->sample_basename[0] != '-') {
10578 sprintf(filename, "%s/%s.tab", dirname, ctl->sample_basename);
10579 write_sample(filename, ctl, met0, met1, atm, t);
10580 }
10581
10582 /* Write station data... */
10583 if (ctl->stat_basename[0] != '-') {
10584 sprintf(filename, "%s/%s.tab", dirname, ctl->stat_basename);
10585 write_station(filename, ctl, atm, t);
10586 }
10587
10588 /* Write VTK data... */
10589 if (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0) {
10590 static int nvtk;
10591 if (t == ctl->t_start)
10592 nvtk = 0;
10593 sprintf(filename, "%s/%s_%05d.vtk", dirname, ctl->vtk_basename, ++nvtk);
10594 write_vtk(filename, ctl, atm, t);
10595 }
10596}
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:9515
void 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:8801
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:10600
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:10989
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:11075
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:10827
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:9612
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:9253
Here is the call graph for this function:

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

10606 {
10607
10608 static FILE *out;
10609
10610 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
10611 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
10612
10613 static int nobs, *obscount, ip, okay;
10614
10615 /* Set timer... */
10616 SELECT_TIMER("WRITE_PROF", "OUTPUT", NVTX_WRITE);
10617
10618 /* Init... */
10619 if (t == ctl->t_start) {
10620
10621 /* Check quantity index for mass... */
10622 if (ctl->qnt_m < 0)
10623 ERRMSG("Need quantity mass!");
10624
10625 /* Check molar mass... */
10626 if (ctl->molmass <= 0)
10627 ERRMSG("Specify molar mass!");
10628
10629 /* Allocate... */
10630 ALLOC(lon, double,
10631 ctl->prof_nx);
10632 ALLOC(lat, double,
10633 ctl->prof_ny);
10634 ALLOC(area, double,
10635 ctl->prof_ny);
10636 ALLOC(z, double,
10637 ctl->prof_nz);
10638 ALLOC(press, double,
10639 ctl->prof_nz);
10640 ALLOC(rt, double,
10641 NOBS);
10642 ALLOC(rz, double,
10643 NOBS);
10644 ALLOC(rlon, double,
10645 NOBS);
10646 ALLOC(rlat, double,
10647 NOBS);
10648 ALLOC(robs, double,
10649 NOBS);
10650
10651 /* Read observation data... */
10652 read_obs(ctl->prof_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
10653
10654 /* Create new output file... */
10655 LOG(1, "Write profile data: %s", filename);
10656 if (!(out = fopen(filename, "w")))
10657 ERRMSG("Cannot create file!");
10658
10659 /* Write header... */
10660 fprintf(out,
10661 "# $1 = time [s]\n"
10662 "# $2 = altitude [km]\n"
10663 "# $3 = longitude [deg]\n"
10664 "# $4 = latitude [deg]\n"
10665 "# $5 = pressure [hPa]\n"
10666 "# $6 = temperature [K]\n"
10667 "# $7 = volume mixing ratio [ppv]\n"
10668 "# $8 = H2O volume mixing ratio [ppv]\n"
10669 "# $9 = O3 volume mixing ratio [ppv]\n"
10670 "# $10 = observed BT index [K]\n"
10671 "# $11 = number of observations\n");
10672
10673 /* Set grid box size... */
10674 dz = (ctl->prof_z1 - ctl->prof_z0) / ctl->prof_nz;
10675 dlon = (ctl->prof_lon1 - ctl->prof_lon0) / ctl->prof_nx;
10676 dlat = (ctl->prof_lat1 - ctl->prof_lat0) / ctl->prof_ny;
10677
10678 /* Set vertical coordinates... */
10679 for (int iz = 0; iz < ctl->prof_nz; iz++) {
10680 z[iz] = ctl->prof_z0 + dz * (iz + 0.5);
10681 press[iz] = P(z[iz]);
10682 }
10683
10684 /* Set horizontal coordinates... */
10685 for (int ix = 0; ix < ctl->prof_nx; ix++)
10686 lon[ix] = ctl->prof_lon0 + dlon * (ix + 0.5);
10687 for (int iy = 0; iy < ctl->prof_ny; iy++) {
10688 lat[iy] = ctl->prof_lat0 + dlat * (iy + 0.5);
10689 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
10690 }
10691 }
10692
10693 /* Set time interval... */
10694 const double t0 = t - 0.5 * ctl->dt_mod;
10695 const double t1 = t + 0.5 * ctl->dt_mod;
10696
10697 /* Allocate... */
10698 ALLOC(mass, double,
10699 ctl->prof_nx * ctl->prof_ny * ctl->prof_nz);
10700 ALLOC(obsmean, double,
10701 ctl->prof_nx * ctl->prof_ny);
10702 ALLOC(obscount, int,
10703 ctl->prof_nx * ctl->prof_ny);
10704
10705 /* Loop over observations... */
10706 for (int i = 0; i < nobs; i++) {
10707
10708 /* Check time... */
10709 if (rt[i] < t0)
10710 continue;
10711 else if (rt[i] >= t1)
10712 break;
10713
10714 /* Check observation data... */
10715 if (!isfinite(robs[i]))
10716 continue;
10717
10718 /* Calculate indices... */
10719 int ix = (int) ((rlon[i] - ctl->prof_lon0) / dlon);
10720 int iy = (int) ((rlat[i] - ctl->prof_lat0) / dlat);
10721
10722 /* Check indices... */
10723 if (ix < 0 || ix >= ctl->prof_nx || iy < 0 || iy >= ctl->prof_ny)
10724 continue;
10725
10726 /* Get mean observation index... */
10727 int idx = ARRAY_2D(ix, iy, ctl->prof_ny);
10728 obsmean[idx] += robs[i];
10729 obscount[idx]++;
10730 }
10731
10732 /* Analyze model data... */
10733 for (ip = 0; ip < atm->np; ip++) {
10734
10735 /* Check time... */
10736 if (atm->time[ip] < t0 || atm->time[ip] > t1)
10737 continue;
10738
10739 /* Get indices... */
10740 int ix = (int) ((atm->lon[ip] - ctl->prof_lon0) / dlon);
10741 int iy = (int) ((atm->lat[ip] - ctl->prof_lat0) / dlat);
10742 int iz = (int) ((Z(atm->p[ip]) - ctl->prof_z0) / dz);
10743
10744 /* Check indices... */
10745 if (ix < 0 || ix >= ctl->prof_nx ||
10746 iy < 0 || iy >= ctl->prof_ny || iz < 0 || iz >= ctl->prof_nz)
10747 continue;
10748
10749 /* Get total mass in grid cell... */
10750 int idx = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
10751 mass[idx] += atm->q[ctl->qnt_m][ip];
10752 }
10753
10754 /* Extract profiles... */
10755 for (int ix = 0; ix < ctl->prof_nx; ix++)
10756 for (int iy = 0; iy < ctl->prof_ny; iy++) {
10757 int idx2 = ARRAY_2D(ix, iy, ctl->prof_ny);
10758 if (obscount[idx2] > 0) {
10759
10760 /* Check profile... */
10761 okay = 0;
10762 for (int iz = 0; iz < ctl->prof_nz; iz++) {
10763 int idx3 = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
10764 if (mass[idx3] > 0) {
10765 okay = 1;
10766 break;
10767 }
10768 }
10769 if (!okay)
10770 continue;
10771
10772 /* Write output... */
10773 fprintf(out, "\n");
10774
10775 /* Loop over altitudes... */
10776 for (int iz = 0; iz < ctl->prof_nz; iz++) {
10777
10778 /* Get temperature, water vapor, and ozone... */
10780 intpol_met_time_3d(met0, met0->t, met1, met1->t, t, press[iz],
10781 lon[ix], lat[iy], &temp, ci, cw, 1);
10782 intpol_met_time_3d(met0, met0->h2o, met1, met1->h2o, t, press[iz],
10783 lon[ix], lat[iy], &h2o, ci, cw, 0);
10784 intpol_met_time_3d(met0, met0->o3, met1, met1->o3, t, press[iz],
10785 lon[ix], lat[iy], &o3, ci, cw, 0);
10786
10787 /* Calculate volume mixing ratio... */
10788 const int idx3 = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
10789 vmr = MA / ctl->molmass * mass[idx3]
10790 / (RHO(press[iz], temp) * area[iy] * dz * 1e9);
10791
10792 /* Write output... */
10793 fprintf(out, "%.2f %g %g %g %g %g %g %g %g %g %d\n",
10794 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
10795 obsmean[idx2] / obscount[idx2], obscount[idx2]);
10796 }
10797 }
10798 }
10799
10800 /* Free... */
10801 free(mass);
10802 free(obsmean);
10803 free(obscount);
10804
10805 /* Finalize... */
10806 if (t == ctl->t_stop) {
10807
10808 /* Close output file... */
10809 fclose(out);
10810
10811 /* Free... */
10812 free(lon);
10813 free(lat);
10814 free(area);
10815 free(z);
10816 free(press);
10817 free(rt);
10818 free(rz);
10819 free(rlon);
10820 free(rlat);
10821 free(robs);
10822 }
10823}
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 10827 of file mptrac.c.

10833 {
10834
10835 static FILE *out;
10836
10837 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[EP],
10838 kw[EP];
10839
10840 static int nobs, nk;
10841
10842 /* Set timer... */
10843 SELECT_TIMER("WRITE_SAMPLE", "OUTPUT", NVTX_WRITE);
10844
10845 /* Init... */
10846 if (t == ctl->t_start) {
10847
10848 /* Allocate... */
10849 ALLOC(rt, double,
10850 NOBS);
10851 ALLOC(rz, double,
10852 NOBS);
10853 ALLOC(rlon, double,
10854 NOBS);
10855 ALLOC(rlat, double,
10856 NOBS);
10857 ALLOC(robs, double,
10858 NOBS);
10859
10860 /* Read observation data... */
10861 read_obs(ctl->sample_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
10862
10863 /* Read kernel data... */
10864 if (ctl->sample_kernel[0] != '-')
10865 read_kernel(ctl->sample_kernel, kz, kw, &nk);
10866
10867 /* Create output file... */
10868 LOG(1, "Write sample data: %s", filename);
10869 if (!(out = fopen(filename, "w")))
10870 ERRMSG("Cannot create file!");
10871
10872 /* Write header... */
10873 fprintf(out,
10874 "# $1 = time [s]\n"
10875 "# $2 = altitude [km]\n"
10876 "# $3 = longitude [deg]\n"
10877 "# $4 = latitude [deg]\n"
10878 "# $5 = surface area [km^2]\n"
10879 "# $6 = layer depth [km]\n"
10880 "# $7 = number of particles [1]\n"
10881 "# $8 = column density [kg/m^2]\n"
10882 "# $9 = volume mixing ratio [ppv]\n"
10883 "# $10 = observed BT index [K]\n\n");
10884
10885 /* Set latitude range, squared radius, and area... */
10886 dlat = DY2DEG(ctl->sample_dx);
10887 rmax2 = SQR(ctl->sample_dx);
10888 area = M_PI * rmax2;
10889 }
10890
10891 /* Set time interval for output... */
10892 const double t0 = t - 0.5 * ctl->dt_mod;
10893 const double t1 = t + 0.5 * ctl->dt_mod;
10894
10895 /* Loop over observations... */
10896 for (int i = 0; i < nobs; i++) {
10897
10898 /* Check time... */
10899 if (rt[i] < t0)
10900 continue;
10901 else if (rt[i] >= t1)
10902 break;
10903
10904 /* Calculate Cartesian coordinates... */
10905 double x0[3];
10906 geo2cart(0, rlon[i], rlat[i], x0);
10907
10908 /* Set pressure range... */
10909 const double rp = P(rz[i]);
10910 const double ptop = P(rz[i] + ctl->sample_dz);
10911 const double pbot = P(rz[i] - ctl->sample_dz);
10912
10913 /* Init... */
10914 double mass = 0;
10915 int np = 0;
10916
10917 /* Loop over air parcels... */
10918 //#pragma omp parallel for default(shared) reduction(+:mass,np)
10919 for (int ip = 0; ip < atm->np; ip++) {
10920
10921 /* Check time... */
10922 if (atm->time[ip] < t0 || atm->time[ip] > t1)
10923 continue;
10924
10925 /* Check latitude... */
10926 if (fabs(rlat[i] - atm->lat[ip]) > dlat)
10927 continue;
10928
10929 /* Check horizontal distance... */
10930 double x1[3];
10931 geo2cart(0, atm->lon[ip], atm->lat[ip], x1);
10932 if (DIST2(x0, x1) > rmax2)
10933 continue;
10934
10935 /* Check pressure... */
10936 if (ctl->sample_dz > 0)
10937 if (atm->p[ip] > pbot || atm->p[ip] < ptop)
10938 continue;
10939
10940 /* Add mass... */
10941 if (ctl->qnt_m >= 0)
10942 mass +=
10943 kernel_weight(kz, kw, nk, atm->p[ip]) * atm->q[ctl->qnt_m][ip];
10944 np++;
10945 }
10946
10947 /* Calculate column density... */
10948 const double cd = mass / (1e6 * area);
10949
10950 /* Calculate volume mixing ratio... */
10951 double vmr = 0;
10952 if (ctl->molmass > 0 && ctl->sample_dz > 0) {
10953 if (mass > 0) {
10954
10955 /* Get temperature... */
10956 double temp;
10958 intpol_met_time_3d(met0, met0->t, met1, met1->t, rt[i], rp,
10959 rlon[i], rlat[i], &temp, ci, cw, 1);
10960
10961 /* Calculate volume mixing ratio... */
10962 vmr = MA / ctl->molmass * cd / (RHO(rp, temp) * ctl->sample_dz * 1e3);
10963 }
10964 } else
10965 vmr = NAN;
10966
10967 /* Write output... */
10968 fprintf(out, "%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
10969 rlon[i], rlat[i], area, ctl->sample_dz, np, cd, vmr, robs[i]);
10970 }
10971
10972 /* Finalize...... */
10973 if (t == ctl->t_stop) {
10974
10975 /* Close output file... */
10976 fclose(out);
10977
10978 /* Free... */
10979 free(rt);
10980 free(rz);
10981 free(rlon);
10982 free(rlat);
10983 free(robs);
10984 }
10985}
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 10989 of file mptrac.c.

10993 {
10994
10995 static FILE *out;
10996
10997 static double rmax2, x0[3], x1[3];
10998
10999 /* Set timer... */
11000 SELECT_TIMER("WRITE_STATION", "OUTPUT", NVTX_WRITE);
11001
11002 /* Init... */
11003 if (t == ctl->t_start) {
11004
11005 /* Write info... */
11006 LOG(1, "Write station data: %s", filename);
11007
11008 /* Create new file... */
11009 if (!(out = fopen(filename, "w")))
11010 ERRMSG("Cannot create file!");
11011
11012 /* Write header... */
11013 fprintf(out,
11014 "# $1 = time [s]\n"
11015 "# $2 = altitude [km]\n"
11016 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11017 for (int iq = 0; iq < ctl->nq; iq++)
11018 fprintf(out, "# $%i = %s [%s]\n", (iq + 5),
11019 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
11020 fprintf(out, "\n");
11021
11022 /* Set geolocation and search radius... */
11023 geo2cart(0, ctl->stat_lon, ctl->stat_lat, x0);
11024 rmax2 = SQR(ctl->stat_r);
11025 }
11026
11027 /* Set time interval for output... */
11028 const double t0 = t - 0.5 * ctl->dt_mod;
11029 const double t1 = t + 0.5 * ctl->dt_mod;
11030
11031 /* Loop over air parcels... */
11032 for (int ip = 0; ip < atm->np; ip++) {
11033
11034 /* Check time... */
11035 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11036 continue;
11037
11038 /* Check time range for station output... */
11039 if (atm->time[ip] < ctl->stat_t0 || atm->time[ip] > ctl->stat_t1)
11040 continue;
11041
11042 /* Check station flag... */
11043 if (ctl->qnt_stat >= 0)
11044 if ((int) atm->q[ctl->qnt_stat][ip])
11045 continue;
11046
11047 /* Get Cartesian coordinates... */
11048 geo2cart(0, atm->lon[ip], atm->lat[ip], x1);
11049
11050 /* Check horizontal distance... */
11051 if (DIST2(x0, x1) > rmax2)
11052 continue;
11053
11054 /* Set station flag... */
11055 if (ctl->qnt_stat >= 0)
11056 atm->q[ctl->qnt_stat][ip] = 1;
11057
11058 /* Write data... */
11059 fprintf(out, "%.2f %g %g %g",
11060 atm->time[ip], Z(atm->p[ip]), atm->lon[ip], atm->lat[ip]);
11061 for (int iq = 0; iq < ctl->nq; iq++) {
11062 fprintf(out, " ");
11063 fprintf(out, ctl->qnt_format[iq], atm->q[iq][ip]);
11064 }
11065 fprintf(out, "\n");
11066 }
11067
11068 /* Close file... */
11069 if (t == ctl->t_stop)
11070 fclose(out);
11071}
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 11075 of file mptrac.c.

11079 {
11080
11081 FILE *out;
11082
11083 /* Set timer... */
11084 SELECT_TIMER("WRITE_VTK", "OUTPUT", NVTX_WRITE);
11085
11086 /* Write info... */
11087 LOG(1, "Write VTK data: %s", filename);
11088
11089 /* Set time interval for output... */
11090 const double t0 = t - 0.5 * ctl->dt_mod;
11091 const double t1 = t + 0.5 * ctl->dt_mod;
11092
11093 /* Create file... */
11094 if (!(out = fopen(filename, "w")))
11095 ERRMSG("Cannot create file!");
11096
11097 /* Count data points... */
11098 int np = 0;
11099 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
11100 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11101 continue;
11102 np++;
11103 }
11104
11105 /* Write header... */
11106 fprintf(out,
11107 "# vtk DataFile Version 3.0\n"
11108 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
11109
11110 /* Write point coordinates... */
11111 fprintf(out, "POINTS %d float\n", np);
11112 if (ctl->vtk_sphere) {
11113 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
11114 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11115 continue;
11116 const double radius = (RE + Z(atm->p[ip]) * ctl->vtk_scale
11117 + ctl->vtk_offset) / RE;
11118 const double coslat = cos(DEG2RAD(atm->lat[ip]));
11119 const double x = radius * coslat * cos(DEG2RAD(atm->lon[ip]));
11120 const double y = radius * coslat * sin(DEG2RAD(atm->lon[ip]));
11121 const double z = radius * sin(DEG2RAD(atm->lat[ip]));
11122 fprintf(out, "%g %g %g\n", x, y, z);
11123 }
11124 } else
11125 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
11126 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11127 continue;
11128 fprintf(out, "%g %g %g\n", atm->lon[ip], atm->lat[ip],
11129 Z(atm->p[ip]) * ctl->vtk_scale + ctl->vtk_offset);
11130 }
11131
11132 /* Write point data... */
11133 fprintf(out, "POINT_DATA %d\n", np);
11134 for (int iq = 0; iq < ctl->nq; iq++) {
11135 fprintf(out, "SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
11136 ctl->qnt_name[iq]);
11137 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
11138 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11139 continue;
11140 fprintf(out, "%g\n", atm->q[iq][ip]);
11141 }
11142 }
11143
11144 /* Close file... */
11145 fclose(out);
11146}