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 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:2450

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:2421

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:1003
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:3511
double oh_chem_beta
Beta parameter for diurnal variablity of OH.
Definition: mptrac.h:2978
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:3467
int np
Number of pressure levels.
Definition: mptrac.h:3464
double vmr[CT][CP][CY]
Volume mixing ratio [ppv].
Definition: mptrac.h:3476
int ntime
Number of timesteps.
Definition: mptrac.h:3458
int nlat
Number of latitudes.
Definition: mptrac.h:3461
double lat[CY]
Latitude [deg].
Definition: mptrac.h:3470
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:2925
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:2861
#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:3385
double sza[CSZA]
Solar zenith angle [rad].
Definition: mptrac.h:3394
double p[CP]
Pressure [hPa].
Definition: mptrac.h:3391
double o3c[CO3]
Total column ozone [DU].
Definition: mptrac.h:3397
int np
Number of pressure levels.
Definition: mptrac.h:3382
int no3c
Number of total ozone columns.
Definition: mptrac.h:3388
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:3490
double tropo_lat[73]
Tropopause latitudes [deg].
Definition: mptrac.h:3499
int tropo_nlat
Number of tropopause latitudes.
Definition: mptrac.h:3493
double tropo[12][73]
Tropopause pressure values [hPa].
Definition: mptrac.h:3502
double tropo_time[12]
Tropopause time steps [s].
Definition: mptrac.h:3496
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:3444
double time[CTS]
Time [s].
Definition: mptrac.h:3441
int ntime
Number of timesteps.
Definition: mptrac.h:3438
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:3473
Here is the call graph for this function:

◆ compress_cms()

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

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

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

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

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

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

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

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

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

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

1918 {
1919
1920 double data[2 * EX];
1921
1922 /* Check size... */
1923 if (n > EX)
1924 ERRMSG("Too many data points!");
1925
1926 /* Allocate... */
1927 gsl_fft_complex_wavetable *wavetable =
1928 gsl_fft_complex_wavetable_alloc((size_t) n);
1929 gsl_fft_complex_workspace *workspace =
1930 gsl_fft_complex_workspace_alloc((size_t) n);
1931
1932 /* Set data (real, complex)... */
1933 for (int i = 0; i < n; i++) {
1934 data[2 * i] = fcReal[i];
1935 data[2 * i + 1] = fcImag[i];
1936 }
1937
1938 /* Calculate FFT... */
1939 gsl_fft_complex_forward(data, 1, (size_t) n, wavetable, workspace);
1940
1941 /* Copy data... */
1942 for (int i = 0; i < n; i++) {
1943 fcReal[i] = data[2 * i];
1944 fcImag[i] = data[2 * i + 1];
1945 }
1946
1947 /* Free... */
1948 gsl_fft_complex_wavetable_free(wavetable);
1949 gsl_fft_complex_workspace_free(workspace);
1950}
#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 1954 of file mptrac.c.

1958 {
1959
1960 const double radius = z + RE;
1961 const double latrad = DEG2RAD(lat);
1962 const double lonrad = DEG2RAD(lon);
1963 const double coslat = cos(latrad);
1964
1965 x[0] = radius * coslat * cos(lonrad);
1966 x[1] = radius * coslat * sin(lonrad);
1967 x[2] = radius * sin(latrad);
1968}

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

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

2042 {
2043
2044 char buffer[LEN];
2045
2046 /* Iterate... */
2047 for (int i = 0; i < 3; i++) {
2048
2049 /* Replace sub-string... */
2050 char *ch;
2051 if (!(ch = strstr(orig, search)))
2052 return;
2053 strncpy(buffer, orig, (size_t) (ch - orig));
2054 buffer[ch - orig] = 0;
2055 sprintf(buffer + (ch - orig), "%s%s", repl, ch + strlen(search));
2056 orig[0] = 0;
2057 strcpy(orig, buffer);
2058 }
2059}

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

2078 {
2079
2081
2082 ctl->met_tropo = met_tropo;
2083 read_met_tropo(ctl, clim, met);
2084#pragma omp parallel for default(shared) private(ci,cw)
2085 for (int ix = 0; ix < nx; ix++)
2086 for (int iy = 0; iy < ny; iy++) {
2087 intpol_met_space_2d(met, met->pt, lons[ix], lats[iy],
2088 &pt[iy * nx + ix], ci, cw, 1);
2089 intpol_met_space_2d(met, met->ps, lons[ix], lats[iy],
2090 &ps[iy * nx + ix], ci, cw, 0);
2091 intpol_met_space_2d(met, met->zs, lons[ix], lats[iy],
2092 &zs[iy * nx + ix], ci, cw, 0);
2093 intpol_met_space_3d(met, met->z, pt[iy * nx + ix], lons[ix],
2094 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
2095 intpol_met_space_3d(met, met->t, pt[iy * nx + ix], lons[ix],
2096 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
2097 intpol_met_space_3d(met, met->h2o, pt[iy * nx + ix], lons[ix],
2098 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
2099 intpol_met_space_3d(met, met->o3, pt[iy * nx + ix], lons[ix],
2100 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
2101 }
2102}
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:2363
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:10666
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:2305
#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:2738
float h2o[EX][EY][EP]
Water vapor volume mixing ratio [1].
Definition: mptrac.h:3675
float ps[EX][EY]
Surface pressure [hPa].
Definition: mptrac.h:3585
float zs[EX][EY]
Surface geopotential height [km].
Definition: mptrac.h:3591
float o3[EX][EY][EP]
Ozone volume mixing ratio [1].
Definition: mptrac.h:3678
float t[EX][EY][EP]
Temperature [K].
Definition: mptrac.h:3660
float pt[EX][EY]
Tropopause pressure [hPa].
Definition: mptrac.h:3618
float z[EX][EY][EP]
Geopotential height [km].
Definition: mptrac.h:3657
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 2106 of file mptrac.c.

2114 {
2115
2116 /* Check longitude... */
2117 *lon2 = FMOD(lon, 360.);
2118 if (*lon2 < lons[0])
2119 *lon2 += 360;
2120 else if (*lon2 > lons[nlon - 1])
2121 *lon2 -= 360;
2122
2123 /* Check latitude... */
2124 *lat2 = lat;
2125 if (lats[0] < lats[nlat - 1])
2126 *lat2 = MIN(MAX(*lat2, lats[0]), lats[nlat - 1]);
2127 else
2128 *lat2 = MIN(MAX(*lat2, lats[nlat - 1]), lats[0]);
2129}

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

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

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

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

2433 {
2434
2435 double var0, var1;
2436
2437 /* Spatial interpolation... */
2438 intpol_met_space_3d(met0, array0, p, lon, lat, &var0, ci, cw, init);
2439 intpol_met_space_3d(met1, array1, p, lon, lat, &var1, ci, cw, 0);
2440
2441 /* Get weighting factor... */
2442 const double wt = (met1->time - ts) / (met1->time - met0->time);
2443
2444 /* Interpolate... */
2445 *var = wt * (var0 - var1) + var1;
2446}
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 2450 of file mptrac.c.

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

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

2582 {
2583
2584 struct tm t0, *t1;
2585
2586 t0.tm_year = 100;
2587 t0.tm_mon = 0;
2588 t0.tm_mday = 1;
2589 t0.tm_hour = 0;
2590 t0.tm_min = 0;
2591 t0.tm_sec = 0;
2592
2593 const time_t jsec0 = (time_t) jsec + timegm(&t0);
2594 t1 = gmtime(&jsec0);
2595
2596 *year = t1->tm_year + 1900;
2597 *mon = t1->tm_mon + 1;
2598 *day = t1->tm_mday;
2599 *hour = t1->tm_hour;
2600 *min = t1->tm_min;
2601 *sec = t1->tm_sec;
2602 *remain = jsec - floor(jsec);
2603}

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

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

2635 {
2636
2637 /*
2638 Calculate moist adiabatic lapse rate [K/km] from temperature [K]
2639 and water vapor volume mixing ratio [1].
2640
2641 Reference: https://en.wikipedia.org/wiki/Lapse_rate
2642 */
2643
2644 const double a = RA * SQR(t), r = SH(h2o) / (1. - SH(h2o));
2645
2646 return 1e3 * G0 * (a + LV * r * t) / (CPD * a + SQR(LV) * r * EPS);
2647}
#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 2651 of file mptrac.c.

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

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

2864 {
2865
2866 int ilo = 0;
2867 int ihi = n - 1;
2868 int i = (ihi + ilo) >> 1;
2869
2870 if (xx[i] < xx[i + 1])
2871 while (ihi > ilo + 1) {
2872 i = (ihi + ilo) >> 1;
2873 if (xx[i] > x)
2874 ihi = i;
2875 else
2876 ilo = i;
2877 } else
2878 while (ihi > ilo + 1) {
2879 i = (ihi + ilo) >> 1;
2880 if (xx[i] <= x)
2881 ihi = i;
2882 else
2883 ilo = i;
2884 }
2885
2886 return ilo;
2887}

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

2895 {
2896
2897 int ilo = 0;
2898 int ihi = n - 1;
2899 int i = (ihi + ilo) >> 1;
2900
2901 if ((xx[ig] <= x && x < xx[ig + 1]) || (xx[ig] >= x && x > xx[ig + 1]))
2902 return ig;
2903
2904 if (xx[i] < xx[i + 1])
2905 while (ihi > ilo + 1) {
2906 i = (ihi + ilo) >> 1;
2907 if (xx[i] > x)
2908 ihi = i;
2909 else
2910 ilo = i;
2911 } else
2912 while (ihi > ilo + 1) {
2913 i = (ihi + ilo) >> 1;
2914 if (xx[i] <= x)
2915 ihi = i;
2916 else
2917 ilo = i;
2918 }
2919
2920 return ilo;
2921}

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

2928 {
2929
2930 /* Calculate index... */
2931 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2932
2933 /* Check range... */
2934 if (i < 0)
2935 return 0;
2936 else if (i > n - 2)
2937 return n - 2;
2938 else
2939 return i;
2940}

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

2950 {
2951
2952 ind[0] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind],
2953 np, height_ap, 0);
2954 ind[1] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind],
2955 np, height_ap, ind[0]);
2956 ind[2] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind + 1],
2957 np, height_ap, ind[1]);
2958 ind[3] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind + 1],
2959 np, height_ap, ind[2]);
2960}
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:2891
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 2964 of file mptrac.c.

2969 {
2970
2971 /* Set timer... */
2972 SELECT_TIMER("MODULE_ADVECT", "PHYSICS", NVTX_GPU);
2973
2974 /* Use omega vertical velocity... */
2975 if (ctl->advect_vert_coord == 0 || ctl->advect_vert_coord == 2) {
2976
2977 /* Loop over particles... */
2978 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2979
2980 /* Init... */
2982 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
2983 x[3] = { 0, 0, 0 };
2984
2985 /* Loop over integration nodes... */
2986 for (int i = 0; i < ctl->advect; i++) {
2987
2988 /* Set position... */
2989 if (i == 0) {
2990 dts = 0.0;
2991 x[0] = atm->lon[ip];
2992 x[1] = atm->lat[ip];
2993 x[2] = atm->p[ip];
2994 } else {
2995 dts = (i == 3 ? 1.0 : 0.5) * cache->dt[ip];
2996 x[0] = atm->lon[ip] + DX2DEG(dts * u[i - 1] / 1000., atm->lat[ip]);
2997 x[1] = atm->lat[ip] + DY2DEG(dts * v[i - 1] / 1000.);
2998 x[2] = atm->p[ip] + dts * w[i - 1];
2999 }
3000 const double tm = atm->time[ip] + dts;
3001
3002 /* Interpolate meteo data on pressure levels... */
3003 if (ctl->advect_vert_coord == 0) {
3004 intpol_met_time_3d(met0, met0->u, met1, met1->u,
3005 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3006 intpol_met_time_3d(met0, met0->v, met1, met1->v,
3007 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3008 intpol_met_time_3d(met0, met0->w, met1, met1->w,
3009 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3010 }
3011
3012 /* Interpolate meteo data on model levels... */
3013 else {
3014 intpol_met_4d_zeta(met0, met0->pl, met0->ul,
3015 met1, met1->pl, met1->ul,
3016 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3017 intpol_met_4d_zeta(met0, met0->pl, met0->vl,
3018 met1, met1->pl, met1->vl,
3019 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3020 intpol_met_4d_zeta(met0, met0->pl, met0->wl,
3021 met1, met1->pl, met1->wl,
3022 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3023 }
3024
3025 /* Get mean wind... */
3026 double k = 1.0;
3027 if (ctl->advect == 2)
3028 k = (i == 0 ? 0.0 : 1.0);
3029 else if (ctl->advect == 4)
3030 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3031 um += k * u[i];
3032 vm += k * v[i];
3033 wm += k * w[i];
3034 }
3035
3036 /* Set new position... */
3037 atm->time[ip] += cache->dt[ip];
3038 atm->lon[ip] += DX2DEG(cache->dt[ip] * um / 1000.,
3039 (ctl->advect == 2 ? x[1] : atm->lat[ip]));
3040 atm->lat[ip] += DY2DEG(cache->dt[ip] * vm / 1000.);
3041 atm->p[ip] += cache->dt[ip] * wm;
3042 }
3043 }
3044
3045 /* Use zeta or eta vertical velocity... */
3046 else if (ctl->advect_vert_coord == 1 || ctl->advect_vert_coord == 3) {
3047
3048 /* Select quantity index depending on coordinate... */
3049 const int qnt = (ctl->advect_vert_coord == 1
3050 ? ctl->qnt_zeta : ctl->qnt_eta);
3051
3052 /* Loop over particles... */
3053 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
3054
3055 /* Convert pressure to vertical coordinate (zeta or eta)... */
3057 intpol_met_4d_zeta(met0, met0->pl, met0->zetal,
3058 met1, met1->pl, met1->zetal,
3059 atm->time[ip], atm->p[ip],
3060 atm->lon[ip], atm->lat[ip],
3061 &atm->q[qnt][ip], ci, cw, 1);
3062
3063 /* Init... */
3064 double dts, u[4], um = 0, v[4], vm = 0, wdot[4],
3065 wdotm = 0, x[3] = { 0, 0, 0 };
3066
3067 /* Loop over integration nodes (Runge–Kutta steps)... */
3068 for (int i = 0; i < ctl->advect; i++) {
3069
3070 /* Set position... */
3071 if (i == 0) {
3072 dts = 0.0;
3073 x[0] = atm->lon[ip];
3074 x[1] = atm->lat[ip];
3075 x[2] = atm->q[qnt][ip];
3076 } else {
3077 dts = (i == 3 ? 1.0 : 0.5) * cache->dt[ip];
3078 x[0] = atm->lon[ip] + DX2DEG(dts * u[i - 1] / 1000., atm->lat[ip]);
3079 x[1] = atm->lat[ip] + DY2DEG(dts * v[i - 1] / 1000.);
3080 x[2] = atm->q[qnt][ip] + dts * wdot[i - 1];
3081 }
3082
3083 const double tm = atm->time[ip] + dts;
3084
3085 /* Interpolate meteo data... */
3086 intpol_met_4d_zeta(met0, met0->zetal, met0->ul,
3087 met1, met1->zetal, met1->ul,
3088 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3089 intpol_met_4d_zeta(met0, met0->zetal, met0->vl,
3090 met1, met1->zetal, met1->vl,
3091 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3092 intpol_met_4d_zeta(met0, met0->zetal, met0->zeta_dotl,
3093 met1, met1->zetal, met1->zeta_dotl,
3094 tm, x[2], x[0], x[1], &wdot[i], ci, cw, 0);
3095
3096 /* Compute Runge–Kutta weights... */
3097 double k = 1.0;
3098 if (ctl->advect == 2)
3099 k = (i == 0 ? 0.0 : 1.0);
3100 else if (ctl->advect == 4)
3101 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3102
3103 um += k * u[i];
3104 vm += k * v[i];
3105 wdotm += k * wdot[i];
3106 }
3107
3108 /* Update particle position... */
3109 atm->time[ip] += cache->dt[ip];
3110 atm->lon[ip] += DX2DEG(cache->dt[ip] * um / 1000.,
3111 (ctl->advect == 2 ? x[1] : atm->lat[ip]));
3112 atm->lat[ip] += DY2DEG(cache->dt[ip] * vm / 1000.);
3113 atm->q[qnt][ip] += cache->dt[ip] * wdotm;
3114
3115 /* Convert vertical coordinate (zeta or eta) back to pressure... */
3116 intpol_met_4d_zeta(met0, met0->zetal, met0->pl,
3117 met1, met1->zetal, met1->pl,
3118 atm->time[ip],
3119 atm->q[qnt][ip], atm->lon[ip], atm->lat[ip],
3120 &atm->p[ip], ci, cw, 1);
3121 }
3122 }
3123}
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:2421
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:2133
#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:3298
double lat[NP]
Latitude [deg].
Definition: mptrac.h:3307
double lon[NP]
Longitude [deg].
Definition: mptrac.h:3304
int np
Number of air parcels.
Definition: mptrac.h:3295
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
Definition: mptrac.h:3310
double p[NP]
Pressure [hPa].
Definition: mptrac.h:3301
double dt[NP]
Timesteps [s].
Definition: mptrac.h:3368
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:2773
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:2777
float zeta_dotl[EX][EY][EP]
Vertical velocity on model levels [K/s].
Definition: mptrac.h:3711
float w[EX][EY][EP]
Vertical velocity [hPa/s].
Definition: mptrac.h:3669
float wl[EX][EY][EP]
Vertical velocity on model levels [hPa/s].
Definition: mptrac.h:3705
float vl[EX][EY][EP]
Meridional wind on model levels [m/s].
Definition: mptrac.h:3702
float u[EX][EY][EP]
Zonal wind [m/s].
Definition: mptrac.h:3663
float ul[EX][EY][EP]
Zonal wind on model levels [m/s].
Definition: mptrac.h:3699
float v[EX][EY][EP]
Meridional wind [m/s].
Definition: mptrac.h:3666
float pl[EX][EY][EP]
Pressure on model levels [hPa].
Definition: mptrac.h:3696
float zetal[EX][EY][EP]
Zeta on model levels [K].
Definition: mptrac.h:3708
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 3127 of file mptrac.c.

3132 {
3133
3134 /* Check parameters... */
3135 if (ctl->advect_vert_coord != 1)
3136 return;
3137
3138 /* Set timer... */
3139 SELECT_TIMER("MODULE_ADVECT_INIT", "PHYSICS", NVTX_GPU);
3140
3141 /* Loop over particles... */
3142 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,met0,met1,atm)") {
3143
3144 /* Initialize pressure consistent with zeta... */
3146 intpol_met_4d_zeta(met0, met0->zetal, met0->pl, met1, met1->zetal,
3147 met1->pl, atm->time[ip], atm->q[ctl->qnt_zeta][ip],
3148 atm->lon[ip], atm->lat[ip], &atm->p[ip], ci, cw, 1);
3149 }
3150}
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 3154 of file mptrac.c.

3160 {
3161
3162 /* Set timer... */
3163 SELECT_TIMER("MODULE_BOUND_COND", "PHYSICS", NVTX_GPU);
3164
3165 /* Check quantity flags... */
3166 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0 && ctl->qnt_Cccl4
3167 && ctl->qnt_Cccl3f < 0 && ctl->qnt_Cccl2f2 < 0
3168 && ctl->qnt_Cn2o < 0 && ctl->qnt_Csf6 < 0 && ctl->qnt_aoa < 0)
3169 return;
3170
3171 /* Loop over particles... */
3172 PARTICLE_LOOP(0, atm->np, 1,
3173 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3174
3175 /* Check latitude and pressure range... */
3176 if (atm->lat[ip] < ctl->bound_lat0 || atm->lat[ip] > ctl->bound_lat1
3177 || atm->p[ip] > ctl->bound_p0 || atm->p[ip] < ctl->bound_p1)
3178 continue;
3179
3180 /* Check surface layer... */
3181 if (ctl->bound_dps > 0 || ctl->bound_dzs > 0
3182 || ctl->bound_zetas > 0 || ctl->bound_pbl) {
3183
3184 /* Get surface pressure... */
3185 double ps;
3187 INTPOL_2D(ps, 1);
3188
3189 /* Check pressure... */
3190 if (ctl->bound_dps > 0 && atm->p[ip] < ps - ctl->bound_dps)
3191 continue;
3192
3193 /* Check height... */
3194 if (ctl->bound_dzs > 0 && Z(atm->p[ip]) > Z(ps) + ctl->bound_dzs)
3195 continue;
3196
3197 /* Check zeta range... */
3198 if (ctl->bound_zetas > 0) {
3199 double t;
3200 INTPOL_3D(t, 1);
3201 if (ZETA(ps, atm->p[ip], t) > ctl->bound_zetas)
3202 continue;
3203 }
3204
3205 /* Check planetary boundary layer... */
3206 if (ctl->bound_pbl) {
3207 double pbl;
3208 INTPOL_2D(pbl, 0);
3209 if (atm->p[ip] < pbl)
3210 continue;
3211 }
3212 }
3213
3214 /* Set mass and volume mixing ratio... */
3215 if (ctl->qnt_m >= 0 && ctl->bound_mass >= 0)
3216 atm->q[ctl->qnt_m][ip] =
3217 ctl->bound_mass + ctl->bound_mass_trend * atm->time[ip];
3218 if (ctl->qnt_vmr >= 0 && ctl->bound_vmr >= 0)
3219 atm->q[ctl->qnt_vmr][ip] =
3220 ctl->bound_vmr + ctl->bound_vmr_trend * atm->time[ip];
3221
3222 /* Set CFC-10 volume mixing ratio... */
3223 if (ctl->qnt_Cccl4 >= 0 && ctl->clim_ccl4_timeseries[0] != '-')
3224 atm->q[ctl->qnt_Cccl4][ip] = clim_ts(&clim->ccl4, atm->time[ip]);
3225
3226 /* Set CFC-11 volume mixing ratio... */
3227 if (ctl->qnt_Cccl3f >= 0 && ctl->clim_ccl3f_timeseries[0] != '-')
3228 atm->q[ctl->qnt_Cccl3f][ip] = clim_ts(&clim->ccl3f, atm->time[ip]);
3229
3230 /* Set CFC-12 volume mixing ratio... */
3231 if (ctl->qnt_Cccl2f2 >= 0 && ctl->clim_ccl2f2_timeseries[0] != '-')
3232 atm->q[ctl->qnt_Cccl2f2][ip] = clim_ts(&clim->ccl2f2, atm->time[ip]);
3233
3234 /* Set N2O volume mixing ratio... */
3235 if (ctl->qnt_Cn2o >= 0 && ctl->clim_n2o_timeseries[0] != '-')
3236 atm->q[ctl->qnt_Cn2o][ip] = clim_ts(&clim->n2o, atm->time[ip]);
3237
3238 /* Set SF6 volume mixing ratio... */
3239 if (ctl->qnt_Csf6 >= 0 && ctl->clim_sf6_timeseries[0] != '-')
3240 atm->q[ctl->qnt_Csf6][ip] = clim_ts(&clim->sf6, atm->time[ip]);
3241
3242 /* Set age of air... */
3243 if (ctl->qnt_aoa >= 0)
3244 atm->q[ctl->qnt_aoa][ip] = atm->time[ip];
3245 }
3246}
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:3529
clim_ts_t sf6
SF6 time series.
Definition: mptrac.h:3535
clim_ts_t ccl4
CFC-10 time series.
Definition: mptrac.h:3523
clim_ts_t ccl3f
CFC-11 time series.
Definition: mptrac.h:3526
clim_ts_t n2o
N2O time series.
Definition: mptrac.h:3532
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:2903
double bound_dzs
Boundary conditions surface layer depth [km].
Definition: mptrac.h:2852
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:2825
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:2840
int bound_pbl
Boundary conditions planetary boundary layer (0=no, 1=yes).
Definition: mptrac.h:2858
double bound_p1
Boundary conditions top pressure [hPa].
Definition: mptrac.h:2846
double bound_vmr
Boundary conditions volume mixing ratio [ppv].
Definition: mptrac.h:2831
double bound_lat0
Boundary conditions minimum longitude [deg].
Definition: mptrac.h:2837
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
Definition: mptrac.h:2834
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:2849
double bound_mass_trend
Boundary conditions mass per particle trend [kg/s].
Definition: mptrac.h:2828
double bound_p0
Boundary conditions bottom pressure [hPa].
Definition: mptrac.h:2843
char clim_ccl4_timeseries[LEN]
Filename of CFC-10 time series.
Definition: mptrac.h:2894
char clim_sf6_timeseries[LEN]
Filename of SF6 time series.
Definition: mptrac.h:2906
char clim_ccl3f_timeseries[LEN]
Filename of CFC-11 time series.
Definition: mptrac.h:2897
char clim_ccl2f2_timeseries[LEN]
Filename of CFC-12 time series.
Definition: mptrac.h:2900
double bound_zetas
Boundary conditions surface layer zeta [K].
Definition: mptrac.h:2855
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 3250 of file mptrac.c.

3255 {
3256
3257 /* Check quantities... */
3258 if (ctl->qnt_m < 0 || ctl->qnt_Cx < 0)
3259 return;
3260 if (ctl->molmass <= 0)
3261 ERRMSG("Molar mass is not defined!");
3262
3263 /* Set timer... */
3264 SELECT_TIMER("MODULE_CHEM_GRID", "PHYSICS", NVTX_GPU);
3265
3266 /* Allocate... */
3267 const int ensemble_mode = (ctl->nens > 0);
3268 const int np = atm->np;
3269 const int nz = ctl->chemgrid_nz;
3270 const int nx = ctl->chemgrid_nx;
3271 const int ny = ctl->chemgrid_ny;
3272 const int ngrid = nx * ny * nz;
3273 const int nens = ensemble_mode ? ctl->nens : 1;
3274
3275 double *restrict const z = (double *) malloc((size_t) nz * sizeof(double));
3276 double *restrict const press =
3277 (double *) malloc((size_t) nz * sizeof(double));
3278 double *restrict const mass =
3279 (double *) calloc((size_t) ngrid * (size_t) nens, sizeof(double));
3280 double *restrict const area =
3281 (double *) malloc((size_t) ny * sizeof(double));
3282 double *restrict const lon =
3283 (double *) malloc((size_t) nx * sizeof(double));
3284 double *restrict const lat =
3285 (double *) malloc((size_t) ny * sizeof(double));
3286
3287 int *restrict const ixs = (int *) malloc((size_t) np * sizeof(int));
3288 int *restrict const iys = (int *) malloc((size_t) np * sizeof(int));
3289 int *restrict const izs = (int *) malloc((size_t) np * sizeof(int));
3290
3291 /* Set grid box size... */
3292 const double dz = (ctl->chemgrid_z1 - ctl->chemgrid_z0) / nz;
3293 const double dlon = (ctl->chemgrid_lon1 - ctl->chemgrid_lon0) / nx;
3294 const double dlat = (ctl->chemgrid_lat1 - ctl->chemgrid_lat0) / ny;
3295
3296 /* Set vertical coordinates... */
3297#ifdef _OPENACC
3298#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])
3299#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
3300#pragma acc parallel loop independent gang vector
3301#else
3302#pragma omp parallel for default(shared)
3303#endif
3304 for (int iz = 0; iz < nz; iz++) {
3305 z[iz] = ctl->chemgrid_z0 + dz * (iz + 0.5);
3306 press[iz] = P(z[iz]);
3307 }
3308
3309 /* Set time interval for output... */
3310 const double t0 = tt - 0.5 * ctl->dt_mod;
3311 const double t1 = tt + 0.5 * ctl->dt_mod;
3312
3313 /* Get indices... */
3314#ifdef _OPENACC
3315#pragma acc parallel loop independent gang vector
3316#else
3317#pragma omp parallel for default(shared)
3318#endif
3319 for (int ip = 0; ip < np; ip++) {
3320 ixs[ip] = (int) ((atm->lon[ip] - ctl->chemgrid_lon0) / dlon);
3321 iys[ip] = (int) ((atm->lat[ip] - ctl->chemgrid_lat0) / dlat);
3322 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->chemgrid_z0) / dz);
3323 if (atm->time[ip] < t0 || atm->time[ip] > t1
3324 || ixs[ip] < 0 || ixs[ip] >= nx
3325 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
3326 izs[ip] = -1;
3327 }
3328
3329 /* Set horizontal coordinates... */
3330#ifdef _OPENACC
3331#pragma acc parallel loop independent gang vector
3332#else
3333#pragma omp parallel for default(shared)
3334#endif
3335 for (int ix = 0; ix < nx; ix++)
3336 lon[ix] = ctl->chemgrid_lon0 + dlon * (ix + 0.5);
3337
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 iy = 0; iy < ny; iy++) {
3344 lat[iy] = ctl->chemgrid_lat0 + dlat * (iy + 0.5);
3345 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
3346 }
3347
3348 /* Get mass per grid box... */
3349#ifdef _OPENACC
3350#pragma acc parallel loop independent gang vector
3351#endif
3352 for (int ip = 0; ip < np; ip++) {
3353 if (izs[ip] >= 0) {
3354 int mass_idx = ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3355 if (ensemble_mode) {
3356 const int ens = (int) atm->q[ctl->qnt_ens][ip];
3357 mass_idx += ens * ngrid;
3358 }
3359#ifdef _OPENACC
3360#pragma acc atomic update
3361#endif
3362 mass[mass_idx] += atm->q[ctl->qnt_m][ip];
3363 }
3364 }
3365
3366 /* Assign grid data to air parcels ... */
3367#ifdef _OPENACC
3368#pragma acc parallel loop independent gang vector
3369#else
3370#pragma omp parallel for default(shared)
3371#endif
3372 for (int ip = 0; ip < np; ip++)
3373 if (izs[ip] >= 0) {
3374
3375 /* Interpolate temperature... */
3376 double temp;
3378 intpol_met_time_3d(met0, met0->t, met1, met1->t, tt,
3379 press[izs[ip]],
3380 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
3381
3382 /* Set mass... */
3383 int mass_idx = ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3384 if (ensemble_mode) {
3385 const int ens = (int) atm->q[ctl->qnt_ens][ip];
3386 mass_idx += ens * ngrid;
3387 }
3388
3389 /* Calculate volume mixing ratio... */
3390 const double m = mass[mass_idx];
3391 atm->q[ctl->qnt_Cx][ip] = MA / ctl->molmass * m
3392 / (RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
3393 }
3394
3395 /* Free... */
3396#ifdef _OPENACC
3397#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
3398#endif
3399 free(mass);
3400 free(lon);
3401 free(lat);
3402 free(area);
3403 free(z);
3404 free(press);
3405 free(ixs);
3406 free(iys);
3407 free(izs);
3408}
#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:2864
double chemgrid_z1
Upper altitude of chemistry grid [km].
Definition: mptrac.h:2951
double chemgrid_z0
Lower altitude of chemistry grid [km].
Definition: mptrac.h:2948
double chemgrid_lat0
Lower latitude of chemistry grid [deg].
Definition: mptrac.h:2966
double chemgrid_lat1
Upper latitude of chemistry grid [deg].
Definition: mptrac.h:2969
double chemgrid_lon0
Lower longitude of chemistry grid [deg].
Definition: mptrac.h:2957
double chemgrid_lon1
Upper longitude of chemistry grid [deg].
Definition: mptrac.h:2960
double dt_mod
Time step of simulation [s].
Definition: mptrac.h:2583
int nens
Number of ensembles.
Definition: mptrac.h:3117
int chemgrid_nz
Number of altitudes of chemistry grid.
Definition: mptrac.h:2945
int chemgrid_nx
Number of longitudes of chemistry grid.
Definition: mptrac.h:2954
int chemgrid_ny
Number of latitudes of chemistry grid.
Definition: mptrac.h:2963
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 3412 of file mptrac.c.

3418 {
3419
3420 /* Set timer... */
3421 SELECT_TIMER("MODULE_CHEM_INIT", "PHYSICS", NVTX_GPU);
3422
3423 /* Loop over particles... */
3424 PARTICLE_LOOP(0, atm->np, 0,
3425 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3426
3427 /* Set H2O and O3 using meteo data... */
3429 if (ctl->qnt_Ch2o >= 0) {
3430 double h2o;
3431 INTPOL_3D(h2o, 1);
3432 SET_ATM(qnt_Ch2o, h2o);
3433 }
3434 if (ctl->qnt_Co3 >= 0) {
3435 double o3;
3436 INTPOL_3D(o3, 1);
3437 SET_ATM(qnt_Co3, o3);
3438 }
3439
3440 /* Set radical species... */
3441 SET_ATM(qnt_Coh, clim_oh(ctl, clim, atm->time[ip],
3442 atm->lon[ip], atm->lat[ip], atm->p[ip]));
3443 SET_ATM(qnt_Cho2, clim_zm(&clim->ho2, atm->time[ip],
3444 atm->lat[ip], atm->p[ip]));
3445 SET_ATM(qnt_Ch2o2, clim_zm(&clim->h2o2, atm->time[ip],
3446 atm->lat[ip], atm->p[ip]));
3447 SET_ATM(qnt_Co1d, clim_zm(&clim->o1d, atm->time[ip],
3448 atm->lat[ip], atm->p[ip]));
3449 }
3450}
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:3517
clim_zm_t o1d
O(1D) zonal means.
Definition: mptrac.h:3520
clim_zm_t h2o2
H2O2 zonal means.
Definition: mptrac.h:3514
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 3454 of file mptrac.c.

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

3571 {
3572
3573 /* Set timer... */
3574 SELECT_TIMER("MODULE_DECAY", "PHYSICS", NVTX_GPU);
3575
3576 /* Check quantity flags... */
3577 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
3578 ERRMSG("Module needs quantity mass or volume mixing ratio!");
3579
3580 /* Loop over particles... */
3581 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,clim,atm)") {
3582
3583 /* Get weighting factor... */
3584 const double w = tropo_weight(clim, atm, ip);
3585
3586 /* Set lifetime... */
3587 const double tdec = w * ctl->tdec_trop + (1 - w) * ctl->tdec_strat;
3588
3589 /* Calculate exponential decay... */
3590 const double aux = exp(-cache->dt[ip] / tdec);
3591 if (ctl->qnt_m >= 0) {
3592 if (ctl->qnt_mloss_decay >= 0)
3593 atm->q[ctl->qnt_mloss_decay][ip]
3594 += atm->q[ctl->qnt_m][ip] * (1 - aux);
3595 atm->q[ctl->qnt_m][ip] *= aux;
3596 if (ctl->qnt_loss_rate >= 0)
3597 atm->q[ctl->qnt_loss_rate][ip] += 1. / tdec;
3598 }
3599 if (ctl->qnt_vmr >= 0)
3600 atm->q[ctl->qnt_vmr][ip] *= aux;
3601 }
3602}
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:11246
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:2870
double tdec_trop
Life time of particles in the troposphere [s].
Definition: mptrac.h:2867
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 3606 of file mptrac.c.

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

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

3814 {
3815
3816 /* Set timer... */
3817 SELECT_TIMER("MODULE_DIFF_TURB", "PHYSICS", NVTX_GPU);
3818
3819 /* Create random numbers... */
3820 module_rng(ctl, cache->rs, 3 * (size_t) atm->np, 1);
3821
3822 /* Loop over particles... */
3823 PARTICLE_LOOP(0, atm->np, 1,
3824 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3825
3826 /* Get PBL and surface pressure... */
3827 double pbl, ps;
3829 INTPOL_2D(pbl, 1);
3830 INTPOL_2D(ps, 0);
3831
3832 /* Get weighting factors... */
3833 const double wpbl = pbl_weight(ctl, atm, ip, pbl, ps);
3834 const double wtrop = tropo_weight(clim, atm, ip) * (1.0 - wpbl);
3835 const double wstrat = 1.0 - wpbl - wtrop;
3836
3837 /* Set diffusivity... */
3838 const double dx = wpbl * ctl->turb_dx_pbl + wtrop * ctl->turb_dx_trop
3839 + wstrat * ctl->turb_dx_strat;
3840 const double dz = wpbl * ctl->turb_dz_pbl + wtrop * ctl->turb_dz_trop
3841 + wstrat * ctl->turb_dz_strat;
3842
3843 /* Horizontal turbulent diffusion... */
3844 if (dx > 0) {
3845 const double sigma = sqrt(2.0 * dx * fabs(cache->dt[ip])) / 1000.;
3846 atm->lon[ip] += DX2DEG(cache->rs[3 * ip] * sigma, atm->lat[ip]);
3847 atm->lat[ip] += DY2DEG(cache->rs[3 * ip + 1] * sigma);
3848 }
3849
3850 /* Vertical turbulent diffusion... */
3851 if (dz > 0) {
3852 const double sigma = sqrt(2.0 * dz * fabs(cache->dt[ip])) / 1000.;
3853 atm->p[ip] += DZ2DP(cache->rs[3 * ip + 2] * sigma, atm->p[ip]);
3854 }
3855 }
3856}
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:6985
double turb_dz_trop
Vertical turbulent diffusion coefficient (troposphere) [m^2/s].
Definition: mptrac.h:2798
double turb_dx_strat
Horizontal turbulent diffusion coefficient (stratosphere) [m^2/s].
Definition: mptrac.h:2792
double turb_dx_trop
Horizontal turbulent diffusion coefficient (troposphere) [m^2/s].
Definition: mptrac.h:2789
double turb_dx_pbl
Horizontal turbulent diffusion coefficient (PBL) [m^2/s].
Definition: mptrac.h:2786
double turb_dz_strat
Vertical turbulent diffusion coefficient (stratosphere) [m^2/s].
Definition: mptrac.h:2801
double turb_dz_pbl
Vertical turbulent diffusion coefficient (PBL) [m^2/s].
Definition: mptrac.h:2795
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 3860 of file mptrac.c.

3865 {
3866
3867 /* Set timer... */
3868 SELECT_TIMER("MODULE_DRY_DEPO", "PHYSICS", NVTX_GPU);
3869
3870 /* Check quantity flags... */
3871 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0)
3872 ERRMSG("Module needs quantity mass or volume mixing ratio!");
3873
3874 /* Loop over particles... */
3875 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
3876
3877 /* Get surface pressure... */
3878 double ps;
3880 INTPOL_2D(ps, 1);
3881
3882 /* Check whether particle is above the surface layer... */
3883 if (atm->p[ip] < ps - ctl->dry_depo_dp)
3884 continue;
3885
3886 /* Set depth of surface layer... */
3887 const double dz = 1000. * (Z(ps - ctl->dry_depo_dp) - Z(ps));
3888
3889 /* Calculate sedimentation velocity for particles... */
3890 double v_dep;
3891 if (ctl->qnt_rp > 0 && ctl->qnt_rhop > 0) {
3892
3893 /* Get temperature... */
3894 double t;
3895 INTPOL_3D(t, 1);
3896
3897 /* Set deposition velocity... */
3898 v_dep = sedi(atm->p[ip], t, atm->q[ctl->qnt_rp][ip],
3899 atm->q[ctl->qnt_rhop][ip]);
3900 }
3901
3902 /* Use explicit sedimentation velocity for gases... */
3903 else
3904 v_dep = ctl->dry_depo_vdep;
3905
3906 /* Calculate loss of mass based on deposition velocity... */
3907 const double aux = exp(-cache->dt[ip] * v_dep / dz);
3908 if (ctl->qnt_m >= 0) {
3909 if (ctl->qnt_mloss_dry >= 0)
3910 atm->q[ctl->qnt_mloss_dry][ip]
3911 += atm->q[ctl->qnt_m][ip] * (1 - aux);
3912 atm->q[ctl->qnt_m][ip] *= aux;
3913 if (ctl->qnt_loss_rate >= 0)
3914 atm->q[ctl->qnt_loss_rate][ip] += v_dep / dz;
3915 }
3916 if (ctl->qnt_vmr >= 0)
3917 atm->q[ctl->qnt_vmr][ip] *= aux;
3918 }
3919}
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:11011
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:3023
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:3026
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 3923 of file mptrac.c.

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

4010 {
4011
4012 double t;
4013
4014 /* Set timer... */
4015 SELECT_TIMER("MODULE_ISOSURF_INIT", "PHYSICS", NVTX_GPU);
4016
4017 /* Save pressure... */
4018 if (ctl->isosurf == 1) {
4019 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,atm)") {
4020 cache->iso_var[ip] = atm->p[ip];
4021 }
4022 }
4023
4024 /* Save density... */
4025 else if (ctl->isosurf == 2) {
4026 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,met0,met1,atm)") {
4028 INTPOL_3D(t, 1);
4029 cache->iso_var[ip] = atm->p[ip] / t;
4030 }
4031 }
4032
4033 /* Save potential temperature... */
4034 else if (ctl->isosurf == 3) {
4035 PARTICLE_LOOP(0, atm->np, 0, "acc data present(cache,met0,met1,atm)") {
4037 INTPOL_3D(t, 1);
4038 cache->iso_var[ip] = THETA(atm->p[ip], t);
4039 }
4040 }
4041
4042 /* Read balloon pressure data... */
4043 else if (ctl->isosurf == 4) {
4044
4045 /* Write info... */
4046 LOG(1, "Read balloon pressure data: %s", ctl->balloon);
4047
4048 /* Open file... */
4049 FILE *in;
4050 if (!(in = fopen(ctl->balloon, "r")))
4051 ERRMSG("Cannot open file!");
4052
4053 /* Read pressure time series... */
4054 char line[LEN];
4055 while (fgets(line, LEN, in))
4056 if (sscanf(line, "%lg %lg", &(cache->iso_ts[cache->iso_n]),
4057 &(cache->iso_ps[cache->iso_n])) == 2)
4058 if ((++cache->iso_n) > NP)
4059 ERRMSG("Too many data points!");
4060
4061 /* Check number of points... */
4062 if (cache->iso_n < 1)
4063 ERRMSG("Could not read any data!");
4064
4065 /* Close file... */
4066 fclose(in);
4067
4068 /* Update of cache data on device... */
4069 mptrac_update_device(NULL, cache, NULL, NULL, NULL, NULL);
4070 }
4071}
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:6654
#define NP
Maximum number of atmospheric data points.
Definition: mptrac.h:308
double iso_ts[NP]
Isosurface balloon time [s].
Definition: mptrac.h:3356
int iso_n
Isosurface balloon number of data points.
Definition: mptrac.h:3359
double iso_ps[NP]
Isosurface balloon pressure [hPa].
Definition: mptrac.h:3353
double iso_var[NP]
Isosurface variables.
Definition: mptrac.h:3350
char balloon[LEN]
Balloon position filename.
Definition: mptrac.h:2770
int isosurf
Isosurface parameter (0=none, 1=pressure, 2=density, 3=theta, 4=balloon).
Definition: mptrac.h:2767
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 4075 of file mptrac.c.

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

4187 {
4188
4189 /* Set timer... */
4190 SELECT_TIMER("MODULE_METEO", "PHYSICS", NVTX_GPU);
4191
4192 /* Check quantity flags... */
4193 if (ctl->qnt_tsts >= 0)
4194 if (ctl->qnt_tice < 0 || ctl->qnt_tnat < 0)
4195 ERRMSG("Need T_ice and T_NAT to calculate T_STS!");
4196
4197 /* Loop over particles... */
4198 PARTICLE_LOOP(0, atm->np, 0,
4199 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4200
4201 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
4202 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
4203 o3, lwc, rwc, iwc, swc, cc, z, zt;
4204
4205 /* Interpolate meteo data... */
4207 INTPOL_TIME_ALL(atm->time[ip], atm->p[ip], atm->lon[ip], atm->lat[ip]);
4208
4209 /* Set quantities... */
4210 SET_ATM(qnt_ps, ps);
4211 SET_ATM(qnt_ts, ts);
4212 SET_ATM(qnt_zs, zs);
4213 SET_ATM(qnt_us, us);
4214 SET_ATM(qnt_vs, vs);
4215 SET_ATM(qnt_ess, ess);
4216 SET_ATM(qnt_nss, nss);
4217 SET_ATM(qnt_shf, shf);
4218 SET_ATM(qnt_lsm, lsm);
4219 SET_ATM(qnt_sst, sst);
4220 SET_ATM(qnt_pbl, pbl);
4221 SET_ATM(qnt_pt, pt);
4222 SET_ATM(qnt_tt, tt);
4223 SET_ATM(qnt_zt, zt);
4224 SET_ATM(qnt_h2ot, h2ot);
4225 SET_ATM(qnt_zg, z);
4226 SET_ATM(qnt_p, atm->p[ip]);
4227 SET_ATM(qnt_t, t);
4228 SET_ATM(qnt_rho, RHO(atm->p[ip], t));
4229 SET_ATM(qnt_u, u);
4230 SET_ATM(qnt_v, v);
4231 SET_ATM(qnt_w, w);
4232 SET_ATM(qnt_h2o, h2o);
4233 SET_ATM(qnt_o3, o3);
4234 SET_ATM(qnt_lwc, lwc);
4235 SET_ATM(qnt_rwc, rwc);
4236 SET_ATM(qnt_iwc, iwc);
4237 SET_ATM(qnt_swc, swc);
4238 SET_ATM(qnt_cc, cc);
4239 SET_ATM(qnt_pct, pct);
4240 SET_ATM(qnt_pcb, pcb);
4241 SET_ATM(qnt_cl, cl);
4242 SET_ATM(qnt_plcl, plcl);
4243 SET_ATM(qnt_plfc, plfc);
4244 SET_ATM(qnt_pel, pel);
4245 SET_ATM(qnt_cape, cape);
4246 SET_ATM(qnt_cin, cin);
4247 SET_ATM(qnt_o3c, o3c);
4248 SET_ATM(qnt_hno3,
4249 clim_zm(&clim->hno3, atm->time[ip], atm->lat[ip], atm->p[ip]));
4250 SET_ATM(qnt_oh, clim_oh(ctl, clim, atm->time[ip],
4251 atm->lon[ip], atm->lat[ip], atm->p[ip]));
4252 SET_ATM(qnt_h2o2, clim_zm(&clim->h2o2, atm->time[ip],
4253 atm->lat[ip], atm->p[ip]));
4254 SET_ATM(qnt_ho2, clim_zm(&clim->ho2, atm->time[ip],
4255 atm->lat[ip], atm->p[ip]));
4256 SET_ATM(qnt_o1d, clim_zm(&clim->o1d, atm->time[ip],
4257 atm->lat[ip], atm->p[ip]));
4258 SET_ATM(qnt_vh, sqrt(u * u + v * v));
4259 SET_ATM(qnt_vz, -1e3 * H0 / atm->p[ip] * w);
4260 SET_ATM(qnt_psat, PSAT(t));
4261 SET_ATM(qnt_psice, PSICE(t));
4262 SET_ATM(qnt_pw, PW(atm->p[ip], h2o));
4263 SET_ATM(qnt_sh, SH(h2o));
4264 SET_ATM(qnt_rh, RH(atm->p[ip], t, h2o));
4265 SET_ATM(qnt_rhice, RHICE(atm->p[ip], t, h2o));
4266 SET_ATM(qnt_theta, THETA(atm->p[ip], t));
4267 SET_ATM(qnt_zeta, atm->q[ctl->qnt_zeta][ip]);
4268 SET_ATM(qnt_zeta_d, ZETA(ps, atm->p[ip], t));
4269 SET_ATM(qnt_zeta_dot, atm->q[ctl->qnt_zeta_dot][ip]);
4270 SET_ATM(qnt_eta, atm->q[ctl->qnt_eta][ip]);
4271 SET_ATM(qnt_eta_dot, atm->q[ctl->qnt_eta_dot][ip]);
4272 SET_ATM(qnt_tvirt, TVIRT(t, h2o));
4273 SET_ATM(qnt_lapse, lapse_rate(t, h2o));
4274 SET_ATM(qnt_pv, pv);
4275 SET_ATM(qnt_tdew, TDEW(atm->p[ip], h2o));
4276 SET_ATM(qnt_tice, TICE(atm->p[ip], h2o));
4277 SET_ATM(qnt_tnat,
4278 nat_temperature(atm->p[ip], h2o,
4279 clim_zm(&clim->hno3, atm->time[ip],
4280 atm->lat[ip], atm->p[ip])));
4281 SET_ATM(qnt_tsts,
4282 0.5 * (atm->q[ctl->qnt_tice][ip] + atm->q[ctl->qnt_tnat][ip]));
4283 }
4284}
double nat_temperature(const double p, const double h2o, const double hno3)
Calculates the nitric acid trihydrate (NAT) temperature.
Definition: mptrac.c:6961
double lapse_rate(const double t, const double h2o)
Calculates the moist adiabatic lapse rate in Kelvin per kilometer.
Definition: mptrac.c:2633
#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:3508
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 4288 of file mptrac.c.

4292 {
4293
4294 /* Set timer... */
4295 SELECT_TIMER("MODULE_MIXING", "PHYSICS", NVTX_GPU);
4296
4297 /* Allocate... */
4298 const int np = atm->np;
4299 int *restrict const ixs = (int *) malloc((size_t) np * sizeof(int));
4300 int *restrict const iys = (int *) malloc((size_t) np * sizeof(int));
4301 int *restrict const izs = (int *) malloc((size_t) np * sizeof(int));
4302
4303 /* Set grid box size... */
4304 const double dz = (ctl->mixing_z1 - ctl->mixing_z0) / ctl->mixing_nz;
4305 const double dlon = (ctl->mixing_lon1 - ctl->mixing_lon0) / ctl->mixing_nx;
4306 const double dlat = (ctl->mixing_lat1 - ctl->mixing_lat0) / ctl->mixing_ny;
4307
4308 /* Set time interval... */
4309 const double t0 = t - 0.5 * ctl->dt_mod;
4310 const double t1 = t + 0.5 * ctl->dt_mod;
4311
4312 /* Get indices... */
4313#ifdef _OPENACC
4314#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
4315#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
4316#pragma acc parallel loop independent gang vector
4317#else
4318#pragma omp parallel for default(shared)
4319#endif
4320 for (int ip = 0; ip < np; ip++) {
4321 ixs[ip] = (int) ((atm->lon[ip] - ctl->mixing_lon0) / dlon);
4322 iys[ip] = (int) ((atm->lat[ip] - ctl->mixing_lat0) / dlat);
4323 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->mixing_z0) / dz);
4324 if (atm->time[ip] < t0 || atm->time[ip] > t1
4325 || ixs[ip] < 0 || ixs[ip] >= ctl->mixing_nx
4326 || iys[ip] < 0 || iys[ip] >= ctl->mixing_ny
4327 || izs[ip] < 0 || izs[ip] >= ctl->mixing_nz)
4328 izs[ip] = -1;
4329 }
4330
4331 /* Calculate interparcel mixing... */
4332 const int use_ensemble = (ctl->nens > 0);
4333
4334 const int quantities[] = {
4335 ctl->qnt_m, ctl->qnt_vmr, ctl->qnt_Ch2o, ctl->qnt_Co3,
4336 ctl->qnt_Cco, ctl->qnt_Coh, ctl->qnt_Ch, ctl->qnt_Cho2,
4337 ctl->qnt_Ch2o2, ctl->qnt_Co1d, ctl->qnt_Co3p, ctl->qnt_Cccl4,
4338 ctl->qnt_Cccl3f, ctl->qnt_Cccl2f2, ctl->qnt_Cn2o,
4339 ctl->qnt_Csf6, ctl->qnt_aoa
4340 };
4341 const int n_qnt = sizeof(quantities) / sizeof(quantities[0]);
4342
4343 for (int i = 0; i < n_qnt; i++)
4344 if (quantities[i] >= 0)
4345 module_mixing_help(ctl, clim, atm, ixs, iys, izs, quantities[i],
4346 use_ensemble);
4347
4348 /* Free... */
4349#ifdef _OPENACC
4350#pragma acc exit data delete(ixs,iys,izs)
4351#endif
4352 free(ixs);
4353 free(iys);
4354 free(izs);
4355}
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:4359
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:2927
double mixing_z1
Upper altitude of mixing grid [km].
Definition: mptrac.h:2924
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:2921
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:2936
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:2939
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:2918
double mixing_lon0
Lower longitude of mixing grid [deg].
Definition: mptrac.h:2930
double mixing_lat1
Upper latitude of mixing grid [deg].
Definition: mptrac.h:2942
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:2933
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 4359 of file mptrac.c.

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

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

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

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

4597 {
4598
4599 /* Initialize GSL random number generators... */
4600 gsl_rng_env_setup();
4601 if (omp_get_max_threads() > NTHREADS)
4602 ERRMSG("Too many threads!");
4603 for (int i = 0; i < NTHREADS; i++) {
4604 rng[i] = gsl_rng_alloc(gsl_rng_default);
4605 gsl_rng_set(rng[i], gsl_rng_default_seed
4606 + (long unsigned) (ntask * NTHREADS + i));
4607 }
4608
4609 /* Initialize cuRAND random number generators... */
4610#ifdef CURAND
4611 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
4612 CURAND_STATUS_SUCCESS)
4613 ERRMSG("Cannot create random number generator!");
4614 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
4615 CURAND_STATUS_SUCCESS)
4616 ERRMSG("Cannot set seed for random number generator!");
4617 if (curandSetStream
4618 (rng_curand,
4619 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
4620 CURAND_STATUS_SUCCESS)
4621 ERRMSG("Cannot set stream for random number generator!");
4622#endif
4623}
#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 4627 of file mptrac.c.

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

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

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

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

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

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

4869 {
4870
4871 /* Set timer... */
4872 SELECT_TIMER("MODULE_TIMESTEPS", "PHYSICS", NVTX_GPU);
4873
4874 const double latmin = gsl_stats_min(met0->lat, 1, (size_t) met0->ny),
4875 latmax = gsl_stats_max(met0->lat, 1, (size_t) met0->ny);
4876
4877 const int local =
4878 (fabs(met0->lon[met0->nx - 1] - met0->lon[0] - 360.0) >= 0.01);
4879
4880 /* Loop over particles... */
4881 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,cache,met0,atm)") {
4882
4883 /* Set time step for each air parcel... */
4884 if ((ctl->direction * (atm->time[ip] - ctl->t_start) >= 0
4885 && ctl->direction * (atm->time[ip] - ctl->t_stop) <= 0
4886 && ctl->direction * (atm->time[ip] - t) < 0))
4887 cache->dt[ip] = t - atm->time[ip];
4888 else
4889 cache->dt[ip] = 0.0;
4890
4891 /* Check horizontal boundaries of local meteo data... */
4892#ifndef DD
4893 int dd = 1;
4894#else
4895 int dd = 0;
4896#endif
4897 if (dd) {
4898 if (local && (atm->lon[ip] <= met0->lon[0]
4899 || atm->lon[ip] >= met0->lon[met0->nx - 1]
4900 || atm->lat[ip] <= latmin || atm->lat[ip] >= latmax))
4901 cache->dt[ip] = 0.0;
4902 } else {
4903 if ((int) atm->q[ctl->qnt_subdomain][ip] == -1)
4904 cache->dt[ip] = 0;
4905 }
4906 }
4907}
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 4911 of file mptrac.c.

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

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

4948 {
4949
4950 /* Set timer... */
4951 SELECT_TIMER("MODULE_TRACER_CHEM", "PHYSICS", NVTX_GPU);
4952
4953 /* Loop over particles... */
4954 PARTICLE_LOOP(0, atm->np, 1,
4955 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4956
4957 /* Get temperature... */
4958 double t;
4960 INTPOL_3D(t, 1);
4961
4962 /* Get molecular density... */
4963 const double M = MOLEC_DENS(atm->p[ip], t);
4964
4965 /* Get total column ozone... */
4966 double o3c;
4967 INTPOL_2D(o3c, 1);
4968
4969 /* Get solar zenith angle... */
4970 const double sza =
4971 acos(cos_sza(atm->time[ip], atm->lon[ip], atm->lat[ip]));
4972
4973 /* Get O(1D) volume mixing ratio... */
4974 const double o1d =
4975 clim_zm(&clim->o1d, atm->time[ip], atm->lat[ip], atm->p[ip]);
4976
4977 /* Reactions for CFC-10... */
4978 if (ctl->qnt_Cccl4 >= 0) {
4979 const double K_o1d = ARRHENIUS(3.30e-10, 0, t) * o1d * M;
4980 const double K_hv = clim_photo(clim->photo.ccl4, &(clim->photo),
4981 atm->p[ip], sza, o3c);
4982 atm->q[ctl->qnt_Cccl4][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4983 }
4984
4985 /* Reactions for CFC-11... */
4986 if (ctl->qnt_Cccl3f >= 0) {
4987 const double K_o1d = ARRHENIUS(2.30e-10, 0, t) * o1d * M;
4988 const double K_hv = clim_photo(clim->photo.ccl3f, &(clim->photo),
4989 atm->p[ip], sza, o3c);
4990 atm->q[ctl->qnt_Cccl3f][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4991 }
4992
4993 /* Reactions for CFC-12... */
4994 if (ctl->qnt_Cccl2f2 >= 0) {
4995 const double K_o1d = ARRHENIUS(1.40e-10, -25, t) * o1d * M;
4996 const double K_hv = clim_photo(clim->photo.ccl2f2, &(clim->photo),
4997 atm->p[ip], sza, o3c);
4998 atm->q[ctl->qnt_Cccl2f2][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4999 }
5000
5001 /* Reactions for N2O... */
5002 if (ctl->qnt_Cn2o >= 0) {
5003 const double K_o1d = ARRHENIUS(1.19e-10, -20, t) * o1d * M;
5004 const double K_hv = clim_photo(clim->photo.n2o, &(clim->photo),
5005 atm->p[ip], sza, o3c);
5006 atm->q[ctl->qnt_Cn2o][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
5007 }
5008 }
5009}
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:3409
double ccl3f[CP][CSZA][CO3]
CCl3F photolysis rate [1/s].
Definition: mptrac.h:3406
double n2o[CP][CSZA][CO3]
N2O photolysis rate [1/s].
Definition: mptrac.h:3400
double ccl4[CP][CSZA][CO3]
CCl4 photolysis rate [1/s].
Definition: mptrac.h:3403
clim_photo_t photo
Photolysis rates.
Definition: mptrac.h:3505
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 5013 of file mptrac.c.

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

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

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

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

5208 {
5209
5210 /* Delete data region on GPU... */
5211#ifdef _OPENACC
5212 SELECT_TIMER("DELETE_DATA_REGION", "MEMORY", NVTX_GPU);
5213#pragma acc exit data delete (ctl,cache,clim,met0,met1,atm)
5214#endif
5215
5216 /* Free... */
5217 SELECT_TIMER("FREE", "MEMORY", NVTX_CPU);
5218 free(atm);
5219 free(ctl);
5220 free(cache);
5221 free(clim);
5222 free(met0);
5223 free(met1);
5224
5225 /* Free MPI datatype... */
5226#ifdef DD
5227 MPI_Type_free(&dd->MPI_Particle);
5228#endif
5229 free(dd);
5230}

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

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

5361 {
5362
5363 /* Initialize timesteps... */
5364 module_timesteps_init(ctl, atm);
5365
5366 /* Initialize random number generator... */
5367 module_rng_init(ntask);
5368
5369 /* Update GPU memory... */
5370 mptrac_update_device(ctl, cache, clim, NULL, NULL, atm);
5371}
void module_timesteps_init(ctl_t *ctl, const atm_t *atm)
Initialize start time and time interval for time-stepping.
Definition: mptrac.c:4911
void module_rng_init(const int ntask)
Initialize random number generators for parallel tasks.
Definition: mptrac.c:4596
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 5375 of file mptrac.c.

5378 {
5379
5380 int result;
5381
5382 /* Set timer... */
5383 SELECT_TIMER("READ_ATM", "INPUT", NVTX_READ);
5384
5385 /* Init... */
5386 atm->np = 0;
5387
5388 /* Write info... */
5389 LOG(1, "Read atmospheric data: %s", filename);
5390
5391 /* Read ASCII data... */
5392 if (ctl->atm_type == 0)
5393 result = read_atm_asc(filename, ctl, atm);
5394
5395 /* Read binary data... */
5396 else if (ctl->atm_type == 1)
5397 result = read_atm_bin(filename, ctl, atm);
5398
5399 /* Read netCDF data... */
5400 else if (ctl->atm_type == 2)
5401 result = read_atm_nc(filename, ctl, atm);
5402
5403 /* Read CLaMS data... */
5404 else if (ctl->atm_type == 3 || ctl->atm_type == 4)
5405 result = read_atm_clams(filename, ctl, atm);
5406
5407 /* Error... */
5408 else
5409 ERRMSG("Atmospheric data type not supported!");
5410
5411 /* Check result... */
5412 if (result != 1)
5413 return 0;
5414
5415 /* Check number of air parcels... */
5416 if (atm->np < 1)
5417 ERRMSG("Can not read any data!");
5418
5419 /* Write info... */
5420 double mini, maxi;
5421 LOG(2, "Number of particles: %d", atm->np);
5422 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
5423 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
5424 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
5425 LOG(2, "Altitude range: %g ... %g km", Z(maxi), Z(mini));
5426 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
5427 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
5428 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
5429 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
5430 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
5431 for (int iq = 0; iq < ctl->nq; iq++) {
5432 char msg[5 * LEN];
5433 sprintf(msg, "Quantity %s range: %s ... %s %s",
5434 ctl->qnt_name[iq], ctl->qnt_format[iq],
5435 ctl->qnt_format[iq], ctl->qnt_unit[iq]);
5436 gsl_stats_minmax(&mini, &maxi, atm->q[iq], 1, (size_t) atm->np);
5437 LOG(2, msg, mini, maxi);
5438 }
5439
5440 /* Return success... */
5441 return 1;
5442}
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:7165
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:7049
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:7105
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:7007
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:3055
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 5446 of file mptrac.c.

5448 {
5449
5450 /* Set timer... */
5451 SELECT_TIMER("READ_CLIM", "INPUT", NVTX_READ);
5452
5453 /* Init tropopause climatology... */
5454 clim_tropo_init(clim);
5455
5456 /* Read photolysis rates... */
5457 if (ctl->clim_photo[0] != '-')
5458 read_clim_photo(ctl->clim_photo, &clim->photo);
5459
5460 /* Read HNO3 climatology... */
5461 if (ctl->clim_hno3_filename[0] != '-')
5462 read_clim_zm(ctl->clim_hno3_filename, "HNO3", &clim->hno3);
5463
5464 /* Read OH climatology... */
5465 if (ctl->clim_oh_filename[0] != '-') {
5466 read_clim_zm(ctl->clim_oh_filename, "OH", &clim->oh);
5467 if (ctl->oh_chem_beta > 0)
5468 clim_oh_diurnal_correction(ctl, clim);
5469 }
5470
5471 /* Read H2O2 climatology... */
5472 if (ctl->clim_h2o2_filename[0] != '-')
5473 read_clim_zm(ctl->clim_h2o2_filename, "H2O2", &clim->h2o2);
5474
5475 /* Read HO2 climatology... */
5476 if (ctl->clim_ho2_filename[0] != '-')
5477 read_clim_zm(ctl->clim_ho2_filename, "HO2", &clim->ho2);
5478
5479 /* Read O(1D) climatology... */
5480 if (ctl->clim_o1d_filename[0] != '-')
5481 read_clim_zm(ctl->clim_o1d_filename, "O1D", &clim->o1d);
5482
5483 /* Read CFC-10 time series... */
5484 if (ctl->clim_ccl4_timeseries[0] != '-')
5486
5487 /* Read CFC-11 time series... */
5488 if (ctl->clim_ccl3f_timeseries[0] != '-')
5490
5491 /* Read CFC-12 time series... */
5492 if (ctl->clim_ccl2f2_timeseries[0] != '-')
5494
5495 /* Read N2O time series... */
5496 if (ctl->clim_n2o_timeseries[0] != '-')
5497 read_clim_ts(ctl->clim_n2o_timeseries, &clim->n2o);
5498
5499 /* Read SF6 time series... */
5500 if (ctl->clim_sf6_timeseries[0] != '-')
5501 read_clim_ts(ctl->clim_sf6_timeseries, &clim->sf6);
5502}
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:7198
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:7317
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:7371
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:2885
char clim_o1d_filename[LEN]
Filename of O(1D) climatology.
Definition: mptrac.h:2888
char clim_photo[LEN]
Filename of photolysis rates climatology.
Definition: mptrac.h:2873
char clim_h2o2_filename[LEN]
Filename of H2O2 climatology.
Definition: mptrac.h:2882
char clim_oh_filename[LEN]
Filename of OH climatology.
Definition: mptrac.h:2879
char clim_hno3_filename[LEN]
Filename of HNO3 climatology.
Definition: mptrac.h:2876
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 5506 of file mptrac.c.

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

6402 {
6403
6404 /* Write info... */
6405 LOG(1, "Read meteo data: %s", filename);
6406
6407 /* Set rank... */
6408 int rank = 0;
6409#ifdef MPI
6410 if (ctl->met_mpi_share)
6411 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
6412#endif
6413
6414 /* Check rank... */
6415 if (!ctl->met_mpi_share || rank == 0) {
6416
6417 /* Read netCDF data... */
6418 if (ctl->met_type == 0) {
6419 if (read_met_nc(filename, ctl, met, dd) != 1)
6420 return 0;
6421 }
6422
6423 /* Read binary data... */
6424 else if ((ctl->met_type >= 1 && ctl->met_type <= 5) || ctl->met_type == 7) {
6425 if (read_met_bin(filename, ctl, met) != 1)
6426 return 0;
6427 }
6428
6429#ifdef ECCODES
6430 /* Read grib data... */
6431 else if (ctl->met_type == 6) {
6432 if (read_met_grib(filename, ctl, met) != 1)
6433 return 0;
6434 }
6435#endif
6436
6437 /* Not implemented... */
6438 else
6439 ERRMSG("MET_TYPE not implemented!");
6440
6441 /* Preprocessing for netCDF and grib files... */
6442 if (ctl->met_type == 0 || ctl->met_type == 6) {
6443
6444 /* Extrapolate data for lower boundary... */
6446
6447 /* Fix polar winds... */
6449
6450 /* Create periodic boundary conditions... */
6451#ifndef DD
6452 read_met_periodic(met);
6453#endif
6454
6455 /* Downsampling... */
6456 read_met_sample(ctl, met);
6457
6458 /* Calculate geopotential heights... */
6459 read_met_geopot(ctl, met);
6460
6461 /* Calculate potential vorticity... */
6462 read_met_pv(met);
6463
6464 /* Calculate boundary layer data... */
6465 read_met_pbl(ctl, met);
6466
6467 /* Calculate tropopause data... */
6468 read_met_tropo(ctl, clim, met);
6469
6470 /* Calculate cloud properties... */
6471 read_met_cloud(met);
6472
6473 /* Calculate convective available potential energy... */
6474 read_met_cape(ctl, clim, met);
6475
6476 /* Calculate total column ozone... */
6477 read_met_ozone(met);
6478
6479 /* Detrending... */
6480 read_met_detrend(ctl, met);
6481
6482 /* Check meteo data and smooth zeta profiles ... */
6483 read_met_monotonize(ctl, met);
6484 }
6485 }
6486
6487 /* Broadcast data via MPI... */
6488#ifdef MPI
6489 if (ctl->met_mpi_share) {
6490
6491 /* Set timer... */
6492 SELECT_TIMER("READ_MET_MPI_BCAST", "COMM", NVTX_SEND);
6493 LOG(2, "Broadcast data on rank %d...", rank);
6494
6495 /* Broadcast... */
6496 broadcast_large_data(met, sizeof(met_t));
6497 }
6498#endif
6499
6500 /* Return success... */
6501 return 1;
6502}
void read_met_geopot(const ctl_t *ctl, met_t *met)
Calculates geopotential heights from meteorological data.
Definition: mptrac.c:8110
void read_met_extrapolate(met_t *met)
Extrapolates meteorological data.
Definition: mptrac.c:8070
void read_met_sample(const ctl_t *ctl, met_t *met)
Downsamples meteorological data based on specified parameters.
Definition: mptrac.c:10493
void read_met_cloud(met_t *met)
Calculates cloud-related variables for each grid point.
Definition: mptrac.c:7909
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:10101
void read_met_detrend(const ctl_t *ctl, met_t *met)
Detrends meteorological data.
Definition: mptrac.c:7966
void read_met_monotonize(const ctl_t *ctl, met_t *met)
Makes zeta and pressure profiles monotone.
Definition: mptrac.c:9736
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
Definition: mptrac.c:10238
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:9821
void read_met_ozone(met_t *met)
Calculates the total column ozone from meteorological ozone data.
Definition: mptrac.c:10464
void read_met_pv(met_t *met)
Calculates potential vorticity (PV) from meteorological data.
Definition: mptrac.c:10358
int read_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a binary file.
Definition: mptrac.c:7511
void read_met_polar_winds(met_t *met)
Applies a fix for polar winds in meteorological data.
Definition: mptrac.c:10299
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:7794
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 6506 of file mptrac.c.

6514 {
6515
6516 /* Initialize modules... */
6517 if (t == ctl->t_start) {
6518
6519 /* Initialize isosurface data... */
6520 if (ctl->isosurf >= 1 && ctl->isosurf <= 4)
6521 module_isosurf_init(ctl, cache, *met0, *met1, atm);
6522
6523 /* Initialize advection... */
6524 module_advect_init(ctl, cache, *met0, *met1, atm);
6525
6526 /* Initialize chemistry... */
6527 module_chem_init(ctl, cache, clim, *met0, *met1, atm);
6528 }
6529
6530 /* Set time steps of air parcels... */
6531 module_timesteps(ctl, cache, *met0, atm, t);
6532
6533 /* Sort particles... */
6534 if (ctl->sort_dt > 0 && fmod(t, ctl->sort_dt) == 0)
6535 module_sort(ctl, *met0, atm);
6536
6537
6538 /* Check positions (initial)... */
6539 module_position(cache, *met0, *met1, atm);
6540
6541 /* Advection... */
6542 if (ctl->advect > 0)
6543 module_advect(ctl, cache, *met0, *met1, atm);
6544
6545 /* Turbulent diffusion... */
6546 if (ctl->diffusion == 1
6547 && (ctl->turb_dx_pbl > 0 || ctl->turb_dz_pbl > 0
6548 || ctl->turb_dx_trop > 0 || ctl->turb_dz_trop > 0
6549 || ctl->turb_dx_strat > 0 || ctl->turb_dz_strat > 0))
6550 module_diff_turb(ctl, cache, clim, *met0, *met1, atm);
6551
6552 /* Mesoscale diffusion... */
6553 if (ctl->diffusion == 1 && (ctl->turb_mesox > 0 || ctl->turb_mesoz > 0))
6554 module_diff_meso(ctl, cache, *met0, *met1, atm);
6555
6556 /* Diffusion... */
6557 if (ctl->diffusion == 2)
6558 module_diff_pbl(ctl, cache, *met0, *met1, atm);
6559
6560 /* Convection... */
6561 if ((ctl->conv_mix_pbl || ctl->conv_cape >= 0)
6562 && (ctl->conv_dt <= 0 || fmod(t, ctl->conv_dt) == 0))
6563 module_convection(ctl, cache, *met0, *met1, atm);
6564
6565 /* Sedimentation... */
6566 if (ctl->qnt_rp >= 0 && ctl->qnt_rhop >= 0)
6567 module_sedi(ctl, cache, *met0, *met1, atm);
6568
6569 /* Isosurface... */
6570 if (ctl->isosurf >= 1 && ctl->isosurf <= 4)
6571 module_isosurf(ctl, cache, *met0, *met1, atm);
6572
6573 /* Check positions (final)... */
6574 module_position(cache, *met0, *met1, atm);
6575
6576 /* Interpolate meteo data... */
6577 if (ctl->met_dt_out > 0
6578 && (ctl->met_dt_out < ctl->dt_mod || fmod(t, ctl->met_dt_out) == 0))
6579 module_meteo(ctl, cache, clim, *met0, *met1, atm);
6580
6581 /* Check boundary conditions (initial)... */
6582 if ((ctl->bound_lat0 < ctl->bound_lat1)
6583 && (ctl->bound_p0 > ctl->bound_p1))
6584 module_bound_cond(ctl, cache, clim, *met0, *met1, atm);
6585
6586 /* Initialize quantity of total loss rate... */
6587 if (ctl->qnt_loss_rate >= 0) {
6588 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,atm)") {
6589 atm->q[ctl->qnt_loss_rate][ip] = 0;
6590 }
6591 }
6592
6593 /* Decay of particle mass... */
6594 if (ctl->tdec_trop > 0 && ctl->tdec_strat > 0)
6595 module_decay(ctl, cache, clim, atm);
6596
6597 /* Interparcel mixing... */
6598 if (ctl->mixing_trop >= 0 && ctl->mixing_strat >= 0
6599 && (ctl->mixing_dt <= 0 || fmod(t, ctl->mixing_dt) == 0))
6600 module_mixing(ctl, clim, atm, t);
6601
6602 /* Calculate the tracer vmr in the chemistry grid... */
6603 if (ctl->oh_chem_reaction != 0 || ctl->h2o2_chem_reaction != 0
6604 || (ctl->kpp_chem && fmod(t, ctl->dt_kpp) == 0))
6605 module_chem_grid(ctl, *met0, *met1, atm, t);
6606
6607 /* OH chemistry... */
6608 if (ctl->oh_chem_reaction != 0)
6609 module_oh_chem(ctl, cache, clim, *met0, *met1, atm);
6610
6611 /* H2O2 chemistry (for SO2 aqueous phase oxidation)... */
6612 if (ctl->h2o2_chem_reaction != 0)
6613 module_h2o2_chem(ctl, cache, clim, *met0, *met1, atm);
6614
6615 /* First-order tracer chemistry... */
6616 if (ctl->tracer_chem)
6617 module_tracer_chem(ctl, cache, clim, *met0, *met1, atm);
6618
6619 /* Domain decomposition... */
6620 if (dd->init) {
6621#ifdef DD
6622 module_dd(ctl, atm, cache, dd, met0);
6623#else
6624 ERRMSG("DD initialized, but model is compiled without DD.")
6625#endif
6626 }
6627
6628 /* KPP chemistry... */
6629 if (ctl->kpp_chem && fmod(t, ctl->dt_kpp) == 0) {
6630#ifdef KPP
6631 module_kpp_chem(ctl, cache, clim, *met0, *met1, atm);
6632#else
6633 ERRMSG("Code was compiled without KPP!");
6634#endif
6635 }
6636
6637 /* Wet deposition... */
6638 if ((ctl->wet_depo_ic_a > 0 || ctl->wet_depo_ic_h[0] > 0)
6639 && (ctl->wet_depo_bc_a > 0 || ctl->wet_depo_bc_h[0] > 0))
6640 module_wet_depo(ctl, cache, *met0, *met1, atm);
6641
6642 /* Dry deposition... */
6643 if (ctl->dry_depo_vdep > 0)
6644 module_dry_depo(ctl, cache, *met0, *met1, atm);
6645
6646 /* Check boundary conditions (final)... */
6647 if ((ctl->bound_lat0 < ctl->bound_lat1)
6648 && (ctl->bound_p0 > ctl->bound_p1))
6649 module_bound_cond(ctl, cache, clim, *met0, *met1, atm);
6650}
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:2964
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:4864
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:4181
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:3567
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:3412
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:4288
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:4005
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:5013
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:3250
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:4732
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:3454
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:3154
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:3127
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:4545
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:3606
void module_sort(const ctl_t *ctl, met_t *met0, atm_t *atm)
Sort particles according to box index.
Definition: mptrac.c:4761
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:3808
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:4942
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:3923
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:3683
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:4075
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:4461
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:3860
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:3779
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 6766 of file mptrac.c.

6770 {
6771
6772 /* Set timer... */
6773 SELECT_TIMER("WRITE_ATM", "OUTPUT", NVTX_WRITE);
6774
6775 /* Write info... */
6776 LOG(1, "Write atmospheric data: %s", filename);
6777
6778 /* Write ASCII data... */
6779 if (ctl->atm_type_out == 0)
6780 write_atm_asc(filename, ctl, atm, t);
6781
6782 /* Write binary data... */
6783 else if (ctl->atm_type_out == 1)
6784 write_atm_bin(filename, ctl, atm);
6785
6786 /* Write netCDF data... */
6787 else if (ctl->atm_type_out == 2)
6788 write_atm_nc(filename, ctl, atm);
6789
6790 /* Write CLaMS trajectory data... */
6791 else if (ctl->atm_type_out == 3)
6792 write_atm_clams_traj(filename, ctl, atm, t);
6793
6794 /* Write CLaMS pos data... */
6795 else if (ctl->atm_type_out == 4)
6796 write_atm_clams(filename, ctl, atm);
6797
6798 /* Error... */
6799 else
6800 ERRMSG("Atmospheric data type not supported!");
6801
6802 /* Write info... */
6803 double mini, maxi;
6804 LOG(2, "Number of particles: %d", atm->np);
6805 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
6806 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
6807 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
6808 LOG(2, "Altitude range: %g ... %g km", Z(maxi), Z(mini));
6809 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
6810 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
6811 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
6812 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
6813 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
6814 for (int iq = 0; iq < ctl->nq; iq++) {
6815 char msg[5 * LEN];
6816 sprintf(msg, "Quantity %s range: %s ... %s %s",
6817 ctl->qnt_name[iq], ctl->qnt_format[iq],
6818 ctl->qnt_format[iq], ctl->qnt_unit[iq]);
6819 gsl_stats_minmax(&mini, &maxi, atm->q[iq], 1, (size_t) atm->np);
6820 LOG(2, msg, mini, maxi);
6821 }
6822}
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:11454
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:11269
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:11401
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:11351
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:11612
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 6826 of file mptrac.c.

6829 {
6830
6831 /* Set timer... */
6832 SELECT_TIMER("WRITE_MET", "OUTPUT", NVTX_WRITE);
6833
6834 /* Write info... */
6835 LOG(1, "Write meteo data: %s", filename);
6836
6837 /* Check compression flags... */
6838#ifndef ZFP
6839 if (ctl->met_type == 3)
6840 ERRMSG("MPTRAC was compiled without ZFP compression!");
6841#endif
6842#ifndef ZSTD
6843 if (ctl->met_type == 4)
6844 ERRMSG("MPTRAC was compiled without ZSTD compression!");
6845#endif
6846#ifndef CMS
6847 if (ctl->met_type == 5)
6848 ERRMSG("MPTRAC was compiled without cmultiscale compression!");
6849#endif
6850#ifndef SZ3
6851 if (ctl->met_type == 7)
6852 ERRMSG("MPTRAC was compiled without SZ3 compression!");
6853#endif
6854
6855 /* Write netCDF data... */
6856 if (ctl->met_type == 0)
6857 write_met_nc(filename, ctl, met);
6858
6859 /* Write binary data... */
6860 else if (ctl->met_type >= 1 && ctl->met_type <= 7)
6861 write_met_bin(filename, ctl, met);
6862
6863 /* Not implemented... */
6864 else
6865 ERRMSG("MET_TYPE not implemented!");
6866}
void write_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a NetCDF file.
Definition: mptrac.c:12689
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:12458
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 6870 of file mptrac.c.

6876 {
6877
6878 char ext[10], filename[2 * LEN];
6879
6880 double r;
6881
6882 int year, mon, day, hour, min, sec;
6883
6884 /* Get time... */
6885 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
6886
6887 /* Update host... */
6888 if ((ctl->atm_basename[0] != '-' && fmod(t, ctl->atm_dt_out) == 0)
6889 || (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0)
6890 || (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0)
6891 || ctl->csi_basename[0] != '-' || ctl->prof_basename[0] != '-'
6892 || ctl->sample_basename[0] != '-' || ctl->stat_basename[0] != '-'
6893 || (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0))
6894 mptrac_update_host(NULL, NULL, NULL, NULL, NULL, atm);
6895
6896 /* Write atmospheric data... */
6897 if (ctl->atm_basename[0] != '-' &&
6898 (fmod(t, ctl->atm_dt_out) == 0 || t == ctl->t_stop)) {
6899 if (ctl->atm_type_out == 0)
6900 sprintf(ext, "tab");
6901 else if (ctl->atm_type_out == 1)
6902 sprintf(ext, "bin");
6903 else if (ctl->atm_type_out == 2)
6904 sprintf(ext, "nc");
6905 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6906 dirname, ctl->atm_basename, year, mon, day, hour, min, ext);
6907 mptrac_write_atm(filename, ctl, atm, t);
6908 }
6909
6910 /* Write gridded data... */
6911 if (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0) {
6912 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6913 dirname, ctl->grid_basename, year, mon, day, hour, min,
6914 ctl->grid_type == 0 ? "tab" : "nc");
6915 write_grid(filename, ctl, met0, met1, atm, t);
6916 }
6917
6918 /* Write CSI data... */
6919 if (ctl->csi_basename[0] != '-') {
6920 sprintf(filename, "%s/%s.tab", dirname, ctl->csi_basename);
6921 write_csi(filename, ctl, atm, t);
6922 }
6923
6924 /* Write ensemble data... */
6925 if (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0) {
6926 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
6927 dirname, ctl->ens_basename, year, mon, day, hour, min);
6928 write_ens(filename, ctl, atm, t);
6929 }
6930
6931 /* Write profile data... */
6932 if (ctl->prof_basename[0] != '-') {
6933 sprintf(filename, "%s/%s.tab", dirname, ctl->prof_basename);
6934 write_prof(filename, ctl, met0, met1, atm, t);
6935 }
6936
6937 /* Write sample data... */
6938 if (ctl->sample_basename[0] != '-') {
6939 sprintf(filename, "%s/%s.tab", dirname, ctl->sample_basename);
6940 write_sample(filename, ctl, met0, met1, atm, t);
6941 }
6942
6943 /* Write station data... */
6944 if (ctl->stat_basename[0] != '-') {
6945 sprintf(filename, "%s/%s.tab", dirname, ctl->stat_basename);
6946 write_station(filename, ctl, atm, t);
6947 }
6948
6949 /* Write VTK data... */
6950 if (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0) {
6951 static int nvtk;
6952 if (t == ctl->t_start)
6953 nvtk = 0;
6954 sprintf(filename, "%s/%s_%05d.vtk", dirname, ctl->vtk_basename, ++nvtk);
6955 write_vtk(filename, ctl, atm, t);
6956 }
6957}
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:6766
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:11936
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:12912
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:6710
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:13301
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:13387
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:13139
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:12033
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:11661
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 6654 of file mptrac.c.

6660 {
6661
6662 /* Update GPU... */
6663 if (ctl != NULL) {
6664#ifdef _OPENACC
6665 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
6666#pragma acc update device(ctl[:1])
6667#endif
6668 }
6669
6670 if (cache != NULL) {
6671#ifdef _OPENACC
6672 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
6673#pragma acc update device(cache[:1])
6674#endif
6675 }
6676
6677 if (clim != NULL) {
6678#ifdef _OPENACC
6679 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
6680#pragma acc update device(clim[:1])
6681#endif
6682 }
6683
6684 if (met0 != NULL) {
6685#ifdef _OPENACC
6686 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
6687 met_t *met0up = *met0;
6688#pragma acc update device(met0up[:1])
6689#endif
6690 }
6691
6692 if (met1 != NULL) {
6693#ifdef _OPENACC
6694 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
6695 met_t *met1up = *met1;
6696#pragma acc update device(met1up[:1])
6697#endif
6698 }
6699
6700 if (atm != NULL) {
6701#ifdef _OPENACC
6702 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
6703#pragma acc update device(atm[:1])
6704#endif
6705 }
6706}

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

6716 {
6717
6718 /* Update GPU... */
6719 if (ctl != NULL) {
6720#ifdef _OPENACC
6721 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
6722#pragma acc update host(ctl[:1])
6723#endif
6724 }
6725
6726 if (cache != NULL) {
6727#ifdef _OPENACC
6728 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
6729#pragma acc update host(cache[:1])
6730#endif
6731 }
6732
6733 if (clim != NULL) {
6734#ifdef _OPENACC
6735 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
6736#pragma acc update host(clim[:1])
6737#endif
6738 }
6739
6740 if (met0 != NULL) {
6741#ifdef _OPENACC
6742 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
6743 met_t *met0up = *met0;
6744#pragma acc update host(met0up[:1])
6745#endif
6746 }
6747
6748 if (met1 != NULL) {
6749#ifdef _OPENACC
6750 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
6751 met_t *met1up = *met1;
6752#pragma acc update host(met1up[:1])
6753#endif
6754 }
6755
6756 if (atm != NULL) {
6757#ifdef _OPENACC
6758 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
6759#pragma acc update host(atm[:1])
6760#endif
6761 }
6762}

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

6964 {
6965
6966 /* Check water vapor volume mixing ratio... */
6967 const double h2o_help = MAX(h2o, 0.1e-6);
6968
6969 /* Calculate T_NAT... */
6970 const double p_hno3 = hno3 * p / 1.333224;
6971 const double p_h2o = h2o_help * p / 1.333224;
6972 const double a = 0.009179 - 0.00088 * log10(p_h2o);
6973 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
6974 const double c = -11397.0 / a;
6975 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
6976 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
6977 if (x2 > 0)
6978 tnat = x2;
6979
6980 return tnat;
6981}

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

6990 {
6991
6992 /* Get pressure range... */
6993 const double p1 = pbl - ctl->conv_pbl_trans * (ps - pbl);
6994 const double p0 = pbl;
6995
6996 /* Get weighting factor... */
6997 if (atm->p[ip] > p0)
6998 return 1;
6999 else if (atm->p[ip] < p1)
7000 return 0;
7001 else
7002 return LIN(p0, 1.0, p1, 0.0, atm->p[ip]);
7003}

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

7010 {
7011
7012 /* Open file... */
7013 FILE *in;
7014 if (!(in = fopen(filename, "r"))) {
7015 WARN("Cannot open file!");
7016 return 0;
7017 }
7018
7019 /* Read line... */
7020 char line[LEN];
7021 while (fgets(line, LEN, in)) {
7022
7023 /* Read data... */
7024 char *tok;
7025 TOK(line, tok, "%lg", atm->time[atm->np]);
7026 TOK(NULL, tok, "%lg", atm->p[atm->np]);
7027 TOK(NULL, tok, "%lg", atm->lon[atm->np]);
7028 TOK(NULL, tok, "%lg", atm->lat[atm->np]);
7029 for (int iq = 0; iq < ctl->nq; iq++)
7030 TOK(NULL, tok, "%lg", atm->q[iq][atm->np]);
7031
7032 /* Convert altitude to pressure... */
7033 atm->p[atm->np] = P(atm->p[atm->np]);
7034
7035 /* Increment data point counter... */
7036 if ((++atm->np) > NP)
7037 ERRMSG("Too many data points!");
7038 }
7039
7040 /* Close file... */
7041 fclose(in);
7042
7043 /* Return success... */
7044 return 1;
7045}
#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 7049 of file mptrac.c.

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

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

7108 {
7109
7110 int ncid, varid;
7111
7112 /* Open file... */
7113 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7114 return 0;
7115
7116 /* Get dimensions... */
7117 NC_INQ_DIM("NPARTS", &atm->np, 1, NP, 1);
7118
7119 /* Get time... */
7120 if (nc_inq_varid(ncid, "TIME_INIT", &varid) == NC_NOERR) {
7121 NC(nc_get_var_double(ncid, varid, atm->time));
7122 } else {
7123 WARN("TIME_INIT not found use time instead!");
7124 double time_init;
7125 NC_GET_DOUBLE("time", &time_init, 1);
7126 for (int ip = 0; ip < atm->np; ip++) {
7127 atm->time[ip] = time_init;
7128 }
7129 }
7130
7131 /* Read zeta coordinate, pressure is optional... */
7132 if (ctl->advect_vert_coord == 1) {
7133 NC_GET_DOUBLE("ZETA", atm->q[ctl->qnt_zeta], 1);
7134 NC_GET_DOUBLE("PRESS", atm->p, 0);
7135 }
7136
7137 /* Read pressure, zeta coordinate is optional... */
7138 else {
7139 if (nc_inq_varid(ncid, "PRESS_INIT", &varid) == NC_NOERR) {
7140 NC(nc_get_var_double(ncid, varid, atm->p));
7141 } else {
7142 WARN("PRESS_INIT not found use PRESS instead!");
7143 nc_inq_varid(ncid, "PRESS", &varid);
7144 NC(nc_get_var_double(ncid, varid, atm->p));
7145 }
7146 }
7147
7148 /* Read further quantities if requested... */
7149 for (int iq = 0; iq < ctl->nq; iq++)
7150 NC_GET_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
7151
7152 /* Read longitude and latitude... */
7153 NC_GET_DOUBLE("LON", atm->lon, 1);
7154 NC_GET_DOUBLE("LAT", atm->lat, 1);
7155
7156 /* Close file... */
7157 NC(nc_close(ncid));
7158
7159 /* Return success... */
7160 return 1;
7161}
#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 7165 of file mptrac.c.

7168 {
7169
7170 int ncid, varid;
7171
7172 /* Open file... */
7173 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7174 return 0;
7175
7176 /* Get dimensions... */
7177 NC_INQ_DIM("obs", &atm->np, 1, NP, 1);
7178
7179 /* Read geolocations... */
7180 NC_GET_DOUBLE("time", atm->time, 1);
7181 NC_GET_DOUBLE("press", atm->p, 1);
7182 NC_GET_DOUBLE("lon", atm->lon, 1);
7183 NC_GET_DOUBLE("lat", atm->lat, 1);
7184
7185 /* Read variables... */
7186 for (int iq = 0; iq < ctl->nq; iq++)
7187 NC_GET_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
7188
7189 /* Close file... */
7190 NC(nc_close(ncid));
7191
7192 /* Return success... */
7193 return 1;
7194}

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

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

7293 {
7294
7295 /* Allocate... */
7296 double *help;
7297 ALLOC(help, double,
7298 photo->np * photo->nsza * photo->no3c);
7299
7300 /* Read varible... */
7301 int varid;
7302 NC_GET_DOUBLE(varname, help, 1);
7303
7304 /* Copy data... */
7305 for (int ip = 0; ip < photo->np; ip++)
7306 for (int is = 0; is < photo->nsza; is++)
7307 for (int io = 0; io < photo->no3c; io++)
7308 var[ip][is][io] =
7309 help[ARRAY_3D(ip, is, photo->nsza, io, photo->no3c)];
7310
7311 /* Free... */
7312 free(help);
7313}

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

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

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

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

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

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

7663 {
7664
7665 float *help;
7666
7667 /* Allocate... */
7668 ALLOC(help, float,
7669 EX * EY);
7670
7671 /* Read uncompressed... */
7672 LOG(2, "Read 2-D variable: %s (uncompressed)", varname);
7673 FREAD(help, float,
7674 (size_t) (met->nx * met->ny),
7675 in);
7676
7677 /* Copy data... */
7678 for (int ix = 0; ix < met->nx; ix++)
7679 for (int iy = 0; iy < met->ny; iy++)
7680 var[ix][iy] = help[ARRAY_2D(ix, iy, met->ny)];
7681
7682 /* Free... */
7683 free(help);
7684}
#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 7688 of file mptrac.c.

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

◆ read_met_cape()

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

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

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

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

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

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

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

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

8071 {
8072
8073 /* Set timer... */
8074 SELECT_TIMER("READ_MET_EXTRAPOLATE", "METPROC", NVTX_READ);
8075 LOG(2, "Extrapolate meteo data...");
8076
8077 /* Loop over columns... */
8078#pragma omp parallel for default(shared) collapse(2)
8079 for (int ix = 0; ix < met->nx; ix++)
8080 for (int iy = 0; iy < met->ny; iy++) {
8081
8082 /* Find lowest valid data point... */
8083 int ip0;
8084 for (ip0 = met->np - 1; ip0 >= 0; ip0--)
8085 if (!isfinite(met->t[ix][iy][ip0])
8086 || !isfinite(met->u[ix][iy][ip0])
8087 || !isfinite(met->v[ix][iy][ip0])
8088 || !isfinite(met->w[ix][iy][ip0]))
8089 break;
8090
8091 /* Extrapolate... */
8092 for (int ip = ip0; ip >= 0; ip--) {
8093 met->t[ix][iy][ip] = met->t[ix][iy][ip + 1];
8094 met->u[ix][iy][ip] = met->u[ix][iy][ip + 1];
8095 met->v[ix][iy][ip] = met->v[ix][iy][ip + 1];
8096 met->w[ix][iy][ip] = met->w[ix][iy][ip + 1];
8097 met->h2o[ix][iy][ip] = met->h2o[ix][iy][ip + 1];
8098 met->o3[ix][iy][ip] = met->o3[ix][iy][ip + 1];
8099 met->lwc[ix][iy][ip] = met->lwc[ix][iy][ip + 1];
8100 met->rwc[ix][iy][ip] = met->rwc[ix][iy][ip + 1];
8101 met->iwc[ix][iy][ip] = met->iwc[ix][iy][ip + 1];
8102 met->swc[ix][iy][ip] = met->swc[ix][iy][ip + 1];
8103 met->cc[ix][iy][ip] = met->cc[ix][iy][ip + 1];
8104 }
8105 }
8106}

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

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

9698 {
9699
9700 double aux[EP], p[EP];
9701
9702 /* Set timer... */
9703 SELECT_TIMER("READ_MET_ML2PL", "METPROC", NVTX_READ);
9704 LOG(2, "Interpolate meteo data to pressure levels: %s", varname);
9705
9706 /* Loop over columns... */
9707#pragma omp parallel for default(shared) private(aux,p) collapse(2)
9708 for (int ix = 0; ix < met->nx; ix++)
9709 for (int iy = 0; iy < met->ny; iy++) {
9710
9711 /* Copy pressure profile... */
9712 for (int ip = 0; ip < met->np; ip++)
9713 p[ip] = met->pl[ix][iy][ip];
9714
9715 /* Interpolate... */
9716 for (int ip = 0; ip < ctl->met_np; ip++) {
9717 double pt = ctl->met_p[ip];
9718 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
9719 pt = p[0];
9720 else if ((pt > p[met->np - 1] && p[1] > p[0])
9721 || (pt < p[met->np - 1] && p[1] < p[0]))
9722 pt = p[met->np - 1];
9723 const int ip2 = locate_irr(p, met->np, pt);
9724 aux[ip] = LIN(p[ip2], var[ix][iy][ip2],
9725 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
9726 }
9727
9728 /* Copy data... */
9729 for (int ip = 0; ip < ctl->met_np; ip++)
9730 var[ix][iy][ip] = (float) aux[ip];
9731 }
9732}
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 9736 of file mptrac.c.

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

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

9825 {
9826
9827 int ncid;
9828
9829 /* Open file... */
9830#ifdef DD
9831 if (ctl->dd) {
9832 NC(nc_open_par
9833 (filename, NC_NOWRITE | NC_SHARE, MPI_COMM_WORLD, MPI_INFO_NULL,
9834 &ncid))
9835 }
9836#else
9837 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
9838 WARN("Cannot open file!");
9839 return 0;
9840 }
9841#endif
9842
9843 /* Read coordinates of meteo data... */
9844 read_met_nc_grid(filename, ncid, ctl, met, dd);
9845
9846 /* Read surface data... */
9847 read_met_nc_surface(ncid, ctl, met, dd);
9848
9849 /* Read meteo data on vertical levels... */
9850 read_met_nc_levels(ncid, ctl, met, dd);
9851
9852 /* Close file... */
9853 NC(nc_close(ncid));
9854
9855 /* Return success... */
9856 return 1;
9857}
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:8543
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:8405
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:8238
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 8238 of file mptrac.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

10359 {
10360
10361 double pows[EP];
10362
10363 /* Set timer... */
10364 SELECT_TIMER("READ_MET_PV", "METPROC", NVTX_READ);
10365 LOG(2, "Calculate potential vorticity...");
10366
10367 /* Set powers... */
10368#pragma omp parallel for default(shared)
10369 for (int ip = 0; ip < met->np; ip++)
10370 pows[ip] = pow(1000. / met->p[ip], 0.286);
10371
10372 /* Loop over grid points... */
10373#pragma omp parallel for default(shared)
10374 for (int ix = 0; ix < met->nx; ix++) {
10375
10376 /* Set indices... */
10377 const int ix0 = MAX(ix - 1, 0);
10378 const int ix1 = MIN(ix + 1, met->nx - 1);
10379
10380 /* Loop over grid points... */
10381 for (int iy = 0; iy < met->ny; iy++) {
10382
10383 /* Set indices... */
10384 const int iy0 = MAX(iy - 1, 0);
10385 const int iy1 = MIN(iy + 1, met->ny - 1);
10386
10387 /* Set auxiliary variables... */
10388 const double latr = 0.5 * (met->lat[iy1] + met->lat[iy0]);
10389 const double dx = 1000. * DEG2DX(met->lon[ix1] - met->lon[ix0], latr);
10390 const double dy = 1000. * DEG2DY(met->lat[iy1] - met->lat[iy0]);
10391 const double c0 = cos(DEG2RAD(met->lat[iy0]));
10392 const double c1 = cos(DEG2RAD(met->lat[iy1]));
10393 const double cr = cos(DEG2RAD(latr));
10394 const double vort = 2 * 7.2921e-5 * sin(DEG2RAD(latr));
10395
10396 /* Loop over grid points... */
10397 for (int ip = 0; ip < met->np; ip++) {
10398
10399 /* Get gradients in longitude... */
10400 const double dtdx
10401 = (met->t[ix1][iy][ip] - met->t[ix0][iy][ip]) * pows[ip] / dx;
10402 const double dvdx = (met->v[ix1][iy][ip] - met->v[ix0][iy][ip]) / dx;
10403
10404 /* Get gradients in latitude... */
10405 const double dtdy
10406 = (met->t[ix][iy1][ip] - met->t[ix][iy0][ip]) * pows[ip] / dy;
10407 const double dudy
10408 = (met->u[ix][iy1][ip] * c1 - met->u[ix][iy0][ip] * c0) / dy;
10409
10410 /* Set indices... */
10411 const int ip0 = MAX(ip - 1, 0);
10412 const int ip1 = MIN(ip + 1, met->np - 1);
10413
10414 /* Get gradients in pressure... */
10415 double dtdp, dudp, dvdp;
10416 const double dp0 = 100. * (met->p[ip] - met->p[ip0]);
10417 const double dp1 = 100. * (met->p[ip1] - met->p[ip]);
10418 if (ip != ip0 && ip != ip1) {
10419 double denom = dp0 * dp1 * (dp0 + dp1);
10420 dtdp = (dp0 * dp0 * met->t[ix][iy][ip1] * pows[ip1]
10421 - dp1 * dp1 * met->t[ix][iy][ip0] * pows[ip0]
10422 + (dp1 * dp1 - dp0 * dp0) * met->t[ix][iy][ip] * pows[ip])
10423 / denom;
10424 dudp = (dp0 * dp0 * met->u[ix][iy][ip1]
10425 - dp1 * dp1 * met->u[ix][iy][ip0]
10426 + (dp1 * dp1 - dp0 * dp0) * met->u[ix][iy][ip])
10427 / denom;
10428 dvdp = (dp0 * dp0 * met->v[ix][iy][ip1]
10429 - dp1 * dp1 * met->v[ix][iy][ip0]
10430 + (dp1 * dp1 - dp0 * dp0) * met->v[ix][iy][ip])
10431 / denom;
10432 } else {
10433 const double denom = dp0 + dp1;
10434 dtdp =
10435 (met->t[ix][iy][ip1] * pows[ip1] -
10436 met->t[ix][iy][ip0] * pows[ip0]) / denom;
10437 dudp = (met->u[ix][iy][ip1] - met->u[ix][iy][ip0]) / denom;
10438 dvdp = (met->v[ix][iy][ip1] - met->v[ix][iy][ip0]) / denom;
10439 }
10440
10441 /* Calculate PV... */
10442 met->pv[ix][iy][ip] = (float)
10443 (1e6 * G0 *
10444 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
10445 }
10446 }
10447 }
10448
10449 /* Fix for polar regions... */
10450#pragma omp parallel for default(shared)
10451 for (int ix = 0; ix < met->nx; ix++)
10452 for (int ip = 0; ip < met->np; ip++) {
10453 met->pv[ix][0][ip]
10454 = met->pv[ix][1][ip]
10455 = met->pv[ix][2][ip];
10456 met->pv[ix][met->ny - 1][ip]
10457 = met->pv[ix][met->ny - 2][ip]
10458 = met->pv[ix][met->ny - 3][ip];
10459 }
10460}
#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 10464 of file mptrac.c.

10465 {
10466
10467 /* Set timer... */
10468 SELECT_TIMER("READ_MET_OZONE", "METPROC", NVTX_READ);
10469 LOG(2, "Calculate total column ozone...");
10470
10471 /* Loop over columns... */
10472#pragma omp parallel for default(shared) collapse(2)
10473 for (int ix = 0; ix < met->nx; ix++)
10474 for (int iy = 0; iy < met->ny; iy++) {
10475
10476 /* Integrate... */
10477 double cd = 0;
10478 for (int ip = 1; ip < met->np; ip++)
10479 if (met->p[ip - 1] <= met->ps[ix][iy]) {
10480 const double vmr =
10481 0.5 * (met->o3[ix][iy][ip - 1] + met->o3[ix][iy][ip]);
10482 const double dp = met->p[ip - 1] - met->p[ip];
10483 cd += vmr * MO3 / MA * dp * 1e2 / G0;
10484 }
10485
10486 /* Convert to Dobson units... */
10487 met->o3c[ix][iy] = (float) (cd / 2.1415e-5);
10488 }
10489}

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

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

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

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

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

10889 {
10890
10891 /* Open observation data file... */
10892 FILE *in;
10893 if (!(in = fopen(filename, "r")))
10894 ERRMSG("Cannot open file!");
10895
10896 /* Read observations... */
10897 char line[LEN];
10898 while (fgets(line, LEN, in))
10899 if (sscanf(line, "%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
10900 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
10901 if ((++(*nobs)) >= NOBS)
10902 ERRMSG("Too many observations!");
10903
10904 /* Close observation data file... */
10905 fclose(in);
10906}
#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 10910 of file mptrac.c.

10917 {
10918
10919 int ncid, varid;
10920
10921 /* Open netCDF file... */
10922 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
10923 ERRMSG("Cannot open file!");
10924
10925 /* Read the observations from the NetCDF file... */
10926 NC_INQ_DIM("nobs", nobs, 1, NOBS, 1);
10927 NC_GET_DOUBLE("time", rt, 1);
10928 NC_GET_DOUBLE("alt", rz, 1);
10929 NC_GET_DOUBLE("lon", rlon, 1);
10930 NC_GET_DOUBLE("lat", rlat, 1);
10931 NC_GET_DOUBLE("obs", robs, 1);
10932
10933 /* Close file... */
10934 NC(nc_close(ncid));
10935}

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

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

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

11015 {
11016
11017 /* Convert particle radius from microns to m... */
11018 const double rp_help = rp * 1e-6;
11019
11020 /* Density of dry air [kg / m^3]... */
11021 const double rho = RHO(p, T);
11022
11023 /* Dynamic viscosity of air [kg / (m s)]... */
11024 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
11025
11026 /* Thermal velocity of an air molecule [m / s]... */
11027 const double v = sqrt(8. * KB * T / (M_PI * 4.8096e-26));
11028
11029 /* Mean free path of an air molecule [m]... */
11030 const double lambda = 2. * eta / (rho * v);
11031
11032 /* Knudsen number for air (dimensionless)... */
11033 const double K = lambda / rp_help;
11034
11035 /* Cunningham slip-flow correction (dimensionless)... */
11036 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
11037
11038 /* Sedimentation velocity [m / s]... */
11039 return 2. * SQR(rp_help) * (rhop - rho) * G0 / (9. * eta) * G;
11040}
#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 11044 of file mptrac.c.

11051 {
11052
11053 /* Cubic spline interpolation... */
11054 if (method == 1) {
11055
11056 /* Allocate... */
11057 gsl_interp_accel *acc = gsl_interp_accel_alloc();
11058 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (size_t) n);
11059
11060 /* Interpolate profile... */
11061 gsl_spline_init(s, x, y, (size_t) n);
11062 for (int i = 0; i < n2; i++)
11063 if (x2[i] <= x[0])
11064 y2[i] = y[0];
11065 else if (x2[i] >= x[n - 1])
11066 y2[i] = y[n - 1];
11067 else
11068 y2[i] = gsl_spline_eval(s, x2[i], acc);
11069
11070 /* Free... */
11071 gsl_spline_free(s);
11072 gsl_interp_accel_free(acc);
11073 }
11074
11075 /* Linear interpolation... */
11076 else {
11077 for (int i = 0; i < n2; i++)
11078 if (x2[i] <= x[0])
11079 y2[i] = y[0];
11080 else if (x2[i] >= x[n - 1])
11081 y2[i] = y[n - 1];
11082 else {
11083 const int idx = locate_irr(x, n, x2[i]);
11084 y2[i] = LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
11085 }
11086 }
11087}
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 11091 of file mptrac.c.

11093 {
11094
11095 if (n <= 0)
11096 return 0;
11097
11098 float mean = 0, var = 0;
11099
11100 for (int i = 0; i < n; ++i) {
11101 mean += data[i];
11102 var += SQR(data[i]);
11103 }
11104
11105 var = var / (float) n - SQR(mean / (float) n);
11106
11107 return (var > 0 ? sqrtf(var) : 0);
11108}

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

11120 {
11121
11122 struct tm t0, t1;
11123
11124 t0.tm_year = 100;
11125 t0.tm_mon = 0;
11126 t0.tm_mday = 1;
11127 t0.tm_hour = 0;
11128 t0.tm_min = 0;
11129 t0.tm_sec = 0;
11130
11131 t1.tm_year = year - 1900;
11132 t1.tm_mon = mon - 1;
11133 t1.tm_mday = day;
11134 t1.tm_hour = hour;
11135 t1.tm_min = min;
11136 t1.tm_sec = sec;
11137
11138 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
11139}

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

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

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

11249 {
11250
11251 /* Get tropopause pressure... */
11252 const double pt = clim_tropo(clim, atm->time[ip], atm->lat[ip]);
11253
11254 /* Get pressure range... */
11255 const double p1 = pt * 0.866877899;
11256 const double p0 = pt / 0.866877899;
11257
11258 /* Get weighting factor... */
11259 if (atm->p[ip] > p0)
11260 return 1;
11261 else if (atm->p[ip] < p1)
11262 return 0;
11263 else
11264 return LIN(p0, 1.0, p1, 0.0, atm->p[ip]);
11265}
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 11269 of file mptrac.c.

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

11354 {
11355
11356 FILE *out;
11357
11358 /* Create file... */
11359 if (!(out = fopen(filename, "w")))
11360 ERRMSG("Cannot create file!");
11361
11362 /* Write version of binary data... */
11363 int version = 100;
11364 FWRITE(&version, int,
11365 1,
11366 out);
11367
11368 /* Write data... */
11369 FWRITE(&atm->np, int,
11370 1,
11371 out);
11372 FWRITE(atm->time, double,
11373 (size_t) atm->np,
11374 out);
11375 FWRITE(atm->p, double,
11376 (size_t) atm->np,
11377 out);
11378 FWRITE(atm->lon, double,
11379 (size_t) atm->np,
11380 out);
11381 FWRITE(atm->lat, double,
11382 (size_t) atm->np,
11383 out);
11384 for (int iq = 0; iq < ctl->nq; iq++)
11385 FWRITE(atm->q[iq], double,
11386 (size_t) atm->np,
11387 out);
11388
11389 /* Write final flag... */
11390 int final = 999;
11391 FWRITE(&final, int,
11392 1,
11393 out);
11394
11395 /* Close file... */
11396 fclose(out);
11397}

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

11404 {
11405
11406 int tid, pid, ncid, varid;
11407 size_t start[2], count[2];
11408
11409 /* Create file... */
11410 NC(nc_create(filename, NC_NETCDF4, &ncid));
11411
11412 /* Define dimensions... */
11413 NC(nc_def_dim(ncid, "time", 1, &tid));
11414 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
11415
11416 /* Define variables and their attributes... */
11417 int dim_ids[2] = { tid, pid };
11418 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
11419 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
11420 NC_DEF_VAR("LAT", NC_DOUBLE, 1, &pid, "Latitude", "deg",
11421 ctl->atm_nc_level, 0);
11422 NC_DEF_VAR("LON", NC_DOUBLE, 1, &pid, "Longitude", "deg",
11423 ctl->atm_nc_level, 0);
11424 NC_DEF_VAR("PRESS", NC_DOUBLE, 1, &pid, "Pressure", "hPa",
11425 ctl->atm_nc_level, 0);
11426 NC_DEF_VAR("ZETA", NC_DOUBLE, 1, &pid, "Zeta", "K", ctl->atm_nc_level, 0);
11427 for (int iq = 0; iq < ctl->nq; iq++)
11428 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
11429 ctl->qnt_name[iq], ctl->qnt_unit[iq],
11430 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
11431
11432 /* Define global attributes... */
11433 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
11434 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
11435
11436 /* End definitions... */
11437 NC(nc_enddef(ncid));
11438
11439 /* Write data... */
11440 NC_PUT_DOUBLE("time", atm->time, 0);
11441 NC_PUT_DOUBLE("LAT", atm->lat, 0);
11442 NC_PUT_DOUBLE("LON", atm->lon, 0);
11443 NC_PUT_DOUBLE("PRESS", atm->p, 0);
11444 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 0);
11445 for (int iq = 0; iq < ctl->nq; iq++)
11446 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
11447
11448 /* Close file... */
11449 NC(nc_close(ncid));
11450}
#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 11454 of file mptrac.c.

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

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

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

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

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

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

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

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

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

12574 {
12575
12576 float *help;
12577
12578 /* Allocate... */
12579 ALLOC(help, float,
12580 EX * EY);
12581
12582 /* Copy data... */
12583 for (int ix = 0; ix < met->nx; ix++)
12584 for (int iy = 0; iy < met->ny; iy++)
12585 help[ARRAY_2D(ix, iy, met->ny)] = var[ix][iy];
12586
12587 /* Write uncompressed data... */
12588 LOG(2, "Write 2-D variable: %s (uncompressed)", varname);
12589 FWRITE(help, float,
12590 (size_t) (met->nx * met->ny),
12591 out);
12592
12593 /* Free... */
12594 free(help);
12595}

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

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

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

12858 {
12859
12860 int varid;
12861 size_t start[4], count[4];
12862
12863 /* Allocate... */
12864 float *help;
12865 ALLOC(help, float,
12866 EX * EY);
12867
12868 /* Copy data... */
12869 for (int ix = 0; ix < met->nx; ix++)
12870 for (int iy = 0; iy < met->ny; iy++)
12871 help[ARRAY_2D(iy, ix, met->nx)] = scl * var[ix][iy];
12872
12873 /* Write data... */
12874 NC_PUT_FLOAT(varname, help, 0);
12875
12876 /* Free... */
12877 free(help);
12878}
#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 12882 of file mptrac.c.

12887 {
12888
12889 int varid;
12890 size_t start[4], count[4];
12891
12892 /* Allocate... */
12893 float *help;
12894 ALLOC(help, float,
12895 EX * EY * EP);
12896
12897 /* Copy data... */
12898 for (int ix = 0; ix < met->nx; ix++)
12899 for (int iy = 0; iy < met->ny; iy++)
12900 for (int ip = 0; ip < met->np; ip++)
12901 help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)] = scl * var[ix][iy][ip];
12902
12903 /* Write data... */
12904 NC_PUT_FLOAT(varname, help, 0);
12905
12906 /* Free... */
12907 free(help);
12908}

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

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

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

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

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