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

MPTRAC library declarations. More...

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

Go to the source code of this file.

Data Structures

struct  ctl_t
 Control parameters. More...
 
struct  atm_t
 Air parcel data. More...
 
struct  particle_t
 Particle data. More...
 
struct  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...
 
struct  dd_t
 Domain decomposition data structure. More...
 

Macros

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

Functions

void broadcast_large_data (void *data, size_t N)
 Broadcasts large data across all processes in an MPI communicator. More...
 
void cart2geo (const double *x, double *z, double *lon, double *lat)
 Converts Cartesian coordinates to geographic coordinates. More...
 
double clim_oh (const ctl_t *ctl, const clim_t *clim, const double t, const double lon, const double lat, const double p)
 Calculates the hydroxyl radical (OH) concentration from climatology data, with an optional diurnal correction based on solar zenith angle. More...
 
void clim_oh_diurnal_correction (const ctl_t *ctl, clim_t *clim)
 Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data. More...
 
double clim_photo (const double rate[CP][CSZA][CO3], const clim_photo_t *photo, const double p, const double sza, const double o3c)
 Calculates the photolysis rate for a given set of atmospheric conditions. More...
 
double clim_tropo (const clim_t *clim, const double t, const double lat)
 Calculates the tropopause pressure based on climatological data. More...
 
void clim_tropo_init (clim_t *clim)
 Initializes the tropopause data in the climatology structure. More...
 
double clim_ts (const clim_ts_t *ts, const double t)
 Interpolates a time series of climatological variables. More...
 
double clim_zm (const clim_zm_t *zm, const double t, const double lat, const double p)
 Interpolates monthly mean zonal mean climatological variables. More...
 
void compress_cms (const ctl_t *ctl, const char *varname, float *array, const size_t nx, const size_t ny, const size_t np, const double *plev, const int decompress, FILE *inout)
 Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm. More...
 
void compress_pck (const char *varname, float *array, const size_t nxy, const size_t nz, const int decompress, FILE *inout)
 Compresses or decompresses a 3D array of floats. More...
 
void compress_sz3 (const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
 Compresses or decompresses a 3-D float array using the SZ3 library. More...
 
void compress_zfp (const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
 Compresses or decompresses a 3D array of floats using the ZFP library. More...
 
void compress_zstd (const char *varname, float *array, const size_t n, const int decompress, const int level, FILE *inout)
 Compresses or decompresses a float array using Zstandard (ZSTD). More...
 
double cos_sza (const double sec, const double lon, const double lat)
 Calculates the cosine of the solar zenith angle. More...
 
void day2doy (const int year, const int mon, const int day, int *doy)
 Get day of year from date. More...
 
void dd_assign_rect_subdomains_atm (atm_t *atm, ctl_t *ctl, dd_t *dd, int init)
 Assign atmospheric particles to rectangular subdomains. More...
 
void dd_atm2particles (atm_t *atm, particle_t *particles, ctl_t *ctl, int *nparticles, cache_t *cache, int rank)
 Extracts particles from an atmospheric state and prepares them for inter-domain transfer. More...
 
int dd_calc_subdomain_from_coords (double lon, double lat, met_t *met, ctl_t *ctl, int mpi_size, int nx_glob, int ny_glob)
 Computes the destination subdomain (MPI rank) for a particle based on its geographic coordinates. More...
 
void dd_communicate_particles (particle_t *particles, int *nparticles, MPI_Datatype MPI_Particle, int *neighbours, int nneighbours, ctl_t ctl)
 Communicates particles between MPI processes. More...
 
void dd_get_rect_neighbour (const ctl_t ctl, dd_t *dd)
 Determines rectangular neighbouring ranks for MPI processes. More...
 
int dd_init (ctl_t *ctl, dd_t *dd, atm_t *atm)
 Initializes domain decomposition for parallel processing. More...
 
int dd_is_periodic_longitude (met_t *met, int nx_glob)
 Check whether the longitude grid is periodic (global coverage). More...
 
void dd_particles2atm (atm_t *atm, particle_t *particles, ctl_t *ctl, int *nparticles, cache_t *cache)
 Converts particle data to atmospheric data. More...
 
void dd_register_MPI_type_particle (MPI_Datatype *MPI_Particle)
 Registers a custom MPI datatype for particle structures. More...
 
void dd_sort (const ctl_t *ctl, met_t *met0, atm_t *atm, dd_t *dd, int *nparticles, int *rank)
 Sort particles according to box index and target rank for neighbours. More...
 
void dd_sort_help (double *a, dd_t *dd, const int np)
 Reorder an array according to a permutation vector. More...
 
void doy2day (const int year, const int doy, int *mon, int *day)
 Converts a given day of the year (DOY) to a date (month and day). More...
 
void fft_help (double *fcReal, double *fcImag, const int n)
 Computes the Fast Fourier Transform (FFT) of a complex sequence. More...
 
void geo2cart (const double z, const double lon, const double lat, double *x)
 Converts geographic coordinates (longitude, latitude, altitude) to Cartesian coordinates. More...
 
void get_met_help (const ctl_t *ctl, const double t, const int direct, const char *metbase, const double dt_met, char *filename)
 Generates a formatted filename for meteorological data files based on the input parameters. More...
 
void get_met_replace (char *orig, char *search, char *repl)
 Replaces occurrences of a substring in a string with another substring. More...
 
void get_tropo (const int met_tropo, ctl_t *ctl, clim_t *clim, met_t *met, const double *lons, const int nx, const double *lats, const int ny, double *pt, double *zt, double *tt, double *qt, double *o3t, double *ps, double *zs)
 Calculate tropopause data. More...
 
void intpol_check_lon_lat (const double *lons, const int nlon, const double *lats, const int nlat, const double lon, const double lat, double *lon2, double *lat2)
 Adjusts longitude and latitude to ensure they fall within valid bounds. More...
 
void intpol_met_4d_zeta (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_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_2d (const met_t *met0, float array0[EX][EY], const met_t *met1, float array1[EX][EY], const double ts, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
 Interpolates meteorological data in 2D space and time. More...
 
void intpol_tropo_3d (const double time0, float array0[EX][EY], const double time1, float array1[EX][EY], const double lons[EX], const double lats[EY], const int nlon, const int nlat, const double time, const double lon, const double lat, const int method, double *var, double *sigma)
 Interpolates tropopause data in 3D (latitude, longitude, and time). More...
 
void jsec2time (const double jsec, int *year, int *mon, int *day, int *hour, int *min, int *sec, double *remain)
 Converts Julian seconds to calendar date and time components. More...
 
double kernel_weight (const double kz[EP], const double kw[EP], const int nk, const double p)
 Calculates the kernel weight based on altitude and given kernel data. More...
 
double lapse_rate (const double t, const double h2o)
 Calculates the moist adiabatic lapse rate in Kelvin per kilometer. More...
 
void level_definitions (ctl_t *ctl)
 Defines pressure levels for meteorological data. More...
 
int locate_irr (const double *xx, const int n, const double x)
 Locate the index of the interval containing a given value in a sorted array. More...
 
int locate_irr_float (const float *xx, const int n, const double x, const int ig)
 Locate the index of the interval containing a given value in an irregularly spaced array. More...
 
int locate_reg (const double *xx, const int n, const double x)
 Locate the index of the interval containing a given value in a regular grid. More...
 
void locate_vert (float profiles[EX][EY][EP], const int np, const int lon_ap_ind, const int lat_ap_ind, const double alt_ap, int *ind)
 Locate the four vertical indizes of a box for a given height value. More...
 
void module_advect (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Advances particle positions using different advection schemes. More...
 
void module_advect_init (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Initializes the advection module by setting up pressure fields. More...
 
void module_bound_cond (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Apply boundary conditions to particles based on meteorological and climatological data. More...
 
void module_chem_grid (const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double t)
 Computes gridded chemical tracer concentrations (volume mixing ratio) from individual air parcel mass data and assigns them back to the parcels. More...
 
void module_chem_init (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Initializes the chemistry modules by setting atmospheric composition. More...
 
void module_convection (const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Performs convective mixing of atmospheric particles. More...
 
void module_dd (ctl_t *ctl, atm_t *atm, cache_t *cache, dd_t *dd, met_t **met)
 Manages domain decomposition and particle communication in parallel processing. More...
 
void module_decay (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, atm_t *atm)
 Simulate exponential decay processes for atmospheric particles. More...
 
void module_diff_meso (const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Simulate mesoscale diffusion for atmospheric particles. More...
 
void module_diff_pbl (const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Computes particle diffusion within the planetary boundary layer (PBL). More...
 
void module_diff_turb (const ctl_t *ctl, cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Applies turbulent diffusion processes to atmospheric particles. More...
 
void module_dry_depo (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Simulate dry deposition of atmospheric particles. More...
 
void module_h2o2_chem (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Perform chemical reactions involving H2O2 within cloud particles. More...
 
void module_isosurf_init (const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Initialize the isosurface module based on atmospheric data. More...
 
void module_isosurf (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Apply the isosurface module to adjust atmospheric properties. More...
 
void module_kpp_chem (ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 KPP chemistry module. More...
 
void module_meteo (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Update atmospheric properties using meteorological data. More...
 
void module_mixing (const ctl_t *ctl, const clim_t *clim, atm_t *atm, const double t)
 Update atmospheric properties through interparcel mixing. More...
 
void module_mixing_help (const ctl_t *ctl, const clim_t *clim, atm_t *atm, const int *ixs, const int *iys, const int *izs, const int qnt_idx, const int use_ensemble)
 Perform subgrid-scale interparcel mixing of a given quantity. More...
 
void module_oh_chem (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Perform hydroxyl chemistry calculations for atmospheric particles. More...
 
void module_position (const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Update the positions and pressure levels of atmospheric particles. More...
 
void module_rng_init (const int ntask)
 Initialize random number generators for parallel tasks. More...
 
void module_rng (const ctl_t *ctl, double *rs, const size_t n, const int method)
 Generate random numbers using various methods and distributions. More...
 
void module_sedi (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Simulate sedimentation of particles in the atmosphere. More...
 
void module_sort (const ctl_t *ctl, met_t *met0, atm_t *atm)
 Sort particles according to box index. More...
 
void module_sort_help (double *a, const int *p, const int np)
 Reorder an array based on a given permutation. More...
 
void module_timesteps (const ctl_t *ctl, cache_t *cache, met_t *met0, atm_t *atm, const double t)
 Calculate time steps for air parcels based on specified conditions. More...
 
void module_timesteps_init (ctl_t *ctl, const atm_t *atm)
 Initialize start time and time interval for time-stepping. More...
 
void module_tracer_chem (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Simulate chemical reactions involving long-lived atmospheric tracers. More...
 
void module_wet_depo (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Perform wet deposition calculations for air parcels. More...
 
void mptrac_alloc (ctl_t **ctl, cache_t **cache, clim_t **clim, met_t **met0, met_t **met1, atm_t **atm, dd_t **dd)
 Allocates and initializes memory resources for MPTRAC. More...
 
void mptrac_free (ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm, dd_t *dd)
 Frees memory resources allocated for MPTRAC. More...
 
void mptrac_get_met (ctl_t *ctl, clim_t *clim, const double t, met_t **met0, met_t **met1, dd_t *dd)
 Retrieves meteorological data for the specified time. More...
 
void mptrac_init (ctl_t *ctl, cache_t *cache, clim_t *clim, atm_t *atm, const int ntask)
 Initializes the MPTRAC model and its associated components. More...
 
int mptrac_read_atm (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads air parcel data from a specified file into the given atmospheric structure. More...
 
void mptrac_read_clim (const ctl_t *ctl, clim_t *clim)
 Reads various climatological data and populates the given climatology structure. More...
 
void mptrac_read_ctl (const char *filename, int argc, char *argv[], ctl_t *ctl)
 Reads control parameters from a configuration file and populates the given structure. More...
 
int mptrac_read_met (const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met, dd_t *dd)
 Reads meteorological data from a file, supporting multiple formats and MPI broadcasting. More...
 
void mptrac_run_timestep (ctl_t *ctl, cache_t *cache, clim_t *clim, met_t **met0, met_t **met1, atm_t *atm, double t, dd_t *dd)
 Executes a single timestep of the MPTRAC model simulation. More...
 
void mptrac_write_atm (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes air parcel data to a file in various formats. More...
 
void mptrac_write_met (const char *filename, const ctl_t *ctl, met_t *met)
 Writes meteorological data to a file, supporting multiple formats and compression options. More...
 
void mptrac_write_output (const char *dirname, const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double t)
 Writes various types of output data to files in a specified directory. More...
 
void mptrac_update_device (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
 Updates device memory for specified data structures. More...
 
void mptrac_update_host (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
 Updates host memory for specified data structures. More...
 
double nat_temperature (const double p, const double h2o, const double hno3)
 Calculates the nitric acid trihydrate (NAT) temperature. More...
 
double pbl_weight (const ctl_t *ctl, const atm_t *atm, const int ip, const double pbl, const double ps)
 Computes a weighting factor based on planetary boundary layer pressure. More...
 
int read_atm_asc (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads air parcel data from an ASCII file and populates the given atmospheric structure. More...
 
int read_atm_bin (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads air parcel data from a binary file and populates the given atmospheric structure. More...
 
int read_atm_clams (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads atmospheric data from a CLAMS NetCDF file. More...
 
int read_atm_nc (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads air parcel data from a generic netCDF file and populates the given atmospheric structure. More...
 
void read_clim_photo (const char *filename, clim_photo_t *photo)
 Reads photolysis rates from a NetCDF file and populates the given photolysis structure. More...
 
void read_clim_photo_help (const int ncid, const char *varname, const clim_photo_t *photo, double var[CP][CSZA][CO3])
 Reads a 3D climatological photochemistry variable from a NetCDF file. More...
 
int read_clim_ts (const char *filename, clim_ts_t *ts)
 Reads a climatological time series from a file and populates the given time series structure. More...
 
void read_clim_zm (const char *filename, const char *varname, clim_zm_t *zm)
 Reads zonally averaged climatological data from a netCDF file and populates the given structure. More...
 
void read_kernel (const char *filename, double kz[EP], double kw[EP], int *nk)
 Reads kernel function data from a file and populates the provided arrays. More...
 
int read_met_bin (const char *filename, const ctl_t *ctl, met_t *met)
 Reads meteorological data from a binary file. More...
 
void read_met_bin_2d (FILE *in, const met_t *met, float var[EX][EY], const char *varname)
 Reads a 2-dimensional meteorological variable from a binary file and stores it in the provided array. More...
 
void read_met_bin_3d (FILE *in, const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname, const float bound_min, const float bound_max)
 Reads 3D meteorological data from a binary file, potentially using different compression methods. More...
 
void read_met_cape (const ctl_t *ctl, const clim_t *clim, met_t *met)
 Calculates Convective Available Potential Energy (CAPE) for each grid point. More...
 
void read_met_cloud (met_t *met)
 Calculates cloud-related variables for each grid point. More...
 
void read_met_detrend (const ctl_t *ctl, met_t *met)
 Detrends meteorological data. More...
 
void read_met_extrapolate (met_t *met)
 Extrapolates meteorological data. More...
 
void read_met_geopot (const ctl_t *ctl, met_t *met)
 Calculates geopotential heights from meteorological data. More...
 
int read_met_grib (const char *filename, const ctl_t *ctl, met_t *met)
 Reads meteorological data from a grib file and processes it. More...
 
void read_met_grib_grid (codes_handle **handles, int count_handles, met_t *met)
 Reads global meteorological information from a grib file. More...
 
void read_met_grib_levels (codes_handle **handles, const int num_messages, const ctl_t *ctl, met_t *met)
 Reads meteorological variables at different vertical levels from a grib file. More...
 
void read_met_grib_surface (codes_handle **handles, const int num_messages, const ctl_t *ctl, met_t *met)
 Reads surface meteorological data from a grib file and stores it in the meteorological data structure. More...
 
void read_met_ml2pl (const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname)
 Interpolates meteorological data to specified pressure levels. More...
 
void read_met_monotonize (const ctl_t *ctl, met_t *met)
 Makes zeta and pressure profiles monotone. More...
 
int read_met_nc (const char *filename, const ctl_t *ctl, met_t *met, dd_t *dd)
 Reads meteorological data from a NetCDF file and processes it. More...
 
void read_met_nc_grid (const char *filename, const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
 Reads meteorological grid data from NetCDF files with domain decomposition. More...
 
void read_met_nc_grid_dd_naive (dd_t *dd, const ctl_t *ctl, met_t *met, const int ncid)
 Read meteorological grid data from a NetCDF file and set up subdomain decomposition with halos. More...
 
void read_met_nc_levels (const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
 Reads and processes meteorological level data from NetCDF files with domain decomposition. More...
 
void read_met_nc_surface (const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
 Reads and processes surface meteorological data from NetCDF files with domain decomposition. More...
 
int read_met_nc_2d (const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const char *varname5, const char *varname6, const ctl_t *ctl, const met_t *met, dd_t *dd, 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, dd_t *dd, float dest[EX][EY][EP], const float scl)
 Reads a 3-dimensional meteorological variable from a NetCDF file. More...
 
void read_met_pbl (const ctl_t *ctl, met_t *met)
 Computes the planetary boundary layer (PBL) pressure based on meteorological data. More...
 
void read_met_periodic (met_t *met)
 Applies periodic boundary conditions to meteorological data along longitudinal axis. More...
 
void read_met_polar_winds (met_t *met)
 Applies a fix for polar winds in meteorological data. More...
 
void read_met_pv (met_t *met)
 Calculates potential vorticity (PV) from meteorological data. More...
 
void read_met_ozone (met_t *met)
 Calculates the total column ozone from meteorological ozone data. More...
 
void read_met_sample (const ctl_t *ctl, met_t *met)
 Downsamples meteorological data based on specified parameters. More...
 
void read_met_tropo (const ctl_t *ctl, const clim_t *clim, met_t *met)
 Calculates the tropopause and related meteorological variables based on various methods and stores the results in the meteorological data structure. More...
 
void read_obs (const char *filename, const ctl_t *ctl, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
 Reads observation data from a file and stores it in arrays. More...
 
void read_obs_asc (const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
 Reads observation data from an ASCII file. More...
 
void read_obs_nc (const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
 Reads observation data from a NetCDF file. More...
 
double scan_ctl (const char *filename, int argc, char *argv[], const char *varname, const int arridx, const char *defvalue, char *value)
 Scans a control file or command-line arguments for a specified variable. More...
 
double sedi (const double p, const double T, const double rp, const double rhop)
 Calculates the sedimentation velocity of a particle in air. More...
 
void spline (const double *x, const double *y, const int n, const double *x2, double *y2, const int n2, const int method)
 Performs spline interpolation or linear interpolation. More...
 
float stddev (const float *data, const int n)
 Calculates the standard deviation of a set of data. More...
 
void time2jsec (const int year, const int mon, const int day, const int hour, const int min, const int sec, const double remain, double *jsec)
 Converts time components to seconds since January 1, 2000, 12:00:00 UTC. More...
 
void timer (const char *name, const char *group, const int output)
 Measures and reports elapsed time for named and grouped timers. More...
 
double time_from_filename (const char *filename, const int offset)
 Extracts and converts a timestamp from a filename to Julian seconds. More...
 
double tropo_weight (const clim_t *clim, const atm_t *atm, const int ip)
 Computes a weighting factor based on tropopause pressure. More...
 
void write_atm_asc (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes air parcel data to an ASCII file or gnuplot. More...
 
void write_atm_bin (const char *filename, const ctl_t *ctl, const atm_t *atm)
 Writes air parcel data to a binary file. More...
 
void write_atm_clams (const char *filename, const ctl_t *ctl, const atm_t *atm)
 Writes air parcel data to a NetCDF file in the CLaMS format. More...
 
void write_atm_clams_traj (const char *dirname, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes CLaMS trajectory data to a NetCDF file. More...
 
void write_atm_nc (const char *filename, const ctl_t *ctl, const atm_t *atm)
 Writes air parcel data to a NetCDF file. More...
 
void write_csi (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes Critical Success Index (CSI) data to a file. More...
 
void write_csi_ens (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes ensemble-based Critical Success Index (CSI) and other verification statistics to an output file. More...
 
void write_ens (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes ensemble data to a file. More...
 
void write_grid (const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
 Writes grid data to a file in ASCII or netCDF format. More...
 
void write_grid_asc (const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
 Writes grid data to an ASCII file. More...
 
void write_grid_nc (const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
 Writes grid data to a NetCDF file. More...
 
void write_met_bin (const char *filename, const ctl_t *ctl, met_t *met)
 Writes meteorological data in binary format to a specified file. More...
 
void write_met_bin_2d (FILE *out, met_t *met, float var[EX][EY], const char *varname)
 Writes a 2-dimensional meteorological variable to a binary file. More...
 
void write_met_bin_3d (FILE *out, const ctl_t *ctl, met_t *met, float var[EX][EY][EP], const char *varname, const int precision, const double tolerance)
 Writes a 3-dimensional meteorological variable to a binary file. More...
 
void write_met_nc (const char *filename, const ctl_t *ctl, met_t *met)
 Writes meteorological data to a NetCDF file. More...
 
void write_met_nc_2d (const int ncid, const char *varname, met_t *met, float var[EX][EY], const float scl)
 Writes a 2D meteorological variable to a NetCDF file. More...
 
void write_met_nc_3d (const int ncid, const char *varname, met_t *met, float var[EX][EY][EP], const float scl)
 Writes a 3D meteorological variable to a NetCDF file. More...
 
void write_prof (const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
 Writes profile data to a specified file. More...
 
void write_sample (const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
 Writes sample data to a specified file. More...
 
void write_station (const char *filename, const ctl_t *ctl, atm_t *atm, const double t)
 Writes station data to a specified file. More...
 
void write_vtk (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes VTK (Visualization Toolkit) data to a specified file. More...
 

Detailed Description

MPTRAC library declarations.

Definition in file mptrac.h.

Macro Definition Documentation

◆ MPI_Datatype

#define MPI_Datatype   void*

Placeholder when MPI is not available.

Definition at line 145 of file mptrac.h.

◆ codes_handle

#define codes_handle   void*

Placeholder when ECCODES is not available.

Definition at line 190 of file mptrac.h.

◆ AVO

#define AVO   6.02214076e23

Avogadro constant [1/mol].

Definition at line 199 of file mptrac.h.

◆ CPD

#define CPD   1003.5

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

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

◆ G0

#define G0   9.80665

Standard gravity [m/s^2].

Definition at line 214 of file mptrac.h.

◆ H0

#define H0   7.0

Scale height [km].

Definition at line 219 of file mptrac.h.

◆ LV

#define LV   2501000.

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

Definition at line 224 of file mptrac.h.

◆ KARMAN

#define KARMAN   0.40

Karman's constant.

Definition at line 229 of file mptrac.h.

◆ KB

#define KB   1.3806504e-23

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

Definition at line 234 of file mptrac.h.

◆ MA

#define MA   28.9644

Molar mass of dry air [g/mol].

Definition at line 239 of file mptrac.h.

◆ MH2O

#define MH2O   18.01528

Molar mass of water vapor [g/mol].

Definition at line 244 of file mptrac.h.

◆ MO3

#define MO3   48.00

Molar mass of ozone [g/mol].

Definition at line 249 of file mptrac.h.

◆ P0

#define P0   1013.25

Standard pressure [hPa].

Definition at line 254 of file mptrac.h.

◆ RA

#define RA   (1e3 * RI / MA)

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

Definition at line 259 of file mptrac.h.

◆ RE

#define RE   6367.421

Mean radius of Earth [km].

Definition at line 264 of file mptrac.h.

◆ RI

#define RI   8.3144598

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

Definition at line 269 of file mptrac.h.

◆ T0

#define T0   273.15

Standard temperature [K].

Definition at line 274 of file mptrac.h.

◆ EP

#define EP   140

Maximum number of pressure levels for meteo data.

Definition at line 283 of file mptrac.h.

◆ EX

#define EX   1444

Maximum number of longitudes for meteo data.

Definition at line 288 of file mptrac.h.

◆ EY

#define EY   724

Maximum number of latitudes for meteo data.

Definition at line 293 of file mptrac.h.

◆ LEN

#define LEN   5000

Maximum length of ASCII data lines.

Definition at line 298 of file mptrac.h.

◆ METVAR

#define METVAR   13

Number of 3-D meteorological variables.

Definition at line 303 of file mptrac.h.

◆ NP

#define NP   10000000

Maximum number of atmospheric data points.

Definition at line 308 of file mptrac.h.

◆ NQ

#define NQ   15

Maximum number of quantities per data point.

Definition at line 313 of file mptrac.h.

◆ NCSI

#define NCSI   1000000

Maximum number of data points for CSI calculation.

Definition at line 318 of file mptrac.h.

◆ NENS

#define NENS   2000

Maximum number of data points for ensemble analysis.

Definition at line 323 of file mptrac.h.

◆ NOBS

#define NOBS   10000000

Maximum number of observation data points.

Definition at line 328 of file mptrac.h.

◆ NTHREADS

#define NTHREADS   512

Maximum number of OpenMP threads.

Definition at line 333 of file mptrac.h.

◆ CY

#define CY   250

Maximum number of latitudes for climatological data.

Definition at line 338 of file mptrac.h.

◆ CO3

#define CO3   30

Maximum number of total column ozone data for climatological data.

Definition at line 343 of file mptrac.h.

◆ CP

#define CP   70

Maximum number of pressure levels for climatological data.

Definition at line 348 of file mptrac.h.

◆ CSZA

#define CSZA   50

Maximum number of solar zenith angles for climatological data.

Definition at line 353 of file mptrac.h.

◆ CT

#define CT   12

Maximum number of time steps for climatological data.

Definition at line 358 of file mptrac.h.

◆ CTS

#define CTS   1000

Maximum number of data points of climatological time series.

Definition at line 363 of file mptrac.h.

◆ DD_NPART

#define DD_NPART   100000

Maximum number of particles to send and recieve in domain decomposition.

Definition at line 368 of file mptrac.h.

◆ DD_NNMAX

#define DD_NNMAX   26

Maximum number of neighbours to communicate with in domain decomposition.

Definition at line 373 of file mptrac.h.

◆ DD_NPOLE

#define DD_NPOLE   -2

Constant indicating the North pole [-].

Definition at line 378 of file mptrac.h.

◆ DD_SPOLE

#define DD_SPOLE   -3

Constant indicating the South pole [-].

Definition at line 383 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 416 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 439 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 458 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 483 of file mptrac.h.

◆ CLAMP

#define CLAMP (   v,
  lo,
  hi 
)     (((v) < (lo)) ? (lo) : (((v) > (hi)) ? (hi) : (v)))

Clamp a value to a specified range.

Ensures that v lies between lo and hi. If v < lo, returns lo. If v > hi, returns hi. Otherwise, returns v unchanged.

This macro works with any numeric type (e.g., int, float, double). All arguments are evaluated exactly once — avoid passing expressions with side effects (e.g., ++ operators or function calls).

Parameters
vInput value to clamp.
loLower bound.
hiUpper bound.
Returns
The clamped value between lo and hi.
Author
Lars Hoffmann

Definition at line 505 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 529 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 550 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 567 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 592 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:264
#define DEG2RAD(deg)
Converts degrees to radians.
Definition: mptrac.h:567

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 614 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 632 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 651 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 667 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 683 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 699 of file mptrac.h.

◆ ECC

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

Execute an ECCODES command and check for errors.

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

Parameters
cmdECCODES command to execute.
Author
Nils Nobre Wittwer

Definition at line 713 of file mptrac.h.

◆ ECC_READ_2D

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

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

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

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

Definition at line 732 of file mptrac.h.

◆ ECC_READ_3D

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

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

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

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

Definition at line 755 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 780 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 798 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 818 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 833 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:2458

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 847 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:2429

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 864 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 883 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 937 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:259
#define G0
Standard gravity [m/s^2].
Definition: mptrac.h:214

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 991 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 1010 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 1037 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 1051 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 1138 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 1153 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 1167 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:298

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 1196 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:2010

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

◆ NC_INQ_DIM

#define NC_INQ_DIM (   dimname,
  ptr,
  min,
  max,
  check 
)
Value:
{ \
int dimid; size_t naux; \
NC(nc_inq_dimid(ncid, dimname, &dimid)); \
NC(nc_inq_dimlen(ncid, dimid, &naux)); \
*ptr = (int)naux; \
if (check) \
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.
checkFlag to check bounds. Set to 1 for bounds check.
Author
Lars Hoffmann
Jan Clemens

Definition at line 1256 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 1280 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 1304 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 1327 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 1349 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 1366 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 1386 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 1413 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 1443 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 1467 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 1491 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 1518 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 1535 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 1565 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 1595 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 1620 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 1639 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 1662 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 1683 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 1696 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 1710 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:1518
#define T0
Standard temperature [K].
Definition: mptrac.h:274

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 1734 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 1759 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 1783 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 1812 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:2043

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 1833 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 1858 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 1880 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:1858
#define MA
Molar mass of dry air [g/mol].
Definition: mptrac.h:239
#define RI
Ideal gas constant [J/(mol K)].
Definition: mptrac.h:269

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 1911 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:1783

Computes the value of the zeta vertical coordinate.

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

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

Definition at line 1930 of file mptrac.h.

◆ LOGLEV

#define LOGLEV   2

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

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

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 1973 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 2010 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 2043 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 2078 of file mptrac.h.

◆ NTIMER

#define NTIMER   100

Maximum number of timers.

Definition at line 2087 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 2102 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 2123 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 2142 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 2157 of file mptrac.h.

◆ NVTX_PUSH

#define NVTX_PUSH (   range_title,
  range_color 
)    {}

Definition at line 2249 of file mptrac.h.

◆ NVTX_POP

#define NVTX_POP   {}

Definition at line 2250 of file mptrac.h.

Function Documentation

◆ broadcast_large_data()

void broadcast_large_data ( void *  data,
size_t  N 
)

Broadcasts large data across all processes in an MPI communicator.

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

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

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

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

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

◆ cart2geo()

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

Converts Cartesian coordinates to geographic coordinates.

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

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

Converts Cartesian coordinates to geographic coordinates.

Definition at line 74 of file mptrac.c.

78 {
79
80 const double radius = sqrt(DOTP(x, x));
81
82 *lat = RAD2DEG(asin(x[2] / radius));
83 *lon = RAD2DEG(atan2(x[1], x[0]));
84 *z = radius - RE;
85}
#define DOTP(a, b)
Calculate the dot product of two vectors.
Definition: mptrac.h:699
#define RAD2DEG(rad)
Converts radians to degrees.
Definition: mptrac.h:1535

◆ clim_oh()

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

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

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

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

Definition at line 89 of file mptrac.c.

95 {
96
97 /* Set SZA threshold... */
98 const double sza_thresh = DEG2RAD(85.), csza_thresh = cos(sza_thresh);
99
100 /* Get OH data from climatology... */
101 const double oh = clim_zm(&clim->oh, t, lat, p);
102
103 /* Check beta... */
104 if (ctl->oh_chem_beta <= 0)
105 return oh;
106
107 /* Apply diurnal correction... */
108 const double csza = cos_sza(t, lon, lat);
109 const double denom = (csza >= csza_thresh) ? csza : csza_thresh;
110 return oh * exp(-ctl->oh_chem_beta / denom);
111}
double cos_sza(const double sec, const double lon, const double lat)
Calculates the cosine of the solar zenith angle.
Definition: mptrac.c:1010
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:405
clim_zm_t oh
OH zonal means.
Definition: mptrac.h:3516
double oh_chem_beta
Beta parameter for diurnal variablity of OH.
Definition: mptrac.h:2983
Here is the call graph for this function:

◆ clim_oh_diurnal_correction()

void clim_oh_diurnal_correction ( const ctl_t ctl,
clim_t clim 
)

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

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

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

Definition at line 115 of file mptrac.c.

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

◆ clim_photo()

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

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

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

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

This function performs the following steps:

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

Definition at line 147 of file mptrac.c.

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

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

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

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

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

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

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

◆ compress_sz3()

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

Compresses or decompresses a 3-D float array using the SZ3 library.

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

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

◆ compress_zfp()

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

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

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

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

The function performs the following steps:

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

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

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

◆ compress_zstd()

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

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

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

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

◆ cos_sza()

double cos_sza ( const double  sec,
const double  lon,
const double  lat 
)

Calculates the cosine of the solar zenith angle.

This function computes the cosine of the solar zenith angle (SZA), which describes the angle between the local zenith (straight up) and the line connecting the observer to the center of the Sun. The cosine of the SZA is often used directly in radiative transfer and photochemical calculations to avoid unnecessary use of trigonometric inverse functions.

Parameters
secSeconds elapsed since 2000-01-01T12:00Z.
lonObserver's longitude in degrees.
latObserver's latitude in degrees.
Returns
The cosine of the solar zenith angle (dimensionless, range [-1, 1]).

The cosine of the solar zenith angle is computed based on the observer's position (longitude and latitude) and the specified time in seconds elapsed since 2000-01-01T12:00Z.

Note
The input longitude and latitude must be specified in degrees.
See also
acos() — can be used to convert the returned value to the solar zenith angle in radians if needed.
Author
Lars Hoffmann

Definition at line 1010 of file mptrac.c.

1013 {
1014
1015 /* Number of days and fraction with respect to 2000-01-01T12:00Z... */
1016 const double D = sec / 86400 - 0.5;
1017
1018 /* Geocentric apparent ecliptic longitude [rad]... */
1019 const double g = DEG2RAD(357.529 + 0.98560028 * D);
1020 const double q = 280.459 + 0.98564736 * D;
1021 const double L = DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
1022
1023 /* Mean obliquity of the ecliptic [rad]... */
1024 const double e = DEG2RAD(23.439 - 0.00000036 * D);
1025
1026 /* Declination [rad]... */
1027 const double sindec = sin(e) * sin(L);
1028
1029 /* Right ascension [rad]... */
1030 const double ra = atan2(cos(e) * sin(L), cos(L));
1031
1032 /* Greenwich Mean Sidereal Time [h]... */
1033 const double GMST = 18.697374558 + 24.06570982441908 * D;
1034
1035 /* Local Sidereal Time [h]... */
1036 const double LST = GMST + lon / 15;
1037
1038 /* Hour angle [rad]... */
1039 const double h = LST / 12 * M_PI - ra;
1040
1041 /* Convert latitude... */
1042 const double lat_help = DEG2RAD(lat);
1043
1044 /* Return cosine of solar zenith angle... */
1045 return sin(lat_help) * sindec + cos(lat_help) * sqrt(1 -
1046 SQR(sindec)) * cos(h);
1047}
#define SQR(x)
Compute the square of a value.
Definition: mptrac.h:1696

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

1055 {
1056
1057 const int
1058 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1059 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1060
1061 /* Get day of year... */
1062 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
1063 *doy = d0l[mon - 1] + day - 1;
1064 else
1065 *doy = d0[mon - 1] + day - 1;
1066}

◆ dd_assign_rect_subdomains_atm()

void dd_assign_rect_subdomains_atm ( atm_t atm,
ctl_t ctl,
dd_t dd,
int  init 
)

Assign atmospheric particles to rectangular subdomains.

This function classifies particles in an atmospheric model into subdomains defined by the domain decomposition (dd). Depending on whether this is the initial assignment (init != 0) or a subsequent reclassification, it either:

  • Assigns each particle to the local subdomain based on longitude and latitude coordinates.
  • Updates particle destinations when they cross subdomain boundaries, using neighbor information.

Longitude values are wrapped into the [0, 360) range to ensure consistency, and boundary conditions at the left and right edges of the domain are handled explicitly. Particles falling outside the subdomain bounds are marked with -1 during initialization.

Parameters
[in,out]atmPointer to an atm_t structure containing particle data:
  • atm->lon, atm->lat : particle coordinates
  • atm->q : classification arrays, indexed by ctl->qnt_subdomain and ctl->qnt_destination.
[in]ctlPointer to a ctl_t structure containing control parameters, including subdomain indices and query IDs (e.g., ctl->qnt_subdomain).
[in]ddPointer to a dd_t structure containing decomposition information:
  • rank, size
  • longitude/latitude subdomain bounds
  • neighbor ranks (dd->neighbours).
[in]initFlag indicating whether this is the initial assignment (init != 0) or a reclassification (init == 0).
Note
  • Parallelization is supported with OpenACC if compiled with _OPENACC.
  • Neighbor indices in dd->neighbours follow a directional convention (left, right, up, down, and diagonals).
  • Particles that do not belong to any subdomain are set to -1 during initialization.
  • Optional logic for handling particles at the poles is provided but currently disabled.
Author
Jan Clemens

◆ dd_atm2particles()

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

Extracts particles from an atmospheric state and prepares them for inter-domain transfer.

This routine scans the atmospheric arrays for particles that should be transferred to another MPI/OpenMP/OpenACC rank (i.e., particles whose destination subdomain differs from the current rank). For each such particle, the function copies its prognostic variables (time, position, pressure, tracers) into the particles buffer and marks the particle in the atmospheric fields as inactive by setting its subdomain flag to -1.

Additionally, the particle's timestep entry in cache is reset so that the receiving process can re-initialize it.

If compiled with OpenACC, the function also manages the corresponding device data movement for particles and nparticles, and performs the selection loop on the accelerator.

Parameters
[in,out]atmPointer to the atmospheric state. Particle properties (time, lon, lat, pressure, tracer fields) are read from this structure. The particle’s subdomain field is overwritten and set to -1 for particles selected for transfer.
[out]particlesOutput buffer where selected particles are copied. The array must be allocated to hold at least *nparticles entries. Indexing is relative to atm->np.
[in]ctlModel control structure containing metadata such as the number of tracers (ctl->nq), and indices of relevant tracer fields (ctl->qnt_destination, ctl->qnt_subdomain).
[in,out]nparticlesOn input, the number of particles to inspect (particles with indices [atm->np, atm->np + *nparticles)).
On output, unchanged. Device copies may be created or updated when using OpenACC.
[in,out]cacheCache structure used to store per-particle timestep values. For each particle selected for transfer, cache->dt[ip] is set to 0.
[in]rankRank of the current processing unit. Particles whose destination field does not match rank are selected for transfer.
Note
Particle selection criteria:
  • atm->q[ctl->qnt_destination][ip] != rank
  • destination index >= 0
  • subdomain index >= 0
The function logs each particle prepared for transfer (verbosity level 3).
Warning
This routine modifies the atmospheric arrays in place. Any subsequent operations should treat selected particles as removed/inactive until they are reconstructed or replaced by incoming particles.
Author
Jan Clemens

◆ dd_calc_subdomain_from_coords()

int dd_calc_subdomain_from_coords ( double  lon,
double  lat,
met_t met,
ctl_t ctl,
int  mpi_size,
int  nx_glob,
int  ny_glob 
)

Computes the destination subdomain (MPI rank) for a particle based on its geographic coordinates.

This function determines which distributed-memory subdomain a particle belongs to, given its longitude and latitude. It performs several steps:

  • Wraps longitude into the canonical range [0, 360).
  • Wraps latitudes that cross the poles (>90 or <−90 degrees) by reflecting them across the poles and applying a 180° longitude shift.
  • Determines the global coordinate ranges from the provided meteorological grid (met).
  • Computes zonal and meridional subdomain indices based on uniform partitioning of the global grid into `ctl->dd_subdomains_zonal × ctl->dd_subdomains_meridional` tiles.
  • Clamps the resulting indices to valid ranges.
  • Converts the 2-D subdomain index (lon × lat) into a 1-D MPI rank index.

The rank is finally clamped into the valid range [0, mpi_size-1].

Parameters
[in]lonInput longitude in degrees. May lie outside [0, 360). Values are wrapped.
[in]latInput latitude in degrees. May lie outside the range [−90, 90].
Values past the poles are wrapped and the longitude is flipped accordingly.
[in]metPointer to meteorological grid information. Only the longitude and latitude arrays (met->lon[], met->lat[]) are used to determine the global range of coordinates.
[in]ctlModel control structure. Provides the number of zonal and meridional subdomains (ctl->dd_subdomains_zonal, ctl->dd_subdomains_meridional) used for domain decomposition.
[in]mpi_sizeNumber of MPI ranks participating in the simulation. The computed target rank is clamped to [0, mpi_size - 1].
[in]nx_globNumber of global longitude points in met->lon. Used to compute the global longitude range.
[in]ny_globNumber of global latitude points in met->lat. Used to compute the global latitude range.
Returns
The MPI rank (subdomain ID) corresponding to the provided coordinates. Guaranteed to be in the range [0, mpi_size - 1].
Note
The function assumes a uniform partitioning of the global grid into rectangular longitude/latitude blocks.
Diagnostic information (wrapped coordinates, computed ranges, indices) is printed to stdout for debugging.
Author
Jan Clemens

◆ dd_communicate_particles()

void dd_communicate_particles ( particle_t particles,
int *  nparticles,
MPI_Datatype  MPI_Particle,
int *  neighbours,
int  nneighbours,
ctl_t  ctl 
)

Communicates particles between MPI processes.

The dd_communicate_particles function manages the communication of particle data between neighbouring MPI processes. It sends and receives particles to and from neighbouring ranks, handling the allocation and deallocation of buffers, and ensuring proper synchronization.

Parameters
particlesAn array of particle_t structures to be communicated.
nparticlesA pointer to an integer representing the number of particles.
MPI_ParticleAn MPI_Datatype representing the structure of a particle.
neighboursAn array of integers representing the neighbouring ranks.
nneighboursAn integer representing the number of neighbours.
ctlA control structure (ctl_t) containing configuration parameters.

The function performs the following steps:

  • Initializes buffers for sending and receiving particles.
  • Retrieves the MPI rank of the current process.
  • Uses non-blocking MPI communication to send and receive the number of particles and particle data.
  • Waits for all communication operations to complete.
  • Copies received particles into the local particle array.
  • Updates the number of particles after receiving.
  • Frees allocated buffers after communication is complete.
Note
This function assumes that the particles array and other parameters are properly initialized. It handles communication with neighbouring ranks, ignoring poles and empty signals. The function uses MPI non-blocking communication for efficiency.
Author
Jan Clemens

◆ dd_get_rect_neighbour()

void dd_get_rect_neighbour ( const ctl_t  ctl,
dd_t dd 
)

Determines rectangular neighbouring ranks for MPI processes.

The dd_get_rect_neighbour function calculates and assigns the neighbouring ranks for an MPI process based on its current rank and the configuration of subdomains. This is typically used in parallel computing to manage data decomposition and communication between processes arranged in a rectangular grid.

Parameters
ctlA control structure (ctl_t) containing configuration parameters for subdomains.
ddA pointer to an dd_t structure where neighbour information will be stored.

The function performs the following steps:

  • Uses conditional logic to determine the neighbours based on the current rank and subdomain configuration.
  • Assigns neighbour ranks to the neighbours array in the dd structure.
  • Handles edge cases for processes at the boundaries of the grid, such as poles or edges.
Note
This function assumes that the ctl and dd structures are properly initialized. The function considers different configurations for processes at the boundaries and handles them appropriately to ensure correct neighbour assignment.
Author
Jan Clemens

◆ dd_init()

int dd_init ( ctl_t ctl,
dd_t dd,
atm_t atm 
)

Initializes domain decomposition for parallel processing.

The dd_init function initializes the domain decomposition setup for parallel processing in a distributed computing environment. It ensures that the number of tasks matches the number of subdomains, registers a custom MPI datatype for particle structures, defines grid neighbours, and assigns particles to their respective subdomains.

Parameters
ctlA pointer to a ctl_t structure containing control parameters.
ddA pointer to an dd_t structure containing MPI information.
atmA pointer to an atm_t structure containing atmospheric data.

The function performs the following steps:

  • Checks if the number of tasks matches the number of subdomains.
  • Registers a custom MPI datatype for particle structures using dd_register_MPI_type_particle.
  • Defines grid neighbours for each MPI task using dd_get_rect_neighbour.
  • Assigns particles to their respective subdomains using dd_assign_rect_subdomains_atm.
  • Sets the initialization flag to indicate successful initialization.
Note
This function assumes that the ctl, dd, atm, and met structures are properly initialized. The function is typically called at the beginning of a parallel processing task to set up the environment.
Author
Jan Clemens

◆ dd_is_periodic_longitude()

int dd_is_periodic_longitude ( met_t met,
int  nx_glob 
)

Check whether the longitude grid is periodic (global coverage).

This function determines if the longitude array in met represents a global, periodic grid (covering 360°). It does so by computing the longitude spacing and testing whether the total range of longitudes plus one spacing approximately equals 360 degrees.

Parameters
[in]metPointer to a met_t structure containing the longitude array (met->lon).
[in]nx_globNumber of global longitude grid points.
Return values
1The longitude grid is periodic (global).
0The longitude grid is not periodic (regional).
Note
  • At least two longitude points are required; otherwise the function returns 0 (not periodic).
  • A tolerance of ±0.01° is used to account for floating-point rounding.
  • The logic used here is consistent with read_met_periodic().
Author
Jan Clemens

◆ dd_particles2atm()

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

Converts particle data to atmospheric data.

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

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

The function performs the following steps:

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

◆ dd_register_MPI_type_particle()

void dd_register_MPI_type_particle ( MPI_Datatype MPI_Particle)

Registers a custom MPI datatype for particle structures.

The dd_register_MPI_type_particle function creates and commits a custom MPI datatype that represents the structure of a particle (particle_t). This datatype is used for efficient communication of particle data in MPI operations.

Parameters
MPI_ParticleA pointer to an MPI_Datatype variable where the new datatype will be stored.

The function performs the following steps:

  • Defines an array of MPI datatypes corresponding to the types of the particle structure's fields.
  • Specifies the block lengths for each field in the particle structure.
  • Calculates the displacements of each field within the particle structure using the offsetof macro.
  • Creates a structured MPI datatype using MPI_Type_create_struct.
  • Commits the new MPI datatype using MPI_Type_commit.
Note
This function assumes that the particle_t structure is defined and accessible. The NQ constant should be defined to represent the number of quantities in the particle structure.
Author
Jan Clemens

◆ dd_sort()

void dd_sort ( const ctl_t ctl,
met_t met0,
atm_t atm,
dd_t dd,
int *  nparticles,
int *  rank 
)

Sort particles according to box index and target rank for neighbours.

The dd_sort function sorts particles within the atmospheric data structure (atm_t) based on their geographical coordinates (longitude and latitude) and pressure level. It also considers the target rank to which a particle will be sent. The function 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 atmospheric data structure.

Parameters
ctlA pointer to a ctl_t structure containing control parameters and settings.
met0A pointer to a met_t structure containing meteorological data at the current time step.
atmA pointer to an atm_t structure containing atmospheric data with particle information.
ddA pointer to an dd_t structure containing MPI information, including rank and neighbours.
nparticlesA pointer to an integer representing the number of particles to be sent.
rankA pointer to an integer storing the current MPI rank.

The function performs the following steps:

  • Allocates temporary arrays for sorting indices and values.
  • Computes a unique index for each particle based on its geographical coordinates and pressure level.
  • Uses parallel processing directives (OpenACC or OpenMP) to calculate these indices.
  • Sorts the particles based on the computed indices using a sorting library (e.g., Thrust).
  • Rearranges the atmospheric data arrays according to the sorted indices.
  • Counts the number of particles that need to be sent to other ranks and updates the particle count.
  • Frees the allocated temporary arrays.
Note
This function assumes that the ctl, met0, atm, nparticles, and rank parameters are properly initialized.
The function utilizes the locate_reg and locate_irr functions to determine the appropriate index for sorting particles.
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
Jan Clemens
Lars Hoffmann

◆ dd_sort_help()

void dd_sort_help ( double *  a,
dd_t dd,
const int  np 
)

Reorder an array according to a permutation vector.

This function reorders the contents of the array a using the permutation indices stored in dd->p. A temporary buffer (dd->help) is used to perform the reordering in two passes:

  • First, elements from a are copied into dd->help in permuted order.
  • Then, dd->help is copied back into a in sequential order.

Parallelization is supported with OpenACC or OpenMP, depending on compilation flags.

Parameters
[in,out]aPointer to the array of doubles to be reordered. On input, it contains the original data; on output, it contains the reordered data.
[in,out]ddPointer to a dd_t structure containing:
  • dd->p : permutation indices (size np)
  • dd->help : temporary buffer (size np)
[in]npNumber of elements in the array and permutation vector.
Note
  • The dd->p and dd->help arrays must be allocated with at least np elements.
  • Uses #pragma acc when compiled with OpenACC (_OPENACC defined), otherwise falls back to OpenMP.
Author
Jan Clemens

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

1897 {
1898
1899 const int
1900 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1901 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1902
1903 int i;
1904
1905 /* Get month and day... */
1906 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
1907 for (i = 11; i > 0; i--)
1908 if (d0l[i] <= doy)
1909 break;
1910 *mon = i + 1;
1911 *day = doy - d0l[i] + 1;
1912 } else {
1913 for (i = 11; i > 0; i--)
1914 if (d0[i] <= doy)
1915 break;
1916 *mon = i + 1;
1917 *day = doy - d0[i] + 1;
1918 }
1919}

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

1926 {
1927
1928 double data[2 * EX];
1929
1930 /* Check size... */
1931 if (n > EX)
1932 ERRMSG("Too many data points!");
1933
1934 /* Allocate... */
1935 gsl_fft_complex_wavetable *wavetable =
1936 gsl_fft_complex_wavetable_alloc((size_t) n);
1937 gsl_fft_complex_workspace *workspace =
1938 gsl_fft_complex_workspace_alloc((size_t) n);
1939
1940 /* Set data (real, complex)... */
1941 for (int i = 0; i < n; i++) {
1942 data[2 * i] = fcReal[i];
1943 data[2 * i + 1] = fcImag[i];
1944 }
1945
1946 /* Calculate FFT... */
1947 gsl_fft_complex_forward(data, 1, (size_t) n, wavetable, workspace);
1948
1949 /* Copy data... */
1950 for (int i = 0; i < n; i++) {
1951 fcReal[i] = data[2 * i];
1952 fcImag[i] = data[2 * i + 1];
1953 }
1954
1955 /* Free... */
1956 gsl_fft_complex_wavetable_free(wavetable);
1957 gsl_fft_complex_workspace_free(workspace);
1958}
#define EX
Maximum number of longitudes for meteo data.
Definition: mptrac.h:288

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

1966 {
1967
1968 const double radius = z + RE;
1969 const double latrad = DEG2RAD(lat);
1970 const double lonrad = DEG2RAD(lon);
1971 const double coslat = cos(latrad);
1972
1973 x[0] = radius * coslat * cos(lonrad);
1974 x[1] = radius * coslat * sin(lonrad);
1975 x[2] = radius * sin(latrad);
1976}

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

1986 {
1987
1988 char repl[LEN];
1989
1990 double t6, r;
1991
1992 int year, mon, day, hour, min, sec;
1993
1994 /* Round time to fixed intervals... */
1995 if (direct == -1)
1996 t6 = floor(t / dt_met) * dt_met;
1997 else
1998 t6 = ceil(t / dt_met) * dt_met;
1999
2000 /* Decode time... */
2001 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
2002
2003 /* Set filename of MPTRAC meteo files... */
2004 if (ctl->met_clams == 0) {
2005 if (ctl->met_type == 0)
2006 sprintf(filename, "%s_YYYY_MM_DD_HH.nc", metbase);
2007 else if (ctl->met_type == 1)
2008 sprintf(filename, "%s_YYYY_MM_DD_HH.bin", metbase);
2009 else if (ctl->met_type == 2)
2010 sprintf(filename, "%s_YYYY_MM_DD_HH.pck", metbase);
2011 else if (ctl->met_type == 3)
2012 sprintf(filename, "%s_YYYY_MM_DD_HH.zfp", metbase);
2013 else if (ctl->met_type == 4)
2014 sprintf(filename, "%s_YYYY_MM_DD_HH.zstd", metbase);
2015 else if (ctl->met_type == 5)
2016 sprintf(filename, "%s_YYYY_MM_DD_HH.cms", metbase);
2017 else if (ctl->met_type == 7)
2018 sprintf(filename, "%s_YYYY_MM_DD_HH.sz3", metbase);
2019 sprintf(repl, "%d", year);
2020 get_met_replace(filename, "YYYY", repl);
2021 sprintf(repl, "%02d", mon);
2022 get_met_replace(filename, "MM", repl);
2023 sprintf(repl, "%02d", day);
2024 get_met_replace(filename, "DD", repl);
2025 sprintf(repl, "%02d", hour);
2026 get_met_replace(filename, "HH", repl);
2027 }
2028
2029 /* Set filename of CLaMS meteo files... */
2030 else {
2031 sprintf(filename, "%s_YYMMDDHH.nc", metbase);
2032 sprintf(repl, "%d", year);
2033 get_met_replace(filename, "YYYY", repl);
2034 sprintf(repl, "%02d", year % 100);
2035 get_met_replace(filename, "YY", repl);
2036 sprintf(repl, "%02d", mon);
2037 get_met_replace(filename, "MM", repl);
2038 sprintf(repl, "%02d", day);
2039 get_met_replace(filename, "DD", repl);
2040 sprintf(repl, "%02d", hour);
2041 get_met_replace(filename, "HH", repl);
2042 }
2043}
void get_met_replace(char *orig, char *search, char *repl)
Replaces occurrences of a substring in a string with another substring.
Definition: mptrac.c:2047
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:2582
int met_clams
Read MPTRAC or CLaMS meteo data (0=MPTRAC, 1=CLaMS).
Definition: mptrac.h:2607
int met_type
Type of meteo data files (0=netCDF, 1=binary, 2=pck, 3=ZFP, 4=ZSTD, 5=cms, 6=grib,...
Definition: mptrac.h:2604
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 2047 of file mptrac.c.

2050 {
2051
2052 char buffer[LEN];
2053
2054 /* Iterate... */
2055 for (int i = 0; i < 3; i++) {
2056
2057 /* Replace sub-string... */
2058 char *ch;
2059 if (!(ch = strstr(orig, search)))
2060 return;
2061 strncpy(buffer, orig, (size_t) (ch - orig));
2062 buffer[ch - orig] = 0;
2063 sprintf(buffer + (ch - orig), "%s%s", repl, ch + strlen(search));
2064 orig[0] = 0;
2065 strcpy(orig, buffer);
2066 }
2067}

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

2086 {
2087
2089
2090 ctl->met_tropo = met_tropo;
2091 read_met_tropo(ctl, clim, met);
2092#pragma omp parallel for default(shared) private(ci,cw)
2093 for (int ix = 0; ix < nx; ix++)
2094 for (int iy = 0; iy < ny; iy++) {
2095 intpol_met_space_2d(met, met->pt, lons[ix], lats[iy],
2096 &pt[iy * nx + ix], ci, cw, 1);
2097 intpol_met_space_2d(met, met->ps, lons[ix], lats[iy],
2098 &ps[iy * nx + ix], ci, cw, 0);
2099 intpol_met_space_2d(met, met->zs, lons[ix], lats[iy],
2100 &zs[iy * nx + ix], ci, cw, 0);
2101 intpol_met_space_3d(met, met->z, pt[iy * nx + ix], lons[ix],
2102 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
2103 intpol_met_space_3d(met, met->t, pt[iy * nx + ix], lons[ix],
2104 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
2105 intpol_met_space_3d(met, met->h2o, pt[iy * nx + ix], lons[ix],
2106 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
2107 intpol_met_space_3d(met, met->o3, pt[iy * nx + ix], lons[ix],
2108 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
2109 }
2110}
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:2371
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:10678
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:2313
#define INTPOL_INIT
Initialize arrays for interpolation.
Definition: mptrac.h:833
int met_tropo
Tropopause definition (0=none, 1=clim, 2=cold point, 3=WMO_1st, 4=WMO_2nd, 5=dynamical).
Definition: mptrac.h:2743
float h2o[EX][EY][EP]
Water vapor volume mixing ratio [1].
Definition: mptrac.h:3680
float ps[EX][EY]
Surface pressure [hPa].
Definition: mptrac.h:3590
float zs[EX][EY]
Surface geopotential height [km].
Definition: mptrac.h:3596
float o3[EX][EY][EP]
Ozone volume mixing ratio [1].
Definition: mptrac.h:3683
float t[EX][EY][EP]
Temperature [K].
Definition: mptrac.h:3665
float pt[EX][EY]
Tropopause pressure [hPa].
Definition: mptrac.h:3623
float z[EX][EY][EP]
Geopotential height [km].
Definition: mptrac.h:3662
Here is the call graph for this function:

◆ intpol_check_lon_lat()

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

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

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

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

Definition at line 2114 of file mptrac.c.

2122 {
2123
2124 /* Check longitude... */
2125 *lon2 = FMOD(lon, 360.);
2126 if (*lon2 < lons[0])
2127 *lon2 += 360;
2128 else if (*lon2 > lons[nlon - 1])
2129 *lon2 -= 360;
2130
2131 /* Check latitude... */
2132 *lat2 = lat;
2133 if (lats[0] < lats[nlat - 1])
2134 *lat2 = MIN(MAX(*lat2, lats[0]), lats[nlat - 1]);
2135 else
2136 *lat2 = MIN(MAX(*lat2, lats[nlat - 1]), lats[0]);
2137}

◆ intpol_met_4d_zeta()

void intpol_met_4d_zeta ( 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 2141 of file mptrac.c.

2155 {
2156
2157 if (init) {
2158
2159 /* Check longitude and latitude... */
2160 double lon2, lat2;
2161 intpol_check_lon_lat(met0->lon, met0->nx, met0->lat, met0->ny, lon, lat,
2162 &lon2, &lat2);
2163
2164 /* Get horizontal indizes... */
2165 ci[0] = locate_reg(met0->lon, met0->nx, lon2);
2166 ci[1] = locate_irr(met0->lat, met0->ny, lat2);
2167
2168 /* Locate the vertical indizes for each edge of the column... */
2169 int ind[2][4];
2170 locate_vert(heights0, met0->npl, ci[0], ci[1], height, ind[0]);
2171 locate_vert(heights1, met1->npl, ci[0], ci[1], height, ind[1]);
2172
2173 /* Find minimum and maximum indizes... */
2174 ci[2] = ind[0][0];
2175 int k_max = ind[0][0];
2176 for (int i = 0; i < 2; i++)
2177 for (int j = 0; j < 4; j++) {
2178 if (ci[2] > ind[i][j])
2179 ci[2] = ind[i][j];
2180 if (k_max < ind[i][j])
2181 k_max = ind[i][j];
2182 }
2183
2184 /* Get weighting factors for time, longitude and latitude... */
2185 cw[3] = (ts - met0->time) / (met1->time - met0->time);
2186 cw[0] = (lon2 - met0->lon[ci[0]]) /
2187 (met0->lon[ci[0] + 1] - met0->lon[ci[0]]);
2188 cw[1] = (lat2 - met0->lat[ci[1]]) /
2189 (met0->lat[ci[1] + 1] - met0->lat[ci[1]]);
2190
2191 /* Interpolate in time at the lowest level... */
2192 double height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
2193 - heights0[ci[0]][ci[1]][ci[2]])
2194 + heights0[ci[0]][ci[1]][ci[2]];
2195 double height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
2196 - heights0[ci[0]][ci[1] + 1][ci[2]])
2197 + heights0[ci[0]][ci[1] + 1][ci[2]];
2198 double height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
2199 - heights0[ci[0] + 1][ci[1]][ci[2]])
2200 + heights0[ci[0] + 1][ci[1]][ci[2]];
2201 double height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
2202 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
2203 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
2204
2205 /* Interpolate in latitude direction... */
2206 double height0 = cw[1] * (height01 - height00) + height00;
2207 double height1 = cw[1] * (height11 - height10) + height10;
2208
2209 /* Interpolate in longitude direction... */
2210 double height_bot = cw[0] * (height1 - height0) + height0;
2211
2212 /* Interpolate in time at the upper level... */
2213 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2214 - heights0[ci[0]][ci[1]][ci[2] + 1])
2215 + heights0[ci[0]][ci[1]][ci[2] + 1];
2216 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2217 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2218 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2219 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2220 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2221 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2222 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2223 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2224 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2225
2226 /* Interpolate in latitude direction... */
2227 height0 = cw[1] * (height01 - height00) + height00;
2228 height1 = cw[1] * (height11 - height10) + height10;
2229
2230 /* Interpolate in longitude direction... */
2231 double height_top = cw[0] * (height1 - height0) + height0;
2232
2233 /* Search at higher levels if height is not in box... */
2234 while (((heights0[0][0][0] > heights0[0][0][1]) &&
2235 ((height_bot <= height) || (height_top > height))
2236 && (height_bot >= height) && (ci[2] < k_max))
2237 ||
2238 ((heights0[0][0][0] < heights0[0][0][1]) &&
2239 ((height_bot >= height) || (height_top < height))
2240 && (height_bot <= height) && (ci[2] < k_max))
2241 ) {
2242
2243 ci[2]++;
2244 height_bot = height_top;
2245
2246 /* Interpolate in time at the next level... */
2247 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2248 - heights0[ci[0]][ci[1]][ci[2] + 1])
2249 + heights0[ci[0]][ci[1]][ci[2] + 1];
2250 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2251 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2252 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2253 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2254 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2255 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2256 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2257 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2258 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2259
2260 /* Interpolate in latitude direction... */
2261 height0 = cw[1] * (height01 - height00) + height00;
2262 height1 = cw[1] * (height11 - height10) + height10;
2263
2264 /* Interpolate in longitude direction... */
2265 height_top = cw[0] * (height1 - height0) + height0;
2266 }
2267
2268 /* Get vertical weighting factors... */
2269 cw[2] = (height - height_bot)
2270 / (height_top - height_bot);
2271 }
2272
2273 /* Calculate the needed array values... */
2274 const double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
2275 - array0[ci[0]][ci[1]][ci[2]])
2276 + array0[ci[0]][ci[1]][ci[2]];
2277 const double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
2278 - array0[ci[0] + 1][ci[1]][ci[2]])
2279 + array0[ci[0] + 1][ci[1]][ci[2]];
2280 const double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
2281 - array0[ci[0]][ci[1] + 1][ci[2]])
2282 + array0[ci[0]][ci[1] + 1][ci[2]];
2283 const double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
2284 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
2285 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
2286 const double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
2287 - array0[ci[0]][ci[1]][ci[2] + 1])
2288 + array0[ci[0]][ci[1]][ci[2] + 1];
2289 const double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
2290 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
2291 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
2292 const double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
2293 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
2294 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
2295 const double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2296 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2297 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2298
2299 const double array00 = cw[0] * (array100 - array000) + array000;
2300 const double array10 = cw[0] * (array110 - array010) + array010;
2301 const double array01 = cw[0] * (array101 - array001) + array001;
2302 const double array11 = cw[0] * (array111 - array011) + array011;
2303
2304 const double aux0 = cw[1] * (array10 - array00) + array00;
2305 const double aux1 = cw[1] * (array11 - array01) + array01;
2306
2307 /* Interpolate vertically... */
2308 *var = cw[2] * (aux1 - aux0) + aux0;
2309}
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:2952
void intpol_check_lon_lat(const double *lons, const int nlon, const double *lats, const int nlat, const double lon, const double lat, double *lon2, double *lat2)
Adjusts longitude and latitude to ensure they fall within valid bounds.
Definition: mptrac.c:2114
int nx
Number of longitudes.
Definition: mptrac.h:3557
int ny
Number of latitudes.
Definition: mptrac.h:3560
double lon[EX]
Longitudes [deg].
Definition: mptrac.h:3569
int npl
Number of model levels.
Definition: mptrac.h:3566
double time
Time [s].
Definition: mptrac.h:3554
double lat[EY]
Latitudes [deg].
Definition: mptrac.h:3572
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 2313 of file mptrac.c.

2322 {
2323
2324 /* Initialize interpolation... */
2325 if (init) {
2326
2327 /* Check longitude and latitude... */
2328 double lon2, lat2;
2329 intpol_check_lon_lat(met->lon, met->nx, met->lat, met->ny, lon, lat,
2330 &lon2, &lat2);
2331
2332 /* Get interpolation indices... */
2333 ci[0] = locate_irr(met->p, met->np, p);
2334 ci[1] = locate_reg(met->lon, met->nx, lon2);
2335 ci[2] = locate_irr(met->lat, met->ny, lat2);
2336
2337 /* Get interpolation weights... */
2338 cw[0] = (met->p[ci[0] + 1] - p)
2339 / (met->p[ci[0] + 1] - met->p[ci[0]]);
2340 cw[1] = (met->lon[ci[1] + 1] - lon2)
2341 / (met->lon[ci[1] + 1] - met->lon[ci[1]]);
2342 cw[2] = (met->lat[ci[2] + 1] - lat2)
2343 / (met->lat[ci[2] + 1] - met->lat[ci[2]]);
2344 }
2345
2346 /* Interpolate vertically... */
2347 const double aux00 =
2348 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
2349 + array[ci[1]][ci[2]][ci[0] + 1];
2350 const double aux01 =
2351 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
2352 array[ci[1]][ci[2] + 1][ci[0] + 1])
2353 + array[ci[1]][ci[2] + 1][ci[0] + 1];
2354 const double aux10 =
2355 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
2356 array[ci[1] + 1][ci[2]][ci[0] + 1])
2357 + array[ci[1] + 1][ci[2]][ci[0] + 1];
2358 const double aux11 =
2359 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
2360 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
2361 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
2362
2363 /* Interpolate horizontally... */
2364 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
2365 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
2366 *var = cw[1] * (aux0 - aux1) + aux1;
2367}
int np
Number of pressure levels.
Definition: mptrac.h:3563
double p[EP]
Pressure levels [hPa].
Definition: mptrac.h:3575
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 2371 of file mptrac.c.

2379 {
2380
2381 /* Initialize interpolation... */
2382 if (init) {
2383
2384 /* Check longitude and latitude... */
2385 double lon2, lat2;
2386 intpol_check_lon_lat(met->lon, met->nx, met->lat, met->ny, lon, lat,
2387 &lon2, &lat2);
2388
2389 /* Get interpolation indices... */
2390 ci[1] = locate_reg(met->lon, met->nx, lon2);
2391 ci[2] = locate_irr(met->lat, met->ny, lat2);
2392
2393 /* Get interpolation weights... */
2394 cw[1] = (met->lon[ci[1] + 1] - lon2)
2395 / (met->lon[ci[1] + 1] - met->lon[ci[1]]);
2396 cw[2] = (met->lat[ci[2] + 1] - lat2)
2397 / (met->lat[ci[2] + 1] - met->lat[ci[2]]);
2398 }
2399
2400 /* Set variables... */
2401 const double aux00 = array[ci[1]][ci[2]];
2402 const double aux01 = array[ci[1]][ci[2] + 1];
2403 const double aux10 = array[ci[1] + 1][ci[2]];
2404 const double aux11 = array[ci[1] + 1][ci[2] + 1];
2405
2406 /* Interpolate horizontally... */
2407 if (isfinite(aux00) && isfinite(aux01)
2408 && isfinite(aux10) && isfinite(aux11)) {
2409 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
2410 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
2411 *var = cw[1] * (aux0 - aux1) + aux1;
2412 } else {
2413 if (cw[2] < 0.5) {
2414 if (cw[1] < 0.5)
2415 *var = aux11;
2416 else
2417 *var = aux01;
2418 } else {
2419 if (cw[1] < 0.5)
2420 *var = aux10;
2421 else
2422 *var = aux00;
2423 }
2424 }
2425}
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 2429 of file mptrac.c.

2441 {
2442
2443 double var0, var1;
2444
2445 /* Spatial interpolation... */
2446 intpol_met_space_3d(met0, array0, p, lon, lat, &var0, ci, cw, init);
2447 intpol_met_space_3d(met1, array1, p, lon, lat, &var1, ci, cw, 0);
2448
2449 /* Get weighting factor... */
2450 const double wt = (met1->time - ts) / (met1->time - met0->time);
2451
2452 /* Interpolate... */
2453 *var = wt * (var0 - var1) + var1;
2454}
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 2458 of file mptrac.c.

2469 {
2470
2471 double var0, var1;
2472
2473 /* Spatial interpolation... */
2474 intpol_met_space_2d(met0, array0, lon, lat, &var0, ci, cw, init);
2475 intpol_met_space_2d(met1, array1, lon, lat, &var1, ci, cw, 0);
2476
2477 /* Get weighting factor... */
2478 const double wt = (met1->time - ts) / (met1->time - met0->time);
2479
2480 /* Interpolate... */
2481 if (isfinite(var0) && isfinite(var1))
2482 *var = wt * (var0 - var1) + var1;
2483 else if (wt < 0.5)
2484 *var = var1;
2485 else
2486 *var = var0;
2487}
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 2491 of file mptrac.c.

2505 {
2506
2507 double mean = 0;
2508
2509 int n = 0;
2510
2511 /* Check longitude and latitude... */
2512 double lon2, lat2;
2513 intpol_check_lon_lat(lons, nlon, lats, nlat, lon, lat, &lon2, &lat2);
2514
2515 /* Get indices... */
2516 const int ix = locate_reg(lons, (int) nlon, lon2);
2517 const int iy = locate_irr(lats, (int) nlat, lat2);
2518
2519 /* Calculate standard deviation... */
2520 *sigma = 0;
2521 for (int dx = 0; dx < 2; dx++)
2522 for (int dy = 0; dy < 2; dy++) {
2523 if (isfinite(array0[ix + dx][iy + dy])) {
2524 mean += array0[ix + dx][iy + dy];
2525 *sigma += SQR(array0[ix + dx][iy + dy]);
2526 n++;
2527 }
2528 if (isfinite(array1[ix + dx][iy + dy])) {
2529 mean += array1[ix + dx][iy + dy];
2530 *sigma += SQR(array1[ix + dx][iy + dy]);
2531 n++;
2532 }
2533 }
2534 if (n > 0)
2535 *sigma = sqrt(MAX(*sigma / n - SQR(mean / n), 0.0));
2536
2537 /* Linear interpolation... */
2538 if (method == 1 && isfinite(array0[ix][iy])
2539 && isfinite(array0[ix][iy + 1])
2540 && isfinite(array0[ix + 1][iy])
2541 && isfinite(array0[ix + 1][iy + 1])
2542 && isfinite(array1[ix][iy])
2543 && isfinite(array1[ix][iy + 1])
2544 && isfinite(array1[ix + 1][iy])
2545 && isfinite(array1[ix + 1][iy + 1])) {
2546
2547 const double aux00 = LIN(lons[ix], array0[ix][iy],
2548 lons[ix + 1], array0[ix + 1][iy], lon2);
2549 const double aux01 = LIN(lons[ix], array0[ix][iy + 1],
2550 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
2551 const double aux0 = LIN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
2552
2553 const double aux10 = LIN(lons[ix], array1[ix][iy],
2554 lons[ix + 1], array1[ix + 1][iy], lon2);
2555 const double aux11 = LIN(lons[ix], array1[ix][iy + 1],
2556 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
2557 const double aux1 = LIN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
2558
2559 *var = LIN(time0, aux0, time1, aux1, time);
2560 }
2561
2562 /* Nearest neighbor interpolation... */
2563 else {
2564 const double aux00 = NN(lons[ix], array0[ix][iy],
2565 lons[ix + 1], array0[ix + 1][iy], lon2);
2566 const double aux01 = NN(lons[ix], array0[ix][iy + 1],
2567 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
2568 const double aux0 = NN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
2569
2570 const double aux10 = NN(lons[ix], array1[ix][iy],
2571 lons[ix + 1], array1[ix + 1][iy], lon2);
2572 const double aux11 = NN(lons[ix], array1[ix][iy + 1],
2573 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
2574 const double aux1 = NN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
2575
2576 *var = NN(time0, aux0, time1, aux1, time);
2577 }
2578}
#define NN(x0, y0, x1, y1, x)
Perform nearest-neighbor interpolation.
Definition: mptrac.h:1386
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 2582 of file mptrac.c.

2590 {
2591
2592 struct tm t0, *t1;
2593
2594 t0.tm_year = 100;
2595 t0.tm_mon = 0;
2596 t0.tm_mday = 1;
2597 t0.tm_hour = 0;
2598 t0.tm_min = 0;
2599 t0.tm_sec = 0;
2600
2601 const time_t jsec0 = (time_t) jsec + timegm(&t0);
2602 t1 = gmtime(&jsec0);
2603
2604 *year = t1->tm_year + 1900;
2605 *mon = t1->tm_mon + 1;
2606 *day = t1->tm_mday;
2607 *hour = t1->tm_hour;
2608 *min = t1->tm_min;
2609 *sec = t1->tm_sec;
2610 *remain = jsec - floor(jsec);
2611}

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

2619 {
2620
2621 /* Check number of data points... */
2622 if (nk < 2)
2623 return 1.0;
2624
2625 /* Get altitude... */
2626 const double z = Z(p);
2627
2628 /* Get weighting factor... */
2629 if (z < kz[0])
2630 return kw[0];
2631 else if (z > kz[nk - 1])
2632 return kw[nk - 1];
2633 else {
2634 const int idx = locate_irr(kz, nk, z);
2635 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
2636 }
2637}
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 2641 of file mptrac.c.

2643 {
2644
2645 /*
2646 Calculate moist adiabatic lapse rate [K/km] from temperature [K]
2647 and water vapor volume mixing ratio [1].
2648
2649 Reference: https://en.wikipedia.org/wiki/Lapse_rate
2650 */
2651
2652 const double a = RA * SQR(t), r = SH(h2o) / (1. - SH(h2o));
2653
2654 return 1e3 * G0 * (a + LV * r * t) / (CPD * a + SQR(LV) * r * EPS);
2655}
#define SH(h2o)
Compute specific humidity from water vapor volume mixing ratio.
Definition: mptrac.h:1683
#define LV
Latent heat of vaporization of water [J/kg].
Definition: mptrac.h:224
#define EPS
Ratio of the specific gas constant of dry air and water vapor [1].
Definition: mptrac.h:209
#define CPD
Specific heat of dry air at constant pressure [J/(kg K)].
Definition: mptrac.h:204

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

2660 {
2661
2662 if (0 == ctl->met_press_level_def) {
2663
2664 ctl->met_np = 138;
2665
2666 const double press[138] = {
2667 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
2668 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
2669 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
2670 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
2671 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2672 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
2673 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
2674 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
2675 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
2676 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
2677 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
2678 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
2679 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
2680 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
2681 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
2682 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
2683 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
2684 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
2685 1010.8487, 1013.2500, 1044.45
2686 };
2687
2688 for (int ip = 0; ip < ctl->met_np; ip++)
2689 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
2690
2691 } else if (1 == ctl->met_press_level_def) {
2692
2693 ctl->met_np = 92;
2694
2695 const double press[92] = {
2696 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
2697 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
2698 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
2699 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
2700 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
2701 113.6382,
2702 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
2703 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
2704 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
2705 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
2706 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
2707 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
2708 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
2709 1007.4431, 1010.8487, 1013.2500, 1044.45
2710 };
2711
2712 for (int ip = 0; ip < ctl->met_np; ip++)
2713 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
2714
2715 } else if (2 == ctl->met_press_level_def) {
2716
2717 ctl->met_np = 60;
2718
2719 const double press[60] = {
2720 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
2721 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
2722 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
2723 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
2724 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
2725 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
2726 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
2727 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1044.45
2728 };
2729
2730 for (int ip = 0; ip < ctl->met_np; ip++)
2731 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
2732
2733 } else if (3 == ctl->met_press_level_def) {
2734
2735 ctl->met_np = 147;
2736
2737 const double press[147] = {
2738 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
2739 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
2740 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
2741 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
2742 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2743 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
2744 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
2745 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
2746 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
2747 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
2748 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
2749 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
2750 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
2751 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
2752 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
2753 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
2754 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
2755 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
2756 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73, 1028.85,
2757 1031.97,
2758 1035.09, 1038.21, 1041.33, 1044.45
2759 };
2760
2761 for (int ip = 0; ip < ctl->met_np; ip++)
2762 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
2763
2764 } else if (4 == ctl->met_press_level_def) {
2765
2766 ctl->met_np = 101;
2767
2768 const double press[101] = {
2769 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
2770 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
2771 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
2772 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
2773 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
2774 113.6382,
2775 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
2776 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
2777 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
2778 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
2779 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
2780 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
2781 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
2782 1007.4431, 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73,
2783 1028.85, 1031.97,
2784 1035.09, 1038.21, 1041.33, 1044.45
2785 };
2786
2787 for (int ip = 0; ip < ctl->met_np; ip++)
2788 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
2789
2790 } else if (5 == ctl->met_press_level_def) {
2791
2792 ctl->met_np = 62;
2793
2794 const double press[62] = {
2795 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
2796 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
2797 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
2798 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
2799 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
2800 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
2801 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
2802 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1034.86, 1039.65,
2803 1044.45
2804 };
2805
2806 for (int ip = 0; ip < ctl->met_np; ip++)
2807 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
2808
2809 } else if (6 == ctl->met_press_level_def) {
2810
2811 ctl->met_np = 137;
2812
2813 const double press[137] = {
2814 0.01, 0.02, 0.031, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861,
2815 0.2499, 0.3299, 0.4288, 0.5496, 0.6952, 0.869, 1.0742,
2816 1.3143, 1.5928, 1.9134, 2.2797, 2.6954, 3.1642, 3.6898,
2817 4.2759, 4.9262, 5.6441, 6.4334, 7.2974, 8.2397, 9.2634,
2818 10.372, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945, 18.9752,
2819 20.761, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2820 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.199, 54.5299,
2821 57.9834, 61.5607, 65.2695, 69.1187, 73.1187, 77.281, 81.6182,
2822 86.145, 90.8774, 95.828, 101.005, 106.415, 112.068, 117.971,
2823 124.134, 130.564, 137.27, 144.262, 151.549, 159.14, 167.045,
2824 175.273, 183.834, 192.739, 201.997, 211.619, 221.615, 231.995,
2825 242.772, 253.955, 265.556, 277.585, 290.055, 302.976, 316.361,
2826 330.22, 344.566, 359.411, 374.767, 390.645, 407.058, 424.019,
2827 441.539, 459.632, 478.31, 497.584, 517.42, 537.72, 558.343,
2828 579.193, 600.167, 621.162, 642.076, 662.808, 683.262, 703.347,
2829 722.979, 742.086, 760.6, 778.466, 795.64, 812.085, 827.776,
2830 842.696, 856.838, 870.2, 882.791, 894.622, 905.712, 916.081,
2831 925.757, 934.767, 943.14, 950.908, 958.104, 965.299, 972.495,
2832 979.69, 986.886, 994.081, 1001.28, 1008.47, 1015.67, 1022.86,
2833 1030.06, 1037.25, 1044.45
2834 };
2835
2836 for (int ip = 0; ip < ctl->met_np; ip++)
2837 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
2838
2839 } else if (7 == ctl->met_press_level_def) {
2840
2841 ctl->met_np = 59;
2842
2843 const double press[59] = {
2844 0.1, 0.2, 0.3843, 0.6365, 0.9564, 1.3448, 1.8058, 2.3478,
2845 2.985, 3.7397, 4.6462, 5.7565, 7.1322, 8.8366, 10.9483,
2846 13.5647, 16.8064, 20.8227, 25.7989, 31.9642, 39.6029, 49.0671,
2847 60.1802, 73.0663, 87.7274, 104.229, 122.614, 142.902, 165.089,
2848 189.147, 215.025, 242.652, 272.059, 303.217, 336.044, 370.407,
2849 406.133, 443.009, 480.791, 519.209, 557.973, 596.777, 635.306,
2850 673.24, 710.263, 746.063, 780.346, 812.83, 843.263, 871.42,
2851 897.112, 920.189, 940.551, 958.148, 975.744, 993.341, 1010.94,
2852 1028.53, 1046.13
2853 };
2854
2855 for (int ip = 0; ip < ctl->met_np; ip++)
2856 ctl->met_p[ctl->met_np - ip - 1] = press[ip];
2857
2858 } else {
2859 ERRMSG("Use 0 for l137, 1 for l91, 2 for l60 or values between 3 and 7.");
2860 }
2861
2862 if (ctl->met_np > EP) {
2863 ERRMSG("Recompile with larger EP to use this pressure level definition.");
2864 }
2865}
int met_press_level_def
Use predefined pressure levels or not.
Definition: mptrac.h:2709
int met_np
Number of target pressure levels.
Definition: mptrac.h:2703
double met_p[EP]
Target pressure levels [hPa].
Definition: mptrac.h:2706

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

2872 {
2873
2874 int ilo = 0;
2875 int ihi = n - 1;
2876 int i = (ihi + ilo) >> 1;
2877
2878 if (xx[i] < xx[i + 1])
2879 while (ihi > ilo + 1) {
2880 i = (ihi + ilo) >> 1;
2881 if (xx[i] > x)
2882 ihi = i;
2883 else
2884 ilo = i;
2885 } else
2886 while (ihi > ilo + 1) {
2887 i = (ihi + ilo) >> 1;
2888 if (xx[i] <= x)
2889 ihi = i;
2890 else
2891 ilo = i;
2892 }
2893
2894 return ilo;
2895}

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

2903 {
2904
2905 int ilo = 0;
2906 int ihi = n - 1;
2907 int i = (ihi + ilo) >> 1;
2908
2909 if ((xx[ig] <= x && x < xx[ig + 1]) || (xx[ig] >= x && x > xx[ig + 1]))
2910 return ig;
2911
2912 if (xx[i] < xx[i + 1])
2913 while (ihi > ilo + 1) {
2914 i = (ihi + ilo) >> 1;
2915 if (xx[i] > x)
2916 ihi = i;
2917 else
2918 ilo = i;
2919 } else
2920 while (ihi > ilo + 1) {
2921 i = (ihi + ilo) >> 1;
2922 if (xx[i] <= x)
2923 ihi = i;
2924 else
2925 ilo = i;
2926 }
2927
2928 return ilo;
2929}

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

2936 {
2937
2938 /* Calculate index... */
2939 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2940
2941 /* Check range... */
2942 if (i < 0)
2943 return 0;
2944 else if (i > n - 2)
2945 return n - 2;
2946 else
2947 return i;
2948}

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

2958 {
2959
2960 ind[0] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind],
2961 np, height_ap, 0);
2962 ind[1] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind],
2963 np, height_ap, ind[0]);
2964 ind[2] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind + 1],
2965 np, height_ap, ind[1]);
2966 ind[3] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind + 1],
2967 np, height_ap, ind[2]);
2968}
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:2899
Here is the call graph for this function:

◆ module_advect()

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

Advances particle positions using different advection schemes.

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

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

Definition at line 2972 of file mptrac.c.

2977 {
2978
2979 /* Set timer... */
2980 SELECT_TIMER("MODULE_ADVECT", "PHYSICS", NVTX_GPU);
2981
2982 /* Use omega vertical velocity... */
2983 if (ctl->advect_vert_coord == 0 || ctl->advect_vert_coord == 2) {
2984
2985 /* Loop over particles... */
2986 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2987
2988 /* Init... */
2990 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
2991 x[3] = { 0, 0, 0 };
2992
2993 /* Loop over integration nodes... */
2994 for (int i = 0; i < ctl->advect; i++) {
2995
2996 /* Set position... */
2997 if (i == 0) {
2998 dts = 0.0;
2999 x[0] = atm->lon[ip];
3000 x[1] = atm->lat[ip];
3001 x[2] = atm->p[ip];
3002 } else {
3003 dts = (i == 3 ? 1.0 : 0.5) * cache->dt[ip];
3004 x[0] = atm->lon[ip] + DX2DEG(dts * u[i - 1] / 1000., atm->lat[ip]);
3005 x[1] = atm->lat[ip] + DY2DEG(dts * v[i - 1] / 1000.);
3006 x[2] = atm->p[ip] + dts * w[i - 1];
3007 }
3008 const double tm = atm->time[ip] + dts;
3009
3010 /* Interpolate meteo data on pressure levels... */
3011 if (ctl->advect_vert_coord == 0) {
3012 intpol_met_time_3d(met0, met0->u, met1, met1->u,
3013 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3014 intpol_met_time_3d(met0, met0->v, met1, met1->v,
3015 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3016 intpol_met_time_3d(met0, met0->w, met1, met1->w,
3017 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3018 }
3019
3020 /* Interpolate meteo data on model levels... */
3021 else {
3022 intpol_met_4d_zeta(met0, met0->pl, met0->ul,
3023 met1, met1->pl, met1->ul,
3024 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3025 intpol_met_4d_zeta(met0, met0->pl, met0->vl,
3026 met1, met1->pl, met1->vl,
3027 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3028 intpol_met_4d_zeta(met0, met0->pl, met0->wl,
3029 met1, met1->pl, met1->wl,
3030 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3031 }
3032
3033 /* Get mean wind... */
3034 double k = 1.0;
3035 if (ctl->advect == 2)
3036 k = (i == 0 ? 0.0 : 1.0);
3037 else if (ctl->advect == 4)
3038 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3039 um += k * u[i];
3040 vm += k * v[i];
3041 wm += k * w[i];
3042 }
3043
3044 /* Set new position... */
3045 atm->time[ip] += cache->dt[ip];
3046 atm->lon[ip] += DX2DEG(cache->dt[ip] * um / 1000.,
3047 (ctl->advect == 2 ? x[1] : atm->lat[ip]));
3048 atm->lat[ip] += DY2DEG(cache->dt[ip] * vm / 1000.);
3049 atm->p[ip] += cache->dt[ip] * wm;
3050 }
3051 }
3052
3053 /* Use zeta or eta vertical velocity... */
3054 else if (ctl->advect_vert_coord == 1 || ctl->advect_vert_coord == 3) {
3055
3056 /* Select quantity index depending on coordinate... */
3057 const int qnt = (ctl->advect_vert_coord == 1
3058 ? ctl->qnt_zeta : ctl->qnt_eta);
3059
3060 /* Loop over particles... */
3061 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
3062
3063 /* Convert pressure to vertical coordinate (zeta or eta)... */
3065 intpol_met_4d_zeta(met0, met0->pl, met0->zetal,
3066 met1, met1->pl, met1->zetal,
3067 atm->time[ip], atm->p[ip],
3068 atm->lon[ip], atm->lat[ip],
3069 &atm->q[qnt][ip], ci, cw, 1);
3070
3071 /* Init... */
3072 double dts, u[4], um = 0, v[4], vm = 0, wdot[4],
3073 wdotm = 0, x[3] = { 0, 0, 0 };
3074
3075 /* Loop over integration nodes (Runge–Kutta steps)... */
3076 for (int i = 0; i < ctl->advect; i++) {
3077
3078 /* Set position... */
3079 if (i == 0) {
3080 dts = 0.0;
3081 x[0] = atm->lon[ip];
3082 x[1] = atm->lat[ip];
3083 x[2] = atm->q[qnt][ip];
3084 } else {
3085 dts = (i == 3 ? 1.0 : 0.5) * cache->dt[ip];
3086 x[0] = atm->lon[ip] + DX2DEG(dts * u[i - 1] / 1000., atm->lat[ip]);
3087 x[1] = atm->lat[ip] + DY2DEG(dts * v[i - 1] / 1000.);
3088 x[2] = atm->q[qnt][ip] + dts * wdot[i - 1];
3089 }
3090
3091 const double tm = atm->time[ip] + dts;
3092
3093 /* Interpolate meteo data... */
3094 intpol_met_4d_zeta(met0, met0->zetal, met0->ul,
3095 met1, met1->zetal, met1->ul,
3096 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3097 intpol_met_4d_zeta(met0, met0->zetal, met0->vl,
3098 met1, met1->zetal, met1->vl,
3099 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3100 intpol_met_4d_zeta(met0, met0->zetal, met0->zeta_dotl,
3101 met1, met1->zetal, met1->zeta_dotl,
3102 tm, x[2], x[0], x[1], &wdot[i], ci, cw, 0);
3103
3104 /* Compute Runge–Kutta weights... */
3105 double k = 1.0;
3106 if (ctl->advect == 2)
3107 k = (i == 0 ? 0.0 : 1.0);
3108 else if (ctl->advect == 4)
3109 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3110
3111 um += k * u[i];
3112 vm += k * v[i];
3113 wdotm += k * wdot[i];
3114 }
3115
3116 /* Update particle position... */
3117 atm->time[ip] += cache->dt[ip];
3118 atm->lon[ip] += DX2DEG(cache->dt[ip] * um / 1000.,
3119 (ctl->advect == 2 ? x[1] : atm->lat[ip]));
3120 atm->lat[ip] += DY2DEG(cache->dt[ip] * vm / 1000.);
3121 atm->q[qnt][ip] += cache->dt[ip] * wdotm;
3122
3123 /* Convert vertical coordinate (zeta or eta) back to pressure... */
3124 intpol_met_4d_zeta(met0, met0->zetal, met0->pl,
3125 met1, met1->zetal, met1->pl,
3126 atm->time[ip],
3127 atm->q[qnt][ip], atm->lon[ip], atm->lat[ip],
3128 &atm->p[ip], ci, cw, 1);
3129 }
3130 }
3131}
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:2429
void intpol_met_4d_zeta(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:2141
#define PARTICLE_LOOP(ip0, ip1, check_dt,...)
Loop over particle indices with OpenACC acceleration.
Definition: mptrac.h:1413
#define DX2DEG(dx, lat)
Convert a distance in kilometers to degrees longitude at a given latitude.
Definition: mptrac.h:614
#define SELECT_TIMER(id, group, color)
Select and start a timer with specific attributes.
Definition: mptrac.h:2123
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
Definition: mptrac.h:632
double time[NP]
Time [s].
Definition: mptrac.h:3303
double lat[NP]
Latitude [deg].
Definition: mptrac.h:3312
double lon[NP]
Longitude [deg].
Definition: mptrac.h:3309
int np
Number of air parcels.
Definition: mptrac.h:3300
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
Definition: mptrac.h:3315
double p[NP]
Pressure [hPa].
Definition: mptrac.h:3306
double dt[NP]
Timesteps [s].
Definition: mptrac.h:3373
int qnt_eta
Quantity array index for eta vertical coordinate.
Definition: mptrac.h:2487
int advect
Advection scheme (0=off, 1=Euler, 2=midpoint, 4=Runge-Kutta).
Definition: mptrac.h:2778
int qnt_zeta
Quantity array index for zeta vertical coordinate.
Definition: mptrac.h:2478
int advect_vert_coord
Vertical velocity of air parcels (0=omega_on_plev, 1=zetadot_on_mlev, 2=omega_on_mlev,...
Definition: mptrac.h:2782
float zeta_dotl[EX][EY][EP]
Vertical velocity on model levels [K/s].
Definition: mptrac.h:3716
float w[EX][EY][EP]
Vertical velocity [hPa/s].
Definition: mptrac.h:3674
float wl[EX][EY][EP]
Vertical velocity on model levels [hPa/s].
Definition: mptrac.h:3710
float vl[EX][EY][EP]
Meridional wind on model levels [m/s].
Definition: mptrac.h:3707
float u[EX][EY][EP]
Zonal wind [m/s].
Definition: mptrac.h:3668
float ul[EX][EY][EP]
Zonal wind on model levels [m/s].
Definition: mptrac.h:3704
float v[EX][EY][EP]
Meridional wind [m/s].
Definition: mptrac.h:3671
float pl[EX][EY][EP]
Pressure on model levels [hPa].
Definition: mptrac.h:3701
float zetal[EX][EY][EP]
Zeta on model levels [K].
Definition: mptrac.h:3713
Here is the call graph for this function:

◆ module_advect_init()

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

Initializes the advection module by setting up pressure fields.

This function initializes the advection module, setting up the air parcel pressure to be consistent with the given zeta vertical coordinate. It utilizes meteorological data from two time steps and interpolates the pressure values accordingly.

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

The function performs the following operations:

  • Sets up a timer labeled "MODULE_ADVECT_INIT" within the "PHYSICS" category.
  • If the zeta vertical coordinate system is specified (ctl->vert_coord_ap == 1), it initializes the pressure fields to be consistent with the zeta coordinate using 4D interpolation.
Author
Jan Clemens

Definition at line 3135 of file mptrac.c.

3140 {
3141
3142 /* Check parameters... */
3143 if (ctl->advect_vert_coord != 1)
3144 return;
3145
3146 /* Set timer... */
3147 SELECT_TIMER("MODULE_ADVECT_INIT", "PHYSICS", NVTX_GPU);
3148
3149 /* Loop over particles... */
3150 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,met0,met1,atm)") {
3151
3152 /* Initialize pressure consistent with zeta... */
3154 intpol_met_4d_zeta(met0, met0->zetal, met0->pl, met1, met1->zetal,
3155 met1->pl, atm->time[ip], atm->q[ctl->qnt_zeta][ip],
3156 atm->lon[ip], atm->lat[ip], &atm->p[ip], ci, cw, 1);
3157 }
3158}
Here is the call graph for this function:

◆ module_bound_cond()

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

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

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

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

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

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

Definition at line 3162 of file mptrac.c.

3168 {
3169
3170 /* Set timer... */
3171 SELECT_TIMER("MODULE_BOUND_COND", "PHYSICS", NVTX_GPU);
3172
3173 /* Check quantity flags... */
3174 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0 && ctl->qnt_Cccl4
3175 && ctl->qnt_Cccl3f < 0 && ctl->qnt_Cccl2f2 < 0
3176 && ctl->qnt_Cn2o < 0 && ctl->qnt_Csf6 < 0 && ctl->qnt_aoa < 0)
3177 return;
3178
3179 /* Loop over particles... */
3180 PARTICLE_LOOP(0, atm->np, 1,
3181 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3182
3183 /* Check latitude and pressure range... */
3184 if (atm->lat[ip] < ctl->bound_lat0 || atm->lat[ip] > ctl->bound_lat1
3185 || atm->p[ip] > ctl->bound_p0 || atm->p[ip] < ctl->bound_p1)
3186 continue;
3187
3188 /* Check surface layer... */
3189 if (ctl->bound_dps > 0 || ctl->bound_dzs > 0
3190 || ctl->bound_zetas > 0 || ctl->bound_pbl) {
3191
3192 /* Get surface pressure... */
3193 double ps;
3195 INTPOL_2D(ps, 1);
3196
3197 /* Check pressure... */
3198 if (ctl->bound_dps > 0 && atm->p[ip] < ps - ctl->bound_dps)
3199 continue;
3200
3201 /* Check height... */
3202 if (ctl->bound_dzs > 0 && Z(atm->p[ip]) > Z(ps) + ctl->bound_dzs)
3203 continue;
3204
3205 /* Check zeta range... */
3206 if (ctl->bound_zetas > 0) {
3207 double t;
3208 INTPOL_3D(t, 1);
3209 if (ZETA(ps, atm->p[ip], t) > ctl->bound_zetas)
3210 continue;
3211 }
3212
3213 /* Check planetary boundary layer... */
3214 if (ctl->bound_pbl) {
3215 double pbl;
3216 INTPOL_2D(pbl, 0);
3217 if (atm->p[ip] < pbl)
3218 continue;
3219 }
3220 }
3221
3222 /* Set mass and volume mixing ratio... */
3223 if (ctl->qnt_m >= 0 && ctl->bound_mass >= 0)
3224 atm->q[ctl->qnt_m][ip] =
3225 ctl->bound_mass + ctl->bound_mass_trend * atm->time[ip];
3226 if (ctl->qnt_vmr >= 0 && ctl->bound_vmr >= 0)
3227 atm->q[ctl->qnt_vmr][ip] =
3228 ctl->bound_vmr + ctl->bound_vmr_trend * atm->time[ip];
3229
3230 /* Set CFC-10 volume mixing ratio... */
3231 if (ctl->qnt_Cccl4 >= 0 && ctl->clim_ccl4_timeseries[0] != '-')
3232 atm->q[ctl->qnt_Cccl4][ip] = clim_ts(&clim->ccl4, atm->time[ip]);
3233
3234 /* Set CFC-11 volume mixing ratio... */
3235 if (ctl->qnt_Cccl3f >= 0 && ctl->clim_ccl3f_timeseries[0] != '-')
3236 atm->q[ctl->qnt_Cccl3f][ip] = clim_ts(&clim->ccl3f, atm->time[ip]);
3237
3238 /* Set CFC-12 volume mixing ratio... */
3239 if (ctl->qnt_Cccl2f2 >= 0 && ctl->clim_ccl2f2_timeseries[0] != '-')
3240 atm->q[ctl->qnt_Cccl2f2][ip] = clim_ts(&clim->ccl2f2, atm->time[ip]);
3241
3242 /* Set N2O volume mixing ratio... */
3243 if (ctl->qnt_Cn2o >= 0 && ctl->clim_n2o_timeseries[0] != '-')
3244 atm->q[ctl->qnt_Cn2o][ip] = clim_ts(&clim->n2o, atm->time[ip]);
3245
3246 /* Set SF6 volume mixing ratio... */
3247 if (ctl->qnt_Csf6 >= 0 && ctl->clim_sf6_timeseries[0] != '-')
3248 atm->q[ctl->qnt_Csf6][ip] = clim_ts(&clim->sf6, atm->time[ip]);
3249
3250 /* Set age of air... */
3251 if (ctl->qnt_aoa >= 0)
3252 atm->q[ctl->qnt_aoa][ip] = atm->time[ip];
3253 }
3254}
double clim_ts(const clim_ts_t *ts, const double t)
Interpolates a time series of climatological variables.
Definition: mptrac.c:387
#define INTPOL_3D(var, init)
Perform 3D interpolation for a meteorological variable.
Definition: mptrac.h:864
#define ZETA(ps, p, t)
Computes the value of the zeta vertical coordinate.
Definition: mptrac.h:1930
#define INTPOL_2D(var, init)
Perform 2D interpolation for a meteorological variable.
Definition: mptrac.h:847
clim_ts_t ccl2f2
CFC-12 time series.
Definition: mptrac.h:3534
clim_ts_t sf6
SF6 time series.
Definition: mptrac.h:3540
clim_ts_t ccl4
CFC-10 time series.
Definition: mptrac.h:3528
clim_ts_t ccl3f
CFC-11 time series.
Definition: mptrac.h:3531
clim_ts_t n2o
N2O time series.
Definition: mptrac.h:3537
int qnt_Cccl2f2
Quantity array index for CFC-12 volume mixing ratio (chemistry code).
Definition: mptrac.h:2556
int qnt_m
Quantity array index for mass.
Definition: mptrac.h:2295
int qnt_aoa
Quantity array index for age of air.
Definition: mptrac.h:2565
char clim_n2o_timeseries[LEN]
Filename of N2O time series.
Definition: mptrac.h:2908
double bound_dzs
Boundary conditions surface layer depth [km].
Definition: mptrac.h:2857
int qnt_Cccl4
Quantity array index for CFC-10 volume mixing ratio (chemistry code).
Definition: mptrac.h:2550
double bound_mass
Boundary conditions mass per particle [kg].
Definition: mptrac.h:2830
int qnt_vmr
Quantity array index for volume mixing ratio.
Definition: mptrac.h:2298
double bound_lat1
Boundary conditions maximum longitude [deg].
Definition: mptrac.h:2845
int bound_pbl
Boundary conditions planetary boundary layer (0=no, 1=yes).
Definition: mptrac.h:2863
double bound_p1
Boundary conditions top pressure [hPa].
Definition: mptrac.h:2851
double bound_vmr
Boundary conditions volume mixing ratio [ppv].
Definition: mptrac.h:2836
double bound_lat0
Boundary conditions minimum longitude [deg].
Definition: mptrac.h:2842
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
Definition: mptrac.h:2839
int qnt_Cn2o
Quantity array index for N2O volume mixing ratio (chemistry code).
Definition: mptrac.h:2559
int qnt_Cccl3f
Quantity array index for CFC-11 volume mixing ratio (chemistry code).
Definition: mptrac.h:2553
int qnt_Csf6
Quantity array index for SF6 volume mixing ratio (chemistry code).
Definition: mptrac.h:2562
double bound_dps
Boundary conditions surface layer depth [hPa].
Definition: mptrac.h:2854
double bound_mass_trend
Boundary conditions mass per particle trend [kg/s].
Definition: mptrac.h:2833
double bound_p0
Boundary conditions bottom pressure [hPa].
Definition: mptrac.h:2848
char clim_ccl4_timeseries[LEN]
Filename of CFC-10 time series.
Definition: mptrac.h:2899
char clim_sf6_timeseries[LEN]
Filename of SF6 time series.
Definition: mptrac.h:2911
char clim_ccl3f_timeseries[LEN]
Filename of CFC-11 time series.
Definition: mptrac.h:2902
char clim_ccl2f2_timeseries[LEN]
Filename of CFC-12 time series.
Definition: mptrac.h:2905
double bound_zetas
Boundary conditions surface layer zeta [K].
Definition: mptrac.h:2860
Here is the call graph for this function:

◆ module_chem_grid()

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

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

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

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

Parallelization is supported via OpenMP or OpenACC.

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

Definition at line 3258 of file mptrac.c.

3263 {
3264
3265 /* Check quantities... */
3266 if (ctl->qnt_m < 0 || ctl->qnt_Cx < 0)
3267 return;
3268 if (ctl->molmass <= 0)
3269 ERRMSG("Molar mass is not defined!");
3270
3271 /* Set timer... */
3272 SELECT_TIMER("MODULE_CHEM_GRID", "PHYSICS", NVTX_GPU);
3273
3274 /* Allocate... */
3275 const int ensemble_mode = (ctl->nens > 0);
3276 const int np = atm->np;
3277 const int nz = ctl->chemgrid_nz;
3278 const int nx = ctl->chemgrid_nx;
3279 const int ny = ctl->chemgrid_ny;
3280 const int ngrid = nx * ny * nz;
3281 const int nens = ensemble_mode ? ctl->nens : 1;
3282
3283 double *restrict const z = (double *) malloc((size_t) nz * sizeof(double));
3284 double *restrict const press =
3285 (double *) malloc((size_t) nz * sizeof(double));
3286 double *restrict const mass =
3287 (double *) calloc((size_t) ngrid * (size_t) nens, sizeof(double));
3288 double *restrict const area =
3289 (double *) malloc((size_t) ny * sizeof(double));
3290 double *restrict const lon =
3291 (double *) malloc((size_t) nx * sizeof(double));
3292 double *restrict const lat =
3293 (double *) malloc((size_t) ny * sizeof(double));
3294
3295 int *restrict const ixs = (int *) malloc((size_t) np * sizeof(int));
3296 int *restrict const iys = (int *) malloc((size_t) np * sizeof(int));
3297 int *restrict const izs = (int *) malloc((size_t) np * sizeof(int));
3298
3299 /* Set grid box size... */
3300 const double dz = (ctl->chemgrid_z1 - ctl->chemgrid_z0) / nz;
3301 const double dlon = (ctl->chemgrid_lon1 - ctl->chemgrid_lon0) / nx;
3302 const double dlat = (ctl->chemgrid_lat1 - ctl->chemgrid_lat0) / ny;
3303
3304 /* Set vertical coordinates... */
3305#ifdef _OPENACC
3306#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np],z[0:nz],press[0:nz],mass[0:ngrid*nens],area[0:ny],lon[0:nx],lat[0:ny])
3307#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
3308#pragma acc parallel loop independent gang vector
3309#else
3310#pragma omp parallel for default(shared)
3311#endif
3312 for (int iz = 0; iz < nz; iz++) {
3313 z[iz] = ctl->chemgrid_z0 + dz * (iz + 0.5);
3314 press[iz] = P(z[iz]);
3315 }
3316
3317 /* Set time interval for output... */
3318 const double t0 = tt - 0.5 * ctl->dt_mod;
3319 const double t1 = tt + 0.5 * ctl->dt_mod;
3320
3321 /* Get indices... */
3322#ifdef _OPENACC
3323#pragma acc parallel loop independent gang vector
3324#else
3325#pragma omp parallel for default(shared)
3326#endif
3327 for (int ip = 0; ip < np; ip++) {
3328 ixs[ip] = (int) ((atm->lon[ip] - ctl->chemgrid_lon0) / dlon);
3329 iys[ip] = (int) ((atm->lat[ip] - ctl->chemgrid_lat0) / dlat);
3330 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->chemgrid_z0) / dz);
3331 if (atm->time[ip] < t0 || atm->time[ip] > t1
3332 || ixs[ip] < 0 || ixs[ip] >= nx
3333 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
3334 izs[ip] = -1;
3335 }
3336
3337 /* Set horizontal coordinates... */
3338#ifdef _OPENACC
3339#pragma acc parallel loop independent gang vector
3340#else
3341#pragma omp parallel for default(shared)
3342#endif
3343 for (int ix = 0; ix < nx; ix++)
3344 lon[ix] = ctl->chemgrid_lon0 + dlon * (ix + 0.5);
3345
3346#ifdef _OPENACC
3347#pragma acc parallel loop independent gang vector
3348#else
3349#pragma omp parallel for default(shared)
3350#endif
3351 for (int iy = 0; iy < ny; iy++) {
3352 lat[iy] = ctl->chemgrid_lat0 + dlat * (iy + 0.5);
3353 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
3354 }
3355
3356 /* Get mass per grid box... */
3357#ifdef _OPENACC
3358#pragma acc parallel loop independent gang vector
3359#endif
3360 for (int ip = 0; ip < np; ip++) {
3361 if (izs[ip] >= 0) {
3362 int mass_idx = ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3363 if (ensemble_mode) {
3364 const int ens = (int) atm->q[ctl->qnt_ens][ip];
3365 mass_idx += ens * ngrid;
3366 }
3367#ifdef _OPENACC
3368#pragma acc atomic update
3369#endif
3370 mass[mass_idx] += atm->q[ctl->qnt_m][ip];
3371 }
3372 }
3373
3374 /* Assign grid data to air parcels ... */
3375#ifdef _OPENACC
3376#pragma acc parallel loop independent gang vector
3377#else
3378#pragma omp parallel for default(shared)
3379#endif
3380 for (int ip = 0; ip < np; ip++)
3381 if (izs[ip] >= 0) {
3382
3383 /* Interpolate temperature... */
3384 double temp;
3386 intpol_met_time_3d(met0, met0->t, met1, met1->t, tt,
3387 press[izs[ip]],
3388 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
3389
3390 /* Set mass... */
3391 int mass_idx = ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3392 if (ensemble_mode) {
3393 const int ens = (int) atm->q[ctl->qnt_ens][ip];
3394 mass_idx += ens * ngrid;
3395 }
3396
3397 /* Calculate volume mixing ratio... */
3398 const double m = mass[mass_idx];
3399 atm->q[ctl->qnt_Cx][ip] = MA / ctl->molmass * m
3400 / (RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
3401 }
3402
3403 /* Free... */
3404#ifdef _OPENACC
3405#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
3406#endif
3407 free(mass);
3408 free(lon);
3409 free(lat);
3410 free(area);
3411 free(z);
3412 free(press);
3413 free(ixs);
3414 free(iys);
3415 free(izs);
3416}
#define ARRAY_3D(ix, iy, ny, iz, nz)
Compute the linear index of a 3D array element.
Definition: mptrac.h:458
#define P(z)
Compute pressure at given altitude.
Definition: mptrac.h:1443
#define RHO(p, t)
Compute density of air.
Definition: mptrac.h:1620
double molmass
Molar mass [g/mol].
Definition: mptrac.h:2869
double chemgrid_z1
Upper altitude of chemistry grid [km].
Definition: mptrac.h:2956
double chemgrid_z0
Lower altitude of chemistry grid [km].
Definition: mptrac.h:2953
double chemgrid_lat0
Lower latitude of chemistry grid [deg].
Definition: mptrac.h:2971
double chemgrid_lat1
Upper latitude of chemistry grid [deg].
Definition: mptrac.h:2974
double chemgrid_lon0
Lower longitude of chemistry grid [deg].
Definition: mptrac.h:2962
double chemgrid_lon1
Upper longitude of chemistry grid [deg].
Definition: mptrac.h:2965
double dt_mod
Time step of simulation [s].
Definition: mptrac.h:2583
int nens
Number of ensembles.
Definition: mptrac.h:3122
int chemgrid_nz
Number of altitudes of chemistry grid.
Definition: mptrac.h:2950
int chemgrid_nx
Number of longitudes of chemistry grid.
Definition: mptrac.h:2959
int chemgrid_ny
Number of latitudes of chemistry grid.
Definition: mptrac.h:2968
int qnt_ens
Quantity array index for ensemble IDs.
Definition: mptrac.h:2289
int qnt_Cx
Quantity array index for trace species x volume mixing ratio (chemistry code).
Definition: mptrac.h:2520
Here is the call graph for this function:

◆ module_chem_init()

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

Initializes the chemistry modules by setting atmospheric composition.

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

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

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

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

Definition at line 3420 of file mptrac.c.

3426 {
3427
3428 /* Set timer... */
3429 SELECT_TIMER("MODULE_CHEM_INIT", "PHYSICS", NVTX_GPU);
3430
3431 /* Loop over particles... */
3432 PARTICLE_LOOP(0, atm->np, 0,
3433 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3434
3435 /* Set H2O and O3 using meteo data... */
3437 if (ctl->qnt_Ch2o >= 0) {
3438 double h2o;
3439 INTPOL_3D(h2o, 1);
3440 SET_ATM(qnt_Ch2o, h2o);
3441 }
3442 if (ctl->qnt_Co3 >= 0) {
3443 double o3;
3444 INTPOL_3D(o3, 1);
3445 SET_ATM(qnt_Co3, o3);
3446 }
3447
3448 /* Set radical species... */
3449 SET_ATM(qnt_Coh, clim_oh(ctl, clim, atm->time[ip],
3450 atm->lon[ip], atm->lat[ip], atm->p[ip]));
3451 SET_ATM(qnt_Cho2, clim_zm(&clim->ho2, atm->time[ip],
3452 atm->lat[ip], atm->p[ip]));
3453 SET_ATM(qnt_Ch2o2, clim_zm(&clim->h2o2, atm->time[ip],
3454 atm->lat[ip], atm->p[ip]));
3455 SET_ATM(qnt_Co1d, clim_zm(&clim->o1d, atm->time[ip],
3456 atm->lat[ip], atm->p[ip]));
3457 }
3458}
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:1639
clim_zm_t ho2
HO2 zonal means.
Definition: mptrac.h:3522
clim_zm_t o1d
O(1D) zonal means.
Definition: mptrac.h:3525
clim_zm_t h2o2
H2O2 zonal means.
Definition: mptrac.h:3519
int qnt_Ch2o
Quantity array index for H2O volume mixing ratio (chemistry code).
Definition: mptrac.h:2523
int qnt_Co3
Quantity array index for O3 volume mixing ratio (chemistry code).
Definition: mptrac.h:2526
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 3462 of file mptrac.c.

3467 {
3468
3469 /* Set timer... */
3470 SELECT_TIMER("MODULE_CONVECTION", "PHYSICS", NVTX_GPU);
3471
3472 /* Create random numbers... */
3473 module_rng(ctl, cache->rs, (size_t) atm->np, 0);
3474
3475 /* Loop over particles... */
3476 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
3477
3478 /* Interpolate surface pressure... */
3479 double ps;
3481 INTPOL_2D(ps, 1);
3482
3483 /* Initialize pressure range for vertical mixing... */
3484 double pbot = ps, ptop = ps;
3485
3486 /* Mixing in the PBL... */
3487 if (ctl->conv_mix_pbl) {
3488
3489 /* Interpolate PBL... */
3490 double pbl;
3491 INTPOL_2D(pbl, 0);
3492
3493 /* Set pressure range... */
3494 ptop = pbl - ctl->conv_pbl_trans * (ps - pbl);
3495 }
3496
3497 /* Convective mixing... */
3498 if (ctl->conv_cape >= 0) {
3499
3500 /* Interpolate CAPE, CIN, and equilibrium level... */
3501 double cape, cin, pel;
3502 INTPOL_2D(cape, 0);
3503 INTPOL_2D(cin, 0);
3504 INTPOL_2D(pel, 0);
3505
3506 /* Set pressure range... */
3507 if (isfinite(cape) && cape >= ctl->conv_cape
3508 && (ctl->conv_cin <= 0 || (isfinite(cin) && cin >= ctl->conv_cin)))
3509 ptop = GSL_MIN(ptop, pel);
3510 }
3511
3512 /* Apply vertical mixing... */
3513 if (ptop != pbot && atm->p[ip] >= ptop) {
3514
3515 /* Get density range... */
3516 double tbot, ttop;
3517 intpol_met_time_3d(met0, met0->t, met1, met1->t, atm->time[ip],
3518 pbot, atm->lon[ip], atm->lat[ip], &tbot, ci, cw, 1);
3519 intpol_met_time_3d(met0, met0->t, met1, met1->t, atm->time[ip], ptop,
3520 atm->lon[ip], atm->lat[ip], &ttop, ci, cw, 1);
3521 const double rhobot = pbot / tbot;
3522 const double rhotop = ptop / ttop;
3523
3524 /* Get new density... */
3525 const double rho = rhobot + (rhotop - rhobot) * cache->rs[ip];
3526
3527 /* Get pressure... */
3528 atm->p[ip] = LIN(rhobot, pbot, rhotop, ptop, rho);
3529 }
3530 }
3531}
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:4635
double rs[3 *NP+1]
Random numbers.
Definition: mptrac.h:3370
double conv_cape
CAPE threshold for convection module [J/kg].
Definition: mptrac.h:2821
double conv_pbl_trans
Depth of PBL transition layer (fraction of PBL depth).
Definition: mptrac.h:2818
int conv_mix_pbl
Vertical mixing in the PBL (0=off, 1=on).
Definition: mptrac.h:2815
double conv_cin
CIN threshold for convection module [J/kg].
Definition: mptrac.h:2824
Here is the call graph for this function:

◆ module_dd()

void module_dd ( ctl_t ctl,
atm_t atm,
cache_t cache,
dd_t dd,
met_t **  met 
)

Manages domain decomposition and particle communication in parallel processing.

The module_dd function orchestrates the domain decomposition process, including particle assignment, sorting, transformation, and communication across MPI processes. It handles the initialization of particles, their assignment to subdomains, and communication between neighbouring processes.

Parameters
ctlA pointer to a ctl_t structure containing control parameters.
atmA pointer to an atm_t structure containing atmospheric data.
cacheA pointer to a cache_t structure used for storing intermediate values.
ddA pointer to an dd_t structure containing MPI information.
metA pointer to a pointer of a met_t structure containing meteorological data.

The function performs the following steps:

  • Initializes a local array of particles.
  • Assigns particles to subdomains using dd_assign_rect_subdomains_atm.
  • Sorts particles according to their location and target rank using dd_sort.
  • Transforms atmospheric data to particle data using atm2particles.
  • Communicates particles between neighbouring MPI processes using dd_communicate_particles.
  • Transforms particle data back to atmospheric data using dd_particles2atm.
  • Frees the local particle array after processing.
Note
This function assumes that the ctl, atm, cache, dd, and met structures are properly initialized. It is designed to work in a parallel processing environment using MPI.
Author
Jan Clemens

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

3579 {
3580
3581 /* Set timer... */
3582 SELECT_TIMER("MODULE_DECAY", "PHYSICS", NVTX_GPU);
3583
3584 /* Check quantity flags... */
3585 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
3586 ERRMSG("Module needs quantity mass or volume mixing ratio!");
3587
3588 /* Loop over particles... */
3589 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,clim,atm)") {
3590
3591 /* Get weighting factor... */
3592 const double w = tropo_weight(clim, atm, ip);
3593
3594 /* Set lifetime... */
3595 const double tdec = w * ctl->tdec_trop + (1 - w) * ctl->tdec_strat;
3596
3597 /* Calculate exponential decay... */
3598 const double aux = exp(-cache->dt[ip] / tdec);
3599 if (ctl->qnt_m >= 0) {
3600 if (ctl->qnt_mloss_decay >= 0)
3601 atm->q[ctl->qnt_mloss_decay][ip]
3602 += atm->q[ctl->qnt_m][ip] * (1 - aux);
3603 atm->q[ctl->qnt_m][ip] *= aux;
3604 if (ctl->qnt_loss_rate >= 0)
3605 atm->q[ctl->qnt_loss_rate][ip] += 1. / tdec;
3606 }
3607 if (ctl->qnt_vmr >= 0)
3608 atm->q[ctl->qnt_vmr][ip] *= aux;
3609 }
3610}
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:11258
int qnt_loss_rate
Quantity array index for total loss rate.
Definition: mptrac.h:2454
int qnt_mloss_decay
Quantity array index for total mass loss due to exponential decay.
Definition: mptrac.h:2451
double tdec_strat
Life time of particles in the stratosphere [s].
Definition: mptrac.h:2875
double tdec_trop
Life time of particles in the troposphere [s].
Definition: mptrac.h:2872
Here is the call graph for this function:

◆ module_diff_meso()

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

Simulate mesoscale diffusion for atmospheric particles.

This function simulates mesoscale diffusion for atmospheric particles, including horizontal and vertical wind fluctuations. It calculates standard deviations of local wind data and temporal correlations for mesoscale fluctuations. Mesoscale wind fluctuations are then calculated based on the provided random numbers and turbulence parameters. The particle positions are updated accordingly.

The function loops over each particle and calculates indices for interpolation of wind data. It then computes standard deviations of local wind data and temporal correlations for mesoscale fluctuations. Based on the turbulence parameters and provided random numbers, it calculates horizontal and vertical mesoscale wind fluctuations. Finally, it updates the particle positions based on the calculated wind fluctuations.

Parameters
ctlPointer to the control structure containing simulation parameters.
cachePointer to the cache structure for temporary data and random numbers.
met0Pointer to the meteorological data structure at the current time step.
met1Pointer to the meteorological data structure at the next time step.
atmPointer to the atmospheric data structure containing particle information.
Note
Control parameters TURB_MESOX and TURB_MESOZ define the subgrid-scale variability as a fraction of the grid-scale variance. Stohl et al. (2005) recommend a default value of 0.16 for both parameters, providing a standard approach for turbulence representation. However, recent findings by Bakels et al. (2024) suggest disabling this approach to improve model accuracy under certain conditions. It is advised to evaluate the applicability of these recommendations based on the specific simulation context and objectives.
Author
Lars Hoffmann

Definition at line 3614 of file mptrac.c.

3619 {
3620
3621 /* Set timer... */
3622 SELECT_TIMER("MODULE_DIFF_MESO", "PHYSICS", NVTX_GPU);
3623
3624 /* Create random numbers... */
3625 module_rng(ctl, cache->rs, 3 * (size_t) atm->np, 1);
3626
3627 /* Loop over particles... */
3628 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
3629
3630 /* Get indices... */
3631 const int ix = locate_reg(met0->lon, met0->nx, atm->lon[ip]);
3632 const int iy = locate_irr(met0->lat, met0->ny, atm->lat[ip]);
3633 const int iz = locate_irr(met0->p, met0->np, atm->p[ip]);
3634
3635 /* Get standard deviations of local wind data... */
3636 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
3637 for (int i = 0; i < 2; i++)
3638 for (int j = 0; j < 2; j++)
3639 for (int k = 0; k < 2; k++) {
3640 umean += met0->u[ix + i][iy + j][iz + k];
3641 usig += SQR(met0->u[ix + i][iy + j][iz + k]);
3642 vmean += met0->v[ix + i][iy + j][iz + k];
3643 vsig += SQR(met0->v[ix + i][iy + j][iz + k]);
3644 wmean += met0->w[ix + i][iy + j][iz + k];
3645 wsig += SQR(met0->w[ix + i][iy + j][iz + k]);
3646
3647 umean += met1->u[ix + i][iy + j][iz + k];
3648 usig += SQR(met1->u[ix + i][iy + j][iz + k]);
3649 vmean += met1->v[ix + i][iy + j][iz + k];
3650 vsig += SQR(met1->v[ix + i][iy + j][iz + k]);
3651 wmean += met1->w[ix + i][iy + j][iz + k];
3652 wsig += SQR(met1->w[ix + i][iy + j][iz + k]);
3653 }
3654 usig = usig / 16.f - SQR(umean / 16.f);
3655 usig = (usig > 0 ? sqrtf(usig) : 0);
3656 vsig = vsig / 16.f - SQR(vmean / 16.f);
3657 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
3658 wsig = wsig / 16.f - SQR(wmean / 16.f);
3659 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
3660
3661 /* Set temporal correlations for mesoscale fluctuations... */
3662 const double r = 1 - 2 * fabs(cache->dt[ip]) / ctl->dt_met;
3663 const double r2 = sqrt(1 - r * r);
3664
3665 /* Calculate horizontal mesoscale wind fluctuations... */
3666 if (ctl->turb_mesox > 0) {
3667 cache->uvwp[ip][0] =
3668 (float) (r * cache->uvwp[ip][0] +
3669 r2 * cache->rs[3 * ip] * ctl->turb_mesox * usig);
3670 atm->lon[ip] +=
3671 DX2DEG(cache->uvwp[ip][0] * cache->dt[ip] / 1000., atm->lat[ip]);
3672
3673 cache->uvwp[ip][1] =
3674 (float) (r * cache->uvwp[ip][1] +
3675 r2 * cache->rs[3 * ip + 1] * ctl->turb_mesox * vsig);
3676 atm->lat[ip] += DY2DEG(cache->uvwp[ip][1] * cache->dt[ip] / 1000.);
3677 }
3678
3679 /* Calculate vertical mesoscale wind fluctuations... */
3680 if (ctl->turb_mesoz > 0) {
3681 cache->uvwp[ip][2] =
3682 (float) (r * cache->uvwp[ip][2] +
3683 r2 * cache->rs[3 * ip + 2] * ctl->turb_mesoz * wsig);
3684 atm->p[ip] += cache->uvwp[ip][2] * cache->dt[ip];
3685 }
3686 }
3687}
float uvwp[NP][3]
Wind perturbations [m/s].
Definition: mptrac.h:3367
double turb_mesoz
Vertical scaling factor for mesoscale wind fluctuations.
Definition: mptrac.h:2812
double dt_met
Time step of meteo data [s].
Definition: mptrac.h:2593
double turb_mesox
Horizontal scaling factor for mesoscale wind fluctuations.
Definition: mptrac.h:2809
Here is the call graph for this function:

◆ module_diff_pbl()

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

Computes particle diffusion within the planetary boundary layer (PBL).

This function handles the effects of turbulence on particles within the PBL. It calculates turbulent velocity variances, Lagrangian timescales, and updates particle positions and perturbations based on random fluctuations and boundary layer physics. This module adapts the approach of Ryall and Maryon (1998) and Stohl et al. (2005).

Parameters
ctlPointer to the control structure containing model settings.
cachePointer to the cache structure for temporary data and random numbers.
met0Pointer to the meteorological data structure for the current timestep.
met1Pointer to the meteorological data structure for the next timestep.
atmPointer to the atmospheric data structure containing particle states.

The function:

  • Allocates memory for random numbers and generates them using module_rng.
  • Loops over all particles to compute their behavior within the boundary layer.
  • Handles both stable/neutral and unstable conditions based on the surface sensible heat flux.
  • Calculates turbulent velocity variances (sig_u, sig_w), their vertical derivatives, and Lagrangian timescales (tau_u, tau_w).
  • Updates particle velocity perturbations and positions using turbulent diffusion equations.

The function uses OpenACC directives for GPU acceleration.

Note
The function handles edge cases like zero diffusivity and imposes minimum limits on calculated values to ensure stability.
Warning
Ensure that all input pointers are properly initialized and accessible before calling this function.
Author
Lars Hoffmann

Definition at line 3691 of file mptrac.c.

3696 {
3697
3698 /* Set timer... */
3699 SELECT_TIMER("MODULE_DIFF_PBL", "PHYSICS", NVTX_GPU);
3700
3701 /* Create random numbers... */
3702 module_rng(ctl, cache->rs, 3 * (size_t) atm->np, 1);
3703
3704 /* Loop over particles... */
3705 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
3706
3707 double dsigw_dz = 0.0, sig_u = 0.25, sig_w = 0.1,
3708 tau_u = 300., tau_w = 100.;
3709
3710 /* Get surface and PBL pressure... */
3711 double pbl, ps;
3713 INTPOL_2D(ps, 1);
3714 INTPOL_2D(pbl, 0);
3715
3716 /* Boundary layer... */
3717 if (atm->p[ip] >= pbl) {
3718
3719 /* Calculate heights... */
3720 const double p = MIN(atm->p[ip], ps);
3721 const double zs = Z(ps);
3722 const double z = 1e3 * (Z(p) - zs);
3723 const double zi = 1e3 * (Z(pbl) - zs);
3724 const double zratio = z / zi;
3725
3726 /* Calculate friction velocity... */
3727 double ess, nss, h2o, t;
3728 INTPOL_2D(ess, 0);
3729 INTPOL_2D(nss, 0);
3730 INTPOL_3D(t, 1);
3731 INTPOL_3D(h2o, 0);
3732 const double rho = RHO(p, TVIRT(t, h2o));
3733 const double tau = sqrt(SQR(ess) + SQR(nss));
3734 const double ustar = sqrt(tau / rho);
3735
3736 /* Get surface sensible heat flux... */
3737 double shf;
3738 INTPOL_2D(shf, 1);
3739
3740 /* Stable or neutral conditions... */
3741 if (shf <= 0) {
3742
3743 /* Calcalute turbulent velocity variances... */
3744 sig_u = 1e-2 + 2.0 * ustar * (1.0 - zratio);
3745 sig_w = 1e-2 + 1.3 * ustar * (1.0 - zratio);
3746
3747 /* Calculate derivative dsig_w/dz... */
3748 dsigw_dz = -1.3 * ustar / zi;
3749
3750 /* Calcalute Lagrangian timescales... */
3751 tau_u = 0.07 * zi / sig_u * sqrt(zratio);
3752 tau_w = 0.1 * zi / sig_w * pow(zratio, 0.8);
3753 }
3754
3755 /* Unstable conditions... */
3756 else {
3757
3758 /* Convective velocity... */
3759 const double wstar =
3760 pow(G0 / THETAVIRT(p, t, h2o) * shf / (rho * CPD) * zi, 1. / 3.);
3761
3762 /* Calcalute turbulent velocity variances... */
3763 sig_u = 1e-2
3764 + sqrt(0.4 * SQR(wstar) + (5.0 - 4.0 * zratio) * SQR(ustar));
3765 sig_w = 1e-2 + sqrt(1.2 * SQR(wstar) * (1.0 - 0.9 * zratio)
3766 * pow(zratio, 2.0 / 3.0)
3767 + (1.8 - 1.4 * zratio) * SQR(ustar));
3768
3769 /* Calculate derivative dsig_w/dz... */
3770 dsigw_dz = 0.5 / sig_w / zi * (-1.4 * SQR(ustar) + SQR(wstar)
3771 * (0.8 *
3772 pow(MAX(zratio, 1e-3), -1.0 / 3.0)
3773 - 1.8 * pow(zratio, 2.0 / 3.0)));
3774
3775 /* Calculate Lagrangian timescales... */
3776 const double C0 = 3.0; // TODO: typically 3...6, NAME model uses 3?
3777 const double eps =
3778 (1.5 - 1.2 * pow(zratio, 1.0 / 3.0)) * SQR(wstar) * wstar / zi
3779 + SQR(ustar) * ustar * (1.0 - 0.8 * zratio) / (KARMAN * z);
3780 tau_u = 2 * SQR(sig_u) / (C0 * eps);
3781 tau_w = 2 * SQR(sig_w) / (C0 * eps);
3782 }
3783 }
3784
3785 /* Set minimum values... */
3786 sig_u = MAX(sig_u, 0.25);
3787 sig_w = MAX(sig_w, 0.1);
3788 tau_u = MAX(tau_u, 300.);
3789 tau_w = MAX(tau_w, 100.);
3790
3791 /* Update perturbations... */
3792 const double ru = exp(-fabs(cache->dt[ip]) / tau_u);
3793 const double ru2 = sqrt(1.0 - SQR(ru));
3794 cache->uvwp[ip][0]
3795 = (float) (cache->uvwp[ip][0] * ru + ru2 * cache->rs[3 * ip]);
3796 cache->uvwp[ip][1]
3797 = (float) (cache->uvwp[ip][1] * ru + ru2 * cache->rs[3 * ip + 1]);
3798
3799 const double rw = exp(-fabs(cache->dt[ip]) / tau_w);
3800 const double rw2 = sqrt(1.0 - SQR(rw));
3801 cache->uvwp[ip][2]
3802 = (float) (cache->uvwp[ip][2] * rw + rw2 * cache->rs[3 * ip + 2]
3803 + sig_w * dsigw_dz * cache->dt[ip]); // TODO: check approx for density correction?
3804
3805 /* Calculate new air parcel position... */
3806 atm->lon[ip] +=
3807 DX2DEG(cache->uvwp[ip][0] * cache->dt[ip] / 1000., atm->lat[ip]);
3808 atm->lat[ip] += DY2DEG(cache->uvwp[ip][1] * cache->dt[ip] / 1000.);
3809 atm->p[ip] +=
3810 DZ2DP(cache->uvwp[ip][2] * cache->dt[ip] / 1000., atm->p[ip]);
3811 }
3812}
#define KARMAN
Karman's constant.
Definition: mptrac.h:229
#define THETAVIRT(p, t, h2o)
Compute virtual potential temperature.
Definition: mptrac.h:1812
#define DZ2DP(dz, p)
Convert a change in altitude to a change in pressure.
Definition: mptrac.h:651
Here is the call graph for this function:

◆ module_diff_turb()

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

Applies turbulent diffusion processes to atmospheric particles.

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

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

The function performs the following operations:

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

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

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

Definition at line 3816 of file mptrac.c.

3822 {
3823
3824 /* Set timer... */
3825 SELECT_TIMER("MODULE_DIFF_TURB", "PHYSICS", NVTX_GPU);
3826
3827 /* Create random numbers... */
3828 module_rng(ctl, cache->rs, 3 * (size_t) atm->np, 1);
3829
3830 /* Loop over particles... */
3831 PARTICLE_LOOP(0, atm->np, 1,
3832 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3833
3834 /* Get PBL and surface pressure... */
3835 double pbl, ps;
3837 INTPOL_2D(pbl, 1);
3838 INTPOL_2D(ps, 0);
3839
3840 /* Get weighting factors... */
3841 const double wpbl = pbl_weight(ctl, atm, ip, pbl, ps);
3842 const double wtrop = tropo_weight(clim, atm, ip) * (1.0 - wpbl);
3843 const double wstrat = 1.0 - wpbl - wtrop;
3844
3845 /* Set diffusivity... */
3846 const double dx = wpbl * ctl->turb_dx_pbl + wtrop * ctl->turb_dx_trop
3847 + wstrat * ctl->turb_dx_strat;
3848 const double dz = wpbl * ctl->turb_dz_pbl + wtrop * ctl->turb_dz_trop
3849 + wstrat * ctl->turb_dz_strat;
3850
3851 /* Horizontal turbulent diffusion... */
3852 if (dx > 0) {
3853 const double sigma = sqrt(2.0 * dx * fabs(cache->dt[ip])) / 1000.;
3854 atm->lon[ip] += DX2DEG(cache->rs[3 * ip] * sigma, atm->lat[ip]);
3855 atm->lat[ip] += DY2DEG(cache->rs[3 * ip + 1] * sigma);
3856 }
3857
3858 /* Vertical turbulent diffusion... */
3859 if (dz > 0) {
3860 const double sigma = sqrt(2.0 * dz * fabs(cache->dt[ip])) / 1000.;
3861 atm->p[ip] += DZ2DP(cache->rs[3 * ip + 2] * sigma, atm->p[ip]);
3862 }
3863 }
3864}
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:6997
double turb_dz_trop
Vertical turbulent diffusion coefficient (troposphere) [m^2/s].
Definition: mptrac.h:2803
double turb_dx_strat
Horizontal turbulent diffusion coefficient (stratosphere) [m^2/s].
Definition: mptrac.h:2797
double turb_dx_trop
Horizontal turbulent diffusion coefficient (troposphere) [m^2/s].
Definition: mptrac.h:2794
double turb_dx_pbl
Horizontal turbulent diffusion coefficient (PBL) [m^2/s].
Definition: mptrac.h:2791
double turb_dz_strat
Vertical turbulent diffusion coefficient (stratosphere) [m^2/s].
Definition: mptrac.h:2806
double turb_dz_pbl
Vertical turbulent diffusion coefficient (PBL) [m^2/s].
Definition: mptrac.h:2800
Here is the call graph for this function:

◆ module_dry_depo()

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

Simulate dry deposition of atmospheric particles.

This function simulates the dry deposition of atmospheric particles, including both particulate matter and gases. It calculates the sedimentation velocity for particles based on the atmospheric properties and applies it to determine the loss of mass or volume mixing ratio due to deposition. The function loops over each particle and calculates the loss of mass or volume mixing ratio based on the deposition velocity and time step.

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

Definition at line 3868 of file mptrac.c.

3873 {
3874
3875 /* Set timer... */
3876 SELECT_TIMER("MODULE_DRY_DEPO", "PHYSICS", NVTX_GPU);
3877
3878 /* Check quantity flags... */
3879 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
3880 ERRMSG("Module needs quantity mass or volume mixing ratio!");
3881
3882 /* Loop over particles... */
3883 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
3884
3885 /* Get surface pressure... */
3886 double ps;
3888 INTPOL_2D(ps, 1);
3889
3890 /* Check whether particle is above the surface layer... */
3891 if (atm->p[ip] < ps - ctl->dry_depo_dp)
3892 continue;
3893
3894 /* Set depth of surface layer... */
3895 const double dz = 1000. * (Z(ps - ctl->dry_depo_dp) - Z(ps));
3896
3897 /* Calculate sedimentation velocity for particles... */
3898 double v_dep;
3899 if (ctl->qnt_rp > 0 && ctl->qnt_rhop > 0) {
3900
3901 /* Get temperature... */
3902 double t;
3903 INTPOL_3D(t, 1);
3904
3905 /* Set deposition velocity... */
3906 v_dep = sedi(atm->p[ip], t, atm->q[ctl->qnt_rp][ip],
3907 atm->q[ctl->qnt_rhop][ip]);
3908 }
3909
3910 /* Use explicit sedimentation velocity for gases... */
3911 else
3912 v_dep = ctl->dry_depo_vdep;
3913
3914 /* Calculate loss of mass based on deposition velocity... */
3915 const double aux = exp(-cache->dt[ip] * v_dep / dz);
3916 if (ctl->qnt_m >= 0) {
3917 if (ctl->qnt_mloss_dry >= 0)
3918 atm->q[ctl->qnt_mloss_dry][ip]
3919 += atm->q[ctl->qnt_m][ip] * (1 - aux);
3920 atm->q[ctl->qnt_m][ip] *= aux;
3921 if (ctl->qnt_loss_rate >= 0)
3922 atm->q[ctl->qnt_loss_rate][ip] += v_dep / dz;
3923 }
3924 if (ctl->qnt_vmr >= 0)
3925 atm->q[ctl->qnt_vmr][ip] *= aux;
3926 }
3927}
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:11023
int qnt_rhop
Quantity array index for particle density.
Definition: mptrac.h:2304
int qnt_rp
Quantity array index for particle radius.
Definition: mptrac.h:2301
double dry_depo_dp
Dry deposition surface layer [hPa].
Definition: mptrac.h:3028
int qnt_mloss_dry
Quantity array index for total mass loss due to dry deposition.
Definition: mptrac.h:2448
double dry_depo_vdep
Dry deposition velocity [m/s].
Definition: mptrac.h:3031
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 3931 of file mptrac.c.

3937 {
3938
3939 /* Set timer... */
3940 SELECT_TIMER("MODULE_H2O2_CHEM", "PHYSICS", NVTX_GPU);
3941
3942 /* Check quantity flags... */
3943 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
3944 ERRMSG("Module needs quantity mass or volume mixing ratio!");
3945
3946 /* Parameter of SO2 correction... */
3947 const double a = 3.12541941e-06;
3948 const double b = -5.72532259e-01;
3949 const double low = pow(1. / a, 1. / b);
3950
3951 /* Loop over particles... */
3952 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
3953
3954 /* Check whether particle is inside cloud... */
3955 double lwc, rwc;
3957 INTPOL_3D(lwc, 1);
3958 INTPOL_3D(rwc, 0);
3959 if (!(lwc > 0 || rwc > 0))
3960 continue;
3961
3962 /* Get temperature... */
3963 double t;
3964 INTPOL_3D(t, 0);
3965
3966 /* Get molecular density... */
3967 const double M = MOLEC_DENS(atm->p[ip], t);
3968
3969 /* Reaction rate (Berglen et al., 2004)... */
3970 const double k = 9.1e7 * exp(-29700. / RI * (1. / t - 1. / 298.15)); /* (Maass, 1999), unit: M^(-2) */
3971
3972 /* Henry constant of SO2... */
3973 const double H_SO2 =
3974 1.3e-2 * exp(2900. * (1. / t - 1. / 298.15)) * RI * t;
3975 const double K_1S = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15)); /* unit: mol/L */
3976
3977 /* Henry constant of H2O2... */
3978 const double H_h2o2 =
3979 8.3e2 * exp(7600. * (1. / t - 1. / 298.15)) * RI * t;
3980
3981 /* Correction factor for high SO2 concentration
3982 (if qnt_Cx is defined, the correction is switched on)... */
3983 double cor = 1.0;
3984 if (ctl->qnt_Cx >= 0)
3985 cor = atm->q[ctl->qnt_Cx][ip] >
3986 low ? a * pow(atm->q[ctl->qnt_Cx][ip], b) : 1;
3987
3988 const double h2o2 = H_h2o2
3989 * clim_zm(&clim->h2o2, atm->time[ip], atm->lat[ip], atm->p[ip])
3990 * M * cor * 1000. / AVO; /* unit: mol/L */
3991
3992 /* Volume water content in cloud [m^3 m^(-3)]... */
3993 const double rho_air = atm->p[ip] / (RI * t) * MA / 10.;
3994 const double CWC = (lwc + rwc) * rho_air / 1e3;
3995
3996 /* Calculate exponential decay (Rolph et al., 1992)... */
3997 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
3998 const double aux = exp(-cache->dt[ip] * rate_coef);
3999 if (ctl->qnt_m >= 0) {
4000 if (ctl->qnt_mloss_h2o2 >= 0)
4001 atm->q[ctl->qnt_mloss_h2o2][ip] += atm->q[ctl->qnt_m][ip] * (1 - aux);
4002 atm->q[ctl->qnt_m][ip] *= aux;
4003 if (ctl->qnt_loss_rate >= 0)
4004 atm->q[ctl->qnt_loss_rate][ip] += rate_coef;
4005 }
4006 if (ctl->qnt_vmr >= 0)
4007 atm->q[ctl->qnt_vmr][ip] *= aux;
4008 }
4009}
#define AVO
Avogadro constant [1/mol].
Definition: mptrac.h:199
#define MOLEC_DENS(p, t)
Calculate the density of a gas molecule.
Definition: mptrac.h:1153
int qnt_mloss_h2o2
Quantity array index for total mass loss due to H2O2 chemistry.
Definition: mptrac.h:2439
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 4013 of file mptrac.c.

4018 {
4019
4020 double t;
4021
4022 /* Set timer... */
4023 SELECT_TIMER("MODULE_ISOSURF_INIT", "PHYSICS", NVTX_GPU);
4024
4025 /* Save pressure... */
4026 if (ctl->isosurf == 1) {
4027 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,atm)") {
4028 cache->iso_var[ip] = atm->p[ip];
4029 }
4030 }
4031
4032 /* Save density... */
4033 else if (ctl->isosurf == 2) {
4034 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,met0,met1,atm)") {
4036 INTPOL_3D(t, 1);
4037 cache->iso_var[ip] = atm->p[ip] / t;
4038 }
4039 }
4040
4041 /* Save potential temperature... */
4042 else if (ctl->isosurf == 3) {
4043 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,met0,met1,atm)") {
4045 INTPOL_3D(t, 1);
4046 cache->iso_var[ip] = THETA(atm->p[ip], t);
4047 }
4048 }
4049
4050 /* Read balloon pressure data... */
4051 else if (ctl->isosurf == 4) {
4052
4053 /* Write info... */
4054 LOG(1, "Read balloon pressure data: %s", ctl->balloon);
4055
4056 /* Open file... */
4057 FILE *in;
4058 if (!(in = fopen(ctl->balloon, "r")))
4059 ERRMSG("Cannot open file!");
4060
4061 /* Read pressure time series... */
4062 char line[LEN];
4063 while (fgets(line, LEN, in))
4064 if (sscanf(line, "%lg %lg", &(cache->iso_ts[cache->iso_n]),
4065 &(cache->iso_ps[cache->iso_n])) == 2)
4066 if ((++cache->iso_n) > NP)
4067 ERRMSG("Too many data points!");
4068
4069 /* Check number of points... */
4070 if (cache->iso_n < 1)
4071 ERRMSG("Could not read any data!");
4072
4073 /* Close file... */
4074 fclose(in);
4075
4076 /* Update of cache data on device... */
4077 mptrac_update_device(NULL, cache, NULL, NULL, NULL, NULL);
4078 }
4079}
void mptrac_update_device(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates device memory for specified data structures.
Definition: mptrac.c:6666
#define NP
Maximum number of atmospheric data points.
Definition: mptrac.h:308
double iso_ts[NP]
Isosurface balloon time [s].
Definition: mptrac.h:3361
int iso_n
Isosurface balloon number of data points.
Definition: mptrac.h:3364
double iso_ps[NP]
Isosurface balloon pressure [hPa].
Definition: mptrac.h:3358
double iso_var[NP]
Isosurface variables.
Definition: mptrac.h:3355
char balloon[LEN]
Balloon position filename.
Definition: mptrac.h:2775
int isosurf
Isosurface parameter (0=none, 1=pressure, 2=density, 3=theta, 4=balloon).
Definition: mptrac.h:2772
Here is the call graph for this function:

◆ module_isosurf()

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

Apply the isosurface module to adjust atmospheric properties.

This function applies the isosurface module to adjust atmospheric properties based on the initialized data stored in the cache. It interpolates and restores atmospheric pressure, density, or potential temperature according to the specified isosurface mode in the control structure.

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

Definition at line 4083 of file mptrac.c.

4088 {
4089
4090 /* Set timer... */
4091 SELECT_TIMER("MODULE_ISOSURF", "PHYSICS", NVTX_GPU);
4092
4093 /* Loop over particles... */
4094 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,cache,met0,met1,atm)") {
4095
4096 /* Init... */
4097 double t;
4099
4100 /* Restore pressure... */
4101 if (ctl->isosurf == 1)
4102 atm->p[ip] = cache->iso_var[ip];
4103
4104 /* Restore density... */
4105 else if (ctl->isosurf == 2) {
4106 INTPOL_3D(t, 1);
4107 atm->p[ip] = cache->iso_var[ip] * t;
4108 }
4109
4110 /* Restore potential temperature... */
4111 else if (ctl->isosurf == 3) {
4112 INTPOL_3D(t, 1);
4113 atm->p[ip] = 1000. * pow(cache->iso_var[ip] / t, -1. / 0.286);
4114 }
4115
4116 /* Interpolate pressure... */
4117 else if (ctl->isosurf == 4) {
4118 if (atm->time[ip] <= cache->iso_ts[0])
4119 atm->p[ip] = cache->iso_ps[0];
4120 else if (atm->time[ip] >= cache->iso_ts[cache->iso_n - 1])
4121 atm->p[ip] = cache->iso_ps[cache->iso_n - 1];
4122 else {
4123 const int idx =
4124 locate_irr(cache->iso_ts, cache->iso_n, atm->time[ip]);
4125 atm->p[ip] =
4126 LIN(cache->iso_ts[idx], cache->iso_ps[idx], cache->iso_ts[idx + 1],
4127 cache->iso_ps[idx + 1], atm->time[ip]);
4128 }
4129 }
4130 }
4131}
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 4189 of file mptrac.c.

4195 {
4196
4197 /* Set timer... */
4198 SELECT_TIMER("MODULE_METEO", "PHYSICS", NVTX_GPU);
4199
4200 /* Check quantity flags... */
4201 if (ctl->qnt_tsts >= 0)
4202 if (ctl->qnt_tice < 0 || ctl->qnt_tnat < 0)
4203 ERRMSG("Need T_ice and T_NAT to calculate T_STS!");
4204
4205 /* Loop over particles... */
4206 PARTICLE_LOOP(0, atm->np, 0,
4207 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4208
4209 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
4210 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
4211 o3, lwc, rwc, iwc, swc, cc, z, zt;
4212
4213 /* Interpolate meteo data... */
4215 INTPOL_TIME_ALL(atm->time[ip], atm->p[ip], atm->lon[ip], atm->lat[ip]);
4216
4217 /* Set quantities... */
4218 SET_ATM(qnt_ps, ps);
4219 SET_ATM(qnt_ts, ts);
4220 SET_ATM(qnt_zs, zs);
4221 SET_ATM(qnt_us, us);
4222 SET_ATM(qnt_vs, vs);
4223 SET_ATM(qnt_ess, ess);
4224 SET_ATM(qnt_nss, nss);
4225 SET_ATM(qnt_shf, shf);
4226 SET_ATM(qnt_lsm, lsm);
4227 SET_ATM(qnt_sst, sst);
4228 SET_ATM(qnt_pbl, pbl);
4229 SET_ATM(qnt_pt, pt);
4230 SET_ATM(qnt_tt, tt);
4231 SET_ATM(qnt_zt, zt);
4232 SET_ATM(qnt_h2ot, h2ot);
4233 SET_ATM(qnt_zg, z);
4234 SET_ATM(qnt_p, atm->p[ip]);
4235 SET_ATM(qnt_t, t);
4236 SET_ATM(qnt_rho, RHO(atm->p[ip], t));
4237 SET_ATM(qnt_u, u);
4238 SET_ATM(qnt_v, v);
4239 SET_ATM(qnt_w, w);
4240 SET_ATM(qnt_h2o, h2o);
4241 SET_ATM(qnt_o3, o3);
4242 SET_ATM(qnt_lwc, lwc);
4243 SET_ATM(qnt_rwc, rwc);
4244 SET_ATM(qnt_iwc, iwc);
4245 SET_ATM(qnt_swc, swc);
4246 SET_ATM(qnt_cc, cc);
4247 SET_ATM(qnt_pct, pct);
4248 SET_ATM(qnt_pcb, pcb);
4249 SET_ATM(qnt_cl, cl);
4250 SET_ATM(qnt_plcl, plcl);
4251 SET_ATM(qnt_plfc, plfc);
4252 SET_ATM(qnt_pel, pel);
4253 SET_ATM(qnt_cape, cape);
4254 SET_ATM(qnt_cin, cin);
4255 SET_ATM(qnt_o3c, o3c);
4256 SET_ATM(qnt_hno3,
4257 clim_zm(&clim->hno3, atm->time[ip], atm->lat[ip], atm->p[ip]));
4258 SET_ATM(qnt_oh, clim_oh(ctl, clim, atm->time[ip],
4259 atm->lon[ip], atm->lat[ip], atm->p[ip]));
4260 SET_ATM(qnt_h2o2, clim_zm(&clim->h2o2, atm->time[ip],
4261 atm->lat[ip], atm->p[ip]));
4262 SET_ATM(qnt_ho2, clim_zm(&clim->ho2, atm->time[ip],
4263 atm->lat[ip], atm->p[ip]));
4264 SET_ATM(qnt_o1d, clim_zm(&clim->o1d, atm->time[ip],
4265 atm->lat[ip], atm->p[ip]));
4266 SET_ATM(qnt_vh, sqrt(u * u + v * v));
4267 SET_ATM(qnt_vz, -1e3 * H0 / atm->p[ip] * w);
4268 SET_ATM(qnt_psat, PSAT(t));
4269 SET_ATM(qnt_psice, PSICE(t));
4270 SET_ATM(qnt_pw, PW(atm->p[ip], h2o));
4271 SET_ATM(qnt_sh, SH(h2o));
4272 SET_ATM(qnt_rh, RH(atm->p[ip], t, h2o));
4273 SET_ATM(qnt_rhice, RHICE(atm->p[ip], t, h2o));
4274 SET_ATM(qnt_theta, THETA(atm->p[ip], t));
4275 SET_ATM(qnt_zeta, atm->q[ctl->qnt_zeta][ip]);
4276 SET_ATM(qnt_zeta_d, ZETA(ps, atm->p[ip], t));
4277 SET_ATM(qnt_zeta_dot, atm->q[ctl->qnt_zeta_dot][ip]);
4278 SET_ATM(qnt_eta, atm->q[ctl->qnt_eta][ip]);
4279 SET_ATM(qnt_eta_dot, atm->q[ctl->qnt_eta_dot][ip]);
4280 SET_ATM(qnt_tvirt, TVIRT(t, h2o));
4281 SET_ATM(qnt_lapse, lapse_rate(t, h2o));
4282 SET_ATM(qnt_pv, pv);
4283 SET_ATM(qnt_tdew, TDEW(atm->p[ip], h2o));
4284 SET_ATM(qnt_tice, TICE(atm->p[ip], h2o));
4285 SET_ATM(qnt_tnat,
4286 nat_temperature(atm->p[ip], h2o,
4287 clim_zm(&clim->hno3, atm->time[ip],
4288 atm->lat[ip], atm->p[ip])));
4289 SET_ATM(qnt_tsts,
4290 0.5 * (atm->q[ctl->qnt_tice][ip] + atm->q[ctl->qnt_tnat][ip]));
4291 }
4292}
double nat_temperature(const double p, const double h2o, const double hno3)
Calculates the nitric acid trihydrate (NAT) temperature.
Definition: mptrac.c:6973
double lapse_rate(const double t, const double h2o)
Calculates the moist adiabatic lapse rate in Kelvin per kilometer.
Definition: mptrac.c:2641
#define H0
Scale height [km].
Definition: mptrac.h:219
#define PSICE(t)
Compute saturation pressure over ice (WMO, 2018).
Definition: mptrac.h:1491
#define TICE(p, h2o)
Calculate frost point temperature (WMO, 2018).
Definition: mptrac.h:1759
#define RHICE(p, t, h2o)
Compute relative humidity over ice.
Definition: mptrac.h:1595
#define INTPOL_TIME_ALL(time, p, lon, lat)
Interpolate multiple meteorological variables in time.
Definition: mptrac.h:937
#define RH(p, t, h2o)
Compute relative humidity over water.
Definition: mptrac.h:1565
#define TDEW(p, h2o)
Calculate dew point temperature.
Definition: mptrac.h:1734
#define PSAT(t)
Compute saturation pressure over water.
Definition: mptrac.h:1467
clim_zm_t hno3
HNO3 zonal means.
Definition: mptrac.h:3513
int qnt_tnat
Quantity array index for T_NAT.
Definition: mptrac.h:2517
int qnt_eta_dot
Quantity array index for velocity of eta vertical coordinate.
Definition: mptrac.h:2490
int qnt_tice
Quantity array index for T_ice.
Definition: mptrac.h:2511
int qnt_zeta_dot
Quantity array index for velocity of zeta vertical coordinate.
Definition: mptrac.h:2484
int qnt_tsts
Quantity array index for T_STS.
Definition: mptrac.h:2514
Here is the call graph for this function:

◆ module_mixing()

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

Update atmospheric properties through interparcel mixing.

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

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

Definition at line 4296 of file mptrac.c.

4300 {
4301
4302 /* Set timer... */
4303 SELECT_TIMER("MODULE_MIXING", "PHYSICS", NVTX_GPU);
4304
4305 /* Allocate... */
4306 const int np = atm->np;
4307 int *restrict const ixs = (int *) malloc((size_t) np * sizeof(int));
4308 int *restrict const iys = (int *) malloc((size_t) np * sizeof(int));
4309 int *restrict const izs = (int *) malloc((size_t) np * sizeof(int));
4310
4311 /* Set grid box size... */
4312 const double dz = (ctl->mixing_z1 - ctl->mixing_z0) / ctl->mixing_nz;
4313 const double dlon = (ctl->mixing_lon1 - ctl->mixing_lon0) / ctl->mixing_nx;
4314 const double dlat = (ctl->mixing_lat1 - ctl->mixing_lat0) / ctl->mixing_ny;
4315
4316 /* Set time interval... */
4317 const double t0 = t - 0.5 * ctl->dt_mod;
4318 const double t1 = t + 0.5 * ctl->dt_mod;
4319
4320 /* Get indices... */
4321#ifdef _OPENACC
4322#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
4323#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
4324#pragma acc parallel loop independent gang vector
4325#else
4326#pragma omp parallel for default(shared)
4327#endif
4328 for (int ip = 0; ip < np; ip++) {
4329 ixs[ip] = (int) ((atm->lon[ip] - ctl->mixing_lon0) / dlon);
4330 iys[ip] = (int) ((atm->lat[ip] - ctl->mixing_lat0) / dlat);
4331 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->mixing_z0) / dz);
4332 if (atm->time[ip] < t0 || atm->time[ip] > t1
4333 || ixs[ip] < 0 || ixs[ip] >= ctl->mixing_nx
4334 || iys[ip] < 0 || iys[ip] >= ctl->mixing_ny
4335 || izs[ip] < 0 || izs[ip] >= ctl->mixing_nz)
4336 izs[ip] = -1;
4337 }
4338
4339 /* Calculate interparcel mixing... */
4340 const int use_ensemble = (ctl->nens > 0);
4341
4342 const int quantities[] = {
4343 ctl->qnt_m, ctl->qnt_vmr, ctl->qnt_Ch2o, ctl->qnt_Co3,
4344 ctl->qnt_Cco, ctl->qnt_Coh, ctl->qnt_Ch, ctl->qnt_Cho2,
4345 ctl->qnt_Ch2o2, ctl->qnt_Co1d, ctl->qnt_Co3p, ctl->qnt_Cccl4,
4346 ctl->qnt_Cccl3f, ctl->qnt_Cccl2f2, ctl->qnt_Cn2o,
4347 ctl->qnt_Csf6, ctl->qnt_aoa
4348 };
4349 const int n_qnt = sizeof(quantities) / sizeof(quantities[0]);
4350
4351 for (int i = 0; i < n_qnt; i++)
4352 if (quantities[i] >= 0)
4353 module_mixing_help(ctl, clim, atm, ixs, iys, izs, quantities[i],
4354 use_ensemble);
4355
4356 /* Free... */
4357#ifdef _OPENACC
4358#pragma acc exit data delete(ixs,iys,izs)
4359#endif
4360 free(ixs);
4361 free(iys);
4362 free(izs);
4363}
void module_mixing_help(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const int *ixs, const int *iys, const int *izs, const int qnt_idx, const int use_ensemble)
Perform subgrid-scale interparcel mixing of a given quantity.
Definition: mptrac.c:4367
int qnt_Coh
Quantity array index for OH volume mixing ratio (chemistry code).
Definition: mptrac.h:2532
int mixing_nx
Number of longitudes of mixing grid.
Definition: mptrac.h:2932
double mixing_z1
Upper altitude of mixing grid [km].
Definition: mptrac.h:2929
int qnt_Co1d
Quantity array index for O(1D) volume mixing ratio (chemistry code).
Definition: mptrac.h:2544
double mixing_z0
Lower altitude of mixing grid [km].
Definition: mptrac.h:2926
int qnt_Cco
Quantity array index for CO volume mixing ratio (chemistry code).
Definition: mptrac.h:2529
int mixing_ny
Number of latitudes of mixing grid.
Definition: mptrac.h:2941
int qnt_Ch
Quantity array index for H volume mixing ratio (chemistry code).
Definition: mptrac.h:2535
double mixing_lat0
Lower latitude of mixing grid [deg].
Definition: mptrac.h:2944
int qnt_Cho2
Quantity array index for HO2 volume mixing ratio (chemistry code).
Definition: mptrac.h:2538
int mixing_nz
Number of altitudes of mixing grid.
Definition: mptrac.h:2923
double mixing_lon0
Lower longitude of mixing grid [deg].
Definition: mptrac.h:2935
double mixing_lat1
Upper latitude of mixing grid [deg].
Definition: mptrac.h:2947
int qnt_Co3p
Quantity array index for O(3P) volume mixing ratio (chemistry code).
Definition: mptrac.h:2547
int qnt_Ch2o2
Quantity array index for H2O2 volume mixing ratio (chemistry code).
Definition: mptrac.h:2541
double mixing_lon1
Upper longitude of mixing grid [deg].
Definition: mptrac.h:2938
Here is the call graph for this function:

◆ module_mixing_help()

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

Perform subgrid-scale interparcel mixing of a given quantity.

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

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

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

Definition at line 4367 of file mptrac.c.

4375 {
4376
4377 const int np = atm->np;
4378 const int ngrid = ctl->mixing_nx * ctl->mixing_ny * ctl->mixing_nz;
4379 const int nens = use_ensemble ? ctl->nens : 1;
4380 const int total_grid = ngrid * nens;
4381
4382 double *restrict const cmean =
4383 (double *) malloc((size_t) total_grid * sizeof(double));
4384 int *restrict const count =
4385 (int *) malloc((size_t) total_grid * sizeof(int));
4386
4387 /* Init... */
4388#ifdef _OPENACC
4389#pragma acc enter data create(cmean[0:total_grid],count[0:total_grid])
4390#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
4391#pragma acc parallel loop independent gang vector
4392#else
4393#ifdef __NVCOMPILER
4394#pragma novector
4395#endif
4396#pragma omp parallel for
4397#endif
4398 for (int i = 0; i < total_grid; i++) {
4399 count[i] = 0;
4400 cmean[i] = 0.0;
4401 }
4402
4403 /* Loop over particles... */
4404#ifdef _OPENACC
4405#pragma acc parallel loop independent gang vector
4406#endif
4407 for (int ip = 0; ip < np; ip++)
4408 if (izs[ip] >= 0) {
4409 const int ens = use_ensemble ? (int) atm->q[ctl->qnt_ens][ip] : 0;
4410 const int idx =
4411 ens * ngrid + ARRAY_3D(ixs[ip], iys[ip], ctl->mixing_ny, izs[ip],
4412 ctl->mixing_nz);
4413#ifdef _OPENACC
4414#pragma acc atomic update
4415#endif
4416 cmean[idx] += atm->q[qnt_idx][ip];
4417#ifdef _OPENACC
4418#pragma acc atomic update
4419#endif
4420 count[idx]++;
4421 }
4422
4423 /* Compute means... */
4424#ifdef _OPENACC
4425#pragma acc parallel loop independent gang vector
4426#else
4427#ifdef __NVCOMPILER
4428#pragma novector
4429#endif
4430#pragma omp parallel for
4431#endif
4432 for (int i = 0; i < total_grid; i++)
4433 if (count[i] > 0)
4434 cmean[i] /= count[i];
4435
4436 /* Interparcel mixing... */
4437#ifdef _OPENACC
4438#pragma acc parallel loop independent gang vector
4439#else
4440#pragma omp parallel for
4441#endif
4442 for (int ip = 0; ip < np; ip++) {
4443 if (izs[ip] >= 0) {
4444 const int ens = use_ensemble ? (int) atm->q[ctl->qnt_ens][ip] : 0;
4445
4446 double mixparam = 1.0;
4447 if (ctl->mixing_trop < 1 || ctl->mixing_strat < 1) {
4448 const double w = tropo_weight(clim, atm, ip);
4449 mixparam = w * ctl->mixing_trop + (1.0 - w) * ctl->mixing_strat;
4450 }
4451
4452 const int idx =
4453 ens * ngrid + ARRAY_3D(ixs[ip], iys[ip], ctl->mixing_ny, izs[ip],
4454 ctl->mixing_nz);
4455 atm->q[qnt_idx][ip] += (cmean[idx] - atm->q[qnt_idx][ip]) * mixparam;
4456 }
4457 }
4458
4459 /* Free... */
4460#ifdef _OPENACC
4461#pragma acc exit data delete(cmean,count)
4462#endif
4463 free(cmean);
4464 free(count);
4465}
double mixing_trop
Interparcel exchange parameter for mixing in the troposphere.
Definition: mptrac.h:2917
double mixing_strat
Interparcel exchange parameter for mixing in the stratosphere.
Definition: mptrac.h:2920
Here is the call graph for this function:

◆ module_oh_chem()

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

Perform hydroxyl chemistry calculations for atmospheric particles.

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

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

Definition at line 4469 of file mptrac.c.

4475 {
4476
4477 /* Set timer... */
4478 SELECT_TIMER("MODULE_OH_CHEM", "PHYSICS", NVTX_GPU);
4479
4480 /* Check quantity flags... */
4481 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
4482 ERRMSG("Module needs quantity mass or volume mixing ratio!");
4483
4484 /* Parameter of SO2 correction... */
4485 const double a = 4.71572206e-08;
4486 const double b = -8.28782867e-01;
4487 const double low = pow(1. / a, 1. / b);
4488
4489 /* Loop over particles... */
4490 PARTICLE_LOOP(0, atm->np, 1,
4491 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4492
4493 /* Get temperature... */
4494 double t;
4496 INTPOL_3D(t, 1);
4497
4498 /* Calculate molecular density... */
4499 const double M = MOLEC_DENS(atm->p[ip], t);
4500
4501 /* Use constant reaction rate... */
4502 double k = NAN;
4503 if (ctl->oh_chem_reaction == 1)
4504 k = ctl->oh_chem[0];
4505
4506 /* Calculate bimolecular reaction rate... */
4507 else if (ctl->oh_chem_reaction == 2)
4508 k = ctl->oh_chem[0] * exp(-ctl->oh_chem[1] / t);
4509
4510 /* Calculate termolecular reaction rate... */
4511 if (ctl->oh_chem_reaction == 3) {
4512
4513 /* Calculate rate coefficient for X + OH + M -> XOH + M
4514 (JPL Publication 19-05) ... */
4515 const double k0 =
4516 ctl->oh_chem[0] * (ctl->oh_chem[1] !=
4517 0 ? pow(298. / t, ctl->oh_chem[1]) : 1.);
4518 const double ki =
4519 ctl->oh_chem[2] * (ctl->oh_chem[3] !=
4520 0 ? pow(298. / t, ctl->oh_chem[3]) : 1.);
4521 const double c = log10(k0 * M / ki);
4522 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
4523 }
4524
4525 /* Correction factor for high SO2 concentration
4526 (if qnt_Cx is defined, the correction is switched on)... */
4527 double cor = 1;
4528 if (ctl->qnt_Cx >= 0)
4529 cor =
4530 atm->q[ctl->qnt_Cx][ip] >
4531 low ? a * pow(atm->q[ctl->qnt_Cx][ip], b) : 1;
4532
4533 /* Calculate exponential decay... */
4534 const double rate_coef =
4535 k * clim_oh(ctl, clim, atm->time[ip], atm->lon[ip],
4536 atm->lat[ip], atm->p[ip]) * M * cor;
4537 const double aux = exp(-cache->dt[ip] * rate_coef);
4538 if (ctl->qnt_m >= 0) {
4539 if (ctl->qnt_mloss_oh >= 0)
4540 atm->q[ctl->qnt_mloss_oh][ip]
4541 += atm->q[ctl->qnt_m][ip] * (1 - aux);
4542 atm->q[ctl->qnt_m][ip] *= aux;
4543 if (ctl->qnt_loss_rate >= 0)
4544 atm->q[ctl->qnt_loss_rate][ip] += rate_coef;
4545 }
4546 if (ctl->qnt_vmr >= 0)
4547 atm->q[ctl->qnt_vmr][ip] *= aux;
4548 }
4549}
double oh_chem[4]
Coefficients for OH reaction rate (A, E/R or k0, n, kinf, m).
Definition: mptrac.h:2980
int oh_chem_reaction
Reaction type for OH chemistry (0=none, 2=bimolecular, 3=termolecular).
Definition: mptrac.h:2977
int qnt_mloss_oh
Quantity array index for total mass loss due to OH chemistry.
Definition: mptrac.h:2436
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 4553 of file mptrac.c.

4557 {
4558
4559 /* Set timer... */
4560 SELECT_TIMER("MODULE_POSITION", "PHYSICS", NVTX_GPU);
4561
4562 /* Loop over particles... */
4563 PARTICLE_LOOP(0, atm->np, 1, "acc data present(cache,met0,met1,atm)") {
4564
4565 /* Init... */
4566 double ps;
4568
4569 /* Calculate modulo... */
4570 atm->lon[ip] = FMOD(atm->lon[ip], 360.);
4571 atm->lat[ip] = FMOD(atm->lat[ip], 360.);
4572
4573 /* Check latitude... */
4574 while (atm->lat[ip] < -90 || atm->lat[ip] > 90) {
4575 if (atm->lat[ip] > 90) {
4576 atm->lat[ip] = 180 - atm->lat[ip];
4577 atm->lon[ip] += 180;
4578 }
4579 if (atm->lat[ip] < -90) {
4580 atm->lat[ip] = -180 - atm->lat[ip];
4581 atm->lon[ip] += 180;
4582 }
4583 }
4584
4585 /* Check longitude... */
4586 while (atm->lon[ip] < -180)
4587 atm->lon[ip] += 360;
4588 while (atm->lon[ip] >= 180)
4589 atm->lon[ip] -= 360;
4590
4591 /* Check pressure... */
4592 if (atm->p[ip] < met0->p[met0->np - 1]) {
4593 atm->p[ip] = met0->p[met0->np - 1];
4594 } else if (atm->p[ip] > 300.) {
4595 INTPOL_2D(ps, 1);
4596 if (atm->p[ip] > ps)
4597 atm->p[ip] = ps;
4598 }
4599 }
4600}

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

4605 {
4606
4607 /* Initialize GSL random number generators... */
4608 gsl_rng_env_setup();
4609 if (omp_get_max_threads() > NTHREADS)
4610 ERRMSG("Too many threads!");
4611 for (int i = 0; i < NTHREADS; i++) {
4612 rng[i] = gsl_rng_alloc(gsl_rng_default);
4613 gsl_rng_set(rng[i], gsl_rng_default_seed
4614 + (long unsigned) (ntask * NTHREADS + i));
4615 }
4616
4617 /* Initialize cuRAND random number generators... */
4618#ifdef CURAND
4619 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
4620 CURAND_STATUS_SUCCESS)
4621 ERRMSG("Cannot create random number generator!");
4622 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
4623 CURAND_STATUS_SUCCESS)
4624 ERRMSG("Cannot set seed for random number generator!");
4625 if (curandSetStream
4626 (rng_curand,
4627 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
4628 CURAND_STATUS_SUCCESS)
4629 ERRMSG("Cannot set stream for random number generator!");
4630#endif
4631}
#define NTHREADS
Maximum number of OpenMP threads.
Definition: mptrac.h:333

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

4639 {
4640
4641 /* Use GSL random number generators... */
4642 if (ctl->rng_type == 0) {
4643
4644 /* Uniform distribution... */
4645 if (method == 0) {
4646#pragma omp parallel for default(shared)
4647 for (size_t i = 0; i < n; ++i)
4648 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
4649 }
4650
4651 /* Normal distribution... */
4652 else if (method == 1) {
4653#pragma omp parallel for default(shared)
4654 for (size_t i = 0; i < n; ++i)
4655 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
4656 }
4657
4658 /* Update of random numbers on device... */
4659#ifdef _OPENACC
4660 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
4661#pragma acc update device(rs[:n])
4662#endif
4663 }
4664
4665 /* Use Squares random number generator (Widynski, 2022)... */
4666 else if (ctl->rng_type == 1) {
4667
4668 /* Set key (don't change this!)... */
4669 const uint64_t key = 0xc8e4fd154ce32f6d;
4670
4671 /* Uniform distribution... */
4672#ifdef _OPENACC
4673#pragma acc data present(rs)
4674#pragma acc parallel loop independent gang vector
4675#else
4676#pragma omp parallel for default(shared)
4677#endif
4678 for (size_t i = 0; i < n + 1; ++i) {
4679 uint64_t r, t, x, y, z;
4680 y = x = (rng_ctr + i) * key;
4681 z = y + key;
4682 x = x * x + y;
4683 x = (x >> 32) | (x << 32);
4684 x = x * x + z;
4685 x = (x >> 32) | (x << 32);
4686 x = x * x + y;
4687 x = (x >> 32) | (x << 32);
4688 t = x = x * x + z;
4689 x = (x >> 32) | (x << 32);
4690 r = t ^ ((x * x + y) >> 32);
4691 rs[i] = (double) r / (double) UINT64_MAX;
4692 }
4693 rng_ctr += n + 1;
4694
4695 /* Normal distribution... */
4696 if (method == 1) {
4697#ifdef _OPENACC
4698#pragma acc parallel loop independent gang vector
4699#else
4700#pragma omp parallel for default(shared)
4701#endif
4702 for (size_t i = 0; i < n; i += 2) {
4703 const double r = sqrt(-2.0 * log(rs[i]));
4704 const double phi = 2.0 * M_PI * rs[i + 1];
4705 rs[i] = r * cosf((float) phi);
4706 rs[i + 1] = r * sinf((float) phi);
4707 }
4708 }
4709 }
4710
4711 /* Use cuRAND random number generators... */
4712 else if (ctl->rng_type == 2) {
4713#ifdef CURAND
4714#pragma acc host_data use_device(rs)
4715 {
4716
4717 /* Uniform distribution... */
4718 if (method == 0) {
4719 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
4720 CURAND_STATUS_SUCCESS)
4721 ERRMSG("Cannot create random numbers!");
4722 }
4723
4724 /* Normal distribution... */
4725 else if (method == 1) {
4726 if (curandGenerateNormalDouble
4727 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
4728 1.0) != CURAND_STATUS_SUCCESS)
4729 ERRMSG("Cannot create random numbers!");
4730 }
4731 }
4732#else
4733 ERRMSG("MPTRAC was compiled without cuRAND!");
4734#endif
4735 }
4736}
int rng_type
Random number generator (0=GSL, 1=Squares, 2=cuRAND).
Definition: mptrac.h:2785

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

4745 {
4746
4747 /* Set timer... */
4748 SELECT_TIMER("MODULE_SEDI", "PHYSICS", NVTX_GPU);
4749
4750 /* Loop over particles... */
4751 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
4752
4753 /* Get temperature... */
4754 double t;
4756 INTPOL_3D(t, 1);
4757
4758 /* Sedimentation velocity... */
4759 const double v_s = sedi(atm->p[ip], t, atm->q[ctl->qnt_rp][ip],
4760 atm->q[ctl->qnt_rhop][ip]);
4761
4762 /* Calculate pressure change... */
4763 atm->p[ip] += DZ2DP(v_s * cache->dt[ip] / 1000., atm->p[ip]);
4764 }
4765}
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 4769 of file mptrac.c.

4772 {
4773
4774 /* Set timer... */
4775 SELECT_TIMER("MODULE_SORT", "PHYSICS", NVTX_GPU);
4776
4777 /* Allocate... */
4778 const int np = atm->np;
4779 double *restrict const a = (double *) malloc((size_t) np * sizeof(double));
4780 int *restrict const p = (int *) malloc((size_t) np * sizeof(int));
4781 if (a == NULL || p == NULL)
4782 ERRMSG("Out of memory!");
4783
4784#ifdef _OPENACC
4785#pragma acc enter data create(a[0:np],p[0:np])
4786#pragma acc data present(ctl,met0,atm,a,p)
4787#endif
4788
4789 /* Get box index... */
4790#ifdef _OPENACC
4791#pragma acc parallel loop independent gang vector
4792#else
4793#pragma omp parallel for default(shared)
4794#endif
4795 for (int ip = 0; ip < np; ip++) {
4796 a[ip] =
4797 (double) ((locate_reg(met0->lon, met0->nx, atm->lon[ip]) * met0->ny +
4798 locate_irr(met0->lat, met0->ny, atm->lat[ip]))
4799 * met0->np + locate_irr(met0->p, met0->np, atm->p[ip]));
4800 p[ip] = ip;
4801 }
4802
4803 /* Sorting... */
4804#ifdef THRUST
4805#ifdef _OPENACC
4806#pragma acc host_data use_device(a,p)
4807#endif
4808 thrustSortWrapper(a, np, p);
4809#else
4810#ifdef _OPENACC
4811 ERRMSG("GSL sort fallback not available on GPU, use THRUST!");
4812#endif
4813 gsl_sort_index((size_t *) p, a, 1, (size_t) np);
4814#endif
4815
4816 /* Sort data... */
4817 module_sort_help(atm->time, p, np);
4818 module_sort_help(atm->p, p, np);
4819 module_sort_help(atm->lon, p, np);
4820 module_sort_help(atm->lat, p, np);
4821 for (int iq = 0; iq < ctl->nq; iq++)
4822 module_sort_help(atm->q[iq], p, np);
4823
4824 /* Free... */
4825#ifdef _OPENACC
4826#pragma acc exit data delete(a,p)
4827#endif
4828 free(a);
4829 free(p);
4830}
void module_sort_help(double *a, const int *p, const int np)
Reorder an array based on a given permutation.
Definition: mptrac.c:4834
int nq
Number of quantities.
Definition: mptrac.h:2271
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 4834 of file mptrac.c.

4837 {
4838
4839 /* Allocate... */
4840 double *restrict const help =
4841 (double *) malloc((size_t) np * sizeof(double));
4842 if (help == NULL)
4843 ERRMSG("Out of memory!");
4844
4845 /* Reordering of array... */
4846#ifdef _OPENACC
4847#pragma acc enter data create(help[0:np])
4848#pragma acc data present(a,p,help)
4849#pragma acc parallel loop independent gang vector
4850#else
4851#pragma omp parallel for default(shared)
4852#endif
4853 for (int ip = 0; ip < np; ip++)
4854 help[ip] = a[p[ip]];
4855#ifdef _OPENACC
4856#pragma acc parallel loop independent gang vector
4857#else
4858#pragma omp parallel for default(shared)
4859#endif
4860 for (int ip = 0; ip < np; ip++)
4861 a[ip] = help[ip];
4862
4863 /* Free... */
4864#ifdef _OPENACC
4865#pragma acc exit data delete(help)
4866#endif
4867 free(help);
4868}

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

4877 {
4878
4879 /* Set timer... */
4880 SELECT_TIMER("MODULE_TIMESTEPS", "PHYSICS", NVTX_GPU);
4881
4882 const double latmin = gsl_stats_min(met0->lat, 1, (size_t) met0->ny),
4883 latmax = gsl_stats_max(met0->lat, 1, (size_t) met0->ny);
4884
4885 const int local =
4886 (fabs(met0->lon[met0->nx - 1] - met0->lon[0] - 360.0) >= 0.01);
4887
4888 /* Loop over particles... */
4889 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,cache,met0,atm)") {
4890
4891 /* Set time step for each air parcel... */
4892 if ((ctl->direction * (atm->time[ip] - ctl->t_start) >= 0
4893 && ctl->direction * (atm->time[ip] - ctl->t_stop) <= 0
4894 && ctl->direction * (atm->time[ip] - t) < 0))
4895 cache->dt[ip] = t - atm->time[ip];
4896 else
4897 cache->dt[ip] = 0.0;
4898
4899 /* Check horizontal boundaries of local meteo data... */
4900#ifndef DD
4901 int dd = 1;
4902#else
4903 int dd = 0;
4904#endif
4905 if (dd) {
4906 if (local && (atm->lon[ip] <= met0->lon[0]
4907 || atm->lon[ip] >= met0->lon[met0->nx - 1]
4908 || atm->lat[ip] <= latmin || atm->lat[ip] >= latmax))
4909 cache->dt[ip] = 0.0;
4910 } else {
4911 if ((int) atm->q[ctl->qnt_subdomain][ip] == -1)
4912 cache->dt[ip] = 0;
4913 }
4914 }
4915}
int direction
Direction flag (1=forward calculation, -1=backward calculation).
Definition: mptrac.h:2574
double t_stop
Stop time of simulation [s].
Definition: mptrac.h:2580
int qnt_subdomain
Quantity array index for current subdomain in domain decomposition.
Definition: mptrac.h:2568
double t_start
Start time of simulation [s].
Definition: mptrac.h:2577

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

4921 {
4922
4923 /* Set timer... */
4924 SELECT_TIMER("MODULE_TIMESTEPS_INIT", "PHYSICS", NVTX_GPU);
4925
4926 /* Set start time... */
4927 if (ctl->direction == 1) {
4928 ctl->t_start = gsl_stats_min(atm->time, 1, (size_t) atm->np);
4929 if (ctl->t_stop > 1e99)
4930 ctl->t_stop = gsl_stats_max(atm->time, 1, (size_t) atm->np);
4931 } else {
4932 ctl->t_start = gsl_stats_max(atm->time, 1, (size_t) atm->np);
4933 if (ctl->t_stop > 1e99)
4934 ctl->t_stop = gsl_stats_min(atm->time, 1, (size_t) atm->np);
4935 }
4936
4937 /* Check time interval... */
4938 if (ctl->direction * (ctl->t_stop - ctl->t_start) <= 0)
4939 ERRMSG("Nothing to do! Check T_STOP and DIRECTION!");
4940
4941 /* Round start time... */
4942 if (ctl->direction == 1)
4943 ctl->t_start = floor(ctl->t_start / ctl->dt_mod) * ctl->dt_mod;
4944 else
4945 ctl->t_start = ceil(ctl->t_start / ctl->dt_mod) * ctl->dt_mod;
4946}

◆ module_tracer_chem()

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

Simulate chemical reactions involving long-lived atmospheric tracers.

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

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

Definition at line 4950 of file mptrac.c.

4956 {
4957
4958 /* Set timer... */
4959 SELECT_TIMER("MODULE_TRACER_CHEM", "PHYSICS", NVTX_GPU);
4960
4961 /* Loop over particles... */
4962 PARTICLE_LOOP(0, atm->np, 1,
4963 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4964
4965 /* Get temperature... */
4966 double t;
4968 INTPOL_3D(t, 1);
4969
4970 /* Get molecular density... */
4971 const double M = MOLEC_DENS(atm->p[ip], t);
4972
4973 /* Get total column ozone... */
4974 double o3c;
4975 INTPOL_2D(o3c, 1);
4976
4977 /* Get solar zenith angle... */
4978 const double sza =
4979 acos(cos_sza(atm->time[ip], atm->lon[ip], atm->lat[ip]));
4980
4981 /* Get O(1D) volume mixing ratio... */
4982 const double o1d =
4983 clim_zm(&clim->o1d, atm->time[ip], atm->lat[ip], atm->p[ip]);
4984
4985 /* Reactions for CFC-10... */
4986 if (ctl->qnt_Cccl4 >= 0) {
4987 const double K_o1d = ARRHENIUS(3.30e-10, 0, t) * o1d * M;
4988 const double K_hv = clim_photo(clim->photo.ccl4, &(clim->photo),
4989 atm->p[ip], sza, o3c);
4990 atm->q[ctl->qnt_Cccl4][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4991 }
4992
4993 /* Reactions for CFC-11... */
4994 if (ctl->qnt_Cccl3f >= 0) {
4995 const double K_o1d = ARRHENIUS(2.30e-10, 0, t) * o1d * M;
4996 const double K_hv = clim_photo(clim->photo.ccl3f, &(clim->photo),
4997 atm->p[ip], sza, o3c);
4998 atm->q[ctl->qnt_Cccl3f][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4999 }
5000
5001 /* Reactions for CFC-12... */
5002 if (ctl->qnt_Cccl2f2 >= 0) {
5003 const double K_o1d = ARRHENIUS(1.40e-10, -25, t) * o1d * M;
5004 const double K_hv = clim_photo(clim->photo.ccl2f2, &(clim->photo),
5005 atm->p[ip], sza, o3c);
5006 atm->q[ctl->qnt_Cccl2f2][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
5007 }
5008
5009 /* Reactions for N2O... */
5010 if (ctl->qnt_Cn2o >= 0) {
5011 const double K_o1d = ARRHENIUS(1.19e-10, -20, t) * o1d * M;
5012 const double K_hv = clim_photo(clim->photo.n2o, &(clim->photo),
5013 atm->p[ip], sza, o3c);
5014 atm->q[ctl->qnt_Cn2o][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
5015 }
5016 }
5017}
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:147
#define ARRHENIUS(a, b, t)
Calculate the Arrhenius rate constant.
Definition: mptrac.h:483
double ccl2f2[CP][CSZA][CO3]
CCl2F2 photolysis rate [1/s].
Definition: mptrac.h:3414
double ccl3f[CP][CSZA][CO3]
CCl3F photolysis rate [1/s].
Definition: mptrac.h:3411
double n2o[CP][CSZA][CO3]
N2O photolysis rate [1/s].
Definition: mptrac.h:3405
double ccl4[CP][CSZA][CO3]
CCl4 photolysis rate [1/s].
Definition: mptrac.h:3408
clim_photo_t photo
Photolysis rates.
Definition: mptrac.h:3510
Here is the call graph for this function:

◆ module_wet_depo()

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

Perform wet deposition calculations for air parcels.

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

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

Definition at line 5021 of file mptrac.c.

5026 {
5027
5028 /* Set timer... */
5029 SELECT_TIMER("MODULE_WET_DEPO", "PHYSICS", NVTX_GPU);
5030
5031 /* Check quantity flags... */
5032 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
5033 ERRMSG("Module needs quantity mass or volume mixing ratio!");
5034
5035 /* Loop over particles... */
5036 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
5037
5038 /* Check whether particle is below cloud top... */
5039 double pct;
5041 INTPOL_2D(pct, 1);
5042 if (!isfinite(pct) || atm->p[ip] <= pct)
5043 continue;
5044
5045 /* Get cloud bottom pressure... */
5046 double pcb;
5047 INTPOL_2D(pcb, 0);
5048
5049 /* Estimate precipitation rate (Pisso et al., 2019)... */
5050 double cl;
5051 INTPOL_2D(cl, 0);
5052 const double Is =
5053 pow(1. / ctl->wet_depo_pre[0] * cl, 1. / ctl->wet_depo_pre[1]);
5054 if (Is < 0.01)
5055 continue;
5056
5057 /* Check whether particle is inside or below cloud... */
5058 double lwc, rwc, iwc, swc;
5059 INTPOL_3D(lwc, 1);
5060 INTPOL_3D(rwc, 0);
5061 INTPOL_3D(iwc, 0);
5062 INTPOL_3D(swc, 0);
5063 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
5064
5065 /* Get temperature... */
5066 double t;
5067 INTPOL_3D(t, 0);
5068
5069 /* Calculate in-cloud scavenging coefficient... */
5070 double lambda = 0;
5071 if (inside) {
5072
5073 /* Calculate retention factor... */
5074 double eta;
5075 if (t > 273.15)
5076 eta = 1;
5077 else if (t <= 238.15)
5078 eta = ctl->wet_depo_ic_ret_ratio;
5079 else
5080 eta = LIN(273.15, 1, 238.15, ctl->wet_depo_ic_ret_ratio, t);
5081
5082 /* Use exponential dependency for particles (Bakels et al., 2024)... */
5083 if (ctl->wet_depo_ic_a > 0)
5084 lambda = ctl->wet_depo_ic_a * pow(Is, ctl->wet_depo_ic_b) * eta;
5085
5086 /* Use Henry's law for gases... */
5087 else if (ctl->wet_depo_ic_h[0] > 0) {
5088
5089 /* Get Henry's constant (Burkholder et al., 2019; Sander, 2023)... */
5090 double h = ctl->wet_depo_ic_h[0]
5091 * exp(ctl->wet_depo_ic_h[1] * (1. / t - 1. / 298.15));
5092
5093 /* Use effective Henry's constant for SO2
5094 (Berglen, 2004; Simpson, 2012)... */
5095 if (ctl->wet_depo_so2_ph > 0) {
5096 const double H_ion = pow(10., -ctl->wet_depo_so2_ph);
5097 const double K_1 = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
5098 const double K_2 = 6e-8 * exp(1.12e3 * (1. / t - 1. / 298.15));
5099 h *= (1. + K_1 / H_ion + K_1 * K_2 / SQR(H_ion));
5100 }
5101
5102 /* Estimate depth of cloud layer... */
5103 const double dz = 1e3 * (Z(pct) - Z(pcb));
5104
5105 /* Calculate scavenging coefficient... */
5106 lambda = h * RI * t * Is / 3.6e6 / dz * eta;
5107 }
5108 }
5109
5110 /* Calculate below-cloud scavenging coefficient... */
5111 else {
5112
5113 /* Calculate retention factor... */
5114 double eta;
5115 if (t > 270)
5116 eta = 1;
5117 else
5118 eta = ctl->wet_depo_bc_ret_ratio;
5119
5120 /* Use exponential dependency for particles (Bakels et al., 2024)... */
5121 if (ctl->wet_depo_bc_a > 0)
5122 lambda = ctl->wet_depo_bc_a * pow(Is, ctl->wet_depo_bc_b) * eta;
5123
5124 /* Use Henry's law for gases... */
5125 else if (ctl->wet_depo_bc_h[0] > 0) {
5126
5127 /* Get Henry's constant (Burkholder et al., 2019; Sander, 2023)... */
5128 const double h = ctl->wet_depo_bc_h[0]
5129 * exp(ctl->wet_depo_bc_h[1] * (1. / t - 1. / 298.15));
5130
5131 /* Estimate depth of cloud layer... */
5132 const double dz = 1e3 * (Z(pct) - Z(pcb));
5133
5134 /* Calculate scavenging coefficient... */
5135 lambda = h * RI * t * Is / 3.6e6 / dz * eta;
5136 }
5137 }
5138
5139 /* Calculate exponential decay of mass... */
5140 const double aux = exp(-cache->dt[ip] * lambda);
5141 if (ctl->qnt_m >= 0) {
5142 if (ctl->qnt_mloss_wet >= 0)
5143 atm->q[ctl->qnt_mloss_wet][ip]
5144 += atm->q[ctl->qnt_m][ip] * (1 - aux);
5145 atm->q[ctl->qnt_m][ip] *= aux;
5146 if (ctl->qnt_loss_rate >= 0)
5147 atm->q[ctl->qnt_loss_rate][ip] += lambda;
5148 }
5149 if (ctl->qnt_vmr >= 0)
5150 atm->q[ctl->qnt_vmr][ip] *= aux;
5151 }
5152}
double wet_depo_ic_a
Coefficient A for wet deposition in cloud (exponential form).
Definition: mptrac.h:3007
double wet_depo_bc_a
Coefficient A for wet deposition below cloud (exponential form).
Definition: mptrac.h:3001
int qnt_mloss_wet
Quantity array index for total mass loss due to wet deposition.
Definition: mptrac.h:2445
double wet_depo_so2_ph
pH value used to calculate effective Henry constant of SO2.
Definition: mptrac.h:3019
double wet_depo_pre[2]
Coefficients for precipitation calculation.
Definition: mptrac.h:2998
double wet_depo_bc_h[2]
Coefficients for wet deposition below cloud (Henry's law: Hb, Cb).
Definition: mptrac.h:3016
double wet_depo_bc_ret_ratio
Coefficients for wet deposition below cloud: retention ratio.
Definition: mptrac.h:3025
double wet_depo_ic_h[2]
Coefficients for wet deposition in cloud (Henry's law: Hb, Cb).
Definition: mptrac.h:3013
double wet_depo_ic_ret_ratio
Coefficients for wet deposition in cloud: retention ratio.
Definition: mptrac.h:3022
double wet_depo_ic_b
Coefficient B for wet deposition in cloud (exponential form).
Definition: mptrac.h:3010
double wet_depo_bc_b
Coefficient B for wet deposition below cloud (exponential form).
Definition: mptrac.h:3004

◆ mptrac_alloc()

void mptrac_alloc ( ctl_t **  ctl,
cache_t **  cache,
clim_t **  clim,
met_t **  met0,
met_t **  met1,
atm_t **  atm,
dd_t **  dd 
)

Allocates and initializes memory resources for MPTRAC.

This function handles memory allocation for various data structures and sets up GPU resources if available. It also creates the necessary data regions on GPUs for OpenACC-enabled execution.

Parameters
[out]ctlPointer to the control structure (ctl_t).
[out]cachePointer to the cache structure (cache_t).
[out]climPointer to the climatology structure (clim_t).
[out]met0Pointer to the first meteorology structure (met_t).
[out]met1Pointer to the second meteorology structure (met_t).
[out]atmPointer to the atmospheric structure (atm_t).
[out]ddpointer to an dd_t structure containing MPI information, including rank and neighbours.
Note
This function uses OpenACC for GPU initialization and memory management. If OpenACC is not enabled, the GPU-specific code is ignored.
Precondition
The function requires an environment supporting OpenACC for GPU operations. MPI support is optional but assumed if compiled with MPI.
Postcondition
Allocated structures are ready for use, and data regions on GPUs are initialized if OpenACC is enabled.
Exceptions
Runtimeerror if no GPU devices are available when OpenACC is enabled.
Author
Lars Hoffmann

Definition at line 5156 of file mptrac.c.

5163 {
5164
5165 /* Initialize GPU... */
5166#ifdef _OPENACC
5167 SELECT_TIMER("ACC_INIT", "INIT", NVTX_GPU);
5168 int rank = 0;
5169#ifdef MPI
5170 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5171#endif
5172 if (acc_get_num_devices(acc_device_nvidia) <= 0)
5173 ERRMSG("Not running on a GPU device!");
5174 acc_set_device_num(rank % acc_get_num_devices(acc_device_nvidia),
5175 acc_device_nvidia);
5176 acc_device_t device_type = acc_get_device_type();
5177 acc_init(device_type);
5178#endif
5179
5180 /* Allocate... */
5181 SELECT_TIMER("ALLOC", "MEMORY", NVTX_CPU);
5182 ALLOC(*ctl, ctl_t, 1);
5183 ALLOC(*cache, cache_t, 1);
5184 ALLOC(*clim, clim_t, 1);
5185 ALLOC(*met0, met_t, 1);
5186 ALLOC(*met1, met_t, 1);
5187 ALLOC(*atm, atm_t, 1);
5188 ALLOC(*dd, dd_t, 1);
5189
5190 /* Create data region on GPU... */
5191#ifdef _OPENACC
5192 SELECT_TIMER("CREATE_DATA_REGION", "MEMORY", NVTX_GPU);
5193 ctl_t *ctlup = *ctl;
5194 cache_t *cacheup = *cache;
5195 clim_t *climup = *clim;
5196 met_t *met0up = *met0;
5197 met_t *met1up = *met1;
5198 atm_t *atmup = *atm;
5199#pragma acc enter data create(ctlup[:1],cacheup[:1],climup[:1],met0up[:1],met1up[:1],atmup[:1])
5200#ifdef DD
5201 dd_t *ddup = *dd;
5202#pragma acc enter data create(ddup[:1])
5203#endif
5204#endif
5205}
Air parcel data.
Definition: mptrac.h:3297
Cache data structure.
Definition: mptrac.h:3352
Climatological data.
Definition: mptrac.h:3492
Control parameters.
Definition: mptrac.h:2264
Domain decomposition data structure.
Definition: mptrac.h:3725
Meteo data structure.
Definition: mptrac.h:3551

◆ mptrac_free()

void mptrac_free ( ctl_t ctl,
cache_t cache,
clim_t clim,
met_t met0,
met_t met1,
atm_t atm,
dd_t dd 
)

Frees memory resources allocated for MPTRAC.

This function releases the memory allocated for various data structures and deletes any associated data regions on GPUs if OpenACC is enabled.

Parameters
[in]ctlPointer to the control structure (ctl_t) to be freed.
[in]cachePointer to the cache structure (cache_t) to be freed.
[in]climPointer to the climatology structure (clim_t) to be freed.
[in]met0Pointer to the first meteorology structure (met_t) to be freed.
[in]met1Pointer to the second meteorology structure (met_t) to be freed.
[in]atmPointer to the atmospheric structure (atm_t) to be freed.
[in]ddPointer to an dd_t structure containing MPI information, including rank and neighbours.
Note
This function uses OpenACC for GPU memory management. If OpenACC is not enabled, the GPU-specific code is ignored.
Precondition
All input pointers must point to valid allocated memory. The function assumes that the memory was allocated using compatible allocation methods.
Postcondition
All input pointers are freed, and the associated data regions on GPUs are deleted if OpenACC is enabled.
Warning
Ensure that the input pointers are not used after calling this function as they will be invalidated.
Author
Lars Hoffmann

Definition at line 5209 of file mptrac.c.

5216 {
5217
5218 /* Delete data region on GPU... */
5219#ifdef _OPENACC
5220 SELECT_TIMER("DELETE_DATA_REGION", "MEMORY", NVTX_GPU);
5221#pragma acc exit data delete (ctl,cache,clim,met0,met1,atm)
5222#endif
5223
5224 /* Free... */
5225 SELECT_TIMER("FREE", "MEMORY", NVTX_CPU);
5226 free(atm);
5227 free(ctl);
5228 free(cache);
5229 free(clim);
5230 free(met0);
5231 free(met1);
5232
5233 /* Free MPI datatype... */
5234#ifdef DD
5235 MPI_Type_free(&dd->MPI_Particle);
5236#endif
5237 free(dd);
5238}

◆ mptrac_get_met()

void mptrac_get_met ( ctl_t ctl,
clim_t clim,
const double  t,
met_t **  met0,
met_t **  met1,
dd_t dd 
)

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.
ddA pointer to an dd_t structure containing MPI information, including rank and neighbours.

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

5248 {
5249
5250 static int init;
5251
5252 met_t *mets;
5253
5254 char cachefile[LEN], cmd[2 * LEN], filename[LEN];
5255
5256 /* Set timer... */
5257 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
5258
5259 /* Init... */
5260 if (t == ctl->t_start || !init) {
5261 init = 1;
5262
5263 /* Read meteo data... */
5264 get_met_help(ctl, t + (ctl->direction == -1 ? -1 : 0), -1,
5265 ctl->metbase, ctl->dt_met, filename);
5266 if (!mptrac_read_met(filename, ctl, clim, *met0, dd))
5267 ERRMSG("Cannot open file!");
5268
5269 get_met_help(ctl, t + (ctl->direction == 1 ? 1 : 0), 1,
5270 ctl->metbase, ctl->dt_met, filename);
5271 if (!mptrac_read_met(filename, ctl, clim, *met1, dd))
5272 ERRMSG("Cannot open file!");
5273
5274 /* Update GPU... */
5275 mptrac_update_device(NULL, NULL, NULL, met0, met1, NULL);
5276 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
5277
5278 /* Caching... */
5279 if (ctl->met_cache && t != ctl->t_stop) {
5280 get_met_help(ctl, t + 1.1 * ctl->dt_met * ctl->direction,
5281 ctl->direction, ctl->metbase, ctl->dt_met, cachefile);
5282 sprintf(cmd, "cat %s > /dev/null &", cachefile);
5283 LOG(1, "Caching: %s", cachefile);
5284 if (system(cmd) != 0)
5285 WARN("Caching command failed!");
5286 }
5287 }
5288
5289 /* Read new data for forward trajectories... */
5290 if (t > (*met1)->time) {
5291
5292 /* Pointer swap... */
5293 mets = *met1;
5294 *met1 = *met0;
5295 *met0 = mets;
5296
5297 /* Read new meteo data... */
5298 get_met_help(ctl, t, 1, ctl->metbase, ctl->dt_met, filename);
5299 if (!mptrac_read_met(filename, ctl, clim, *met1, dd))
5300 ERRMSG("Cannot open file!");
5301
5302 /* Update GPU... */
5303 mptrac_update_device(NULL, NULL, NULL, NULL, met1, NULL);
5304 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
5305
5306 /* Caching... */
5307 if (ctl->met_cache && t != ctl->t_stop) {
5308 get_met_help(ctl, t + ctl->dt_met, 1, ctl->metbase, ctl->dt_met,
5309 cachefile);
5310 sprintf(cmd, "cat %s > /dev/null &", cachefile);
5311 LOG(1, "Caching: %s", cachefile);
5312 if (system(cmd) != 0)
5313 WARN("Caching command failed!");
5314 }
5315 }
5316
5317 /* Read new data for backward trajectories... */
5318 if (t < (*met0)->time) {
5319
5320 /* Pointer swap... */
5321 mets = *met1;
5322 *met1 = *met0;
5323 *met0 = mets;
5324
5325 /* Read new meteo data... */
5326 get_met_help(ctl, t, -1, ctl->metbase, ctl->dt_met, filename);
5327 if (!mptrac_read_met(filename, ctl, clim, *met0, dd))
5328 ERRMSG("Cannot open file!");
5329
5330 /* Update GPU... */
5331 mptrac_update_device(NULL, NULL, NULL, met0, NULL, NULL);
5332 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
5333
5334 /* Caching... */
5335 if (ctl->met_cache && t != ctl->t_stop) {
5336 get_met_help(ctl, t - ctl->dt_met, -1, ctl->metbase, ctl->dt_met,
5337 cachefile);
5338 sprintf(cmd, "cat %s > /dev/null &", cachefile);
5339 LOG(1, "Caching: %s", cachefile);
5340 if (system(cmd) != 0)
5341 WARN("Caching command failed!");
5342 }
5343 }
5344
5345 /* Check that grids are consistent... */
5346 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
5347 if ((*met0)->nx != (*met1)->nx
5348 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
5349 ERRMSG("Meteo grid dimensions do not match!");
5350 for (int ix = 0; ix < (*met0)->nx; ix++)
5351 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
5352 ERRMSG("Meteo grid longitudes do not match!");
5353 for (int iy = 0; iy < (*met0)->ny; iy++)
5354 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
5355 ERRMSG("Meteo grid latitudes do not match!");
5356 for (int ip = 0; ip < (*met0)->np; ip++)
5357 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
5358 ERRMSG("Meteo grid pressure levels do not match!");
5359 }
5360}
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:1980
int mptrac_read_met(const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met, dd_t *dd)
Reads meteorological data from a file, supporting multiple formats and MPI broadcasting.
Definition: mptrac.c:6409
int met_cache
Preload meteo data into disk cache (0=no, 1=yes).
Definition: mptrac.h:2758
char metbase[LEN]
Basename for meteo data.
Definition: mptrac.h:2590
Here is the call graph for this function:

◆ mptrac_init()

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

Initializes the MPTRAC model and its associated components.

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

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

The function performs the following operations:

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

Definition at line 5364 of file mptrac.c.

5369 {
5370
5371 /* Initialize timesteps... */
5372 module_timesteps_init(ctl, atm);
5373
5374 /* Initialize random number generator... */
5375 module_rng_init(ntask);
5376
5377 /* Update GPU memory... */
5378 mptrac_update_device(ctl, cache, clim, NULL, NULL, atm);
5379}
void module_timesteps_init(ctl_t *ctl, const atm_t *atm)
Initialize start time and time interval for time-stepping.
Definition: mptrac.c:4919
void module_rng_init(const int ntask)
Initialize random number generators for parallel tasks.
Definition: mptrac.c:4604
Here is the call graph for this function:

◆ mptrac_read_atm()

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

Reads air parcel data from a specified file into the given atmospheric structure.

This function reads air parcel data from a file and populates the provided atm_t structure based on the type of data specified in the ctl_t control structure. It supports various data formats including ASCII, binary, netCDF, and CLaMS.

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

This function performs the following steps:

  • Sets a timer for performance measurement.
  • Initializes the atmospheric structure.
  • Logs the file being read.
  • Reads data from the file based on the specified type (ctl->atm_type):
    • 0 for ASCII data
    • 1 for binary data
    • 2 for netCDF data
    • 3 or 4 for CLaMS data
  • Handles errors if the data type is not supported.
  • Checks the result of the data reading function and ensures data was read successfully.
  • Logs information about the number of air parcels and the ranges of various parameters (time, altitude, pressure, longitude, latitude, and other quantities).

The function utilizes several helper functions and macros:

  • SELECT_TIMER for setting the timer.
  • LOG for logging information.
  • ERRMSG for handling error messages.
  • gsl_stats_minmax for calculating minimum and maximum values.
  • Z for converting altitude.
Author
Lars Hoffmann

Definition at line 5383 of file mptrac.c.

5386 {
5387
5388 int result;
5389
5390 /* Set timer... */
5391 SELECT_TIMER("READ_ATM", "INPUT", NVTX_READ);
5392
5393 /* Init... */
5394 atm->np = 0;
5395
5396 /* Write info... */
5397 LOG(1, "Read atmospheric data: %s", filename);
5398
5399 /* Read ASCII data... */
5400 if (ctl->atm_type == 0)
5401 result = read_atm_asc(filename, ctl, atm);
5402
5403 /* Read binary data... */
5404 else if (ctl->atm_type == 1)
5405 result = read_atm_bin(filename, ctl, atm);
5406
5407 /* Read netCDF data... */
5408 else if (ctl->atm_type == 2)
5409 result = read_atm_nc(filename, ctl, atm);
5410
5411 /* Read CLaMS data... */
5412 else if (ctl->atm_type == 3 || ctl->atm_type == 4)
5413 result = read_atm_clams(filename, ctl, atm);
5414
5415 /* Error... */
5416 else
5417 ERRMSG("Atmospheric data type not supported!");
5418
5419 /* Check result... */
5420 if (result != 1)
5421 return 0;
5422
5423 /* Check number of air parcels... */
5424 if (atm->np < 1)
5425 ERRMSG("Can not read any data!");
5426
5427 /* Write info... */
5428 double mini, maxi;
5429 LOG(2, "Number of particles: %d", atm->np);
5430 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
5431 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
5432 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
5433 LOG(2, "Altitude range: %g ... %g km", Z(maxi), Z(mini));
5434 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
5435 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
5436 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
5437 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
5438 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
5439 for (int iq = 0; iq < ctl->nq; iq++) {
5440 char msg[5 * LEN];
5441 sprintf(msg, "Quantity %s range: %s ... %s %s",
5442 ctl->qnt_name[iq], ctl->qnt_format[iq],
5443 ctl->qnt_format[iq], ctl->qnt_unit[iq]);
5444 gsl_stats_minmax(&mini, &maxi, atm->q[iq], 1, (size_t) atm->np);
5445 LOG(2, msg, mini, maxi);
5446 }
5447
5448 /* Return success... */
5449 return 1;
5450}
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:7177
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:7061
int read_atm_clams(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads atmospheric data from a CLAMS NetCDF file.
Definition: mptrac.c:7117
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:7019
char qnt_format[NQ][LEN]
Quantity output format.
Definition: mptrac.h:2283
int atm_type
Type of atmospheric data files (0=ASCII, 1=binary, 2=netCDF, 3=CLaMS_traj, 4=CLaMS_pos).
Definition: mptrac.h:3060
char qnt_unit[NQ][LEN]
Quantity units.
Definition: mptrac.h:2280
char qnt_name[NQ][LEN]
Quantity names.
Definition: mptrac.h:2274
Here is the call graph for this function:

◆ mptrac_read_clim()

void mptrac_read_clim ( const ctl_t ctl,
clim_t clim 
)

Reads various climatological data and populates the given climatology structure.

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

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

This function performs the following steps:

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

The function utilizes several helper functions:

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

Definition at line 5454 of file mptrac.c.

5456 {
5457
5458 /* Set timer... */
5459 SELECT_TIMER("READ_CLIM", "INPUT", NVTX_READ);
5460
5461 /* Init tropopause climatology... */
5462 clim_tropo_init(clim);
5463
5464 /* Read photolysis rates... */
5465 if (ctl->clim_photo[0] != '-')
5466 read_clim_photo(ctl->clim_photo, &clim->photo);
5467
5468 /* Read HNO3 climatology... */
5469 if (ctl->clim_hno3_filename[0] != '-')
5470 read_clim_zm(ctl->clim_hno3_filename, "HNO3", &clim->hno3);
5471
5472 /* Read OH climatology... */
5473 if (ctl->clim_oh_filename[0] != '-') {
5474 read_clim_zm(ctl->clim_oh_filename, "OH", &clim->oh);
5475 if (ctl->oh_chem_beta > 0)
5476 clim_oh_diurnal_correction(ctl, clim);
5477 }
5478
5479 /* Read H2O2 climatology... */
5480 if (ctl->clim_h2o2_filename[0] != '-')
5481 read_clim_zm(ctl->clim_h2o2_filename, "H2O2", &clim->h2o2);
5482
5483 /* Read HO2 climatology... */
5484 if (ctl->clim_ho2_filename[0] != '-')
5485 read_clim_zm(ctl->clim_ho2_filename, "HO2", &clim->ho2);
5486
5487 /* Read O(1D) climatology... */
5488 if (ctl->clim_o1d_filename[0] != '-')
5489 read_clim_zm(ctl->clim_o1d_filename, "O1D", &clim->o1d);
5490
5491 /* Read CFC-10 time series... */
5492 if (ctl->clim_ccl4_timeseries[0] != '-')
5494
5495 /* Read CFC-11 time series... */
5496 if (ctl->clim_ccl3f_timeseries[0] != '-')
5498
5499 /* Read CFC-12 time series... */
5500 if (ctl->clim_ccl2f2_timeseries[0] != '-')
5502
5503 /* Read N2O time series... */
5504 if (ctl->clim_n2o_timeseries[0] != '-')
5505 read_clim_ts(ctl->clim_n2o_timeseries, &clim->n2o);
5506
5507 /* Read SF6 time series... */
5508 if (ctl->clim_sf6_timeseries[0] != '-')
5509 read_clim_ts(ctl->clim_sf6_timeseries, &clim->sf6);
5510}
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:7210
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:7329
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:7383
void clim_tropo_init(clim_t *clim)
Initializes the tropopause data in the climatology structure.
Definition: mptrac.c:232
void clim_oh_diurnal_correction(const ctl_t *ctl, clim_t *clim)
Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data.
Definition: mptrac.c:115
char clim_ho2_filename[LEN]
Filename of HO2 climatology.
Definition: mptrac.h:2890
char clim_o1d_filename[LEN]
Filename of O(1D) climatology.
Definition: mptrac.h:2893
char clim_photo[LEN]
Filename of photolysis rates climatology.
Definition: mptrac.h:2878
char clim_h2o2_filename[LEN]
Filename of H2O2 climatology.
Definition: mptrac.h:2887
char clim_oh_filename[LEN]
Filename of OH climatology.
Definition: mptrac.h:2884
char clim_hno3_filename[LEN]
Filename of HNO3 climatology.
Definition: mptrac.h:2881
Here is the call graph for this function:

◆ mptrac_read_ctl()

void mptrac_read_ctl ( const char *  filename,
int  argc,
char *  argv[],
ctl_t ctl 
)

Reads control parameters from a configuration file and populates the given structure.

This function reads control parameters from a specified configuration file and command line arguments, populating the provided ctl_t structure with the parsed data. It handles a wide range of parameters, performing necessary checks and providing default values where applicable.

Parameters
filenameA string containing the path to the configuration file.
argcAn integer representing the number of command line arguments.
argvAn array of strings containing the command line arguments.
ctlA pointer to the structure (ctl_t) that will be populated with the control parameters.

The function performs the following steps:

  • Sets a timer for reading the control file.
  • Logs information about the MPTRAC executable version and compilation details.
  • Initializes quantity indices.
  • Reads and sets various control parameters such as quantities, vertical coordinates, time steps, meteorological data, sorting options, isosurface parameters, random number generator type, advection parameters, diffusion parameters, convection parameters, boundary conditions, species parameters, molar mass, OH chemistry parameters, H2O2 chemistry parameters, KPP chemistry parameters, first order tracer chemistry parameters, wet deposition parameters, dry deposition parameters, climatological data paths, mixing parameters, chemistry grid parameters, exponential decay parameters, PSC analysis parameters, output parameters for atmospheric data, CSI data, ensemble data, grid data, profile data, sample data, station data, and VTK data.
Author
Lars Hoffmann

Definition at line 5514 of file mptrac.c.

5518 {
5519
5520 /* Set timer... */
5521 SELECT_TIMER("READ_CTL", "INPUT", NVTX_READ);
5522
5523 /* Write info... */
5524 LOG(1, "\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
5525 "(executable: %s | version: %s | compiled: %s, %s)\n",
5526 argv[0], VERSION, __DATE__, __TIME__);
5527
5528 /* Initialize quantity indices... */
5529 ctl->qnt_idx = -1;
5530 ctl->qnt_ens = -1;
5531 ctl->qnt_stat = -1;
5532 ctl->qnt_m = -1;
5533 ctl->qnt_vmr = -1;
5534 ctl->qnt_rp = -1;
5535 ctl->qnt_rhop = -1;
5536 ctl->qnt_ps = -1;
5537 ctl->qnt_ts = -1;
5538 ctl->qnt_zs = -1;
5539 ctl->qnt_us = -1;
5540 ctl->qnt_vs = -1;
5541 ctl->qnt_ess = -1;
5542 ctl->qnt_nss = -1;
5543 ctl->qnt_shf = -1;
5544 ctl->qnt_lsm = -1;
5545 ctl->qnt_sst = -1;
5546 ctl->qnt_pbl = -1;
5547 ctl->qnt_pt = -1;
5548 ctl->qnt_tt = -1;
5549 ctl->qnt_zt = -1;
5550 ctl->qnt_h2ot = -1;
5551 ctl->qnt_zg = -1;
5552 ctl->qnt_p = -1;
5553 ctl->qnt_t = -1;
5554 ctl->qnt_rho = -1;
5555 ctl->qnt_u = -1;
5556 ctl->qnt_v = -1;
5557 ctl->qnt_w = -1;
5558 ctl->qnt_h2o = -1;
5559 ctl->qnt_o3 = -1;
5560 ctl->qnt_lwc = -1;
5561 ctl->qnt_rwc = -1;
5562 ctl->qnt_iwc = -1;
5563 ctl->qnt_swc = -1;
5564 ctl->qnt_cc = -1;
5565 ctl->qnt_pct = -1;
5566 ctl->qnt_pcb = -1;
5567 ctl->qnt_cl = -1;
5568 ctl->qnt_plcl = -1;
5569 ctl->qnt_plfc = -1;
5570 ctl->qnt_pel = -1;
5571 ctl->qnt_cape = -1;
5572 ctl->qnt_cin = -1;
5573 ctl->qnt_o3c = -1;
5574 ctl->qnt_hno3 = -1;
5575 ctl->qnt_oh = -1;
5576 ctl->qnt_h2o2 = -1;
5577 ctl->qnt_ho2 = -1;
5578 ctl->qnt_o1d = -1;
5579 ctl->qnt_mloss_oh = -1;
5580 ctl->qnt_mloss_h2o2 = -1;
5581 ctl->qnt_mloss_kpp = -1;
5582 ctl->qnt_mloss_wet = -1;
5583 ctl->qnt_mloss_dry = -1;
5584 ctl->qnt_mloss_decay = -1;
5585 ctl->qnt_loss_rate = -1;
5586 ctl->qnt_psat = -1;
5587 ctl->qnt_psice = -1;
5588 ctl->qnt_pw = -1;
5589 ctl->qnt_sh = -1;
5590 ctl->qnt_rh = -1;
5591 ctl->qnt_rhice = -1;
5592 ctl->qnt_theta = -1;
5593 ctl->qnt_zeta = -1;
5594 ctl->qnt_zeta_d = -1;
5595 ctl->qnt_zeta_dot = -1;
5596 ctl->qnt_eta = -1;
5597 ctl->qnt_eta_dot = -1;
5598 ctl->qnt_tvirt = -1;
5599 ctl->qnt_lapse = -1;
5600 ctl->qnt_vh = -1;
5601 ctl->qnt_vz = -1;
5602 ctl->qnt_pv = -1;
5603 ctl->qnt_tdew = -1;
5604 ctl->qnt_tice = -1;
5605 ctl->qnt_tsts = -1;
5606 ctl->qnt_tnat = -1;
5607 ctl->qnt_Cx = -1;
5608 ctl->qnt_Ch2o = -1;
5609 ctl->qnt_Co3 = -1;
5610 ctl->qnt_Cco = -1;
5611 ctl->qnt_Coh = -1;
5612 ctl->qnt_Ch = -1;
5613 ctl->qnt_Cho2 = -1;
5614 ctl->qnt_Ch2o2 = -1;
5615 ctl->qnt_Co1d = -1;
5616 ctl->qnt_Co3p = -1;
5617 ctl->qnt_Cccl4 = -1;
5618 ctl->qnt_Cccl3f = -1;
5619 ctl->qnt_Cccl2f2 = -1;
5620 ctl->qnt_Cn2o = -1;
5621 ctl->qnt_Csf6 = -1;
5622 ctl->qnt_aoa = -1;
5623
5624#ifdef DD
5625 ctl->qnt_destination = -1;
5626 ctl->qnt_subdomain = -1;
5627#endif
5628
5629 /* Read quantities... */
5630 ctl->nq = (int) scan_ctl(filename, argc, argv, "NQ", -1, "0", NULL);
5631 if (ctl->nq > NQ)
5632 ERRMSG("Too many quantities!");
5633 for (int iq = 0; iq < ctl->nq; iq++) {
5634
5635 /* Read quantity name and format... */
5636 scan_ctl(filename, argc, argv, "QNT_NAME", iq, "", ctl->qnt_name[iq]);
5637 scan_ctl(filename, argc, argv, "QNT_LONGNAME", iq, ctl->qnt_name[iq],
5638 ctl->qnt_longname[iq]);
5639 scan_ctl(filename, argc, argv, "QNT_FORMAT", iq, "%g",
5640 ctl->qnt_format[iq]);
5641 if (strcasecmp(ctl->qnt_name[iq], "aoa") == 0)
5642 sprintf(ctl->qnt_format[iq], "%%.2f");
5643
5644 /* Try to identify quantity... */
5645 SET_QNT(qnt_idx, "idx", "particle index", "-")
5646 SET_QNT(qnt_ens, "ens", "ensemble index", "-")
5647 SET_QNT(qnt_stat, "stat", "station flag", "-")
5648 SET_QNT(qnt_m, "m", "mass", "kg")
5649 SET_QNT(qnt_vmr, "vmr", "volume mixing ratio", "ppv")
5650 SET_QNT(qnt_rp, "rp", "particle radius", "microns")
5651 SET_QNT(qnt_rhop, "rhop", "particle density", "kg/m^3")
5652 SET_QNT(qnt_ps, "ps", "surface pressure", "hPa")
5653 SET_QNT(qnt_ts, "ts", "surface temperature", "K")
5654 SET_QNT(qnt_zs, "zs", "surface height", "km")
5655 SET_QNT(qnt_us, "us", "surface zonal wind", "m/s")
5656 SET_QNT(qnt_vs, "vs", "surface meridional wind", "m/s")
5657 SET_QNT(qnt_ess, "ess", "eastward turbulent surface stress", "N/m^2")
5658 SET_QNT(qnt_nss, "nss", "northward turbulent surface stress", "N/m^2")
5659 SET_QNT(qnt_shf, "shf", "surface sensible heat flux", "W/m^2")
5660 SET_QNT(qnt_lsm, "lsm", "land-sea mask", "1")
5661 SET_QNT(qnt_sst, "sst", "sea surface temperature", "K")
5662 SET_QNT(qnt_pbl, "pbl", "planetary boundary layer", "hPa")
5663 SET_QNT(qnt_pt, "pt", "tropopause pressure", "hPa")
5664 SET_QNT(qnt_tt, "tt", "tropopause temperature", "K")
5665 SET_QNT(qnt_zt, "zt", "tropopause geopotential height", "km")
5666 SET_QNT(qnt_h2ot, "h2ot", "tropopause water vapor", "ppv")
5667 SET_QNT(qnt_zg, "zg", "geopotential height", "km")
5668 SET_QNT(qnt_p, "p", "pressure", "hPa")
5669 SET_QNT(qnt_t, "t", "temperature", "K")
5670 SET_QNT(qnt_rho, "rho", "air density", "kg/m^3")
5671 SET_QNT(qnt_u, "u", "zonal wind", "m/s")
5672 SET_QNT(qnt_v, "v", "meridional wind", "m/s")
5673 SET_QNT(qnt_w, "w", "vertical velocity", "hPa/s")
5674 SET_QNT(qnt_h2o, "h2o", "water vapor", "ppv")
5675 SET_QNT(qnt_o3, "o3", "ozone", "ppv")
5676 SET_QNT(qnt_lwc, "lwc", "cloud liquid water content", "kg/kg")
5677 SET_QNT(qnt_rwc, "rwc", "cloud rain water content", "kg/kg")
5678 SET_QNT(qnt_iwc, "iwc", "cloud ice water content", "kg/kg")
5679 SET_QNT(qnt_swc, "swc", "cloud snow water content", "kg/kg")
5680 SET_QNT(qnt_cc, "cc", "cloud cover", "1")
5681 SET_QNT(qnt_pct, "pct", "cloud top pressure", "hPa")
5682 SET_QNT(qnt_pcb, "pcb", "cloud bottom pressure", "hPa")
5683 SET_QNT(qnt_cl, "cl", "total column cloud water", "kg/m^2")
5684 SET_QNT(qnt_plcl, "plcl", "lifted condensation level", "hPa")
5685 SET_QNT(qnt_plfc, "plfc", "level of free convection", "hPa")
5686 SET_QNT(qnt_pel, "pel", "equilibrium level", "hPa")
5687 SET_QNT(qnt_cape, "cape", "convective available potential energy",
5688 "J/kg")
5689 SET_QNT(qnt_cin, "cin", "convective inhibition", "J/kg")
5690 SET_QNT(qnt_o3c, "o3c", "total column ozone", "DU")
5691 SET_QNT(qnt_hno3, "hno3", "nitric acid", "ppv")
5692 SET_QNT(qnt_oh, "oh", "hydroxyl radical", "ppv")
5693 SET_QNT(qnt_h2o2, "h2o2", "hydrogen peroxide", "ppv")
5694 SET_QNT(qnt_ho2, "ho2", "hydroperoxyl radical", "ppv")
5695 SET_QNT(qnt_o1d, "o1d", "atomic oxygen", "ppv")
5696 SET_QNT(qnt_mloss_oh, "mloss_oh", "mass loss due to OH chemistry", "kg")
5697 SET_QNT(qnt_mloss_h2o2, "mloss_h2o2",
5698 "mass loss due to H2O2 chemistry", "kg")
5699 SET_QNT(qnt_mloss_kpp, "mloss_kpp", "mass loss due to kpp chemistry",
5700 "kg")
5701 SET_QNT(qnt_mloss_wet, "mloss_wet", "mass loss due to wet deposition",
5702 "kg")
5703 SET_QNT(qnt_mloss_dry, "mloss_dry", "mass loss due to dry deposition",
5704 "kg")
5705 SET_QNT(qnt_mloss_decay, "mloss_decay",
5706 "mass loss due to exponential decay", "kg")
5707 SET_QNT(qnt_loss_rate, "loss_rate", "total loss rate", "s^-1")
5708 SET_QNT(qnt_psat, "psat", "saturation pressure over water", "hPa")
5709 SET_QNT(qnt_psice, "psice", "saturation pressure over ice", "hPa")
5710 SET_QNT(qnt_pw, "pw", "partial water vapor pressure", "hPa")
5711 SET_QNT(qnt_sh, "sh", "specific humidity", "kg/kg")
5712 SET_QNT(qnt_rh, "rh", "relative humidity", "%%")
5713 SET_QNT(qnt_rhice, "rhice", "relative humidity over ice", "%%")
5714 SET_QNT(qnt_theta, "theta", "potential temperature", "K")
5715 SET_QNT(qnt_zeta, "zeta", "zeta coordinate", "K")
5716 SET_QNT(qnt_zeta_d, "zeta_d", "diagnosed zeta coordinate", "K")
5717 SET_QNT(qnt_zeta_dot, "zeta_dot", "velocity of zeta coordinate",
5718 "K/day")
5719 SET_QNT(qnt_eta, "eta", "eta coordinate", "1")
5720 SET_QNT(qnt_eta_dot, "eta_dot", "velocity of eta coordinate", "1/s")
5721 SET_QNT(qnt_tvirt, "tvirt", "virtual temperature", "K")
5722 SET_QNT(qnt_lapse, "lapse", "temperature lapse rate", "K/km")
5723 SET_QNT(qnt_vh, "vh", "horizontal velocity", "m/s")
5724 SET_QNT(qnt_vz, "vz", "vertical velocity", "m/s")
5725 SET_QNT(qnt_pv, "pv", "potential vorticity", "PVU")
5726 SET_QNT(qnt_tdew, "tdew", "dew point temperature", "K")
5727 SET_QNT(qnt_tice, "tice", "frost point temperature", "K")
5728 SET_QNT(qnt_tsts, "tsts", "STS existence temperature", "K")
5729 SET_QNT(qnt_tnat, "tnat", "NAT existence temperature", "K")
5730 SET_QNT(qnt_Cx, "Cx", "Trace species x volume mixing ratio", "ppv")
5731 SET_QNT(qnt_Ch2o, "Ch2o", "H2O volume mixing ratio", "ppv")
5732 SET_QNT(qnt_Co3, "Co3", "O3 volume mixing ratio", "ppv")
5733 SET_QNT(qnt_Cco, "Cco", "CO volume mixing ratio", "ppv")
5734 SET_QNT(qnt_Coh, "Coh", "HO volume mixing ratio", "ppv")
5735 SET_QNT(qnt_Ch, "Ch", "H radical volume mixing ratio", "ppv")
5736 SET_QNT(qnt_Cho2, "Cho2", "HO2 volume mixing ratio", "ppv")
5737 SET_QNT(qnt_Ch2o2, "Ch2o2", "H2O2 volume mixing ratio", "ppv")
5738 SET_QNT(qnt_Co1d, "Co1d", "O(1D) volume mixing ratio", "ppv")
5739 SET_QNT(qnt_Co3p, "Co3p", "O(3P) radical volume mixing ratio", "ppv")
5740 SET_QNT(qnt_Cccl4, "Cccl4", "CCl4 (CFC-10) volume mixing ratio", "ppv")
5741 SET_QNT(qnt_Cccl3f, "Cccl3f", "CCl3F (CFC-11) volume mixing ratio",
5742 "ppv")
5743 SET_QNT(qnt_Cccl2f2, "Cccl2f2", "CCl2F2 (CFC-12) volume mixing ratio",
5744 "ppv")
5745 SET_QNT(qnt_Cn2o, "Cn2o", "N2O volume mixing ratio", "ppv")
5746 SET_QNT(qnt_Csf6, "Csf6", "SF6 volume mixing ratio", "ppv")
5747 SET_QNT(qnt_aoa, "aoa", "age of air", "s")
5748#ifdef DD
5749 SET_QNT(qnt_destination, "destination",
5750 "subdomain index of destination", "-")
5751 SET_QNT(qnt_subdomain, "subdomain", "current subdomain index", "-")
5752#endif
5753 scan_ctl(filename, argc, argv, "QNT_UNIT", iq, "", ctl->qnt_unit[iq]);
5754 }
5755
5756 /* Vertical coordinate and velocity... */
5757 ctl->advect_vert_coord =
5758 (int) scan_ctl(filename, argc, argv, "ADVECT_VERT_COORD", -1, "0", NULL);
5759 if (ctl->advect_vert_coord < 0 || ctl->advect_vert_coord > 3)
5760 ERRMSG("ADVECT_VERT_COORD must be 0, 1, 2, or 3!");
5761
5762 if (ctl->advect_vert_coord == 1 && ctl->qnt_zeta < 0)
5763 ERRMSG("Add quantity zeta for diabatic advection!");
5764 if (ctl->advect_vert_coord == 3 && ctl->qnt_eta < 0)
5765 ERRMSG("Add quantity eta for etadot avection!");
5766
5767 ctl->met_vert_coord =
5768 (int) scan_ctl(filename, argc, argv, "MET_VERT_COORD", -1, "0", NULL);
5769 if (ctl->met_vert_coord < 0 || ctl->met_vert_coord > 4)
5770 ERRMSG("MET_VERT_COORD must be 0, 1, 2, 3, or 4!");
5771
5772 if (ctl->advect_vert_coord == 2 && ctl->met_vert_coord == 0)
5773 ERRMSG
5774 ("Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
5775 if (ctl->advect_vert_coord == 3 && ctl->met_vert_coord != 3)
5776 ERRMSG
5777 ("Using ADVECT_VERT_COORD = 3 requires A and B model level coefficients!");
5778
5779 /* Time steps of simulation... */
5780 ctl->direction =
5781 (int) scan_ctl(filename, argc, argv, "DIRECTION", -1, "1", NULL);
5782 if (ctl->direction != -1 && ctl->direction != 1)
5783 ERRMSG("Set DIRECTION to -1 or 1!");
5784 ctl->t_stop = scan_ctl(filename, argc, argv, "T_STOP", -1, "1e100", NULL);
5785 ctl->dt_mod = scan_ctl(filename, argc, argv, "DT_MOD", -1, "180", NULL);
5786
5787 /* Meteo data... */
5788 scan_ctl(filename, argc, argv, "METBASE", -1, "-", ctl->metbase);
5789 ctl->dt_met = scan_ctl(filename, argc, argv, "DT_MET", -1, "3600", NULL);
5790 ctl->met_convention =
5791 (int) scan_ctl(filename, argc, argv, "MET_CONVENTION", -1, "0", NULL);
5792 ctl->met_type =
5793 (int) scan_ctl(filename, argc, argv, "MET_TYPE", -1, "0", NULL);
5794 if (ctl->advect_vert_coord == 1 && ctl->met_type != 0)
5795 ERRMSG
5796 ("Please use meteo files in netcdf format for diabatic calculations.");
5797 if (ctl->advect_vert_coord == 3 && ctl->met_type != 0)
5798 ERRMSG
5799 ("Please use meteo files in netcdf format for etadot calculations.");
5800 ctl->met_clams =
5801 (int) scan_ctl(filename, argc, argv, "MET_CLAMS", -1, "0", NULL);
5802 ctl->met_nc_scale =
5803 (int) scan_ctl(filename, argc, argv, "MET_NC_SCALE", -1, "1", NULL);
5804 ctl->met_nc_level =
5805 (int) scan_ctl(filename, argc, argv, "MET_NC_LEVEL", -1, "0", NULL);
5806 ctl->met_nc_quant =
5807 (int) scan_ctl(filename, argc, argv, "MET_NC_QUANT", -1, "0", NULL);
5808 ctl->met_zstd_level =
5809 (int) scan_ctl(filename, argc, argv, "MET_ZSTD_LEVEL", -1, "0", NULL);
5810 for (int i = 0; i < METVAR; i++) {
5811 char defprec[LEN] = "0", deftol[LEN] = "0.0";
5812 if (i == 0) /* geopotential height */
5813 sprintf(deftol, "0.5");
5814 else if (i == 1) /* temperature */
5815 sprintf(deftol, "5.0");
5816 else /* other variables */
5817 sprintf(defprec, "8");
5818 ctl->met_comp_prec[i] =
5819 (int) scan_ctl(filename, argc, argv, "MET_COMP_PREC", i, defprec, NULL);
5820 ctl->met_comp_tol[i] =
5821 scan_ctl(filename, argc, argv, "MET_COMP_TOL", i, deftol, NULL);
5822 }
5823 ctl->met_cms_batch =
5824 (int) scan_ctl(filename, argc, argv, "MET_CMS_BATCH", -1, "-1", NULL);
5825 ctl->met_cms_zstd =
5826 (int) scan_ctl(filename, argc, argv, "MET_CMS_ZSTD", -1, "1", NULL);
5827 ctl->met_cms_nd0x =
5828 (int) scan_ctl(filename, argc, argv, "MET_CMS_ND0X", -1, "48", NULL);
5829 ctl->met_cms_nd0y =
5830 (int) scan_ctl(filename, argc, argv, "MET_CMS_ND0Y", -1, "24", NULL);
5831 ctl->met_cms_maxlev =
5832 (int) scan_ctl(filename, argc, argv, "MET_CMS_MAXLEV", -1, "6", NULL);
5833 ctl->met_cms_eps_z =
5834 scan_ctl(filename, argc, argv, "MET_CMS_EPS_Z", -1, "1.0", NULL);
5835 ctl->met_cms_eps_t =
5836 scan_ctl(filename, argc, argv, "MET_CMS_EPS_T", -1, "0.05", NULL);
5837 ctl->met_cms_eps_u =
5838 scan_ctl(filename, argc, argv, "MET_CMS_EPS_U", -1, "0.05", NULL);
5839 ctl->met_cms_eps_v =
5840 scan_ctl(filename, argc, argv, "MET_CMS_EPS_V", -1, "0.05", NULL);
5841 ctl->met_cms_eps_w =
5842 scan_ctl(filename, argc, argv, "MET_CMS_EPS_W", -1, "1.0", NULL);
5843 ctl->met_cms_eps_pv =
5844 scan_ctl(filename, argc, argv, "MET_CMS_EPS_PV", -1, "1.0", NULL);
5845 ctl->met_cms_eps_h2o =
5846 scan_ctl(filename, argc, argv, "MET_CMS_EPS_H2O", -1, "1.0", NULL);
5847 ctl->met_cms_eps_o3 =
5848 scan_ctl(filename, argc, argv, "MET_CMS_EPS_O3", -1, "1.0", NULL);
5849 ctl->met_cms_eps_lwc =
5850 scan_ctl(filename, argc, argv, "MET_CMS_EPS_LWC", -1, "1.0", NULL);
5851 ctl->met_cms_eps_rwc =
5852 scan_ctl(filename, argc, argv, "MET_CMS_EPS_RWC", -1, "1.0", NULL);
5853 ctl->met_cms_eps_iwc =
5854 scan_ctl(filename, argc, argv, "MET_CMS_EPS_IWC", -1, "1.0", NULL);
5855 ctl->met_cms_eps_swc =
5856 scan_ctl(filename, argc, argv, "MET_CMS_EPS_SWC", -1, "1.0", NULL);
5857 ctl->met_cms_eps_cc =
5858 scan_ctl(filename, argc, argv, "MET_CMS_EPS_CC", -1, "1.0", NULL);
5859 ctl->met_dx = (int) scan_ctl(filename, argc, argv, "MET_DX", -1, "1", NULL);
5860 ctl->met_dy = (int) scan_ctl(filename, argc, argv, "MET_DY", -1, "1", NULL);
5861 ctl->met_dp = (int) scan_ctl(filename, argc, argv, "MET_DP", -1, "1", NULL);
5862 if (ctl->met_dx < 1 || ctl->met_dy < 1 || ctl->met_dp < 1)
5863 ERRMSG("MET_DX, MET_DY, and MET_DP need to be greater than zero!");
5864 ctl->met_sx = (int) scan_ctl(filename, argc, argv, "MET_SX", -1, "1", NULL);
5865 ctl->met_sy = (int) scan_ctl(filename, argc, argv, "MET_SY", -1, "1", NULL);
5866 ctl->met_sp = (int) scan_ctl(filename, argc, argv, "MET_SP", -1, "1", NULL);
5867 if (ctl->met_sx < 1 || ctl->met_sy < 1 || ctl->met_sp < 1)
5868 ERRMSG("MET_SX, MET_SY, and MET_SP need to be greater than zero!");
5869 ctl->met_detrend =
5870 scan_ctl(filename, argc, argv, "MET_DETREND", -1, "-999", NULL);
5871 ctl->met_np = (int) scan_ctl(filename, argc, argv, "MET_NP", -1, "0", NULL);
5872 if (ctl->met_np > EP)
5873 ERRMSG("Too many pressure levels!");
5874 ctl->met_press_level_def =
5875 (int) scan_ctl(filename, argc, argv, "MET_PRESS_LEVEL_DEF", -1, "-1",
5876 NULL);
5877 if (ctl->met_press_level_def >= 0) {
5878 level_definitions(ctl);
5879 } else {
5880 if (ctl->met_np > 0) {
5881 for (int ip = 0; ip < ctl->met_np; ip++)
5882 ctl->met_p[ip] =
5883 scan_ctl(filename, argc, argv, "MET_P", ip, "", NULL);
5884 }
5885 }
5886 ctl->met_nlev =
5887 (int) scan_ctl(filename, argc, argv, "MET_NLEV", -1, "0", NULL);
5888 if (ctl->met_nlev > EP)
5889 ERRMSG("Too many model levels!");
5890 for (int ip = 0; ip < ctl->met_nlev; ip++)
5891 ctl->met_lev_hyam[ip] =
5892 scan_ctl(filename, argc, argv, "MET_LEV_HYAM", ip, "", NULL);
5893 for (int ip = 0; ip < ctl->met_nlev; ip++)
5894 ctl->met_lev_hybm[ip] =
5895 scan_ctl(filename, argc, argv, "MET_LEV_HYBM", ip, "", NULL);
5896 ctl->met_geopot_sx =
5897 (int) scan_ctl(filename, argc, argv, "MET_GEOPOT_SX", -1, "-1", NULL);
5898 ctl->met_geopot_sy =
5899 (int) scan_ctl(filename, argc, argv, "MET_GEOPOT_SY", -1, "-1", NULL);
5900 ctl->met_relhum =
5901 (int) scan_ctl(filename, argc, argv, "MET_RELHUM", -1, "0", NULL);
5902 ctl->met_cape =
5903 (int) scan_ctl(filename, argc, argv, "MET_CAPE", -1, "1", NULL);
5904 if (ctl->met_cape < 0 || ctl->met_cape > 1)
5905 ERRMSG("Set MET_CAPE to 0 or 1!");
5906 ctl->met_pbl =
5907 (int) scan_ctl(filename, argc, argv, "MET_PBL", -1, "3", NULL);
5908 if (ctl->met_pbl < 0 || ctl->met_pbl > 3)
5909 ERRMSG("Set MET_PBL to 0 ... 3!");
5910 ctl->met_pbl_min =
5911 scan_ctl(filename, argc, argv, "MET_PBL_MIN", -1, "0.1", NULL);
5912 ctl->met_pbl_max =
5913 scan_ctl(filename, argc, argv, "MET_PBL_MAX", -1, "5.0", NULL);
5914 ctl->met_tropo =
5915 (int) scan_ctl(filename, argc, argv, "MET_TROPO", -1, "3", NULL);
5916 if (ctl->met_tropo < 0 || ctl->met_tropo > 5)
5917 ERRMSG("Set MET_TROPO to 0 ... 5!");
5918 ctl->met_tropo_pv =
5919 scan_ctl(filename, argc, argv, "MET_TROPO_PV", -1, "3.5", NULL);
5920 ctl->met_tropo_theta =
5921 scan_ctl(filename, argc, argv, "MET_TROPO_THETA", -1, "380", NULL);
5922 ctl->met_tropo_spline =
5923 (int) scan_ctl(filename, argc, argv, "MET_TROPO_SPLINE", -1, "1", NULL);
5924 ctl->met_dt_out =
5925 scan_ctl(filename, argc, argv, "MET_DT_OUT", -1, "0.1", NULL);
5926 ctl->met_cache =
5927 (int) scan_ctl(filename, argc, argv, "MET_CACHE", -1, "0", NULL);
5928 ctl->met_mpi_share =
5929 (int) scan_ctl(filename, argc, argv, "MET_MPI_SHARE", -1, "0", NULL);
5930
5931 /* Sorting... */
5932 ctl->sort_dt = scan_ctl(filename, argc, argv, "SORT_DT", -1, "-999", NULL);
5933
5934 /* Isosurface parameters... */
5935 ctl->isosurf =
5936 (int) scan_ctl(filename, argc, argv, "ISOSURF", -1, "0", NULL);
5937 scan_ctl(filename, argc, argv, "BALLOON", -1, "-", ctl->balloon);
5938
5939 /* Random number generator... */
5940 ctl->rng_type =
5941 (int) scan_ctl(filename, argc, argv, "RNG_TYPE", -1, "1", NULL);
5942 if (ctl->rng_type < 0 || ctl->rng_type > 2)
5943 ERRMSG("Set RNG_TYPE to 0, 1, or 2!");
5944
5945 /* Advection parameters... */
5946 ctl->advect = (int) scan_ctl(filename, argc, argv, "ADVECT", -1, "2", NULL);
5947 if (!
5948 (ctl->advect == 0 || ctl->advect == 1 || ctl->advect == 2
5949 || ctl->advect == 4))
5950 ERRMSG("Set ADVECT to 0, 1, 2, or 4!");
5951
5952 /* Diffusion parameters... */
5953 ctl->diffusion
5954 = (int) scan_ctl(filename, argc, argv, "DIFFUSION", -1, "0", NULL);
5955 if (ctl->diffusion < 0 || ctl->diffusion > 2)
5956 ERRMSG("Set DIFFUSION to 0, 1 or 2!");
5957 ctl->turb_dx_pbl =
5958 scan_ctl(filename, argc, argv, "TURB_DX_PBL", -1, "50", NULL);
5959 ctl->turb_dx_trop =
5960 scan_ctl(filename, argc, argv, "TURB_DX_TROP", -1, "50", NULL);
5961 ctl->turb_dx_strat =
5962 scan_ctl(filename, argc, argv, "TURB_DX_STRAT", -1, "0", NULL);
5963 ctl->turb_dz_pbl =
5964 scan_ctl(filename, argc, argv, "TURB_DZ_PBL", -1, "0", NULL);
5965 ctl->turb_dz_trop =
5966 scan_ctl(filename, argc, argv, "TURB_DZ_TROP", -1, "0", NULL);
5967 ctl->turb_dz_strat =
5968 scan_ctl(filename, argc, argv, "TURB_DZ_STRAT", -1, "0.1", NULL);
5969 ctl->turb_mesox =
5970 scan_ctl(filename, argc, argv, "TURB_MESOX", -1, "0.16", NULL);
5971 ctl->turb_mesoz =
5972 scan_ctl(filename, argc, argv, "TURB_MESOZ", -1, "0.16", NULL);
5973
5974 /* Convection... */
5975 ctl->conv_mix_pbl
5976 = (int) scan_ctl(filename, argc, argv, "CONV_MIX_PBL", -1, "0", NULL);
5977 ctl->conv_pbl_trans
5978 = scan_ctl(filename, argc, argv, "CONV_PBL_TRANS", -1, "0", NULL);
5979 ctl->conv_cape
5980 = scan_ctl(filename, argc, argv, "CONV_CAPE", -1, "-999", NULL);
5981 ctl->conv_cin
5982 = scan_ctl(filename, argc, argv, "CONV_CIN", -1, "-999", NULL);
5983 ctl->conv_dt = scan_ctl(filename, argc, argv, "CONV_DT", -1, "-999", NULL);
5984
5985 /* Boundary conditions... */
5986 ctl->bound_mass =
5987 scan_ctl(filename, argc, argv, "BOUND_MASS", -1, "-999", NULL);
5988 ctl->bound_mass_trend =
5989 scan_ctl(filename, argc, argv, "BOUND_MASS_TREND", -1, "0", NULL);
5990 ctl->bound_vmr =
5991 scan_ctl(filename, argc, argv, "BOUND_VMR", -1, "-999", NULL);
5992 ctl->bound_vmr_trend =
5993 scan_ctl(filename, argc, argv, "BOUND_VMR_TREND", -1, "0", NULL);
5994 ctl->bound_lat0 =
5995 scan_ctl(filename, argc, argv, "BOUND_LAT0", -1, "-999", NULL);
5996 ctl->bound_lat1 =
5997 scan_ctl(filename, argc, argv, "BOUND_LAT1", -1, "-999", NULL);
5998 ctl->bound_p0 =
5999 scan_ctl(filename, argc, argv, "BOUND_P0", -1, "-999", NULL);
6000 ctl->bound_p1 =
6001 scan_ctl(filename, argc, argv, "BOUND_P1", -1, "-999", NULL);
6002 ctl->bound_dps =
6003 scan_ctl(filename, argc, argv, "BOUND_DPS", -1, "-999", NULL);
6004 ctl->bound_dzs =
6005 scan_ctl(filename, argc, argv, "BOUND_DZS", -1, "-999", NULL);
6006 ctl->bound_zetas =
6007 scan_ctl(filename, argc, argv, "BOUND_ZETAS", -1, "-999", NULL);
6008 ctl->bound_pbl =
6009 (int) scan_ctl(filename, argc, argv, "BOUND_PBL", -1, "0", NULL);
6010
6011 /* Species parameters... */
6012 scan_ctl(filename, argc, argv, "SPECIES", -1, "-", ctl->species);
6013 if (strcasecmp(ctl->species, "CF2Cl2") == 0) {
6014 ctl->molmass = 120.907;
6015 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 3e-5;
6016 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3500.0;
6017 } else if (strcasecmp(ctl->species, "CFCl3") == 0) {
6018 ctl->molmass = 137.359;
6019 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.1e-4;
6020 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3300.0;
6021 } else if (strcasecmp(ctl->species, "CH4") == 0) {
6022 ctl->molmass = 16.043;
6023 ctl->oh_chem_reaction = 2;
6024 ctl->oh_chem[0] = 2.45e-12;
6025 ctl->oh_chem[1] = 1775;
6026 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.4e-5;
6027 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1600.0;
6028 } else if (strcasecmp(ctl->species, "CO") == 0) {
6029 ctl->molmass = 28.01;
6030 ctl->oh_chem_reaction = 3;
6031 ctl->oh_chem[0] = 6.9e-33;
6032 ctl->oh_chem[1] = 2.1;
6033 ctl->oh_chem[2] = 1.1e-12;
6034 ctl->oh_chem[3] = -1.3;
6035 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 9.7e-6;
6036 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1300.0;
6037 } else if (strcasecmp(ctl->species, "CO2") == 0) {
6038 ctl->molmass = 44.009;
6039 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 3.3e-4;
6040 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2400.0;
6041 } else if (strcasecmp(ctl->species, "H2O") == 0) {
6042 ctl->molmass = 18.01528;
6043 } else if (strcasecmp(ctl->species, "N2O") == 0) {
6044 ctl->molmass = 44.013;
6045 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.4e-4;
6046 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2600.;
6047 } else if (strcasecmp(ctl->species, "NH3") == 0) {
6048 ctl->molmass = 17.031;
6049 ctl->oh_chem_reaction = 2;
6050 ctl->oh_chem[0] = 1.7e-12;
6051 ctl->oh_chem[1] = 710;
6052 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 5.9e-1;
6053 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 4200.0;
6054 } else if (strcasecmp(ctl->species, "HNO3") == 0) {
6055 ctl->molmass = 63.012;
6056 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.1e3;
6057 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 8700.0;
6058 } else if (strcasecmp(ctl->species, "NO") == 0) {
6059 ctl->molmass = 30.006;
6060 ctl->oh_chem_reaction = 3;
6061 ctl->oh_chem[0] = 7.1e-31;
6062 ctl->oh_chem[1] = 2.6;
6063 ctl->oh_chem[2] = 3.6e-11;
6064 ctl->oh_chem[3] = 0.1;
6065 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.9e-5;
6066 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 1600.0;
6067 } else if (strcasecmp(ctl->species, "NO2") == 0) {
6068 ctl->molmass = 46.005;
6069 ctl->oh_chem_reaction = 3;
6070 ctl->oh_chem[0] = 1.8e-30;
6071 ctl->oh_chem[1] = 3.0;
6072 ctl->oh_chem[2] = 2.8e-11;
6073 ctl->oh_chem[3] = 0.0;
6074 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.2e-4;
6075 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2400.0;
6076 } else if (strcasecmp(ctl->species, "O3") == 0) {
6077 ctl->molmass = 47.997;
6078 ctl->oh_chem_reaction = 2;
6079 ctl->oh_chem[0] = 1.7e-12;
6080 ctl->oh_chem[1] = 940;
6081 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1e-4;
6082 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2800.0;
6083 } else if (strcasecmp(ctl->species, "SF6") == 0) {
6084 ctl->molmass = 146.048;
6085 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 2.4e-6;
6086 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 3100.0;
6087 } else if (strcasecmp(ctl->species, "SO2") == 0) {
6088 ctl->molmass = 64.066;
6089 ctl->oh_chem_reaction = 3;
6090 ctl->oh_chem[0] = 2.9e-31;
6091 ctl->oh_chem[1] = 4.1;
6092 ctl->oh_chem[2] = 1.7e-12;
6093 ctl->oh_chem[3] = -0.2;
6094 ctl->wet_depo_ic_h[0] = ctl->wet_depo_bc_h[0] = 1.3e-2;
6095 ctl->wet_depo_ic_h[1] = ctl->wet_depo_bc_h[1] = 2900.0;
6096 }
6097
6098 /* Molar mass... */
6099 char defstr[LEN];
6100 sprintf(defstr, "%g", ctl->molmass);
6101 ctl->molmass = scan_ctl(filename, argc, argv, "MOLMASS", -1, defstr, NULL);
6102
6103 /* OH chemistry... */
6104 sprintf(defstr, "%d", ctl->oh_chem_reaction);
6105 ctl->oh_chem_reaction =
6106 (int) scan_ctl(filename, argc, argv, "OH_CHEM_REACTION", -1, defstr,
6107 NULL);
6108 for (int ip = 0; ip < 4; ip++) {
6109 sprintf(defstr, "%g", ctl->oh_chem[ip]);
6110 ctl->oh_chem[ip] =
6111 scan_ctl(filename, argc, argv, "OH_CHEM", ip, defstr, NULL);
6112 }
6113 ctl->oh_chem_beta =
6114 scan_ctl(filename, argc, argv, "OH_CHEM_BETA", -1, "0", NULL);
6115
6116 /* H2O2 chemistry... */
6117 ctl->h2o2_chem_reaction =
6118 (int) scan_ctl(filename, argc, argv, "H2O2_CHEM_REACTION", -1, "0", NULL);
6119
6120 /* KPP chemistry... */
6121 ctl->kpp_chem =
6122 (int) scan_ctl(filename, argc, argv, "KPP_CHEM", -1, "0", NULL);
6123 ctl->dt_kpp = scan_ctl(filename, argc, argv, "DT_KPP", -1, "1800", NULL);
6124
6125 /* First order tracer chemistry... */
6126 ctl->tracer_chem =
6127 (int) scan_ctl(filename, argc, argv, "TRACER_CHEM", -1, "0", NULL);
6128
6129 /* Wet deposition... */
6130 for (int ip = 0; ip < 2; ip++) {
6131 sprintf(defstr, "%g", ctl->wet_depo_ic_h[ip]);
6132 ctl->wet_depo_ic_h[ip] =
6133 scan_ctl(filename, argc, argv, "WET_DEPO_IC_H", ip, defstr, NULL);
6134 }
6135 for (int ip = 0; ip < 1; ip++) {
6136 sprintf(defstr, "%g", ctl->wet_depo_bc_h[ip]);
6137 ctl->wet_depo_bc_h[ip] =
6138 scan_ctl(filename, argc, argv, "WET_DEPO_BC_H", ip, defstr, NULL);
6139 }
6140 ctl->wet_depo_so2_ph =
6141 scan_ctl(filename, argc, argv, "WET_DEPO_SO2_PH", -1, "0", NULL);
6142 ctl->wet_depo_ic_a =
6143 scan_ctl(filename, argc, argv, "WET_DEPO_IC_A", -1, "0", NULL);
6144 ctl->wet_depo_ic_b =
6145 scan_ctl(filename, argc, argv, "WET_DEPO_IC_B", -1, "0", NULL);
6146 ctl->wet_depo_bc_a =
6147 scan_ctl(filename, argc, argv, "WET_DEPO_BC_A", -1, "0", NULL);
6148 ctl->wet_depo_bc_b =
6149 scan_ctl(filename, argc, argv, "WET_DEPO_BC_B", -1, "0", NULL);
6150 ctl->wet_depo_pre[0] =
6151 scan_ctl(filename, argc, argv, "WET_DEPO_PRE", 0, "0.5", NULL);
6152 ctl->wet_depo_pre[1] =
6153 scan_ctl(filename, argc, argv, "WET_DEPO_PRE", 1, "0.36", NULL);
6155 scan_ctl(filename, argc, argv, "WET_DEPO_IC_RET_RATIO", -1, "1", NULL);
6157 scan_ctl(filename, argc, argv, "WET_DEPO_BC_RET_RATIO", -1, "1", NULL);
6158
6159 /* Dry deposition... */
6160 ctl->dry_depo_vdep =
6161 scan_ctl(filename, argc, argv, "DRY_DEPO_VDEP", -1, "0", NULL);
6162 ctl->dry_depo_dp =
6163 scan_ctl(filename, argc, argv, "DRY_DEPO_DP", -1, "30", NULL);
6164
6165 /* Climatological data... */
6166 scan_ctl(filename, argc, argv, "CLIM_PHOTO", -1,
6167 "../../data/clams_photolysis_rates.nc", ctl->clim_photo);
6168 scan_ctl(filename, argc, argv, "CLIM_HNO3_FILENAME", -1,
6169 "../../data/gozcards_HNO3.nc", ctl->clim_hno3_filename);
6170 scan_ctl(filename, argc, argv, "CLIM_OH_FILENAME", -1,
6171 "../../data/clams_radical_species_vmr.nc", ctl->clim_oh_filename);
6172 scan_ctl(filename, argc, argv, "CLIM_H2O2_FILENAME", -1,
6173 "../../data/cams_H2O2.nc", ctl->clim_h2o2_filename);
6174 scan_ctl(filename, argc, argv, "CLIM_HO2_FILENAME", -1,
6175 "../../data/clams_radical_species_vmr.nc", ctl->clim_ho2_filename);
6176 scan_ctl(filename, argc, argv, "CLIM_O1D_FILENAME", -1,
6177 "../../data/clams_radical_species_vmr.nc", ctl->clim_o1d_filename);
6178 scan_ctl(filename, argc, argv, "CLIM_CCL4_TIMESERIES", -1,
6179 "../../data/noaa_gml_ccl4.tab", ctl->clim_ccl4_timeseries);
6180 scan_ctl(filename, argc, argv, "CLIM_CCL3F_TIMESERIES", -1,
6181 "../../data/noaa_gml_cfc11.tab", ctl->clim_ccl3f_timeseries);
6182 scan_ctl(filename, argc, argv, "CLIM_CCL2F2_TIMESERIES", -1,
6183 "../../data/noaa_gml_cfc12.tab", ctl->clim_ccl2f2_timeseries);
6184 scan_ctl(filename, argc, argv, "CLIM_N2O_TIMESERIES", -1,
6185 "../../data/noaa_gml_n2o.tab", ctl->clim_n2o_timeseries);
6186 scan_ctl(filename, argc, argv, "CLIM_SF6_TIMESERIES", -1,
6187 "../../data/noaa_gml_sf6.tab", ctl->clim_sf6_timeseries);
6188
6189 /* Mixing... */
6190 ctl->mixing_dt =
6191 scan_ctl(filename, argc, argv, "MIXING_DT", -1, "3600.", NULL);
6192 ctl->mixing_trop =
6193 scan_ctl(filename, argc, argv, "MIXING_TROP", -1, "-999", NULL);
6194 ctl->mixing_strat =
6195 scan_ctl(filename, argc, argv, "MIXING_STRAT", -1, "-999", NULL);
6196 ctl->mixing_z0 =
6197 scan_ctl(filename, argc, argv, "MIXING_Z0", -1, "-5", NULL);
6198 ctl->mixing_z1 =
6199 scan_ctl(filename, argc, argv, "MIXING_Z1", -1, "85", NULL);
6200 ctl->mixing_nz =
6201 (int) scan_ctl(filename, argc, argv, "MIXING_NZ", -1, "90", NULL);
6202 ctl->mixing_lon0 =
6203 scan_ctl(filename, argc, argv, "MIXING_LON0", -1, "-180", NULL);
6204 ctl->mixing_lon1 =
6205 scan_ctl(filename, argc, argv, "MIXING_LON1", -1, "180", NULL);
6206 ctl->mixing_nx =
6207 (int) scan_ctl(filename, argc, argv, "MIXING_NX", -1, "360", NULL);
6208 ctl->mixing_lat0 =
6209 scan_ctl(filename, argc, argv, "MIXING_LAT0", -1, "-90", NULL);
6210 ctl->mixing_lat1 =
6211 scan_ctl(filename, argc, argv, "MIXING_LAT1", -1, "90", NULL);
6212 ctl->mixing_ny =
6213 (int) scan_ctl(filename, argc, argv, "MIXING_NY", -1, "180", NULL);
6214
6215 /* Chemistry grid... */
6216 ctl->chemgrid_z0 =
6217 scan_ctl(filename, argc, argv, "CHEMGRID_Z0", -1, "-5", NULL);
6218 ctl->chemgrid_z1 =
6219 scan_ctl(filename, argc, argv, "CHEMGRID_Z1", -1, "85", NULL);
6220 ctl->chemgrid_nz =
6221 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NZ", -1, "90", NULL);
6222 ctl->chemgrid_lon0 =
6223 scan_ctl(filename, argc, argv, "CHEMGRID_LON0", -1, "-180", NULL);
6224 ctl->chemgrid_lon1 =
6225 scan_ctl(filename, argc, argv, "CHEMGRID_LON1", -1, "180", NULL);
6226 ctl->chemgrid_nx =
6227 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NX", -1, "360", NULL);
6228 ctl->chemgrid_lat0 =
6229 scan_ctl(filename, argc, argv, "CHEMGRID_LAT0", -1, "-90", NULL);
6230 ctl->chemgrid_lat1 =
6231 scan_ctl(filename, argc, argv, "CHEMGRID_LAT1", -1, "90", NULL);
6232 ctl->chemgrid_ny =
6233 (int) scan_ctl(filename, argc, argv, "CHEMGRID_NY", -1, "180", NULL);
6234
6235 /* Exponential decay... */
6236 ctl->tdec_trop = scan_ctl(filename, argc, argv, "TDEC_TROP", -1, "0", NULL);
6237 ctl->tdec_strat =
6238 scan_ctl(filename, argc, argv, "TDEC_STRAT", -1, "0", NULL);
6239
6240 /* PSC analysis... */
6241 ctl->psc_h2o = scan_ctl(filename, argc, argv, "PSC_H2O", -1, "4e-6", NULL);
6242 ctl->psc_hno3 =
6243 scan_ctl(filename, argc, argv, "PSC_HNO3", -1, "9e-9", NULL);
6244
6245 /* Output of atmospheric data... */
6246 scan_ctl(filename, argc, argv, "ATM_BASENAME", -1, "-", ctl->atm_basename);
6247 scan_ctl(filename, argc, argv, "ATM_GPFILE", -1, "-", ctl->atm_gpfile);
6248 ctl->atm_dt_out =
6249 scan_ctl(filename, argc, argv, "ATM_DT_OUT", -1, "86400", NULL);
6250 ctl->atm_filter =
6251 (int) scan_ctl(filename, argc, argv, "ATM_FILTER", -1, "0", NULL);
6252 ctl->atm_stride =
6253 (int) scan_ctl(filename, argc, argv, "ATM_STRIDE", -1, "1", NULL);
6254 ctl->atm_type =
6255 (int) scan_ctl(filename, argc, argv, "ATM_TYPE", -1, "0", NULL);
6256 ctl->atm_type_out =
6257 (int) scan_ctl(filename, argc, argv, "ATM_TYPE_OUT", -1, "-1", NULL);
6258 if (ctl->atm_type_out == -1)
6259 ctl->atm_type_out = ctl->atm_type;
6260 ctl->atm_nc_level =
6261 (int) scan_ctl(filename, argc, argv, "ATM_NC_LEVEL", -1, "0", NULL);
6262 for (int iq = 0; iq < ctl->nq; iq++)
6263 ctl->atm_nc_quant[iq] =
6264 (int) scan_ctl(filename, argc, argv, "ATM_NC_QUANT", iq, "0", NULL);
6265 ctl->obs_type =
6266 (int) scan_ctl(filename, argc, argv, "OBS_TYPE", -1, "0", NULL);
6267
6268 /* Output of CSI data... */
6269 scan_ctl(filename, argc, argv, "CSI_BASENAME", -1, "-", ctl->csi_basename);
6270 scan_ctl(filename, argc, argv, "CSI_KERNEL", -1, "-", ctl->csi_kernel);
6271 ctl->csi_dt_out =
6272 scan_ctl(filename, argc, argv, "CSI_DT_OUT", -1, "86400", NULL);
6273 scan_ctl(filename, argc, argv, "CSI_OBSFILE", -1, "-", ctl->csi_obsfile);
6274 ctl->csi_obsmin =
6275 scan_ctl(filename, argc, argv, "CSI_OBSMIN", -1, "0", NULL);
6276 ctl->csi_modmin =
6277 scan_ctl(filename, argc, argv, "CSI_MODMIN", -1, "0", NULL);
6278 ctl->csi_z0 = scan_ctl(filename, argc, argv, "CSI_Z0", -1, "-5", NULL);
6279 ctl->csi_z1 = scan_ctl(filename, argc, argv, "CSI_Z1", -1, "85", NULL);
6280 ctl->csi_nz = (int) scan_ctl(filename, argc, argv, "CSI_NZ", -1, "1", NULL);
6281 ctl->csi_lon0 =
6282 scan_ctl(filename, argc, argv, "CSI_LON0", -1, "-180", NULL);
6283 ctl->csi_lon1 = scan_ctl(filename, argc, argv, "CSI_LON1", -1, "180", NULL);
6284 ctl->csi_nx =
6285 (int) scan_ctl(filename, argc, argv, "CSI_NX", -1, "360", NULL);
6286 ctl->csi_lat0 = scan_ctl(filename, argc, argv, "CSI_LAT0", -1, "-90", NULL);
6287 ctl->csi_lat1 = scan_ctl(filename, argc, argv, "CSI_LAT1", -1, "90", NULL);
6288 ctl->csi_ny =
6289 (int) scan_ctl(filename, argc, argv, "CSI_NY", -1, "180", NULL);
6290
6291 /* Output of ensemble data... */
6292 ctl->nens = (int) scan_ctl(filename, argc, argv, "NENS", -1, "0", NULL);
6293 scan_ctl(filename, argc, argv, "ENS_BASENAME", -1, "-", ctl->ens_basename);
6294 ctl->ens_dt_out =
6295 scan_ctl(filename, argc, argv, "ENS_DT_OUT", -1, "86400", NULL);
6296
6297 /* Output of grid data... */
6298 scan_ctl(filename, argc, argv, "GRID_BASENAME", -1, "-",
6299 ctl->grid_basename);
6300 scan_ctl(filename, argc, argv, "GRID_KERNEL", -1, "-", ctl->grid_kernel);
6301 scan_ctl(filename, argc, argv, "GRID_GPFILE", -1, "-", ctl->grid_gpfile);
6302 ctl->grid_dt_out =
6303 scan_ctl(filename, argc, argv, "GRID_DT_OUT", -1, "86400", NULL);
6304 ctl->grid_sparse =
6305 (int) scan_ctl(filename, argc, argv, "GRID_SPARSE", -1, "0", NULL);
6306 ctl->grid_nc_level =
6307 (int) scan_ctl(filename, argc, argv, "GRID_NC_LEVEL", -1, "0", NULL);
6308 for (int iq = 0; iq < ctl->nq; iq++)
6309 ctl->grid_nc_quant[iq] =
6310 (int) scan_ctl(filename, argc, argv, "GRID_NC_QUANT", iq, "0", NULL);
6311 ctl->grid_stddev =
6312 (int) scan_ctl(filename, argc, argv, "GRID_STDDEV", -1, "0", NULL);
6313 ctl->grid_z0 = scan_ctl(filename, argc, argv, "GRID_Z0", -1, "-5", NULL);
6314 ctl->grid_z1 = scan_ctl(filename, argc, argv, "GRID_Z1", -1, "85", NULL);
6315 ctl->grid_nz =
6316 (int) scan_ctl(filename, argc, argv, "GRID_NZ", -1, "1", NULL);
6317 ctl->grid_lon0 =
6318 scan_ctl(filename, argc, argv, "GRID_LON0", -1, "-180", NULL);
6319 ctl->grid_lon1 =
6320 scan_ctl(filename, argc, argv, "GRID_LON1", -1, "180", NULL);
6321 ctl->grid_nx =
6322 (int) scan_ctl(filename, argc, argv, "GRID_NX", -1, "360", NULL);
6323 ctl->grid_lat0 =
6324 scan_ctl(filename, argc, argv, "GRID_LAT0", -1, "-90", NULL);
6325 ctl->grid_lat1 =
6326 scan_ctl(filename, argc, argv, "GRID_LAT1", -1, "90", NULL);
6327 ctl->grid_ny =
6328 (int) scan_ctl(filename, argc, argv, "GRID_NY", -1, "180", NULL);
6329 ctl->grid_type =
6330 (int) scan_ctl(filename, argc, argv, "GRID_TYPE", -1, "0", NULL);
6331
6332 /* Output of profile data... */
6333 scan_ctl(filename, argc, argv, "PROF_BASENAME", -1, "-",
6334 ctl->prof_basename);
6335 scan_ctl(filename, argc, argv, "PROF_OBSFILE", -1, "-", ctl->prof_obsfile);
6336 ctl->prof_z0 = scan_ctl(filename, argc, argv, "PROF_Z0", -1, "0", NULL);
6337 ctl->prof_z1 = scan_ctl(filename, argc, argv, "PROF_Z1", -1, "60", NULL);
6338 ctl->prof_nz =
6339 (int) scan_ctl(filename, argc, argv, "PROF_NZ", -1, "60", NULL);
6340 ctl->prof_lon0 =
6341 scan_ctl(filename, argc, argv, "PROF_LON0", -1, "-180", NULL);
6342 ctl->prof_lon1 =
6343 scan_ctl(filename, argc, argv, "PROF_LON1", -1, "180", NULL);
6344 ctl->prof_nx =
6345 (int) scan_ctl(filename, argc, argv, "PROF_NX", -1, "360", NULL);
6346 ctl->prof_lat0 =
6347 scan_ctl(filename, argc, argv, "PROF_LAT0", -1, "-90", NULL);
6348 ctl->prof_lat1 =
6349 scan_ctl(filename, argc, argv, "PROF_LAT1", -1, "90", NULL);
6350 ctl->prof_ny =
6351 (int) scan_ctl(filename, argc, argv, "PROF_NY", -1, "180", NULL);
6352
6353 /* Output of sample data... */
6354 scan_ctl(filename, argc, argv, "SAMPLE_BASENAME", -1, "-",
6355 ctl->sample_basename);
6356 scan_ctl(filename, argc, argv, "SAMPLE_KERNEL", -1, "-",
6357 ctl->sample_kernel);
6358 scan_ctl(filename, argc, argv, "SAMPLE_OBSFILE", -1, "-",
6359 ctl->sample_obsfile);
6360 ctl->sample_dx =
6361 scan_ctl(filename, argc, argv, "SAMPLE_DX", -1, "50", NULL);
6362 ctl->sample_dz =
6363 scan_ctl(filename, argc, argv, "SAMPLE_DZ", -1, "-999", NULL);
6364
6365 /* Output of station data... */
6366 scan_ctl(filename, argc, argv, "STAT_BASENAME", -1, "-",
6367 ctl->stat_basename);
6368 ctl->stat_lon = scan_ctl(filename, argc, argv, "STAT_LON", -1, "0", NULL);
6369 ctl->stat_lat = scan_ctl(filename, argc, argv, "STAT_LAT", -1, "0", NULL);
6370 ctl->stat_r = scan_ctl(filename, argc, argv, "STAT_R", -1, "50", NULL);
6371 ctl->stat_t0 =
6372 scan_ctl(filename, argc, argv, "STAT_T0", -1, "-1e100", NULL);
6373 ctl->stat_t1 = scan_ctl(filename, argc, argv, "STAT_T1", -1, "1e100", NULL);
6374
6375 /* Output of VTK data... */
6376 scan_ctl(filename, argc, argv, "VTK_BASENAME", -1, "-", ctl->vtk_basename);
6377 ctl->vtk_dt_out =
6378 scan_ctl(filename, argc, argv, "VTK_DT_OUT", -1, "86400", NULL);
6379 ctl->vtk_stride =
6380 (int) scan_ctl(filename, argc, argv, "VTK_STRIDE", -1, "1", NULL);
6381 ctl->vtk_scale =
6382 scan_ctl(filename, argc, argv, "VTK_SCALE", -1, "1.0", NULL);
6383 ctl->vtk_offset =
6384 scan_ctl(filename, argc, argv, "VTK_OFFSET", -1, "0.0", NULL);
6385 ctl->vtk_sphere =
6386 (int) scan_ctl(filename, argc, argv, "VTK_SPHERE", -1, "0", NULL);
6387
6388 /* Domain decomposition... */
6389 ctl->dd = (int) scan_ctl(filename, argc, argv, "DD", -1, "0", NULL);
6391 (int) scan_ctl(filename, argc, argv, "DD_SUBDOMAINS_MERIDIONAL", -1,
6392 (ctl->dd == 1) ? "2" : "1", NULL);
6393 ctl->dd_subdomains_zonal =
6394 (int) scan_ctl(filename, argc, argv, "DD_SUBDOMAINS_ZONAL", -1,
6395 (ctl->dd == 1) ? "2" : "1", NULL);
6397 ctl->dd = 1;
6398 else if (ctl->dd == 1)
6399 ERRMSG("Please provide zonal and meridional subdomain numbers!")
6400 ctl->dd_nbr_neighbours =
6401 (int) scan_ctl(filename, argc, argv, "DD_NBR_NEIGHBOURS", -1, "8",
6402 NULL);
6403 ctl->dd_halos_size =
6404 (int) scan_ctl(filename, argc, argv, "DD_HALOS_SIZE", -1, "1", NULL);
6405}
void level_definitions(ctl_t *ctl)
Defines pressure levels for meteorological data.
Definition: mptrac.c:2659
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:10951
#define METVAR
Number of 3-D meteorological variables.
Definition: mptrac.h:303
#define NQ
Maximum number of quantities per data point.
Definition: mptrac.h:313
#define SET_QNT(qnt, name, longname, unit)
Set atmospheric quantity index.
Definition: mptrac.h:1662
double grid_z0
Lower altitude of gridded data [km].
Definition: mptrac.h:3158
int qnt_o3
Quantity array index for ozone volume mixing ratio.
Definition: mptrac.h:2376
double csi_lat1
Upper latitude of gridded CSI data [deg].
Definition: mptrac.h:3119
char csi_obsfile[LEN]
Observation data file for CSI analysis.
Definition: mptrac.h:3086
int met_nc_scale
Check netCDF scaling factors (0=no, 1=yes).
Definition: mptrac.h:2610
int qnt_pel
Quantity array index for pressure at equilibrium level (EL).
Definition: mptrac.h:2409
int csi_nz
Number of altitudes of gridded CSI data.
Definition: mptrac.h:3095
int qnt_p
Quantity array index for pressure.
Definition: mptrac.h:2355
char atm_gpfile[LEN]
Gnuplot file for atmospheric data.
Definition: mptrac.h:3047
int qnt_swc
Quantity array index for cloud snow water content.
Definition: mptrac.h:2388
double csi_obsmin
Minimum observation index to trigger detection.
Definition: mptrac.h:3089
int qnt_pcb
Quantity array index for cloud bottom pressure.
Definition: mptrac.h:2397
double csi_lon1
Upper longitude of gridded CSI data [deg].
Definition: mptrac.h:3110
int qnt_u
Quantity array index for zonal wind.
Definition: mptrac.h:2364
double stat_lon
Longitude of station [deg].
Definition: mptrac.h:3236
double sort_dt
Time step for sorting of particle data [s].
Definition: mptrac.h:2768
double stat_r
Search radius around station [km].
Definition: mptrac.h:3242
int met_zstd_level
ZSTD compression level (from -5 to 22).
Definition: mptrac.h:2619
int csi_ny
Number of latitudes of gridded CSI data.
Definition: mptrac.h:3113
int vtk_sphere
Spherical projection for VTK data (0=no, 1=yes).
Definition: mptrac.h:3266
double met_pbl_min
Minimum depth of planetary boundary layer [km].
Definition: mptrac.h:2736
int qnt_iwc
Quantity array index for cloud ice water content.
Definition: mptrac.h:2385
double met_cms_eps_pv
cmultiscale compression epsilon for potential vorticity.
Definition: mptrac.h:2658
int qnt_pw
Quantity array index for partial water vapor pressure.
Definition: mptrac.h:2463
char prof_basename[LEN]
Basename for profile output file.
Definition: mptrac.h:3185
double grid_z1
Upper altitude of gridded data [km].
Definition: mptrac.h:3161
int met_dp
Stride for pressure levels.
Definition: mptrac.h:2688
double met_dt_out
Time step for sampling of meteo data along trajectories [s].
Definition: mptrac.h:2755
int qnt_h2o2
Quantity array index for H2O2 volume mixing ratio (climatology).
Definition: mptrac.h:2427
int qnt_vh
Quantity array index for horizontal wind.
Definition: mptrac.h:2499
char species[LEN]
Species.
Definition: mptrac.h:2866
int csi_nx
Number of longitudes of gridded CSI data.
Definition: mptrac.h:3104
double csi_lat0
Lower latitude of gridded CSI data [deg].
Definition: mptrac.h:3116
int met_pbl
Planetary boundary layer data (0=file, 1=z2p, 2=Richardson, 3=theta).
Definition: mptrac.h:2733
double met_comp_tol[METVAR]
Compression tolerance for SZ3 or ZFP.
Definition: mptrac.h:2625
int qnt_lwc
Quantity array index for cloud liquid water content.
Definition: mptrac.h:2379
int grid_nc_level
zlib compression level of netCDF grid data files (0=off).
Definition: mptrac.h:3146
int grid_nx
Number of longitudes of gridded data.
Definition: mptrac.h:3164
double grid_lat0
Lower latitude of gridded data [deg].
Definition: mptrac.h:3176
int qnt_ts
Quantity array index for surface temperature.
Definition: mptrac.h:2310
double met_cms_eps_h2o
cmultiscale compression epsilon for water vapor.
Definition: mptrac.h:2661
int qnt_plfc
Quantity array index for pressure at level of free convection (LCF).
Definition: mptrac.h:2406
double grid_lon0
Lower longitude of gridded data [deg].
Definition: mptrac.h:3167
int qnt_o1d
Quantity array index for O(1D) volume mixing ratio (climatology).
Definition: mptrac.h:2433
int met_tropo_spline
Tropopause interpolation method (0=linear, 1=spline).
Definition: mptrac.h:2752
char sample_kernel[LEN]
Kernel data file for sample output.
Definition: mptrac.h:3221
int qnt_tvirt
Quantity array index for virtual temperature.
Definition: mptrac.h:2493
int met_geopot_sy
Latitudinal smoothing of geopotential heights.
Definition: mptrac.h:2724
char grid_gpfile[LEN]
Gnuplot file for gridded data.
Definition: mptrac.h:3137
double met_cms_eps_u
cmultiscale compression epsilon for zonal wind.
Definition: mptrac.h:2649
int qnt_lsm
Quantity array index for land-sea mask.
Definition: mptrac.h:2331
int qnt_theta
Quantity array index for potential temperature.
Definition: mptrac.h:2475
double stat_t1
Stop time for station output [s].
Definition: mptrac.h:3248
char csi_kernel[LEN]
Kernel data file for CSI output.
Definition: mptrac.h:3080
int grid_type
Type of grid data files (0=ASCII, 1=netCDF).
Definition: mptrac.h:3182
double csi_lon0
Lower longitude of gridded CSI data [deg].
Definition: mptrac.h:3107
int qnt_pbl
Quantity array index for boundary layer pressure.
Definition: mptrac.h:2337
int grid_stddev
Include standard deviations in grid output (0=no, 1=yes).
Definition: mptrac.h:3152
int qnt_psice
Quantity array index for saturation pressure over ice.
Definition: mptrac.h:2460
int met_geopot_sx
Longitudinal smoothing of geopotential heights.
Definition: mptrac.h:2721
int met_sy
Smoothing for latitudes.
Definition: mptrac.h:2694
int qnt_ps
Quantity array index for surface pressure.
Definition: mptrac.h:2307
char prof_obsfile[LEN]
Observation data file for profile output.
Definition: mptrac.h:3188
int qnt_zs
Quantity array index for surface geopotential height.
Definition: mptrac.h:2313
int prof_nz
Number of altitudes of gridded profile data.
Definition: mptrac.h:3191
double csi_dt_out
Time step for CSI output [s].
Definition: mptrac.h:3083
int met_cape
Convective available potential energy data (0=file, 1=calculate).
Definition: mptrac.h:2730
double csi_modmin
Minimum column density to trigger detection [kg/m^2].
Definition: mptrac.h:3092
int met_sx
Smoothing for longitudes.
Definition: mptrac.h:2691
double met_cms_eps_iwc
cmultiscale compression epsilon for cloud ice water content.
Definition: mptrac.h:2673
double met_cms_eps_swc
cmultiscale compression epsilon for cloud snow water content.
Definition: mptrac.h:2676
char grid_kernel[LEN]
Kernel data file for grid output.
Definition: mptrac.h:3134
double met_cms_eps_v
cmultiscale compression epsilon for meridional wind.
Definition: mptrac.h:2652
double prof_z0
Lower altitude of gridded profile data [km].
Definition: mptrac.h:3194
int qnt_w
Quantity array index for vertical velocity.
Definition: mptrac.h:2370
double met_tropo_pv
Dynamical tropopause potential vorticity threshold [PVU].
Definition: mptrac.h:2746
int prof_nx
Number of longitudes of gridded profile data.
Definition: mptrac.h:3200
int qnt_stat
Quantity array index for station flag.
Definition: mptrac.h:2292
int met_mpi_share
Use MPI to share meteo (0=no, 1=yes).
Definition: mptrac.h:2761
int qnt_vz
Quantity array index for vertical velocity.
Definition: mptrac.h:2502
int qnt_ho2
Quantity array index for HO2 volume mixing ratio (climatology).
Definition: mptrac.h:2430
double csi_z1
Upper altitude of gridded CSI data [km].
Definition: mptrac.h:3101
double stat_t0
Start time for station output [s].
Definition: mptrac.h:3245
int dd
Domain decomposition (0=no, 1=yes, with 2x2 if not specified).
Definition: mptrac.h:3273
int atm_type_out
Type of atmospheric data files for output (-1=same as ATM_TYPE, 0=ASCII, 1=binary,...
Definition: mptrac.h:3065
int met_cms_nd0x
cmultiscale number of cells of coarsest grid in x-direction.
Definition: mptrac.h:2634
int met_nlev
Number of meteo data model levels.
Definition: mptrac.h:2712
double dt_kpp
Time step for KPP chemistry [s].
Definition: mptrac.h:2992
char csi_basename[LEN]
Basename of CSI data files.
Definition: mptrac.h:3077
int qnt_shf
Quantity array index for surface sensible heat flux.
Definition: mptrac.h:2328
int qnt_vs
Quantity array index for surface meridional wind.
Definition: mptrac.h:2319
double vtk_dt_out
Time step for VTK data output [s].
Definition: mptrac.h:3254
double conv_dt
Time interval for convection module [s].
Definition: mptrac.h:2827
char sample_obsfile[LEN]
Observation data file for sample output.
Definition: mptrac.h:3224
int qnt_hno3
Quantity array index for HNO3 volume mixing ratio (climatology).
Definition: mptrac.h:2421
char grid_basename[LEN]
Basename of grid data files.
Definition: mptrac.h:3131
int met_comp_prec[METVAR]
Compression precision for SZ3 or ZFP.
Definition: mptrac.h:2622
int qnt_h2ot
Quantity array index for tropopause water vapor volume mixing ratio.
Definition: mptrac.h:2349
int qnt_rh
Quantity array index for relative humidity over water.
Definition: mptrac.h:2469
double met_cms_eps_cc
cmultiscale compression epsilon for cloud cover.
Definition: mptrac.h:2679
double met_pbl_max
Maximum depth of planetary boundary layer [km].
Definition: mptrac.h:2739
int met_dx
Stride for longitudes.
Definition: mptrac.h:2682
int qnt_destination
Quantity array index for destination subdomain in domain decomposition.
Definition: mptrac.h:2571
int met_convention
Meteo data layout (0=[lev, lat, lon], 1=[lon, lat, lev]).
Definition: mptrac.h:2596
int qnt_zeta_d
Quantity array index for diagnosed zeta vertical coordinate.
Definition: mptrac.h:2481
int tracer_chem
Switch for first order tracer chemistry module (0=off, 1=on).
Definition: mptrac.h:2995
int diffusion
Diffusion scheme (0=off, 1=fixed-K, 2=PBL).
Definition: mptrac.h:2788
int qnt_zg
Quantity array index for geopotential height.
Definition: mptrac.h:2352
double vtk_offset
Vertical offset for VTK data [km].
Definition: mptrac.h:3263
int qnt_v
Quantity array index for meridional wind.
Definition: mptrac.h:2367
int qnt_oh
Quantity array index for OH volume mixing ratio (climatology).
Definition: mptrac.h:2424
int qnt_h2o
Quantity array index for water vapor volume mixing ratio.
Definition: mptrac.h:2373
int prof_ny
Number of latitudes of gridded profile data.
Definition: mptrac.h:3209
int qnt_rhice
Quantity array index for relative humidity over ice.
Definition: mptrac.h:2472
int qnt_rho
Quantity array index for density of air.
Definition: mptrac.h:2361
double sample_dz
Layer depth for sample output [km].
Definition: mptrac.h:3230
int obs_type
Type of observation data files (0=ASCII, 1=netCDF).
Definition: mptrac.h:3074
int grid_nc_quant[NQ]
Number of digits for quantization of netCDF grid data files (0=off).
Definition: mptrac.h:3149
double met_cms_eps_lwc
cmultiscale compression epsilon for cloud liquid water content.
Definition: mptrac.h:2667
int qnt_us
Quantity array index for surface zonal wind.
Definition: mptrac.h:2316
double met_cms_eps_z
cmultiscale compression epsilon for geopotential height.
Definition: mptrac.h:2643
double grid_lon1
Upper longitude of gridded data [deg].
Definition: mptrac.h:3170
char atm_basename[LEN]
Basename of atmospheric data files.
Definition: mptrac.h:3044
int qnt_pt
Quantity array index for tropopause pressure.
Definition: mptrac.h:2340
int qnt_cl
Quantity array index for total column cloud water.
Definition: mptrac.h:2400
double prof_z1
Upper altitude of gridded profile data [km].
Definition: mptrac.h:3197
double met_lev_hyam[EP]
Meteo data model level a coefficients.
Definition: mptrac.h:2715
int qnt_t
Quantity array index for temperature.
Definition: mptrac.h:2358
int atm_filter
Time filter for atmospheric data output (0=none, 1=missval, 2=remove).
Definition: mptrac.h:3053
int kpp_chem
Switch for KPP chemistry module (0=off, 1=on).
Definition: mptrac.h:2989
char ens_basename[LEN]
Basename of ensemble data file.
Definition: mptrac.h:3125
int met_vert_coord
Vertical coordinate of input meteo data (0=plev, 1=mlev_p_file, 2=mlev_ab_file, 3=mlev_ab_full,...
Definition: mptrac.h:2600
double csi_z0
Lower altitude of gridded CSI data [km].
Definition: mptrac.h:3098
int qnt_lapse
Quantity array index for lapse rate.
Definition: mptrac.h:2496
double stat_lat
Latitude of station [deg].
Definition: mptrac.h:3239
int grid_ny
Number of latitudes of gridded data.
Definition: mptrac.h:3173
double met_detrend
FWHM of horizontal Gaussian used for detrending [km].
Definition: mptrac.h:2700
double met_cms_eps_t
cmultiscale compression epsilon for temperature.
Definition: mptrac.h:2646
int qnt_cape
Quantity array index for convective available potential energy (CAPE).
Definition: mptrac.h:2412
int met_cms_nd0y
cmultiscale number of cells of coarsest grid in y-direction.
Definition: mptrac.h:2637
int qnt_o3c
Quantity array index for total column ozone.
Definition: mptrac.h:2418
int grid_nz
Number of altitudes of gridded data.
Definition: mptrac.h:3155
int qnt_nss
Quantity array index for northward turbulent surface stress.
Definition: mptrac.h:2325
double ens_dt_out
Time step for ensemble output [s].
Definition: mptrac.h:3128
char sample_basename[LEN]
Basename of sample data file.
Definition: mptrac.h:3218
int atm_stride
Particle index stride for atmospheric data files.
Definition: mptrac.h:3056
int met_relhum
Try to read relative humidity (0=no, 1=yes).
Definition: mptrac.h:2727
double atm_dt_out
Time step for atmospheric data output [s].
Definition: mptrac.h:3050
double prof_lat1
Upper latitude of gridded profile data [deg].
Definition: mptrac.h:3215
int met_cms_batch
cmultiscale batch size.
Definition: mptrac.h:2628
double psc_h2o
H2O volume mixing ratio for PSC analysis.
Definition: mptrac.h:3034
int met_sp
Smoothing for pressure levels.
Definition: mptrac.h:2697
double prof_lon0
Lower longitude of gridded profile data [deg].
Definition: mptrac.h:3203
int qnt_pct
Quantity array index for cloud top pressure.
Definition: mptrac.h:2394
int qnt_mloss_kpp
Quantity array index for total mass loss due to KPP chemistry.
Definition: mptrac.h:2442
int qnt_psat
Quantity array index for saturation pressure over water.
Definition: mptrac.h:2457
double met_lev_hybm[EP]
Meteo data model level b coefficients.
Definition: mptrac.h:2718
double prof_lat0
Lower latitude of gridded profile data [deg].
Definition: mptrac.h:3212
int qnt_cin
Quantity array index for convective inhibition (CIN).
Definition: mptrac.h:2415
double psc_hno3
HNO3 volume mixing ratio for PSC analysis.
Definition: mptrac.h:3037
double prof_lon1
Upper longitude of gridded profile data [deg].
Definition: mptrac.h:3206
double met_cms_eps_rwc
cmultiscale compression epsilon for cloud rain water content.
Definition: mptrac.h:2670
int met_nc_quant
Number of digits for quantization of netCDF meteo files (0=off).
Definition: mptrac.h:2616
int h2o2_chem_reaction
Reaction type for H2O2 chemistry (0=none, 1=SO2).
Definition: mptrac.h:2986
int atm_nc_quant[NQ]
Number of digits for quantization of netCDF atmospheric data files (0=off).
Definition: mptrac.h:3071
double met_cms_eps_o3
cmultiscale compression epsilon for ozone.
Definition: mptrac.h:2664
int met_cms_zstd
cmultiscale ZSTD compression (0=off, 1=on).
Definition: mptrac.h:2631
int met_cms_maxlev
cmultiscale maximum refinement level.
Definition: mptrac.h:2640
int grid_sparse
Sparse output in grid data files (0=no, 1=yes).
Definition: mptrac.h:3143
char vtk_basename[LEN]
Basename of VTK data files.
Definition: mptrac.h:3251
int qnt_tt
Quantity array index for tropopause temperature.
Definition: mptrac.h:2343
int met_nc_level
zlib compression level of netCDF meteo files (0=off).
Definition: mptrac.h:2613
double mixing_dt
Time interval for mixing [s].
Definition: mptrac.h:2914
double vtk_scale
Vertical scaling factor for VTK data.
Definition: mptrac.h:3260
double met_cms_eps_w
cmultiscale compression epsilon for vertical velocity.
Definition: mptrac.h:2655
int qnt_pv
Quantity array index for potential vorticity.
Definition: mptrac.h:2505
int qnt_sst
Quantity array index for sea surface temperature.
Definition: mptrac.h:2334
int atm_nc_level
zlib compression level of netCDF atmospheric data files (0=off).
Definition: mptrac.h:3068
int qnt_sh
Quantity array index for specific humidity.
Definition: mptrac.h:2466
int qnt_ess
Quantity array index for eastward turbulent surface stress.
Definition: mptrac.h:2322
int met_dy
Stride for latitudes.
Definition: mptrac.h:2685
int dd_subdomains_zonal
Domain decomposition zonal subdomain number.
Definition: mptrac.h:3276
int qnt_idx
Quantity array index for air parcel IDs.
Definition: mptrac.h:2286
double met_tropo_theta
Dynamical tropopause potential temperature threshold [K].
Definition: mptrac.h:2749
int qnt_rwc
Quantity array index for cloud rain water content.
Definition: mptrac.h:2382
char qnt_longname[NQ][LEN]
Quantity long names.
Definition: mptrac.h:2277
double sample_dx
Horizontal radius for sample output [km].
Definition: mptrac.h:3227
int vtk_stride
Particle index stride for VTK data.
Definition: mptrac.h:3257
char stat_basename[LEN]
Basename of station data file.
Definition: mptrac.h:3233
double grid_lat1
Upper latitude of gridded data [deg].
Definition: mptrac.h:3179
int dd_subdomains_meridional
Domain decomposition meridional subdomain number.
Definition: mptrac.h:3279
int qnt_zt
Quantity array index for tropopause geopotential height.
Definition: mptrac.h:2346
int qnt_cc
Quantity array index for cloud cover.
Definition: mptrac.h:2391
int qnt_plcl
Quantity array index for pressure at lifted condensation level (LCL).
Definition: mptrac.h:2403
double grid_dt_out
Time step for gridded data output [s].
Definition: mptrac.h:3140
int qnt_tdew
Quantity array index for dew point temperature.
Definition: mptrac.h:2508
Here is the call graph for this function:

◆ mptrac_read_met()

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

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.
ddA pointer to an dd_t structure containing MPI information, including rank and neighbours.
Returns
Returns an integer, where 1 indicates success.
Note
  • The function logs the action of reading meteorological data, including the file name.
  • It supports MPI parallelization and will share the data across multiple processes if the met_mpi_share flag is set in the control structure.
  • If ctl->met_type is 0, the data is read from a NetCDF file using the read_met_nc function.
  • If ctl->met_type is between 1 and 5 or 7, the data is read from a binary file using the read_met_bin function.
  • If ctl->met_type is 6, the data is read from grib files using the read_met_grib function.
  • If the met_type is not recognized, an error message is generated.
Author
Lars Hoffmann

Definition at line 6409 of file mptrac.c.

6414 {
6415
6416 /* Write info... */
6417 LOG(1, "Read meteo data: %s", filename);
6418
6419 /* Set rank... */
6420 int rank = 0;
6421#ifdef MPI
6422 if (ctl->met_mpi_share)
6423 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
6424#endif
6425
6426 /* Check rank... */
6427 if (!ctl->met_mpi_share || rank == 0) {
6428
6429 /* Read netCDF data... */
6430 if (ctl->met_type == 0) {
6431 if (read_met_nc(filename, ctl, met, dd) != 1)
6432 return 0;
6433 }
6434
6435 /* Read binary data... */
6436 else if ((ctl->met_type >= 1 && ctl->met_type <= 5) || ctl->met_type == 7) {
6437 if (read_met_bin(filename, ctl, met) != 1)
6438 return 0;
6439 }
6440
6441#ifdef ECCODES
6442 /* Read grib data... */
6443 else if (ctl->met_type == 6) {
6444 if (read_met_grib(filename, ctl, met) != 1)
6445 return 0;
6446 }
6447#endif
6448
6449 /* Not implemented... */
6450 else
6451 ERRMSG("MET_TYPE not implemented!");
6452
6453 /* Preprocessing for netCDF and grib files... */
6454 if (ctl->met_type == 0 || ctl->met_type == 6) {
6455
6456 /* Extrapolate data for lower boundary... */
6458
6459 /* Fix polar winds... */
6461
6462 /* Create periodic boundary conditions... */
6463#ifndef DD
6464 read_met_periodic(met);
6465#endif
6466
6467 /* Downsampling... */
6468 read_met_sample(ctl, met);
6469
6470 /* Calculate geopotential heights... */
6471 read_met_geopot(ctl, met);
6472
6473 /* Calculate potential vorticity... */
6474 read_met_pv(met);
6475
6476 /* Calculate boundary layer data... */
6477 read_met_pbl(ctl, met);
6478
6479 /* Calculate tropopause data... */
6480 read_met_tropo(ctl, clim, met);
6481
6482 /* Calculate cloud properties... */
6483 read_met_cloud(met);
6484
6485 /* Calculate convective available potential energy... */
6486 read_met_cape(ctl, clim, met);
6487
6488 /* Calculate total column ozone... */
6489 read_met_ozone(met);
6490
6491 /* Detrending... */
6492 read_met_detrend(ctl, met);
6493
6494 /* Check meteo data and smooth zeta profiles ... */
6495 read_met_monotonize(ctl, met);
6496 }
6497 }
6498
6499 /* Broadcast data via MPI... */
6500#ifdef MPI
6501 if (ctl->met_mpi_share) {
6502
6503 /* Set timer... */
6504 SELECT_TIMER("READ_MET_MPI_BCAST", "COMM", NVTX_SEND);
6505 LOG(2, "Broadcast data on rank %d...", rank);
6506
6507 /* Broadcast... */
6508 broadcast_large_data(met, sizeof(met_t));
6509 }
6510#endif
6511
6512 /* Return success... */
6513 return 1;
6514}
void read_met_geopot(const ctl_t *ctl, met_t *met)
Calculates geopotential heights from meteorological data.
Definition: mptrac.c:8122
void read_met_extrapolate(met_t *met)
Extrapolates meteorological data.
Definition: mptrac.c:8082
void read_met_sample(const ctl_t *ctl, met_t *met)
Downsamples meteorological data based on specified parameters.
Definition: mptrac.c:10505
void read_met_cloud(met_t *met)
Calculates cloud-related variables for each grid point.
Definition: mptrac.c:7921
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:10113
void read_met_detrend(const ctl_t *ctl, met_t *met)
Detrends meteorological data.
Definition: mptrac.c:7978
void read_met_monotonize(const ctl_t *ctl, met_t *met)
Makes zeta and pressure profiles monotone.
Definition: mptrac.c:9748
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
Definition: mptrac.c:10250
int read_met_nc(const char *filename, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads meteorological data from a NetCDF file and processes it.
Definition: mptrac.c:9833
void read_met_ozone(met_t *met)
Calculates the total column ozone from meteorological ozone data.
Definition: mptrac.c:10476
void read_met_pv(met_t *met)
Calculates potential vorticity (PV) from meteorological data.
Definition: mptrac.c:10370
int read_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a binary file.
Definition: mptrac.c:7523
void read_met_polar_winds(met_t *met)
Applies a fix for polar winds in meteorological data.
Definition: mptrac.c:10311
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:7806
int read_met_grib(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a grib file and processes it.
void broadcast_large_data(void *data, size_t N)
Broadcasts large data across all processes in an MPI communicator.
Here is the call graph for this function:

◆ mptrac_run_timestep()

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

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.
ddMPI information required for the domain decomposition.
Author
Lars Hoffmann

Definition at line 6518 of file mptrac.c.

6526 {
6527
6528 /* Initialize modules... */
6529 if (t == ctl->t_start) {
6530
6531 /* Initialize isosurface data... */
6532 if (ctl->isosurf >= 1 && ctl->isosurf <= 4)
6533 module_isosurf_init(ctl, cache, *met0, *met1, atm);
6534
6535 /* Initialize advection... */
6536 module_advect_init(ctl, cache, *met0, *met1, atm);
6537
6538 /* Initialize chemistry... */
6539 module_chem_init(ctl, cache, clim, *met0, *met1, atm);
6540 }
6541
6542 /* Set time steps of air parcels... */
6543 module_timesteps(ctl, cache, *met0, atm, t);
6544
6545 /* Sort particles... */
6546 if (ctl->sort_dt > 0 && fmod(t, ctl->sort_dt) == 0)
6547 module_sort(ctl, *met0, atm);
6548
6549
6550 /* Check positions (initial)... */
6551 module_position(cache, *met0, *met1, atm);
6552
6553 /* Advection... */
6554 if (ctl->advect > 0)
6555 module_advect(ctl, cache, *met0, *met1, atm);
6556
6557 /* Turbulent diffusion... */
6558 if (ctl->diffusion == 1
6559 && (ctl->turb_dx_pbl > 0 || ctl->turb_dz_pbl > 0
6560 || ctl->turb_dx_trop > 0 || ctl->turb_dz_trop > 0
6561 || ctl->turb_dx_strat > 0 || ctl->turb_dz_strat > 0))
6562 module_diff_turb(ctl, cache, clim, *met0, *met1, atm);
6563
6564 /* Mesoscale diffusion... */
6565 if (ctl->diffusion == 1 && (ctl->turb_mesox > 0 || ctl->turb_mesoz > 0))
6566 module_diff_meso(ctl, cache, *met0, *met1, atm);
6567
6568 /* Diffusion... */
6569 if (ctl->diffusion == 2)
6570 module_diff_pbl(ctl, cache, *met0, *met1, atm);
6571
6572 /* Convection... */
6573 if ((ctl->conv_mix_pbl || ctl->conv_cape >= 0)
6574 && (ctl->conv_dt <= 0 || fmod(t, ctl->conv_dt) == 0))
6575 module_convection(ctl, cache, *met0, *met1, atm);
6576
6577 /* Sedimentation... */
6578 if (ctl->qnt_rp >= 0 && ctl->qnt_rhop >= 0)
6579 module_sedi(ctl, cache, *met0, *met1, atm);
6580
6581 /* Isosurface... */
6582 if (ctl->isosurf >= 1 && ctl->isosurf <= 4)
6583 module_isosurf(ctl, cache, *met0, *met1, atm);
6584
6585 /* Check positions (final)... */
6586 module_position(cache, *met0, *met1, atm);
6587
6588 /* Interpolate meteo data... */
6589 if (ctl->met_dt_out > 0
6590 && (ctl->met_dt_out < ctl->dt_mod || fmod(t, ctl->met_dt_out) == 0))
6591 module_meteo(ctl, cache, clim, *met0, *met1, atm);
6592
6593 /* Check boundary conditions (initial)... */
6594 if ((ctl->bound_lat0 < ctl->bound_lat1)
6595 && (ctl->bound_p0 > ctl->bound_p1))
6596 module_bound_cond(ctl, cache, clim, *met0, *met1, atm);
6597
6598 /* Initialize quantity of total loss rate... */
6599 if (ctl->qnt_loss_rate >= 0) {
6600 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,atm)") {
6601 atm->q[ctl->qnt_loss_rate][ip] = 0;
6602 }
6603 }
6604
6605 /* Decay of particle mass... */
6606 if (ctl->tdec_trop > 0 && ctl->tdec_strat > 0)
6607 module_decay(ctl, cache, clim, atm);
6608
6609 /* Interparcel mixing... */
6610 if (ctl->mixing_trop >= 0 && ctl->mixing_strat >= 0
6611 && (ctl->mixing_dt <= 0 || fmod(t, ctl->mixing_dt) == 0))
6612 module_mixing(ctl, clim, atm, t);
6613
6614 /* Calculate the tracer vmr in the chemistry grid... */
6615 if (ctl->oh_chem_reaction != 0 || ctl->h2o2_chem_reaction != 0
6616 || (ctl->kpp_chem && fmod(t, ctl->dt_kpp) == 0))
6617 module_chem_grid(ctl, *met0, *met1, atm, t);
6618
6619 /* OH chemistry... */
6620 if (ctl->oh_chem_reaction != 0)
6621 module_oh_chem(ctl, cache, clim, *met0, *met1, atm);
6622
6623 /* H2O2 chemistry (for SO2 aqueous phase oxidation)... */
6624 if (ctl->h2o2_chem_reaction != 0)
6625 module_h2o2_chem(ctl, cache, clim, *met0, *met1, atm);
6626
6627 /* First-order tracer chemistry... */
6628 if (ctl->tracer_chem)
6629 module_tracer_chem(ctl, cache, clim, *met0, *met1, atm);
6630
6631 /* Domain decomposition... */
6632 if (dd->init) {
6633#ifdef DD
6634 module_dd(ctl, atm, cache, dd, met0);
6635#else
6636 ERRMSG("DD initialized, but model is compiled without DD.")
6637#endif
6638 }
6639
6640 /* KPP chemistry... */
6641 if (ctl->kpp_chem && fmod(t, ctl->dt_kpp) == 0) {
6642#ifdef KPP
6643 module_kpp_chem(ctl, cache, clim, *met0, *met1, atm);
6644#else
6645 ERRMSG("Code was compiled without KPP!");
6646#endif
6647 }
6648
6649 /* Wet deposition... */
6650 if ((ctl->wet_depo_ic_a > 0 || ctl->wet_depo_ic_h[0] > 0)
6651 && (ctl->wet_depo_bc_a > 0 || ctl->wet_depo_bc_h[0] > 0))
6652 module_wet_depo(ctl, cache, *met0, *met1, atm);
6653
6654 /* Dry deposition... */
6655 if (ctl->dry_depo_vdep > 0)
6656 module_dry_depo(ctl, cache, *met0, *met1, atm);
6657
6658 /* Check boundary conditions (final)... */
6659 if ((ctl->bound_lat0 < ctl->bound_lat1)
6660 && (ctl->bound_p0 > ctl->bound_p1))
6661 module_bound_cond(ctl, cache, clim, *met0, *met1, atm);
6662}
void module_advect(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Advances particle positions using different advection schemes.
Definition: mptrac.c:2972
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:4872
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:4189
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:3575
void module_chem_init(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Initializes the chemistry modules by setting atmospheric composition.
Definition: mptrac.c:3420
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:4296
void module_isosurf_init(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initialize the isosurface module based on atmospheric data.
Definition: mptrac.c:4013
void module_wet_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Perform wet deposition calculations for air parcels.
Definition: mptrac.c:5021
void module_chem_grid(const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double tt)
Computes gridded chemical tracer concentrations (volume mixing ratio) from individual air parcel mass...
Definition: mptrac.c:3258
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:4740
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:3462
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:3162
void module_advect_init(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initializes the advection module by setting up pressure fields.
Definition: mptrac.c:3135
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:4553
void module_diff_meso(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate mesoscale diffusion for atmospheric particles.
Definition: mptrac.c:3614
void module_sort(const ctl_t *ctl, met_t *met0, atm_t *atm)
Sort particles according to box index.
Definition: mptrac.c:4769
void module_diff_turb(const ctl_t *ctl, cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Applies turbulent diffusion processes to atmospheric particles.
Definition: mptrac.c:3816
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:4950
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:3931
void module_diff_pbl(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Computes particle diffusion within the planetary boundary layer (PBL).
Definition: mptrac.c:3691
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:4083
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:4469
void module_dry_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate dry deposition of atmospheric particles.
Definition: mptrac.c:3868
void module_dd(ctl_t *ctl, atm_t *atm, cache_t *cache, dd_t *dd, met_t **met)
Manages domain decomposition and particle communication in parallel processing.
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.
int init
Shows if domain decomposition was initialized.
Definition: mptrac.h:3784
Here is the call graph for this function:

◆ mptrac_write_atm()

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

Writes air parcel data to a file in various formats.

The mptrac_write_atm function writes the air parcel data stored in the atm structure to a file specified by filename. The format of the output file is determined by the atm_type_out field in the ctl control structure.

Parameters
filenameA string representing the name of the file to write the data to.
ctlA pointer to a ctl_t structure containing control parameters.
atmA pointer to an atm_t structure containing atmospheric data.
tThe current time, used for certain output formats.

The function performs the following steps:

  • Sets a timer for the write operation using the SELECT_TIMER macro.
  • Logs the beginning of the write operation with the specified filename.
  • Depending on the atm_type_out value in the ctl structure, writes the data in one of the following formats:
    • ASCII (atm_type_out == 0): Calls write_atm_asc.
    • Binary (atm_type_out == 1): Calls write_atm_bin.
    • netCDF (atm_type_out == 2): Calls write_atm_nc.
    • CLaMS trajectory data (atm_type_out == 3): Calls write_atm_clams_traj.
    • CLaMS position data (atm_type_out == 4): Calls write_atm_clams.
  • If the atm_type_out value is not supported, triggers an error message.
  • Logs various statistics about the atmospheric data, including the number of particles, time range, altitude range, pressure range, longitude range, and latitude range.
  • Logs the range for each quantity specified in the ctl structure.
Author
Lars Hoffmann

Definition at line 6778 of file mptrac.c.

6782 {
6783
6784 /* Set timer... */
6785 SELECT_TIMER("WRITE_ATM", "OUTPUT", NVTX_WRITE);
6786
6787 /* Write info... */
6788 LOG(1, "Write atmospheric data: %s", filename);
6789
6790 /* Write ASCII data... */
6791 if (ctl->atm_type_out == 0)
6792 write_atm_asc(filename, ctl, atm, t);
6793
6794 /* Write binary data... */
6795 else if (ctl->atm_type_out == 1)
6796 write_atm_bin(filename, ctl, atm);
6797
6798 /* Write netCDF data... */
6799 else if (ctl->atm_type_out == 2)
6800 write_atm_nc(filename, ctl, atm);
6801
6802 /* Write CLaMS trajectory data... */
6803 else if (ctl->atm_type_out == 3)
6804 write_atm_clams_traj(filename, ctl, atm, t);
6805
6806 /* Write CLaMS pos data... */
6807 else if (ctl->atm_type_out == 4)
6808 write_atm_clams(filename, ctl, atm);
6809
6810 /* Error... */
6811 else
6812 ERRMSG("Atmospheric data type not supported!");
6813
6814 /* Write info... */
6815 double mini, maxi;
6816 LOG(2, "Number of particles: %d", atm->np);
6817 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
6818 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
6819 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
6820 LOG(2, "Altitude range: %g ... %g km", Z(maxi), Z(mini));
6821 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
6822 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
6823 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
6824 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
6825 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
6826 for (int iq = 0; iq < ctl->nq; iq++) {
6827 char msg[5 * LEN];
6828 sprintf(msg, "Quantity %s range: %s ... %s %s",
6829 ctl->qnt_name[iq], ctl->qnt_format[iq],
6830 ctl->qnt_format[iq], ctl->qnt_unit[iq]);
6831 gsl_stats_minmax(&mini, &maxi, atm->q[iq], 1, (size_t) atm->np);
6832 LOG(2, msg, mini, maxi);
6833 }
6834}
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:11466
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:11281
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:11413
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:11363
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:11624
Here is the call graph for this function:

◆ mptrac_write_met()

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

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

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

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

Definition at line 6838 of file mptrac.c.

6841 {
6842
6843 /* Set timer... */
6844 SELECT_TIMER("WRITE_MET", "OUTPUT", NVTX_WRITE);
6845
6846 /* Write info... */
6847 LOG(1, "Write meteo data: %s", filename);
6848
6849 /* Check compression flags... */
6850#ifndef ZFP
6851 if (ctl->met_type == 3)
6852 ERRMSG("MPTRAC was compiled without ZFP compression!");
6853#endif
6854#ifndef ZSTD
6855 if (ctl->met_type == 4)
6856 ERRMSG("MPTRAC was compiled without ZSTD compression!");
6857#endif
6858#ifndef CMS
6859 if (ctl->met_type == 5)
6860 ERRMSG("MPTRAC was compiled without cmultiscale compression!");
6861#endif
6862#ifndef SZ3
6863 if (ctl->met_type == 7)
6864 ERRMSG("MPTRAC was compiled without SZ3 compression!");
6865#endif
6866
6867 /* Write netCDF data... */
6868 if (ctl->met_type == 0)
6869 write_met_nc(filename, ctl, met);
6870
6871 /* Write binary data... */
6872 else if (ctl->met_type >= 1 && ctl->met_type <= 7)
6873 write_met_bin(filename, ctl, met);
6874
6875 /* Not implemented... */
6876 else
6877 ERRMSG("MET_TYPE not implemented!");
6878}
void write_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a NetCDF file.
Definition: mptrac.c:12701
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:12470
Here is the call graph for this function:

◆ mptrac_write_output()

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

Writes various types of output data to files in a specified directory.

The mptrac_write_output function writes various types of output data to files in the directory specified by the dirname parameter. The function takes control parameters (ctl), two meteorological data structures (met0 and met1), an atmospheric data structure (atm), and a time value (t) as input.

Parameters
dirnameA string representing the directory path where output files will be written.
ctlA pointer to a ctl_t structure containing control parameters.
met0A pointer to a met_t structure representing the first set of meteorological data.
met1A pointer to a met_t structure representing the second set of meteorological data.
atmA pointer to an atm_t structure representing atmospheric data.
tA double value representing the time at which the output is being written.

The function performs the following steps:

  • Parses the input time (t) to extract year, month, day, hour, minute, and second.
  • Updates host memory if necessary based on control parameters.
  • Writes atmospheric data to files if specified by control parameters.
  • Writes gridded data to files if specified by control parameters.
  • Writes CSI (Critical Success Index) data to files if specified by control parameters.
  • Writes ensemble data to files if specified by control parameters.
  • Writes profile data to files if specified by control parameters.
  • Writes sample data to files if specified by control parameters.
  • Writes station data to files if specified by control parameters.
  • Writes VTK (Visualization Toolkit) data to files if specified by control parameters.
Note
This function orchestrates the writing of various types of output data to files based on control parameters and the current simulation time.
Author
Lars Hoffmann

Definition at line 6882 of file mptrac.c.

6888 {
6889
6890 char ext[10], filename[2 * LEN];
6891
6892 double r;
6893
6894 int year, mon, day, hour, min, sec;
6895
6896 /* Get time... */
6897 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
6898
6899 /* Update host... */
6900 if ((ctl->atm_basename[0] != '-' && fmod(t, ctl->atm_dt_out) == 0)
6901 || (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0)
6902 || (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0)
6903 || ctl->csi_basename[0] != '-' || ctl->prof_basename[0] != '-'
6904 || ctl->sample_basename[0] != '-' || ctl->stat_basename[0] != '-'
6905 || (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0))
6906 mptrac_update_host(NULL, NULL, NULL, NULL, NULL, atm);
6907
6908 /* Write atmospheric data... */
6909 if (ctl->atm_basename[0] != '-' &&
6910 (fmod(t, ctl->atm_dt_out) == 0 || t == ctl->t_stop)) {
6911 if (ctl->atm_type_out == 0)
6912 sprintf(ext, "tab");
6913 else if (ctl->atm_type_out == 1)
6914 sprintf(ext, "bin");
6915 else if (ctl->atm_type_out == 2)
6916 sprintf(ext, "nc");
6917 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6918 dirname, ctl->atm_basename, year, mon, day, hour, min, ext);
6919 mptrac_write_atm(filename, ctl, atm, t);
6920 }
6921
6922 /* Write gridded data... */
6923 if (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0) {
6924 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6925 dirname, ctl->grid_basename, year, mon, day, hour, min,
6926 ctl->grid_type == 0 ? "tab" : "nc");
6927 write_grid(filename, ctl, met0, met1, atm, t);
6928 }
6929
6930 /* Write CSI data... */
6931 if (ctl->csi_basename[0] != '-') {
6932 sprintf(filename, "%s/%s.tab", dirname, ctl->csi_basename);
6933 write_csi(filename, ctl, atm, t);
6934 }
6935
6936 /* Write ensemble data... */
6937 if (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0) {
6938 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
6939 dirname, ctl->ens_basename, year, mon, day, hour, min);
6940 write_ens(filename, ctl, atm, t);
6941 }
6942
6943 /* Write profile data... */
6944 if (ctl->prof_basename[0] != '-') {
6945 sprintf(filename, "%s/%s.tab", dirname, ctl->prof_basename);
6946 write_prof(filename, ctl, met0, met1, atm, t);
6947 }
6948
6949 /* Write sample data... */
6950 if (ctl->sample_basename[0] != '-') {
6951 sprintf(filename, "%s/%s.tab", dirname, ctl->sample_basename);
6952 write_sample(filename, ctl, met0, met1, atm, t);
6953 }
6954
6955 /* Write station data... */
6956 if (ctl->stat_basename[0] != '-') {
6957 sprintf(filename, "%s/%s.tab", dirname, ctl->stat_basename);
6958 write_station(filename, ctl, atm, t);
6959 }
6960
6961 /* Write VTK data... */
6962 if (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0) {
6963 static int nvtk;
6964 if (t == ctl->t_start)
6965 nvtk = 0;
6966 sprintf(filename, "%s/%s_%05d.vtk", dirname, ctl->vtk_basename, ++nvtk);
6967 write_vtk(filename, ctl, atm, t);
6968 }
6969}
void mptrac_write_atm(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes air parcel data to a file in various formats.
Definition: mptrac.c:6778
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:11948
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:12924
void mptrac_update_host(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates host memory for specified data structures.
Definition: mptrac.c:6722
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:13313
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:13399
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:13151
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:12045
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:11673
Here is the call graph for this function:

◆ mptrac_update_device()

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

Updates device memory for specified data structures.

This function updates the GPU memory with the data from the provided host data structures (ctl, cache, clim, atm) using OpenACC directives. It ensures that the host data is transferred to the device for further computation.

Parameters
[in]ctlPointer to the ctl_t structure. If not NULL, the corresponding device memory for ctl is updated.
[in]cachePointer to the cache_t structure. If not NULL, the corresponding device memory for cache is updated.
[in]climPointer to the clim_t structure. If not NULL, the corresponding device memory for clim is updated.
[in]met0Pointer to the first met_t structure. If not NULL, the corresponding device memory for met0 is updated.
[in]met1Pointer to the second met_t structure. If not NULL, the corresponding device memory for met1 is updated.
[in]atmPointer to the atm_t structure. If not NULL, the corresponding device memory for atm is updated.
Note
The function assumes that OpenACC is enabled and uses the #pragma acc update directive for device memory synchronization. Each update operation is wrapped with a timer labeled as "UPDATE_DEVICE" for performance tracking.
Warning
Ensure that the pointers passed to this function are valid and properly initialized before calling this function. Passing invalid or uninitialized pointers may lead to undefined behavior.
Author
Lars Hoffmann

Definition at line 6666 of file mptrac.c.

6672 {
6673
6674 /* Update GPU... */
6675 if (ctl != NULL) {
6676#ifdef _OPENACC
6677 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
6678#pragma acc update device(ctl[:1])
6679#endif
6680 }
6681
6682 if (cache != NULL) {
6683#ifdef _OPENACC
6684 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
6685#pragma acc update device(cache[:1])
6686#endif
6687 }
6688
6689 if (clim != NULL) {
6690#ifdef _OPENACC
6691 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
6692#pragma acc update device(clim[:1])
6693#endif
6694 }
6695
6696 if (met0 != NULL) {
6697#ifdef _OPENACC
6698 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
6699 met_t *met0up = *met0;
6700#pragma acc update device(met0up[:1])
6701#endif
6702 }
6703
6704 if (met1 != NULL) {
6705#ifdef _OPENACC
6706 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
6707 met_t *met1up = *met1;
6708#pragma acc update device(met1up[:1])
6709#endif
6710 }
6711
6712 if (atm != NULL) {
6713#ifdef _OPENACC
6714 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
6715#pragma acc update device(atm[:1])
6716#endif
6717 }
6718}

◆ mptrac_update_host()

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

Updates host memory for specified data structures.

This function transfers data from the device (GPU) memory back to the host memory for the provided data structures (ctl, cache, clim, atm) using OpenACC directives. It ensures that the latest data from the device is synchronized with the host.

Parameters
[in]ctlPointer to the ctl_t structure. If not NULL, the corresponding host memory for ctl is updated from the device.
[in]cachePointer to the cache_t structure. If not NULL, the corresponding host memory for cache is updated from the device.
[in]climPointer to the clim_t structure. If not NULL, the corresponding host memory for clim is updated from the device.
[in]met0Pointer to the first met_t structure. If not NULL, the corresponding host memory for met0 is updated.
[in]met1Pointer to the second met_t structure. If not NULL, the corresponding host memory for met1 is updated.
[in]atmPointer to the atm_t structure. If not NULL, the corresponding host memory for atm is updated from the device.
Note
The function assumes that OpenACC is enabled and uses the #pragma acc update directive for host memory synchronization. Each update operation is wrapped with a timer labeled as "UPDATE_HOST" for performance tracking.
Warning
Ensure that the pointers passed to this function are valid and properly initialized before calling this function
Author
Lars Hoffmann

Definition at line 6722 of file mptrac.c.

6728 {
6729
6730 /* Update GPU... */
6731 if (ctl != NULL) {
6732#ifdef _OPENACC
6733 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
6734#pragma acc update host(ctl[:1])
6735#endif
6736 }
6737
6738 if (cache != NULL) {
6739#ifdef _OPENACC
6740 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
6741#pragma acc update host(cache[:1])
6742#endif
6743 }
6744
6745 if (clim != NULL) {
6746#ifdef _OPENACC
6747 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
6748#pragma acc update host(clim[:1])
6749#endif
6750 }
6751
6752 if (met0 != NULL) {
6753#ifdef _OPENACC
6754 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
6755 met_t *met0up = *met0;
6756#pragma acc update host(met0up[:1])
6757#endif
6758 }
6759
6760 if (met1 != NULL) {
6761#ifdef _OPENACC
6762 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
6763 met_t *met1up = *met1;
6764#pragma acc update host(met1up[:1])
6765#endif
6766 }
6767
6768 if (atm != NULL) {
6769#ifdef _OPENACC
6770 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
6771#pragma acc update host(atm[:1])
6772#endif
6773 }
6774}

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

6976 {
6977
6978 /* Check water vapor volume mixing ratio... */
6979 const double h2o_help = MAX(h2o, 0.1e-6);
6980
6981 /* Calculate T_NAT... */
6982 const double p_hno3 = hno3 * p / 1.333224;
6983 const double p_h2o = h2o_help * p / 1.333224;
6984 const double a = 0.009179 - 0.00088 * log10(p_h2o);
6985 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
6986 const double c = -11397.0 / a;
6987 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
6988 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
6989 if (x2 > 0)
6990 tnat = x2;
6991
6992 return tnat;
6993}

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

7002 {
7003
7004 /* Get pressure range... */
7005 const double p1 = pbl - ctl->conv_pbl_trans * (ps - pbl);
7006 const double p0 = pbl;
7007
7008 /* Get weighting factor... */
7009 if (atm->p[ip] > p0)
7010 return 1;
7011 else if (atm->p[ip] < p1)
7012 return 0;
7013 else
7014 return LIN(p0, 1.0, p1, 0.0, atm->p[ip]);
7015}

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

7022 {
7023
7024 /* Open file... */
7025 FILE *in;
7026 if (!(in = fopen(filename, "r"))) {
7027 WARN("Cannot open file!");
7028 return 0;
7029 }
7030
7031 /* Read line... */
7032 char line[LEN];
7033 while (fgets(line, LEN, in)) {
7034
7035 /* Read data... */
7036 char *tok;
7037 TOK(line, tok, "%lg", atm->time[atm->np]);
7038 TOK(NULL, tok, "%lg", atm->p[atm->np]);
7039 TOK(NULL, tok, "%lg", atm->lon[atm->np]);
7040 TOK(NULL, tok, "%lg", atm->lat[atm->np]);
7041 for (int iq = 0; iq < ctl->nq; iq++)
7042 TOK(NULL, tok, "%lg", atm->q[iq][atm->np]);
7043
7044 /* Convert altitude to pressure... */
7045 atm->p[atm->np] = P(atm->p[atm->np]);
7046
7047 /* Increment data point counter... */
7048 if ((++atm->np) > NP)
7049 ERRMSG("Too many data points!");
7050 }
7051
7052 /* Close file... */
7053 fclose(in);
7054
7055 /* Return success... */
7056 return 1;
7057}
#define TOK(line, tok, format, var)
Get string tokens.
Definition: mptrac.h:1833

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

7064 {
7065
7066 /* Open file... */
7067 FILE *in;
7068 if (!(in = fopen(filename, "r")))
7069 return 0;
7070
7071 /* Check version of binary data... */
7072 int version;
7073 FREAD(&version, int,
7074 1,
7075 in);
7076 if (version != 100)
7077 ERRMSG("Wrong version of binary data!");
7078
7079 /* Read data... */
7080 FREAD(&atm->np, int,
7081 1,
7082 in);
7083 FREAD(atm->time, double,
7084 (size_t) atm->np,
7085 in);
7086 FREAD(atm->p, double,
7087 (size_t) atm->np,
7088 in);
7089 FREAD(atm->lon, double,
7090 (size_t) atm->np,
7091 in);
7092 FREAD(atm->lat, double,
7093 (size_t) atm->np,
7094 in);
7095 for (int iq = 0; iq < ctl->nq; iq++)
7096 FREAD(atm->q[iq], double,
7097 (size_t) atm->np,
7098 in);
7099
7100 /* Read final flag... */
7101 int final;
7102 FREAD(&final, int,
7103 1,
7104 in);
7105 if (final != 999)
7106 ERRMSG("Error while reading binary data!");
7107
7108 /* Close file... */
7109 fclose(in);
7110
7111 /* Return success... */
7112 return 1;
7113}

◆ read_atm_clams()

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

Reads atmospheric data from a CLAMS NetCDF file.

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

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

Definition at line 7117 of file mptrac.c.

7120 {
7121
7122 int ncid, varid;
7123
7124 /* Open file... */
7125 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7126 return 0;
7127
7128 /* Get dimensions... */
7129 NC_INQ_DIM("NPARTS", &atm->np, 1, NP, 1);
7130
7131 /* Get time... */
7132 if (nc_inq_varid(ncid, "TIME_INIT", &varid) == NC_NOERR) {
7133 NC(nc_get_var_double(ncid, varid, atm->time));
7134 } else {
7135 WARN("TIME_INIT not found use time instead!");
7136 double time_init;
7137 NC_GET_DOUBLE("time", &time_init, 1);
7138 for (int ip = 0; ip < atm->np; ip++) {
7139 atm->time[ip] = time_init;
7140 }
7141 }
7142
7143 /* Read zeta coordinate, pressure is optional... */
7144 if (ctl->advect_vert_coord == 1) {
7145 NC_GET_DOUBLE("ZETA", atm->q[ctl->qnt_zeta], 1);
7146 NC_GET_DOUBLE("PRESS", atm->p, 0);
7147 }
7148
7149 /* Read pressure, zeta coordinate is optional... */
7150 else {
7151 if (nc_inq_varid(ncid, "PRESS_INIT", &varid) == NC_NOERR) {
7152 NC(nc_get_var_double(ncid, varid, atm->p));
7153 } else {
7154 WARN("PRESS_INIT not found use PRESS instead!");
7155 nc_inq_varid(ncid, "PRESS", &varid);
7156 NC(nc_get_var_double(ncid, varid, atm->p));
7157 }
7158 }
7159
7160 /* Read further quantities if requested... */
7161 for (int iq = 0; iq < ctl->nq; iq++)
7162 NC_GET_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
7163
7164 /* Read longitude and latitude... */
7165 NC_GET_DOUBLE("LON", atm->lon, 1);
7166 NC_GET_DOUBLE("LAT", atm->lat, 1);
7167
7168 /* Close file... */
7169 NC(nc_close(ncid));
7170
7171 /* Return success... */
7172 return 1;
7173}
#define NC(cmd)
Execute a NetCDF command and check for errors.
Definition: mptrac.h:1167
#define NC_GET_DOUBLE(varname, ptr, force)
Retrieve a double-precision variable from a NetCDF file.
Definition: mptrac.h:1226
#define NC_INQ_DIM(dimname, ptr, min, max, check)
Inquire the length of a dimension in a NetCDF file.
Definition: mptrac.h:1256

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

7180 {
7181
7182 int ncid, varid;
7183
7184 /* Open file... */
7185 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7186 return 0;
7187
7188 /* Get dimensions... */
7189 NC_INQ_DIM("obs", &atm->np, 1, NP, 1);
7190
7191 /* Read geolocations... */
7192 NC_GET_DOUBLE("time", atm->time, 1);
7193 NC_GET_DOUBLE("press", atm->p, 1);
7194 NC_GET_DOUBLE("lon", atm->lon, 1);
7195 NC_GET_DOUBLE("lat", atm->lat, 1);
7196
7197 /* Read variables... */
7198 for (int iq = 0; iq < ctl->nq; iq++)
7199 NC_GET_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
7200
7201 /* Close file... */
7202 NC(nc_close(ncid));
7203
7204 /* Return success... */
7205 return 1;
7206}

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

7212 {
7213
7214 int ncid, varid;
7215
7216 /* Write info... */
7217 LOG(1, "Read photolysis rates: %s", filename);
7218
7219 /* Open netCDF file... */
7220 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7221 WARN("Photolysis rate data are missing!");
7222 return;
7223 }
7224
7225 /* Read pressure data... */
7226 NC_INQ_DIM("press", &photo->np, 2, CP, 1);
7227 NC_GET_DOUBLE("press", photo->p, 1);
7228 if (photo->p[0] < photo->p[1])
7229 ERRMSG("Pressure data are not descending!");
7230
7231 /* Read total column ozone data... */
7232 NC_INQ_DIM("total_o3col", &photo->no3c, 2, CO3, 1);
7233 NC_GET_DOUBLE("total_o3col", photo->o3c, 1);
7234 if (photo->o3c[0] > photo->o3c[1])
7235 ERRMSG("Total column ozone data are not ascending!");
7236
7237 /* Read solar zenith angle data... */
7238 NC_INQ_DIM("sza", &photo->nsza, 2, CSZA, 1);
7239 NC_GET_DOUBLE("sza", photo->sza, 1);
7240 if (photo->sza[0] > photo->sza[1])
7241 ERRMSG("Solar zenith angle data are not ascending!");
7242
7243 /* Read data... */
7244 read_clim_photo_help(ncid, "J_N2O", photo, photo->n2o);
7245 read_clim_photo_help(ncid, "J_CCl4", photo, photo->ccl4);
7246 read_clim_photo_help(ncid, "J_CFC-11", photo, photo->ccl3f);
7247 read_clim_photo_help(ncid, "J_CFC-12", photo, photo->ccl2f2);
7248 read_clim_photo_help(ncid, "J_O2", photo, photo->o2);
7249 read_clim_photo_help(ncid, "J_O3b", photo, photo->o3_1);
7250 read_clim_photo_help(ncid, "J_O3a", photo, photo->o3_2);
7251 read_clim_photo_help(ncid, "J_H2O2", photo, photo->h2o2);
7252 read_clim_photo_help(ncid, "J_H2O", photo, photo->h2o);
7253
7254 /* Close netCDF file... */
7255 NC(nc_close(ncid));
7256
7257 /* Write info... */
7258 LOG(2, "Number of pressure levels: %d", photo->np);
7259 LOG(2, "Altitude levels: %g, %g ... %g km",
7260 Z(photo->p[0]), Z(photo->p[1]), Z(photo->p[photo->np - 1]));
7261 LOG(2, "Pressure levels: %g, %g ... %g hPa",
7262 photo->p[0], photo->p[1], photo->p[photo->np - 1]);
7263 LOG(2, "Number of solar zenith angles: %d", photo->nsza);
7264 LOG(2, "Solar zenith angles: %g, %g ... %g deg",
7265 RAD2DEG(photo->sza[0]), RAD2DEG(photo->sza[1]),
7266 RAD2DEG(photo->sza[photo->nsza - 1]));
7267 LOG(2, "Number of total column ozone values: %d", photo->no3c);
7268 LOG(2, "Total column ozone: %g, %g ... %g DU",
7269 photo->o3c[0], photo->o3c[1], photo->o3c[photo->no3c - 1]);
7270 LOG(2, "N2O photolysis rate: %g, %g ... %g s**-1",
7271 photo->n2o[0][0][0], photo->n2o[1][0][0],
7272 photo->n2o[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
7273 LOG(2, "CCl4 photolysis rate: %g, %g ... %g s**-1",
7274 photo->ccl4[0][0][0], photo->ccl4[1][0][0],
7275 photo->ccl4[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
7276 LOG(2, "CFC-11 photolysis rate: %g, %g ... %g s**-1",
7277 photo->ccl3f[0][0][0], photo->ccl3f[1][0][0],
7278 photo->ccl3f[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
7279 LOG(2, "CFC-12 photolysis rate: %g, %g ... %g s**-1",
7280 photo->ccl2f2[0][0][0], photo->ccl2f2[1][0][0],
7281 photo->ccl2f2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
7282 LOG(2, "O2 photolysis rate: %g, %g ... %g s**-1",
7283 photo->o2[0][0][0], photo->o2[1][0][0],
7284 photo->o2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
7285 LOG(2, "O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
7286 photo->o3_1[0][0][0], photo->o3_1[1][0][0],
7287 photo->o3_1[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
7288 LOG(2, "O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
7289 photo->o3_2[0][0][0], photo->o3_2[1][0][0],
7290 photo->o3_2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
7291 LOG(2, "H2O2 photolysis rate: %g, %g ... %g s**-1",
7292 photo->h2o2[0][0][0], photo->h2o2[1][0][0],
7293 photo->h2o2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
7294 LOG(2, "H2O photolysis rate: %g, %g ... %g s**-1",
7295 photo->h2o[0][0][0], photo->h2o[1][0][0],
7296 photo->h2o[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
7297}
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:7301
#define CP
Maximum number of pressure levels for climatological data.
Definition: mptrac.h:348
#define CO3
Maximum number of total column ozone data for climatological data.
Definition: mptrac.h:343
#define CSZA
Maximum number of solar zenith angles for climatological data.
Definition: mptrac.h:353
double o3_1[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O1d + O2) [1/s].
Definition: mptrac.h:3420
double o2[CP][CSZA][CO3]
O2 photolysis rate [1/s].
Definition: mptrac.h:3417
double h2o2[CP][CSZA][CO3]
H2O2 photolysis rate [1/s].
Definition: mptrac.h:3426
double h2o[CP][CSZA][CO3]
H2O photolysis rate [1/s].
Definition: mptrac.h:3429
double o3_2[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O3p + O2) [1/s].
Definition: mptrac.h:3423
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 7301 of file mptrac.c.

7305 {
7306
7307 /* Allocate... */
7308 double *help;
7309 ALLOC(help, double,
7310 photo->np * photo->nsza * photo->no3c);
7311
7312 /* Read varible... */
7313 int varid;
7314 NC_GET_DOUBLE(varname, help, 1);
7315
7316 /* Copy data... */
7317 for (int ip = 0; ip < photo->np; ip++)
7318 for (int is = 0; is < photo->nsza; is++)
7319 for (int io = 0; io < photo->no3c; io++)
7320 var[ip][is][io] =
7321 help[ARRAY_3D(ip, is, photo->nsza, io, photo->no3c)];
7322
7323 /* Free... */
7324 free(help);
7325}

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

7331 {
7332
7333 /* Write info... */
7334 LOG(1, "Read climatological time series: %s", filename);
7335
7336 /* Open file... */
7337 FILE *in;
7338 if (!(in = fopen(filename, "r"))) {
7339 WARN("Cannot open file!");
7340 return 0;
7341 }
7342
7343 /* Read data... */
7344 char line[LEN];
7345 int nh = 0;
7346 while (fgets(line, LEN, in))
7347 if (sscanf(line, "%lg %lg", &ts->time[nh], &ts->vmr[nh]) == 2) {
7348
7349 /* Convert years to seconds... */
7350 ts->time[nh] = (ts->time[nh] - 2000.0) * 365.25 * 86400.;
7351
7352 /* Check data... */
7353 if (nh > 0 && ts->time[nh] <= ts->time[nh - 1])
7354 ERRMSG("Time series must be ascending!");
7355
7356 /* Count time steps... */
7357 if ((++nh) >= CTS)
7358 ERRMSG("Too many data points!");
7359 }
7360
7361 /* Close file... */
7362 fclose(in);
7363
7364 /* Check number of data points... */
7365 ts->ntime = nh;
7366 if (nh < 2)
7367 ERRMSG("Not enough data points!");
7368
7369 /* Write info... */
7370 LOG(2, "Number of time steps: %d", ts->ntime);
7371 LOG(2, "Time steps: %.2f, %.2f ... %.2f s", ts->time[0], ts->time[1],
7372 ts->time[nh - 1]);
7373 LOG(2, "Volume mixing ratio range: %g ... %g ppv",
7374 gsl_stats_min(ts->vmr, 1, (size_t) nh), gsl_stats_max(ts->vmr, 1,
7375 (size_t) nh));
7376
7377 /* Exit success... */
7378 return 1;
7379}
#define CTS
Maximum number of data points of climatological time series.
Definition: mptrac.h:363

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

7386 {
7387
7388 int ncid, varid, it, iy, iz, iz2, nt;
7389
7390 double *help, varmin = 1e99, varmax = -1e99;
7391
7392 /* Write info... */
7393 LOG(1, "Read %s data: %s", varname, filename);
7394
7395 /* Open netCDF file... */
7396 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7397 WARN("%s climatology data are missing!", varname);
7398 return;
7399 }
7400
7401 /* Read pressure data... */
7402 NC_INQ_DIM("press", &zm->np, 2, CP, 1);
7403 NC_GET_DOUBLE("press", zm->p, 1);
7404 if (zm->p[0] < zm->p[1])
7405 ERRMSG("Pressure data are not descending!");
7406
7407 /* Read latitudes... */
7408 NC_INQ_DIM("lat", &zm->nlat, 2, CY, 1);
7409 NC_GET_DOUBLE("lat", zm->lat, 1);
7410 if (zm->lat[0] > zm->lat[1])
7411 ERRMSG("Latitude data are not ascending!");
7412
7413 /* Set time data (for monthly means)... */
7414 zm->ntime = 12;
7415 zm->time[0] = 1209600.00;
7416 zm->time[1] = 3888000.00;
7417 zm->time[2] = 6393600.00;
7418 zm->time[3] = 9072000.00;
7419 zm->time[4] = 11664000.00;
7420 zm->time[5] = 14342400.00;
7421 zm->time[6] = 16934400.00;
7422 zm->time[7] = 19612800.00;
7423 zm->time[8] = 22291200.00;
7424 zm->time[9] = 24883200.00;
7425 zm->time[10] = 27561600.00;
7426 zm->time[11] = 30153600.00;
7427
7428 /* Check number of timesteps... */
7429 NC_INQ_DIM("time", &nt, 12, 12, 1);
7430
7431 /* Read data... */
7432 ALLOC(help, double,
7433 zm->nlat * zm->np * zm->ntime);
7434 NC_GET_DOUBLE(varname, help, 1);
7435 for (it = 0; it < zm->ntime; it++)
7436 for (iz = 0; iz < zm->np; iz++)
7437 for (iy = 0; iy < zm->nlat; iy++)
7438 zm->vmr[it][iz][iy] = help[ARRAY_3D(it, iz, zm->np, iy, zm->nlat)];
7439 free(help);
7440
7441 /* Fix data gaps... */
7442 for (it = 0; it < zm->ntime; it++)
7443 for (iy = 0; iy < zm->nlat; iy++)
7444 for (iz = 0; iz < zm->np; iz++) {
7445 if (zm->vmr[it][iz][iy] < 0) {
7446 for (iz2 = 0; iz2 < zm->np; iz2++)
7447 if (zm->vmr[it][iz2][iy] >= 0) {
7448 zm->vmr[it][iz][iy] = zm->vmr[it][iz2][iy];
7449 break;
7450 }
7451 for (iz2 = zm->np - 1; iz2 >= 0; iz2--)
7452 if (zm->vmr[it][iz2][iy] >= 0) {
7453 zm->vmr[it][iz][iy] = zm->vmr[it][iz2][iy];
7454 break;
7455 }
7456 }
7457 varmin = MIN(varmin, zm->vmr[it][iz][iy]);
7458 varmax = MAX(varmax, zm->vmr[it][iz][iy]);
7459 }
7460
7461 /* Close netCDF file... */
7462 NC(nc_close(ncid));
7463
7464 /* Write info... */
7465 LOG(2, "Number of time steps: %d", zm->ntime);
7466 LOG(2, "Time steps: %.2f, %.2f ... %.2f s",
7467 zm->time[0], zm->time[1], zm->time[zm->ntime - 1]);
7468 LOG(2, "Number of pressure levels: %d", zm->np);
7469 LOG(2, "Altitude levels: %g, %g ... %g km",
7470 Z(zm->p[0]), Z(zm->p[1]), Z(zm->p[zm->np - 1]));
7471 LOG(2, "Pressure levels: %g, %g ... %g hPa", zm->p[0],
7472 zm->p[1], zm->p[zm->np - 1]);
7473 LOG(2, "Number of latitudes: %d", zm->nlat);
7474 LOG(2, "Latitudes: %g, %g ... %g deg",
7475 zm->lat[0], zm->lat[1], zm->lat[zm->nlat - 1]);
7476 LOG(2, "%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
7477 varmax);
7478}
#define CY
Maximum number of latitudes for climatological data.
Definition: mptrac.h:338

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

7486 {
7487
7488 /* Write info... */
7489 LOG(1, "Read kernel function: %s", filename);
7490
7491 /* Open file... */
7492 FILE *in;
7493 if (!(in = fopen(filename, "r")))
7494 ERRMSG("Cannot open file!");
7495
7496 /* Read data... */
7497 char line[LEN];
7498 int n = 0;
7499 while (fgets(line, LEN, in))
7500 if (sscanf(line, "%lg %lg", &kz[n], &kw[n]) == 2) {
7501 if (n > 0 && kz[n] < kz[n - 1])
7502 ERRMSG("Height levels must be ascending!");
7503 if ((++n) >= EP)
7504 ERRMSG("Too many height levels!");
7505 }
7506
7507 /* Close file... */
7508 fclose(in);
7509
7510 /* Check number of data points... */
7511 *nk = n;
7512 if (n < 2)
7513 ERRMSG("Not enough height levels!");
7514
7515 /* Normalize kernel function... */
7516 const double kmax = gsl_stats_max(kw, 1, (size_t) n);
7517 for (int iz = 0; iz < n; iz++)
7518 kw[iz] /= kmax;
7519}

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

7526 {
7527
7528 FILE *in;
7529
7530 double r;
7531
7532 int year, mon, day, hour, min, sec;
7533
7534 /* Set timer... */
7535 SELECT_TIMER("READ_MET_BIN", "INPUT", NVTX_READ);
7536
7537 /* Open file... */
7538 if (!(in = fopen(filename, "r"))) {
7539 WARN("Cannot open file!");
7540 return 0;
7541 }
7542
7543 /* Check type of binary data... */
7544 int met_type;
7545 FREAD(&met_type, int,
7546 1,
7547 in);
7548 if (met_type != ctl->met_type)
7549 ERRMSG("Wrong MET_TYPE of binary data!");
7550
7551 /* Check version of binary data... */
7552 int version;
7553 FREAD(&version, int,
7554 1,
7555 in);
7556 if (version != 103)
7557 ERRMSG("Wrong version of binary data!");
7558
7559 /* Read time... */
7560 FREAD(&met->time, double,
7561 1,
7562 in);
7563 jsec2time(met->time, &year, &mon, &day, &hour, &min, &sec, &r);
7564 LOG(2, "Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
7565 met->time, year, mon, day, hour, min);
7566 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
7567 || day < 1 || day > 31 || hour < 0 || hour > 23)
7568 ERRMSG("Error while reading time!");
7569
7570 /* Read dimensions... */
7571 FREAD(&met->nx, int,
7572 1,
7573 in);
7574 LOG(2, "Number of longitudes: %d", met->nx);
7575 if (met->nx < 2 || met->nx > EX)
7576 ERRMSG("Number of longitudes out of range!");
7577
7578 FREAD(&met->ny, int,
7579 1,
7580 in);
7581 LOG(2, "Number of latitudes: %d", met->ny);
7582 if (met->ny < 2 || met->ny > EY)
7583 ERRMSG("Number of latitudes out of range!");
7584
7585 FREAD(&met->np, int,
7586 1,
7587 in);
7588 LOG(2, "Number of levels: %d", met->np);
7589 if (met->np < 2 || met->np > EP)
7590 ERRMSG("Number of levels out of range!");
7591
7592 /* Read grid... */
7593 FREAD(met->lon, double,
7594 (size_t) met->nx,
7595 in);
7596 LOG(2, "Longitudes: %g, %g ... %g deg",
7597 met->lon[0], met->lon[1], met->lon[met->nx - 1]);
7598
7599 FREAD(met->lat, double,
7600 (size_t) met->ny,
7601 in);
7602 LOG(2, "Latitudes: %g, %g ... %g deg",
7603 met->lat[0], met->lat[1], met->lat[met->ny - 1]);
7604
7605 FREAD(met->p, double,
7606 (size_t) met->np,
7607 in);
7608 LOG(2, "Altitude levels: %g, %g ... %g km",
7609 Z(met->p[0]), Z(met->p[1]), Z(met->p[met->np - 1]));
7610 LOG(2, "Pressure levels: %g, %g ... %g hPa",
7611 met->p[0], met->p[1], met->p[met->np - 1]);
7612
7613 /* Read surface data... */
7614 read_met_bin_2d(in, met, met->ps, "PS");
7615 read_met_bin_2d(in, met, met->ts, "TS");
7616 read_met_bin_2d(in, met, met->zs, "ZS");
7617 read_met_bin_2d(in, met, met->us, "US");
7618 read_met_bin_2d(in, met, met->vs, "VS");
7619 read_met_bin_2d(in, met, met->ess, "ESS");
7620 read_met_bin_2d(in, met, met->nss, "NSS");
7621 read_met_bin_2d(in, met, met->shf, "SHF");
7622 read_met_bin_2d(in, met, met->lsm, "LSM");
7623 read_met_bin_2d(in, met, met->sst, "SST");
7624 read_met_bin_2d(in, met, met->pbl, "PBL");
7625 read_met_bin_2d(in, met, met->pt, "PT");
7626 read_met_bin_2d(in, met, met->tt, "TT");
7627 read_met_bin_2d(in, met, met->zt, "ZT");
7628 read_met_bin_2d(in, met, met->h2ot, "H2OT");
7629 read_met_bin_2d(in, met, met->pct, "PCT");
7630 read_met_bin_2d(in, met, met->pcb, "PCB");
7631 read_met_bin_2d(in, met, met->cl, "CL");
7632 read_met_bin_2d(in, met, met->plcl, "PLCL");
7633 read_met_bin_2d(in, met, met->plfc, "PLFC");
7634 read_met_bin_2d(in, met, met->pel, "PEL");
7635 read_met_bin_2d(in, met, met->cape, "CAPE");
7636 read_met_bin_2d(in, met, met->cin, "CIN");
7637 read_met_bin_2d(in, met, met->o3c, "O3C");
7638
7639 /* Read level data... */
7640 read_met_bin_3d(in, ctl, met, met->z, "Z", -1e34f, 1e34f);
7641 read_met_bin_3d(in, ctl, met, met->t, "T", 0, 1e34f);
7642 read_met_bin_3d(in, ctl, met, met->u, "U", -1e34f, 1e34f);
7643 read_met_bin_3d(in, ctl, met, met->v, "V", -1e34f, 1e34f);
7644 read_met_bin_3d(in, ctl, met, met->w, "W", -1e34f, 1e34f);
7645 read_met_bin_3d(in, ctl, met, met->pv, "PV", -1e34f, 1e34f);
7646 read_met_bin_3d(in, ctl, met, met->h2o, "H2O", 0, 1e34f);
7647 read_met_bin_3d(in, ctl, met, met->o3, "O3", 0, 1e34f);
7648 read_met_bin_3d(in, ctl, met, met->lwc, "LWC", 0, 1e34f);
7649 read_met_bin_3d(in, ctl, met, met->rwc, "RWC", 0, 1e34f);
7650 read_met_bin_3d(in, ctl, met, met->iwc, "IWC", 0, 1e34f);
7651 read_met_bin_3d(in, ctl, met, met->swc, "SWC", 0, 1e34f);
7652 read_met_bin_3d(in, ctl, met, met->cc, "CC", 0, 1);
7653
7654 /* Read final flag... */
7655 int final;
7656 FREAD(&final, int,
7657 1,
7658 in);
7659 if (final != 999)
7660 ERRMSG("Error while reading binary data!");
7661
7662 /* Close file... */
7663 fclose(in);
7664
7665 /* Return success... */
7666 return 1;
7667}
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:7671
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:7700
#define EY
Maximum number of latitudes for meteo data.
Definition: mptrac.h:293
float zt[EX][EY]
Tropopause geopotential height [km].
Definition: mptrac.h:3629
float sst[EX][EY]
Sea surface temperature [K].
Definition: mptrac.h:3617
float rwc[EX][EY][EP]
Cloud rain water content [kg/kg].
Definition: mptrac.h:3689
float o3c[EX][EY]
Total column ozone [DU].
Definition: mptrac.h:3659
float cape[EX][EY]
Convective available potential energy [J/kg].
Definition: mptrac.h:3653
float pct[EX][EY]
Cloud top pressure [hPa].
Definition: mptrac.h:3635
float shf[EX][EY]
Surface sensible heat flux [W/m^2].
Definition: mptrac.h:3611
float lwc[EX][EY][EP]
Cloud liquid water content [kg/kg].
Definition: mptrac.h:3686
float us[EX][EY]
Surface zonal wind [m/s].
Definition: mptrac.h:3599
float cc[EX][EY][EP]
Cloud cover [1].
Definition: mptrac.h:3698
float ts[EX][EY]
Surface temperature [K].
Definition: mptrac.h:3593
float ess[EX][EY]
Eastward turbulent surface stress [N/m^2].
Definition: mptrac.h:3605
float pcb[EX][EY]
Cloud bottom pressure [hPa].
Definition: mptrac.h:3638
float pel[EX][EY]
Pressure at equilibrium level (EL) [hPa].
Definition: mptrac.h:3650
float cin[EX][EY]
Convective inhibition [J/kg].
Definition: mptrac.h:3656
float plcl[EX][EY]
Pressure at lifted condensation level (LCL) [hPa].
Definition: mptrac.h:3644
float tt[EX][EY]
Tropopause temperature [K].
Definition: mptrac.h:3626
float pbl[EX][EY]
Boundary layer pressure [hPa].
Definition: mptrac.h:3620
float vs[EX][EY]
Surface meridional wind [m/s].
Definition: mptrac.h:3602
float lsm[EX][EY]
Land-sea mask [1].
Definition: mptrac.h:3614
float iwc[EX][EY][EP]
Cloud ice water content [kg/kg].
Definition: mptrac.h:3692
float h2ot[EX][EY]
Tropopause water vapor volume mixing ratio [ppv].
Definition: mptrac.h:3632
float pv[EX][EY][EP]
Potential vorticity [PVU].
Definition: mptrac.h:3677
float cl[EX][EY]
Total column cloud water [kg/m^2].
Definition: mptrac.h:3641
float nss[EX][EY]
Northward turbulent surface stress [N/m^2].
Definition: mptrac.h:3608
float plfc[EX][EY]
Pressure at level of free convection (LFC) [hPa].
Definition: mptrac.h:3647
float swc[EX][EY][EP]
Cloud snow water content [kg/kg].
Definition: mptrac.h:3695
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 7671 of file mptrac.c.

7675 {
7676
7677 float *help;
7678
7679 /* Allocate... */
7680 ALLOC(help, float,
7681 EX * EY);
7682
7683 /* Read uncompressed... */
7684 LOG(2, "Read 2-D variable: %s (uncompressed)", varname);
7685 FREAD(help, float,
7686 (size_t) (met->nx * met->ny),
7687 in);
7688
7689 /* Copy data... */
7690 for (int ix = 0; ix < met->nx; ix++)
7691 for (int iy = 0; iy < met->ny; iy++)
7692 var[ix][iy] = help[ARRAY_2D(ix, iy, met->ny)];
7693
7694 /* Free... */
7695 free(help);
7696}
#define ARRAY_2D(ix, iy, ny)
Macro for computing the linear index of a 2D array element.
Definition: mptrac.h:439

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

7707 {
7708
7709 float *help;
7710
7711 /* Allocate... */
7712 ALLOC(help, float,
7713 EX * EY * EP);
7714
7715 /* Read uncompressed data... */
7716 if (ctl->met_type == 1) {
7717 LOG(2, "Read 3-D variable: %s (uncompressed)", varname);
7718 FREAD(help, float,
7719 (size_t) (met->nx * met->ny * met->np),
7720 in);
7721 }
7722
7723 /* Read packed data... */
7724 else if (ctl->met_type == 2)
7725 compress_pck(varname, help, (size_t) (met->ny * met->nx),
7726 (size_t) met->np, 1, in);
7727
7728 /* Read ZFP data... */
7729 else if (ctl->met_type == 3) {
7730#ifdef ZFP
7731 int precision;
7732 FREAD(&precision, int,
7733 1,
7734 in);
7735
7736 double tolerance;
7737 FREAD(&tolerance, double,
7738 1,
7739 in);
7740
7741 compress_zfp(varname, help, met->np, met->ny, met->nx, precision,
7742 tolerance, 1, in);
7743#else
7744 ERRMSG("MPTRAC was compiled without ZFP compression!");
7745#endif
7746 }
7747
7748 /* Read zstd data... */
7749 else if (ctl->met_type == 4) {
7750#ifdef ZSTD
7751 compress_zstd(varname, help, (size_t) (met->np * met->ny * met->nx), 1,
7752 ctl->met_zstd_level, in);
7753#else
7754 ERRMSG("MPTRAC was compiled without ZSTD compression!");
7755#endif
7756 }
7757
7758 /* Read cmultiscale data... */
7759 else if (ctl->met_type == 5) {
7760#ifdef CMS
7761 compress_cms(ctl, varname, help, (size_t) met->nx, (size_t) met->ny,
7762 (size_t) met->np, met->p, 1, in);
7763#else
7764 ERRMSG("MPTRAC was compiled without cmultiscale compression!");
7765#endif
7766 }
7767
7768 /* Read SZ3 data... */
7769 else if (ctl->met_type == 7) {
7770#ifdef SZ3
7771 int precision;
7772 FREAD(&precision, int,
7773 1,
7774 in);
7775
7776 double tolerance;
7777 FREAD(&tolerance, double,
7778 1,
7779 in);
7780
7781 compress_sz3(varname, help, met->np, met->ny, met->nx, precision,
7782 tolerance, 1, in);
7783#else
7784 ERRMSG("MPTRAC was compiled without sz3 compression!");
7785#endif
7786 }
7787
7788 /* Copy data... */
7789#pragma omp parallel for default(shared) collapse(2)
7790 for (int ix = 0; ix < met->nx; ix++)
7791 for (int iy = 0; iy < met->ny; iy++)
7792 for (int ip = 0; ip < met->np; ip++) {
7793 var[ix][iy][ip] = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
7794 if (var[ix][iy][ip] < bound_min)
7795 var[ix][iy][ip] = bound_min;
7796 else if (var[ix][iy][ip] > bound_max)
7797 var[ix][iy][ip] = bound_max;
7798 }
7799
7800 /* Free... */
7801 free(help);
7802}
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:679
void compress_zstd(const char *varname, float *array, const size_t n, const int decompress, const int level, FILE *inout)
Compresses or decompresses a float array using Zstandard (ZSTD).
void compress_cms(const ctl_t *ctl, const char *varname, float *array, const size_t nx, const size_t ny, const size_t np, const double *plev, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm.
void compress_zfp(const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using the ZFP library.
void compress_sz3(const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
Compresses or decompresses a 3-D float array using the SZ3 library.
Here is the call graph for this function:

◆ read_met_cape()

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

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

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

Parameters
ctlPointer to the control structure that contains metadata about the type of data and how it is stored.
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 7806 of file mptrac.c.

7809 {
7810
7811 /* Check parameters... */
7812 if (ctl->met_cape != 1)
7813 return;
7814
7815 /* Set timer... */
7816 SELECT_TIMER("READ_MET_CAPE", "METPROC", NVTX_READ);
7817 LOG(2, "Calculate CAPE...");
7818
7819 /* Vertical spacing (about 100 m)... */
7820 const double pfac = 1.01439, dz0 = RI / MA / G0 * log(pfac);
7821
7822 /* Loop over columns... */
7823#pragma omp parallel for default(shared) collapse(2)
7824 for (int ix = 0; ix < met->nx; ix++)
7825 for (int iy = 0; iy < met->ny; iy++) {
7826
7827 /* Get potential temperature and water vapor at lowest 50 hPa... */
7828 int n = 0;
7829 double h2o = 0, t, theta = 0;
7830 double pbot = MIN(met->ps[ix][iy], met->p[0]);
7831 double ptop = pbot - 50.;
7832 for (int ip = 0; ip < met->np; ip++) {
7833 if (met->p[ip] <= pbot) {
7834 theta += THETA(met->p[ip], met->t[ix][iy][ip]);
7835 h2o += met->h2o[ix][iy][ip];
7836 n++;
7837 }
7838 if (met->p[ip] < ptop && n > 0)
7839 break;
7840 }
7841 theta /= n;
7842 h2o /= n;
7843
7844 /* Cannot compute anything if water vapor is missing... */
7845 met->plcl[ix][iy] = NAN;
7846 met->plfc[ix][iy] = NAN;
7847 met->pel[ix][iy] = NAN;
7848 met->cape[ix][iy] = NAN;
7849 met->cin[ix][iy] = NAN;
7850 if (h2o <= 0)
7851 continue;
7852
7853 /* Find lifted condensation level (LCL)... */
7854 ptop = P(20.);
7855 pbot = met->ps[ix][iy];
7856 do {
7857 met->plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
7858 t = theta / pow(1000. / met->plcl[ix][iy], 0.286);
7859 if (RH(met->plcl[ix][iy], t, h2o) > 100.)
7860 ptop = met->plcl[ix][iy];
7861 else
7862 pbot = met->plcl[ix][iy];
7863 } while (pbot - ptop > 0.1);
7864
7865 /* Calculate CIN up to LCL... */
7867 double dcape, dz, h2o_env, t_env;
7868 double p = met->ps[ix][iy];
7869 met->cape[ix][iy] = met->cin[ix][iy] = 0;
7870 do {
7871 dz = dz0 * TVIRT(t, h2o);
7872 p /= pfac;
7873 t = theta / pow(1000. / p, 0.286);
7874 intpol_met_space_3d(met, met->t, p, met->lon[ix], met->lat[iy],
7875 &t_env, ci, cw, 1);
7876 intpol_met_space_3d(met, met->h2o, p, met->lon[ix], met->lat[iy],
7877 &h2o_env, ci, cw, 0);
7878 dcape = 1e3 * G0 * (TVIRT(t, h2o) - TVIRT(t_env, h2o_env)) /
7879 TVIRT(t_env, h2o_env) * dz;
7880 if (dcape < 0)
7881 met->cin[ix][iy] += fabsf((float) dcape);
7882 } while (p > met->plcl[ix][iy]);
7883
7884 /* Calculate level of free convection (LFC), equilibrium level (EL),
7885 and convective available potential energy (CAPE)... */
7886 dcape = 0;
7887 p = met->plcl[ix][iy];
7888 t = theta / pow(1000. / p, 0.286);
7889 ptop = 0.75 * clim_tropo(clim, met->time, met->lat[iy]);
7890 do {
7891 dz = dz0 * TVIRT(t, h2o);
7892 p /= pfac;
7893 t -= lapse_rate(t, h2o) * dz;
7894 double psat = PSAT(t);
7895 h2o = psat / (p - (1. - EPS) * psat);
7896 intpol_met_space_3d(met, met->t, p, met->lon[ix], met->lat[iy],
7897 &t_env, ci, cw, 1);
7898 intpol_met_space_3d(met, met->h2o, p, met->lon[ix], met->lat[iy],
7899 &h2o_env, ci, cw, 0);
7900 double dcape_old = dcape;
7901 dcape = 1e3 * G0 * (TVIRT(t, h2o) - TVIRT(t_env, h2o_env)) /
7902 TVIRT(t_env, h2o_env) * dz;
7903 if (dcape > 0) {
7904 met->cape[ix][iy] += (float) dcape;
7905 if (!isfinite(met->plfc[ix][iy]))
7906 met->plfc[ix][iy] = (float) p;
7907 } else if (dcape_old > 0)
7908 met->pel[ix][iy] = (float) p;
7909 if (dcape < 0 && !isfinite(met->plfc[ix][iy]))
7910 met->cin[ix][iy] += fabsf((float) dcape);
7911 } while (p > ptop);
7912
7913 /* Check results... */
7914 if (!isfinite(met->plfc[ix][iy]))
7915 met->cin[ix][iy] = NAN;
7916 }
7917}
double clim_tropo(const clim_t *clim, const double t, const double lat)
Calculates the tropopause pressure based on climatological data.
Definition: mptrac.c:204
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 7921 of file mptrac.c.

7922 {
7923
7924 /* Set timer... */
7925 SELECT_TIMER("READ_MET_CLOUD", "METPROC", NVTX_READ);
7926 LOG(2, "Calculate cloud data...");
7927
7928 /* Thresholds for cloud detection... */
7929 const double ccmin = 0.01, cwmin = 1e-6;
7930
7931 /* Loop over columns... */
7932#pragma omp parallel for default(shared) collapse(2)
7933 for (int ix = 0; ix < met->nx; ix++)
7934 for (int iy = 0; iy < met->ny; iy++) {
7935
7936 /* Init... */
7937 met->pct[ix][iy] = NAN;
7938 met->pcb[ix][iy] = NAN;
7939 met->cl[ix][iy] = 0;
7940
7941 /* Loop over pressure levels... */
7942 for (int ip = 0; ip < met->np - 1; ip++) {
7943
7944 /* Check pressure... */
7945 if (met->p[ip] > met->ps[ix][iy] || met->p[ip] < P(20.))
7946 continue;
7947
7948 /* Check ice water and liquid water content... */
7949 if (met->cc[ix][iy][ip] > ccmin
7950 && (met->lwc[ix][iy][ip] > cwmin
7951 || met->rwc[ix][iy][ip] > cwmin
7952 || met->iwc[ix][iy][ip] > cwmin
7953 || met->swc[ix][iy][ip] > cwmin)) {
7954
7955 /* Get cloud top pressure ... */
7956 met->pct[ix][iy]
7957 = (float) (0.5 * (met->p[ip] + (float) met->p[ip + 1]));
7958
7959 /* Get cloud bottom pressure ... */
7960 if (!isfinite(met->pcb[ix][iy]))
7961 met->pcb[ix][iy]
7962 = (float) (0.5 * (met->p[ip] + met->p[MAX(ip - 1, 0)]));
7963 }
7964
7965 /* Get cloud water... */
7966 met->cl[ix][iy] += (float)
7967 (0.5 * (met->lwc[ix][iy][ip] + met->lwc[ix][iy][ip + 1]
7968 + met->rwc[ix][iy][ip] + met->rwc[ix][iy][ip + 1]
7969 + met->iwc[ix][iy][ip] + met->iwc[ix][iy][ip + 1]
7970 + met->swc[ix][iy][ip] + met->swc[ix][iy][ip + 1])
7971 * 100. * (met->p[ip] - met->p[ip + 1]) / G0);
7972 }
7973 }
7974}

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

7980 {
7981
7982 met_t *help;
7983
7984 /* Check parameters... */
7985 if (ctl->met_detrend <= 0)
7986 return;
7987
7988 /* Set timer... */
7989 SELECT_TIMER("READ_MET_DETREND", "METPROC", NVTX_READ);
7990 LOG(2, "Detrend meteo data...");
7991
7992 /* Allocate... */
7993 ALLOC(help, met_t, 1);
7994
7995 /* Calculate standard deviation... */
7996 const double sigma = ctl->met_detrend / 2.355;
7997 const double tssq = 2. * SQR(sigma);
7998
7999 /* Calculate box size in latitude... */
8000 int sy = (int) (3. * DY2DEG(sigma) / fabs(met->lat[1] - met->lat[0]));
8001 sy = MIN(MAX(1, sy), met->ny / 2);
8002
8003 /* Calculate background... */
8004#pragma omp parallel for default(shared) collapse(2)
8005 for (int ix = 0; ix < met->nx; ix++) {
8006 for (int iy = 0; iy < met->ny; iy++) {
8007
8008 /* Calculate Cartesian coordinates... */
8009 double x0[3];
8010 geo2cart(0.0, met->lon[ix], met->lat[iy], x0);
8011
8012 /* Calculate box size in longitude... */
8013 int sx =
8014 (int) (3. * DX2DEG(sigma, met->lat[iy]) /
8015 fabs(met->lon[1] - met->lon[0]));
8016 sx = MIN(MAX(1, sx), met->nx / 2);
8017
8018 /* Init... */
8019 float wsum = 0;
8020 for (int ip = 0; ip < met->np; ip++) {
8021 help->t[ix][iy][ip] = 0;
8022 help->u[ix][iy][ip] = 0;
8023 help->v[ix][iy][ip] = 0;
8024 help->w[ix][iy][ip] = 0;
8025 }
8026
8027 /* Loop over neighboring grid points... */
8028 for (int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
8029 int ix3 = ix2;
8030 if (ix3 < 0)
8031 ix3 += met->nx;
8032 else if (ix3 >= met->nx)
8033 ix3 -= met->nx;
8034 for (int iy2 = MAX(iy - sy, 0);
8035 iy2 <= MIN(iy + sy, met->ny - 1); iy2++) {
8036
8037 /* Calculate Cartesian coordinates... */
8038 double x1[3];
8039 geo2cart(0.0, met->lon[ix3], met->lat[iy2], x1);
8040
8041 /* Calculate weighting factor... */
8042 const float w = (float) exp(-DIST2(x0, x1) / tssq);
8043
8044 /* Add data... */
8045 wsum += w;
8046 for (int ip = 0; ip < met->np; ip++) {
8047 help->t[ix][iy][ip] += w * met->t[ix3][iy2][ip];
8048 help->u[ix][iy][ip] += w * met->u[ix3][iy2][ip];
8049 help->v[ix][iy][ip] += w * met->v[ix3][iy2][ip];
8050 help->w[ix][iy][ip] += w * met->w[ix3][iy2][ip];
8051 }
8052 }
8053 }
8054
8055 /* Normalize... */
8056 for (int ip = 0; ip < met->np; ip++) {
8057 help->t[ix][iy][ip] /= wsum;
8058 help->u[ix][iy][ip] /= wsum;
8059 help->v[ix][iy][ip] /= wsum;
8060 help->w[ix][iy][ip] /= wsum;
8061 }
8062 }
8063 }
8064
8065 /* Subtract background... */
8066#pragma omp parallel for default(shared) collapse(3)
8067 for (int ix = 0; ix < met->nx; ix++)
8068 for (int iy = 0; iy < met->ny; iy++)
8069 for (int ip = 0; ip < met->np; ip++) {
8070 met->t[ix][iy][ip] -= help->t[ix][iy][ip];
8071 met->u[ix][iy][ip] -= help->u[ix][iy][ip];
8072 met->v[ix][iy][ip] -= help->v[ix][iy][ip];
8073 met->w[ix][iy][ip] -= help->w[ix][iy][ip];
8074 }
8075
8076 /* Free... */
8077 free(help);
8078}
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:1962
#define DIST2(a, b)
Calculate the squared Euclidean distance between two points in Cartesian coordinates.
Definition: mptrac.h:683
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 8082 of file mptrac.c.

8083 {
8084
8085 /* Set timer... */
8086 SELECT_TIMER("READ_MET_EXTRAPOLATE", "METPROC", NVTX_READ);
8087 LOG(2, "Extrapolate meteo data...");
8088
8089 /* Loop over columns... */
8090#pragma omp parallel for default(shared) collapse(2)
8091 for (int ix = 0; ix < met->nx; ix++)
8092 for (int iy = 0; iy < met->ny; iy++) {
8093
8094 /* Find lowest valid data point... */
8095 int ip0;
8096 for (ip0 = met->np - 1; ip0 >= 0; ip0--)
8097 if (!isfinite(met->t[ix][iy][ip0])
8098 || !isfinite(met->u[ix][iy][ip0])
8099 || !isfinite(met->v[ix][iy][ip0])
8100 || !isfinite(met->w[ix][iy][ip0]))
8101 break;
8102
8103 /* Extrapolate... */
8104 for (int ip = ip0; ip >= 0; ip--) {
8105 met->t[ix][iy][ip] = met->t[ix][iy][ip + 1];
8106 met->u[ix][iy][ip] = met->u[ix][iy][ip + 1];
8107 met->v[ix][iy][ip] = met->v[ix][iy][ip + 1];
8108 met->w[ix][iy][ip] = met->w[ix][iy][ip + 1];
8109 met->h2o[ix][iy][ip] = met->h2o[ix][iy][ip + 1];
8110 met->o3[ix][iy][ip] = met->o3[ix][iy][ip + 1];
8111 met->lwc[ix][iy][ip] = met->lwc[ix][iy][ip + 1];
8112 met->rwc[ix][iy][ip] = met->rwc[ix][iy][ip + 1];
8113 met->iwc[ix][iy][ip] = met->iwc[ix][iy][ip + 1];
8114 met->swc[ix][iy][ip] = met->swc[ix][iy][ip + 1];
8115 met->cc[ix][iy][ip] = met->cc[ix][iy][ip + 1];
8116 }
8117 }
8118}

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

8124 {
8125
8126 float *help;
8127
8128 double logp[EP];
8129
8130 int dx = ctl->met_geopot_sx, dy = ctl->met_geopot_sy;
8131
8132 /* Set timer... */
8133 SELECT_TIMER("READ_MET_GEOPOT", "METPROC", NVTX_READ);
8134 LOG(2, "Calculate geopotential heights...");
8135
8136 /* Allocate... */
8137 ALLOC(help, float,
8138 EX * EY * EP);
8139
8140 /* Calculate log pressure... */
8141#pragma omp parallel for default(shared)
8142 for (int ip = 0; ip < met->np; ip++)
8143 logp[ip] = log(met->p[ip]);
8144
8145 /* Apply hydrostatic equation to calculate geopotential heights... */
8146#pragma omp parallel for default(shared) collapse(2)
8147 for (int ix = 0; ix < met->nx; ix++)
8148 for (int iy = 0; iy < met->ny; iy++) {
8149
8150 /* Get surface height and pressure... */
8151 const double zs = met->zs[ix][iy];
8152 const double lnps = log(met->ps[ix][iy]);
8153
8154 /* Get temperature and water vapor at the surface... */
8155 const int ip0 = locate_irr(met->p, met->np, met->ps[ix][iy]);
8156 const double ts = LIN(met->p[ip0], met->t[ix][iy][ip0], met->p[ip0 + 1],
8157 met->t[ix][iy][ip0 + 1], met->ps[ix][iy]);
8158 const double h2os =
8159 LIN(met->p[ip0], met->h2o[ix][iy][ip0], met->p[ip0 + 1],
8160 met->h2o[ix][iy][ip0 + 1], met->ps[ix][iy]);
8161
8162 /* Upper part of profile... */
8163 met->z[ix][iy][ip0 + 1]
8164 = (float) (zs +
8165 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
8166 met->t[ix][iy][ip0 + 1], met->h2o[ix][iy][ip0 + 1]));
8167 for (int ip = ip0 + 2; ip < met->np; ip++)
8168 met->z[ix][iy][ip]
8169 = (float) (met->z[ix][iy][ip - 1] +
8170 ZDIFF(logp[ip - 1], met->t[ix][iy][ip - 1],
8171 met->h2o[ix][iy][ip - 1], logp[ip],
8172 met->t[ix][iy][ip], met->h2o[ix][iy][ip]));
8173
8174 /* Lower part of profile... */
8175 met->z[ix][iy][ip0]
8176 = (float) (zs +
8177 ZDIFF(lnps, ts, h2os, logp[ip0],
8178 met->t[ix][iy][ip0], met->h2o[ix][iy][ip0]));
8179 for (int ip = ip0 - 1; ip >= 0; ip--)
8180 met->z[ix][iy][ip]
8181 = (float) (met->z[ix][iy][ip + 1] +
8182 ZDIFF(logp[ip + 1], met->t[ix][iy][ip + 1],
8183 met->h2o[ix][iy][ip + 1], logp[ip],
8184 met->t[ix][iy][ip], met->h2o[ix][iy][ip]));
8185 }
8186
8187 /* Check control parameters... */
8188 if (dx == 0 || dy == 0)
8189 return;
8190
8191 /* Default smoothing parameters... */
8192 if (dx < 0 || dy < 0) {
8193 if (fabs(met->lon[1] - met->lon[0]) < 0.5) {
8194 dx = 3;
8195 dy = 2;
8196 } else {
8197 dx = 6;
8198 dy = 4;
8199 }
8200 }
8201
8202 /* Calculate weights for smoothing... */
8203 float ws[dx + 1][dy + 1];
8204#pragma omp parallel for default(shared) collapse(2)
8205 for (int ix = 0; ix <= dx; ix++)
8206 for (int iy = 0; iy < dy; iy++)
8207 ws[ix][iy] = (1.0f - (float) ix / (float) dx)
8208 * (1.0f - (float) iy / (float) dy);
8209
8210 /* Copy data... */
8211#pragma omp parallel for default(shared) collapse(3)
8212 for (int ix = 0; ix < met->nx; ix++)
8213 for (int iy = 0; iy < met->ny; iy++)
8214 for (int ip = 0; ip < met->np; ip++)
8215 help[ARRAY_3D(ip, ix, met->nx, iy, met->ny)] = met->z[ix][iy][ip];
8216
8217 /* Horizontal smoothing... */
8218#pragma omp parallel for default(shared) collapse(3)
8219 for (int ip = 0; ip < met->np; ip++)
8220 for (int ix = 0; ix < met->nx; ix++)
8221 for (int iy = 0; iy < met->ny; iy++) {
8222 float res = 0, wsum = 0;
8223 int iy0 = MAX(iy - dy + 1, 0);
8224 int iy1 = MIN(iy + dy - 1, met->ny - 1);
8225 for (int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
8226 int ix3 = ix2;
8227 if (ix3 < 0)
8228 ix3 += met->nx;
8229 else if (ix3 >= met->nx)
8230 ix3 -= met->nx;
8231 for (int iy2 = iy0; iy2 <= iy1; ++iy2)
8232 if (isfinite(help[ARRAY_3D(ip, ix3, met->nx, iy2, met->ny)])) {
8233 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
8234 res += w * help[ARRAY_3D(ip, ix3, met->nx, iy2, met->ny)];
8235 wsum += w;
8236 }
8237 }
8238 if (wsum > 0)
8239 met->z[ix][iy][ip] = res / wsum;
8240 else
8241 met->z[ix][iy][ip] = NAN;
8242 }
8243
8244 /* Free... */
8245 free(help);
8246}
#define ZDIFF(lnp0, t0, h2o0, lnp1, t1, h2o1)
Calculate geopotential height difference.
Definition: mptrac.h:1911
Here is the call graph for this function:

◆ read_met_grib()

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

Reads meteorological data from a grib file and processes it.

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

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

◆ read_met_grib_grid()

void read_met_grib_grid ( codes_handle **  handles,
int  count_handles,
met_t met 
)

Reads global meteorological information from a grib file.

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

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

The function performs the following steps:

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

◆ read_met_grib_levels()

void read_met_grib_levels ( codes_handle **  handles,
const int  num_messages,
const ctl_t ctl,
met_t met 
)

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

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

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

The function performs the following steps:

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

◆ read_met_grib_surface()

void read_met_grib_surface ( codes_handle **  handles,
const int  num_messages,
const ctl_t ctl,
met_t met 
)

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

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

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

The function performs the following steps:

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

◆ read_met_ml2pl()

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

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

9710 {
9711
9712 double aux[EP], p[EP];
9713
9714 /* Set timer... */
9715 SELECT_TIMER("READ_MET_ML2PL", "METPROC", NVTX_READ);
9716 LOG(2, "Interpolate meteo data to pressure levels: %s", varname);
9717
9718 /* Loop over columns... */
9719#pragma omp parallel for default(shared) private(aux,p) collapse(2)
9720 for (int ix = 0; ix < met->nx; ix++)
9721 for (int iy = 0; iy < met->ny; iy++) {
9722
9723 /* Copy pressure profile... */
9724 for (int ip = 0; ip < met->np; ip++)
9725 p[ip] = met->pl[ix][iy][ip];
9726
9727 /* Interpolate... */
9728 for (int ip = 0; ip < ctl->met_np; ip++) {
9729 double pt = ctl->met_p[ip];
9730 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
9731 pt = p[0];
9732 else if ((pt > p[met->np - 1] && p[1] > p[0])
9733 || (pt < p[met->np - 1] && p[1] < p[0]))
9734 pt = p[met->np - 1];
9735 const int ip2 = locate_irr(p, met->np, pt);
9736 aux[ip] = LIN(p[ip2], var[ix][iy][ip2],
9737 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
9738 }
9739
9740 /* Copy data... */
9741 for (int ip = 0; ip < ctl->met_np; ip++)
9742 var[ix][iy][ip] = (float) aux[ip];
9743 }
9744}
Here is the call graph for this function:

◆ read_met_monotonize()

void read_met_monotonize ( const ctl_t ctl,
met_t met 
)

Makes zeta and pressure profiles monotone.

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

Parameters
ctlA pointer to a control parameter structure.
metA pointer to a structure containing meteorological data.

The function performs the following steps:

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

Definition at line 9748 of file mptrac.c.

9750 {
9751
9752 /* Check parameters... */
9753 if (ctl->advect_vert_coord != 1)
9754 return;
9755
9756 /* Set timer... */
9757 SELECT_TIMER("READ_MET_MONOTONIZE", "METPROC", NVTX_READ);
9758 LOG(2, "Make zeta profiles monotone...");
9759
9760 /* Create monotone zeta profiles... */
9761#pragma omp parallel for default(shared) collapse(2)
9762 for (int i = 0; i < met->nx; i++)
9763 for (int j = 0; j < met->ny; j++) {
9764 int k = 1;
9765
9766 while (k < met->npl) { /* Check if there is an inversion at level k... */
9767 if ((met->zetal[i][j][k - 1] >= met->zetal[i][j][k])) {
9768 /* Find the upper level k+l over the inversion... */
9769 int l = 0;
9770 do {
9771 l++;
9772 }
9773 while ((met->zetal[i][j][k - 1] >=
9774 met->zetal[i][j][k + l]) & (k + l < met->npl));
9775
9776 /* Interpolate linear between the top and bottom
9777 of the inversion... */
9778 float s =
9779 (float) (met->zetal[i][j][k + l] - met->zetal[i][j][k - 1])
9780 / (float) (met->hybrid[k + l] - met->hybrid[k - 1]);
9781
9782 for (int m = k; m < k + l; m++) {
9783 float d = (float) (met->hybrid[m] - met->hybrid[k - 1]);
9784 met->zetal[i][j][m] = s * d + met->zetal[i][j][k - 1];
9785 }
9786
9787 /* Search for more inversions above the last inversion ... */
9788 k = k + l;
9789 } else {
9790 k++;
9791 }
9792 }
9793 }
9794
9795 /* Create monotone pressure profiles... */
9796#pragma omp parallel for default(shared) collapse(2)
9797 for (int i = 0; i < met->nx; i++)
9798 for (int j = 0; j < met->ny; j++) {
9799 int k = 1;
9800
9801 while (k < met->npl) { /* Check if there is an inversion at level k... */
9802 if ((met->pl[i][j][k - 1] <= met->pl[i][j][k])) {
9803
9804 /* Find the upper level k+l over the inversion... */
9805 int l = 0;
9806 do {
9807 l++;
9808 }
9809 while ((met->pl[i][j][k - 1] <= met->pl[i][j][k + l]) & (k + l <
9810 met->npl));
9811
9812 /* Interpolate linear between the top and bottom
9813 of the inversion... */
9814 float s = (float) (met->pl[i][j][k + l] - met->pl[i][j][k - 1])
9815 / (float) (met->hybrid[k + l] - met->hybrid[k - 1]);
9816
9817 for (int m = k; m < k + l; m++) {
9818 float d = (float) (met->hybrid[m] - met->hybrid[k - 1]);
9819 met->pl[i][j][m] = s * d + met->pl[i][j][k - 1];
9820 }
9821
9822 /* Search for more inversions above the last inversion ... */
9823 k += l;
9824 } else {
9825 k++;
9826 }
9827 }
9828 }
9829}
double hybrid[EP]
Model hybrid levels.
Definition: mptrac.h:3578

◆ read_met_nc()

int read_met_nc ( const char *  filename,
const ctl_t ctl,
met_t met,
dd_t dd 
)

Reads meteorological data from a NetCDF file and processes it.

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

Parameters
filenameA constant character pointer representing the name of the NetCDF file to read the meteorological data from.
ctlA pointer to a ctl_t structure, which contains control parameters for reading and processing the meteorological data.
metA pointer to a met_t structure that will store the meteorological data read and processed from the NetCDF file.
ddA pointer to an dd_t structure containing MPI information, including rank and neighbours.
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 9833 of file mptrac.c.

9837 {
9838
9839 int ncid;
9840
9841 /* Open file... */
9842#ifdef DD
9843 if (ctl->dd) {
9844 NC(nc_open_par
9845 (filename, NC_NOWRITE | NC_SHARE, MPI_COMM_WORLD, MPI_INFO_NULL,
9846 &ncid))
9847 }
9848#else
9849 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
9850 WARN("Cannot open file!");
9851 return 0;
9852 }
9853#endif
9854
9855 /* Read coordinates of meteo data... */
9856 read_met_nc_grid(filename, ncid, ctl, met, dd);
9857
9858 /* Read surface data... */
9859 read_met_nc_surface(ncid, ctl, met, dd);
9860
9861 /* Read meteo data on vertical levels... */
9862 read_met_nc_levels(ncid, ctl, met, dd);
9863
9864 /* Close file... */
9865 NC(nc_close(ncid));
9866
9867 /* Return success... */
9868 return 1;
9869}
void read_met_nc_levels(const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads and processes meteorological level data from NetCDF files with domain decomposition.
Definition: mptrac.c:8555
void read_met_nc_surface(const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads and processes surface meteorological data from NetCDF files with domain decomposition.
Definition: mptrac.c:8417
void read_met_nc_grid(const char *filename, const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads meteorological grid data from NetCDF files with domain decomposition.
Definition: mptrac.c:8250
Here is the call graph for this function:

◆ read_met_nc_grid()

void read_met_nc_grid ( const char *  filename,
const int  ncid,
const ctl_t ctl,
met_t met,
dd_t dd 
)

Reads meteorological grid data from NetCDF files with domain decomposition.

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

Parameters
filenameA string representing the filename of the NetCDF file to read.
ncidA NetCDF file ID.
ctlA pointer to a ctl_t structure containing control parameters.
metA pointer to a met_t structure where meteorological data will be stored.
ddA pointer to an dd_t structure containing MPI information, including rank and neighbours.

The function performs the following steps:

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

Definition at line 8250 of file mptrac.c.

8255 {
8256
8257 char levname[LEN], tstr[10];
8258
8259 double rtime = 0, r, r2;
8260
8261 int varid, ndims, dimids[NC_MAX_DIMS], year2, mon2, day2, hour2, min2, sec2,
8262 year, mon, day, hour, min, sec;
8263
8264 size_t dimlen;
8265
8266 /* Set timer... */
8267 SELECT_TIMER("READ_MET_NC_GRID", "INPUT", NVTX_READ);
8268 LOG(2, "Read meteo grid information...");
8269
8270 /* MPTRAC meteo files... */
8271 if (!ctl->met_clams) {
8272
8273 /* Get time from filename... */
8274 met->time = time_from_filename(filename, 16);
8275
8276 /* Check time information from data file... */
8277 jsec2time(met->time, &year, &mon, &day, &hour, &min, &sec, &r);
8278 if (nc_inq_varid(ncid, "time", &varid) == NC_NOERR) {
8279 NC(nc_get_var_double(ncid, varid, &rtime));
8280 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
8281 WARN("Time information in meteo file does not match filename!");
8282 } else
8283 WARN("Time information in meteo file is missing!");
8284 }
8285
8286 /* CLaMS meteo files... */
8287 else {
8288
8289 /* Read time from file... */
8290 NC_GET_DOUBLE("time", &rtime, 0);
8291
8292 /* Get time from filename (considering the century)... */
8293 if (rtime < 0)
8294 sprintf(tstr, "19%.2s", &filename[strlen(filename) - 11]);
8295 else
8296 sprintf(tstr, "20%.2s", &filename[strlen(filename) - 11]);
8297 year = atoi(tstr);
8298 sprintf(tstr, "%.2s", &filename[strlen(filename) - 9]);
8299 mon = atoi(tstr);
8300 sprintf(tstr, "%.2s", &filename[strlen(filename) - 7]);
8301 day = atoi(tstr);
8302 sprintf(tstr, "%.2s", &filename[strlen(filename) - 5]);
8303 hour = atoi(tstr);
8304 time2jsec(year, mon, day, hour, 0, 0, 0, &met->time);
8305 }
8306
8307 /* Check time... */
8308 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
8309 || day < 1 || day > 31 || hour < 0 || hour > 23)
8310 ERRMSG("Cannot read time from filename!");
8311 jsec2time(met->time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
8312 LOG(2, "Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
8313 met->time, year2, mon2, day2, hour2, min2);
8314
8315 /* Get vertical dimension... */
8316 if (nc_inq_varid(ncid, "u", &varid) != NC_NOERR)
8317 if (nc_inq_varid(ncid, "U", &varid) != NC_NOERR)
8318 ERRMSG
8319 ("Variable 'u' or 'U' not found, cannot determine vertical dimension!");
8320
8321 NC(nc_inq_varndims(ncid, varid, &ndims));
8322 NC(nc_inq_vardimid(ncid, varid, dimids));
8323
8324 if (ndims == 4) {
8325 NC(nc_inq_dim
8326 (ncid, dimids[ctl->met_convention == 0 ? 1 : 3], levname, &dimlen));
8327 } else if (ndims == 3) {
8328 NC(nc_inq_dim
8329 (ncid, dimids[ctl->met_convention == 0 ? 0 : 2], levname, &dimlen));
8330 } else
8331 ERRMSG("Cannot determine vertical dimension!")
8332 met->np = (int) dimlen;
8333
8334 LOG(2, "Number of levels: %d", met->np);
8335 if (met->np < 2 || met->np > EP)
8336 ERRMSG("Number of levels out of range!");
8337
8338 if (!ctl->dd) {
8339
8340 /* Get grid dimensions... */
8341 NC_INQ_DIM("lon", &met->nx, 2, EX, 1);
8342 LOG(2, "Number of longitudes: %d", met->nx);
8343
8344 NC_INQ_DIM("lat", &met->ny, 2, EY, 1);
8345 LOG(2, "Number of latitudes: %d", met->ny);
8346
8347 /* Read longitudes and latitudes... */
8348 NC_GET_DOUBLE("lon", met->lon, 1);
8349 LOG(2, "Longitudes: %g, %g ... %g deg",
8350 met->lon[0], met->lon[1], met->lon[met->nx - 1]);
8351 NC_GET_DOUBLE("lat", met->lat, 1);
8352 LOG(2, "Latitudes: %g, %g ... %g deg",
8353 met->lat[0], met->lat[1], met->lat[met->ny - 1]);
8354
8355 } else {
8356
8357 /* Use 'naive', i.e. equidistant lat-lon domain decomposition... */
8358 read_met_nc_grid_dd_naive(dd, ctl, met, ncid);
8359
8360 }
8361
8362 /* Read pressure levels... */
8363 if (ctl->met_np <= 0) {
8364 NC_GET_DOUBLE(levname, met->p, 1);
8365 for (int ip = 0; ip < met->np; ip++)
8366 met->p[ip] /= 100.;
8367 LOG(2, "Altitude levels: %g, %g ... %g km",
8368 Z(met->p[0]), Z(met->p[1]), Z(met->p[met->np - 1]));
8369 LOG(2, "Pressure levels: %g, %g ... %g hPa",
8370 met->p[0], met->p[1], met->p[met->np - 1]);
8371 }
8372
8373 /* Read hybrid levels... */
8374 if (strcasecmp(levname, "hybrid") == 0)
8375 NC_GET_DOUBLE("hybrid", met->hybrid, 1);
8376
8377 /* Read model level coefficients from file... */
8378 if (ctl->met_vert_coord == 2) {
8379 NC_GET_DOUBLE("hyam", met->hyam, 1);
8380 NC_GET_DOUBLE("hybm", met->hybm, 1);
8381 }
8382
8383 /* Copy model level coefficients from control parameters... */
8384 else if (ctl->met_vert_coord == 3 || ctl->met_vert_coord == 4) {
8385 if (ctl->met_nlev <= 0)
8386 ERRMSG("You need to specify MET_NLEV, MET_LEV_HYAM, and MET_LEV_HYBM!");
8387 for (int ip = 0; ip < ctl->met_nlev; ip++) {
8388 met->hyam[ip] = ctl->met_lev_hyam[ip];
8389 met->hybm[ip] = ctl->met_lev_hybm[ip];
8390 }
8391 }
8392
8393 /* Calculate eta levels... */
8394 for (int k = 0; k < MAX(met->np, ctl->met_nlev); ++k) {
8395 met->eta[k] = met->hyam[k] / 100000.0 + met->hybm[k];
8396 if (ctl->met_vert_coord >= 2 && k > 0 && met->eta[k] <= met->eta[k - 1])
8397 ERRMSG("Eta levels must be ascending!");
8398 }
8399
8400 /* Check horizontal grid spacing... */
8401 for (int ix = 2; ix < met->nx; ix++)
8402 if (fabs
8403 (fabs(met->lon[ix] - met->lon[ix - 1]) -
8404 fabs(met->lon[1] - met->lon[0])) > 0.001)
8405 ERRMSG("No regular grid spacing in longitudes!");
8406 for (int iy = 2; iy < met->ny; iy++)
8407 if (fabs
8408 (fabs(met->lat[iy] - met->lat[iy - 1]) -
8409 fabs(met->lat[1] - met->lat[0])) > 0.001) {
8410 WARN("No regular grid spacing in latitudes!");
8411 break;
8412 }
8413}
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:11124
void read_met_nc_grid_dd_naive(dd_t *dd, const ctl_t *ctl, met_t *met, const int ncid)
Read meteorological grid data from a NetCDF file and set up subdomain decomposition with halos.
Definition: mptrac.c:9873
double time_from_filename(const char *filename, const int offset)
Extracts and converts a timestamp from a filename to Julian seconds.
Definition: mptrac.c:11223
double eta[EP]
Model level eta values.
Definition: mptrac.h:3587
double hyam[EP]
Model level a coefficients [Pa].
Definition: mptrac.h:3581
double hybm[EP]
Model level b coefficients.
Definition: mptrac.h:3584
Here is the call graph for this function:

◆ read_met_nc_grid_dd_naive()

void read_met_nc_grid_dd_naive ( dd_t dd,
const ctl_t ctl,
met_t met,
const int  ncid 
)

Read meteorological grid data from a NetCDF file and set up subdomain decomposition with halos.

This function initializes the distributed grid decomposition for meteorological data stored in a NetCDF file. It queries global grid dimensions (longitude, latitude), determines the local subdomain size for each MPI rank, and sets up hyperslabs for reading data in parallel. It also constructs halo regions for subdomain boundaries, ensuring periodic wrap-around in the zonal direction when applicable.

The function adjusts subdomain sizes at the right and bottom edges of the global grid to exactly fit the full domain. It then updates the met_t structure with the local longitude and latitude arrays for the subdomain including halos, and stores decomposition metadata in the dd_t structure.

Parameters
[out]ddPointer to a dd_t structure. On output, it contains:
  • MPI rank and size
  • subdomain start indices and counts
  • halo start indices and counts
  • subdomain longitude and latitude ranges
  • halo offsets
[in]ctlPointer to a ctl_t structure containing decomposition parameters:
  • ctl->dd_subdomains_zonal
  • ctl->dd_subdomains_meridional
  • ctl->dd_halos_size
[out]metPointer to a met_t structure. On output, it contains:
  • subdomain grid dimensions (nx, ny, np)
  • longitude and latitude arrays restricted to the subdomain including halos.
[in]ncidNetCDF file ID obtained from a call to nc_open.
Note
  • Requires MPI if compiled with -DMPI.
  • Assumes latitude is ordered from 90 to -90 (descending). A warning is issued if latitude range is positive.
  • Allocates and frees temporary arrays for global longitude and latitude.
  • Halo setup ensures overlap with neighboring subdomains, and handles wrap-around at the left and right boundaries.
  • For periodic grids, the longitude range is assumed to be 360°.
Author
Jan Clemens

Definition at line 9873 of file mptrac.c.

9877 {
9878
9879 int varid;
9880
9881 /* Get the MPI information... */
9882#ifdef MPI
9883 MPI_Comm_rank(MPI_COMM_WORLD, &dd->rank);
9884 MPI_Comm_size(MPI_COMM_WORLD, &dd->size);
9885#endif
9886
9887 int help_nx_glob;
9888 int help_ny_glob;
9889
9890 /* Get grid dimensions... */
9891 NC_INQ_DIM("lon", &help_nx_glob, 0, 0, 0);
9892 LOG(2, "Number of longitudes: %d", help_nx_glob);
9893 met->nx = (int) floor(help_nx_glob / ctl->dd_subdomains_zonal);
9894
9895 NC_INQ_DIM("lat", &help_ny_glob, 0, 0, 0);
9896 LOG(2, "Number of latitudes: %d", help_ny_glob);
9897 met->ny = (int) floor(help_ny_glob / ctl->dd_subdomains_meridional);
9898
9899 double *help_lon_glob;
9900 double *help_lat_glob;
9901 ALLOC(help_lon_glob, double,
9902 help_nx_glob);
9903 ALLOC(help_lat_glob, double,
9904 help_ny_glob);
9905
9906 /* Read global longitudes and latitudes... */
9907 NC_GET_DOUBLE("lon", help_lon_glob, 1);
9908 LOG(2, "Longitudes: %g, %g ... %g deg",
9909 help_lon_glob[0], help_lon_glob[1], help_lon_glob[help_nx_glob - 1]);
9910 NC_GET_DOUBLE("lat", help_lat_glob, 1);
9911 LOG(2, "Latitudes: %g, %g ... %g deg",
9912 help_lat_glob[0], help_lat_glob[1], help_lat_glob[help_ny_glob - 1]);
9913
9914 /* Determine hyperslabs for reading the data in parallel... */
9915
9916 /* Check for edge cases... */
9917 int left = (dd->rank <= ctl->dd_subdomains_meridional - 1);
9918 int right = (dd->rank >= dd->size - ctl->dd_subdomains_meridional);
9919 int top = (dd->rank % ctl->dd_subdomains_meridional == 0);
9920 int bottom =
9921 (dd->rank % ctl->dd_subdomains_meridional ==
9922 ctl->dd_subdomains_meridional - 1);
9923
9924 /* Set the hyperslab for the subdomain... */
9925 dd->subdomain_start[0] = 0;
9926 dd->subdomain_start[1] = 0;
9927 dd->subdomain_start[2] =
9928 (size_t) ((dd->rank % ctl->dd_subdomains_meridional) * met->ny);
9929 dd->subdomain_start[3] =
9930 (size_t) (floor(dd->rank / ctl->dd_subdomains_meridional) * met->nx);
9931
9932 /* Extend subdomains at the right and bottom to fit the full domain. */
9933 if (right) {
9934 int gap = help_nx_glob - ctl->dd_subdomains_zonal * met->nx;
9935 if (gap > 0) {
9936 met->nx = met->nx + gap;
9937 WARN("Extended subdomains at the right to fit to full domain.");
9938 }
9939 }
9940 if (bottom) {
9941 int gap = help_ny_glob - ctl->dd_subdomains_meridional * met->ny;
9942 if (gap > 0) {
9943 met->ny = met->ny + gap;
9944 WARN("Extended subdomains at the bottom to fit to full domain.");
9945 }
9946 }
9947
9948 /* Block-size, i.e. count */
9949 dd->subdomain_count[0] = 1;
9950 dd->subdomain_count[1] = (size_t) met->np;
9951 dd->subdomain_count[2] = (size_t) met->ny;
9952 dd->subdomain_count[3] = (size_t) met->nx;
9953
9954 /* Create halos and include them into the subdomain... */
9955 if (!left && !right) {
9956 // If we are not at the left or right edge extend in zonal direction...
9957 // Move the start one point to the left...
9958 dd->subdomain_count[3] =
9959 dd->subdomain_count[3] + (size_t) (ctl->dd_halos_size * 2);
9960 dd->subdomain_start[3] =
9961 dd->subdomain_start[3] - (size_t) ctl->dd_halos_size;
9962 } else {
9963 // If we are at the left or right edge, extend only in one zonal direction...
9964 dd->subdomain_count[3] =
9965 dd->subdomain_count[3] + (size_t) ctl->dd_halos_size;
9966 if (!left)
9967 // If we are not at the left edge, move the start to the left...
9968 dd->subdomain_start[3] =
9969 dd->subdomain_start[3] - (size_t) ctl->dd_halos_size;
9970 }
9971
9972 if (!top && !bottom) {
9973 // If we are not at the upper or lower edge extend in meridional direction...
9974 // Move the start point one point down...
9975 dd->subdomain_count[2] =
9976 dd->subdomain_count[2] + (size_t) (ctl->dd_halos_size * 2);
9977 dd->subdomain_start[2] =
9978 dd->subdomain_start[2] - (size_t) ctl->dd_halos_size;
9979 } else {
9980 // If we are at the top or the lower edge only extend in one mer. direction...
9981 dd->subdomain_count[2] =
9982 dd->subdomain_count[2] + (size_t) ctl->dd_halos_size;
9983 if (!top)
9984 // If we are not at the top, move the start one upward...
9985 dd->subdomain_start[2] =
9986 dd->subdomain_start[2] - (size_t) ctl->dd_halos_size;
9987 }
9988
9989 /* Set boundary halo hyperslabs ... */
9990 double lon_shift = 0;
9991 if (left || right) {
9992
9993 met->nx = met->nx + ctl->dd_halos_size;
9994
9995 dd->halo_bnd_start[0] = 0;
9996 dd->halo_bnd_start[1] = 0;
9997 dd->halo_bnd_start[3] = (size_t) (left ? (help_nx_glob - ctl->dd_halos_size) : (0)); //x
9998 dd->halo_bnd_start[2] = dd->subdomain_start[2]; //y
9999
10000 dd->halo_bnd_count[0] = 1;
10001 dd->halo_bnd_count[1] = (size_t) met->np;
10002 dd->halo_bnd_count[3] = (size_t) ctl->dd_halos_size;
10003 dd->halo_bnd_count[2] =
10004 (size_t) met->ny +
10005 (size_t) ctl->dd_halos_size * ((top || bottom) ? 1 : 2);
10006
10007 dd->halo_offset_start = (left ? (int) dd->halo_bnd_count[3] : 0);
10008 dd->halo_offset_end = (left ? 0 : (int) dd->subdomain_count[3]);
10009 lon_shift = (left ? -360 : 360);
10010
10011 } else {
10012
10013 dd->halo_bnd_start[0] = 0;
10014 dd->halo_bnd_start[1] = 0;
10015 dd->halo_bnd_start[3] = 0;
10016 dd->halo_bnd_start[2] = 0;
10017
10018 dd->halo_bnd_count[0] = 0;
10019 dd->halo_bnd_count[1] = 0;
10020 dd->halo_bnd_count[3] = 0;
10021 dd->halo_bnd_count[2] = 0;
10022 }
10023
10024 /* Get the range of the entire meteodata... */
10025 /* Handle both periodic (global) and non-periodic (regional) longitude grids */
10026 double lon_range = 360;
10027 //if (dd_is_periodic_longitude(met, help_nx_glob)) {
10028 /* For global grids with periodic boundaries, use full 360 degrees */
10029 //lon_range = 360.0;
10030 //LOG(3, "Detected periodic longitude boundaries, using lon_range = 360.0");
10031 //} else {
10032 /* For regional grids, use the actual data range */
10033 //lon_range = help_lon_glob[help_nx_glob - 1] - help_lon_glob[0];
10034 //LOG(3, "Detected non-periodic longitude boundaries, using lon_range = %g", lon_range);
10035 //}
10036
10037 double lat_range = help_lat_glob[help_ny_glob - 1] - help_lat_glob[0];
10038
10039 /* Focus on subdomain latitudes and longitudes... */
10040 for (int iy = 0; iy < (int) dd->subdomain_count[2]; iy++)
10041 met->lat[iy] = help_lat_glob[(int) dd->subdomain_start[2] + iy];
10042
10043 /* Focus on subdomain longitudes... */
10044 /* Keep space at the beginning or end of the array for halo... */
10045 for (int ix = 0; ix < (int) dd->subdomain_count[3]; ix++)
10046 met->lon[ix + dd->halo_offset_start] =
10047 help_lon_glob[(int) dd->subdomain_start[3] + ix];
10048
10049 for (int ix = 0; ix < (int) dd->halo_bnd_count[3]; ix++)
10050 met->lon[ix + dd->halo_offset_end] =
10051 help_lon_glob[(int) dd->halo_bnd_start[3] + ix] + lon_shift;
10052
10053 /* Reset the grid dimensions... */
10054 met->nx = (int) dd->subdomain_count[3] + (int) dd->halo_bnd_count[3];
10055 met->ny = (int) dd->subdomain_count[2];
10056
10057 /* Determine subdomain edges... */
10058 dd->subdomain_lon_min = floor(dd->rank / ctl->dd_subdomains_meridional)
10059 * (lon_range) / (double) ctl->dd_subdomains_zonal;
10060 dd->subdomain_lon_max = dd->subdomain_lon_min
10061 + (lon_range) / (double) ctl->dd_subdomains_zonal;
10062
10063 /* Latitudes in descending order (90 to -90) */
10064 if (lat_range < 0) {
10065 dd->subdomain_lat_max = 90 + (dd->rank % ctl->dd_subdomains_meridional)
10066 * (lat_range) / (double) ctl->dd_subdomains_meridional;
10068 + (lat_range) / (double) ctl->dd_subdomains_meridional;
10069 } else {
10070 WARN
10071 ("lat_range > 0, but is expected to be negative, i.e. latitudes should range from 90 to -90")
10072 dd->subdomain_lat_min = -90 + (dd->rank % ctl->dd_subdomains_meridional)
10073 * (lat_range) / (double) ctl->dd_subdomains_meridional;
10074 dd->subdomain_lat_max = dd->subdomain_lat_min
10075 + (lat_range) / (double) ctl->dd_subdomains_meridional;
10076 }
10077
10078 LOG(2, "Total longitude range: %g deg", lon_range);
10079 LOG(2, "Total latitude range: %g deg", lat_range);
10080
10081 LOG(2, "Define subdomain properties.");
10082 LOG(2, "MPI information: Rank %d, Size %d", dd->rank, dd->size);
10083 LOG(2, "Edge position: l=%d,r=%d,t=%d, b=%d", (int) left, (int) right,
10084 (int) top, (int) bottom);
10085 LOG(2, "Sizes for limits: EX %d EY %d EP %d", EX, EY, EP);
10086 LOG(2, "Total size for subdomain meteo data: nx %d ny %d np %d", met->nx,
10087 met->ny, met->np);
10088 LOG(2, "Hyperslab sizes for boundary halos: nx %d ny %d np %d",
10089 (int) dd->halo_bnd_count[3], (int) dd->halo_bnd_count[2],
10090 (int) dd->halo_bnd_count[1]);
10091 LOG(2, "Hyperslab sizes for subdomain and inner halos: nx %d ny %d np %d",
10092 (int) dd->subdomain_count[3], (int) dd->subdomain_count[2],
10093 (int) dd->subdomain_count[1]);
10094 LOG(2, "Subdomain start: nx %ld ny %ld np %ld", dd->subdomain_start[3],
10095 dd->subdomain_start[2], dd->subdomain_start[1]);
10096 LOG(2, "Boundary halo start: nx %ld ny %ld np %ld", dd->halo_bnd_start[3],
10097 dd->halo_bnd_start[2], dd->halo_bnd_start[1]);
10098 LOG(2, "Offsets: nx %d ny %d", dd->halo_offset_start, dd->halo_offset_end);
10099
10100 LOG(2, " %d Subdomain longitudes: %g, %g ... %g deg (edges: %g to %g)",
10101 dd->rank, met->lon[0], met->lon[1], met->lon[met->nx - 1],
10102 dd->subdomain_lon_min, dd->subdomain_lon_max);
10103 LOG(2, " %d Subdomain latitudes: %g, %g ... %g deg (edges: %g to %g)",
10104 dd->rank, met->lat[0], met->lat[1], met->lat[met->ny - 1],
10105 dd->subdomain_lat_min, dd->subdomain_lat_max);
10106
10107 free(help_lon_glob);
10108 free(help_lat_glob);
10109}
int dd_halos_size
Domain decomposition size of halos given in grid-points.
Definition: mptrac.h:3285
size_t halo_bnd_count[4]
Hyperslab of boundary halos count.
Definition: mptrac.h:3771
int halo_offset_end
Hyperslab of boundary halos count.
Definition: mptrac.h:3777
int rank
Rank of node.
Definition: mptrac.h:3732
size_t halo_bnd_start[4]
Hyperslab of boundary halos start.
Definition: mptrac.h:3768
double subdomain_lat_max
Rectangular grid limit of subdomain.
Definition: mptrac.h:3756
int halo_offset_start
Hyperslab of boundary halos count.
Definition: mptrac.h:3774
size_t subdomain_count[4]
Hyperslab start and count for subdomain.
Definition: mptrac.h:3765
size_t subdomain_start[4]
Hyperslab start and count for subdomain.
Definition: mptrac.h:3762
int size
Size of node.
Definition: mptrac.h:3735
double subdomain_lat_min
Rectangular grid limit of subdomain.
Definition: mptrac.h:3759

◆ read_met_nc_levels()

void read_met_nc_levels ( const int  ncid,
const ctl_t ctl,
met_t met,
dd_t dd 
)

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

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

Parameters
ncidAn integer representing the NetCDF file ID.
ctlA pointer to a ctl_t structure containing control parameters and settings.
metA pointer to a met_t structure where meteorological level data will be stored.
ddA pointer to an dd_t structure containing MPI information, including rank and neighbours.

The function performs the following steps:

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

Definition at line 8555 of file mptrac.c.

8559 {
8560
8561 /* Set timer... */
8562 SELECT_TIMER("READ_MET_NC_LEVELS", "INPUT", NVTX_READ);
8563 LOG(2, "Read level data...");
8564
8565 /* Read temperature... */
8566 if (!read_met_nc_3d
8567 (ncid, "t", "T", "temp", "TEMP", ctl, met, dd, met->t, 1.0))
8568 ERRMSG("Cannot read temperature!");
8569
8570 /* Read horizontal wind and vertical velocity... */
8571 if (!read_met_nc_3d(ncid, "u", "U", NULL, NULL, ctl, met, dd, met->u, 1.0))
8572 ERRMSG("Cannot read zonal wind!");
8573 if (!read_met_nc_3d(ncid, "v", "V", NULL, NULL, ctl, met, dd, met->v, 1.0))
8574 ERRMSG("Cannot read meridional wind!");
8575 if (!read_met_nc_3d
8576 (ncid, "w", "W", "omega", "OMEGA", ctl, met, dd, met->w, 0.01f))
8577 WARN("Cannot read vertical velocity!");
8578
8579 /* Read water vapor... */
8580 if (!ctl->met_relhum) {
8581 if (!read_met_nc_3d
8582 (ncid, "q", "Q", "sh", "SH", ctl, met, dd, met->h2o,
8583 (float) (MA / MH2O)))
8584 WARN("Cannot read specific humidity!");
8585 } else {
8586 if (!read_met_nc_3d
8587 (ncid, "rh", "RH", NULL, NULL, ctl, met, dd, met->h2o, 0.01f))
8588 WARN("Cannot read relative humidity!");
8589#pragma omp parallel for default(shared) collapse(2)
8590 for (int ix = 0; ix < met->nx; ix++)
8591 for (int iy = 0; iy < met->ny; iy++)
8592 for (int ip = 0; ip < met->np; ip++) {
8593 double pw = met->h2o[ix][iy][ip] * PSAT(met->t[ix][iy][ip]);
8594 met->h2o[ix][iy][ip] =
8595 (float) (pw / (met->p[ip] - (1.0 - EPS) * pw));
8596 }
8597 }
8598
8599 /* Read ozone... */
8600 if (!read_met_nc_3d
8601 (ncid, "o3", "O3", NULL, NULL, ctl, met, dd, met->o3,
8602 (float) (MA / MO3)))
8603 WARN("Cannot read ozone data!");
8604
8605 /* Read cloud data... */
8606 if (!read_met_nc_3d
8607 (ncid, "clwc", "CLWC", NULL, NULL, ctl, met, dd, met->lwc, 1.0))
8608 WARN("Cannot read cloud liquid water content!");
8609 if (!read_met_nc_3d
8610 (ncid, "crwc", "CRWC", NULL, NULL, ctl, met, dd, met->rwc, 1.0))
8611 WARN("Cannot read cloud rain water content!");
8612 if (!read_met_nc_3d
8613 (ncid, "ciwc", "CIWC", NULL, NULL, ctl, met, dd, met->iwc, 1.0))
8614 WARN("Cannot read cloud ice water content!");
8615 if (!read_met_nc_3d
8616 (ncid, "cswc", "CSWC", NULL, NULL, ctl, met, dd, met->swc, 1.0))
8617 WARN("Cannot read cloud snow water content!");
8618 if (!read_met_nc_3d
8619 (ncid, "cc", "CC", NULL, NULL, ctl, met, dd, met->cc, 1.0))
8620 WARN("Cannot read cloud cover!");
8621
8622 /* Read zeta and zeta_dot... */
8623 if (ctl->advect_vert_coord == 1) {
8624 if (!read_met_nc_3d
8625 (ncid, "ZETA", "zeta", NULL, NULL, ctl, met, dd, met->zetal, 1.0))
8626 WARN("Cannot read ZETA!");
8627 if (!read_met_nc_3d
8628 (ncid, "ZETA_DOT_TOT", "ZETA_DOT_clr", "zeta_dot_clr",
8629 NULL, ctl, met, dd, met->zeta_dotl, 0.00001157407f))
8630 WARN("Cannot read ZETA_DOT!");
8631 }
8632
8633 /* Read eta and eta_dot... */
8634 else if (ctl->advect_vert_coord == 3) {
8635#pragma omp parallel for default(shared)
8636 for (int ix = 0; ix < met->nx; ix++)
8637 for (int iy = 0; iy < met->ny; iy++)
8638 for (int ip = 0; ip < met->np; ip++)
8639 met->zetal[ix][iy][ip] =
8640 (float) (met->hyam[ip] / 100000.0 + met->hybm[ip]);
8641 if (!read_met_nc_3d
8642 (ncid, "etadot", "ETADOT", NULL, NULL, ctl, met, dd, met->zeta_dotl,
8643 1.0))
8644 WARN("Cannot read eta vertical velocity!");
8645 }
8646
8647 /* Store velocities on model levels... */
8648 if (ctl->met_vert_coord != 0) {
8649#pragma omp parallel for default(shared)
8650 for (int ix = 0; ix < met->nx; ix++)
8651 for (int iy = 0; iy < met->ny; iy++)
8652 for (int ip = 0; ip < met->np; ip++) {
8653 met->ul[ix][iy][ip] = met->u[ix][iy][ip];
8654 met->vl[ix][iy][ip] = met->v[ix][iy][ip];
8655 met->wl[ix][iy][ip] = met->w[ix][iy][ip];
8656 }
8657
8658 /* Save number of model levels... */
8659 met->npl = met->np;
8660 }
8661
8662 /* Get pressure on model levels... */
8663 if (ctl->met_np > 0 || ctl->met_vert_coord != 0) {
8664
8665 /* Read 3-D pressure field... */
8666 if (ctl->met_vert_coord == 1) {
8667 if (!read_met_nc_3d
8668 (ncid, "pl", "PL", "pressure", "PRESSURE", ctl, met, dd, met->pl,
8669 0.01f))
8670 if (!read_met_nc_3d
8671 (ncid, "press", "PRESS", NULL, NULL, ctl, met, dd, met->pl, 1.0))
8672 ERRMSG("Cannot read pressure on model levels!");
8673 }
8674
8675 /* Use a and b coefficients for full levels (at layer midpoints)... */
8676 else if (ctl->met_vert_coord == 2 || ctl->met_vert_coord == 3) {
8677
8678 /* Check number of levels... */
8679 if (ctl->met_vert_coord == 3 && met->np != ctl->met_nlev)
8680 ERRMSG("Mismatch in number of model levels!");
8681
8682 /* Calculate pressure... */
8683 for (int ix = 0; ix < met->nx; ix++)
8684 for (int iy = 0; iy < met->ny; iy++)
8685 for (int ip = 0; ip < met->np; ip++)
8686 met->pl[ix][iy][ip] =
8687 (float) (met->hyam[ip] / 100. +
8688 met->hybm[ip] * met->ps[ix][iy]);
8689 }
8690
8691 /* Use a and b coefficients for half levels (at layer interfaces)... */
8692 else if (ctl->met_vert_coord == 4) {
8693
8694 /* Check number of levels... */
8695 if (met->np + 1 != ctl->met_nlev)
8696 ERRMSG("Mismatch in number of model levels!");
8697
8698 /* Calculate pressure... */
8699#pragma omp parallel for default(shared) collapse(2)
8700 for (int ix = 0; ix < met->nx; ix++)
8701 for (int iy = 0; iy < met->ny; iy++)
8702 for (int ip = 0; ip < met->np; ip++) {
8703 const double p0 =
8704 met->hyam[ip] / 100. + met->hybm[ip] * met->ps[ix][iy];
8705 const double p1 =
8706 met->hyam[ip + 1] / 100. + met->hybm[ip + 1] * met->ps[ix][iy];
8707 met->pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
8708 }
8709 }
8710
8711 /* Check ordering of pressure levels... */
8712 for (int ix = 0; ix < met->nx; ix++)
8713 for (int iy = 0; iy < met->ny; iy++)
8714 for (int ip = 1; ip < met->np; ip++)
8715 if ((met->pl[ix][iy][0] > met->pl[ix][iy][1]
8716 && met->pl[ix][iy][ip - 1] <= met->pl[ix][iy][ip])
8717 || (met->pl[ix][iy][0] < met->pl[ix][iy][1]
8718 && met->pl[ix][iy][ip - 1] >= met->pl[ix][iy][ip]))
8719 ERRMSG("Pressure profiles are not monotonic!");
8720 }
8721
8722 /* Interpolate from model levels to pressure levels... */
8723 if (ctl->met_np > 0) {
8724
8725 /* Interpolate variables... */
8726 read_met_ml2pl(ctl, met, met->t, "T");
8727 read_met_ml2pl(ctl, met, met->u, "U");
8728 read_met_ml2pl(ctl, met, met->v, "V");
8729 read_met_ml2pl(ctl, met, met->w, "W");
8730 read_met_ml2pl(ctl, met, met->h2o, "H2O");
8731 read_met_ml2pl(ctl, met, met->o3, "O3");
8732 read_met_ml2pl(ctl, met, met->lwc, "LWC");
8733 read_met_ml2pl(ctl, met, met->rwc, "RWC");
8734 read_met_ml2pl(ctl, met, met->iwc, "IWC");
8735 read_met_ml2pl(ctl, met, met->swc, "SWC");
8736 read_met_ml2pl(ctl, met, met->cc, "CC");
8737
8738 /* Set new pressure levels... */
8739 met->np = ctl->met_np;
8740 for (int ip = 0; ip < met->np; ip++)
8741 met->p[ip] = ctl->met_p[ip];
8742 }
8743
8744 /* Check ordering of pressure levels... */
8745 for (int ip = 1; ip < met->np; ip++)
8746 if (met->p[ip - 1] < met->p[ip])
8747 ERRMSG("Pressure levels must be descending!");
8748}
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, dd_t *dd, float dest[EX][EY][EP], const float scl)
Reads a 3-dimensional meteorological variable from a NetCDF file.
Definition: mptrac.c:9014
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:9706
#define MH2O
Molar mass of water vapor [g/mol].
Definition: mptrac.h:244
#define MO3
Molar mass of ozone [g/mol].
Definition: mptrac.h:249
Here is the call graph for this function:

◆ read_met_nc_surface()

void read_met_nc_surface ( const int  ncid,
const ctl_t ctl,
met_t met,
dd_t dd 
)

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

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

Parameters
ncidAn integer representing the NetCDF file ID.
ctlA pointer to a ctl_t structure containing control parameters and settings.
metA pointer to a met_t structure where surface meteorological data will be stored.
ddA pointer to an dd_t structure containing MPI information, including rank and neighbours.

The function performs the following steps:

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

Definition at line 8417 of file mptrac.c.

8421 {
8422
8423 /* Set timer... */
8424 SELECT_TIMER("READ_MET_SURFACE", "INPUT", NVTX_READ);
8425 LOG(2, "Read surface data...");
8426
8427 /* Read surface pressure... */
8428 if (read_met_nc_2d
8429 (ncid, "lnsp", "LNSP", NULL, NULL, NULL, NULL, ctl, met, dd, met->ps,
8430 1.0f, 1)) {
8431 for (int ix = 0; ix < met->nx; ix++)
8432 for (int iy = 0; iy < met->ny; iy++)
8433 met->ps[ix][iy] = (float) (exp(met->ps[ix][iy]) / 100.);
8434 } else
8435 if (!read_met_nc_2d
8436 (ncid, "ps", "PS", "sp", "SP", NULL, NULL, ctl, met, dd, met->ps,
8437 0.01f, 1)) {
8438 WARN("Cannot not read surface pressure data (use lowest level)!");
8439 for (int ix = 0; ix < met->nx; ix++)
8440 for (int iy = 0; iy < met->ny; iy++)
8441 met->ps[ix][iy]
8442 = (ctl->met_np > 0 ? (float) ctl->met_p[0] : (float) met->p[0]);
8443 }
8444
8445 /* MPTRAC meteo data... */
8446 if (ctl->met_clams == 0) {
8447
8448 /* Read geopotential height at the surface... */
8449 if (!read_met_nc_2d
8450 (ncid, "z", "Z", NULL, NULL, NULL, NULL, ctl, met, dd, met->zs,
8451 (float) (1. / (1000. * G0)), 1))
8452 if (!read_met_nc_2d
8453 (ncid, "zm", "ZM", NULL, NULL, NULL, NULL, ctl, met, dd, met->zs,
8454 (float) (1. / 1000.), 1))
8455 WARN("Cannot read surface geopotential height!");
8456 }
8457
8458 /* CLaMS meteo data... */
8459 else {
8460
8461 /* Read geopotential height at the surface
8462 (use lowermost level of 3-D data field)... */
8463 float *help;
8464 ALLOC(help, float,
8465 EX * EY * EP);
8466 memcpy(help, met->pl, sizeof(met->pl));
8467 if (!read_met_nc_3d
8468 (ncid, "gph", "GPH", NULL, NULL, ctl, met, dd, met->pl,
8469 (float) (1e-3 / G0)))
8470 ERRMSG("Cannot read geopotential height!");
8471 for (int ix = 0; ix < met->nx; ix++)
8472 for (int iy = 0; iy < met->ny; iy++)
8473 met->zs[ix][iy] = met->pl[ix][iy][0];
8474 memcpy(met->pl, help, sizeof(met->pl));
8475 free(help);
8476 }
8477
8478 /* Read temperature at the surface... */
8479 if (!read_met_nc_2d
8480 (ncid, "t2m", "T2M", "2t", "2T", "t2", "T2", ctl, met, dd, met->ts, 1.0,
8481 1))
8482 WARN("Cannot read surface temperature!");
8483
8484 /* Read zonal wind at the surface... */
8485 if (!read_met_nc_2d
8486 (ncid, "u10m", "U10M", "10u", "10U", "u10", "U10", ctl, met, dd,
8487 met->us, 1.0, 1))
8488 WARN("Cannot read surface zonal wind!");
8489
8490 /* Read meridional wind at the surface... */
8491 if (!read_met_nc_2d
8492 (ncid, "v10m", "V10M", "10v", "10V", "v10", "V10", ctl, met, dd,
8493 met->vs, 1.0, 1))
8494 WARN("Cannot read surface meridional wind!");
8495
8496 /* Read eastward turbulent surface stress... */
8497 if (!read_met_nc_2d
8498 (ncid, "iews", "IEWS", NULL, NULL, NULL, NULL, ctl, met, dd, met->ess,
8499 1.0, 1))
8500 WARN("Cannot read eastward turbulent surface stress!");
8501
8502 /* Read northward turbulent surface stress... */
8503 if (!read_met_nc_2d
8504 (ncid, "inss", "INSS", NULL, NULL, NULL, NULL, ctl, met, dd, met->nss,
8505 1.0, 1))
8506 WARN("Cannot read nothward turbulent surface stress!");
8507
8508 /* Read surface sensible heat flux... */
8509 if (!read_met_nc_2d
8510 (ncid, "ishf", "ISHF", NULL, NULL, NULL, NULL, ctl, met, dd, met->shf,
8511 1.0, 1))
8512 WARN("Cannot read surface sensible heat flux!");
8513
8514 /* Read land-sea mask... */
8515 if (!read_met_nc_2d
8516 (ncid, "lsm", "LSM", NULL, NULL, NULL, NULL, ctl, met, dd, met->lsm,
8517 1.0, 1))
8518 WARN("Cannot read land-sea mask!");
8519
8520 /* Read sea surface temperature... */
8521 if (!read_met_nc_2d
8522 (ncid, "sstk", "SSTK", "sst", "SST", NULL, NULL, ctl, met, dd, met->sst,
8523 1.0, 1))
8524 WARN("Cannot read sea surface temperature!");
8525
8526 /* Read PBL... */
8527 if (ctl->met_pbl == 0)
8528 if (!read_met_nc_2d
8529 (ncid, "blp", "BLP", NULL, NULL, NULL, NULL, ctl, met, dd, met->pbl,
8530 0.01f, 1))
8531 WARN("Cannot read planetary boundary layer pressure!");
8532 if (ctl->met_pbl == 1)
8533 if (!read_met_nc_2d
8534 (ncid, "blh", "BLH", NULL, NULL, NULL, NULL, ctl, met, dd, met->pbl,
8535 0.001f, 1))
8536 WARN("Cannot read planetary boundary layer height!");
8537
8538 /* Read CAPE... */
8539 if (ctl->met_cape == 0)
8540 if (!read_met_nc_2d
8541 (ncid, "cape", "CAPE", NULL, NULL, NULL, NULL, ctl, met, dd,
8542 met->cape, 1.0, 1))
8543 WARN("Cannot read CAPE!");
8544
8545 /* Read CIN... */
8546 if (ctl->met_cape == 0)
8547 if (!read_met_nc_2d
8548 (ncid, "cin", "CIN", NULL, NULL, NULL, NULL, ctl, met, dd, met->cin,
8549 1.0, 1))
8550 WARN("Cannot read convective inhibition!");
8551}
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, dd_t *dd, float dest[EX][EY], const float scl, const int init)
Reads a 2-dimensional meteorological variable from a NetCDF file.
Definition: mptrac.c:8752
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,
dd_t dd,
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).
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.
ddA pointer to an dd_t structure containing MPI information, including rank and neighbours.
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 8752 of file mptrac.c.

8765 {
8766
8767 char varsel[LEN];
8768
8769 float offset, scalfac;
8770
8771 int varid;
8772
8773 /* Check if variable exists... */
8774 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
8775 sprintf(varsel, "%s", varname);
8776 else if (varname2 != NULL
8777 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
8778 sprintf(varsel, "%s", varname2);
8779 else if (varname3 != NULL
8780 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
8781 sprintf(varsel, "%s", varname3);
8782 else if (varname4 != NULL
8783 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
8784 sprintf(varsel, "%s", varname4);
8785 else if (varname5 != NULL
8786 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
8787 sprintf(varsel, "%s", varname5);
8788 else if (varname6 != NULL
8789 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
8790 sprintf(varsel, "%s", varname6);
8791 else
8792 return 0;
8793
8794 /* Read packed data... */
8795 if (ctl->met_nc_scale && !ctl->dd
8796 && nc_get_att_float(ncid, varid, "add_offset", &offset) == NC_NOERR
8797 && nc_get_att_float(ncid, varid, "scale_factor",
8798 &scalfac) == NC_NOERR) {
8799
8800 /* Allocate... */
8801 short *help;
8802 ALLOC(help, short,
8803 EX * EY * EP);
8804
8805 /* Read fill value and missing value... */
8806 short fillval, missval;
8807 if (nc_get_att_short(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
8808 fillval = 0;
8809 if (nc_get_att_short(ncid, varid, "missing_value", &missval) != NC_NOERR)
8810 missval = 0;
8811
8812 /* Write info... */
8813 LOG(2, "Read 2-D variable: %s"
8814 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
8815 varsel, fillval, missval, scalfac, offset);
8816
8817 /* Read data... */
8818 NC(nc_get_var_short(ncid, varid, help));
8819
8820 /* Check meteo data layout... */
8821 if (ctl->met_convention != 0)
8822 ERRMSG("Meteo data layout not implemented for packed netCDF files!");
8823
8824 /* Copy and check data... */
8825 omp_set_dynamic(1);
8826#pragma omp parallel for default(shared)
8827 for (int ix = 0; ix < met->nx; ix++)
8828 for (int iy = 0; iy < met->ny; iy++) {
8829 if (init)
8830 dest[ix][iy] = 0;
8831 const short aux = help[ARRAY_2D(iy, ix, met->nx)];
8832 if ((fillval == 0 || aux != fillval)
8833 && (missval == 0 || aux != missval)
8834 && fabsf(aux * scalfac + offset) < 1e14f)
8835 dest[ix][iy] += scl * (aux * scalfac + offset);
8836 else
8837 dest[ix][iy] = NAN;
8838 }
8839 omp_set_dynamic(0);
8840
8841 /* Free... */
8842 free(help);
8843 }
8844
8845 /* Unpacked data... */
8846 else if (!ctl->dd) {
8847
8848 /* Allocate... */
8849 float *help;
8850 ALLOC(help, float,
8851 EX * EY);
8852
8853 /* Read fill value and missing value... */
8854 float fillval, missval;
8855 if (nc_get_att_float(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
8856 fillval = 0;
8857 if (nc_get_att_float(ncid, varid, "missing_value", &missval) != NC_NOERR)
8858 missval = 0;
8859
8860 /* Write info... */
8861 LOG(2, "Read 2-D variable: %s (FILL = %g, MISS = %g)",
8862 varsel, fillval, missval);
8863
8864 /* Read data... */
8865 NC(nc_get_var_float(ncid, varid, help));
8866
8867 /* Check meteo data layout... */
8868 if (ctl->met_convention == 0) {
8869
8870 /* Copy and check data (ordering: lat, lon)... */
8871 omp_set_dynamic(1);
8872#pragma omp parallel for default(shared)
8873 for (int ix = 0; ix < met->nx; ix++)
8874 for (int iy = 0; iy < met->ny; iy++) {
8875 if (init)
8876 dest[ix][iy] = 0;
8877 const float aux = help[ARRAY_2D(iy, ix, met->nx)];
8878 if ((fillval == 0 || aux != fillval)
8879 && (missval == 0 || aux != missval)
8880 && fabsf(aux) < 1e14f)
8881 dest[ix][iy] += scl * aux;
8882 else
8883 dest[ix][iy] = NAN;
8884 }
8885 omp_set_dynamic(0);
8886
8887 } else {
8888
8889 /* Copy and check data (ordering: lon, lat)... */
8890 omp_set_dynamic(1);
8891#pragma omp parallel for default(shared)
8892 for (int iy = 0; iy < met->ny; iy++)
8893 for (int ix = 0; ix < met->nx; ix++) {
8894 if (init)
8895 dest[ix][iy] = 0;
8896 const float aux = help[ARRAY_2D(ix, iy, met->ny)];
8897 if ((fillval == 0 || aux != fillval)
8898 && (missval == 0 || aux != missval)
8899 && fabsf(aux) < 1e14f)
8900 dest[ix][iy] += scl * aux;
8901 else
8902 dest[ix][iy] = NAN;
8903 }
8904 omp_set_dynamic(0);
8905 }
8906
8907 /* Free... */
8908 free(help);
8909
8910 }
8911 /* Domain decomposed data... */
8912 else {
8913
8914 /* Read fill value and missing value... */
8915 float fillval, missval;
8916 if (nc_get_att_float(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
8917 fillval = 0;
8918 if (nc_get_att_float(ncid, varid, "missing_value", &missval) != NC_NOERR)
8919 missval = 0;
8920
8921 /* Write info... */
8922 LOG(2, "Read 2-D variable: %s (FILL = %g, MISS = %g)",
8923 varsel, fillval, missval);
8924
8925 /* Define hyperslab... */
8926 float *help;
8927 size_t help_subdomain_start[3];
8928 size_t help_subdomain_count[3];
8929
8930 help_subdomain_start[0] = 0;
8931 help_subdomain_start[1] = dd->subdomain_start[2];
8932 help_subdomain_start[2] = dd->subdomain_start[3];
8933
8934 help_subdomain_count[0] = 1;
8935 help_subdomain_count[1] = dd->subdomain_count[2]; //y
8936 help_subdomain_count[2] = dd->subdomain_count[3]; //x
8937
8938 ALLOC(help, float,
8939 (int) dd->subdomain_count[2] * (int) dd->subdomain_count[3]
8940 );
8941
8942 /* Read data... */
8943 NC(nc_get_vara_float
8944 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
8945
8946 /* Read halos at boundaries... */
8947 size_t help_halo_bnd_start[3];
8948 size_t help_halo_bnd_count[3];
8949
8950 help_halo_bnd_start[0] = 0;
8951 help_halo_bnd_start[1] = dd->halo_bnd_start[2];
8952 help_halo_bnd_start[2] = dd->halo_bnd_start[3];
8953
8954 help_halo_bnd_count[0] = 1;
8955 help_halo_bnd_count[1] = dd->halo_bnd_count[2]; //y
8956 help_halo_bnd_count[2] = dd->halo_bnd_count[3]; //x
8957
8958 float *help_halo;
8959 ALLOC(help_halo, float,
8960 help_halo_bnd_count[1] * help_halo_bnd_count[2]);
8961 NC(nc_get_vara_float
8962 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count, help_halo));
8963
8964 /* Check meteo data layout... */
8965 if (ctl->met_convention == 0) {
8966 /* Copy and check data (ordering: lat, lon)... */
8967#pragma omp parallel for default(shared) num_threads(12)
8968 for (int ix = 0; ix < (int) help_subdomain_count[2]; ix++)
8969 for (int iy = 0; iy < (int) help_subdomain_count[1]; iy++) {
8970 if (init == 1)
8971 dest[ix + dd->halo_offset_start][iy] = 0;
8972 const float aux =
8973 help[ARRAY_2D(iy, ix, (int) help_subdomain_count[2])];
8974 if ((fillval == 0 || aux != fillval)
8975 && (missval == 0 || aux != missval)
8976 && fabsf(aux) < 1e14f) {
8977 dest[ix + dd->halo_offset_start][iy] += scl * aux;
8978 } else
8979 dest[ix + dd->halo_offset_start][iy] = NAN;
8980 }
8981
8982 /* Copy and check data (ordering: lat, lon)... */
8983#pragma omp parallel for default(shared) num_threads(12)
8984 for (int ix = 0; ix < (int) help_halo_bnd_count[2]; ix++)
8985 for (int iy = 0; iy < (int) help_halo_bnd_count[1]; iy++) {
8986 if (init == 1)
8987 dest[ix + dd->halo_offset_end][iy] = 0;
8988 const float aux =
8989 help_halo[ARRAY_2D(iy, ix, (int) help_halo_bnd_count[2])];
8990 if ((fillval == 0 || aux != fillval)
8991 && (missval == 0 || aux != missval)
8992 && fabsf(aux) < 1e14f)
8993 dest[ix + dd->halo_offset_end][iy] += scl * aux;
8994 else {
8995 dest[ix + dd->halo_offset_end][iy] = NAN;
8996 }
8997 }
8998
8999 } else {
9000 ERRMSG("Domain decomposition with data convection incompatible!");
9001 }
9002
9003 /* Free... */
9004 free(help);
9005 free(help_halo);
9006 }
9007
9008 /* Return... */
9009 return 1;
9010}

◆ 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,
dd_t dd,
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).
ctlA pointer to a structure containing control parameters.
metA pointer to a structure containing meteorological data.
ddA pointer to an dd_t structure containing MPI information, including rank and neighbours.
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 9014 of file mptrac.c.

9024 {
9025
9026 SELECT_TIMER("read_met_nc_3d", "INPUT", NVTX_READ);
9027
9028 char varsel[LEN];
9029
9030 float offset, scalfac;
9031
9032 int varid;
9033
9034 /* Check if variable exists... */
9035 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
9036 sprintf(varsel, "%s", varname);
9037 else if (varname2 != NULL
9038 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
9039 sprintf(varsel, "%s", varname2);
9040 else if (varname3 != NULL
9041 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
9042 sprintf(varsel, "%s", varname3);
9043 else if (varname4 != NULL
9044 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
9045 sprintf(varsel, "%s", varname4);
9046 else
9047 return 0;
9048
9049 if (ctl->met_nc_scale && !ctl->dd
9050 && nc_get_att_float(ncid, varid, "add_offset", &offset) == NC_NOERR
9051 && nc_get_att_float(ncid, varid, "scale_factor",
9052 &scalfac) == NC_NOERR) {
9053
9054 /* Allocate... */
9055 short *help;
9056 ALLOC(help, short,
9057 EX * EY * EP);
9058
9059 /* Read fill value and missing value... */
9060 short fillval, missval;
9061 if (nc_get_att_short(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
9062 fillval = 0;
9063 if (nc_get_att_short(ncid, varid, "missing_value", &missval) != NC_NOERR)
9064 missval = 0;
9065
9066 /* Write info... */
9067 LOG(2, "Read 3-D variable: %s "
9068 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
9069 varsel, fillval, missval, scalfac, offset);
9070
9071 /* Read data... */
9072 NC(nc_get_var_short(ncid, varid, help));
9073
9074 /* Check meteo data layout... */
9075 if (ctl->met_convention != 0)
9076 ERRMSG("Meteo data layout not implemented for packed netCDF files!");
9077
9078 /* Copy and check data... */
9079 omp_set_dynamic(1);
9080#pragma omp parallel for default(shared)
9081 for (int ix = 0; ix < met->nx; ix++)
9082 for (int iy = 0; iy < met->ny; iy++)
9083 for (int ip = 0; ip < met->np; ip++) {
9084 const short aux = help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)];
9085 if ((fillval == 0 || aux != fillval)
9086 && (missval == 0 || aux != missval)
9087 && fabsf(aux * scalfac + offset) < 1e14f)
9088 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
9089 else
9090 dest[ix][iy][ip] = NAN;
9091 }
9092 omp_set_dynamic(0);
9093
9094 /* Free... */
9095 free(help);
9096 }
9097
9098 /* Unpacked data... */
9099 else if (!ctl->dd) {
9100
9101 /* Allocate... */
9102 float *help;
9103 ALLOC(help, float,
9104 EX * EY * EP);
9105
9106 /* Read fill value and missing value... */
9107 float fillval, missval;
9108 if (nc_get_att_float(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
9109 fillval = 0;
9110 if (nc_get_att_float(ncid, varid, "missing_value", &missval) != NC_NOERR)
9111 missval = 0;
9112
9113 /* Write info... */
9114 LOG(2, "Read 3-D variable: %s (FILL = %g, MISS = %g)",
9115 varsel, fillval, missval);
9116
9117 /* Read data... */
9118 NC(nc_get_var_float(ncid, varid, help));
9119
9120 /* Check meteo data layout... */
9121 if (ctl->met_convention == 0) {
9122
9123 /* Copy and check data (ordering: lev, lat, lon)... */
9124 omp_set_dynamic(1);
9125#pragma omp parallel for default(shared)
9126 for (int ix = 0; ix < met->nx; ix++)
9127 for (int iy = 0; iy < met->ny; iy++)
9128 for (int ip = 0; ip < met->np; ip++) {
9129 const float aux = help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)];
9130 if ((fillval == 0 || aux != fillval)
9131 && (missval == 0 || aux != missval)
9132 && fabsf(aux) < 1e14f)
9133 dest[ix][iy][ip] = scl * aux;
9134 else
9135 dest[ix][iy][ip] = NAN;
9136 }
9137 omp_set_dynamic(0);
9138
9139 } else {
9140
9141 /* Copy and check data (ordering: lon, lat, lev)... */
9142 omp_set_dynamic(1);
9143#pragma omp parallel for default(shared)
9144 for (int ip = 0; ip < met->np; ip++)
9145 for (int iy = 0; iy < met->ny; iy++)
9146 for (int ix = 0; ix < met->nx; ix++) {
9147 const float aux = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
9148 if ((fillval == 0 || aux != fillval)
9149 && (missval == 0 || aux != missval)
9150 && fabsf(aux) < 1e14f)
9151 dest[ix][iy][ip] = scl * aux;
9152 else
9153 dest[ix][iy][ip] = NAN;
9154 }
9155 omp_set_dynamic(0);
9156 }
9157
9158 /* Free... */
9159 free(help);
9160
9161 }
9162 /* Domain decomposed data... */
9163 else {
9164
9165 /* Read fill value and missing value... */
9166 float fillval, missval;
9167 if (nc_get_att_float(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
9168 fillval = 0;
9169 if (nc_get_att_float(ncid, varid, "missing_value", &missval) != NC_NOERR)
9170 missval = 0;
9171
9172 /* Write info... */
9173 LOG(2, "Read 3-D variable: %s (FILL = %g, MISS = %g)",
9174 varsel, fillval, missval);
9175
9176 SELECT_TIMER("read_met_nc_3d_CP1", "INPUT", NVTX_READ);
9177
9178 /* Define hyperslab... */
9179
9180 /* Allocate... */
9181 float *help;
9182 ALLOC(help, float,
9183 (int) dd->subdomain_count[0] * (int) dd->subdomain_count[1]
9184 * (int) dd->subdomain_count[2] * (int) dd->subdomain_count[3]);
9185
9186 SELECT_TIMER("read_met_nc_3d_CP2", "INPUT", NVTX_READ);
9187
9188 /* Use default NetCDF parallel I/O behavior */
9189 NC(nc_get_vara_float
9190 (ncid, varid, dd->subdomain_start, dd->subdomain_count, help));
9191
9192 /* Read halos separately at boundaries... */
9193 float *help_halo;
9194 ALLOC(help_halo, float,
9195 dd->halo_bnd_count[0] * dd->halo_bnd_count[1] *
9196 dd->halo_bnd_count[2] * dd->halo_bnd_count[3]);
9197
9198 SELECT_TIMER("read_met_nc_3d_CP3", "INPUT", NVTX_READ);
9199
9200 /* Halo read also uses independent access */
9201 NC(nc_get_vara_float(ncid,
9202 varid,
9203 dd->halo_bnd_start, dd->halo_bnd_count, help_halo));
9204
9205 SELECT_TIMER("read_met_nc_3d_CP4", "INPUT", NVTX_READ);
9206
9207 /* Check meteo data layout... */
9208 if (ctl->met_convention == 0) {
9209 /* Copy and check data (ordering: lev, lat, lon)... */
9210#pragma omp parallel for default(shared) num_threads(12)
9211 for (int ix = 0; ix < (int) dd->subdomain_count[3]; ix++)
9212 for (int iy = 0; iy < (int) dd->subdomain_count[2]; iy++)
9213 for (int ip = 0; ip < met->np; ip++) {
9214 const float aux =
9215 help[ARRAY_3D(ip, iy, (int) dd->subdomain_count[2], ix,
9216 (int) dd->subdomain_count[3])];
9217 if ((fillval == 0 || aux != fillval)
9218 && (missval == 0 || aux != missval)
9219 && fabsf(aux) < 1e14f)
9220 dest[ix + dd->halo_offset_start][iy][ip] = scl * aux;
9221 else
9222 dest[ix + dd->halo_offset_start][iy][ip] = NAN;
9223 }
9224
9225#pragma omp parallel for default(shared) num_threads(12)
9226 for (int ix = 0; ix < (int) dd->halo_bnd_count[3]; ix++)
9227 for (int iy = 0; iy < (int) dd->halo_bnd_count[2]; iy++)
9228 for (int ip = 0; ip < met->np; ip++) {
9229 const float aux =
9230 help_halo[ARRAY_3D(ip, iy, (int) dd->halo_bnd_count[2], ix,
9231 (int) dd->halo_bnd_count[3])];
9232 if ((fillval == 0 || aux != fillval)
9233 && (missval == 0 || aux != missval)
9234 && fabsf(aux) < 1e14f)
9235 dest[ix + dd->halo_offset_end][iy][ip] = scl * aux;
9236 else
9237 dest[ix + dd->halo_offset_end][iy][ip] = NAN;
9238 }
9239
9240 } else {
9241
9242 /* Copy and check data (ordering: lon, lat, lev)... */
9243#pragma omp parallel for default(shared) num_threads(12)
9244 for (int ip = 0; ip < met->np; ip++)
9245 for (int iy = 0; iy < (int) dd->subdomain_count[2]; iy++)
9246 for (int ix = 0; ix < (int) dd->subdomain_count[3]; ix++) {
9247 const float aux = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
9248 if ((fillval == 0 || aux != fillval)
9249 && (missval == 0 || aux != missval)
9250 && fabsf(aux) < 1e14f)
9251 dest[ix + dd->halo_offset_end][iy][ip] = scl * aux;
9252 else
9253 dest[ix + dd->halo_offset_end][iy][ip] = NAN;
9254 }
9255
9256#pragma omp parallel for default(shared) num_threads(12)
9257 for (int ip = 0; ip < met->np; ip++)
9258 for (int iy = 0; iy < (int) dd->halo_bnd_count[2]; iy++)
9259 for (int ix = 0; ix < (int) dd->halo_bnd_count[3]; ix++) {
9260 const float aux = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
9261 if ((fillval == 0 || aux != fillval)
9262 && (missval == 0 || aux != missval)
9263 && fabsf(aux) < 1e14f)
9264 dest[ix + dd->halo_offset_start][iy][ip] = scl * aux;
9265 else
9266 dest[ix + dd->halo_offset_start][iy][ip] = NAN;
9267 }
9268 }
9269
9270 /* Free... */
9271 free(help);
9272 free(help_halo);
9273 }
9274
9275 /* Return... */
9276 return 1;
9277}

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

10115 {
10116
10117 /* Set timer... */
10118 SELECT_TIMER("READ_MET_PBL", "METPROC", NVTX_READ);
10119 LOG(2, "Calculate planetary boundary layer...");
10120
10121 /* Convert PBL height from meteo file to pressure... */
10122 if (ctl->met_pbl == 1) {
10123
10124 /* Loop over grid points... */
10125#pragma omp parallel for default(shared) collapse(2)
10126 for (int ix = 0; ix < met->nx; ix++)
10127 for (int iy = 0; iy < met->ny; iy++) {
10128
10129 /* Get pressure at top of PBL... */
10130 const float z = met->zs[ix][iy] + met->pbl[ix][iy];
10131 const int ip = locate_irr_float(met->z[ix][iy], met->np, z, 0);
10132 met->pbl[ix][iy] =
10133 (float) (LIN(met->z[ix][iy][ip], met->p[ip],
10134 met->z[ix][iy][ip + 1], met->p[ip + 1], z));
10135 }
10136 }
10137
10138 /* Determine PBL based on Richardson number... */
10139 else if (ctl->met_pbl == 2) {
10140
10141 /* Parameters used to estimate the height of the PBL
10142 (e.g., Vogelezang and Holtslag, 1996; Seidel et al., 2012)... */
10143 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
10144
10145 /* Loop over grid points... */
10146#pragma omp parallel for default(shared) collapse(2)
10147 for (int ix = 0; ix < met->nx; ix++)
10148 for (int iy = 0; iy < met->ny; iy++) {
10149
10150 /* Set bottom level of PBL... */
10151 const double pbl_bot = met->ps[ix][iy] * exp(-dz / H0);
10152
10153 /* Find lowest level near the bottom... */
10154 int ip;
10155 for (ip = 1; ip < met->np; ip++)
10156 if (met->p[ip] < pbl_bot)
10157 break;
10158
10159 /* Get near surface data... */
10160 const double h2os = LIN(met->p[ip - 1], met->h2o[ix][iy][ip - 1],
10161 met->p[ip], met->h2o[ix][iy][ip], pbl_bot);
10162 const double tvs = THETAVIRT(pbl_bot, met->ts[ix][iy], h2os);
10163
10164 /* Init... */
10165 double rib_old = 0;
10166
10167 /* Loop over levels... */
10168 for (; ip < met->np; ip++) {
10169
10170 /* Get squared horizontal wind speed... */
10171 double vh2 = SQR(met->u[ix][iy][ip] - met->us[ix][iy])
10172 + SQR(met->v[ix][iy][ip] - met->vs[ix][iy]);
10173 vh2 = MAX(vh2, SQR(umin));
10174
10175 /* Calculate bulk Richardson number... */
10176 const double rib =
10177 G0 * 1e3 * (met->z[ix][iy][ip] - met->zs[ix][iy]) / tvs
10178 * (THETAVIRT(met->p[ip], met->t[ix][iy][ip],
10179 met->h2o[ix][iy][ip]) - tvs) / vh2;
10180
10181 /* Check for critical value... */
10182 if (rib >= rib_crit) {
10183 met->pbl[ix][iy] = (float) (LIN(rib_old, met->p[ip - 1],
10184 rib, met->p[ip], rib_crit));
10185 if (met->pbl[ix][iy] > pbl_bot)
10186 met->pbl[ix][iy] = (float) pbl_bot;
10187 break;
10188 }
10189
10190 /* Save Richardson number... */
10191 rib_old = rib;
10192 }
10193 }
10194 }
10195
10196 /* Determine PBL based on potential temperature... */
10197 if (ctl->met_pbl == 3) {
10198
10199 /* Parameters used to estimate the height of the PBL
10200 (following HYSPLIT model)... */
10201 const double dtheta = 2.0, zmin = 0.1;
10202
10203 /* Loop over grid points... */
10204#pragma omp parallel for default(shared) collapse(2)
10205 for (int ix = 0; ix < met->nx; ix++)
10206 for (int iy = 0; iy < met->ny; iy++) {
10207
10208 /* Potential temperature at the surface... */
10209 const double theta0 = THETA(met->ps[ix][iy], met->ts[ix][iy]);
10210
10211 /* Find topmost level where theta exceeds surface value by 2 K... */
10212 int ip;
10213 for (ip = met->np - 2; ip > 0; ip--)
10214 if (met->p[ip] >= 300.)
10215 if (met->p[ip] > met->ps[ix][iy]
10216 || THETA(met->p[ip], met->t[ix][iy][ip]) <= theta0 + dtheta)
10217 break;
10218
10219 /* Interpolate... */
10220 met->pbl[ix][iy]
10221 = (float) (LIN(THETA(met->p[ip + 1], met->t[ix][iy][ip + 1]),
10222 met->p[ip + 1],
10223 THETA(met->p[ip], met->t[ix][iy][ip]),
10224 met->p[ip], theta0 + dtheta));
10225
10226 /* Check minimum value... */
10227 double pbl_min = met->ps[ix][iy] * exp(-zmin / H0);
10228 if (met->pbl[ix][iy] > pbl_min || met->p[ip] > met->ps[ix][iy])
10229 met->pbl[ix][iy] = (float) pbl_min;
10230 }
10231 }
10232
10233 /* Loop over grid points... */
10234#pragma omp parallel for default(shared) collapse(2)
10235 for (int ix = 0; ix < met->nx; ix++)
10236 for (int iy = 0; iy < met->ny; iy++) {
10237
10238 /* Check minimum value... */
10239 double pbl_min = met->ps[ix][iy] * exp(-ctl->met_pbl_min / H0);
10240 met->pbl[ix][iy] = MIN(met->pbl[ix][iy], (float) pbl_min);
10241
10242 /* Check maximum value... */
10243 double pbl_max = met->ps[ix][iy] * exp(-ctl->met_pbl_max / H0);
10244 met->pbl[ix][iy] = MAX(met->pbl[ix][iy], (float) pbl_max);
10245 }
10246}
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 10250 of file mptrac.c.

10251 {
10252
10253 /* Set timer... */
10254 SELECT_TIMER("READ_MET_PERIODIC", "METPROC", NVTX_READ);
10255 LOG(2, "Apply periodic boundary conditions...");
10256
10257 /* Check longitudes... */
10258 if (!(fabs(met->lon[met->nx - 1] - met->lon[0]
10259 + met->lon[1] - met->lon[0] - 360) < 0.01))
10260 return;
10261
10262 /* Increase longitude counter... */
10263 if ((++met->nx) >= EX)
10264 ERRMSG("Cannot create periodic boundary conditions!");
10265
10266 /* Set longitude... */
10267 met->lon[met->nx - 1] = met->lon[met->nx - 2] + met->lon[1] - met->lon[0];
10268
10269 /* Loop over latitudes and pressure levels... */
10270#pragma omp parallel for default(shared)
10271 for (int iy = 0; iy < met->ny; iy++) {
10272 met->ps[met->nx - 1][iy] = met->ps[0][iy];
10273 met->zs[met->nx - 1][iy] = met->zs[0][iy];
10274 met->ts[met->nx - 1][iy] = met->ts[0][iy];
10275 met->us[met->nx - 1][iy] = met->us[0][iy];
10276 met->vs[met->nx - 1][iy] = met->vs[0][iy];
10277 met->ess[met->nx - 1][iy] = met->ess[0][iy];
10278 met->nss[met->nx - 1][iy] = met->nss[0][iy];
10279 met->shf[met->nx - 1][iy] = met->shf[0][iy];
10280 met->lsm[met->nx - 1][iy] = met->lsm[0][iy];
10281 met->sst[met->nx - 1][iy] = met->sst[0][iy];
10282 met->pbl[met->nx - 1][iy] = met->pbl[0][iy];
10283 met->cape[met->nx - 1][iy] = met->cape[0][iy];
10284 met->cin[met->nx - 1][iy] = met->cin[0][iy];
10285 for (int ip = 0; ip < met->np; ip++) {
10286 met->t[met->nx - 1][iy][ip] = met->t[0][iy][ip];
10287 met->u[met->nx - 1][iy][ip] = met->u[0][iy][ip];
10288 met->v[met->nx - 1][iy][ip] = met->v[0][iy][ip];
10289 met->w[met->nx - 1][iy][ip] = met->w[0][iy][ip];
10290 met->h2o[met->nx - 1][iy][ip] = met->h2o[0][iy][ip];
10291 met->o3[met->nx - 1][iy][ip] = met->o3[0][iy][ip];
10292 met->lwc[met->nx - 1][iy][ip] = met->lwc[0][iy][ip];
10293 met->rwc[met->nx - 1][iy][ip] = met->rwc[0][iy][ip];
10294 met->iwc[met->nx - 1][iy][ip] = met->iwc[0][iy][ip];
10295 met->swc[met->nx - 1][iy][ip] = met->swc[0][iy][ip];
10296 met->cc[met->nx - 1][iy][ip] = met->cc[0][iy][ip];
10297 }
10298 for (int ip = 0; ip < met->npl; ip++) {
10299 met->ul[met->nx - 1][iy][ip] = met->ul[0][iy][ip];
10300 met->vl[met->nx - 1][iy][ip] = met->vl[0][iy][ip];
10301 met->wl[met->nx - 1][iy][ip] = met->wl[0][iy][ip];
10302 met->pl[met->nx - 1][iy][ip] = met->pl[0][iy][ip];
10303 met->zetal[met->nx - 1][iy][ip] = met->zetal[0][iy][ip];
10304 met->zeta_dotl[met->nx - 1][iy][ip] = met->zeta_dotl[0][iy][ip];
10305 }
10306 }
10307}

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

10312 {
10313
10314 /* Set timer... */
10315 SELECT_TIMER("READ_MET_POLAR_WINDS", "METPROC", NVTX_READ);
10316 LOG(2, "Apply fix for polar winds...");
10317
10318 /* Check latitudes... */
10319 if (fabs(met->lat[0]) < 89.999 || fabs(met->lat[met->ny - 1]) < 89.999)
10320 return;
10321
10322 /* Loop over hemispheres... */
10323 for (int ihem = 0; ihem < 2; ihem++) {
10324
10325 /* Set latitude indices... */
10326 int i89 = 1, i90 = 0, sign = 1;
10327 if (ihem == 1) {
10328 i89 = met->ny - 2;
10329 i90 = met->ny - 1;
10330 }
10331 if (met->lat[i90] < 0)
10332 sign = -1;
10333
10334 /* Look-up table of cosinus and sinus... */
10335 double clon[EX], slon[EX];
10336#pragma omp parallel for default(shared)
10337 for (int ix = 0; ix < met->nx; ix++) {
10338 clon[ix] = cos(sign * DEG2RAD(met->lon[ix]));
10339 slon[ix] = sin(sign * DEG2RAD(met->lon[ix]));
10340 }
10341
10342 /* Loop over levels... */
10343#pragma omp parallel for default(shared)
10344 for (int ip = 0; ip < met->np; ip++) {
10345
10346 /* Transform 89 degree u and v winds into Cartesian coordinates and take the mean... */
10347 double vel89x = 0, vel89y = 0;
10348 for (int ix = 0; ix < met->nx; ix++) {
10349 vel89x +=
10350 (met->u[ix][i89][ip] * clon[ix] -
10351 met->v[ix][i89][ip] * slon[ix]) / met->nx;
10352 vel89y +=
10353 (met->u[ix][i89][ip] * slon[ix] +
10354 met->v[ix][i89][ip] * clon[ix]) / met->nx;
10355 }
10356
10357 /* Replace 90 degree winds by 89 degree mean... */
10358 for (int ix = 0; ix < met->nx; ix++) {
10359 met->u[ix][i90][ip]
10360 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
10361 met->v[ix][i90][ip]
10362 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
10363 }
10364 }
10365 }
10366}

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

10371 {
10372
10373 double pows[EP];
10374
10375 /* Set timer... */
10376 SELECT_TIMER("READ_MET_PV", "METPROC", NVTX_READ);
10377 LOG(2, "Calculate potential vorticity...");
10378
10379 /* Set powers... */
10380#pragma omp parallel for default(shared)
10381 for (int ip = 0; ip < met->np; ip++)
10382 pows[ip] = pow(1000. / met->p[ip], 0.286);
10383
10384 /* Loop over grid points... */
10385#pragma omp parallel for default(shared)
10386 for (int ix = 0; ix < met->nx; ix++) {
10387
10388 /* Set indices... */
10389 const int ix0 = MAX(ix - 1, 0);
10390 const int ix1 = MIN(ix + 1, met->nx - 1);
10391
10392 /* Loop over grid points... */
10393 for (int iy = 0; iy < met->ny; iy++) {
10394
10395 /* Set indices... */
10396 const int iy0 = MAX(iy - 1, 0);
10397 const int iy1 = MIN(iy + 1, met->ny - 1);
10398
10399 /* Set auxiliary variables... */
10400 const double latr = 0.5 * (met->lat[iy1] + met->lat[iy0]);
10401 const double dx = 1000. * DEG2DX(met->lon[ix1] - met->lon[ix0], latr);
10402 const double dy = 1000. * DEG2DY(met->lat[iy1] - met->lat[iy0]);
10403 const double c0 = cos(DEG2RAD(met->lat[iy0]));
10404 const double c1 = cos(DEG2RAD(met->lat[iy1]));
10405 const double cr = cos(DEG2RAD(latr));
10406 const double vort = 2 * 7.2921e-5 * sin(DEG2RAD(latr));
10407
10408 /* Loop over grid points... */
10409 for (int ip = 0; ip < met->np; ip++) {
10410
10411 /* Get gradients in longitude... */
10412 const double dtdx
10413 = (met->t[ix1][iy][ip] - met->t[ix0][iy][ip]) * pows[ip] / dx;
10414 const double dvdx = (met->v[ix1][iy][ip] - met->v[ix0][iy][ip]) / dx;
10415
10416 /* Get gradients in latitude... */
10417 const double dtdy
10418 = (met->t[ix][iy1][ip] - met->t[ix][iy0][ip]) * pows[ip] / dy;
10419 const double dudy
10420 = (met->u[ix][iy1][ip] * c1 - met->u[ix][iy0][ip] * c0) / dy;
10421
10422 /* Set indices... */
10423 const int ip0 = MAX(ip - 1, 0);
10424 const int ip1 = MIN(ip + 1, met->np - 1);
10425
10426 /* Get gradients in pressure... */
10427 double dtdp, dudp, dvdp;
10428 const double dp0 = 100. * (met->p[ip] - met->p[ip0]);
10429 const double dp1 = 100. * (met->p[ip1] - met->p[ip]);
10430 if (ip != ip0 && ip != ip1) {
10431 double denom = dp0 * dp1 * (dp0 + dp1);
10432 dtdp = (dp0 * dp0 * met->t[ix][iy][ip1] * pows[ip1]
10433 - dp1 * dp1 * met->t[ix][iy][ip0] * pows[ip0]
10434 + (dp1 * dp1 - dp0 * dp0) * met->t[ix][iy][ip] * pows[ip])
10435 / denom;
10436 dudp = (dp0 * dp0 * met->u[ix][iy][ip1]
10437 - dp1 * dp1 * met->u[ix][iy][ip0]
10438 + (dp1 * dp1 - dp0 * dp0) * met->u[ix][iy][ip])
10439 / denom;
10440 dvdp = (dp0 * dp0 * met->v[ix][iy][ip1]
10441 - dp1 * dp1 * met->v[ix][iy][ip0]
10442 + (dp1 * dp1 - dp0 * dp0) * met->v[ix][iy][ip])
10443 / denom;
10444 } else {
10445 const double denom = dp0 + dp1;
10446 dtdp =
10447 (met->t[ix][iy][ip1] * pows[ip1] -
10448 met->t[ix][iy][ip0] * pows[ip0]) / denom;
10449 dudp = (met->u[ix][iy][ip1] - met->u[ix][iy][ip0]) / denom;
10450 dvdp = (met->v[ix][iy][ip1] - met->v[ix][iy][ip0]) / denom;
10451 }
10452
10453 /* Calculate PV... */
10454 met->pv[ix][iy][ip] = (float)
10455 (1e6 * G0 *
10456 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
10457 }
10458 }
10459 }
10460
10461 /* Fix for polar regions... */
10462#pragma omp parallel for default(shared)
10463 for (int ix = 0; ix < met->nx; ix++)
10464 for (int ip = 0; ip < met->np; ip++) {
10465 met->pv[ix][0][ip]
10466 = met->pv[ix][1][ip]
10467 = met->pv[ix][2][ip];
10468 met->pv[ix][met->ny - 1][ip]
10469 = met->pv[ix][met->ny - 2][ip]
10470 = met->pv[ix][met->ny - 3][ip];
10471 }
10472}
#define DEG2DY(dlat)
Convert a latitude difference to a distance in the y-direction (north-south).
Definition: mptrac.h:550
#define DEG2DX(dlon, lat)
Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude.
Definition: mptrac.h:529

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

10477 {
10478
10479 /* Set timer... */
10480 SELECT_TIMER("READ_MET_OZONE", "METPROC", NVTX_READ);
10481 LOG(2, "Calculate total column ozone...");
10482
10483 /* Loop over columns... */
10484#pragma omp parallel for default(shared) collapse(2)
10485 for (int ix = 0; ix < met->nx; ix++)
10486 for (int iy = 0; iy < met->ny; iy++) {
10487
10488 /* Integrate... */
10489 double cd = 0;
10490 for (int ip = 1; ip < met->np; ip++)
10491 if (met->p[ip - 1] <= met->ps[ix][iy]) {
10492 const double vmr =
10493 0.5 * (met->o3[ix][iy][ip - 1] + met->o3[ix][iy][ip]);
10494 const double dp = met->p[ip - 1] - met->p[ip];
10495 cd += vmr * MO3 / MA * dp * 1e2 / G0;
10496 }
10497
10498 /* Convert to Dobson units... */
10499 met->o3c[ix][iy] = (float) (cd / 2.1415e-5);
10500 }
10501}

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

10507 {
10508
10509 met_t *help;
10510
10511 /* Check parameters... */
10512 if (ctl->met_dp <= 1 && ctl->met_dx <= 1 && ctl->met_dy <= 1
10513 && ctl->met_sp <= 1 && ctl->met_sx <= 1 && ctl->met_sy <= 1)
10514 return;
10515
10516 /* Set timer... */
10517 SELECT_TIMER("READ_MET_SAMPLE", "METPROC", NVTX_READ);
10518 LOG(2, "Downsampling of meteo data...");
10519
10520 /* Allocate... */
10521 ALLOC(help, met_t, 1);
10522
10523 /* Copy data... */
10524 help->nx = met->nx;
10525 help->ny = met->ny;
10526 help->np = met->np;
10527 memcpy(help->lon, met->lon, sizeof(met->lon));
10528 memcpy(help->lat, met->lat, sizeof(met->lat));
10529 memcpy(help->p, met->p, sizeof(met->p));
10530
10531 /* Smoothing... */
10532 for (int ix = 0; ix < met->nx; ix += ctl->met_dx) {
10533 for (int iy = 0; iy < met->ny; iy += ctl->met_dy) {
10534 for (int ip = 0; ip < met->np; ip += ctl->met_dp) {
10535 help->ps[ix][iy] = 0;
10536 help->zs[ix][iy] = 0;
10537 help->ts[ix][iy] = 0;
10538 help->us[ix][iy] = 0;
10539 help->vs[ix][iy] = 0;
10540 help->ess[ix][iy] = 0;
10541 help->nss[ix][iy] = 0;
10542 help->shf[ix][iy] = 0;
10543 help->lsm[ix][iy] = 0;
10544 help->sst[ix][iy] = 0;
10545 help->pbl[ix][iy] = 0;
10546 help->cape[ix][iy] = 0;
10547 help->cin[ix][iy] = 0;
10548 help->t[ix][iy][ip] = 0;
10549 help->u[ix][iy][ip] = 0;
10550 help->v[ix][iy][ip] = 0;
10551 help->w[ix][iy][ip] = 0;
10552 help->h2o[ix][iy][ip] = 0;
10553 help->o3[ix][iy][ip] = 0;
10554 help->lwc[ix][iy][ip] = 0;
10555 help->rwc[ix][iy][ip] = 0;
10556 help->iwc[ix][iy][ip] = 0;
10557 help->swc[ix][iy][ip] = 0;
10558 help->cc[ix][iy][ip] = 0;
10559 float wsum = 0;
10560 for (int ix2 = ix - ctl->met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
10561 ix2++) {
10562 int ix3 = ix2;
10563 if (ix3 < 0)
10564 ix3 += met->nx;
10565 else if (ix3 >= met->nx)
10566 ix3 -= met->nx;
10567
10568 for (int iy2 = MAX(iy - ctl->met_sy + 1, 0);
10569 iy2 <= MIN(iy + ctl->met_sy - 1, met->ny - 1); iy2++)
10570 for (int ip2 = MAX(ip - ctl->met_sp + 1, 0);
10571 ip2 <= MIN(ip + ctl->met_sp - 1, met->np - 1); ip2++) {
10572 const float w =
10573 (1.0f - (float) abs(ix - ix2) / (float) ctl->met_sx)
10574 * (1.0f - (float) abs(iy - iy2) / (float) ctl->met_sy)
10575 * (1.0f - (float) abs(ip - ip2) / (float) ctl->met_sp);
10576 help->ps[ix][iy] += w * met->ps[ix3][iy2];
10577 help->zs[ix][iy] += w * met->zs[ix3][iy2];
10578 help->ts[ix][iy] += w * met->ts[ix3][iy2];
10579 help->us[ix][iy] += w * met->us[ix3][iy2];
10580 help->vs[ix][iy] += w * met->vs[ix3][iy2];
10581 help->ess[ix][iy] += w * met->ess[ix3][iy2];
10582 help->nss[ix][iy] += w * met->nss[ix3][iy2];
10583 help->shf[ix][iy] += w * met->shf[ix3][iy2];
10584 help->lsm[ix][iy] += w * met->lsm[ix3][iy2];
10585 help->sst[ix][iy] += w * met->sst[ix3][iy2];
10586 help->pbl[ix][iy] += w * met->pbl[ix3][iy2];
10587 help->cape[ix][iy] += w * met->cape[ix3][iy2];
10588 help->cin[ix][iy] += w * met->cin[ix3][iy2];
10589 help->t[ix][iy][ip] += w * met->t[ix3][iy2][ip2];
10590 help->u[ix][iy][ip] += w * met->u[ix3][iy2][ip2];
10591 help->v[ix][iy][ip] += w * met->v[ix3][iy2][ip2];
10592 help->w[ix][iy][ip] += w * met->w[ix3][iy2][ip2];
10593 help->h2o[ix][iy][ip] += w * met->h2o[ix3][iy2][ip2];
10594 help->o3[ix][iy][ip] += w * met->o3[ix3][iy2][ip2];
10595 help->lwc[ix][iy][ip] += w * met->lwc[ix3][iy2][ip2];
10596 help->rwc[ix][iy][ip] += w * met->rwc[ix3][iy2][ip2];
10597 help->iwc[ix][iy][ip] += w * met->iwc[ix3][iy2][ip2];
10598 help->swc[ix][iy][ip] += w * met->swc[ix3][iy2][ip2];
10599 help->cc[ix][iy][ip] += w * met->cc[ix3][iy2][ip2];
10600 wsum += w;
10601 }
10602 }
10603 help->ps[ix][iy] /= wsum;
10604 help->zs[ix][iy] /= wsum;
10605 help->ts[ix][iy] /= wsum;
10606 help->us[ix][iy] /= wsum;
10607 help->vs[ix][iy] /= wsum;
10608 help->ess[ix][iy] /= wsum;
10609 help->nss[ix][iy] /= wsum;
10610 help->shf[ix][iy] /= wsum;
10611 help->lsm[ix][iy] /= wsum;
10612 help->sst[ix][iy] /= wsum;
10613 help->pbl[ix][iy] /= wsum;
10614 help->cape[ix][iy] /= wsum;
10615 help->cin[ix][iy] /= wsum;
10616 help->t[ix][iy][ip] /= wsum;
10617 help->u[ix][iy][ip] /= wsum;
10618 help->v[ix][iy][ip] /= wsum;
10619 help->w[ix][iy][ip] /= wsum;
10620 help->h2o[ix][iy][ip] /= wsum;
10621 help->o3[ix][iy][ip] /= wsum;
10622 help->lwc[ix][iy][ip] /= wsum;
10623 help->rwc[ix][iy][ip] /= wsum;
10624 help->iwc[ix][iy][ip] /= wsum;
10625 help->swc[ix][iy][ip] /= wsum;
10626 help->cc[ix][iy][ip] /= wsum;
10627 }
10628 }
10629 }
10630
10631 /* Downsampling... */
10632 met->nx = 0;
10633 for (int ix = 0; ix < help->nx; ix += ctl->met_dx) {
10634 met->lon[met->nx] = help->lon[ix];
10635 met->ny = 0;
10636 for (int iy = 0; iy < help->ny; iy += ctl->met_dy) {
10637 met->lat[met->ny] = help->lat[iy];
10638 met->ps[met->nx][met->ny] = help->ps[ix][iy];
10639 met->zs[met->nx][met->ny] = help->zs[ix][iy];
10640 met->ts[met->nx][met->ny] = help->ts[ix][iy];
10641 met->us[met->nx][met->ny] = help->us[ix][iy];
10642 met->vs[met->nx][met->ny] = help->vs[ix][iy];
10643 met->ess[met->nx][met->ny] = help->ess[ix][iy];
10644 met->nss[met->nx][met->ny] = help->nss[ix][iy];
10645 met->shf[met->nx][met->ny] = help->shf[ix][iy];
10646 met->lsm[met->nx][met->ny] = help->lsm[ix][iy];
10647 met->sst[met->nx][met->ny] = help->sst[ix][iy];
10648 met->pbl[met->nx][met->ny] = help->pbl[ix][iy];
10649 met->cape[met->nx][met->ny] = help->cape[ix][iy];
10650 met->cin[met->nx][met->ny] = help->cin[ix][iy];
10651 met->np = 0;
10652 for (int ip = 0; ip < help->np; ip += ctl->met_dp) {
10653 met->p[met->np] = help->p[ip];
10654 met->t[met->nx][met->ny][met->np] = help->t[ix][iy][ip];
10655 met->u[met->nx][met->ny][met->np] = help->u[ix][iy][ip];
10656 met->v[met->nx][met->ny][met->np] = help->v[ix][iy][ip];
10657 met->w[met->nx][met->ny][met->np] = help->w[ix][iy][ip];
10658 met->h2o[met->nx][met->ny][met->np] = help->h2o[ix][iy][ip];
10659 met->o3[met->nx][met->ny][met->np] = help->o3[ix][iy][ip];
10660 met->lwc[met->nx][met->ny][met->np] = help->lwc[ix][iy][ip];
10661 met->rwc[met->nx][met->ny][met->np] = help->rwc[ix][iy][ip];
10662 met->iwc[met->nx][met->ny][met->np] = help->iwc[ix][iy][ip];
10663 met->swc[met->nx][met->ny][met->np] = help->swc[ix][iy][ip];
10664 met->cc[met->nx][met->ny][met->np] = help->cc[ix][iy][ip];
10665 met->np++;
10666 }
10667 met->ny++;
10668 }
10669 met->nx++;
10670 }
10671
10672 /* Free... */
10673 free(help);
10674}

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

10681 {
10682
10683 double p2[200], pv[EP], pv2[200], t[EP], t2[200], th[EP],
10684 th2[200], z[EP], z2[200];
10685
10686 /* Set timer... */
10687 SELECT_TIMER("READ_MET_TROPO", "METPROC", NVTX_READ);
10688 LOG(2, "Calculate tropopause...");
10689
10690 /* Get altitude and pressure profiles... */
10691#pragma omp parallel for default(shared)
10692 for (int iz = 0; iz < met->np; iz++)
10693 z[iz] = Z(met->p[iz]);
10694#pragma omp parallel for default(shared)
10695 for (int iz = 0; iz <= 190; iz++) {
10696 z2[iz] = 4.5 + 0.1 * iz;
10697 p2[iz] = P(z2[iz]);
10698 }
10699
10700 /* Do not calculate tropopause... */
10701 if (ctl->met_tropo == 0)
10702#pragma omp parallel for default(shared) collapse(2)
10703 for (int ix = 0; ix < met->nx; ix++)
10704 for (int iy = 0; iy < met->ny; iy++)
10705 met->pt[ix][iy] = NAN;
10706
10707 /* Use tropopause climatology... */
10708 else if (ctl->met_tropo == 1) {
10709#pragma omp parallel for default(shared) collapse(2)
10710 for (int ix = 0; ix < met->nx; ix++)
10711 for (int iy = 0; iy < met->ny; iy++)
10712 met->pt[ix][iy] = (float) clim_tropo(clim, met->time, met->lat[iy]);
10713 }
10714
10715 /* Use cold point... */
10716 else if (ctl->met_tropo == 2) {
10717
10718 /* Loop over grid points... */
10719#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10720 for (int ix = 0; ix < met->nx; ix++)
10721 for (int iy = 0; iy < met->ny; iy++) {
10722
10723 /* Interpolate temperature profile... */
10724 for (int iz = 0; iz < met->np; iz++)
10725 t[iz] = met->t[ix][iy][iz];
10726 spline(z, t, met->np, z2, t2, 171, ctl->met_tropo_spline);
10727
10728 /* Find minimum... */
10729 int iz = (int) gsl_stats_min_index(t2, 1, 171);
10730 if (iz > 0 && iz < 170)
10731 met->pt[ix][iy] = (float) p2[iz];
10732 else
10733 met->pt[ix][iy] = NAN;
10734 }
10735 }
10736
10737 /* Use WMO definition... */
10738 else if (ctl->met_tropo == 3 || ctl->met_tropo == 4) {
10739
10740 /* Loop over grid points... */
10741#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10742 for (int ix = 0; ix < met->nx; ix++)
10743 for (int iy = 0; iy < met->ny; iy++) {
10744
10745 /* Interpolate temperature profile... */
10746 int iz;
10747 for (iz = 0; iz < met->np; iz++)
10748 t[iz] = met->t[ix][iy][iz];
10749 spline(z, t, met->np, z2, t2, 191, ctl->met_tropo_spline);
10750
10751 /* Find 1st tropopause... */
10752 met->pt[ix][iy] = NAN;
10753 for (iz = 0; iz <= 170; iz++) {
10754 int found = 1;
10755 for (int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10756 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10757 found = 0;
10758 break;
10759 }
10760 if (found) {
10761 if (iz > 0 && iz < 170)
10762 met->pt[ix][iy] = (float) p2[iz];
10763 break;
10764 }
10765 }
10766
10767 /* Find 2nd tropopause... */
10768 if (ctl->met_tropo == 4) {
10769 met->pt[ix][iy] = NAN;
10770 for (; iz <= 170; iz++) {
10771 int found = 1;
10772 for (int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
10773 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
10774 found = 0;
10775 break;
10776 }
10777 if (found)
10778 break;
10779 }
10780 for (; iz <= 170; iz++) {
10781 int found = 1;
10782 for (int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10783 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10784 found = 0;
10785 break;
10786 }
10787 if (found) {
10788 if (iz > 0 && iz < 170)
10789 met->pt[ix][iy] = (float) p2[iz];
10790 break;
10791 }
10792 }
10793 }
10794 }
10795 }
10796
10797 /* Use dynamical tropopause... */
10798 else if (ctl->met_tropo == 5) {
10799
10800 /* Loop over grid points... */
10801#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
10802 for (int ix = 0; ix < met->nx; ix++)
10803 for (int iy = 0; iy < met->ny; iy++) {
10804
10805 /* Interpolate potential vorticity profile... */
10806 for (int iz = 0; iz < met->np; iz++)
10807 pv[iz] = met->pv[ix][iy][iz];
10808 spline(z, pv, met->np, z2, pv2, 171, ctl->met_tropo_spline);
10809
10810 /* Interpolate potential temperature profile... */
10811 for (int iz = 0; iz < met->np; iz++)
10812 th[iz] = THETA(met->p[iz], met->t[ix][iy][iz]);
10813 spline(z, th, met->np, z2, th2, 171, ctl->met_tropo_spline);
10814
10815 /* Find dynamical tropopause... */
10816 met->pt[ix][iy] = NAN;
10817 for (int iz = 0; iz <= 170; iz++)
10818 if (fabs(pv2[iz]) >= ctl->met_tropo_pv
10819 || th2[iz] >= ctl->met_tropo_theta) {
10820 if (iz > 0 && iz < 170)
10821 met->pt[ix][iy] = (float) p2[iz];
10822 break;
10823 }
10824 }
10825 }
10826
10827 else
10828 ERRMSG("Cannot calculate tropopause!");
10829
10830 /* Interpolate temperature, geopotential height, and water vapor... */
10831#pragma omp parallel for default(shared) collapse(2)
10832 for (int ix = 0; ix < met->nx; ix++)
10833 for (int iy = 0; iy < met->ny; iy++) {
10834 double h2ot, tt, zt;
10836 intpol_met_space_3d(met, met->t, met->pt[ix][iy], met->lon[ix],
10837 met->lat[iy], &tt, ci, cw, 1);
10838 intpol_met_space_3d(met, met->z, met->pt[ix][iy], met->lon[ix],
10839 met->lat[iy], &zt, ci, cw, 0);
10840 intpol_met_space_3d(met, met->h2o, met->pt[ix][iy], met->lon[ix],
10841 met->lat[iy], &h2ot, ci, cw, 0);
10842 met->tt[ix][iy] = (float) tt;
10843 met->zt[ix][iy] = (float) zt;
10844 met->h2ot[ix][iy] = (float) h2ot;
10845 }
10846}
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:11056
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
Definition: mptrac.h:991
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 10850 of file mptrac.c.

10858 {
10859
10860 /* Write info... */
10861 LOG(1, "Read observation data: %s", filename);
10862
10863 /* Read data... */
10864 if (ctl->obs_type == 0)
10865 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
10866 else if (ctl->obs_type == 1)
10867 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
10868 else
10869 ERRMSG("Set OBS_TYPE to 0 or 1!");
10870
10871 /* Check time... */
10872 for (int i = 1; i < *nobs; i++)
10873 if (rt[i] < rt[i - 1])
10874 ERRMSG("Time must be ascending!");
10875
10876 /* Write info... */
10877 int n = *nobs;
10878 double mini, maxi;
10879 LOG(2, "Number of observations: %d", *nobs);
10880 gsl_stats_minmax(&mini, &maxi, rt, 1, (size_t) n);
10881 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
10882 gsl_stats_minmax(&mini, &maxi, rz, 1, (size_t) n);
10883 LOG(2, "Altitude range: %g ... %g km", mini, maxi);
10884 gsl_stats_minmax(&mini, &maxi, rlon, 1, (size_t) n);
10885 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
10886 gsl_stats_minmax(&mini, &maxi, rlat, 1, (size_t) n);
10887 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
10888 gsl_stats_minmax(&mini, &maxi, robs, 1, (size_t) n);
10889 LOG(2, "Observation range: %g ... %g", mini, maxi);
10890}
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:10894
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:10922
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 10894 of file mptrac.c.

10901 {
10902
10903 /* Open observation data file... */
10904 FILE *in;
10905 if (!(in = fopen(filename, "r")))
10906 ERRMSG("Cannot open file!");
10907
10908 /* Read observations... */
10909 char line[LEN];
10910 while (fgets(line, LEN, in))
10911 if (sscanf(line, "%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
10912 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
10913 if ((++(*nobs)) >= NOBS)
10914 ERRMSG("Too many observations!");
10915
10916 /* Close observation data file... */
10917 fclose(in);
10918}
#define NOBS
Maximum number of observation data points.
Definition: mptrac.h:328

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

10929 {
10930
10931 int ncid, varid;
10932
10933 /* Open netCDF file... */
10934 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
10935 ERRMSG("Cannot open file!");
10936
10937 /* Read the observations from the NetCDF file... */
10938 NC_INQ_DIM("nobs", nobs, 1, NOBS, 1);
10939 NC_GET_DOUBLE("time", rt, 1);
10940 NC_GET_DOUBLE("alt", rz, 1);
10941 NC_GET_DOUBLE("lon", rlon, 1);
10942 NC_GET_DOUBLE("lat", rlat, 1);
10943 NC_GET_DOUBLE("obs", robs, 1);
10944
10945 /* Close file... */
10946 NC(nc_close(ncid));
10947}

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

10958 {
10959
10960 FILE *in = NULL;
10961
10962 char fullname1[LEN], fullname2[LEN], rval[LEN];
10963
10964 int contain = 0, i;
10965
10966 /* Open file... */
10967 if (filename[strlen(filename) - 1] != '-')
10968 if (!(in = fopen(filename, "r")))
10969 ERRMSG("Cannot open file!");
10970
10971 /* Set full variable name... */
10972 if (arridx >= 0) {
10973 sprintf(fullname1, "%s[%d]", varname, arridx);
10974 sprintf(fullname2, "%s[*]", varname);
10975 } else {
10976 sprintf(fullname1, "%s", varname);
10977 sprintf(fullname2, "%s", varname);
10978 }
10979
10980 /* Read data... */
10981 if (in != NULL) {
10982 char dummy[LEN], line[LEN], rvarname[LEN];
10983 while (fgets(line, LEN, in)) {
10984 if (sscanf(line, "%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
10985 if (strcasecmp(rvarname, fullname1) == 0 ||
10986 strcasecmp(rvarname, fullname2) == 0) {
10987 contain = 1;
10988 break;
10989 }
10990 }
10991 }
10992 for (i = 1; i < argc - 1; i++)
10993 if (strcasecmp(argv[i], fullname1) == 0 ||
10994 strcasecmp(argv[i], fullname2) == 0) {
10995 sprintf(rval, "%s", argv[i + 1]);
10996 contain = 1;
10997 break;
10998 }
10999
11000 /* Close file... */
11001 if (in != NULL)
11002 fclose(in);
11003
11004 /* Check for missing variables... */
11005 if (!contain) {
11006 if (strlen(defvalue) > 0)
11007 sprintf(rval, "%s", defvalue);
11008 else
11009 ERRMSG("Missing variable %s!\n", fullname1);
11010 }
11011
11012 /* Write info... */
11013 LOG(1, "%s = %s", fullname1, rval);
11014
11015 /* Return values... */
11016 if (value != NULL)
11017 sprintf(value, "%s", rval);
11018 return atof(rval);
11019}

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

11027 {
11028
11029 /* Convert particle radius from microns to m... */
11030 const double rp_help = rp * 1e-6;
11031
11032 /* Density of dry air [kg / m^3]... */
11033 const double rho = RHO(p, T);
11034
11035 /* Dynamic viscosity of air [kg / (m s)]... */
11036 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
11037
11038 /* Thermal velocity of an air molecule [m / s]... */
11039 const double v = sqrt(8. * KB * T / (M_PI * 4.8096e-26));
11040
11041 /* Mean free path of an air molecule [m]... */
11042 const double lambda = 2. * eta / (rho * v);
11043
11044 /* Knudsen number for air (dimensionless)... */
11045 const double K = lambda / rp_help;
11046
11047 /* Cunningham slip-flow correction (dimensionless)... */
11048 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
11049
11050 /* Sedimentation velocity [m / s]... */
11051 return 2. * SQR(rp_help) * (rhop - rho) * G0 / (9. * eta) * G;
11052}
#define KB
Boltzmann constant [kg m^2/(K s^2)].
Definition: mptrac.h:234

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

11063 {
11064
11065 /* Cubic spline interpolation... */
11066 if (method == 1) {
11067
11068 /* Allocate... */
11069 gsl_interp_accel *acc = gsl_interp_accel_alloc();
11070 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (size_t) n);
11071
11072 /* Interpolate profile... */
11073 gsl_spline_init(s, x, y, (size_t) n);
11074 for (int i = 0; i < n2; i++)
11075 if (x2[i] <= x[0])
11076 y2[i] = y[0];
11077 else if (x2[i] >= x[n - 1])
11078 y2[i] = y[n - 1];
11079 else
11080 y2[i] = gsl_spline_eval(s, x2[i], acc);
11081
11082 /* Free... */
11083 gsl_spline_free(s);
11084 gsl_interp_accel_free(acc);
11085 }
11086
11087 /* Linear interpolation... */
11088 else {
11089 for (int i = 0; i < n2; i++)
11090 if (x2[i] <= x[0])
11091 y2[i] = y[0];
11092 else if (x2[i] >= x[n - 1])
11093 y2[i] = y[n - 1];
11094 else {
11095 const int idx = locate_irr(x, n, x2[i]);
11096 y2[i] = LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
11097 }
11098 }
11099}
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 11103 of file mptrac.c.

11105 {
11106
11107 if (n <= 0)
11108 return 0;
11109
11110 float mean = 0, var = 0;
11111
11112 for (int i = 0; i < n; ++i) {
11113 mean += data[i];
11114 var += SQR(data[i]);
11115 }
11116
11117 var = var / (float) n - SQR(mean / (float) n);
11118
11119 return (var > 0 ? sqrtf(var) : 0);
11120}

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

11132 {
11133
11134 struct tm t0, t1;
11135
11136 t0.tm_year = 100;
11137 t0.tm_mon = 0;
11138 t0.tm_mday = 1;
11139 t0.tm_hour = 0;
11140 t0.tm_min = 0;
11141 t0.tm_sec = 0;
11142
11143 t1.tm_year = year - 1900;
11144 t1.tm_mon = mon - 1;
11145 t1.tm_mday = day;
11146 t1.tm_hour = hour;
11147 t1.tm_min = min;
11148 t1.tm_sec = sec;
11149
11150 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
11151}

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

11158 {
11159
11160 static char names[NTIMER][100], groups[NTIMER][100];
11161
11162 static double rt_name[NTIMER], rt_group[NTIMER],
11163 rt_min[NTIMER], rt_max[NTIMER], dt, t0, t1;
11164
11165 static int iname = -1, igroup = -1, nname, ngroup, ct_name[NTIMER];
11166
11167 /* Get time... */
11168 t1 = omp_get_wtime();
11169 dt = t1 - t0;
11170
11171 /* Add elapsed time to current timers... */
11172 if (iname >= 0) {
11173 rt_name[iname] += dt;
11174 rt_min[iname] = (ct_name[iname] <= 0 ? dt : MIN(rt_min[iname], dt));
11175 rt_max[iname] = (ct_name[iname] <= 0 ? dt : MAX(rt_max[iname], dt));
11176 ct_name[iname]++;
11177 }
11178 if (igroup >= 0)
11179 rt_group[igroup] += t1 - t0;
11180
11181 /* Report timers... */
11182 if (output) {
11183 for (int i = 0; i < nname; i++)
11184 LOG(1, "TIMER_%s = %.3f s (min= %g s, mean= %g s,"
11185 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
11186 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
11187 for (int i = 0; i < ngroup; i++)
11188 LOG(1, "TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
11189 double total = 0.0;
11190 for (int i = 0; i < nname; i++)
11191 total += rt_name[i];
11192 LOG(1, "TIMER_TOTAL = %.3f s", total);
11193 }
11194
11195 /* Identify IDs of next timer... */
11196 for (iname = 0; iname < nname; iname++)
11197 if (strcasecmp(name, names[iname]) == 0)
11198 break;
11199 for (igroup = 0; igroup < ngroup; igroup++)
11200 if (strcasecmp(group, groups[igroup]) == 0)
11201 break;
11202
11203 /* Check whether this is a new timer... */
11204 if (iname >= nname) {
11205 sprintf(names[iname], "%s", name);
11206 if ((++nname) >= NTIMER)
11207 ERRMSG("Too many timers!");
11208 }
11209
11210 /* Check whether this is a new group... */
11211 if (igroup >= ngroup) {
11212 sprintf(groups[igroup], "%s", group);
11213 if ((++ngroup) >= NTIMER)
11214 ERRMSG("Too many groups!");
11215 }
11216
11217 /* Save starting time... */
11218 t0 = t1;
11219}
#define NTIMER
Maximum number of timers.
Definition: mptrac.h:2087

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

11225 {
11226
11227 char tstr[10];
11228
11229 double t;
11230
11231 /* Get time from filename... */
11232 int len = (int) strlen(filename);
11233 sprintf(tstr, "%.4s", &filename[len - offset]);
11234 int year = atoi(tstr);
11235 sprintf(tstr, "%.2s", &filename[len - offset + 5]);
11236 int mon = atoi(tstr);
11237 sprintf(tstr, "%.2s", &filename[len - offset + 8]);
11238 int day = atoi(tstr);
11239 sprintf(tstr, "%.2s", &filename[len - offset + 11]);
11240 int hour = atoi(tstr);
11241 sprintf(tstr, "%.2s", &filename[len - offset + 14]);
11242 int min = atoi(tstr);
11243
11244 /* Check time... */
11245 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
11246 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
11247 ERRMSG("Cannot read time from filename!");
11248
11249 /* Convert time to Julian seconds... */
11250 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
11251
11252 /* Return time... */
11253 return t;
11254}
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 11258 of file mptrac.c.

11261 {
11262
11263 /* Get tropopause pressure... */
11264 const double pt = clim_tropo(clim, atm->time[ip], atm->lat[ip]);
11265
11266 /* Get pressure range... */
11267 const double p1 = pt * 0.866877899;
11268 const double p0 = pt / 0.866877899;
11269
11270 /* Get weighting factor... */
11271 if (atm->p[ip] > p0)
11272 return 1;
11273 else if (atm->p[ip] < p1)
11274 return 0;
11275 else
11276 return LIN(p0, 1.0, p1, 0.0, atm->p[ip]);
11277}
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 11281 of file mptrac.c.

11285 {
11286
11287 FILE *out;
11288
11289 /* Set time interval for output... */
11290 const double t0 = t - 0.5 * ctl->dt_mod;
11291 const double t1 = t + 0.5 * ctl->dt_mod;
11292
11293 /* Check if gnuplot output is requested... */
11294 if (ctl->atm_gpfile[0] != '-') {
11295
11296 /* Create gnuplot pipe... */
11297 if (!(out = popen("gnuplot", "w")))
11298 ERRMSG("Cannot create pipe to gnuplot!");
11299
11300 /* Set plot filename... */
11301 fprintf(out, "set out \"%s.png\"\n", filename);
11302
11303 /* Set time string... */
11304 double r;
11305 int year, mon, day, hour, min, sec;
11306 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11307 fprintf(out, "timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
11308 year, mon, day, hour, min);
11309
11310 /* Dump gnuplot file to pipe... */
11311 FILE *in;
11312 if (!(in = fopen(ctl->atm_gpfile, "r")))
11313 ERRMSG("Cannot open file!");
11314 char line[LEN];
11315 while (fgets(line, LEN, in))
11316 fprintf(out, "%s", line);
11317 fclose(in);
11318 }
11319
11320 else {
11321
11322 /* Create file... */
11323 if (!(out = fopen(filename, "w")))
11324 ERRMSG("Cannot create file!");
11325 }
11326
11327 /* Write header... */
11328 fprintf(out,
11329 "# $1 = time [s]\n"
11330 "# $2 = altitude [km]\n"
11331 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11332 for (int iq = 0; iq < ctl->nq; iq++)
11333 fprintf(out, "# $%i = %s [%s]\n", iq + 5, ctl->qnt_name[iq],
11334 ctl->qnt_unit[iq]);
11335 fprintf(out, "\n");
11336
11337 /* Write data... */
11338 for (int ip = 0; ip < atm->np; ip += ctl->atm_stride) {
11339
11340 /* Check time... */
11341 if (ctl->atm_filter == 2 && (atm->time[ip] < t0 || atm->time[ip] > t1))
11342 continue;
11343
11344 /* Write output... */
11345 fprintf(out, "%.2f %g %g %g", atm->time[ip], Z(atm->p[ip]),
11346 atm->lon[ip], atm->lat[ip]);
11347 for (int iq = 0; iq < ctl->nq; iq++) {
11348 fprintf(out, " ");
11349 if (ctl->atm_filter == 1 && (atm->time[ip] < t0 || atm->time[ip] > t1))
11350 fprintf(out, ctl->qnt_format[iq], NAN);
11351 else
11352 fprintf(out, ctl->qnt_format[iq], atm->q[iq][ip]);
11353 }
11354 fprintf(out, "\n");
11355 }
11356
11357 /* Close file... */
11358 fclose(out);
11359}
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 11363 of file mptrac.c.

11366 {
11367
11368 FILE *out;
11369
11370 /* Create file... */
11371 if (!(out = fopen(filename, "w")))
11372 ERRMSG("Cannot create file!");
11373
11374 /* Write version of binary data... */
11375 int version = 100;
11376 FWRITE(&version, int,
11377 1,
11378 out);
11379
11380 /* Write data... */
11381 FWRITE(&atm->np, int,
11382 1,
11383 out);
11384 FWRITE(atm->time, double,
11385 (size_t) atm->np,
11386 out);
11387 FWRITE(atm->p, double,
11388 (size_t) atm->np,
11389 out);
11390 FWRITE(atm->lon, double,
11391 (size_t) atm->np,
11392 out);
11393 FWRITE(atm->lat, double,
11394 (size_t) atm->np,
11395 out);
11396 for (int iq = 0; iq < ctl->nq; iq++)
11397 FWRITE(atm->q[iq], double,
11398 (size_t) atm->np,
11399 out);
11400
11401 /* Write final flag... */
11402 int final = 999;
11403 FWRITE(&final, int,
11404 1,
11405 out);
11406
11407 /* Close file... */
11408 fclose(out);
11409}

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

11416 {
11417
11418 int tid, pid, ncid, varid;
11419 size_t start[2], count[2];
11420
11421 /* Create file... */
11422 NC(nc_create(filename, NC_NETCDF4, &ncid));
11423
11424 /* Define dimensions... */
11425 NC(nc_def_dim(ncid, "time", 1, &tid));
11426 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
11427
11428 /* Define variables and their attributes... */
11429 int dim_ids[2] = { tid, pid };
11430 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
11431 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
11432 NC_DEF_VAR("LAT", NC_DOUBLE, 1, &pid, "Latitude", "deg",
11433 ctl->atm_nc_level, 0);
11434 NC_DEF_VAR("LON", NC_DOUBLE, 1, &pid, "Longitude", "deg",
11435 ctl->atm_nc_level, 0);
11436 NC_DEF_VAR("PRESS", NC_DOUBLE, 1, &pid, "Pressure", "hPa",
11437 ctl->atm_nc_level, 0);
11438 NC_DEF_VAR("ZETA", NC_DOUBLE, 1, &pid, "Zeta", "K", ctl->atm_nc_level, 0);
11439 for (int iq = 0; iq < ctl->nq; iq++)
11440 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
11441 ctl->qnt_name[iq], ctl->qnt_unit[iq],
11442 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
11443
11444 /* Define global attributes... */
11445 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
11446 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
11447
11448 /* End definitions... */
11449 NC(nc_enddef(ncid));
11450
11451 /* Write data... */
11452 NC_PUT_DOUBLE("time", atm->time, 0);
11453 NC_PUT_DOUBLE("LAT", atm->lat, 0);
11454 NC_PUT_DOUBLE("LON", atm->lon, 0);
11455 NC_PUT_DOUBLE("PRESS", atm->p, 0);
11456 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 0);
11457 for (int iq = 0; iq < ctl->nq; iq++)
11458 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
11459
11460 /* Close file... */
11461 NC(nc_close(ncid));
11462}
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
Definition: mptrac.h:1366
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units, level, quant)
Define a NetCDF variable with attributes.
Definition: mptrac.h:1196
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
Write double precision data to a NetCDF variable.
Definition: mptrac.h:1280

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

11470 {
11471
11472 /* Global Counter... */
11473 static size_t out_cnt = 0;
11474
11475 double r, r_start, r_stop;
11476 int year, mon, day, hour, min, sec;
11477 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
11478 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
11479 char filename_out[2 * LEN] = "traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
11480
11481 int ncid, varid, tid, pid, cid;
11482 int dim_ids[2];
11483
11484 /* time, nparc */
11485 size_t start[2];
11486 size_t count[2];
11487
11488 /* Determine start and stop times of calculation... */
11489 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11490 jsec2time(ctl->t_start, &year_start, &mon_start, &day_start, &hour_start,
11491 &min_start, &sec_start, &r_start);
11492 jsec2time(ctl->t_stop, &year_stop, &mon_stop, &day_stop, &hour_stop,
11493 &min_stop, &sec_stop, &r_stop);
11494
11495 sprintf(filename_out,
11496 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
11497 year_start % 100, mon_start, day_start, hour_start,
11498 year_stop % 100, mon_stop, day_stop, hour_stop);
11499 LOG(1, "Write traj file: %s", filename_out);
11500
11501 /* Define hyperslap for the traj_file... */
11502 start[0] = out_cnt;
11503 start[1] = 0;
11504 count[0] = 1;
11505 count[1] = (size_t) atm->np;
11506
11507 /* Create the file at the first timestep... */
11508 if (out_cnt == 0) {
11509
11510 /* Create file... */
11511 NC(nc_create(filename_out, NC_NETCDF4, &ncid));
11512
11513 /* Define dimensions... */
11514 NC(nc_def_dim(ncid, "time", NC_UNLIMITED, &tid));
11515 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
11516 NC(nc_def_dim(ncid, "TMDT", 7, &cid));
11517 dim_ids[0] = tid;
11518 dim_ids[1] = pid;
11519
11520 /* Define variables and their attributes... */
11521 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
11522 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
11523 NC_DEF_VAR("LAT", NC_DOUBLE, 2, dim_ids, "Latitude", "deg",
11524 ctl->atm_nc_level, 0);
11525 NC_DEF_VAR("LON", NC_DOUBLE, 2, dim_ids, "Longitude", "deg",
11526 ctl->atm_nc_level, 0);
11527 NC_DEF_VAR("PRESS", NC_DOUBLE, 2, dim_ids, "Pressure", "hPa",
11528 ctl->atm_nc_level, 0);
11529 NC_DEF_VAR("ZETA", NC_DOUBLE, 2, dim_ids, "Zeta", "K",
11530 ctl->atm_nc_level, 0);
11531 for (int iq = 0; iq < ctl->nq; iq++)
11532 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
11533 ctl->qnt_name[iq], ctl->qnt_unit[iq],
11534 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
11535
11536 /* Define global attributes... */
11537 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
11538 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
11539
11540 /* End definitions... */
11541 NC(nc_enddef(ncid));
11542 NC(nc_close(ncid));
11543 }
11544
11545 /* Increment global counter to change hyperslap... */
11546 out_cnt++;
11547
11548 /* Open file... */
11549 NC(nc_open(filename_out, NC_WRITE, &ncid));
11550
11551 /* Write data... */
11552 NC_PUT_DOUBLE("time", atm->time, 1);
11553 NC_PUT_DOUBLE("LAT", atm->lat, 1);
11554 NC_PUT_DOUBLE("LON", atm->lon, 1);
11555 NC_PUT_DOUBLE("PRESS", atm->p, 1);
11556 if (ctl->advect_vert_coord == 1) {
11557 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta], 1);
11558 } else if (ctl->qnt_zeta >= 0) {
11559 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 1);
11560 }
11561 for (int iq = 0; iq < ctl->nq; iq++)
11562 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 1);
11563
11564 /* Close file... */
11565 NC(nc_close(ncid));
11566
11567 /* At the last time step create the init_fix_YYYYMMDDHH file... */
11568 if ((year == year_stop) && (mon == mon_stop)
11569 && (day == day_stop) && (hour == hour_stop)) {
11570
11571 /* Set filename... */
11572 char filename_init[2 * LEN] = "./init_fix_YYYYMMDDHH.nc";
11573 sprintf(filename_init, "%s/init_fix_%02d%02d%02d%02d.nc",
11574 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
11575 LOG(1, "Write init file: %s", filename_init);
11576
11577 /* Create file... */
11578 NC(nc_create(filename_init, NC_NETCDF4, &ncid));
11579
11580 /* Define dimensions... */
11581 NC(nc_def_dim(ncid, "time", 1, &tid));
11582 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
11583 dim_ids[0] = tid;
11584 dim_ids[1] = pid;
11585
11586 /* Define variables and their attributes... */
11587 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
11588 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
11589 NC_DEF_VAR("LAT", NC_DOUBLE, 1, &pid, "Latitude", "deg",
11590 ctl->atm_nc_level, 0);
11591 NC_DEF_VAR("LON", NC_DOUBLE, 1, &pid, "Longitude", "deg",
11592 ctl->atm_nc_level, 0);
11593 NC_DEF_VAR("PRESS", NC_DOUBLE, 1, &pid, "Pressure", "hPa",
11594 ctl->atm_nc_level, 0);
11595 NC_DEF_VAR("ZETA", NC_DOUBLE, 1, &pid, "Zeta", "K", ctl->atm_nc_level, 0);
11596 for (int iq = 0; iq < ctl->nq; iq++)
11597 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
11598 ctl->qnt_name[iq], ctl->qnt_unit[iq],
11599 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
11600
11601 /* Define global attributes... */
11602 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
11603 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
11604
11605 /* End definitions... */
11606 NC(nc_enddef(ncid));
11607
11608 /* Write data... */
11609 NC_PUT_DOUBLE("time", atm->time, 0);
11610 NC_PUT_DOUBLE("LAT", atm->lat, 0);
11611 NC_PUT_DOUBLE("LON", atm->lon, 0);
11612 NC_PUT_DOUBLE("PRESS", atm->p, 0);
11613 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 0);
11614 for (int iq = 0; iq < ctl->nq; iq++)
11615 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
11616
11617 /* Close file... */
11618 NC(nc_close(ncid));
11619 }
11620}
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 11624 of file mptrac.c.

11627 {
11628
11629 int ncid, obsid, varid;
11630
11631 size_t start[2], count[2];
11632
11633 /* Create file... */
11634 NC(nc_create(filename, NC_NETCDF4, &ncid));
11635
11636 /* Define dimensions... */
11637 NC(nc_def_dim(ncid, "obs", (size_t) atm->np, &obsid));
11638
11639 /* Define variables and their attributes... */
11640 NC_DEF_VAR("time", NC_DOUBLE, 1, &obsid, "time",
11641 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
11642 NC_DEF_VAR("press", NC_DOUBLE, 1, &obsid, "pressure", "hPa",
11643 ctl->atm_nc_level, 0);
11644 NC_DEF_VAR("lon", NC_DOUBLE, 1, &obsid, "longitude", "degrees_east",
11645 ctl->atm_nc_level, 0);
11646 NC_DEF_VAR("lat", NC_DOUBLE, 1, &obsid, "latitude", "degrees_north",
11647 ctl->atm_nc_level, 0);
11648 for (int iq = 0; iq < ctl->nq; iq++)
11649 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 1, &obsid,
11650 ctl->qnt_longname[iq], ctl->qnt_unit[iq],
11651 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
11652
11653 /* Define global attributes... */
11654 NC_PUT_ATT_GLOBAL("featureType", "point");
11655
11656 /* End definitions... */
11657 NC(nc_enddef(ncid));
11658
11659 /* Write data... */
11660 NC_PUT_DOUBLE("time", atm->time, 0);
11661 NC_PUT_DOUBLE("press", atm->p, 0);
11662 NC_PUT_DOUBLE("lon", atm->lon, 0);
11663 NC_PUT_DOUBLE("lat", atm->lat, 0);
11664 for (int iq = 0; iq < ctl->nq; iq++)
11665 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
11666
11667 /* Close file... */
11668 NC(nc_close(ncid));
11669}

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

11677 {
11678
11679 static FILE *out;
11680
11681 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
11682 *area, dlon, dlat, dz, x[NCSI], y[NCSI], obsstdn[NCSI], kz[EP], kw[EP];
11683
11684 static int *obscount, nobs, nk;
11685
11686 static int ct[NENS], cx[NENS], cy[NENS], cz[NENS], n[NENS];
11687
11688 const int ensemble = (ctl->nens > 0);
11689
11690 /* Set timer */
11691 SELECT_TIMER("WRITE_CSI", "OUTPUT", NVTX_WRITE);
11692
11693 /* Check quantities... */
11694 if (ctl->qnt_m < 0)
11695 ERRMSG("Need quantity mass!");
11696 if (ensemble) {
11697 if (ctl->qnt_ens < 0)
11698 ERRMSG("Missing ensemble IDs!");
11699 if (ctl->nens > NENS)
11700 ERRMSG("Too many ensembles!");
11701 }
11702
11703 /* Init... */
11704 if (t == ctl->t_start) {
11705
11706 /* Allocate.. */
11707 ALLOC(area, double,
11708 ctl->csi_ny);
11709 ALLOC(rt, double,
11710 NOBS);
11711 ALLOC(rz, double,
11712 NOBS);
11713 ALLOC(rlon, double,
11714 NOBS);
11715 ALLOC(rlat, double,
11716 NOBS);
11717 ALLOC(robs, double,
11718 NOBS);
11719
11720 /* Read observation data... */
11721 read_obs(ctl->csi_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
11722
11723 /* Read kernel data... */
11724 if (ctl->csi_kernel[0] != '-')
11725 read_kernel(ctl->csi_kernel, kz, kw, &nk);
11726
11727 /* Create new file... */
11728 LOG(1, "Write CSI%s data: %s", ensemble ? " ensemble" : "", filename);
11729 if (!(out = fopen(filename, "w")))
11730 ERRMSG("Cannot create file!");
11731
11732 /* Write header... */
11733 fprintf(out,
11734 "# $1 = time [s]\n"
11735 "# $2 = ensemble ID\n"
11736 "# $3 = number of hits (cx)\n"
11737 "# $4 = number of misses (cy)\n"
11738 "# $5 = number of false alarms (cz)\n"
11739 "# $6 = number of observations (cx + cy)\n"
11740 "# $7 = number of forecasts (cx + cz)\n"
11741 "# $8 = bias (%%)\n"
11742 "# $9 = POD (%%)\n"
11743 "# $10 = FAR (%%)\n"
11744 "# $11 = CSI (%%)\n"
11745 "# $12 = hits by random chance\n"
11746 "# $13 = ETS (%%)\n"
11747 "# $14 = Pearson R\n"
11748 "# $15 = Spearman R\n"
11749 "# $16 = mean error [kg/m²]\n"
11750 "# $17 = RMSE [kg/m²]\n"
11751 "# $18 = MAE [kg/m²]\n"
11752 "# $19 = log-likelihood\n" "# $20 = number of points\n\n");
11753
11754 /* Set grid box size... */
11755 dz = (ctl->csi_z1 - ctl->csi_z0) / ctl->csi_nz;
11756 dlon = (ctl->csi_lon1 - ctl->csi_lon0) / ctl->csi_nx;
11757 dlat = (ctl->csi_lat1 - ctl->csi_lat0) / ctl->csi_ny;
11758
11759 /* Set horizontal coordinates... */
11760 for (int iy = 0; iy < ctl->csi_ny; iy++) {
11761 const double lat = ctl->csi_lat0 + dlat * (iy + 0.5);
11762 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.0) * cos(DEG2RAD(lat));
11763 }
11764 }
11765
11766 /* Set time interval... */
11767 const double t0 = t - 0.5 * ctl->dt_mod;
11768 const double t1 = t + 0.5 * ctl->dt_mod;
11769
11770 /* Allocate... */
11771 int grid_size = ctl->csi_nx * ctl->csi_ny * ctl->csi_nz;
11772 ALLOC(modmean, double,
11773 (ensemble ? ctl->nens : 1) * grid_size);
11774 ALLOC(obsmean, double,
11775 grid_size);
11776 ALLOC(obscount, int,
11777 grid_size);
11778 ALLOC(obsstd, double,
11779 grid_size);
11780
11781 /* Init... */
11782 for (int i = 0; i < (ensemble ? ctl->nens : 1); i++)
11783 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
11784
11785 /* Loop over observations... */
11786 for (int i = 0; i < nobs; i++) {
11787 if (rt[i] < t0 || rt[i] >= t1 || !isfinite(robs[i]))
11788 continue;
11789
11790 /* Calculate indices... */
11791 const int ix = (int) ((rlon[i] - ctl->csi_lon0) / dlon);
11792 const int iy = (int) ((rlat[i] - ctl->csi_lat0) / dlat);
11793 const int iz = (int) ((rz[i] - ctl->csi_z0) / dz);
11794 if (ix < 0 || ix >= ctl->csi_nx || iy < 0 || iy >= ctl->csi_ny || iz < 0
11795 || iz >= ctl->csi_nz)
11796 continue;
11797
11798 /* Get mean observation index... */
11799 const int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
11800 obsmean[idx] += robs[i];
11801 obsstd[idx] += SQR(robs[i]);
11802 obscount[idx]++;
11803 }
11804
11805 /* Analyze model data... */
11806 for (int ip = 0; ip < atm->np; ip++) {
11807
11808 /* Check time... */
11809 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11810 continue;
11811
11812 /* Get ensemble ID... */
11813 int ens_id = ensemble ? (int) atm->q[ctl->qnt_ens][ip] : 0;
11814 if (ens_id < 0 || ens_id >= (ensemble ? ctl->nens : 1))
11815 ERRMSG("Ensemble ID out of range!");
11816
11817 /* Get indices... */
11818 const int ix = (int) ((atm->lon[ip] - ctl->csi_lon0) / dlon);
11819 const int iy = (int) ((atm->lat[ip] - ctl->csi_lat0) / dlat);
11820 const int iz = (int) ((Z(atm->p[ip]) - ctl->csi_z0) / dz);
11821 if (ix < 0 || ix >= ctl->csi_nx || iy < 0 || iy >= ctl->csi_ny || iz < 0
11822 || iz >= ctl->csi_nz)
11823 continue;
11824
11825 /* Get total mass in grid cell... */
11826 const int idx =
11827 ens_id * grid_size + ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
11828 modmean[idx] +=
11829 kernel_weight(kz, kw, nk, atm->p[ip]) * atm->q[ctl->qnt_m][ip];
11830 }
11831 for (int e = 0; e < (ensemble ? ctl->nens : 1); e++) {
11832 /* Analyze all grid cells... */
11833 for (int ix = 0; ix < ctl->csi_nx; ix++)
11834 for (int iy = 0; iy < ctl->csi_ny; iy++)
11835 for (int iz = 0; iz < ctl->csi_nz; iz++) {
11836
11837 /* Calculate mean observation index... */
11838 const int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
11839 if (e == 0)
11840 if (obscount[idx]) {
11841 obsmean[idx] /= obscount[idx];
11842 obsstd[idx] =
11843 sqrt(obsstd[idx] / obscount[idx] - SQR(obsmean[idx]));
11844 }
11845
11846 /* Calculate model mean per ensemble... */
11847 const int midx = e * grid_size + idx;
11848 if (modmean[midx] > 0)
11849 modmean[midx] /= (1e6 * area[iy]);
11850
11851 /* Check number of observations... */
11852 if (obscount[idx]) {
11853
11854 /* Calculate CSI... */
11855 ct[e]++;
11856 if (obsmean[idx] >= ctl->csi_obsmin
11857 && modmean[midx] >= ctl->csi_modmin)
11858 cx[e]++;
11859 else if (obsmean[idx] >= ctl->csi_obsmin)
11860 cy[e]++;
11861 else if (modmean[midx] >= ctl->csi_modmin)
11862 cz[e]++;
11863
11864 /* Save data for other verification statistics... */
11865 if (obsmean[idx] >= ctl->csi_obsmin
11866 || modmean[midx] >= ctl->csi_modmin) {
11867 x[n[e]] = modmean[midx];
11868 y[n[e]] = obsmean[idx];
11869 if (modmean[midx] >= ctl->csi_modmin)
11870 obsstdn[n[e]] = obsstd[idx];
11871 if ((++n[e]) >= NCSI)
11872 ERRMSG("Too many points for statistics!");
11873 }
11874 }
11875 }
11876 /* Write output... */
11877 if (fmod(t, ctl->csi_dt_out) == 0) {
11878
11879 if (n[e] == 0)
11880 continue;
11881
11882 /* Calculate verification statistics
11883 (https://www.cawcr.gov.au/projects/verification/) ... */
11884 static double work[2 * NCSI], work2[2 * NCSI];
11885 const int n_obs = cx[e] + cy[e];
11886 const int n_for = cx[e] + cz[e];
11887 const double cx_rd = (ct[e] > 0) ? (1. * n_obs * n_for) / ct[e] : NAN;
11888 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
11889 const double pod = (n_obs > 0) ? 100. * cx[e] / n_obs : NAN;
11890 const double far = (n_for > 0) ? 100. * cz[e] / n_for : NAN;
11891 const double csi =
11892 (cx[e] + cy[e] + cz[e] >
11893 0) ? 100. * cx[e] / (cx[e] + cy[e] + cz[e]) : NAN;
11894 const double ets =
11895 (cx[e] + cy[e] + cz[e] - cx_rd >
11896 0) ? 100. * (cx[e] - cx_rd) / (cx[e] + cy[e] + cz[e] - cx_rd) : NAN;
11897 const double rho_p = gsl_stats_correlation(x, 1, y, 1, (size_t) n[e]);
11898 const double rho_s =
11899 gsl_stats_spearman(x, 1, y, 1, (size_t) n[e], work);
11900 for (int i = 0; i < n[e]; i++) {
11901 work[i] = x[i] - y[i];
11902 work2[i] = (obsstdn[i] != 0) ? work[i] / obsstdn[i] : 0;
11903 }
11904 const double mean = gsl_stats_mean(work, 1, (size_t) n[e]);
11905 const double rmse =
11906 gsl_stats_sd_with_fixed_mean(work, 1, (size_t) n[e], 0.0);
11907 const double absdev = gsl_stats_absdev_m(work, 1, (size_t) n[e], 0.0);
11908 const double loglikelihood =
11909 gsl_stats_tss_m(work2, 1, (size_t) n[e], 0.0) * -0.5;
11910
11911 /* Write... */
11912 fprintf(out,
11913 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
11914 t, ensemble ? e : -999, cx[e], cy[e], cz[e], n_obs, n_for, bias,
11915 pod, far, csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
11916 loglikelihood, n[e]);
11917
11918 /* Set counters to zero... */
11919 for (int i = 0; i < n[e]; i++)
11920 work[i] = work2[i] = x[i] = y[i] = obsstdn[i] = 0;
11921 ct[e] = cx[e] = cy[e] = cz[e] = n[e] = 0;
11922 }
11923 }
11924 /* Free... */
11925 free(modmean);
11926 free(obsmean);
11927 free(obscount);
11928 free(obsstd);
11929
11930 /* Finalize... */
11931 if (t == ctl->t_stop) {
11932
11933 /* Close output file... */
11934 fclose(out);
11935
11936 /* Free... */
11937 free(area);
11938 free(rt);
11939 free(rz);
11940 free(rlon);
11941 free(rlat);
11942 free(robs);
11943 }
11944}
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:10850
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:7482
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:2615
#define NENS
Maximum number of data points for ensemble analysis.
Definition: mptrac.h:323
#define NCSI
Maximum number of data points for CSI calculation.
Definition: mptrac.h:318
Here is the call graph for this function:

◆ write_csi_ens()

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

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

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

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

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

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

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

◆ write_ens()

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

Writes ensemble data to a file.

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

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

The function performs the following steps:

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

Definition at line 11948 of file mptrac.c.

11952 {
11953
11954 static FILE *out;
11955
11956 static double dummy, lat, lon, qm[NQ][NENS], qs[NQ][NENS], xm[NENS][3],
11957 x[3], zm[NENS];
11958
11959 static int n[NENS];
11960
11961 /* Set timer... */
11962 SELECT_TIMER("WRITE_ENS", "OUTPUT", NVTX_WRITE);
11963
11964 /* Check quantities... */
11965 if (ctl->qnt_ens < 0)
11966 ERRMSG("Missing ensemble IDs!");
11967
11968 /* Set time interval... */
11969 const double t0 = t - 0.5 * ctl->dt_mod;
11970 const double t1 = t + 0.5 * ctl->dt_mod;
11971
11972 /* Init... */
11973 for (int i = 0; i < NENS; i++) {
11974 for (int iq = 0; iq < ctl->nq; iq++)
11975 qm[iq][i] = qs[iq][i] = 0;
11976 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
11977 n[i] = 0;
11978 }
11979
11980 /* Loop over air parcels... */
11981 for (int ip = 0; ip < atm->np; ip++) {
11982
11983 /* Check time... */
11984 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11985 continue;
11986
11987 /* Check ensemble ID... */
11988 if (atm->q[ctl->qnt_ens][ip] < 0 || atm->q[ctl->qnt_ens][ip] >= NENS)
11989 ERRMSG("Ensemble ID is out of range!");
11990
11991 /* Get means... */
11992 geo2cart(0, atm->lon[ip], atm->lat[ip], x);
11993 for (int iq = 0; iq < ctl->nq; iq++) {
11994 qm[iq][ctl->qnt_ens] += atm->q[iq][ip];
11995 qs[iq][ctl->qnt_ens] += SQR(atm->q[iq][ip]);
11996 }
11997 xm[ctl->qnt_ens][0] += x[0];
11998 xm[ctl->qnt_ens][1] += x[1];
11999 xm[ctl->qnt_ens][2] += x[2];
12000 zm[ctl->qnt_ens] += Z(atm->p[ip]);
12001 n[ctl->qnt_ens]++;
12002 }
12003
12004 /* Create file... */
12005 LOG(1, "Write ensemble data: %s", filename);
12006 if (!(out = fopen(filename, "w")))
12007 ERRMSG("Cannot create file!");
12008
12009 /* Write header... */
12010 fprintf(out,
12011 "# $1 = time [s]\n"
12012 "# $2 = altitude [km]\n"
12013 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
12014 for (int iq = 0; iq < ctl->nq; iq++)
12015 fprintf(out, "# $%d = %s (mean) [%s]\n", 5 + iq,
12016 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
12017 for (int iq = 0; iq < ctl->nq; iq++)
12018 fprintf(out, "# $%d = %s (sigma) [%s]\n", 5 + ctl->nq + iq,
12019 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
12020 fprintf(out, "# $%d = number of members\n\n", 5 + 2 * ctl->nq);
12021
12022 /* Write data... */
12023 for (int i = 0; i < NENS; i++)
12024 if (n[i] > 0) {
12025 cart2geo(xm[i], &dummy, &lon, &lat);
12026 fprintf(out, "%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
12027 for (int iq = 0; iq < ctl->nq; iq++) {
12028 fprintf(out, " ");
12029 fprintf(out, ctl->qnt_format[iq], qm[iq][i] / n[i]);
12030 }
12031 for (int iq = 0; iq < ctl->nq; iq++) {
12032 fprintf(out, " ");
12033 double var = qs[iq][i] / n[i] - SQR(qm[iq][i] / n[i]);
12034 fprintf(out, ctl->qnt_format[iq], (var > 0 ? sqrt(var) : 0));
12035 }
12036 fprintf(out, " %d\n", n[i]);
12037 }
12038
12039 /* Close file... */
12040 fclose(out);
12041}
void cart2geo(const double *x, double *z, double *lon, double *lat)
State variables of cuRAND random number generator.
Definition: mptrac.c:74
Here is the call graph for this function:

◆ write_grid()

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

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

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

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

The function performs the following steps:

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

Definition at line 12045 of file mptrac.c.

12051 {
12052
12053 static double kz[EP], kw[EP];
12054
12055 static int nk;
12056
12057 double *cd, *mean[NQ], *sigma[NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
12058
12059 int *ixs, *iys, *izs, *np;
12060
12061 /* Set timer... */
12062 SELECT_TIMER("WRITE_GRID", "OUTPUT", NVTX_WRITE);
12063
12064 /* Write info... */
12065 LOG(1, "Write grid data: %s", filename);
12066
12067 /* Init... */
12068 if (t == ctl->t_start) {
12069
12070 /* Read kernel data... */
12071 if (ctl->grid_kernel[0] != '-')
12072 read_kernel(ctl->grid_kernel, kz, kw, &nk);
12073 }
12074
12075 /* Allocate... */
12076 ALLOC(cd, double,
12077 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
12078 for (int iq = 0; iq < ctl->nq; iq++) {
12079 ALLOC(mean[iq], double,
12080 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
12081 ALLOC(sigma[iq], double,
12082 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
12083 }
12084 ALLOC(vmr_impl, double,
12085 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
12086 ALLOC(z, double,
12087 ctl->grid_nz);
12088 ALLOC(lon, double,
12089 ctl->grid_nx);
12090 ALLOC(lat, double,
12091 ctl->grid_ny);
12092 ALLOC(area, double,
12093 ctl->grid_ny);
12094 ALLOC(press, double,
12095 ctl->grid_nz);
12096 ALLOC(np, int,
12097 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
12098 ALLOC(ixs, int,
12099 atm->np);
12100 ALLOC(iys, int,
12101 atm->np);
12102 ALLOC(izs, int,
12103 atm->np);
12104
12105 /* Set grid box size... */
12106 const double dz = (ctl->grid_z1 - ctl->grid_z0) / ctl->grid_nz;
12107 const double dlon = (ctl->grid_lon1 - ctl->grid_lon0) / ctl->grid_nx;
12108 const double dlat = (ctl->grid_lat1 - ctl->grid_lat0) / ctl->grid_ny;
12109
12110 /* Set vertical coordinates... */
12111#pragma omp parallel for default(shared)
12112 for (int iz = 0; iz < ctl->grid_nz; iz++) {
12113 z[iz] = ctl->grid_z0 + dz * (iz + 0.5);
12114 press[iz] = P(z[iz]);
12115 }
12116
12117 /* Set horizontal coordinates... */
12118 for (int ix = 0; ix < ctl->grid_nx; ix++)
12119 lon[ix] = ctl->grid_lon0 + dlon * (ix + 0.5);
12120#pragma omp parallel for default(shared)
12121 for (int iy = 0; iy < ctl->grid_ny; iy++) {
12122 lat[iy] = ctl->grid_lat0 + dlat * (iy + 0.5);
12123 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
12124 }
12125
12126 /* Set time interval for output... */
12127 const double t0 = t - 0.5 * ctl->dt_mod;
12128 const double t1 = t + 0.5 * ctl->dt_mod;
12129
12130 /* Get grid box indices... */
12131#pragma omp parallel for default(shared)
12132 for (int ip = 0; ip < atm->np; ip++) {
12133 ixs[ip] = (int) ((atm->lon[ip] - ctl->grid_lon0) / dlon);
12134 iys[ip] = (int) ((atm->lat[ip] - ctl->grid_lat0) / dlat);
12135 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->grid_z0) / dz);
12136 if (atm->time[ip] < t0 || atm->time[ip] > t1
12137 || ixs[ip] < 0 || ixs[ip] >= ctl->grid_nx
12138 || iys[ip] < 0 || iys[ip] >= ctl->grid_ny
12139 || izs[ip] < 0 || izs[ip] >= ctl->grid_nz)
12140 izs[ip] = -1;
12141 }
12142
12143 /* Average data... */
12144 for (int ip = 0; ip < atm->np; ip++)
12145 if (izs[ip] >= 0) {
12146 const int idx =
12147 ARRAY_3D(ixs[ip], iys[ip], ctl->grid_ny, izs[ip], ctl->grid_nz);
12148 const double kernel = kernel_weight(kz, kw, nk, atm->p[ip]);
12149 np[idx]++;
12150 for (int iq = 0; iq < ctl->nq; iq++) {
12151 mean[iq][idx] += kernel * atm->q[iq][ip];
12152 sigma[iq][idx] += SQR(kernel * atm->q[iq][ip]);
12153 }
12154 }
12155
12156 /* Calculate column density and volume mixing ratio... */
12157#pragma omp parallel for default(shared)
12158 for (int ix = 0; ix < ctl->grid_nx; ix++)
12159 for (int iy = 0; iy < ctl->grid_ny; iy++)
12160 for (int iz = 0; iz < ctl->grid_nz; iz++) {
12161
12162 /* Get grid index... */
12163 const int idx = ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz);
12164
12165 /* Calculate column density... */
12166 cd[idx] = NAN;
12167 if (ctl->qnt_m >= 0)
12168 cd[idx] = mean[ctl->qnt_m][idx] / (1e6 * area[iy]);
12169
12170 /* Calculate volume mixing ratio (implicit)... */
12171 vmr_impl[idx] = NAN;
12172 if (ctl->qnt_m >= 0 && ctl->molmass > 0 && met0 != NULL
12173 && met1 != NULL) {
12174 vmr_impl[idx] = 0;
12175 if (mean[ctl->qnt_m][idx] > 0) {
12176
12177 /* Get temperature... */
12178 double temp;
12180 intpol_met_time_3d(met0, met0->t, met1, met1->t, t, press[iz],
12181 lon[ix], lat[iy], &temp, ci, cw, 1);
12182
12183 /* Calculate volume mixing ratio... */
12184 vmr_impl[idx] =
12185 MA / ctl->molmass * cd[idx] / (RHO(press[iz], temp) * dz * 1e3);
12186 }
12187 }
12188
12189 /* Calculate mean... */
12190 if (np[idx] > 0)
12191 for (int iq = 0; iq < ctl->nq; iq++) {
12192 mean[iq][idx] /= np[idx];
12193 const double var = sigma[iq][idx] / np[idx] - SQR(mean[iq][idx]);
12194 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
12195 } else
12196 for (int iq = 0; iq < ctl->nq; iq++) {
12197 mean[iq][idx] = NAN;
12198 sigma[iq][idx] = NAN;
12199 }
12200 }
12201
12202 /* Write ASCII data... */
12203 if (ctl->grid_type == 0)
12204 write_grid_asc(filename, ctl, cd, mean, sigma, vmr_impl,
12205 t, z, lon, lat, area, dz, np);
12206
12207 /* Write netCDF data... */
12208 else if (ctl->grid_type == 1)
12209 write_grid_nc(filename, ctl, cd, mean, sigma, vmr_impl,
12210 t, z, lon, lat, area, dz, np);
12211
12212 /* Error message... */
12213 else
12214 ERRMSG("Grid data format GRID_TYPE unknown!");
12215
12216 /* Free... */
12217 free(cd);
12218 for (int iq = 0; iq < ctl->nq; iq++) {
12219 free(mean[iq]);
12220 free(sigma[iq]);
12221 }
12222 free(vmr_impl);
12223 free(z);
12224 free(lon);
12225 free(lat);
12226 free(area);
12227 free(press);
12228 free(np);
12229 free(ixs);
12230 free(iys);
12231 free(izs);
12232}
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:12236
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:12340
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 12236 of file mptrac.c.

12249 {
12250
12251 FILE *out;
12252
12253 /* Check if gnuplot output is requested... */
12254 if (ctl->grid_gpfile[0] != '-') {
12255
12256 /* Create gnuplot pipe... */
12257 if (!(out = popen("gnuplot", "w")))
12258 ERRMSG("Cannot create pipe to gnuplot!");
12259
12260 /* Set plot filename... */
12261 fprintf(out, "set out \"%s.png\"\n", filename);
12262
12263 /* Set time string... */
12264 double r;
12265 int year, mon, day, hour, min, sec;
12266 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
12267 fprintf(out, "timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
12268 year, mon, day, hour, min);
12269
12270 /* Dump gnuplot file to pipe... */
12271 FILE *in;
12272 char line[LEN];
12273 if (!(in = fopen(ctl->grid_gpfile, "r")))
12274 ERRMSG("Cannot open file!");
12275 while (fgets(line, LEN, in))
12276 fprintf(out, "%s", line);
12277 fclose(in);
12278 }
12279
12280 else {
12281
12282 /* Create file... */
12283 if (!(out = fopen(filename, "w")))
12284 ERRMSG("Cannot create file!");
12285 }
12286
12287 /* Write header... */
12288 fprintf(out,
12289 "# $1 = time [s]\n"
12290 "# $2 = altitude [km]\n"
12291 "# $3 = longitude [deg]\n"
12292 "# $4 = latitude [deg]\n"
12293 "# $5 = surface area [km^2]\n"
12294 "# $6 = layer depth [km]\n"
12295 "# $7 = column density (implicit) [kg/m^2]\n"
12296 "# $8 = volume mixing ratio (implicit) [ppv]\n"
12297 "# $9 = number of particles [1]\n");
12298 for (int iq = 0; iq < ctl->nq; iq++)
12299 fprintf(out, "# $%i = %s (mean) [%s]\n", 10 + iq, ctl->qnt_name[iq],
12300 ctl->qnt_unit[iq]);
12301 if (ctl->grid_stddev)
12302 for (int iq = 0; iq < ctl->nq; iq++)
12303 fprintf(out, "# $%i = %s (stddev) [%s]\n", 10 + ctl->nq + iq,
12304 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
12305 fprintf(out, "\n");
12306
12307 /* Write data... */
12308 for (int ix = 0; ix < ctl->grid_nx; ix++) {
12309 if (ix > 0 && ctl->grid_ny > 1 && !ctl->grid_sparse)
12310 fprintf(out, "\n");
12311 for (int iy = 0; iy < ctl->grid_ny; iy++) {
12312 if (iy > 0 && ctl->grid_nz > 1 && !ctl->grid_sparse)
12313 fprintf(out, "\n");
12314 for (int iz = 0; iz < ctl->grid_nz; iz++) {
12315 int idx = ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz);
12316 if (!ctl->grid_sparse || vmr_impl[idx] > 0) {
12317 fprintf(out, "%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
12318 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
12319 for (int iq = 0; iq < ctl->nq; iq++) {
12320 fprintf(out, " ");
12321 fprintf(out, ctl->qnt_format[iq], mean[iq][idx]);
12322 }
12323 if (ctl->grid_stddev)
12324 for (int iq = 0; iq < ctl->nq; iq++) {
12325 fprintf(out, " ");
12326 fprintf(out, ctl->qnt_format[iq], sigma[iq][idx]);
12327 }
12328 fprintf(out, "\n");
12329 }
12330 }
12331 }
12332 }
12333
12334 /* Close file... */
12335 fclose(out);
12336}
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 12340 of file mptrac.c.

12353 {
12354
12355 char longname[2 * LEN], varname[2 * LEN];
12356
12357 double *help;
12358
12359 int *help2, ncid, dimid[10], varid;
12360
12361 size_t start[2], count[2];
12362
12363 /* Allocate... */
12364 ALLOC(help, double,
12365 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
12366 ALLOC(help2, int,
12367 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
12368
12369 /* Create file... */
12370 NC(nc_create(filename, NC_NETCDF4, &ncid));
12371
12372 /* Define dimensions... */
12373 NC(nc_def_dim(ncid, "time", 1, &dimid[0]));
12374 NC(nc_def_dim(ncid, "z", (size_t) ctl->grid_nz, &dimid[1]));
12375 NC(nc_def_dim(ncid, "lat", (size_t) ctl->grid_ny, &dimid[2]));
12376 NC(nc_def_dim(ncid, "lon", (size_t) ctl->grid_nx, &dimid[3]));
12377 NC(nc_def_dim(ncid, "dz", 1, &dimid[4]));
12378
12379 /* Define variables and their attributes... */
12380 NC_DEF_VAR("time", NC_DOUBLE, 1, &dimid[0], "time",
12381 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12382 NC_DEF_VAR("z", NC_DOUBLE, 1, &dimid[1], "altitude", "km", 0, 0);
12383 NC_DEF_VAR("lat", NC_DOUBLE, 1, &dimid[2], "latitude", "degrees_north", 0,
12384 0);
12385 NC_DEF_VAR("lon", NC_DOUBLE, 1, &dimid[3], "longitude", "degrees_east", 0,
12386 0);
12387 NC_DEF_VAR("dz", NC_DOUBLE, 1, &dimid[1], "layer depth", "km", 0, 0);
12388 NC_DEF_VAR("area", NC_DOUBLE, 1, &dimid[2], "surface area", "km**2", 0, 0);
12389
12390 NC_DEF_VAR("cd", NC_FLOAT, 4, dimid, "column density", "kg m**-2",
12391 ctl->grid_nc_level, 0);
12392 NC_DEF_VAR("vmr_impl", NC_FLOAT, 4, dimid,
12393 "volume mixing ratio (implicit)", "ppv", ctl->grid_nc_level, 0);
12394 NC_DEF_VAR("np", NC_INT, 4, dimid, "number of particles", "1", 0, 0);
12395 for (int iq = 0; iq < ctl->nq; iq++) {
12396 sprintf(varname, "%s_mean", ctl->qnt_name[iq]);
12397 sprintf(longname, "%s (mean)", ctl->qnt_longname[iq]);
12398 NC_DEF_VAR(varname, NC_DOUBLE, 4, dimid, longname, ctl->qnt_unit[iq],
12399 ctl->grid_nc_level, ctl->grid_nc_quant[iq]);
12400 if (ctl->grid_stddev) {
12401 sprintf(varname, "%s_stddev", ctl->qnt_name[iq]);
12402 sprintf(longname, "%s (stddev)", ctl->qnt_longname[iq]);
12403 NC_DEF_VAR(varname, NC_DOUBLE, 4, dimid, longname, ctl->qnt_unit[iq],
12404 ctl->grid_nc_level, ctl->grid_nc_quant[iq]);
12405 }
12406 }
12407 /* End definitions... */
12408 NC(nc_enddef(ncid));
12409
12410 /* Write data... */
12411 NC_PUT_DOUBLE("time", &t, 0);
12412 NC_PUT_DOUBLE("lon", lon, 0);
12413 NC_PUT_DOUBLE("lat", lat, 0);
12414 NC_PUT_DOUBLE("z", z, 0);
12415 NC_PUT_DOUBLE("area", area, 0);
12416 NC_PUT_DOUBLE("dz", &dz, 0);
12417
12418 for (int ix = 0; ix < ctl->grid_nx; ix++)
12419 for (int iy = 0; iy < ctl->grid_ny; iy++)
12420 for (int iz = 0; iz < ctl->grid_nz; iz++)
12421 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
12422 cd[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
12423 NC_PUT_DOUBLE("cd", help, 0);
12424
12425 for (int ix = 0; ix < ctl->grid_nx; ix++)
12426 for (int iy = 0; iy < ctl->grid_ny; iy++)
12427 for (int iz = 0; iz < ctl->grid_nz; iz++)
12428 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
12429 vmr_impl[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
12430 NC_PUT_DOUBLE("vmr_impl", help, 0);
12431
12432 for (int ix = 0; ix < ctl->grid_nx; ix++)
12433 for (int iy = 0; iy < ctl->grid_ny; iy++)
12434 for (int iz = 0; iz < ctl->grid_nz; iz++)
12435 help2[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
12436 np[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
12437 NC_PUT_INT("np", help2, 0);
12438
12439 for (int iq = 0; iq < ctl->nq; iq++) {
12440 sprintf(varname, "%s_mean", ctl->qnt_name[iq]);
12441 for (int ix = 0; ix < ctl->grid_nx; ix++)
12442 for (int iy = 0; iy < ctl->grid_ny; iy++)
12443 for (int iz = 0; iz < ctl->grid_nz; iz++)
12444 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
12445 mean[iq][ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
12446 NC_PUT_DOUBLE(varname, help, 0);
12447 }
12448
12449 if (ctl->grid_stddev)
12450 for (int iq = 0; iq < ctl->nq; iq++) {
12451 sprintf(varname, "%s_stddev", ctl->qnt_name[iq]);
12452 for (int ix = 0; ix < ctl->grid_nx; ix++)
12453 for (int iy = 0; iy < ctl->grid_ny; iy++)
12454 for (int iz = 0; iz < ctl->grid_nz; iz++)
12455 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
12456 sigma[iq][ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
12457 NC_PUT_DOUBLE(varname, help, 0);
12458 }
12459
12460 /* Close file... */
12461 NC(nc_close(ncid));
12462
12463 /* Free... */
12464 free(help);
12465 free(help2);
12466}
#define NC_PUT_INT(varname, ptr, hyperslab)
Write integer data to a NetCDF variable.
Definition: mptrac.h:1327

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

12473 {
12474
12475 /* Create file... */
12476 FILE *out;
12477 if (!(out = fopen(filename, "w")))
12478 ERRMSG("Cannot create file!");
12479
12480 /* Write type of binary data... */
12481 FWRITE(&ctl->met_type, int,
12482 1,
12483 out);
12484
12485 /* Write version of binary data... */
12486 int version = 103;
12487 FWRITE(&version, int,
12488 1,
12489 out);
12490
12491 /* Write grid data... */
12492 FWRITE(&met->time, double,
12493 1,
12494 out);
12495 FWRITE(&met->nx, int,
12496 1,
12497 out);
12498 FWRITE(&met->ny, int,
12499 1,
12500 out);
12501 FWRITE(&met->np, int,
12502 1,
12503 out);
12504 FWRITE(met->lon, double,
12505 (size_t) met->nx,
12506 out);
12507 FWRITE(met->lat, double,
12508 (size_t) met->ny,
12509 out);
12510 FWRITE(met->p, double,
12511 (size_t) met->np,
12512 out);
12513
12514 /* Write surface data... */
12515 write_met_bin_2d(out, met, met->ps, "PS");
12516 write_met_bin_2d(out, met, met->ts, "TS");
12517 write_met_bin_2d(out, met, met->zs, "ZS");
12518 write_met_bin_2d(out, met, met->us, "US");
12519 write_met_bin_2d(out, met, met->vs, "VS");
12520 write_met_bin_2d(out, met, met->ess, "ESS");
12521 write_met_bin_2d(out, met, met->nss, "NSS");
12522 write_met_bin_2d(out, met, met->shf, "SHF");
12523 write_met_bin_2d(out, met, met->lsm, "LSM");
12524 write_met_bin_2d(out, met, met->sst, "SST");
12525 write_met_bin_2d(out, met, met->pbl, "PBL");
12526 write_met_bin_2d(out, met, met->pt, "PT");
12527 write_met_bin_2d(out, met, met->tt, "TT");
12528 write_met_bin_2d(out, met, met->zt, "ZT");
12529 write_met_bin_2d(out, met, met->h2ot, "H2OT");
12530 write_met_bin_2d(out, met, met->pct, "PCT");
12531 write_met_bin_2d(out, met, met->pcb, "PCB");
12532 write_met_bin_2d(out, met, met->cl, "CL");
12533 write_met_bin_2d(out, met, met->plcl, "PLCL");
12534 write_met_bin_2d(out, met, met->plfc, "PLFC");
12535 write_met_bin_2d(out, met, met->pel, "PEL");
12536 write_met_bin_2d(out, met, met->cape, "CAPE");
12537 write_met_bin_2d(out, met, met->cin, "CIN");
12538 write_met_bin_2d(out, met, met->o3c, "O3C");
12539
12540 /* Write level data... */
12541 write_met_bin_3d(out, ctl, met, met->z, "Z",
12542 ctl->met_comp_prec[0], ctl->met_comp_tol[0]);
12543 write_met_bin_3d(out, ctl, met, met->t, "T",
12544 ctl->met_comp_prec[1], ctl->met_comp_tol[1]);
12545 write_met_bin_3d(out, ctl, met, met->u, "U",
12546 ctl->met_comp_prec[2], ctl->met_comp_tol[2]);
12547 write_met_bin_3d(out, ctl, met, met->v, "V",
12548 ctl->met_comp_prec[3], ctl->met_comp_tol[3]);
12549 write_met_bin_3d(out, ctl, met, met->w, "W",
12550 ctl->met_comp_prec[4], ctl->met_comp_tol[4]);
12551 write_met_bin_3d(out, ctl, met, met->pv, "PV",
12552 ctl->met_comp_prec[5], ctl->met_comp_tol[5]);
12553 write_met_bin_3d(out, ctl, met, met->h2o, "H2O",
12554 ctl->met_comp_prec[6], ctl->met_comp_tol[6]);
12555 write_met_bin_3d(out, ctl, met, met->o3, "O3",
12556 ctl->met_comp_prec[7], ctl->met_comp_tol[7]);
12557 write_met_bin_3d(out, ctl, met, met->lwc, "LWC",
12558 ctl->met_comp_prec[8], ctl->met_comp_tol[8]);
12559 write_met_bin_3d(out, ctl, met, met->rwc, "RWC",
12560 ctl->met_comp_prec[9], ctl->met_comp_tol[9]);
12561 write_met_bin_3d(out, ctl, met, met->iwc, "IWC",
12562 ctl->met_comp_prec[10], ctl->met_comp_tol[10]);
12563 write_met_bin_3d(out, ctl, met, met->swc, "SWC",
12564 ctl->met_comp_prec[11], ctl->met_comp_tol[11]);
12565 write_met_bin_3d(out, ctl, met, met->cc, "CC",
12566 ctl->met_comp_prec[12], ctl->met_comp_tol[12]);
12567 if (METVAR != 13)
12568 ERRMSG("Number of meteo variables doesn't match!");
12569
12570 /* Write final flag... */
12571 int final = 999;
12572 FWRITE(&final, int,
12573 1,
12574 out);
12575
12576 /* Close file... */
12577 fclose(out);
12578}
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:12611
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:12582
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 12582 of file mptrac.c.

12586 {
12587
12588 float *help;
12589
12590 /* Allocate... */
12591 ALLOC(help, float,
12592 EX * EY);
12593
12594 /* Copy data... */
12595 for (int ix = 0; ix < met->nx; ix++)
12596 for (int iy = 0; iy < met->ny; iy++)
12597 help[ARRAY_2D(ix, iy, met->ny)] = var[ix][iy];
12598
12599 /* Write uncompressed data... */
12600 LOG(2, "Write 2-D variable: %s (uncompressed)", varname);
12601 FWRITE(help, float,
12602 (size_t) (met->nx * met->ny),
12603 out);
12604
12605 /* Free... */
12606 free(help);
12607}

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

12618 {
12619
12620 float *help;
12621
12622 /* Allocate... */
12623 ALLOC(help, float,
12624 EX * EY * EP);
12625
12626 /* Copy data... */
12627#pragma omp parallel for default(shared) collapse(2)
12628 for (int ix = 0; ix < met->nx; ix++)
12629 for (int iy = 0; iy < met->ny; iy++)
12630 for (int ip = 0; ip < met->np; ip++)
12631 help[ARRAY_3D(ix, iy, met->ny, ip, met->np)] = var[ix][iy][ip];
12632
12633 /* Write uncompressed data... */
12634 if (ctl->met_type == 1) {
12635 LOG(2, "Write 3-D variable: %s (uncompressed)", varname);
12636 FWRITE(help, float,
12637 (size_t) (met->nx * met->ny * met->np),
12638 out);
12639 }
12640
12641 /* Write packed data... */
12642 else if (ctl->met_type == 2)
12643 compress_pck(varname, help, (size_t) (met->ny * met->nx),
12644 (size_t) met->np, 0, out);
12645
12646 /* Write ZFP data... */
12647#ifdef ZFP
12648 else if (ctl->met_type == 3) {
12649 FWRITE(&precision, int,
12650 1,
12651 out);
12652 FWRITE(&tolerance, double,
12653 1,
12654 out);
12655 compress_zfp(varname, help, met->np, met->ny, met->nx, precision,
12656 tolerance, 0, out);
12657 }
12658#endif
12659
12660 /* Write zstd data... */
12661#ifdef ZSTD
12662 else if (ctl->met_type == 4)
12663 compress_zstd(varname, help, (size_t) (met->np * met->ny * met->nx), 0,
12664 ctl->met_zstd_level, out);
12665#endif
12666
12667 /* Write cmultiscale data... */
12668#ifdef CMS
12669 else if (ctl->met_type == 5) {
12670 compress_cms(ctl, varname, help, (size_t) met->nx, (size_t) met->ny,
12671 (size_t) met->np, met->p, 0, out);
12672 }
12673#endif
12674
12675 /* Write SZ3 data... */
12676#ifdef SZ3
12677 else if (ctl->met_type == 7) {
12678 FWRITE(&precision, int,
12679 1,
12680 out);
12681 FWRITE(&tolerance, double,
12682 1,
12683 out);
12684 compress_sz3(varname, help, met->np, met->ny, met->nx, precision,
12685 tolerance, 0, out);
12686 }
12687#endif
12688
12689 /* Unknown method... */
12690 else {
12691 ERRMSG("MET_TYPE not supported!");
12692 LOG(3, "%d %g", precision, tolerance);
12693 }
12694
12695 /* Free... */
12696 free(help);
12697}
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 12701 of file mptrac.c.

12704 {
12705
12706 /* Create file... */
12707 int ncid, varid;
12708 size_t start[4], count[4];
12709 NC(nc_create(filename, NC_NETCDF4, &ncid));
12710
12711 /* Define dimensions... */
12712 int tid, lonid, latid, levid;
12713 NC(nc_def_dim(ncid, "time", 1, &tid));
12714 NC(nc_def_dim(ncid, "lon", (size_t) met->nx, &lonid));
12715 NC(nc_def_dim(ncid, "lat", (size_t) met->ny, &latid));
12716 NC(nc_def_dim(ncid, "lev", (size_t) met->np, &levid));
12717
12718 /* Define grid... */
12719 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "time",
12720 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12721 NC_DEF_VAR("lon", NC_DOUBLE, 1, &lonid, "longitude", "degrees_east", 0, 0);
12722 NC_DEF_VAR("lat", NC_DOUBLE, 1, &latid, "latitude", "degrees_north", 0, 0);
12723 NC_DEF_VAR("lev", NC_DOUBLE, 1, &levid, "pressure", "Pa", 0, 0);
12724
12725 /* Define surface variables... */
12726 int dimid2[2] = { latid, lonid };
12727 NC_DEF_VAR("sp", NC_FLOAT, 2, dimid2, "Surface pressure", "Pa",
12728 ctl->met_nc_level, 0);
12729 NC_DEF_VAR("z", NC_FLOAT, 2, dimid2, "Geopotential", "m**2 s**-2",
12730 ctl->met_nc_level, 0);
12731 NC_DEF_VAR("t2m", NC_FLOAT, 2, dimid2, "2 metre temperature", "K",
12732 ctl->met_nc_level, 0);
12733 NC_DEF_VAR("u10m", NC_FLOAT, 2, dimid2, "10 metre U wind component",
12734 "m s**-1", ctl->met_nc_level, 0);
12735 NC_DEF_VAR("v10m", NC_FLOAT, 2, dimid2, "10 metre V wind component",
12736 "m s**-1", ctl->met_nc_level, 0);
12737 NC_DEF_VAR("iews", NC_FLOAT, 2, dimid2,
12738 "Instantaneous eastward turbulent surface stress", "N m**-2",
12739 ctl->met_nc_level, 0);
12740 NC_DEF_VAR("inss", NC_FLOAT, 2, dimid2,
12741 "Instantaneous northward turbulent surface stress", "N m**-2",
12742 ctl->met_nc_level, 0);
12743 NC_DEF_VAR("ishf", NC_FLOAT, 2, dimid2,
12744 "Instantaneous surface sensible heat flux", "W m**-1",
12745 ctl->met_nc_level, 0);
12746 NC_DEF_VAR("lsm", NC_FLOAT, 2, dimid2, "Land/sea mask", "-",
12747 ctl->met_nc_level, 0);
12748 NC_DEF_VAR("sstk", NC_FLOAT, 2, dimid2, "Sea surface temperature", "K",
12749 ctl->met_nc_level, 0);
12750 NC_DEF_VAR("blp", NC_FLOAT, 2, dimid2, "Boundary layer pressure", "Pa",
12751 ctl->met_nc_level, 0);
12752 NC_DEF_VAR("pt", NC_FLOAT, 2, dimid2, "Tropopause pressure", "Pa",
12753 ctl->met_nc_level, 0);
12754 NC_DEF_VAR("tt", NC_FLOAT, 2, dimid2, "Tropopause temperature", "K",
12755 ctl->met_nc_level, 0);
12756 NC_DEF_VAR("zt", NC_FLOAT, 2, dimid2, "Tropopause height", "m",
12757 ctl->met_nc_level, 0);
12758 NC_DEF_VAR("h2ot", NC_FLOAT, 2, dimid2, "Tropopause water vapor", "ppv",
12759 ctl->met_nc_level, 0);
12760 NC_DEF_VAR("pct", NC_FLOAT, 2, dimid2, "Cloud top pressure", "Pa",
12761 ctl->met_nc_level, 0);
12762 NC_DEF_VAR("pcb", NC_FLOAT, 2, dimid2, "Cloud bottom pressure", "Pa",
12763 ctl->met_nc_level, 0);
12764 NC_DEF_VAR("cl", NC_FLOAT, 2, dimid2, "Total column cloud water",
12765 "kg m**2", ctl->met_nc_level, 0);
12766 NC_DEF_VAR("plcl", NC_FLOAT, 2, dimid2,
12767 "Pressure at lifted condensation level (LCL)", "Pa",
12768 ctl->met_nc_level, 0);
12769 NC_DEF_VAR("plfc", NC_FLOAT, 2, dimid2,
12770 "Pressure at level of free convection (LFC)", "Pa",
12771 ctl->met_nc_level, 0);
12772 NC_DEF_VAR("pel", NC_FLOAT, 2, dimid2,
12773 "Pressure at equilibrium level (EL)", "Pa", ctl->met_nc_level,
12774 0);
12775 NC_DEF_VAR("cape", NC_FLOAT, 2, dimid2,
12776 "Convective available potential energy", "J kg**-1",
12777 ctl->met_nc_level, 0);
12778 NC_DEF_VAR("cin", NC_FLOAT, 2, dimid2, "Convective inhibition",
12779 "J kg**-1", ctl->met_nc_level, 0);
12780 NC_DEF_VAR("o3c", NC_FLOAT, 2, dimid2, "Total column ozone", "DU",
12781 ctl->met_nc_level, 0);
12782
12783 /* Define level data... */
12784 int dimid3[3] = { levid, latid, lonid };
12785 NC_DEF_VAR("t", NC_FLOAT, 3, dimid3, "Temperature", "K",
12786 ctl->met_nc_level, ctl->met_nc_quant);
12787 NC_DEF_VAR("u", NC_FLOAT, 3, dimid3, "U velocity", "m s**-1",
12788 ctl->met_nc_level, ctl->met_nc_quant);
12789 NC_DEF_VAR("v", NC_FLOAT, 3, dimid3, "V velocity", "m s**-1",
12790 ctl->met_nc_level, ctl->met_nc_quant);
12791 NC_DEF_VAR("w", NC_FLOAT, 3, dimid3, "Vertical velocity", "Pa s**-1",
12792 ctl->met_nc_level, ctl->met_nc_quant);
12793 NC_DEF_VAR("q", NC_FLOAT, 3, dimid3, "Specific humidity", "kg kg**-1",
12794 ctl->met_nc_level, ctl->met_nc_quant);
12795 NC_DEF_VAR("o3", NC_FLOAT, 3, dimid3, "Ozone mass mixing ratio",
12796 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
12797 NC_DEF_VAR("clwc", NC_FLOAT, 3, dimid3, "Cloud liquid water content",
12798 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
12799 NC_DEF_VAR("crwc", NC_FLOAT, 3, dimid3, "Cloud rain water content",
12800 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
12801 NC_DEF_VAR("ciwc", NC_FLOAT, 3, dimid3, "Cloud ice water content",
12802 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
12803 NC_DEF_VAR("cswc", NC_FLOAT, 3, dimid3, "Cloud snow water content",
12804 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
12805 NC_DEF_VAR("cc", NC_FLOAT, 3, dimid3, "Cloud cover", "-",
12806 ctl->met_nc_level, ctl->met_nc_quant);
12807
12808 /* End definitions... */
12809 NC(nc_enddef(ncid));
12810
12811 /* Write grid data... */
12812 NC_PUT_DOUBLE("time", &met->time, 0);
12813 NC_PUT_DOUBLE("lon", met->lon, 0);
12814 NC_PUT_DOUBLE("lat", met->lat, 0);
12815 double phelp[EP];
12816 for (int ip = 0; ip < met->np; ip++)
12817 phelp[ip] = 100. * met->p[ip];
12818 NC_PUT_DOUBLE("lev", phelp, 0);
12819
12820 /* Write surface data... */
12821 write_met_nc_2d(ncid, "sp", met, met->ps, 100.0f);
12822 write_met_nc_2d(ncid, "z", met, met->zs, (float) (1000. * G0));
12823 write_met_nc_2d(ncid, "t2m", met, met->ts, 1.0f);
12824 write_met_nc_2d(ncid, "u10m", met, met->us, 1.0f);
12825 write_met_nc_2d(ncid, "v10m", met, met->vs, 1.0f);
12826 write_met_nc_2d(ncid, "iews", met, met->ess, 1.0f);
12827 write_met_nc_2d(ncid, "inss", met, met->nss, 1.0f);
12828 write_met_nc_2d(ncid, "ishf", met, met->shf, 1.0f);
12829 write_met_nc_2d(ncid, "lsm", met, met->lsm, 1.0f);
12830 write_met_nc_2d(ncid, "sstk", met, met->sst, 1.0f);
12831 write_met_nc_2d(ncid, "blp", met, met->pbl, 100.0f);
12832 write_met_nc_2d(ncid, "pt", met, met->pt, 100.0f);
12833 write_met_nc_2d(ncid, "tt", met, met->tt, 1.0f);
12834 write_met_nc_2d(ncid, "zt", met, met->zt, 1000.0f);
12835 write_met_nc_2d(ncid, "h2ot", met, met->h2ot, 1.0f);
12836 write_met_nc_2d(ncid, "pct", met, met->pct, 100.0f);
12837 write_met_nc_2d(ncid, "pcb", met, met->pcb, 100.0f);
12838 write_met_nc_2d(ncid, "cl", met, met->cl, 1.0f);
12839 write_met_nc_2d(ncid, "plcl", met, met->plcl, 100.0f);
12840 write_met_nc_2d(ncid, "plfc", met, met->plfc, 100.0f);
12841 write_met_nc_2d(ncid, "pel", met, met->pel, 100.0f);
12842 write_met_nc_2d(ncid, "cape", met, met->cape, 1.0f);
12843 write_met_nc_2d(ncid, "cin", met, met->cin, 1.0f);
12844 write_met_nc_2d(ncid, "o3c", met, met->o3c, 1.0f);
12845
12846 /* Write level data... */
12847 write_met_nc_3d(ncid, "t", met, met->t, 1.0f);
12848 write_met_nc_3d(ncid, "u", met, met->u, 1.0f);
12849 write_met_nc_3d(ncid, "v", met, met->v, 1.0f);
12850 write_met_nc_3d(ncid, "w", met, met->w, 100.0f);
12851 write_met_nc_3d(ncid, "q", met, met->h2o, (float) (MH2O / MA));
12852 write_met_nc_3d(ncid, "o3", met, met->o3, (float) (MO3 / MA));
12853 write_met_nc_3d(ncid, "clwc", met, met->lwc, 1.0f);
12854 write_met_nc_3d(ncid, "crwc", met, met->rwc, 1.0f);
12855 write_met_nc_3d(ncid, "ciwc", met, met->iwc, 1.0f);
12856 write_met_nc_3d(ncid, "cswc", met, met->swc, 1.0f);
12857 write_met_nc_3d(ncid, "cc", met, met->cc, 1.0f);
12858
12859 /* Close file... */
12860 NC(nc_close(ncid));
12861}
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:12865
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:12894
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.
Author
Lars Hoffmann

Definition at line 12865 of file mptrac.c.

12870 {
12871
12872 int varid;
12873 size_t start[4], count[4];
12874
12875 /* Allocate... */
12876 float *help;
12877 ALLOC(help, float,
12878 EX * EY);
12879
12880 /* Copy data... */
12881 for (int ix = 0; ix < met->nx; ix++)
12882 for (int iy = 0; iy < met->ny; iy++)
12883 help[ARRAY_2D(iy, ix, met->nx)] = scl * var[ix][iy];
12884
12885 /* Write data... */
12886 NC_PUT_FLOAT(varname, help, 0);
12887
12888 /* Free... */
12889 free(help);
12890}
#define NC_PUT_FLOAT(varname, ptr, hyperslab)
Write a float array to a NetCDF file.
Definition: mptrac.h:1304

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

Definition at line 12894 of file mptrac.c.

12899 {
12900
12901 int varid;
12902 size_t start[4], count[4];
12903
12904 /* Allocate... */
12905 float *help;
12906 ALLOC(help, float,
12907 EX * EY * EP);
12908
12909 /* Copy data... */
12910 for (int ix = 0; ix < met->nx; ix++)
12911 for (int iy = 0; iy < met->ny; iy++)
12912 for (int ip = 0; ip < met->np; ip++)
12913 help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)] = scl * var[ix][iy][ip];
12914
12915 /* Write data... */
12916 NC_PUT_FLOAT(varname, help, 0);
12917
12918 /* Free... */
12919 free(help);
12920}

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

12930 {
12931
12932 static FILE *out;
12933
12934 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
12935 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
12936
12937 static int nobs, *obscount, ip, okay;
12938
12939 /* Set timer... */
12940 SELECT_TIMER("WRITE_PROF", "OUTPUT", NVTX_WRITE);
12941
12942 /* Init... */
12943 if (t == ctl->t_start) {
12944
12945 /* Check quantity index for mass... */
12946 if (ctl->qnt_m < 0)
12947 ERRMSG("Need quantity mass!");
12948
12949 /* Check molar mass... */
12950 if (ctl->molmass <= 0)
12951 ERRMSG("Specify molar mass!");
12952
12953 /* Allocate... */
12954 ALLOC(lon, double,
12955 ctl->prof_nx);
12956 ALLOC(lat, double,
12957 ctl->prof_ny);
12958 ALLOC(area, double,
12959 ctl->prof_ny);
12960 ALLOC(z, double,
12961 ctl->prof_nz);
12962 ALLOC(press, double,
12963 ctl->prof_nz);
12964 ALLOC(rt, double,
12965 NOBS);
12966 ALLOC(rz, double,
12967 NOBS);
12968 ALLOC(rlon, double,
12969 NOBS);
12970 ALLOC(rlat, double,
12971 NOBS);
12972 ALLOC(robs, double,
12973 NOBS);
12974
12975 /* Read observation data... */
12976 read_obs(ctl->prof_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
12977
12978 /* Create new output file... */
12979 LOG(1, "Write profile data: %s", filename);
12980 if (!(out = fopen(filename, "w")))
12981 ERRMSG("Cannot create file!");
12982
12983 /* Write header... */
12984 fprintf(out,
12985 "# $1 = time [s]\n"
12986 "# $2 = altitude [km]\n"
12987 "# $3 = longitude [deg]\n"
12988 "# $4 = latitude [deg]\n"
12989 "# $5 = pressure [hPa]\n"
12990 "# $6 = temperature [K]\n"
12991 "# $7 = volume mixing ratio [ppv]\n"
12992 "# $8 = H2O volume mixing ratio [ppv]\n"
12993 "# $9 = O3 volume mixing ratio [ppv]\n"
12994 "# $10 = observed BT index [K]\n"
12995 "# $11 = number of observations\n");
12996
12997 /* Set grid box size... */
12998 dz = (ctl->prof_z1 - ctl->prof_z0) / ctl->prof_nz;
12999 dlon = (ctl->prof_lon1 - ctl->prof_lon0) / ctl->prof_nx;
13000 dlat = (ctl->prof_lat1 - ctl->prof_lat0) / ctl->prof_ny;
13001
13002 /* Set vertical coordinates... */
13003 for (int iz = 0; iz < ctl->prof_nz; iz++) {
13004 z[iz] = ctl->prof_z0 + dz * (iz + 0.5);
13005 press[iz] = P(z[iz]);
13006 }
13007
13008 /* Set horizontal coordinates... */
13009 for (int ix = 0; ix < ctl->prof_nx; ix++)
13010 lon[ix] = ctl->prof_lon0 + dlon * (ix + 0.5);
13011 for (int iy = 0; iy < ctl->prof_ny; iy++) {
13012 lat[iy] = ctl->prof_lat0 + dlat * (iy + 0.5);
13013 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
13014 }
13015 }
13016
13017 /* Set time interval... */
13018 const double t0 = t - 0.5 * ctl->dt_mod;
13019 const double t1 = t + 0.5 * ctl->dt_mod;
13020
13021 /* Allocate... */
13022 ALLOC(mass, double,
13023 ctl->prof_nx * ctl->prof_ny * ctl->prof_nz);
13024 ALLOC(obsmean, double,
13025 ctl->prof_nx * ctl->prof_ny);
13026 ALLOC(obscount, int,
13027 ctl->prof_nx * ctl->prof_ny);
13028
13029 /* Loop over observations... */
13030 for (int i = 0; i < nobs; i++) {
13031
13032 /* Check time... */
13033 if (rt[i] < t0)
13034 continue;
13035 else if (rt[i] >= t1)
13036 break;
13037
13038 /* Check observation data... */
13039 if (!isfinite(robs[i]))
13040 continue;
13041
13042 /* Calculate indices... */
13043 const int ix = (int) ((rlon[i] - ctl->prof_lon0) / dlon);
13044 const int iy = (int) ((rlat[i] - ctl->prof_lat0) / dlat);
13045
13046 /* Check indices... */
13047 if (ix < 0 || ix >= ctl->prof_nx || iy < 0 || iy >= ctl->prof_ny)
13048 continue;
13049
13050 /* Get mean observation index... */
13051 const int idx = ARRAY_2D(ix, iy, ctl->prof_ny);
13052 obsmean[idx] += robs[i];
13053 obscount[idx]++;
13054 }
13055
13056 /* Analyze model data... */
13057 for (ip = 0; ip < atm->np; ip++) {
13058
13059 /* Check time... */
13060 if (atm->time[ip] < t0 || atm->time[ip] > t1)
13061 continue;
13062
13063 /* Get indices... */
13064 const int ix = (int) ((atm->lon[ip] - ctl->prof_lon0) / dlon);
13065 const int iy = (int) ((atm->lat[ip] - ctl->prof_lat0) / dlat);
13066 const int iz = (int) ((Z(atm->p[ip]) - ctl->prof_z0) / dz);
13067
13068 /* Check indices... */
13069 if (ix < 0 || ix >= ctl->prof_nx ||
13070 iy < 0 || iy >= ctl->prof_ny || iz < 0 || iz >= ctl->prof_nz)
13071 continue;
13072
13073 /* Get total mass in grid cell... */
13074 const int idx = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
13075 mass[idx] += atm->q[ctl->qnt_m][ip];
13076 }
13077
13078 /* Extract profiles... */
13079 for (int ix = 0; ix < ctl->prof_nx; ix++)
13080 for (int iy = 0; iy < ctl->prof_ny; iy++) {
13081 int idx2 = ARRAY_2D(ix, iy, ctl->prof_ny);
13082 if (obscount[idx2] > 0) {
13083
13084 /* Check profile... */
13085 okay = 0;
13086 for (int iz = 0; iz < ctl->prof_nz; iz++) {
13087 int idx3 = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
13088 if (mass[idx3] > 0) {
13089 okay = 1;
13090 break;
13091 }
13092 }
13093 if (!okay)
13094 continue;
13095
13096 /* Write output... */
13097 fprintf(out, "\n");
13098
13099 /* Loop over altitudes... */
13100 for (int iz = 0; iz < ctl->prof_nz; iz++) {
13101
13102 /* Get temperature, water vapor, and ozone... */
13104 intpol_met_time_3d(met0, met0->t, met1, met1->t, t, press[iz],
13105 lon[ix], lat[iy], &temp, ci, cw, 1);
13106 intpol_met_time_3d(met0, met0->h2o, met1, met1->h2o, t, press[iz],
13107 lon[ix], lat[iy], &h2o, ci, cw, 0);
13108 intpol_met_time_3d(met0, met0->o3, met1, met1->o3, t, press[iz],
13109 lon[ix], lat[iy], &o3, ci, cw, 0);
13110
13111 /* Calculate volume mixing ratio... */
13112 const int idx3 = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
13113 vmr = MA / ctl->molmass * mass[idx3]
13114 / (RHO(press[iz], temp) * area[iy] * dz * 1e9);
13115
13116 /* Write output... */
13117 fprintf(out, "%.2f %g %g %g %g %g %g %g %g %g %d\n",
13118 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
13119 obsmean[idx2] / obscount[idx2], obscount[idx2]);
13120 }
13121 }
13122 }
13123
13124 /* Free... */
13125 free(mass);
13126 free(obsmean);
13127 free(obscount);
13128
13129 /* Finalize... */
13130 if (t == ctl->t_stop) {
13131
13132 /* Close output file... */
13133 fclose(out);
13134
13135 /* Free... */
13136 free(lon);
13137 free(lat);
13138 free(area);
13139 free(z);
13140 free(press);
13141 free(rt);
13142 free(rz);
13143 free(rlon);
13144 free(rlat);
13145 free(robs);
13146 }
13147}
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 13151 of file mptrac.c.

13157 {
13158
13159 static FILE *out;
13160
13161 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[EP],
13162 kw[EP];
13163
13164 static int nobs, nk;
13165
13166 /* Set timer... */
13167 SELECT_TIMER("WRITE_SAMPLE", "OUTPUT", NVTX_WRITE);
13168
13169 /* Init... */
13170 if (t == ctl->t_start) {
13171
13172 /* Allocate... */
13173 ALLOC(rt, double,
13174 NOBS);
13175 ALLOC(rz, double,
13176 NOBS);
13177 ALLOC(rlon, double,
13178 NOBS);
13179 ALLOC(rlat, double,
13180 NOBS);
13181 ALLOC(robs, double,
13182 NOBS);
13183
13184 /* Read observation data... */
13185 read_obs(ctl->sample_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
13186
13187 /* Read kernel data... */
13188 if (ctl->sample_kernel[0] != '-')
13189 read_kernel(ctl->sample_kernel, kz, kw, &nk);
13190
13191 /* Create output file... */
13192 LOG(1, "Write sample data: %s", filename);
13193 if (!(out = fopen(filename, "w")))
13194 ERRMSG("Cannot create file!");
13195
13196 /* Write header... */
13197 fprintf(out,
13198 "# $1 = time [s]\n"
13199 "# $2 = altitude [km]\n"
13200 "# $3 = longitude [deg]\n"
13201 "# $4 = latitude [deg]\n"
13202 "# $5 = surface area [km^2]\n"
13203 "# $6 = layer depth [km]\n"
13204 "# $7 = number of particles [1]\n"
13205 "# $8 = column density [kg/m^2]\n"
13206 "# $9 = volume mixing ratio [ppv]\n"
13207 "# $10 = observed BT index [K]\n\n");
13208
13209 /* Set latitude range, squared radius, and area... */
13210 dlat = DY2DEG(ctl->sample_dx);
13211 rmax2 = SQR(ctl->sample_dx);
13212 area = M_PI * rmax2;
13213 }
13214
13215 /* Set time interval for output... */
13216 const double t0 = t - 0.5 * ctl->dt_mod;
13217 const double t1 = t + 0.5 * ctl->dt_mod;
13218
13219 /* Loop over observations... */
13220 for (int i = 0; i < nobs; i++) {
13221
13222 /* Check time... */
13223 if (rt[i] < t0)
13224 continue;
13225 else if (rt[i] >= t1)
13226 break;
13227
13228 /* Calculate Cartesian coordinates... */
13229 double x0[3];
13230 geo2cart(0, rlon[i], rlat[i], x0);
13231
13232 /* Set pressure range... */
13233 const double rp = P(rz[i]);
13234 const double ptop = P(rz[i] + ctl->sample_dz);
13235 const double pbot = P(rz[i] - ctl->sample_dz);
13236
13237 /* Init... */
13238 double mass = 0;
13239 int np = 0;
13240
13241 /* Loop over air parcels... */
13242 //#pragma omp parallel for default(shared) reduction(+:mass,np)
13243 for (int ip = 0; ip < atm->np; ip++) {
13244
13245 /* Check time... */
13246 if (atm->time[ip] < t0 || atm->time[ip] > t1)
13247 continue;
13248
13249 /* Check latitude... */
13250 if (fabs(rlat[i] - atm->lat[ip]) > dlat)
13251 continue;
13252
13253 /* Check horizontal distance... */
13254 double x1[3];
13255 geo2cart(0, atm->lon[ip], atm->lat[ip], x1);
13256 if (DIST2(x0, x1) > rmax2)
13257 continue;
13258
13259 /* Check pressure... */
13260 if (ctl->sample_dz > 0)
13261 if (atm->p[ip] > pbot || atm->p[ip] < ptop)
13262 continue;
13263
13264 /* Add mass... */
13265 if (ctl->qnt_m >= 0)
13266 mass +=
13267 kernel_weight(kz, kw, nk, atm->p[ip]) * atm->q[ctl->qnt_m][ip];
13268 np++;
13269 }
13270
13271 /* Calculate column density... */
13272 const double cd = mass / (1e6 * area);
13273
13274 /* Calculate volume mixing ratio... */
13275 double vmr = 0;
13276 if (ctl->molmass > 0 && ctl->sample_dz > 0) {
13277 if (mass > 0) {
13278
13279 /* Get temperature... */
13280 double temp;
13282 intpol_met_time_3d(met0, met0->t, met1, met1->t, rt[i], rp,
13283 rlon[i], rlat[i], &temp, ci, cw, 1);
13284
13285 /* Calculate volume mixing ratio... */
13286 vmr = MA / ctl->molmass * cd / (RHO(rp, temp) * ctl->sample_dz * 1e3);
13287 }
13288 } else
13289 vmr = NAN;
13290
13291 /* Write output... */
13292 fprintf(out, "%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
13293 rlon[i], rlat[i], area, ctl->sample_dz, np, cd, vmr, robs[i]);
13294 }
13295
13296 /* Finalize...... */
13297 if (t == ctl->t_stop) {
13298
13299 /* Close output file... */
13300 fclose(out);
13301
13302 /* Free... */
13303 free(rt);
13304 free(rz);
13305 free(rlon);
13306 free(rlat);
13307 free(robs);
13308 }
13309}
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 13313 of file mptrac.c.

13317 {
13318
13319 static FILE *out;
13320
13321 static double rmax2, x0[3], x1[3];
13322
13323 /* Set timer... */
13324 SELECT_TIMER("WRITE_STATION", "OUTPUT", NVTX_WRITE);
13325
13326 /* Init... */
13327 if (t == ctl->t_start) {
13328
13329 /* Write info... */
13330 LOG(1, "Write station data: %s", filename);
13331
13332 /* Create new file... */
13333 if (!(out = fopen(filename, "w")))
13334 ERRMSG("Cannot create file!");
13335
13336 /* Write header... */
13337 fprintf(out,
13338 "# $1 = time [s]\n"
13339 "# $2 = altitude [km]\n"
13340 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
13341 for (int iq = 0; iq < ctl->nq; iq++)
13342 fprintf(out, "# $%i = %s [%s]\n", (iq + 5),
13343 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
13344 fprintf(out, "\n");
13345
13346 /* Set geolocation and search radius... */
13347 geo2cart(0, ctl->stat_lon, ctl->stat_lat, x0);
13348 rmax2 = SQR(ctl->stat_r);
13349 }
13350
13351 /* Set time interval for output... */
13352 const double t0 = t - 0.5 * ctl->dt_mod;
13353 const double t1 = t + 0.5 * ctl->dt_mod;
13354
13355 /* Loop over air parcels... */
13356 for (int ip = 0; ip < atm->np; ip++) {
13357
13358 /* Check time... */
13359 if (atm->time[ip] < t0 || atm->time[ip] > t1)
13360 continue;
13361
13362 /* Check time range for station output... */
13363 if (atm->time[ip] < ctl->stat_t0 || atm->time[ip] > ctl->stat_t1)
13364 continue;
13365
13366 /* Check station flag... */
13367 if (ctl->qnt_stat >= 0)
13368 if ((int) atm->q[ctl->qnt_stat][ip])
13369 continue;
13370
13371 /* Get Cartesian coordinates... */
13372 geo2cart(0, atm->lon[ip], atm->lat[ip], x1);
13373
13374 /* Check horizontal distance... */
13375 if (DIST2(x0, x1) > rmax2)
13376 continue;
13377
13378 /* Set station flag... */
13379 if (ctl->qnt_stat >= 0)
13380 atm->q[ctl->qnt_stat][ip] = 1;
13381
13382 /* Write data... */
13383 fprintf(out, "%.2f %g %g %g",
13384 atm->time[ip], Z(atm->p[ip]), atm->lon[ip], atm->lat[ip]);
13385 for (int iq = 0; iq < ctl->nq; iq++) {
13386 fprintf(out, " ");
13387 fprintf(out, ctl->qnt_format[iq], atm->q[iq][ip]);
13388 }
13389 fprintf(out, "\n");
13390 }
13391
13392 /* Close file... */
13393 if (t == ctl->t_stop)
13394 fclose(out);
13395}
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 13399 of file mptrac.c.

13403 {
13404
13405 FILE *out;
13406
13407 /* Set timer... */
13408 SELECT_TIMER("WRITE_VTK", "OUTPUT", NVTX_WRITE);
13409
13410 /* Write info... */
13411 LOG(1, "Write VTK data: %s", filename);
13412
13413 /* Set time interval for output... */
13414 const double t0 = t - 0.5 * ctl->dt_mod;
13415 const double t1 = t + 0.5 * ctl->dt_mod;
13416
13417 /* Create file... */
13418 if (!(out = fopen(filename, "w")))
13419 ERRMSG("Cannot create file!");
13420
13421 /* Count data points... */
13422 int np = 0;
13423 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
13424 if (atm->time[ip] < t0 || atm->time[ip] > t1)
13425 continue;
13426 np++;
13427 }
13428
13429 /* Write header... */
13430 fprintf(out,
13431 "# vtk DataFile Version 3.0\n"
13432 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
13433
13434 /* Write point coordinates... */
13435 fprintf(out, "POINTS %d float\n", np);
13436 if (ctl->vtk_sphere) {
13437 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
13438 if (atm->time[ip] < t0 || atm->time[ip] > t1)
13439 continue;
13440 const double radius = (RE + Z(atm->p[ip]) * ctl->vtk_scale
13441 + ctl->vtk_offset) / RE;
13442 const double coslat = cos(DEG2RAD(atm->lat[ip]));
13443 const double x = radius * coslat * cos(DEG2RAD(atm->lon[ip]));
13444 const double y = radius * coslat * sin(DEG2RAD(atm->lon[ip]));
13445 const double z = radius * sin(DEG2RAD(atm->lat[ip]));
13446 fprintf(out, "%g %g %g\n", x, y, z);
13447 }
13448 } else
13449 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
13450 if (atm->time[ip] < t0 || atm->time[ip] > t1)
13451 continue;
13452 fprintf(out, "%g %g %g\n", atm->lon[ip], atm->lat[ip],
13453 Z(atm->p[ip]) * ctl->vtk_scale + ctl->vtk_offset);
13454 }
13455
13456 /* Write point data... */
13457 fprintf(out, "POINT_DATA %d\n", np);
13458 for (int iq = 0; iq < ctl->nq; iq++) {
13459 fprintf(out, "SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
13460 ctl->qnt_name[iq]);
13461 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
13462 if (atm->time[ip] < t0 || atm->time[ip] > t1)
13463 continue;
13464 fprintf(out, "%g\n", atm->q[iq][ip]);
13465 }
13466 }
13467
13468 /* Close file... */
13469 fclose(out);
13470}