MPTRAC
Functions
mptrac.c File Reference

MPTRAC library definitions. More...

#include "mptrac.h"

Go to the source code of this file.

Functions

void cart2geo (const double *x, double *z, double *lon, double *lat)
 State variables of cuRAND random number generator. 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_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 day2doy (const int year, const int mon, const int day, int *doy)
 Get day of year from date. More...
 
void doy2day (const int year, const int doy, int *mon, int *day)
 Converts a given day of the year (DOY) to a date (month and day). More...
 
void fft_help (double *fcReal, double *fcImag, const int n)
 Computes the Fast Fourier Transform (FFT) of a complex sequence. More...
 
void geo2cart (const double z, const double lon, const double lat, double *x)
 Converts geographic coordinates (longitude, latitude, altitude) to Cartesian coordinates. More...
 
void get_met_help (const ctl_t *ctl, const double t, const int direct, const char *metbase, const double dt_met, char *filename)
 Generates a formatted filename for meteorological data files based on the input parameters. More...
 
void get_met_replace (char *orig, char *search, char *repl)
 Replaces occurrences of a substring in a string with another substring. More...
 
void get_tropo (const int met_tropo, ctl_t *ctl, clim_t *clim, met_t *met, const double *lons, const int nx, const double *lats, const int ny, double *pt, double *zt, double *tt, double *qt, double *o3t, double *ps, double *zs)
 Calculate tropopause data. More...
 
void intpol_check_lon_lat (const double *lons, const int nlon, const double *lats, const int nlat, const double lon, const double lat, double *lon2, double *lat2)
 Adjusts longitude and latitude to ensure they fall within valid bounds. More...
 
void intpol_met_4d_coord (const met_t *met0, float 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. More...
 
void intpol_met_space_3d (const met_t *met, float array[EX][EY][EP], const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
 Interpolates meteorological variables in 3D space. More...
 
void intpol_met_space_3d_ml (const met_t *met, float zs[EX][EY][EP], float array[EX][EY][EP], const double z, const double lon, const double lat, double *var)
 Interpolates meteorological data in 3D space. More...
 
void intpol_met_space_2d (const met_t *met, float array[EX][EY], const double lon, const double lat, double *var, int *ci, double *cw, const int init)
 Interpolates meteorological variables in 2D space. More...
 
void intpol_met_time_3d (const met_t *met0, float array0[EX][EY][EP], const met_t *met1, float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
 Interpolates meteorological data in 3D space and time. More...
 
void intpol_met_time_3d_ml (const met_t *met0, float zs0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float zs1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var)
 Interpolates meteorological data in both space and time. More...
 
void intpol_met_time_2d (const met_t *met0, float array0[EX][EY], const met_t *met1, float array1[EX][EY], const double ts, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
 Interpolates meteorological data in 2D space and time. More...
 
void intpol_tropo_3d (const double time0, float array0[EX][EY], const double time1, float array1[EX][EY], const double lons[EX], const double lats[EY], const int nlon, const int nlat, const double time, const double lon, const double lat, const int method, double *var, double *sigma)
 Interpolates tropopause data in 3D (latitude, longitude, and time). More...
 
void jsec2time (const double jsec, int *year, int *mon, int *day, int *hour, int *min, int *sec, double *remain)
 Converts Julian seconds to calendar date and time components. More...
 
double kernel_weight (const double kz[EP], const double kw[EP], const int nk, const double p)
 Calculates the kernel weight based on altitude and given kernel data. More...
 
double lapse_rate (const double t, const double h2o)
 Calculates the moist adiabatic lapse rate in Kelvin per kilometer. More...
 
void level_definitions (ctl_t *ctl)
 Defines pressure levels for meteorological data. More...
 
int locate_irr (const double *xx, const int n, const double x)
 Locate the index of the interval containing a given value in a sorted array. More...
 
int locate_irr_float (const float *xx, const int n, const double x, const int ig)
 Locate the index of the interval containing a given value in an irregularly spaced array. More...
 
int locate_reg (const double *xx, const int n, const double x)
 Locate the index of the interval containing a given value in a regular grid. More...
 
void locate_vert (float profiles[EX][EY][EP], const int np, const int lon_ap_ind, const int lat_ap_ind, const double height_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 tt)
 Computes gridded chemical tracer concentrations (volume mixing ratio) from individual air parcel mass data and assigns them back to the parcels. More...
 
void module_chem_init (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Initializes the chemistry modules by setting atmospheric composition. More...
 
void module_convection (const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Performs convective mixing of atmospheric particles. More...
 
void module_decay (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, atm_t *atm)
 Simulate exponential decay processes for atmospheric particles. More...
 
void module_diff_meso (const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Simulate mesoscale diffusion for atmospheric particles. More...
 
void module_diff_pbl (const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Computes particle diffusion within the planetary boundary layer (PBL). More...
 
void module_diff_turb (const ctl_t *ctl, cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Applies turbulent diffusion processes to atmospheric particles. More...
 
void module_dry_depo (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Simulate dry deposition of atmospheric particles. More...
 
void module_h2o2_chem (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Perform chemical reactions involving H2O2 within cloud particles. More...
 
void module_isosurf_init (const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Initialize the isosurface module based on atmospheric data. More...
 
void module_isosurf (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Apply the isosurface module to adjust atmospheric properties. More...
 
void module_meteo (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Update atmospheric properties using meteorological data. More...
 
void module_mixing (const ctl_t *ctl, const clim_t *clim, atm_t *atm, const double t)
 Update atmospheric properties through interparcel mixing. More...
 
void module_mixing_help (const ctl_t *ctl, const clim_t *clim, atm_t *atm, const int *ixs, const int *iys, const int *izs, const int qnt_idx, const int use_ensemble)
 Perform subgrid-scale interparcel mixing of a given quantity. More...
 
void module_oh_chem (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Perform hydroxyl chemistry calculations for atmospheric particles. More...
 
void module_position (const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Update the positions and pressure levels of atmospheric particles. More...
 
void module_rng_init (const int ntask)
 Initialize random number generators for parallel tasks. More...
 
void module_rng (const ctl_t *ctl, double *rs, const size_t n, const int method)
 Generate random numbers using various methods and distributions. More...
 
void module_sedi (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Simulate sedimentation of particles in the atmosphere. More...
 
void module_sort (const ctl_t *ctl, met_t *met0, atm_t *atm)
 Sort particles according to box index. More...
 
void module_sort_help (double *a, const int *p, const int np)
 Reorder an array based on a given permutation. More...
 
void module_timesteps (const ctl_t *ctl, cache_t *cache, met_t *met0, atm_t *atm, const double t)
 Calculate time steps for air parcels based on specified conditions. More...
 
void module_timesteps_init (ctl_t *ctl, const atm_t *atm)
 Initialize start time and time interval for time-stepping. More...
 
void module_tracer_chem (const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Simulate chemical reactions involving long-lived atmospheric tracers. More...
 
void module_wet_depo (const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
 Perform wet deposition calculations for air parcels. More...
 
void mptrac_alloc (ctl_t **ctl, cache_t **cache, clim_t **clim, met_t **met0, met_t **met1, atm_t **atm)
 Allocates and initializes memory resources for MPTRAC. More...
 
void mptrac_free (ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
 Frees memory resources allocated for MPTRAC. More...
 
void mptrac_get_met (ctl_t *ctl, clim_t *clim, const double t, met_t **met0, met_t **met1)
 Retrieves meteorological data for the specified time. More...
 
void mptrac_init (ctl_t *ctl, cache_t *cache, clim_t *clim, atm_t *atm, const int ntask)
 Initializes the MPTRAC model and its associated components. More...
 
int mptrac_read_atm (const char *filename, const ctl_t *ctl, atm_t *atm)
 Reads air parcel data from a specified file into the given atmospheric structure. More...
 
void mptrac_read_clim (const ctl_t *ctl, clim_t *clim)
 Reads various climatological data and populates the given climatology structure. More...
 
void mptrac_read_ctl (const char *filename, int argc, char *argv[], ctl_t *ctl)
 Reads control parameters from a configuration file and populates the given structure. More...
 
int mptrac_read_met (const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met)
 Reads meteorological data from a file, supporting multiple formats and MPI broadcasting. More...
 
void mptrac_run_timestep (ctl_t *ctl, cache_t *cache, clim_t *clim, met_t **met0, met_t **met1, atm_t *atm, double t)
 Executes a single timestep of the MPTRAC model simulation. More...
 
void mptrac_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...
 
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...
 
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...
 
void read_met_ml2pl (const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname)
 Reads global meteorological information from a grib file. More...
 
void read_met_monotonize (const ctl_t *ctl, met_t *met)
 Makes zeta and pressure profiles monotone. More...
 
int read_met_nc (const char *filename, const ctl_t *ctl, met_t *met)
 Reads meteorological data from a NetCDF file and processes it. More...
 
int read_met_nc_2d (const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const char *varname5, const char *varname6, const ctl_t *ctl, const met_t *met, float dest[EX][EY], const float scl, const int init)
 Reads a 2-dimensional meteorological variable from a NetCDF file. More...
 
int read_met_nc_3d (const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const ctl_t *ctl, const met_t *met, float dest[EX][EY][EP], const float scl)
 Reads a 3-dimensional meteorological variable from a NetCDF file. More...
 
void read_met_nc_grid (const char *filename, const int ncid, const ctl_t *ctl, met_t *met)
 Reads meteorological grid information from a NetCDF file. More...
 
void read_met_nc_levels (const int ncid, const ctl_t *ctl, met_t *met)
 Reads meteorological variables at different vertical levels from a NetCDF file. More...
 
void read_met_nc_surface (const int ncid, const ctl_t *ctl, met_t *met)
 Reads surface meteorological data from a netCDF file and stores it in the meteorological data structure. More...
 
void read_met_pbl (const ctl_t *ctl, met_t *met)
 Computes the planetary boundary layer (PBL) pressure based on meteorological data. More...
 
void read_met_periodic (met_t *met)
 Applies periodic boundary conditions to meteorological data along longitudinal axis. More...
 
void read_met_polar_winds (met_t *met)
 Applies a fix for polar winds in meteorological data. More...
 
void read_met_pv (met_t *met)
 Calculates potential vorticity (PV) from meteorological data. More...
 
void read_met_ozone (met_t *met)
 Calculates the total column ozone from meteorological ozone data. More...
 
void read_met_sample (const ctl_t *ctl, met_t *met)
 Downsamples meteorological data based on specified parameters. More...
 
void read_met_tropo (const ctl_t *ctl, const clim_t *clim, met_t *met)
 Calculates the tropopause and related meteorological variables based on various methods and stores the results in the meteorological data structure. More...
 
void read_obs (const char *filename, const ctl_t *ctl, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
 Reads observation data from a file and stores it in arrays. More...
 
void read_obs_asc (const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
 Reads observation data from an ASCII file. More...
 
void read_obs_nc (const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
 Reads observation data from a NetCDF file. More...
 
double scan_ctl (const char *filename, int argc, char *argv[], const char *varname, const int arridx, const char *defvalue, char *value)
 Scans a control file or command-line arguments for a specified variable. More...
 
double sedi (const double p, const double T, const double rp, const double rhop)
 Calculates the sedimentation velocity of a particle in air. More...
 
void spline (const double *x, const double *y, const int n, const double *x2, double *y2, const int n2, const int method)
 Performs spline interpolation or linear interpolation. More...
 
float stddev (const float *data, const int n)
 Calculates the standard deviation of a set of data. More...
 
double sza_calc (const double sec, const double lon, const double lat)
 Calculates the solar zenith angle. More...
 
void time2jsec (const int year, const int mon, const int day, const int hour, const int min, const int sec, const double remain, double *jsec)
 Converts time components to seconds since January 1, 2000, 12:00:00 UTC. More...
 
void timer (const char *name, const char *group, const int output)
 Measures and reports elapsed time for named and grouped timers. More...
 
double time_from_filename (const char *filename, const int offset)
 Extracts and converts a timestamp from a filename to Julian seconds. More...
 
double tropo_weight (const clim_t *clim, const atm_t *atm, const int ip)
 Computes a weighting factor based on tropopause pressure. More...
 
void write_atm_asc (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes air parcel data to an ASCII file or gnuplot. More...
 
void write_atm_bin (const char *filename, const ctl_t *ctl, const atm_t *atm)
 Writes air parcel data to a binary file. More...
 
void write_atm_clams (const char *filename, const ctl_t *ctl, const atm_t *atm)
 Writes air parcel data to a NetCDF file in the CLaMS format. More...
 
void write_atm_clams_traj (const char *dirname, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes CLaMS trajectory data to a NetCDF file. More...
 
void write_atm_nc (const char *filename, const ctl_t *ctl, const atm_t *atm)
 Writes air parcel data to a NetCDF file. More...
 
void write_csi (const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
 Writes Critical Success Index (CSI) data to a file. More...
 
void write_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 definitions.

Definition in file mptrac.c.

Function Documentation

◆ cart2geo()

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

State variables of cuRAND random number generator.

Converts Cartesian coordinates to geographic coordinates.

Definition at line 74 of file mptrac.c.

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

◆ clim_oh()

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

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

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

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

Definition at line 89 of file mptrac.c.

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

◆ clim_oh_diurnal_correction()

void clim_oh_diurnal_correction ( const ctl_t ctl,
clim_t clim 
)

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

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

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

Definition at line 116 of file mptrac.c.

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

◆ clim_photo()

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

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

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

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

This function performs the following steps:

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

Definition at line 149 of file mptrac.c.

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

◆ clim_tropo()

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

Calculates the tropopause pressure based on climatological data.

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

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

This function performs the following steps:

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

Definition at line 200 of file mptrac.c.

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

◆ clim_tropo_init()

void clim_tropo_init ( clim_t clim)

Initializes the tropopause data in the climatology structure.

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

Parameters
climPointer to the climatology structure to be initialized.

This function performs the following steps:

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

Definition at line 228 of file mptrac.c.

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

◆ clim_ts()

double clim_ts ( const clim_ts_t ts,
const double  t 
)

Interpolates a time series of climatological variables.

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

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

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

Author
Lars Hoffmann

Definition at line 383 of file mptrac.c.

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

◆ clim_zm()

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

Interpolates monthly mean zonal mean climatological variables.

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

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

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

Author
Lars Hoffmann

Definition at line 401 of file mptrac.c.

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

◆ compress_pck()

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

Compresses or decompresses a 3D array of floats.

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

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

The function performs the following steps:

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

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

Author
Lars Hoffmann

Definition at line 664 of file mptrac.c.

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

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

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

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

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

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

952 {
953
954 double data[2 * EX];
955
956 /* Check size... */
957 if (n > EX)
958 ERRMSG("Too many data points!");
959
960 /* Allocate... */
961 gsl_fft_complex_wavetable *wavetable =
962 gsl_fft_complex_wavetable_alloc((size_t) n);
963 gsl_fft_complex_workspace *workspace =
964 gsl_fft_complex_workspace_alloc((size_t) n);
965
966 /* Set data (real, complex)... */
967 for (int i = 0; i < n; i++) {
968 data[2 * i] = fcReal[i];
969 data[2 * i + 1] = fcImag[i];
970 }
971
972 /* Calculate FFT... */
973 gsl_fft_complex_forward(data, 1, (size_t) n, wavetable, workspace);
974
975 /* Copy data... */
976 for (int i = 0; i < n; i++) {
977 fcReal[i] = data[2 * i];
978 fcImag[i] = data[2 * i + 1];
979 }
980
981 /* Free... */
982 gsl_fft_complex_wavetable_free(wavetable);
983 gsl_fft_complex_workspace_free(workspace);
984}
#define ERRMSG(...)
Print an error message with contextual information and terminate the program.
Definition: mptrac.h:1991
#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 988 of file mptrac.c.

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

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

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

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

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

1110 {
1111
1113
1114 ctl->met_tropo = met_tropo;
1115 read_met_tropo(ctl, clim, met);
1116#pragma omp parallel for default(shared) private(ci,cw)
1117 for (int ix = 0; ix < nx; ix++)
1118 for (int iy = 0; iy < ny; iy++) {
1119 intpol_met_space_2d(met, met->pt, lons[ix], lats[iy],
1120 &pt[iy * nx + ix], ci, cw, 1);
1121 intpol_met_space_2d(met, met->ps, lons[ix], lats[iy],
1122 &ps[iy * nx + ix], ci, cw, 0);
1123 intpol_met_space_2d(met, met->zs, lons[ix], lats[iy],
1124 &zs[iy * nx + ix], ci, cw, 0);
1125 intpol_met_space_3d(met, met->z, pt[iy * nx + ix], lons[ix],
1126 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
1127 intpol_met_space_3d(met, met->t, pt[iy * nx + ix], lons[ix],
1128 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
1129 intpol_met_space_3d(met, met->h2o, pt[iy * nx + ix], lons[ix],
1130 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
1131 intpol_met_space_3d(met, met->o3, pt[iy * nx + ix], lons[ix],
1132 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
1133 }
1134}
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:1462
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:9122
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:1337
#define INTPOL_INIT
Initialize arrays for interpolation.
Definition: mptrac.h:769
int met_tropo
Tropopause definition (0=none, 1=clim, 2=cold point, 3=WMO_1st, 4=WMO_2nd, 5=dynamical).
Definition: mptrac.h:2707
float h2o[EX][EY][EP]
Water vapor volume mixing ratio [1].
Definition: mptrac.h:3589
float ps[EX][EY]
Surface pressure [hPa].
Definition: mptrac.h:3499
float zs[EX][EY]
Surface geopotential height [km].
Definition: mptrac.h:3505
float o3[EX][EY][EP]
Ozone volume mixing ratio [1].
Definition: mptrac.h:3592
float t[EX][EY][EP]
Temperature [K].
Definition: mptrac.h:3574
float pt[EX][EY]
Tropopause pressure [hPa].
Definition: mptrac.h:3532
float z[EX][EY][EP]
Geopotential height [km].
Definition: mptrac.h:3571
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 1138 of file mptrac.c.

1146 {
1147
1148 /* Check longitude... */
1149 *lon2 = FMOD(lon, 360.);
1150 if (*lon2 < lons[0])
1151 *lon2 += 360;
1152 else if (*lon2 > lons[nlon - 1])
1153 *lon2 -= 360;
1154
1155 /* Check latitude... */
1156 *lat2 = lat;
1157 if (lats[0] < lats[nlat - 1])
1158 *lat2 = MIN(MAX(*lat2, lats[0]), lats[nlat - 1]);
1159 else
1160 *lat2 = MIN(MAX(*lat2, lats[nlat - 1]), lats[0]);
1161}

◆ intpol_met_4d_coord()

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

Interpolates meteorological variables to a given position and time.

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

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

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

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

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

Definition at line 1165 of file mptrac.c.

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

1346 {
1347
1348 /* Initialize interpolation... */
1349 if (init) {
1350
1351 /* Check longitude and latitude... */
1352 double lon2, lat2;
1353 intpol_check_lon_lat(met->lon, met->nx, met->lat, met->ny, lon, lat,
1354 &lon2, &lat2);
1355
1356 /* Get interpolation indices... */
1357 ci[0] = locate_irr(met->p, met->np, p);
1358 ci[1] = locate_reg(met->lon, met->nx, lon2);
1359 ci[2] = locate_irr(met->lat, met->ny, lat2);
1360
1361 /* Get interpolation weights... */
1362 cw[0] = (met->p[ci[0] + 1] - p)
1363 / (met->p[ci[0] + 1] - met->p[ci[0]]);
1364 cw[1] = (met->lon[ci[1] + 1] - lon2)
1365 / (met->lon[ci[1] + 1] - met->lon[ci[1]]);
1366 cw[2] = (met->lat[ci[2] + 1] - lat2)
1367 / (met->lat[ci[2] + 1] - met->lat[ci[2]]);
1368 }
1369
1370 /* Interpolate vertically... */
1371 double aux00 =
1372 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
1373 + array[ci[1]][ci[2]][ci[0] + 1];
1374 double aux01 =
1375 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
1376 array[ci[1]][ci[2] + 1][ci[0] + 1])
1377 + array[ci[1]][ci[2] + 1][ci[0] + 1];
1378 double aux10 =
1379 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
1380 array[ci[1] + 1][ci[2]][ci[0] + 1])
1381 + array[ci[1] + 1][ci[2]][ci[0] + 1];
1382 double aux11 =
1383 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
1384 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
1385 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
1386
1387 /* Interpolate horizontally... */
1388 aux00 = cw[2] * (aux00 - aux01) + aux01;
1389 aux11 = cw[2] * (aux10 - aux11) + aux11;
1390 *var = cw[1] * (aux00 - aux11) + aux11;
1391}
int np
Number of pressure levels.
Definition: mptrac.h:3481
double p[EP]
Pressure levels [hPa].
Definition: mptrac.h:3493
Here is the call graph for this function:

◆ intpol_met_space_3d_ml()

void intpol_met_space_3d_ml ( const met_t met,
float  zs[EX][EY][EP],
float  vals[EX][EY][EP],
const double  z,
const double  lon,
const double  lat,
double *  val 
)

Interpolates meteorological data in 3D space.

This function performs trilinear interpolation to estimate a meteorological variable at a given altitude (z), longitude (lon), and latitude (lat). It uses a structured 3D grid with irregular vertical spacing and regular horizontal spacing.

Parameters
metPointer to the meteorological data structure containing grid information.
zs3D array of altitude levels at each horizontal grid point.
array3D array of meteorological data values corresponding to the grid points.
zTarget altitude for interpolation.
lonTarget longitude for interpolation.
latTarget latitude for interpolation.
varPointer to a variable where the interpolated value will be stored.
Author
Lars Hoffmann

Definition at line 1395 of file mptrac.c.

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

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

1532 {
1533
1534 double var0, var1;
1535
1536 /* Spatial interpolation... */
1537 intpol_met_space_3d(met0, array0, p, lon, lat, &var0, ci, cw, init);
1538 intpol_met_space_3d(met1, array1, p, lon, lat, &var1, ci, cw, 0);
1539
1540 /* Get weighting factor... */
1541 const double wt = (met1->time - ts) / (met1->time - met0->time);
1542
1543 /* Interpolate... */
1544 *var = wt * (var0 - var1) + var1;
1545}
Here is the call graph for this function:

◆ intpol_met_time_3d_ml()

void intpol_met_time_3d_ml ( const met_t met0,
float  zs0[EX][EY][EP],
float  array0[EX][EY][EP],
const met_t met1,
float  zs1[EX][EY][EP],
float  array1[EX][EY][EP],
const double  ts,
const double  p,
const double  lon,
const double  lat,
double *  var 
)

Interpolates meteorological data in both space and time.

This function performs 3D spatial interpolation at two time steps (met0 and met1), then interpolates the results in time to estimate the meteorological variable at a given time (ts), pressure level (p), longitude (lon), and latitude (lat).

Parameters
met0Pointer to the meteorological data structure at the earlier time step.
zs03D array of altitude levels for met0.
array03D array of meteorological data values corresponding to met0.
met1Pointer to the meteorological data structure at the later time step.
zs13D array of altitude levels for met1.
array13D array of meteorological data values corresponding to met1.
tsTarget time for interpolation.
pTarget pressure level for interpolation.
lonTarget longitude for interpolation.
latTarget latitude for interpolation.
varPointer to a variable where the interpolated value will be stored.
Author
Lars Hoffmann

Definition at line 1549 of file mptrac.c.

1560 {
1561
1562 double var0, var1;
1563
1564 /* Spatial interpolation... */
1565 intpol_met_space_3d_ml(met0, zs0, array0, p, lon, lat, &var0);
1566 intpol_met_space_3d_ml(met1, zs1, array1, p, lon, lat, &var1);
1567
1568 /* Interpolate... */
1569 *var = LIN(met0->time, var0, met1->time, var1, ts);
1570}
void intpol_met_space_3d_ml(const met_t *met, float zs[EX][EY][EP], float array[EX][EY][EP], const double z, const double lon, const double lat, double *var)
Interpolates meteorological data in 3D space.
Definition: mptrac.c:1395
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 1574 of file mptrac.c.

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

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

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

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

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

1759 {
1760
1761 /*
1762 Calculate moist adiabatic lapse rate [K/km] from temperature [K]
1763 and water vapor volume mixing ratio [1].
1764
1765 Reference: https://en.wikipedia.org/wiki/Lapse_rate
1766 */
1767
1768 const double a = RA * SQR(t), r = SH(h2o) / (1. - SH(h2o));
1769
1770 return 1e3 * G0 * (a + LV * r * t) / (CPD * a + SQR(LV) * r * EPS);
1771}
#define RA
Specific gas constant of dry air [J/(kg K)].
Definition: mptrac.h:239
#define SH(h2o)
Compute specific humidity from water vapor volume mixing ratio.
Definition: mptrac.h:1631
#define LV
Latent heat of vaporization of water [J/kg].
Definition: mptrac.h:204
#define G0
Standard gravity [m/s^2].
Definition: mptrac.h:194
#define EPS
Ratio of the specific gas constant of dry air and water vapor [1].
Definition: mptrac.h:189
#define CPD
Specific heat of dry air at constant pressure [J/(kg K)].
Definition: mptrac.h:184

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

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

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

1988 {
1989
1990 int ilo = 0;
1991 int ihi = n - 1;
1992 int i = (ihi + ilo) >> 1;
1993
1994 if (xx[i] < xx[i + 1])
1995 while (ihi > ilo + 1) {
1996 i = (ihi + ilo) >> 1;
1997 if (xx[i] > x)
1998 ihi = i;
1999 else
2000 ilo = i;
2001 } else
2002 while (ihi > ilo + 1) {
2003 i = (ihi + ilo) >> 1;
2004 if (xx[i] <= x)
2005 ihi = i;
2006 else
2007 ilo = i;
2008 }
2009
2010 return ilo;
2011}

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

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

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

2052 {
2053
2054 /* Calculate index... */
2055 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2056
2057 /* Check range... */
2058 if (i < 0)
2059 return 0;
2060 else if (i > n - 2)
2061 return n - 2;
2062 else
2063 return i;
2064}

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

2074 {
2075
2076 ind[0] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind],
2077 np, height_ap, 0);
2078 ind[1] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind],
2079 np, height_ap, ind[0]);
2080 ind[2] = locate_irr_float(profiles[lon_ap_ind][lat_ap_ind + 1],
2081 np, height_ap, ind[1]);
2082 ind[3] = locate_irr_float(profiles[lon_ap_ind + 1][lat_ap_ind + 1],
2083 np, height_ap, ind[2]);
2084}
Here is the call graph for this function:

◆ module_advect()

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

Advances particle positions using different advection schemes.

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

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

Definition at line 2088 of file mptrac.c.

2093 {
2094
2095 /* Set timer... */
2096 SELECT_TIMER("MODULE_ADVECT", "PHYSICS", NVTX_GPU);
2097
2098 /* Use omega vertical velocity... */
2099 if (ctl->advect_vert_coord == 0 || ctl->advect_vert_coord == 2) {
2100
2101 /* Loop over particles... */
2102 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2103
2104 /* Init... */
2106 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
2107 x[3] = { 0, 0, 0 };
2108
2109 /* Loop over integration nodes... */
2110 for (int i = 0; i < ctl->advect; i++) {
2111
2112 /* Set position... */
2113 if (i == 0) {
2114 dts = 0.0;
2115 x[0] = atm->lon[ip];
2116 x[1] = atm->lat[ip];
2117 x[2] = atm->p[ip];
2118 } else {
2119 dts = (i == 3 ? 1.0 : 0.5) * cache->dt[ip];
2120 x[0] = atm->lon[ip] + DX2DEG(dts * u[i - 1] / 1000., atm->lat[ip]);
2121 x[1] = atm->lat[ip] + DY2DEG(dts * v[i - 1] / 1000.);
2122 x[2] = atm->p[ip] + dts * w[i - 1];
2123 }
2124 const double tm = atm->time[ip] + dts;
2125
2126 /* Interpolate meteo data on pressure levels... */
2127 if (ctl->advect_vert_coord == 0) {
2128 intpol_met_time_3d(met0, met0->u, met1, met1->u,
2129 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2130 intpol_met_time_3d(met0, met0->v, met1, met1->v,
2131 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2132 intpol_met_time_3d(met0, met0->w, met1, met1->w,
2133 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
2134 }
2135
2136 /* Interpolate meteo data on model levels... */
2137 else {
2138 intpol_met_time_3d_ml(met0, met0->pl, met0->ul,
2139 met1, met1->pl, met1->ul,
2140 tm, x[2], x[0], x[1], &u[i]);
2141 intpol_met_time_3d_ml(met0, met0->pl, met0->vl,
2142 met1, met1->pl, met1->vl,
2143 tm, x[2], x[0], x[1], &v[i]);
2144 intpol_met_time_3d_ml(met0, met0->pl, met0->wl,
2145 met1, met1->pl, met1->wl,
2146 tm, x[2], x[0], x[1], &w[i]);
2147 }
2148
2149 /* Get mean wind... */
2150 double k = 1.0;
2151 if (ctl->advect == 2)
2152 k = (i == 0 ? 0.0 : 1.0);
2153 else if (ctl->advect == 4)
2154 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2155 um += k * u[i];
2156 vm += k * v[i];
2157 wm += k * w[i];
2158 }
2159
2160 /* Set new position... */
2161 atm->time[ip] += cache->dt[ip];
2162 atm->lon[ip] += DX2DEG(cache->dt[ip] * um / 1000.,
2163 (ctl->advect == 2 ? x[1] : atm->lat[ip]));
2164 atm->lat[ip] += DY2DEG(cache->dt[ip] * vm / 1000.);
2165 atm->p[ip] += cache->dt[ip] * wm;
2166 }
2167 }
2168
2169 /* Use zetadot vertical velocity... */
2170 else if (ctl->advect_vert_coord == 1) {
2171
2172 /* Loop over particles... */
2173 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,cache,met0,met1,atm)") {
2174
2175 /* Convert pressure to zeta... */
2177 intpol_met_4d_coord(met0, met0->pl, met0->zetal, met1,
2178 met1->pl, met1->zetal, atm->time[ip], atm->p[ip],
2179 atm->lon[ip], atm->lat[ip],
2180 &atm->q[ctl->qnt_zeta][ip], ci, cw, 1);
2181
2182 /* Init... */
2183 double dts, u[4], um = 0, v[4], vm = 0, zeta_dot[4],
2184 zeta_dotm = 0, x[3] = { 0, 0, 0 };
2185
2186 /* Loop over integration nodes... */
2187 for (int i = 0; i < ctl->advect; i++) {
2188
2189 /* Set position... */
2190 if (i == 0) {
2191 dts = 0.0;
2192 x[0] = atm->lon[ip];
2193 x[1] = atm->lat[ip];
2194 x[2] = atm->q[ctl->qnt_zeta][ip];
2195 } else {
2196 dts = (i == 3 ? 1.0 : 0.5) * cache->dt[ip];
2197 x[0] = atm->lon[ip] + DX2DEG(dts * u[i - 1] / 1000., atm->lat[ip]);
2198 x[1] = atm->lat[ip] + DY2DEG(dts * v[i - 1] / 1000.);
2199 x[2] = atm->q[ctl->qnt_zeta][ip] + dts * zeta_dot[i - 1];
2200 }
2201 const double tm = atm->time[ip] + dts;
2202
2203 /* Interpolate meteo data... */
2204 intpol_met_4d_coord(met0, met0->zetal, met0->ul, met1, met1->zetal,
2205 met1->ul, tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2206 intpol_met_4d_coord(met0, met0->zetal, met0->vl, met1, met1->zetal,
2207 met1->vl, tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2208 intpol_met_4d_coord(met0, met0->zetal, met0->zeta_dotl, met1,
2209 met1->zetal, met1->zeta_dotl, tm, x[2], x[0],
2210 x[1], &zeta_dot[i], ci, cw, 0);
2211
2212 /* Get mean wind... */
2213 double k = 1.0;
2214 if (ctl->advect == 2)
2215 k = (i == 0 ? 0.0 : 1.0);
2216 else if (ctl->advect == 4)
2217 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2218 um += k * u[i];
2219 vm += k * v[i];
2220 zeta_dotm += k * zeta_dot[i];
2221 }
2222
2223 /* Set new position... */
2224 atm->time[ip] += cache->dt[ip];
2225 atm->lon[ip] += DX2DEG(cache->dt[ip] * um / 1000.,
2226 (ctl->advect == 2 ? x[1] : atm->lat[ip]));
2227 atm->lat[ip] += DY2DEG(cache->dt[ip] * vm / 1000.);
2228 atm->q[ctl->qnt_zeta][ip] += cache->dt[ip] * zeta_dotm;
2229
2230 /* Convert zeta to pressure... */
2231 intpol_met_4d_coord(met0, met0->zetal, met0->pl, met1, met1->zetal,
2232 met1->pl, atm->time[ip],
2233 atm->q[ctl->qnt_zeta][ip], atm->lon[ip],
2234 atm->lat[ip], &atm->p[ip], ci, cw, 1);
2235 }
2236 }
2237}
void intpol_met_4d_coord(const met_t *met0, float heights0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float heights1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double height, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables to a given position and time.
Definition: mptrac.c:1165
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:1520
void intpol_met_time_3d_ml(const met_t *met0, float zs0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float zs1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var)
Interpolates meteorological data in both space and time.
Definition: mptrac.c:1549
#define PARTICLE_LOOP(ip0, ip1, check_dt,...)
Loop over particle indices with OpenACC acceleration.
Definition: mptrac.h:1361
#define DX2DEG(dx, lat)
Convert a distance in kilometers to degrees longitude at a given latitude.
Definition: mptrac.h:547
#define SELECT_TIMER(id, group, color)
Select and start a timer with specific attributes.
Definition: mptrac.h:2071
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
Definition: mptrac.h:565
double time[NP]
Time [s].
Definition: mptrac.h:3248
double lat[NP]
Latitude [deg].
Definition: mptrac.h:3257
double lon[NP]
Longitude [deg].
Definition: mptrac.h:3254
int np
Number of air parcels.
Definition: mptrac.h:3245
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
Definition: mptrac.h:3260
double p[NP]
Pressure [hPa].
Definition: mptrac.h:3251
double dt[NP]
Timesteps [s].
Definition: mptrac.h:3291
int advect
Advection scheme (0=off, 1=Euler, 2=midpoint, 4=Runge-Kutta).
Definition: mptrac.h:2742
int qnt_zeta
Quantity array index for zeta vertical coordinate.
Definition: mptrac.h:2459
int advect_vert_coord
Vertical velocity of air parcels (0=omega_on_plev, 1=zetadot_on_mlev, 2=omega_on_mlev).
Definition: mptrac.h:2746
float zeta_dotl[EX][EY][EP]
Vertical velocity on model levels [K/s].
Definition: mptrac.h:3625
float w[EX][EY][EP]
Vertical velocity [hPa/s].
Definition: mptrac.h:3583
float wl[EX][EY][EP]
Vertical velocity on model levels [hPa/s].
Definition: mptrac.h:3619
float vl[EX][EY][EP]
Meridional wind on model levels [m/s].
Definition: mptrac.h:3616
float u[EX][EY][EP]
Zonal wind [m/s].
Definition: mptrac.h:3577
float ul[EX][EY][EP]
Zonal wind on model levels [m/s].
Definition: mptrac.h:3613
float v[EX][EY][EP]
Meridional wind [m/s].
Definition: mptrac.h:3580
float pl[EX][EY][EP]
Pressure on model levels [hPa].
Definition: mptrac.h:3610
float zetal[EX][EY][EP]
Zeta on model levels [K].
Definition: mptrac.h:3622
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 2241 of file mptrac.c.

2246 {
2247
2248 /* Check parameters... */
2249 if (ctl->advect_vert_coord != 1)
2250 return;
2251
2252 /* Set timer... */
2253 SELECT_TIMER("MODULE_ADVECT_INIT", "PHYSICS", NVTX_GPU);
2254
2255 /* Loop over particles... */
2256 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,met0,met1,atm)") {
2257
2258 /* Initialize pressure consistent with zeta... */
2260 intpol_met_4d_coord(met0, met0->zetal, met0->pl, met1, met1->zetal,
2261 met1->pl, atm->time[ip], atm->q[ctl->qnt_zeta][ip],
2262 atm->lon[ip], atm->lat[ip], &atm->p[ip], ci, cw, 1);
2263 }
2264}
Here is the call graph for this function:

◆ module_bound_cond()

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

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

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

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

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

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

Definition at line 2268 of file mptrac.c.

2274 {
2275
2276 /* Set timer... */
2277 SELECT_TIMER("MODULE_BOUND_COND", "PHYSICS", NVTX_GPU);
2278
2279 /* Check quantity flags... */
2280 if (ctl->qnt_m < 0 && ctl->qnt_vmr < 0 && ctl->qnt_Cccl4
2281 && ctl->qnt_Cccl3f < 0 && ctl->qnt_Cccl2f2 < 0
2282 && ctl->qnt_Cn2o < 0 && ctl->qnt_Csf6 < 0 && ctl->qnt_aoa < 0)
2283 return;
2284
2285 /* Loop over particles... */
2286 PARTICLE_LOOP(0, atm->np, 1,
2287 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2288
2289 /* Check latitude and pressure range... */
2290 if (atm->lat[ip] < ctl->bound_lat0 || atm->lat[ip] > ctl->bound_lat1
2291 || atm->p[ip] > ctl->bound_p0 || atm->p[ip] < ctl->bound_p1)
2292 continue;
2293
2294 /* Check surface layer... */
2295 if (ctl->bound_dps > 0 || ctl->bound_dzs > 0
2296 || ctl->bound_zetas > 0 || ctl->bound_pbl) {
2297
2298 /* Get surface pressure... */
2299 double ps;
2301 INTPOL_2D(ps, 1);
2302
2303 /* Check pressure... */
2304 if (ctl->bound_dps > 0 && atm->p[ip] < ps - ctl->bound_dps)
2305 continue;
2306
2307 /* Check height... */
2308 if (ctl->bound_dzs > 0 && Z(atm->p[ip]) > Z(ps) + ctl->bound_dzs)
2309 continue;
2310
2311 /* Check zeta range... */
2312 if (ctl->bound_zetas > 0) {
2313 double t;
2314 INTPOL_3D(t, 1);
2315 if (ZETA(ps, atm->p[ip], t) > ctl->bound_zetas)
2316 continue;
2317 }
2318
2319 /* Check planetary boundary layer... */
2320 if (ctl->bound_pbl) {
2321 double pbl;
2322 INTPOL_2D(pbl, 0);
2323 if (atm->p[ip] < pbl)
2324 continue;
2325 }
2326 }
2327
2328 /* Set mass and volume mixing ratio... */
2329 if (ctl->qnt_m >= 0 && ctl->bound_mass >= 0)
2330 atm->q[ctl->qnt_m][ip] =
2331 ctl->bound_mass + ctl->bound_mass_trend * atm->time[ip];
2332 if (ctl->qnt_vmr >= 0 && ctl->bound_vmr >= 0)
2333 atm->q[ctl->qnt_vmr][ip] =
2334 ctl->bound_vmr + ctl->bound_vmr_trend * atm->time[ip];
2335
2336 /* Set CFC-10 volume mixing ratio... */
2337 if (ctl->qnt_Cccl4 >= 0 && ctl->clim_ccl4_timeseries[0] != '-')
2338 atm->q[ctl->qnt_Cccl4][ip] = clim_ts(&clim->ccl4, atm->time[ip]);
2339
2340 /* Set CFC-11 volume mixing ratio... */
2341 if (ctl->qnt_Cccl3f >= 0 && ctl->clim_ccl3f_timeseries[0] != '-')
2342 atm->q[ctl->qnt_Cccl3f][ip] = clim_ts(&clim->ccl3f, atm->time[ip]);
2343
2344 /* Set CFC-12 volume mixing ratio... */
2345 if (ctl->qnt_Cccl2f2 >= 0 && ctl->clim_ccl2f2_timeseries[0] != '-')
2346 atm->q[ctl->qnt_Cccl2f2][ip] = clim_ts(&clim->ccl2f2, atm->time[ip]);
2347
2348 /* Set N2O volume mixing ratio... */
2349 if (ctl->qnt_Cn2o >= 0 && ctl->clim_n2o_timeseries[0] != '-')
2350 atm->q[ctl->qnt_Cn2o][ip] = clim_ts(&clim->n2o, atm->time[ip]);
2351
2352 /* Set SF6 volume mixing ratio... */
2353 if (ctl->qnt_Csf6 >= 0 && ctl->clim_sf6_timeseries[0] != '-')
2354 atm->q[ctl->qnt_Csf6][ip] = clim_ts(&clim->sf6, atm->time[ip]);
2355
2356 /* Set age of air... */
2357 if (ctl->qnt_aoa >= 0)
2358 atm->q[ctl->qnt_aoa][ip] = atm->time[ip];
2359 }
2360}
double clim_ts(const clim_ts_t *ts, const double t)
Interpolates a time series of climatological variables.
Definition: mptrac.c:383
#define INTPOL_3D(var, init)
Perform 3D interpolation for a meteorological variable.
Definition: mptrac.h:800
#define ZETA(ps, p, t)
Computes the value of the zeta vertical coordinate.
Definition: mptrac.h:1878
#define INTPOL_2D(var, init)
Perform 2D interpolation for a meteorological variable.
Definition: mptrac.h:783
clim_ts_t ccl2f2
CFC-12 time series.
Definition: mptrac.h:3452
clim_ts_t sf6
SF6 time series.
Definition: mptrac.h:3458
clim_ts_t ccl4
CFC-10 time series.
Definition: mptrac.h:3446
clim_ts_t ccl3f
CFC-11 time series.
Definition: mptrac.h:3449
clim_ts_t n2o
N2O time series.
Definition: mptrac.h:3455
int qnt_Cccl2f2
Quantity array index for CFC-12 volume mixing ratio (chemistry code).
Definition: mptrac.h:2528
int qnt_m
Quantity array index for mass.
Definition: mptrac.h:2276
int qnt_aoa
Quantity array index for age of air.
Definition: mptrac.h:2537
char clim_n2o_timeseries[LEN]
Filename of N2O time series.
Definition: mptrac.h:2872
double bound_dzs
Boundary conditions surface layer depth [km].
Definition: mptrac.h:2821
int qnt_Cccl4
Quantity array index for CFC-10 volume mixing ratio (chemistry code).
Definition: mptrac.h:2522
double bound_mass
Boundary conditions mass per particle [kg].
Definition: mptrac.h:2794
int qnt_vmr
Quantity array index for volume mixing ratio.
Definition: mptrac.h:2279
double bound_lat1
Boundary conditions maximum longitude [deg].
Definition: mptrac.h:2809
int bound_pbl
Boundary conditions planetary boundary layer (0=no, 1=yes).
Definition: mptrac.h:2827
double bound_p1
Boundary conditions top pressure [hPa].
Definition: mptrac.h:2815
double bound_vmr
Boundary conditions volume mixing ratio [ppv].
Definition: mptrac.h:2800
double bound_lat0
Boundary conditions minimum longitude [deg].
Definition: mptrac.h:2806
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
Definition: mptrac.h:2803
int qnt_Cn2o
Quantity array index for N2O volume mixing ratio (chemistry code).
Definition: mptrac.h:2531
int qnt_Cccl3f
Quantity array index for CFC-11 volume mixing ratio (chemistry code).
Definition: mptrac.h:2525
int qnt_Csf6
Quantity array index for SF6 volume mixing ratio (chemistry code).
Definition: mptrac.h:2534
double bound_dps
Boundary conditions surface layer depth [hPa].
Definition: mptrac.h:2818
double bound_mass_trend
Boundary conditions mass per particle trend [kg/s].
Definition: mptrac.h:2797
double bound_p0
Boundary conditions bottom pressure [hPa].
Definition: mptrac.h:2812
char clim_ccl4_timeseries[LEN]
Filename of CFC-10 time series.
Definition: mptrac.h:2863
char clim_sf6_timeseries[LEN]
Filename of SF6 time series.
Definition: mptrac.h:2875
char clim_ccl3f_timeseries[LEN]
Filename of CFC-11 time series.
Definition: mptrac.h:2866
char clim_ccl2f2_timeseries[LEN]
Filename of CFC-12 time series.
Definition: mptrac.h:2869
double bound_zetas
Boundary conditions surface layer zeta [K].
Definition: mptrac.h:2824
Here is the call graph for this function:

◆ module_chem_grid()

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

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

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

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

Parallelization is supported via OpenMP or OpenACC.

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

Definition at line 2364 of file mptrac.c.

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

◆ module_chem_init()

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

Initializes the chemistry modules by setting atmospheric composition.

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

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

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

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

Definition at line 2526 of file mptrac.c.

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

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

◆ module_decay()

void module_decay ( const ctl_t ctl,
const cache_t cache,
const clim_t clim,
atm_t atm 
)

Simulate exponential decay processes for atmospheric particles.

This function simulates decay processes for atmospheric particles based on their mass or volume mixing ratio. It loops over each particle and calculates the decay rate using weighting factors for tropospheric and stratospheric lifetimes. Exponential decay is then calculated, and the mass or volume mixing ratio of particles is updated accordingly. Loss rates can also be calculated and updated based on the decay process.

The function checks for quantity flags to ensure that mass or volume mixing ratio data is available. It then calculates the weighting factor based on the particle's location in the atmosphere and sets the lifetime accordingly. Exponential decay is calculated using the time step and the lifetime, and the particle's mass or volume mixing ratio is updated. Loss rates can also be updated based on the decay process.

Parameters
ctlPointer to the control structure containing simulation parameters.
cachePointer to the cache structure for temporary data and random numbers.
climPointer to the climate data structure containing atmospheric data.
atmPointer to the atmospheric data structure containing particle information.
Author
Lars Hoffmann

Definition at line 2641 of file mptrac.c.

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

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

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

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

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

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

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

3154 {
3155
3156 /* Set timer... */
3157 SELECT_TIMER("MODULE_ISOSURF", "PHYSICS", NVTX_GPU);
3158
3159 /* Loop over particles... */
3160 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,cache,met0,met1,atm)") {
3161
3162 /* Init... */
3163 double t;
3165
3166 /* Restore pressure... */
3167 if (ctl->isosurf == 1)
3168 atm->p[ip] = cache->iso_var[ip];
3169
3170 /* Restore density... */
3171 else if (ctl->isosurf == 2) {
3172 INTPOL_3D(t, 1);
3173 atm->p[ip] = cache->iso_var[ip] * t;
3174 }
3175
3176 /* Restore potential temperature... */
3177 else if (ctl->isosurf == 3) {
3178 INTPOL_3D(t, 1);
3179 atm->p[ip] = 1000. * pow(cache->iso_var[ip] / t, -1. / 0.286);
3180 }
3181
3182 /* Interpolate pressure... */
3183 else if (ctl->isosurf == 4) {
3184 if (atm->time[ip] <= cache->iso_ts[0])
3185 atm->p[ip] = cache->iso_ps[0];
3186 else if (atm->time[ip] >= cache->iso_ts[cache->iso_n - 1])
3187 atm->p[ip] = cache->iso_ps[cache->iso_n - 1];
3188 else {
3189 int idx = locate_irr(cache->iso_ts, cache->iso_n, atm->time[ip]);
3190 atm->p[ip] = LIN(cache->iso_ts[idx], cache->iso_ps[idx],
3191 cache->iso_ts[idx + 1], cache->iso_ps[idx + 1],
3192 atm->time[ip]);
3193 }
3194 }
3195 }
3196}
Here is the call graph for this function:

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

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

◆ module_mixing()

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

Update atmospheric properties through interparcel mixing.

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

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

Definition at line 3358 of file mptrac.c.

3362 {
3363
3364 /* Set timer... */
3365 SELECT_TIMER("MODULE_MIXING", "PHYSICS", NVTX_GPU);
3366
3367 /* Allocate... */
3368 const int np = atm->np;
3369 int *restrict const ixs = (int *) malloc((size_t) np * sizeof(int));
3370 int *restrict const iys = (int *) malloc((size_t) np * sizeof(int));
3371 int *restrict const izs = (int *) malloc((size_t) np * sizeof(int));
3372
3373 /* Set grid box size... */
3374 const double dz = (ctl->mixing_z1 - ctl->mixing_z0) / ctl->mixing_nz;
3375 const double dlon = (ctl->mixing_lon1 - ctl->mixing_lon0) / ctl->mixing_nx;
3376 const double dlat = (ctl->mixing_lat1 - ctl->mixing_lat0) / ctl->mixing_ny;
3377
3378 /* Set time interval... */
3379 const double t0 = t - 0.5 * ctl->dt_mod;
3380 const double t1 = t + 0.5 * ctl->dt_mod;
3381
3382 /* Get indices... */
3383#ifdef _OPENACC
3384#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
3385#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
3386#pragma acc parallel loop independent gang vector
3387#else
3388#pragma omp parallel for default(shared)
3389#endif
3390 for (int ip = 0; ip < np; ip++) {
3391 ixs[ip] = (int) ((atm->lon[ip] - ctl->mixing_lon0) / dlon);
3392 iys[ip] = (int) ((atm->lat[ip] - ctl->mixing_lat0) / dlat);
3393 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->mixing_z0) / dz);
3394 if (atm->time[ip] < t0 || atm->time[ip] > t1
3395 || ixs[ip] < 0 || ixs[ip] >= ctl->mixing_nx
3396 || iys[ip] < 0 || iys[ip] >= ctl->mixing_ny
3397 || izs[ip] < 0 || izs[ip] >= ctl->mixing_nz)
3398 izs[ip] = -1;
3399 }
3400
3401 /* Calculate interparcel mixing... */
3402 const int use_ensemble = (ctl->nens > 0);
3403
3404 const int quantities[] = {
3405 ctl->qnt_m, ctl->qnt_vmr, ctl->qnt_Ch2o, ctl->qnt_Co3,
3406 ctl->qnt_Cco, ctl->qnt_Coh, ctl->qnt_Ch, ctl->qnt_Cho2,
3407 ctl->qnt_Ch2o2, ctl->qnt_Co1d, ctl->qnt_Co3p, ctl->qnt_Cccl4,
3408 ctl->qnt_Cccl3f, ctl->qnt_Cccl2f2, ctl->qnt_Cn2o,
3409 ctl->qnt_Csf6, ctl->qnt_aoa
3410 };
3411 const int n_qnt = sizeof(quantities) / sizeof(quantities[0]);
3412
3413 for (int i = 0; i < n_qnt; i++)
3414 if (quantities[i] >= 0)
3415 module_mixing_help(ctl, clim, atm, ixs, iys, izs, quantities[i],
3416 use_ensemble);
3417
3418 /* Free... */
3419#ifdef _OPENACC
3420#pragma acc exit data delete(ixs,iys,izs)
3421#endif
3422 free(ixs);
3423 free(iys);
3424 free(izs);
3425}
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:3429
int qnt_Coh
Quantity array index for OH volume mixing ratio (chemistry code).
Definition: mptrac.h:2504
int mixing_nx
Number of longitudes of mixing grid.
Definition: mptrac.h:2896
double mixing_z1
Upper altitude of mixing grid [km].
Definition: mptrac.h:2893
int qnt_Co1d
Quantity array index for O(1D) volume mixing ratio (chemistry code).
Definition: mptrac.h:2516
double mixing_z0
Lower altitude of mixing grid [km].
Definition: mptrac.h:2890
int qnt_Cco
Quantity array index for CO volume mixing ratio (chemistry code).
Definition: mptrac.h:2501
int mixing_ny
Number of latitudes of mixing grid.
Definition: mptrac.h:2905
int qnt_Ch
Quantity array index for H volume mixing ratio (chemistry code).
Definition: mptrac.h:2507
double mixing_lat0
Lower latitude of mixing grid [deg].
Definition: mptrac.h:2908
int qnt_Cho2
Quantity array index for HO2 volume mixing ratio (chemistry code).
Definition: mptrac.h:2510
int mixing_nz
Number of altitudes of mixing grid.
Definition: mptrac.h:2887
double mixing_lon0
Lower longitude of mixing grid [deg].
Definition: mptrac.h:2899
double mixing_lat1
Upper latitude of mixing grid [deg].
Definition: mptrac.h:2911
int qnt_Co3p
Quantity array index for O(3P) volume mixing ratio (chemistry code).
Definition: mptrac.h:2519
int qnt_Ch2o2
Quantity array index for H2O2 volume mixing ratio (chemistry code).
Definition: mptrac.h:2513
double mixing_lon1
Upper longitude of mixing grid [deg].
Definition: mptrac.h:2902
Here is the call graph for this function:

◆ module_mixing_help()

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

Perform subgrid-scale interparcel mixing of a given quantity.

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

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

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

Definition at line 3429 of file mptrac.c.

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

◆ module_oh_chem()

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

Perform hydroxyl chemistry calculations for atmospheric particles.

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

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

Definition at line 3531 of file mptrac.c.

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

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

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

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

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

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

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

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

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

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

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

3932 {
3933
3934 /* Set timer... */
3935 SELECT_TIMER("MODULE_TIMESTEPS", "PHYSICS", NVTX_GPU);
3936
3937 const double latmin = gsl_stats_min(met0->lat, 1, (size_t) met0->ny),
3938 latmax = gsl_stats_max(met0->lat, 1, (size_t) met0->ny);
3939
3940 const int local =
3941 (fabs(met0->lon[met0->nx - 1] - met0->lon[0] - 360.0) >= 0.01);
3942
3943 /* Loop over particles... */
3944 PARTICLE_LOOP(0, atm->np, 0, "acc data present(ctl,cache,met0,atm)") {
3945
3946 /* Set time step for each air parcel... */
3947 if ((ctl->direction * (atm->time[ip] - ctl->t_start) >= 0
3948 && ctl->direction * (atm->time[ip] - ctl->t_stop) <= 0
3949 && ctl->direction * (atm->time[ip] - t) < 0))
3950 cache->dt[ip] = t - atm->time[ip];
3951 else
3952 cache->dt[ip] = 0.0;
3953
3954 /* Check horizontal boundaries of local meteo data... */
3955 if (local && (atm->lon[ip] <= met0->lon[0]
3956 || atm->lon[ip] >= met0->lon[met0->nx - 1]
3957 || atm->lat[ip] <= latmin || atm->lat[ip] >= latmax))
3958 cache->dt[ip] = 0.0;
3959 }
3960}
int direction
Direction flag (1=forward calculation, -1=backward calculation).
Definition: mptrac.h:2540
double t_stop
Stop time of simulation [s].
Definition: mptrac.h:2546
double t_start
Start time of simulation [s].
Definition: mptrac.h:2543

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

3966 {
3967
3968 /* Set timer... */
3969 SELECT_TIMER("MODULE_TIMESTEPS_INIT", "PHYSICS", NVTX_GPU);
3970
3971 /* Set start time... */
3972 if (ctl->direction == 1) {
3973 ctl->t_start = gsl_stats_min(atm->time, 1, (size_t) atm->np);
3974 if (ctl->t_stop > 1e99)
3975 ctl->t_stop = gsl_stats_max(atm->time, 1, (size_t) atm->np);
3976 } else {
3977 ctl->t_start = gsl_stats_max(atm->time, 1, (size_t) atm->np);
3978 if (ctl->t_stop > 1e99)
3979 ctl->t_stop = gsl_stats_min(atm->time, 1, (size_t) atm->np);
3980 }
3981
3982 /* Check time interval... */
3983 if (ctl->direction * (ctl->t_stop - ctl->t_start) <= 0)
3984 ERRMSG("Nothing to do! Check T_STOP and DIRECTION!");
3985
3986 /* Round start time... */
3987 if (ctl->direction == 1)
3988 ctl->t_start = floor(ctl->t_start / ctl->dt_mod) * ctl->dt_mod;
3989 else
3990 ctl->t_start = ceil(ctl->t_start / ctl->dt_mod) * ctl->dt_mod;
3991}

◆ module_tracer_chem()

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

Simulate chemical reactions involving long-lived atmospheric tracers.

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

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

Definition at line 3995 of file mptrac.c.

4001 {
4002
4003 /* Set timer... */
4004 SELECT_TIMER("MODULE_TRACER_CHEM", "PHYSICS", NVTX_GPU);
4005
4006 /* Loop over particles... */
4007 PARTICLE_LOOP(0, atm->np, 1,
4008 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4009
4010 /* Get temperature... */
4011 double t;
4013 INTPOL_3D(t, 1);
4014
4015 /* Get molecular density... */
4016 const double M = MOLEC_DENS(atm->p[ip], t);
4017
4018 /* Get total column ozone... */
4019 double o3c;
4020 INTPOL_2D(o3c, 1);
4021
4022 /* Get solar zenith angle... */
4023 const double sza = sza_calc(atm->time[ip], atm->lon[ip], atm->lat[ip]);
4024
4025 /* Get O(1D) volume mixing ratio... */
4026 const double o1d =
4027 clim_zm(&clim->o1d, atm->time[ip], atm->lat[ip], atm->p[ip]);
4028
4029 /* Reactions for CFC-10... */
4030 if (ctl->qnt_Cccl4 >= 0) {
4031 const double K_o1d = ARRHENIUS(3.30e-10, 0, t) * o1d * M;
4032 const double K_hv = clim_photo(clim->photo.ccl4, &(clim->photo),
4033 atm->p[ip], sza, o3c);
4034 atm->q[ctl->qnt_Cccl4][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4035 }
4036
4037 /* Reactions for CFC-11... */
4038 if (ctl->qnt_Cccl3f >= 0) {
4039 const double K_o1d = ARRHENIUS(2.30e-10, 0, t) * o1d * M;
4040 const double K_hv = clim_photo(clim->photo.ccl3f, &(clim->photo),
4041 atm->p[ip], sza, o3c);
4042 atm->q[ctl->qnt_Cccl3f][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4043 }
4044
4045 /* Reactions for CFC-12... */
4046 if (ctl->qnt_Cccl2f2 >= 0) {
4047 const double K_o1d = ARRHENIUS(1.40e-10, -25, t) * o1d * M;
4048 const double K_hv = clim_photo(clim->photo.ccl2f2, &(clim->photo),
4049 atm->p[ip], sza, o3c);
4050 atm->q[ctl->qnt_Cccl2f2][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4051 }
4052
4053 /* Reactions for N2O... */
4054 if (ctl->qnt_Cn2o >= 0) {
4055 const double K_o1d = ARRHENIUS(1.19e-10, -20, t) * o1d * M;
4056 const double K_hv = clim_photo(clim->photo.n2o, &(clim->photo),
4057 atm->p[ip], sza, o3c);
4058 atm->q[ctl->qnt_Cn2o][ip] *= exp(-cache->dt[ip] * (K_hv + K_o1d));
4059 }
4060 }
4061}
double clim_photo(const double rate[CP][CSZA][CO3], const clim_photo_t *photo, const double p, const double sza, const double o3c)
Calculates the photolysis rate for a given set of atmospheric conditions.
Definition: mptrac.c:149
#define ARRHENIUS(a, b, t)
Calculate the Arrhenius rate constant.
Definition: mptrac.h:438
double ccl2f2[CP][CSZA][CO3]
CCl2F2 photolysis rate [1/s].
Definition: mptrac.h:3332
double ccl3f[CP][CSZA][CO3]
CCl3F photolysis rate [1/s].
Definition: mptrac.h:3329
double n2o[CP][CSZA][CO3]
N2O photolysis rate [1/s].
Definition: mptrac.h:3323
double ccl4[CP][CSZA][CO3]
CCl4 photolysis rate [1/s].
Definition: mptrac.h:3326
clim_photo_t photo
Photolysis rates.
Definition: mptrac.h:3428
Here is the call graph for this function:

◆ module_wet_depo()

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

Perform wet deposition calculations for air parcels.

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

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

Definition at line 4065 of file mptrac.c.

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

◆ mptrac_alloc()

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

Allocates and initializes memory resources for MPTRAC.

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

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

Definition at line 4200 of file mptrac.c.

4206 {
4207
4208 /* Initialize GPU... */
4209#ifdef _OPENACC
4210 SELECT_TIMER("ACC_INIT", "INIT", NVTX_GPU);
4211 int rank = 0;
4212#ifdef MPI
4213 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
4214#endif
4215 if (acc_get_num_devices(acc_device_nvidia) <= 0)
4216 ERRMSG("Not running on a GPU device!");
4217 acc_set_device_num(rank % acc_get_num_devices(acc_device_nvidia),
4218 acc_device_nvidia);
4219 acc_device_t device_type = acc_get_device_type();
4220 acc_init(device_type);
4221#endif
4222
4223 /* Allocate... */
4224 SELECT_TIMER("ALLOC", "MEMORY", NVTX_CPU);
4225 ALLOC(*ctl, ctl_t, 1);
4226 ALLOC(*cache, cache_t, 1);
4227 ALLOC(*clim, clim_t, 1);
4228 ALLOC(*met0, met_t, 1);
4229 ALLOC(*met1, met_t, 1);
4230 ALLOC(*atm, atm_t, 1);
4231
4232 /* Create data region on GPU... */
4233#ifdef _OPENACC
4234 SELECT_TIMER("CREATE_DATA_REGION", "MEMORY", NVTX_GPU);
4235 ctl_t *ctlup = *ctl;
4236 cache_t *cacheup = *cache;
4237 clim_t *climup = *clim;
4238 met_t *met0up = *met0;
4239 met_t *met1up = *met1;
4240 atm_t *atmup = *atm;
4241#pragma acc enter data create(ctlup[:1],cacheup[:1],climup[:1],met0up[:1],met1up[:1],atmup[:1])
4242#endif
4243}
Air parcel data.
Definition: mptrac.h:3242
Cache data structure.
Definition: mptrac.h:3270
Climatological data.
Definition: mptrac.h:3410
Control parameters.
Definition: mptrac.h:2245
Meteo data structure.
Definition: mptrac.h:3469

◆ mptrac_free()

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

Frees memory resources allocated for MPTRAC.

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

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

Definition at line 4247 of file mptrac.c.

4253 {
4254
4255 /* Delete data region on GPU... */
4256#ifdef _OPENACC
4257 SELECT_TIMER("DELETE_DATA_REGION", "MEMORY", NVTX_GPU);
4258#pragma acc exit data delete (ctl,cache,clim,met0,met1,atm)
4259#endif
4260
4261 /* Free... */
4262 SELECT_TIMER("FREE", "MEMORY", NVTX_CPU);
4263 free(atm);
4264 free(ctl);
4265 free(cache);
4266 free(clim);
4267 free(met0);
4268 free(met1);
4269}

◆ mptrac_get_met()

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

Retrieves meteorological data for the specified time.

This function retrieves meteorological data for the given time t and updates the provided pointers to the met0 and met1 structures accordingly. It handles both the initialization and subsequent updates of the meteorological data based on the direction of time integration.

Parameters
ctlPointer to the control structure containing configuration settings.
climPointer to the climate structure.
tThe current time for which meteorological data is to be retrieved.
met0Pointer to the pointer of the first meteorological data structure.
met1Pointer to the pointer of the second meteorological data structure.

The function performs the following steps:

  • Initializes meteorological data on the first call or when the simulation restarts.
  • Reads new meteorological data when advancing forward or backward in time.
  • Swaps pointers to manage double buffering of the meteorological data.
  • Performs caching to optimize subsequent data retrieval.
  • Ensures consistency of the meteorological grids.
Note
This function utilizes GPU acceleration with OpenACC directives if enabled.
Ensure that ctl, clim, met0, and met1 are properly initialized before calling this function.
See also
get_met_help
read_met
SELECT_TIMER
LOG
ERRMSG
WARN
Author
Lars Hoffmann

Definition at line 4273 of file mptrac.c.

4278 {
4279
4280 static int init;
4281
4282 met_t *mets;
4283
4284 char cachefile[LEN], cmd[2 * LEN], filename[LEN];
4285
4286 /* Set timer... */
4287 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4288
4289 /* Init... */
4290 if (t == ctl->t_start || !init) {
4291 init = 1;
4292
4293 /* Read meteo data... */
4294 get_met_help(ctl, t + (ctl->direction == -1 ? -1 : 0), -1,
4295 ctl->metbase, ctl->dt_met, filename);
4296 if (!mptrac_read_met(filename, ctl, clim, *met0))
4297 ERRMSG("Cannot open file!");
4298
4299 get_met_help(ctl, t + (ctl->direction == 1 ? 1 : 0), 1,
4300 ctl->metbase, ctl->dt_met, filename);
4301 if (!mptrac_read_met(filename, ctl, clim, *met1))
4302 ERRMSG("Cannot open file!");
4303
4304 /* Update GPU... */
4305 mptrac_update_device(NULL, NULL, NULL, met0, met1, NULL);
4306 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4307
4308 /* Caching... */
4309 if (ctl->met_cache && t != ctl->t_stop) {
4310 get_met_help(ctl, t + 1.1 * ctl->dt_met * ctl->direction,
4311 ctl->direction, ctl->metbase, ctl->dt_met, cachefile);
4312 sprintf(cmd, "cat %s > /dev/null &", cachefile);
4313 LOG(1, "Caching: %s", cachefile);
4314 if (system(cmd) != 0)
4315 WARN("Caching command failed!");
4316 }
4317 }
4318
4319 /* Read new data for forward trajectories... */
4320 if (t > (*met1)->time) {
4321
4322 /* Pointer swap... */
4323 mets = *met1;
4324 *met1 = *met0;
4325 *met0 = mets;
4326
4327 /* Read new meteo data... */
4328 get_met_help(ctl, t, 1, ctl->metbase, ctl->dt_met, filename);
4329 if (!mptrac_read_met(filename, ctl, clim, *met1))
4330 ERRMSG("Cannot open file!");
4331
4332 /* Update GPU... */
4333 mptrac_update_device(NULL, NULL, NULL, NULL, met1, NULL);
4334 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4335
4336 /* Caching... */
4337 if (ctl->met_cache && t != ctl->t_stop) {
4338 get_met_help(ctl, t + ctl->dt_met, 1, ctl->metbase, ctl->dt_met,
4339 cachefile);
4340 sprintf(cmd, "cat %s > /dev/null &", cachefile);
4341 LOG(1, "Caching: %s", cachefile);
4342 if (system(cmd) != 0)
4343 WARN("Caching command failed!");
4344 }
4345 }
4346
4347 /* Read new data for backward trajectories... */
4348 if (t < (*met0)->time) {
4349
4350 /* Pointer swap... */
4351 mets = *met1;
4352 *met1 = *met0;
4353 *met0 = mets;
4354
4355 /* Read new meteo data... */
4356 get_met_help(ctl, t, -1, ctl->metbase, ctl->dt_met, filename);
4357 if (!mptrac_read_met(filename, ctl, clim, *met0))
4358 ERRMSG("Cannot open file!");
4359
4360 /* Update GPU... */
4361 mptrac_update_device(NULL, NULL, NULL, met0, NULL, NULL);
4362 SELECT_TIMER("GET_MET", "INPUT", NVTX_READ);
4363
4364 /* Caching... */
4365 if (ctl->met_cache && t != ctl->t_stop) {
4366 get_met_help(ctl, t - ctl->dt_met, -1, ctl->metbase, ctl->dt_met,
4367 cachefile);
4368 sprintf(cmd, "cat %s > /dev/null &", cachefile);
4369 LOG(1, "Caching: %s", cachefile);
4370 if (system(cmd) != 0)
4371 WARN("Caching command failed!");
4372 }
4373 }
4374
4375 /* Check that grids are consistent... */
4376 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
4377 if ((*met0)->nx != (*met1)->nx
4378 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
4379 ERRMSG("Meteo grid dimensions do not match!");
4380 for (int ix = 0; ix < (*met0)->nx; ix++)
4381 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
4382 ERRMSG("Meteo grid longitudes do not match!");
4383 for (int iy = 0; iy < (*met0)->ny; iy++)
4384 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
4385 ERRMSG("Meteo grid latitudes do not match!");
4386 for (int ip = 0; ip < (*met0)->np; ip++)
4387 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
4388 ERRMSG("Meteo grid pressure levels do not match!");
4389 }
4390}
int mptrac_read_met(const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met)
Reads meteorological data from a file, supporting multiple formats and MPI broadcasting.
Definition: mptrac.c:5382
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:1006
#define WARN(...)
Print a warning message with contextual information.
Definition: mptrac.h:1958
int met_cache
Preload meteo data into disk cache (0=no, 1=yes).
Definition: mptrac.h:2722
char metbase[LEN]
Basename for meteo data.
Definition: mptrac.h:2556
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 4394 of file mptrac.c.

4399 {
4400
4401 /* Initialize timesteps... */
4402 module_timesteps_init(ctl, atm);
4403
4404 /* Initialize random number generator... */
4405 module_rng_init(ntask);
4406
4407 /* Update GPU memory... */
4408 mptrac_update_device(ctl, cache, clim, NULL, NULL, atm);
4409}
void module_timesteps_init(ctl_t *ctl, const atm_t *atm)
Initialize start time and time interval for time-stepping.
Definition: mptrac.c:3964
void module_rng_init(const int ntask)
Initialize random number generators for parallel tasks.
Definition: mptrac.c:3666
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 4413 of file mptrac.c.

4416 {
4417
4418 int result;
4419
4420 /* Set timer... */
4421 SELECT_TIMER("READ_ATM", "INPUT", NVTX_READ);
4422
4423 /* Init... */
4424 atm->np = 0;
4425
4426 /* Write info... */
4427 LOG(1, "Read atmospheric data: %s", filename);
4428
4429 /* Read ASCII data... */
4430 if (ctl->atm_type == 0)
4431 result = read_atm_asc(filename, ctl, atm);
4432
4433 /* Read binary data... */
4434 else if (ctl->atm_type == 1)
4435 result = read_atm_bin(filename, ctl, atm);
4436
4437 /* Read netCDF data... */
4438 else if (ctl->atm_type == 2)
4439 result = read_atm_nc(filename, ctl, atm);
4440
4441 /* Read CLaMS data... */
4442 else if (ctl->atm_type == 3 || ctl->atm_type == 4)
4443 result = read_atm_clams(filename, ctl, atm);
4444
4445 /* Error... */
4446 else
4447 ERRMSG("Atmospheric data type not supported!");
4448
4449 /* Check result... */
4450 if (result != 1)
4451 return 0;
4452
4453 /* Check number of air parcels... */
4454 if (atm->np < 1)
4455 ERRMSG("Can not read any data!");
4456
4457 /* Write info... */
4458 double mini, maxi;
4459 LOG(2, "Number of particles: %d", atm->np);
4460 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
4461 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
4462 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
4463 LOG(2, "Altitude range: %g ... %g km", Z(maxi), Z(mini));
4464 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
4465 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
4466 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
4467 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
4468 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
4469 for (int iq = 0; iq < ctl->nq; iq++) {
4470 char msg[5 * LEN];
4471 sprintf(msg, "Quantity %s range: %s ... %s %s",
4472 ctl->qnt_name[iq], ctl->qnt_format[iq],
4473 ctl->qnt_format[iq], ctl->qnt_unit[iq]);
4474 gsl_stats_minmax(&mini, &maxi, atm->q[iq], 1, (size_t) atm->np);
4475 LOG(2, msg, mini, maxi);
4476 }
4477
4478 /* Return success... */
4479 return 1;
4480}
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:6127
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:6015
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:6071
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:5973
char qnt_format[NQ][LEN]
Quantity output format.
Definition: mptrac.h:2264
int atm_type
Type of atmospheric data files (0=ASCII, 1=binary, 2=netCDF, 3=CLaMS_traj, 4=CLaMS_pos).
Definition: mptrac.h:3024
char qnt_unit[NQ][LEN]
Quantity units.
Definition: mptrac.h:2261
char qnt_name[NQ][LEN]
Quantity names.
Definition: mptrac.h:2255
Here is the call graph for this function:

◆ mptrac_read_clim()

void mptrac_read_clim ( const ctl_t ctl,
clim_t clim 
)

Reads various climatological data and populates the given climatology structure.

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

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

This function performs the following steps:

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

The function utilizes several helper functions:

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

Definition at line 4484 of file mptrac.c.

4486 {
4487
4488 /* Set timer... */
4489 SELECT_TIMER("READ_CLIM", "INPUT", NVTX_READ);
4490
4491 /* Init tropopause climatology... */
4492 clim_tropo_init(clim);
4493
4494 /* Read photolysis rates... */
4495 if (ctl->clim_photo[0] != '-')
4496 read_clim_photo(ctl->clim_photo, &clim->photo);
4497
4498 /* Read HNO3 climatology... */
4499 if (ctl->clim_hno3_filename[0] != '-')
4500 read_clim_zm(ctl->clim_hno3_filename, "HNO3", &clim->hno3);
4501
4502 /* Read OH climatology... */
4503 if (ctl->clim_oh_filename[0] != '-') {
4504 read_clim_zm(ctl->clim_oh_filename, "OH", &clim->oh);
4505 if (ctl->oh_chem_beta > 0)
4506 clim_oh_diurnal_correction(ctl, clim);
4507 }
4508
4509 /* Read H2O2 climatology... */
4510 if (ctl->clim_h2o2_filename[0] != '-')
4511 read_clim_zm(ctl->clim_h2o2_filename, "H2O2", &clim->h2o2);
4512
4513 /* Read HO2 climatology... */
4514 if (ctl->clim_ho2_filename[0] != '-')
4515 read_clim_zm(ctl->clim_ho2_filename, "HO2", &clim->ho2);
4516
4517 /* Read O(1D) climatology... */
4518 if (ctl->clim_o1d_filename[0] != '-')
4519 read_clim_zm(ctl->clim_o1d_filename, "O1D", &clim->o1d);
4520
4521 /* Read CFC-10 time series... */
4522 if (ctl->clim_ccl4_timeseries[0] != '-')
4524
4525 /* Read CFC-11 time series... */
4526 if (ctl->clim_ccl3f_timeseries[0] != '-')
4528
4529 /* Read CFC-12 time series... */
4530 if (ctl->clim_ccl2f2_timeseries[0] != '-')
4532
4533 /* Read N2O time series... */
4534 if (ctl->clim_n2o_timeseries[0] != '-')
4535 read_clim_ts(ctl->clim_n2o_timeseries, &clim->n2o);
4536
4537 /* Read SF6 time series... */
4538 if (ctl->clim_sf6_timeseries[0] != '-')
4539 read_clim_ts(ctl->clim_sf6_timeseries, &clim->sf6);
4540}
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:6160
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:6279
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:6333
void clim_tropo_init(clim_t *clim)
Initializes the tropopause data in the climatology structure.
Definition: mptrac.c:228
void clim_oh_diurnal_correction(const ctl_t *ctl, clim_t *clim)
Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data.
Definition: mptrac.c:116
char clim_ho2_filename[LEN]
Filename of HO2 climatology.
Definition: mptrac.h:2854
char clim_o1d_filename[LEN]
Filename of O(1D) climatology.
Definition: mptrac.h:2857
char clim_photo[LEN]
Filename of photolysis rates climatology.
Definition: mptrac.h:2842
char clim_h2o2_filename[LEN]
Filename of H2O2 climatology.
Definition: mptrac.h:2851
char clim_oh_filename[LEN]
Filename of OH climatology.
Definition: mptrac.h:2848
char clim_hno3_filename[LEN]
Filename of HNO3 climatology.
Definition: mptrac.h:2845
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 4544 of file mptrac.c.

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

◆ mptrac_read_met()

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

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

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

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

Definition at line 5382 of file mptrac.c.

5386 {
5387
5388 /* Write info... */
5389 LOG(1, "Read meteo data: %s", filename);
5390
5391 /* Set rank... */
5392 int rank = 0;
5393#ifdef MPI
5394 if (ctl->met_mpi_share)
5395 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5396#endif
5397
5398 /* Check rank... */
5399 if (!ctl->met_mpi_share || rank == 0) {
5400
5401 /* Read netCDF data... */
5402 if (ctl->met_type == 0) {
5403 if (read_met_nc(filename, ctl, met) != 1)
5404 return 0;
5405 }
5406
5407 /* Read binary data... */
5408 else if (ctl->met_type >= 1 && ctl->met_type <= 5) {
5409 if (read_met_bin(filename, ctl, met) != 1)
5410 return 0;
5411 }
5412#ifdef ECCODES
5413 /* Read grib data... */
5414 else if (ctl->met_type == 6) {
5415 if (read_met_grib(filename, ctl, met) != 1)
5416 return 0;
5417 }
5418#endif
5419
5420 /* Not implemented... */
5421 else
5422 ERRMSG("MET_TYPE not implemented!");
5423
5424 /* Preprocessing for netCDF and grib files... */
5425 if (ctl->met_type == 0 || ctl->met_type == 6) {
5426
5427 /* Extrapolate data for lower boundary... */
5429
5430 /* Fix polar winds... */
5432
5433 /* Create periodic boundary conditions... */
5434 read_met_periodic(met);
5435
5436 /* Downsampling... */
5437 read_met_sample(ctl, met);
5438
5439 /* Calculate geopotential heights... */
5440 read_met_geopot(ctl, met);
5441
5442 /* Calculate potential vorticity... */
5443 read_met_pv(met);
5444
5445 /* Calculate boundary layer data... */
5446 read_met_pbl(ctl, met);
5447
5448 /* Calculate tropopause data... */
5449 read_met_tropo(ctl, clim, met);
5450
5451 /* Calculate cloud properties... */
5452 read_met_cloud(met);
5453
5454 /* Calculate convective available potential energy... */
5455 read_met_cape(ctl, clim, met);
5456
5457 /* Calculate total column ozone... */
5458 read_met_ozone(met);
5459
5460 /* Detrending... */
5461 read_met_detrend(ctl, met);
5462
5463 /* Check meteo data and smooth zeta profiles ... */
5464 read_met_monotonize(ctl, met);
5465 }
5466 }
5467
5468 /* Broadcast data via MPI... */
5469#ifdef MPI
5470 if (ctl->met_mpi_share) {
5471
5472 /* Set timer... */
5473 SELECT_TIMER("READ_MET_MPI_BCAST", "COMM", NVTX_SEND);
5474 LOG(2, "Broadcast data on rank %d...", rank);
5475
5476 /* Broadcast... */
5477 broadcast_large_data(met, sizeof(met_t));
5478 }
5479#endif
5480
5481 /* Return success... */
5482 return 1;
5483}
void read_met_geopot(const ctl_t *ctl, met_t *met)
Calculates geopotential heights from meteorological data.
Definition: mptrac.c:7052
void read_met_extrapolate(met_t *met)
Extrapolates meteorological data.
Definition: mptrac.c:7012
void read_met_sample(const ctl_t *ctl, met_t *met)
Downsamples meteorological data based on specified parameters.
Definition: mptrac.c:8950
void read_met_cloud(met_t *met)
Calculates cloud-related variables for each grid point.
Definition: mptrac.c:6851
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:8558
void read_met_detrend(const ctl_t *ctl, met_t *met)
Detrends meteorological data.
Definition: mptrac.c:6908
void read_met_monotonize(const ctl_t *ctl, met_t *met)
Makes zeta and pressure profiles monotone.
Definition: mptrac.c:7654
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
Definition: mptrac.c:8695
void read_met_ozone(met_t *met)
Calculates the total column ozone from meteorological ozone data.
Definition: mptrac.c:8921
void read_met_pv(met_t *met)
Calculates potential vorticity (PV) from meteorological data.
Definition: mptrac.c:8815
int read_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a NetCDF file and processes it.
Definition: mptrac.c:7739
int read_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a binary file.
Definition: mptrac.c:6473
void read_met_polar_winds(met_t *met)
Applies a fix for polar winds in meteorological data.
Definition: mptrac.c:8756
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:6736
int read_met_grib(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a grib file and processes it.
void broadcast_large_data(void *data, size_t N)
Broadcasts large data across all processes in an MPI communicator.
Here is the call graph for this function:

◆ mptrac_run_timestep()

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

Executes a single timestep of the MPTRAC model simulation.

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

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

Definition at line 5487 of file mptrac.c.

5494 {
5495
5496 /* Initialize modules... */
5497 if (t == ctl->t_start) {
5498
5499 /* Initialize isosurface data... */
5500 if (ctl->isosurf >= 1 && ctl->isosurf <= 4)
5501 module_isosurf_init(ctl, cache, *met0, *met1, atm);
5502
5503 /* Initialize advection... */
5504 module_advect_init(ctl, cache, *met0, *met1, atm);
5505
5506 /* Initialize chemistry... */
5507 module_chem_init(ctl, cache, clim, *met0, *met1, atm);
5508 }
5509
5510 /* Set time steps of air parcels... */
5511 module_timesteps(ctl, cache, *met0, atm, t);
5512
5513 /* Sort particles... */
5514 if (ctl->sort_dt > 0 && fmod(t, ctl->sort_dt) == 0)
5515 module_sort(ctl, *met0, atm);
5516
5517 /* Check positions (initial)... */
5518 module_position(cache, *met0, *met1, atm);
5519
5520 /* Advection... */
5521 if (ctl->advect > 0)
5522 module_advect(ctl, cache, *met0, *met1, atm);
5523
5524 /* Turbulent diffusion... */
5525 if (ctl->diffusion == 1
5526 && (ctl->turb_dx_pbl > 0 || ctl->turb_dz_pbl > 0
5527 || ctl->turb_dx_trop > 0 || ctl->turb_dz_trop > 0
5528 || ctl->turb_dx_strat > 0 || ctl->turb_dz_strat > 0))
5529 module_diff_turb(ctl, cache, clim, *met0, *met1, atm);
5530
5531 /* Mesoscale diffusion... */
5532 if (ctl->diffusion == 1 && (ctl->turb_mesox > 0 || ctl->turb_mesoz > 0))
5533 module_diff_meso(ctl, cache, *met0, *met1, atm);
5534
5535 /* Diffusion... */
5536 if (ctl->diffusion == 2)
5537 module_diff_pbl(ctl, cache, *met0, *met1, atm);
5538
5539 /* Convection... */
5540 if ((ctl->conv_mix_pbl || ctl->conv_cape >= 0)
5541 && (ctl->conv_dt <= 0 || fmod(t, ctl->conv_dt) == 0))
5542 module_convection(ctl, cache, *met0, *met1, atm);
5543
5544 /* Sedimentation... */
5545 if (ctl->qnt_rp >= 0 && ctl->qnt_rhop >= 0)
5546 module_sedi(ctl, cache, *met0, *met1, atm);
5547
5548 /* Isosurface... */
5549 if (ctl->isosurf >= 1 && ctl->isosurf <= 4)
5550 module_isosurf(ctl, cache, *met0, *met1, atm);
5551
5552 /* Check positions (final)... */
5553 module_position(cache, *met0, *met1, atm);
5554
5555 /* Interpolate meteo data... */
5556 if (ctl->met_dt_out > 0
5557 && (ctl->met_dt_out < ctl->dt_mod || fmod(t, ctl->met_dt_out) == 0))
5558 module_meteo(ctl, cache, clim, *met0, *met1, atm);
5559
5560 /* Check boundary conditions (initial)... */
5561 if ((ctl->bound_lat0 < ctl->bound_lat1)
5562 && (ctl->bound_p0 > ctl->bound_p1))
5563 module_bound_cond(ctl, cache, clim, *met0, *met1, atm);
5564
5565 /* Initialize quantity of total loss rate... */
5566 if (ctl->qnt_loss_rate >= 0) {
5567 PARTICLE_LOOP(0, atm->np, 1, "acc data present(ctl,atm)") {
5568 atm->q[ctl->qnt_loss_rate][ip] = 0;
5569 }
5570 }
5571
5572 /* Decay of particle mass... */
5573 if (ctl->tdec_trop > 0 && ctl->tdec_strat > 0)
5574 module_decay(ctl, cache, clim, atm);
5575
5576 /* Interparcel mixing... */
5577 if (ctl->mixing_trop >= 0 && ctl->mixing_strat >= 0
5578 && (ctl->mixing_dt <= 0 || fmod(t, ctl->mixing_dt) == 0))
5579 module_mixing(ctl, clim, atm, t);
5580
5581 /* Calculate the tracer vmr in the chemistry grid... */
5582 if (ctl->oh_chem_reaction != 0 || ctl->h2o2_chem_reaction != 0
5583 || (ctl->kpp_chem && fmod(t, ctl->dt_kpp) == 0))
5584 module_chem_grid(ctl, *met0, *met1, atm, t);
5585
5586 /* OH chemistry... */
5587 if (ctl->oh_chem_reaction != 0)
5588 module_oh_chem(ctl, cache, clim, *met0, *met1, atm);
5589
5590 /* H2O2 chemistry (for SO2 aqueous phase oxidation)... */
5591 if (ctl->h2o2_chem_reaction != 0)
5592 module_h2o2_chem(ctl, cache, clim, *met0, *met1, atm);
5593
5594 /* First-order tracer chemistry... */
5595 if (ctl->tracer_chem)
5596 module_tracer_chem(ctl, cache, clim, *met0, *met1, atm);
5597
5598 /* KPP chemistry... */
5599 if (ctl->kpp_chem && fmod(t, ctl->dt_kpp) == 0) {
5600#ifdef KPP
5601 module_kpp_chem(ctl, cache, clim, *met0, *met1, atm);
5602#else
5603 ERRMSG("Code was compiled without KPP!");
5604#endif
5605 }
5606
5607 /* Wet deposition... */
5608 if ((ctl->wet_depo_ic_a > 0 || ctl->wet_depo_ic_h[0] > 0)
5609 && (ctl->wet_depo_bc_a > 0 || ctl->wet_depo_bc_h[0] > 0))
5610 module_wet_depo(ctl, cache, *met0, *met1, atm);
5611
5612 /* Dry deposition... */
5613 if (ctl->dry_depo_vdep > 0)
5614 module_dry_depo(ctl, cache, *met0, *met1, atm);
5615
5616 /* Check boundary conditions (final)... */
5617 if ((ctl->bound_lat0 < ctl->bound_lat1)
5618 && (ctl->bound_p0 > ctl->bound_p1))
5619 module_bound_cond(ctl, cache, clim, *met0, *met1, atm);
5620}
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:2088
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:3927
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:3254
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:2641
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:2526
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:3358
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:3079
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:4065
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:2364
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:3802
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:2568
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:2268
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:2241
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:3615
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:2680
void module_sort(const ctl_t *ctl, met_t *met0, atm_t *atm)
Sort particles according to box index.
Definition: mptrac.c:3831
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:2882
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:3995
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:2997
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:2757
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:3149
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:3531
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:2934
void module_kpp_chem(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
KPP chemistry module.
Here is the call graph for this function:

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

5630 {
5631
5632 /* Update GPU... */
5633 if (ctl != NULL) {
5634#ifdef _OPENACC
5635 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5636#pragma acc update device(ctl[:1])
5637#endif
5638 }
5639
5640 if (cache != NULL) {
5641#ifdef _OPENACC
5642 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5643#pragma acc update device(cache[:1])
5644#endif
5645 }
5646
5647 if (clim != NULL) {
5648#ifdef _OPENACC
5649 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5650#pragma acc update device(clim[:1])
5651#endif
5652 }
5653
5654 if (met0 != NULL) {
5655#ifdef _OPENACC
5656 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5657 met_t *met0up = *met0;
5658#pragma acc update device(met0up[:1])
5659#endif
5660 }
5661
5662 if (met1 != NULL) {
5663#ifdef _OPENACC
5664 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5665 met_t *met1up = *met1;
5666#pragma acc update device(met1up[:1])
5667#endif
5668 }
5669
5670 if (atm != NULL) {
5671#ifdef _OPENACC
5672 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5673#pragma acc update device(atm[:1])
5674#endif
5675 }
5676}

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

5686 {
5687
5688 /* Update GPU... */
5689 if (ctl != NULL) {
5690#ifdef _OPENACC
5691 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5692#pragma acc update host(ctl[:1])
5693#endif
5694 }
5695
5696 if (cache != NULL) {
5697#ifdef _OPENACC
5698 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5699#pragma acc update host(cache[:1])
5700#endif
5701 }
5702
5703 if (clim != NULL) {
5704#ifdef _OPENACC
5705 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5706#pragma acc update host(clim[:1])
5707#endif
5708 }
5709
5710 if (met0 != NULL) {
5711#ifdef _OPENACC
5712 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5713 met_t *met0up = *met0;
5714#pragma acc update host(met0up[:1])
5715#endif
5716 }
5717
5718 if (met1 != NULL) {
5719#ifdef _OPENACC
5720 SELECT_TIMER("UPDATE_DEVICE", "MEMORY", NVTX_H2D);
5721 met_t *met1up = *met1;
5722#pragma acc update host(met1up[:1])
5723#endif
5724 }
5725
5726 if (atm != NULL) {
5727#ifdef _OPENACC
5728 SELECT_TIMER("UPDATE_HOST", "MEMORY", NVTX_H2D);
5729#pragma acc update host(atm[:1])
5730#endif
5731 }
5732}

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

5740 {
5741
5742 /* Set timer... */
5743 SELECT_TIMER("WRITE_ATM", "OUTPUT", NVTX_WRITE);
5744
5745 /* Write info... */
5746 LOG(1, "Write atmospheric data: %s", filename);
5747
5748 /* Write ASCII data... */
5749 if (ctl->atm_type_out == 0)
5750 write_atm_asc(filename, ctl, atm, t);
5751
5752 /* Write binary data... */
5753 else if (ctl->atm_type_out == 1)
5754 write_atm_bin(filename, ctl, atm);
5755
5756 /* Write netCDF data... */
5757 else if (ctl->atm_type_out == 2)
5758 write_atm_nc(filename, ctl, atm);
5759
5760 /* Write CLaMS trajectory data... */
5761 else if (ctl->atm_type_out == 3)
5762 write_atm_clams_traj(filename, ctl, atm, t);
5763
5764 /* Write CLaMS pos data... */
5765 else if (ctl->atm_type_out == 4)
5766 write_atm_clams(filename, ctl, atm);
5767
5768 /* Error... */
5769 else
5770 ERRMSG("Atmospheric data type not supported!");
5771
5772 /* Write info... */
5773 double mini, maxi;
5774 LOG(2, "Number of particles: %d", atm->np);
5775 gsl_stats_minmax(&mini, &maxi, atm->time, 1, (size_t) atm->np);
5776 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
5777 gsl_stats_minmax(&mini, &maxi, atm->p, 1, (size_t) atm->np);
5778 LOG(2, "Altitude range: %g ... %g km", Z(maxi), Z(mini));
5779 LOG(2, "Pressure range: %g ... %g hPa", maxi, mini);
5780 gsl_stats_minmax(&mini, &maxi, atm->lon, 1, (size_t) atm->np);
5781 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
5782 gsl_stats_minmax(&mini, &maxi, atm->lat, 1, (size_t) atm->np);
5783 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
5784 for (int iq = 0; iq < ctl->nq; iq++) {
5785 char msg[5 * LEN];
5786 sprintf(msg, "Quantity %s range: %s ... %s %s",
5787 ctl->qnt_name[iq], ctl->qnt_format[iq],
5788 ctl->qnt_format[iq], ctl->qnt_unit[iq]);
5789 gsl_stats_minmax(&mini, &maxi, atm->q[iq], 1, (size_t) atm->np);
5790 LOG(2, msg, mini, maxi);
5791 }
5792}
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:9951
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:9766
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:9898
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:9848
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:10109
Here is the call graph for this function:

◆ mptrac_write_met()

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

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

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

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

Definition at line 5796 of file mptrac.c.

5799 {
5800
5801 /* Set timer... */
5802 SELECT_TIMER("WRITE_MET", "OUTPUT", NVTX_WRITE);
5803
5804 /* Write info... */
5805 LOG(1, "Write meteo data: %s", filename);
5806
5807 /* Check compression flags... */
5808#ifndef ZFP
5809 if (ctl->met_type == 3)
5810 ERRMSG("MPTRAC was compiled without zfp compression!");
5811#endif
5812#ifndef ZSTD
5813 if (ctl->met_type == 4)
5814 ERRMSG("MPTRAC was compiled without zstd compression!");
5815#endif
5816#ifndef CMS
5817 if (ctl->met_type == 5)
5818 ERRMSG("MPTRAC was compiled without cmultiscale compression!");
5819#endif
5820
5821 /* Write netCDF data... */
5822 if (ctl->met_type == 0)
5823 write_met_nc(filename, ctl, met);
5824
5825 /* Write binary data... */
5826 else if (ctl->met_type >= 1 && ctl->met_type <= 5)
5827 write_met_bin(filename, ctl, met);
5828
5829 /* Not implemented... */
5830 else
5831 ERRMSG("MET_TYPE not implemented!");
5832}
void write_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a NetCDF file.
Definition: mptrac.c:11162
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:10956
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 5836 of file mptrac.c.

5842 {
5843
5844 char ext[10], filename[2 * LEN];
5845
5846 double r;
5847
5848 int year, mon, day, hour, min, sec;
5849
5850 /* Get time... */
5851 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
5852
5853 /* Update host... */
5854 if ((ctl->atm_basename[0] != '-' && fmod(t, ctl->atm_dt_out) == 0)
5855 || (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0)
5856 || (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0)
5857 || ctl->csi_basename[0] != '-' || ctl->prof_basename[0] != '-'
5858 || ctl->sample_basename[0] != '-' || ctl->stat_basename[0] != '-'
5859 || (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0))
5860 mptrac_update_host(NULL, NULL, NULL, NULL, NULL, atm);
5861
5862 /* Write atmospheric data... */
5863 if (ctl->atm_basename[0] != '-' &&
5864 (fmod(t, ctl->atm_dt_out) == 0 || t == ctl->t_stop)) {
5865 if (ctl->atm_type_out == 0)
5866 sprintf(ext, "tab");
5867 else if (ctl->atm_type_out == 1)
5868 sprintf(ext, "bin");
5869 else if (ctl->atm_type_out == 2)
5870 sprintf(ext, "nc");
5871 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
5872 dirname, ctl->atm_basename, year, mon, day, hour, min, ext);
5873 mptrac_write_atm(filename, ctl, atm, t);
5874 }
5875
5876 /* Write gridded data... */
5877 if (ctl->grid_basename[0] != '-' && fmod(t, ctl->grid_dt_out) == 0) {
5878 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
5879 dirname, ctl->grid_basename, year, mon, day, hour, min,
5880 ctl->grid_type == 0 ? "tab" : "nc");
5881 write_grid(filename, ctl, met0, met1, atm, t);
5882 }
5883
5884 /* Write CSI data... */
5885 if (ctl->csi_basename[0] != '-') {
5886 sprintf(filename, "%s/%s.tab", dirname, ctl->csi_basename);
5887 write_csi(filename, ctl, atm, t);
5888 }
5889
5890 /* Write ensemble data... */
5891 if (ctl->ens_basename[0] != '-' && fmod(t, ctl->ens_dt_out) == 0) {
5892 sprintf(filename, "%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
5893 dirname, ctl->ens_basename, year, mon, day, hour, min);
5894 write_ens(filename, ctl, atm, t);
5895 }
5896
5897 /* Write profile data... */
5898 if (ctl->prof_basename[0] != '-') {
5899 sprintf(filename, "%s/%s.tab", dirname, ctl->prof_basename);
5900 write_prof(filename, ctl, met0, met1, atm, t);
5901 }
5902
5903 /* Write sample data... */
5904 if (ctl->sample_basename[0] != '-') {
5905 sprintf(filename, "%s/%s.tab", dirname, ctl->sample_basename);
5906 write_sample(filename, ctl, met0, met1, atm, t);
5907 }
5908
5909 /* Write station data... */
5910 if (ctl->stat_basename[0] != '-') {
5911 sprintf(filename, "%s/%s.tab", dirname, ctl->stat_basename);
5912 write_station(filename, ctl, atm, t);
5913 }
5914
5915 /* Write VTK data... */
5916 if (ctl->vtk_basename[0] != '-' && fmod(t, ctl->vtk_dt_out) == 0) {
5917 static int nvtk;
5918 if (t == ctl->t_start)
5919 nvtk = 0;
5920 sprintf(filename, "%s/%s_%05d.vtk", dirname, ctl->vtk_basename, ++nvtk);
5921 write_vtk(filename, ctl, atm, t);
5922 }
5923}
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:5736
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:10434
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:11385
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:5680
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:11774
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:11860
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:11612
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:10531
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:10158
Here is the call graph for this function:

◆ nat_temperature()

double nat_temperature ( const double  p,
const double  h2o,
const double  hno3 
)

Calculates the nitric acid trihydrate (NAT) temperature.

This function computes the temperature at which nitric acid trihydrate (NAT) can form given the partial pressures of water vapor and nitric acid in the atmosphere.

Parameters
pThe total atmospheric pressure (in hPa).
h2oThe volume mixing ratio of water vapor (H2O).
hno3The volume mixing ratio of nitric acid (HNO3).
Returns
The NAT temperature (in Kelvin).

This function follows these steps:

  • Ensures the water vapor volume mixing ratio is above a minimum threshold.
  • Converts the volume mixing ratios of H2O and HNO3 to partial pressures.
  • Uses these partial pressures to compute coefficients for the quadratic equation that determines the NAT temperature.
  • Solves the quadratic equation to find the NAT temperature.

The calculations are based on empirical relationships involving logarithms of the partial pressures of H2O and HNO3.

Note
The constants and formulae used are specific to the context of atmospheric chemistry and the formation of NAT.
Author
Lars Hoffmann

Definition at line 5927 of file mptrac.c.

5930 {
5931
5932 /* Check water vapor volume mixing ratio... */
5933 const double h2o_help = MAX(h2o, 0.1e-6);
5934
5935 /* Calculate T_NAT... */
5936 const double p_hno3 = hno3 * p / 1.333224;
5937 const double p_h2o = h2o_help * p / 1.333224;
5938 const double a = 0.009179 - 0.00088 * log10(p_h2o);
5939 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
5940 const double c = -11397.0 / a;
5941 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
5942 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
5943 if (x2 > 0)
5944 tnat = x2;
5945
5946 return tnat;
5947}

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

5956 {
5957
5958 /* Get pressure range... */
5959 const double p1 = pbl - ctl->conv_pbl_trans * (ps - pbl);
5960 const double p0 = pbl;
5961
5962 /* Get weighting factor... */
5963 if (atm->p[ip] > p0)
5964 return 1;
5965 else if (atm->p[ip] < p1)
5966 return 0;
5967 else
5968 return LIN(p0, 1.0, p1, 0.0, atm->p[ip]);
5969}

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

5976 {
5977
5978 /* Open file... */
5979 FILE *in;
5980 if (!(in = fopen(filename, "r"))) {
5981 WARN("Cannot open file!");
5982 return 0;
5983 }
5984
5985 /* Read line... */
5986 char line[LEN];
5987 while (fgets(line, LEN, in)) {
5988
5989 /* Read data... */
5990 char *tok;
5991 TOK(line, tok, "%lg", atm->time[atm->np]);
5992 TOK(NULL, tok, "%lg", atm->p[atm->np]);
5993 TOK(NULL, tok, "%lg", atm->lon[atm->np]);
5994 TOK(NULL, tok, "%lg", atm->lat[atm->np]);
5995 for (int iq = 0; iq < ctl->nq; iq++)
5996 TOK(NULL, tok, "%lg", atm->q[iq][atm->np]);
5997
5998 /* Convert altitude to pressure... */
5999 atm->p[atm->np] = P(atm->p[atm->np]);
6000
6001 /* Increment data point counter... */
6002 if ((++atm->np) > NP)
6003 ERRMSG("Too many data points!");
6004 }
6005
6006 /* Close file... */
6007 fclose(in);
6008
6009 /* Return success... */
6010 return 1;
6011}
#define TOK(line, tok, format, var)
Get string tokens.
Definition: mptrac.h:1781

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

6018 {
6019
6020 /* Open file... */
6021 FILE *in;
6022 if (!(in = fopen(filename, "r")))
6023 return 0;
6024
6025 /* Check version of binary data... */
6026 int version;
6027 FREAD(&version, int,
6028 1,
6029 in);
6030 if (version != 100)
6031 ERRMSG("Wrong version of binary data!");
6032
6033 /* Read data... */
6034 FREAD(&atm->np, int,
6035 1,
6036 in);
6037 FREAD(atm->time, double,
6038 (size_t) atm->np,
6039 in);
6040 FREAD(atm->p, double,
6041 (size_t) atm->np,
6042 in);
6043 FREAD(atm->lon, double,
6044 (size_t) atm->np,
6045 in);
6046 FREAD(atm->lat, double,
6047 (size_t) atm->np,
6048 in);
6049 for (int iq = 0; iq < ctl->nq; iq++)
6050 FREAD(atm->q[iq], double,
6051 (size_t) atm->np,
6052 in);
6053
6054 /* Read final flag... */
6055 int final;
6056 FREAD(&final, int,
6057 1,
6058 in);
6059 if (final != 999)
6060 ERRMSG("Error while reading binary data!");
6061
6062 /* Close file... */
6063 fclose(in);
6064
6065 /* Return success... */
6066 return 1;
6067}

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

6074 {
6075
6076 int ncid, varid;
6077
6078 /* Open file... */
6079 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6080 return 0;
6081
6082 /* Get dimensions... */
6083 NC_INQ_DIM("NPARTS", &atm->np, 1, NP);
6084
6085 /* Get time... */
6086 if (nc_inq_varid(ncid, "TIME_INIT", &varid) == NC_NOERR) {
6087 NC(nc_get_var_double(ncid, varid, atm->time));
6088 } else {
6089 WARN("TIME_INIT not found use time instead!");
6090 double time_init;
6091 NC_GET_DOUBLE("time", &time_init, 1);
6092 for (int ip = 0; ip < atm->np; ip++) {
6093 atm->time[ip] = time_init;
6094 }
6095 }
6096
6097 /* Read zeta coordinate, pressure is optional... */
6098 if (ctl->advect_vert_coord == 1) {
6099 NC_GET_DOUBLE("ZETA", atm->q[ctl->qnt_zeta], 1);
6100 NC_GET_DOUBLE("PRESS", atm->p, 0);
6101 }
6102
6103 /* Read pressure, zeta coordinate is optional... */
6104 else {
6105 if (nc_inq_varid(ncid, "PRESS_INIT", &varid) == NC_NOERR) {
6106 NC(nc_get_var_double(ncid, varid, atm->p));
6107 } else {
6108 WARN("PRESS_INIT not found use PRESS instead!");
6109 nc_inq_varid(ncid, "PRESS", &varid);
6110 NC(nc_get_var_double(ncid, varid, atm->p));
6111 }
6112 }
6113
6114 /* Read longitude and latitude... */
6115 NC_GET_DOUBLE("LON", atm->lon, 1);
6116 NC_GET_DOUBLE("LAT", atm->lat, 1);
6117
6118 /* Close file... */
6119 NC(nc_close(ncid));
6120
6121 /* Return success... */
6122 return 1;
6123}
#define NC(cmd)
Execute a NetCDF command and check for errors.
Definition: mptrac.h:1103
#define NC_INQ_DIM(dimname, ptr, min, max)
Inquire the length of a dimension in a NetCDF file.
Definition: mptrac.h:1190
#define NC_GET_DOUBLE(varname, ptr, force)
Retrieve a double-precision variable from a NetCDF file.
Definition: mptrac.h:1162

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

6130 {
6131
6132 int ncid, varid;
6133
6134 /* Open file... */
6135 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6136 return 0;
6137
6138 /* Get dimensions... */
6139 NC_INQ_DIM("obs", &atm->np, 1, NP);
6140
6141 /* Read geolocations... */
6142 NC_GET_DOUBLE("time", atm->time, 1);
6143 NC_GET_DOUBLE("press", atm->p, 1);
6144 NC_GET_DOUBLE("lon", atm->lon, 1);
6145 NC_GET_DOUBLE("lat", atm->lat, 1);
6146
6147 /* Read variables... */
6148 for (int iq = 0; iq < ctl->nq; iq++)
6149 NC_GET_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
6150
6151 /* Close file... */
6152 NC(nc_close(ncid));
6153
6154 /* Return success... */
6155 return 1;
6156}

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

6162 {
6163
6164 int ncid, varid;
6165
6166 /* Write info... */
6167 LOG(1, "Read photolysis rates: %s", filename);
6168
6169 /* Open netCDF file... */
6170 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
6171 WARN("Photolysis rate data are missing!");
6172 return;
6173 }
6174
6175 /* Read pressure data... */
6176 NC_INQ_DIM("press", &photo->np, 2, CP);
6177 NC_GET_DOUBLE("press", photo->p, 1);
6178 if (photo->p[0] < photo->p[1])
6179 ERRMSG("Pressure data are not descending!");
6180
6181 /* Read total column ozone data... */
6182 NC_INQ_DIM("total_o3col", &photo->no3c, 2, CO3);
6183 NC_GET_DOUBLE("total_o3col", photo->o3c, 1);
6184 if (photo->o3c[0] > photo->o3c[1])
6185 ERRMSG("Total column ozone data are not ascending!");
6186
6187 /* Read solar zenith angle data... */
6188 NC_INQ_DIM("sza", &photo->nsza, 2, CSZA);
6189 NC_GET_DOUBLE("sza", photo->sza, 1);
6190 if (photo->sza[0] > photo->sza[1])
6191 ERRMSG("Solar zenith angle data are not ascending!");
6192
6193 /* Read data... */
6194 read_clim_photo_help(ncid, "J_N2O", photo, photo->n2o);
6195 read_clim_photo_help(ncid, "J_CCl4", photo, photo->ccl4);
6196 read_clim_photo_help(ncid, "J_CFC-11", photo, photo->ccl3f);
6197 read_clim_photo_help(ncid, "J_CFC-12", photo, photo->ccl2f2);
6198 read_clim_photo_help(ncid, "J_O2", photo, photo->o2);
6199 read_clim_photo_help(ncid, "J_O3b", photo, photo->o3_1);
6200 read_clim_photo_help(ncid, "J_O3a", photo, photo->o3_2);
6201 read_clim_photo_help(ncid, "J_H2O2", photo, photo->h2o2);
6202 read_clim_photo_help(ncid, "J_H2O", photo, photo->h2o);
6203
6204 /* Close netCDF file... */
6205 NC(nc_close(ncid));
6206
6207 /* Write info... */
6208 LOG(2, "Number of pressure levels: %d", photo->np);
6209 LOG(2, "Altitude levels: %g, %g ... %g km",
6210 Z(photo->p[0]), Z(photo->p[1]), Z(photo->p[photo->np - 1]));
6211 LOG(2, "Pressure levels: %g, %g ... %g hPa",
6212 photo->p[0], photo->p[1], photo->p[photo->np - 1]);
6213 LOG(2, "Number of solar zenith angles: %d", photo->nsza);
6214 LOG(2, "Solar zenith angles: %g, %g ... %g deg",
6215 RAD2DEG(photo->sza[0]), RAD2DEG(photo->sza[1]),
6216 RAD2DEG(photo->sza[photo->nsza - 1]));
6217 LOG(2, "Number of total column ozone values: %d", photo->no3c);
6218 LOG(2, "Total column ozone: %g, %g ... %g DU",
6219 photo->o3c[0], photo->o3c[1], photo->o3c[photo->no3c - 1]);
6220 LOG(2, "N2O photolysis rate: %g, %g ... %g s**-1",
6221 photo->n2o[0][0][0], photo->n2o[1][0][0],
6222 photo->n2o[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6223 LOG(2, "CCl4 photolysis rate: %g, %g ... %g s**-1",
6224 photo->ccl4[0][0][0], photo->ccl4[1][0][0],
6225 photo->ccl4[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6226 LOG(2, "CFC-11 photolysis rate: %g, %g ... %g s**-1",
6227 photo->ccl3f[0][0][0], photo->ccl3f[1][0][0],
6228 photo->ccl3f[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6229 LOG(2, "CFC-12 photolysis rate: %g, %g ... %g s**-1",
6230 photo->ccl2f2[0][0][0], photo->ccl2f2[1][0][0],
6231 photo->ccl2f2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6232 LOG(2, "O2 photolysis rate: %g, %g ... %g s**-1",
6233 photo->o2[0][0][0], photo->o2[1][0][0],
6234 photo->o2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6235 LOG(2, "O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
6236 photo->o3_1[0][0][0], photo->o3_1[1][0][0],
6237 photo->o3_1[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6238 LOG(2, "O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
6239 photo->o3_2[0][0][0], photo->o3_2[1][0][0],
6240 photo->o3_2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6241 LOG(2, "H2O2 photolysis rate: %g, %g ... %g s**-1",
6242 photo->h2o2[0][0][0], photo->h2o2[1][0][0],
6243 photo->h2o2[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6244 LOG(2, "H2O photolysis rate: %g, %g ... %g s**-1",
6245 photo->h2o[0][0][0], photo->h2o[1][0][0],
6246 photo->h2o[photo->np - 1][photo->nsza - 1][photo->no3c - 1]);
6247}
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:6251
#define CP
Maximum number of pressure levels for climatological data.
Definition: mptrac.h:323
#define CO3
Maximum number of total column ozone data for climatological data.
Definition: mptrac.h:318
#define CSZA
Maximum number of solar zenith angles for climatological data.
Definition: mptrac.h:328
double o3_1[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O1d + O2) [1/s].
Definition: mptrac.h:3338
double o2[CP][CSZA][CO3]
O2 photolysis rate [1/s].
Definition: mptrac.h:3335
double h2o2[CP][CSZA][CO3]
H2O2 photolysis rate [1/s].
Definition: mptrac.h:3344
double h2o[CP][CSZA][CO3]
H2O photolysis rate [1/s].
Definition: mptrac.h:3347
double o3_2[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O3p + O2) [1/s].
Definition: mptrac.h:3341
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 6251 of file mptrac.c.

6255 {
6256
6257 /* Allocate... */
6258 double *help;
6259 ALLOC(help, double,
6260 photo->np * photo->nsza * photo->no3c);
6261
6262 /* Read varible... */
6263 int varid;
6264 NC_GET_DOUBLE(varname, help, 1);
6265
6266 /* Copy data... */
6267 for (int ip = 0; ip < photo->np; ip++)
6268 for (int is = 0; is < photo->nsza; is++)
6269 for (int io = 0; io < photo->no3c; io++)
6270 var[ip][is][io] =
6271 help[ARRAY_3D(ip, is, photo->nsza, io, photo->no3c)];
6272
6273 /* Free... */
6274 free(help);
6275}

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

6281 {
6282
6283 /* Write info... */
6284 LOG(1, "Read climatological time series: %s", filename);
6285
6286 /* Open file... */
6287 FILE *in;
6288 if (!(in = fopen(filename, "r"))) {
6289 WARN("Cannot open file!");
6290 return 0;
6291 }
6292
6293 /* Read data... */
6294 char line[LEN];
6295 int nh = 0;
6296 while (fgets(line, LEN, in))
6297 if (sscanf(line, "%lg %lg", &ts->time[nh], &ts->vmr[nh]) == 2) {
6298
6299 /* Convert years to seconds... */
6300 ts->time[nh] = (ts->time[nh] - 2000.0) * 365.25 * 86400.;
6301
6302 /* Check data... */
6303 if (nh > 0 && ts->time[nh] <= ts->time[nh - 1])
6304 ERRMSG("Time series must be ascending!");
6305
6306 /* Count time steps... */
6307 if ((++nh) >= CTS)
6308 ERRMSG("Too many data points!");
6309 }
6310
6311 /* Close file... */
6312 fclose(in);
6313
6314 /* Check number of data points... */
6315 ts->ntime = nh;
6316 if (nh < 2)
6317 ERRMSG("Not enough data points!");
6318
6319 /* Write info... */
6320 LOG(2, "Number of time steps: %d", ts->ntime);
6321 LOG(2, "Time steps: %.2f, %.2f ... %.2f s", ts->time[0], ts->time[1],
6322 ts->time[nh - 1]);
6323 LOG(2, "Volume mixing ratio range: %g ... %g ppv",
6324 gsl_stats_min(ts->vmr, 1, (size_t) nh), gsl_stats_max(ts->vmr, 1,
6325 (size_t) nh));
6326
6327 /* Exit success... */
6328 return 1;
6329}
#define CTS
Maximum number of data points of climatological time series.
Definition: mptrac.h:338

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

6336 {
6337
6338 int ncid, varid, it, iy, iz, iz2, nt;
6339
6340 double *help, varmin = 1e99, varmax = -1e99;
6341
6342 /* Write info... */
6343 LOG(1, "Read %s data: %s", varname, filename);
6344
6345 /* Open netCDF file... */
6346 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
6347 WARN("%s climatology data are missing!", varname);
6348 return;
6349 }
6350
6351 /* Read pressure data... */
6352 NC_INQ_DIM("press", &zm->np, 2, CP);
6353 NC_GET_DOUBLE("press", zm->p, 1);
6354 if (zm->p[0] < zm->p[1])
6355 ERRMSG("Pressure data are not descending!");
6356
6357 /* Read latitudes... */
6358 NC_INQ_DIM("lat", &zm->nlat, 2, CY);
6359 NC_GET_DOUBLE("lat", zm->lat, 1);
6360 if (zm->lat[0] > zm->lat[1])
6361 ERRMSG("Latitude data are not ascending!");
6362
6363 /* Set time data (for monthly means)... */
6364 zm->ntime = 12;
6365 zm->time[0] = 1209600.00;
6366 zm->time[1] = 3888000.00;
6367 zm->time[2] = 6393600.00;
6368 zm->time[3] = 9072000.00;
6369 zm->time[4] = 11664000.00;
6370 zm->time[5] = 14342400.00;
6371 zm->time[6] = 16934400.00;
6372 zm->time[7] = 19612800.00;
6373 zm->time[8] = 22291200.00;
6374 zm->time[9] = 24883200.00;
6375 zm->time[10] = 27561600.00;
6376 zm->time[11] = 30153600.00;
6377
6378 /* Check number of timesteps... */
6379 NC_INQ_DIM("time", &nt, 12, 12);
6380
6381 /* Read data... */
6382 ALLOC(help, double,
6383 zm->nlat * zm->np * zm->ntime);
6384 NC_GET_DOUBLE(varname, help, 1);
6385 for (it = 0; it < zm->ntime; it++)
6386 for (iz = 0; iz < zm->np; iz++)
6387 for (iy = 0; iy < zm->nlat; iy++)
6388 zm->vmr[it][iz][iy] = help[ARRAY_3D(it, iz, zm->np, iy, zm->nlat)];
6389 free(help);
6390
6391 /* Fix data gaps... */
6392 for (it = 0; it < zm->ntime; it++)
6393 for (iy = 0; iy < zm->nlat; iy++)
6394 for (iz = 0; iz < zm->np; iz++) {
6395 if (zm->vmr[it][iz][iy] < 0) {
6396 for (iz2 = 0; iz2 < zm->np; iz2++)
6397 if (zm->vmr[it][iz2][iy] >= 0) {
6398 zm->vmr[it][iz][iy] = zm->vmr[it][iz2][iy];
6399 break;
6400 }
6401 for (iz2 = zm->np - 1; iz2 >= 0; iz2--)
6402 if (zm->vmr[it][iz2][iy] >= 0) {
6403 zm->vmr[it][iz][iy] = zm->vmr[it][iz2][iy];
6404 break;
6405 }
6406 }
6407 varmin = MIN(varmin, zm->vmr[it][iz][iy]);
6408 varmax = MAX(varmax, zm->vmr[it][iz][iy]);
6409 }
6410
6411 /* Close netCDF file... */
6412 NC(nc_close(ncid));
6413
6414 /* Write info... */
6415 LOG(2, "Number of time steps: %d", zm->ntime);
6416 LOG(2, "Time steps: %.2f, %.2f ... %.2f s",
6417 zm->time[0], zm->time[1], zm->time[zm->ntime - 1]);
6418 LOG(2, "Number of pressure levels: %d", zm->np);
6419 LOG(2, "Altitude levels: %g, %g ... %g km",
6420 Z(zm->p[0]), Z(zm->p[1]), Z(zm->p[zm->np - 1]));
6421 LOG(2, "Pressure levels: %g, %g ... %g hPa", zm->p[0],
6422 zm->p[1], zm->p[zm->np - 1]);
6423 LOG(2, "Number of latitudes: %d", zm->nlat);
6424 LOG(2, "Latitudes: %g, %g ... %g deg",
6425 zm->lat[0], zm->lat[1], zm->lat[zm->nlat - 1]);
6426 LOG(2, "%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
6427 varmax);
6428}
#define CY
Maximum number of latitudes for climatological data.
Definition: mptrac.h:313

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

6436 {
6437
6438 /* Write info... */
6439 LOG(1, "Read kernel function: %s", filename);
6440
6441 /* Open file... */
6442 FILE *in;
6443 if (!(in = fopen(filename, "r")))
6444 ERRMSG("Cannot open file!");
6445
6446 /* Read data... */
6447 char line[LEN];
6448 int n = 0;
6449 while (fgets(line, LEN, in))
6450 if (sscanf(line, "%lg %lg", &kz[n], &kw[n]) == 2) {
6451 if (n > 0 && kz[n] < kz[n - 1])
6452 ERRMSG("Height levels must be ascending!");
6453 if ((++n) >= EP)
6454 ERRMSG("Too many height levels!");
6455 }
6456
6457 /* Close file... */
6458 fclose(in);
6459
6460 /* Check number of data points... */
6461 *nk = n;
6462 if (n < 2)
6463 ERRMSG("Not enough height levels!");
6464
6465 /* Normalize kernel function... */
6466 const double kmax = gsl_stats_max(kw, 1, (size_t) n);
6467 for (int iz = 0; iz < n; iz++)
6468 kw[iz] /= kmax;
6469}

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

6476 {
6477
6478 FILE *in;
6479
6480 double r;
6481
6482 int year, mon, day, hour, min, sec;
6483
6484 /* Set timer... */
6485 SELECT_TIMER("READ_MET_BIN", "INPUT", NVTX_READ);
6486
6487 /* Open file... */
6488 if (!(in = fopen(filename, "r"))) {
6489 WARN("Cannot open file!");
6490 return 0;
6491 }
6492
6493 /* Check type of binary data... */
6494 int met_type;
6495 FREAD(&met_type, int,
6496 1,
6497 in);
6498 if (met_type != ctl->met_type)
6499 ERRMSG("Wrong MET_TYPE of binary data!");
6500
6501 /* Check version of binary data... */
6502 int version;
6503 FREAD(&version, int,
6504 1,
6505 in);
6506 if (version != 103)
6507 ERRMSG("Wrong version of binary data!");
6508
6509 /* Read time... */
6510 FREAD(&met->time, double,
6511 1,
6512 in);
6513 jsec2time(met->time, &year, &mon, &day, &hour, &min, &sec, &r);
6514 LOG(2, "Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
6515 met->time, year, mon, day, hour, min);
6516 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
6517 || day < 1 || day > 31 || hour < 0 || hour > 23)
6518 ERRMSG("Error while reading time!");
6519
6520 /* Read dimensions... */
6521 FREAD(&met->nx, int,
6522 1,
6523 in);
6524 LOG(2, "Number of longitudes: %d", met->nx);
6525 if (met->nx < 2 || met->nx > EX)
6526 ERRMSG("Number of longitudes out of range!");
6527
6528 FREAD(&met->ny, int,
6529 1,
6530 in);
6531 LOG(2, "Number of latitudes: %d", met->ny);
6532 if (met->ny < 2 || met->ny > EY)
6533 ERRMSG("Number of latitudes out of range!");
6534
6535 FREAD(&met->np, int,
6536 1,
6537 in);
6538 LOG(2, "Number of levels: %d", met->np);
6539 if (met->np < 2 || met->np > EP)
6540 ERRMSG("Number of levels out of range!");
6541
6542 /* Read grid... */
6543 FREAD(met->lon, double,
6544 (size_t) met->nx,
6545 in);
6546 LOG(2, "Longitudes: %g, %g ... %g deg",
6547 met->lon[0], met->lon[1], met->lon[met->nx - 1]);
6548
6549 FREAD(met->lat, double,
6550 (size_t) met->ny,
6551 in);
6552 LOG(2, "Latitudes: %g, %g ... %g deg",
6553 met->lat[0], met->lat[1], met->lat[met->ny - 1]);
6554
6555 FREAD(met->p, double,
6556 (size_t) met->np,
6557 in);
6558 LOG(2, "Altitude levels: %g, %g ... %g km",
6559 Z(met->p[0]), Z(met->p[1]), Z(met->p[met->np - 1]));
6560 LOG(2, "Pressure levels: %g, %g ... %g hPa",
6561 met->p[0], met->p[1], met->p[met->np - 1]);
6562
6563 /* Read surface data... */
6564 read_met_bin_2d(in, met, met->ps, "PS");
6565 read_met_bin_2d(in, met, met->ts, "TS");
6566 read_met_bin_2d(in, met, met->zs, "ZS");
6567 read_met_bin_2d(in, met, met->us, "US");
6568 read_met_bin_2d(in, met, met->vs, "VS");
6569 read_met_bin_2d(in, met, met->ess, "ESS");
6570 read_met_bin_2d(in, met, met->nss, "NSS");
6571 read_met_bin_2d(in, met, met->shf, "SHF");
6572 read_met_bin_2d(in, met, met->lsm, "LSM");
6573 read_met_bin_2d(in, met, met->sst, "SST");
6574 read_met_bin_2d(in, met, met->pbl, "PBL");
6575 read_met_bin_2d(in, met, met->pt, "PT");
6576 read_met_bin_2d(in, met, met->tt, "TT");
6577 read_met_bin_2d(in, met, met->zt, "ZT");
6578 read_met_bin_2d(in, met, met->h2ot, "H2OT");
6579 read_met_bin_2d(in, met, met->pct, "PCT");
6580 read_met_bin_2d(in, met, met->pcb, "PCB");
6581 read_met_bin_2d(in, met, met->cl, "CL");
6582 read_met_bin_2d(in, met, met->plcl, "PLCL");
6583 read_met_bin_2d(in, met, met->plfc, "PLFC");
6584 read_met_bin_2d(in, met, met->pel, "PEL");
6585 read_met_bin_2d(in, met, met->cape, "CAPE");
6586 read_met_bin_2d(in, met, met->cin, "CIN");
6587 read_met_bin_2d(in, met, met->o3c, "O3C");
6588
6589 /* Read level data... */
6590 read_met_bin_3d(in, ctl, met, met->z, "Z", -1e34f, 1e34f);
6591 read_met_bin_3d(in, ctl, met, met->t, "T", 0, 1e34f);
6592 read_met_bin_3d(in, ctl, met, met->u, "U", -1e34f, 1e34f);
6593 read_met_bin_3d(in, ctl, met, met->v, "V", -1e34f, 1e34f);
6594 read_met_bin_3d(in, ctl, met, met->w, "W", -1e34f, 1e34f);
6595 read_met_bin_3d(in, ctl, met, met->pv, "PV", -1e34f, 1e34f);
6596 read_met_bin_3d(in, ctl, met, met->h2o, "H2O", 0, 1e34f);
6597 read_met_bin_3d(in, ctl, met, met->o3, "O3", 0, 1e34f);
6598 read_met_bin_3d(in, ctl, met, met->lwc, "LWC", 0, 1e34f);
6599 read_met_bin_3d(in, ctl, met, met->rwc, "RWC", 0, 1e34f);
6600 read_met_bin_3d(in, ctl, met, met->iwc, "IWC", 0, 1e34f);
6601 read_met_bin_3d(in, ctl, met, met->swc, "SWC", 0, 1e34f);
6602 read_met_bin_3d(in, ctl, met, met->cc, "CC", 0, 1);
6603
6604 /* Read final flag... */
6605 int final;
6606 FREAD(&final, int,
6607 1,
6608 in);
6609 if (final != 999)
6610 ERRMSG("Error while reading binary data!");
6611
6612 /* Close file... */
6613 fclose(in);
6614
6615 /* Return success... */
6616 return 1;
6617}
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:6621
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:6650
#define EY
Maximum number of latitudes for meteo data.
Definition: mptrac.h:293
float zt[EX][EY]
Tropopause geopotential height [km].
Definition: mptrac.h:3538
float sst[EX][EY]
Sea surface temperature [K].
Definition: mptrac.h:3526
float rwc[EX][EY][EP]
Cloud rain water content [kg/kg].
Definition: mptrac.h:3598
float o3c[EX][EY]
Total column ozone [DU].
Definition: mptrac.h:3568
float cape[EX][EY]
Convective available potential energy [J/kg].
Definition: mptrac.h:3562
float pct[EX][EY]
Cloud top pressure [hPa].
Definition: mptrac.h:3544
float shf[EX][EY]
Surface sensible heat flux [W/m^2].
Definition: mptrac.h:3520
float lwc[EX][EY][EP]
Cloud liquid water content [kg/kg].
Definition: mptrac.h:3595
float us[EX][EY]
Surface zonal wind [m/s].
Definition: mptrac.h:3508
float cc[EX][EY][EP]
Cloud cover [1].
Definition: mptrac.h:3607
float ts[EX][EY]
Surface temperature [K].
Definition: mptrac.h:3502
float ess[EX][EY]
Eastward turbulent surface stress [N/m^2].
Definition: mptrac.h:3514
float pcb[EX][EY]
Cloud bottom pressure [hPa].
Definition: mptrac.h:3547
float pel[EX][EY]
Pressure at equilibrium level (EL) [hPa].
Definition: mptrac.h:3559
float cin[EX][EY]
Convective inhibition [J/kg].
Definition: mptrac.h:3565
float plcl[EX][EY]
Pressure at lifted condensation level (LCL) [hPa].
Definition: mptrac.h:3553
float tt[EX][EY]
Tropopause temperature [K].
Definition: mptrac.h:3535
float pbl[EX][EY]
Boundary layer pressure [hPa].
Definition: mptrac.h:3529
float vs[EX][EY]
Surface meridional wind [m/s].
Definition: mptrac.h:3511
float lsm[EX][EY]
Land-sea mask [1].
Definition: mptrac.h:3523
float iwc[EX][EY][EP]
Cloud ice water content [kg/kg].
Definition: mptrac.h:3601
float h2ot[EX][EY]
Tropopause water vapor volume mixing ratio [ppv].
Definition: mptrac.h:3541
float pv[EX][EY][EP]
Potential vorticity [PVU].
Definition: mptrac.h:3586
float cl[EX][EY]
Total column cloud water [kg/m^2].
Definition: mptrac.h:3550
float nss[EX][EY]
Northward turbulent surface stress [N/m^2].
Definition: mptrac.h:3517
float plfc[EX][EY]
Pressure at level of free convection (LFC) [hPa].
Definition: mptrac.h:3556
float swc[EX][EY][EP]
Cloud snow water content [kg/kg].
Definition: mptrac.h:3604
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 6621 of file mptrac.c.

6625 {
6626
6627 float *help;
6628
6629 /* Allocate... */
6630 ALLOC(help, float,
6631 EX * EY);
6632
6633 /* Read uncompressed... */
6634 LOG(2, "Read 2-D variable: %s (uncompressed)", varname);
6635 FREAD(help, float,
6636 (size_t) (met->nx * met->ny),
6637 in);
6638
6639 /* Copy data... */
6640 for (int ix = 0; ix < met->nx; ix++)
6641 for (int iy = 0; iy < met->ny; iy++)
6642 var[ix][iy] = help[ARRAY_2D(ix, iy, met->ny)];
6643
6644 /* Free... */
6645 free(help);
6646}
#define ARRAY_2D(ix, iy, ny)
Macro for computing the linear index of a 2D array element.
Definition: mptrac.h:394

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

6657 {
6658
6659 float *help;
6660
6661 /* Allocate... */
6662 ALLOC(help, float,
6663 EX * EY * EP);
6664
6665 /* Read uncompressed data... */
6666 if (ctl->met_type == 1) {
6667 LOG(2, "Read 3-D variable: %s (uncompressed)", varname);
6668 FREAD(help, float,
6669 (size_t) (met->nx * met->ny * met->np),
6670 in);
6671 }
6672
6673 /* Read packed data... */
6674 else if (ctl->met_type == 2)
6675 compress_pck(varname, help, (size_t) (met->ny * met->nx),
6676 (size_t) met->np, 1, in);
6677
6678 /* Read zfp data... */
6679 else if (ctl->met_type == 3) {
6680#ifdef ZFP
6681 int precision;
6682 FREAD(&precision, int,
6683 1,
6684 in);
6685
6686 double tolerance;
6687 FREAD(&tolerance, double,
6688 1,
6689 in);
6690
6691 compress_zfp(varname, help, met->np, met->ny, met->nx, precision,
6692 tolerance, 1, in);
6693#else
6694 ERRMSG("MPTRAC was compiled without zfp compression!");
6695#endif
6696 }
6697
6698 /* Read zstd data... */
6699 else if (ctl->met_type == 4) {
6700#ifdef ZSTD
6701 compress_zstd(varname, help, (size_t) (met->np * met->ny * met->nx), 1,
6702 ctl->met_zstd_level, in);
6703#else
6704 ERRMSG("MPTRAC was compiled without zstd compression!");
6705#endif
6706 }
6707
6708 /* Read cmultiscale data... */
6709 else if (ctl->met_type == 5) {
6710#ifdef CMS
6711 compress_cms(ctl, varname, help, (size_t) met->nx, (size_t) met->ny,
6712 (size_t) met->np, 1, in);
6713#else
6714 ERRMSG("MPTRAC was compiled without cmultiscale compression!");
6715#endif
6716 }
6717
6718 /* Copy data... */
6719#pragma omp parallel for default(shared) collapse(2)
6720 for (int ix = 0; ix < met->nx; ix++)
6721 for (int iy = 0; iy < met->ny; iy++)
6722 for (int ip = 0; ip < met->np; ip++) {
6723 var[ix][iy][ip] = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
6724 if (var[ix][iy][ip] < bound_min)
6725 var[ix][iy][ip] = bound_min;
6726 else if (var[ix][iy][ip] > bound_max)
6727 var[ix][iy][ip] = bound_max;
6728 }
6729
6730 /* Free... */
6731 free(help);
6732}
void compress_pck(const char *varname, float *array, const size_t nxy, const size_t nz, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats.
Definition: mptrac.c:664
void compress_zstd(const char *varname, float *array, const size_t n, const int decompress, const int level, FILE *inout)
Compresses or decompresses a float array using Zstandard (ZSTD).
void compress_cms(const ctl_t *ctl, const char *varname, float *array, const size_t nx, const size_t ny, const size_t np, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm.
void compress_zfp(const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using the ZFP library.
int met_zstd_level
ZSTD compression level (from -5 to 22).
Definition: mptrac.h:2585
Here is the call graph for this function:

◆ read_met_cape()

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

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

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

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

The function performs the following steps:

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

Definition at line 6736 of file mptrac.c.

6739 {
6740
6741 /* Check parameters... */
6742 if (ctl->met_cape != 1)
6743 return;
6744
6745 /* Set timer... */
6746 SELECT_TIMER("READ_MET_CAPE", "METPROC", NVTX_READ);
6747 LOG(2, "Calculate CAPE...");
6748
6749 /* Vertical spacing (about 100 m)... */
6750 const double pfac = 1.01439, dz0 = RI / MA / G0 * log(pfac);
6751
6752 /* Loop over columns... */
6753#pragma omp parallel for default(shared) collapse(2)
6754 for (int ix = 0; ix < met->nx; ix++)
6755 for (int iy = 0; iy < met->ny; iy++) {
6756
6757 /* Get potential temperature and water vapor at lowest 50 hPa... */
6758 int n = 0;
6759 double h2o = 0, t, theta = 0;
6760 double pbot = MIN(met->ps[ix][iy], met->p[0]);
6761 double ptop = pbot - 50.;
6762 for (int ip = 0; ip < met->np; ip++) {
6763 if (met->p[ip] <= pbot) {
6764 theta += THETA(met->p[ip], met->t[ix][iy][ip]);
6765 h2o += met->h2o[ix][iy][ip];
6766 n++;
6767 }
6768 if (met->p[ip] < ptop && n > 0)
6769 break;
6770 }
6771 theta /= n;
6772 h2o /= n;
6773
6774 /* Cannot compute anything if water vapor is missing... */
6775 met->plcl[ix][iy] = NAN;
6776 met->plfc[ix][iy] = NAN;
6777 met->pel[ix][iy] = NAN;
6778 met->cape[ix][iy] = NAN;
6779 met->cin[ix][iy] = NAN;
6780 if (h2o <= 0)
6781 continue;
6782
6783 /* Find lifted condensation level (LCL)... */
6784 ptop = P(20.);
6785 pbot = met->ps[ix][iy];
6786 do {
6787 met->plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
6788 t = theta / pow(1000. / met->plcl[ix][iy], 0.286);
6789 if (RH(met->plcl[ix][iy], t, h2o) > 100.)
6790 ptop = met->plcl[ix][iy];
6791 else
6792 pbot = met->plcl[ix][iy];
6793 } while (pbot - ptop > 0.1);
6794
6795 /* Calculate CIN up to LCL... */
6797 double dcape, dz, h2o_env, t_env;
6798 double p = met->ps[ix][iy];
6799 met->cape[ix][iy] = met->cin[ix][iy] = 0;
6800 do {
6801 dz = dz0 * TVIRT(t, h2o);
6802 p /= pfac;
6803 t = theta / pow(1000. / p, 0.286);
6804 intpol_met_space_3d(met, met->t, p, met->lon[ix], met->lat[iy],
6805 &t_env, ci, cw, 1);
6806 intpol_met_space_3d(met, met->h2o, p, met->lon[ix], met->lat[iy],
6807 &h2o_env, ci, cw, 0);
6808 dcape = 1e3 * G0 * (TVIRT(t, h2o) - TVIRT(t_env, h2o_env)) /
6809 TVIRT(t_env, h2o_env) * dz;
6810 if (dcape < 0)
6811 met->cin[ix][iy] += fabsf((float) dcape);
6812 } while (p > met->plcl[ix][iy]);
6813
6814 /* Calculate level of free convection (LFC), equilibrium level (EL),
6815 and convective available potential energy (CAPE)... */
6816 dcape = 0;
6817 p = met->plcl[ix][iy];
6818 t = theta / pow(1000. / p, 0.286);
6819 ptop = 0.75 * clim_tropo(clim, met->time, met->lat[iy]);
6820 do {
6821 dz = dz0 * TVIRT(t, h2o);
6822 p /= pfac;
6823 t -= lapse_rate(t, h2o) * dz;
6824 double psat = PSAT(t);
6825 h2o = psat / (p - (1. - EPS) * psat);
6826 intpol_met_space_3d(met, met->t, p, met->lon[ix], met->lat[iy],
6827 &t_env, ci, cw, 1);
6828 intpol_met_space_3d(met, met->h2o, p, met->lon[ix], met->lat[iy],
6829 &h2o_env, ci, cw, 0);
6830 double dcape_old = dcape;
6831 dcape = 1e3 * G0 * (TVIRT(t, h2o) - TVIRT(t_env, h2o_env)) /
6832 TVIRT(t_env, h2o_env) * dz;
6833 if (dcape > 0) {
6834 met->cape[ix][iy] += (float) dcape;
6835 if (!isfinite(met->plfc[ix][iy]))
6836 met->plfc[ix][iy] = (float) p;
6837 } else if (dcape_old > 0)
6838 met->pel[ix][iy] = (float) p;
6839 if (dcape < 0 && !isfinite(met->plfc[ix][iy]))
6840 met->cin[ix][iy] += fabsf((float) dcape);
6841 } while (p > ptop);
6842
6843 /* Check results... */
6844 if (!isfinite(met->plfc[ix][iy]))
6845 met->cin[ix][iy] = NAN;
6846 }
6847}
double clim_tropo(const clim_t *clim, const double t, const double lat)
Calculates the tropopause pressure based on climatological data.
Definition: mptrac.c:200
Here is the call graph for this function:

◆ read_met_cloud()

void read_met_cloud ( met_t met)

Calculates cloud-related variables for each grid point.

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

Parameters
metA pointer to a structure containing meteorological data.

The function performs the following steps:

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

Definition at line 6851 of file mptrac.c.

6852 {
6853
6854 /* Set timer... */
6855 SELECT_TIMER("READ_MET_CLOUD", "METPROC", NVTX_READ);
6856 LOG(2, "Calculate cloud data...");
6857
6858 /* Thresholds for cloud detection... */
6859 const double ccmin = 0.01, cwmin = 1e-6;
6860
6861 /* Loop over columns... */
6862#pragma omp parallel for default(shared) collapse(2)
6863 for (int ix = 0; ix < met->nx; ix++)
6864 for (int iy = 0; iy < met->ny; iy++) {
6865
6866 /* Init... */
6867 met->pct[ix][iy] = NAN;
6868 met->pcb[ix][iy] = NAN;
6869 met->cl[ix][iy] = 0;
6870
6871 /* Loop over pressure levels... */
6872 for (int ip = 0; ip < met->np - 1; ip++) {
6873
6874 /* Check pressure... */
6875 if (met->p[ip] > met->ps[ix][iy] || met->p[ip] < P(20.))
6876 continue;
6877
6878 /* Check ice water and liquid water content... */
6879 if (met->cc[ix][iy][ip] > ccmin
6880 && (met->lwc[ix][iy][ip] > cwmin
6881 || met->rwc[ix][iy][ip] > cwmin
6882 || met->iwc[ix][iy][ip] > cwmin
6883 || met->swc[ix][iy][ip] > cwmin)) {
6884
6885 /* Get cloud top pressure ... */
6886 met->pct[ix][iy]
6887 = (float) (0.5 * (met->p[ip] + (float) met->p[ip + 1]));
6888
6889 /* Get cloud bottom pressure ... */
6890 if (!isfinite(met->pcb[ix][iy]))
6891 met->pcb[ix][iy]
6892 = (float) (0.5 * (met->p[ip] + met->p[MAX(ip - 1, 0)]));
6893 }
6894
6895 /* Get cloud water... */
6896 met->cl[ix][iy] += (float)
6897 (0.5 * (met->lwc[ix][iy][ip] + met->lwc[ix][iy][ip + 1]
6898 + met->rwc[ix][iy][ip] + met->rwc[ix][iy][ip + 1]
6899 + met->iwc[ix][iy][ip] + met->iwc[ix][iy][ip + 1]
6900 + met->swc[ix][iy][ip] + met->swc[ix][iy][ip + 1])
6901 * 100. * (met->p[ip] - met->p[ip + 1]) / G0);
6902 }
6903 }
6904}

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

6910 {
6911
6912 met_t *help;
6913
6914 /* Check parameters... */
6915 if (ctl->met_detrend <= 0)
6916 return;
6917
6918 /* Set timer... */
6919 SELECT_TIMER("READ_MET_DETREND", "METPROC", NVTX_READ);
6920 LOG(2, "Detrend meteo data...");
6921
6922 /* Allocate... */
6923 ALLOC(help, met_t, 1);
6924
6925 /* Calculate standard deviation... */
6926 const double sigma = ctl->met_detrend / 2.355;
6927 const double tssq = 2. * SQR(sigma);
6928
6929 /* Calculate box size in latitude... */
6930 int sy = (int) (3. * DY2DEG(sigma) / fabs(met->lat[1] - met->lat[0]));
6931 sy = MIN(MAX(1, sy), met->ny / 2);
6932
6933 /* Calculate background... */
6934#pragma omp parallel for default(shared) collapse(2)
6935 for (int ix = 0; ix < met->nx; ix++) {
6936 for (int iy = 0; iy < met->ny; iy++) {
6937
6938 /* Calculate Cartesian coordinates... */
6939 double x0[3];
6940 geo2cart(0.0, met->lon[ix], met->lat[iy], x0);
6941
6942 /* Calculate box size in longitude... */
6943 int sx =
6944 (int) (3. * DX2DEG(sigma, met->lat[iy]) /
6945 fabs(met->lon[1] - met->lon[0]));
6946 sx = MIN(MAX(1, sx), met->nx / 2);
6947
6948 /* Init... */
6949 float wsum = 0;
6950 for (int ip = 0; ip < met->np; ip++) {
6951 help->t[ix][iy][ip] = 0;
6952 help->u[ix][iy][ip] = 0;
6953 help->v[ix][iy][ip] = 0;
6954 help->w[ix][iy][ip] = 0;
6955 }
6956
6957 /* Loop over neighboring grid points... */
6958 for (int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
6959 int ix3 = ix2;
6960 if (ix3 < 0)
6961 ix3 += met->nx;
6962 else if (ix3 >= met->nx)
6963 ix3 -= met->nx;
6964 for (int iy2 = MAX(iy - sy, 0);
6965 iy2 <= MIN(iy + sy, met->ny - 1); iy2++) {
6966
6967 /* Calculate Cartesian coordinates... */
6968 double x1[3];
6969 geo2cart(0.0, met->lon[ix3], met->lat[iy2], x1);
6970
6971 /* Calculate weighting factor... */
6972 const float w = (float) exp(-DIST2(x0, x1) / tssq);
6973
6974 /* Add data... */
6975 wsum += w;
6976 for (int ip = 0; ip < met->np; ip++) {
6977 help->t[ix][iy][ip] += w * met->t[ix3][iy2][ip];
6978 help->u[ix][iy][ip] += w * met->u[ix3][iy2][ip];
6979 help->v[ix][iy][ip] += w * met->v[ix3][iy2][ip];
6980 help->w[ix][iy][ip] += w * met->w[ix3][iy2][ip];
6981 }
6982 }
6983 }
6984
6985 /* Normalize... */
6986 for (int ip = 0; ip < met->np; ip++) {
6987 help->t[ix][iy][ip] /= wsum;
6988 help->u[ix][iy][ip] /= wsum;
6989 help->v[ix][iy][ip] /= wsum;
6990 help->w[ix][iy][ip] /= wsum;
6991 }
6992 }
6993 }
6994
6995 /* Subtract background... */
6996#pragma omp parallel for default(shared) collapse(3)
6997 for (int ix = 0; ix < met->nx; ix++)
6998 for (int iy = 0; iy < met->ny; iy++)
6999 for (int ip = 0; ip < met->np; ip++) {
7000 met->t[ix][iy][ip] -= help->t[ix][iy][ip];
7001 met->u[ix][iy][ip] -= help->u[ix][iy][ip];
7002 met->v[ix][iy][ip] -= help->v[ix][iy][ip];
7003 met->w[ix][iy][ip] -= help->w[ix][iy][ip];
7004 }
7005
7006 /* Free... */
7007 free(help);
7008}
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:988
#define DIST2(a, b)
Calculate the squared Euclidean distance between two points in Cartesian coordinates.
Definition: mptrac.h:616
double met_detrend
FWHM of horizontal Gaussian used for detrending [km].
Definition: mptrac.h:2664
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 7012 of file mptrac.c.

7013 {
7014
7015 /* Set timer... */
7016 SELECT_TIMER("READ_MET_EXTRAPOLATE", "METPROC", NVTX_READ);
7017 LOG(2, "Extrapolate meteo data...");
7018
7019 /* Loop over columns... */
7020#pragma omp parallel for default(shared) collapse(2)
7021 for (int ix = 0; ix < met->nx; ix++)
7022 for (int iy = 0; iy < met->ny; iy++) {
7023
7024 /* Find lowest valid data point... */
7025 int ip0;
7026 for (ip0 = met->np - 1; ip0 >= 0; ip0--)
7027 if (!isfinite(met->t[ix][iy][ip0])
7028 || !isfinite(met->u[ix][iy][ip0])
7029 || !isfinite(met->v[ix][iy][ip0])
7030 || !isfinite(met->w[ix][iy][ip0]))
7031 break;
7032
7033 /* Extrapolate... */
7034 for (int ip = ip0; ip >= 0; ip--) {
7035 met->t[ix][iy][ip] = met->t[ix][iy][ip + 1];
7036 met->u[ix][iy][ip] = met->u[ix][iy][ip + 1];
7037 met->v[ix][iy][ip] = met->v[ix][iy][ip + 1];
7038 met->w[ix][iy][ip] = met->w[ix][iy][ip + 1];
7039 met->h2o[ix][iy][ip] = met->h2o[ix][iy][ip + 1];
7040 met->o3[ix][iy][ip] = met->o3[ix][iy][ip + 1];
7041 met->lwc[ix][iy][ip] = met->lwc[ix][iy][ip + 1];
7042 met->rwc[ix][iy][ip] = met->rwc[ix][iy][ip + 1];
7043 met->iwc[ix][iy][ip] = met->iwc[ix][iy][ip + 1];
7044 met->swc[ix][iy][ip] = met->swc[ix][iy][ip + 1];
7045 met->cc[ix][iy][ip] = met->cc[ix][iy][ip + 1];
7046 }
7047 }
7048}

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

7054 {
7055
7056 float *help;
7057
7058 double logp[EP];
7059
7060 int dx = ctl->met_geopot_sx, dy = ctl->met_geopot_sy;
7061
7062 /* Set timer... */
7063 SELECT_TIMER("READ_MET_GEOPOT", "METPROC", NVTX_READ);
7064 LOG(2, "Calculate geopotential heights...");
7065
7066 /* Allocate... */
7067 ALLOC(help, float,
7068 EX * EY * EP);
7069
7070 /* Calculate log pressure... */
7071#pragma omp parallel for default(shared)
7072 for (int ip = 0; ip < met->np; ip++)
7073 logp[ip] = log(met->p[ip]);
7074
7075 /* Apply hydrostatic equation to calculate geopotential heights... */
7076#pragma omp parallel for default(shared) collapse(2)
7077 for (int ix = 0; ix < met->nx; ix++)
7078 for (int iy = 0; iy < met->ny; iy++) {
7079
7080 /* Get surface height and pressure... */
7081 const double zs = met->zs[ix][iy];
7082 const double lnps = log(met->ps[ix][iy]);
7083
7084 /* Get temperature and water vapor at the surface... */
7085 const int ip0 = locate_irr(met->p, met->np, met->ps[ix][iy]);
7086 const double ts = LIN(met->p[ip0], met->t[ix][iy][ip0], met->p[ip0 + 1],
7087 met->t[ix][iy][ip0 + 1], met->ps[ix][iy]);
7088 const double h2os =
7089 LIN(met->p[ip0], met->h2o[ix][iy][ip0], met->p[ip0 + 1],
7090 met->h2o[ix][iy][ip0 + 1], met->ps[ix][iy]);
7091
7092 /* Upper part of profile... */
7093 met->z[ix][iy][ip0 + 1]
7094 = (float) (zs +
7095 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
7096 met->t[ix][iy][ip0 + 1], met->h2o[ix][iy][ip0 + 1]));
7097 for (int ip = ip0 + 2; ip < met->np; ip++)
7098 met->z[ix][iy][ip]
7099 = (float) (met->z[ix][iy][ip - 1] +
7100 ZDIFF(logp[ip - 1], met->t[ix][iy][ip - 1],
7101 met->h2o[ix][iy][ip - 1], logp[ip],
7102 met->t[ix][iy][ip], met->h2o[ix][iy][ip]));
7103
7104 /* Lower part of profile... */
7105 met->z[ix][iy][ip0]
7106 = (float) (zs +
7107 ZDIFF(lnps, ts, h2os, logp[ip0],
7108 met->t[ix][iy][ip0], met->h2o[ix][iy][ip0]));
7109 for (int ip = ip0 - 1; ip >= 0; ip--)
7110 met->z[ix][iy][ip]
7111 = (float) (met->z[ix][iy][ip + 1] +
7112 ZDIFF(logp[ip + 1], met->t[ix][iy][ip + 1],
7113 met->h2o[ix][iy][ip + 1], logp[ip],
7114 met->t[ix][iy][ip], met->h2o[ix][iy][ip]));
7115 }
7116
7117 /* Check control parameters... */
7118 if (dx == 0 || dy == 0)
7119 return;
7120
7121 /* Default smoothing parameters... */
7122 if (dx < 0 || dy < 0) {
7123 if (fabs(met->lon[1] - met->lon[0]) < 0.5) {
7124 dx = 3;
7125 dy = 2;
7126 } else {
7127 dx = 6;
7128 dy = 4;
7129 }
7130 }
7131
7132 /* Calculate weights for smoothing... */
7133 float ws[dx + 1][dy + 1];
7134#pragma omp parallel for default(shared) collapse(2)
7135 for (int ix = 0; ix <= dx; ix++)
7136 for (int iy = 0; iy < dy; iy++)
7137 ws[ix][iy] = (1.0f - (float) ix / (float) dx)
7138 * (1.0f - (float) iy / (float) dy);
7139
7140 /* Copy data... */
7141#pragma omp parallel for default(shared) collapse(3)
7142 for (int ix = 0; ix < met->nx; ix++)
7143 for (int iy = 0; iy < met->ny; iy++)
7144 for (int ip = 0; ip < met->np; ip++)
7145 help[ARRAY_3D(ip, ix, met->nx, iy, met->ny)] = met->z[ix][iy][ip];
7146
7147 /* Horizontal smoothing... */
7148#pragma omp parallel for default(shared) collapse(3)
7149 for (int ip = 0; ip < met->np; ip++)
7150 for (int ix = 0; ix < met->nx; ix++)
7151 for (int iy = 0; iy < met->ny; iy++) {
7152 float res = 0, wsum = 0;
7153 int iy0 = MAX(iy - dy + 1, 0);
7154 int iy1 = MIN(iy + dy - 1, met->ny - 1);
7155 for (int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
7156 int ix3 = ix2;
7157 if (ix3 < 0)
7158 ix3 += met->nx;
7159 else if (ix3 >= met->nx)
7160 ix3 -= met->nx;
7161 for (int iy2 = iy0; iy2 <= iy1; ++iy2)
7162 if (isfinite(help[ARRAY_3D(ip, ix3, met->nx, iy2, met->ny)])) {
7163 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
7164 res += w * help[ARRAY_3D(ip, ix3, met->nx, iy2, met->ny)];
7165 wsum += w;
7166 }
7167 }
7168 if (wsum > 0)
7169 met->z[ix][iy][ip] = res / wsum;
7170 else
7171 met->z[ix][iy][ip] = NAN;
7172 }
7173
7174 /* Free... */
7175 free(help);
7176}
#define ZDIFF(lnp0, t0, h2o0, lnp1, t1, h2o1)
Calculate geopotential height difference.
Definition: mptrac.h:1859
Here is the call graph for this function:

◆ read_met_ml2pl()

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

Reads global meteorological information from a grib file.

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

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

The function performs the following steps:

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

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

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

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

The function performs the following steps:

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

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

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

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

The function performs the following steps:

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

Interpolates meteorological data to specified pressure levels.

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

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

This function performs the following steps:

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

Definition at line 7612 of file mptrac.c.

7616 {
7617
7618 double aux[EP], p[EP];
7619
7620 /* Set timer... */
7621 SELECT_TIMER("READ_MET_ML2PL", "METPROC", NVTX_READ);
7622 LOG(2, "Interpolate meteo data to pressure levels: %s", varname);
7623
7624 /* Loop over columns... */
7625#pragma omp parallel for default(shared) private(aux,p) collapse(2)
7626 for (int ix = 0; ix < met->nx; ix++)
7627 for (int iy = 0; iy < met->ny; iy++) {
7628
7629 /* Copy pressure profile... */
7630 for (int ip = 0; ip < met->np; ip++)
7631 p[ip] = met->pl[ix][iy][ip];
7632
7633 /* Interpolate... */
7634 for (int ip = 0; ip < ctl->met_np; ip++) {
7635 double pt = ctl->met_p[ip];
7636 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
7637 pt = p[0];
7638 else if ((pt > p[met->np - 1] && p[1] > p[0])
7639 || (pt < p[met->np - 1] && p[1] < p[0]))
7640 pt = p[met->np - 1];
7641 int ip2 = locate_irr(p, met->np, pt);
7642 aux[ip] = LIN(p[ip2], var[ix][iy][ip2],
7643 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
7644 }
7645
7646 /* Copy data... */
7647 for (int ip = 0; ip < ctl->met_np; ip++)
7648 var[ix][iy][ip] = (float) aux[ip];
7649 }
7650}
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 7654 of file mptrac.c.

7656 {
7657
7658 /* Check parameters... */
7659 if (ctl->advect_vert_coord != 1)
7660 return;
7661
7662 /* Set timer... */
7663 SELECT_TIMER("READ_MET_MONOTONIZE", "METPROC", NVTX_READ);
7664 LOG(2, "Make zeta profiles monotone...");
7665
7666 /* Create monotone zeta profiles... */
7667#pragma omp parallel for default(shared) collapse(2)
7668 for (int i = 0; i < met->nx; i++)
7669 for (int j = 0; j < met->ny; j++) {
7670 int k = 1;
7671
7672 while (k < met->npl) { /* Check if there is an inversion at level k... */
7673 if ((met->zetal[i][j][k - 1] >= met->zetal[i][j][k])) {
7674 /* Find the upper level k+l over the inversion... */
7675 int l = 0;
7676 do {
7677 l++;
7678 }
7679 while ((met->zetal[i][j][k - 1] >=
7680 met->zetal[i][j][k + l]) & (k + l < met->npl));
7681
7682 /* Interpolate linear between the top and bottom
7683 of the inversion... */
7684 float s =
7685 (float) (met->zetal[i][j][k + l] - met->zetal[i][j][k - 1])
7686 / (float) (met->hybrid[k + l] - met->hybrid[k - 1]);
7687
7688 for (int m = k; m < k + l; m++) {
7689 float d = (float) (met->hybrid[m] - met->hybrid[k - 1]);
7690 met->zetal[i][j][m] = s * d + met->zetal[i][j][k - 1];
7691 }
7692
7693 /* Search for more inversions above the last inversion ... */
7694 k = k + l;
7695 } else {
7696 k++;
7697 }
7698 }
7699 }
7700
7701 /* Create monotone pressure profiles... */
7702#pragma omp parallel for default(shared) collapse(2)
7703 for (int i = 0; i < met->nx; i++)
7704 for (int j = 0; j < met->ny; j++) {
7705 int k = 1;
7706
7707 while (k < met->npl) { /* Check if there is an inversion at level k... */
7708 if ((met->pl[i][j][k - 1] <= met->pl[i][j][k])) {
7709
7710 /* Find the upper level k+l over the inversion... */
7711 int l = 0;
7712 do {
7713 l++;
7714 }
7715 while ((met->pl[i][j][k - 1] <= met->pl[i][j][k + l]) & (k + l <
7716 met->npl));
7717
7718 /* Interpolate linear between the top and bottom
7719 of the inversion... */
7720 float s = (float) (met->pl[i][j][k + l] - met->pl[i][j][k - 1])
7721 / (float) (met->hybrid[k + l] - met->hybrid[k - 1]);
7722
7723 for (int m = k; m < k + l; m++) {
7724 float d = (float) (met->hybrid[m] - met->hybrid[k - 1]);
7725 met->pl[i][j][m] = s * d + met->pl[i][j][k - 1];
7726 }
7727
7728 /* Search for more inversions above the last inversion ... */
7729 k += l;
7730 } else {
7731 k++;
7732 }
7733 }
7734 }
7735}
double hybrid[EP]
Model hybrid levels.
Definition: mptrac.h:3496

◆ read_met_nc()

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

Reads meteorological data from a NetCDF file and processes it.

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

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

Definition at line 7739 of file mptrac.c.

7742 {
7743
7744 int ncid;
7745
7746 /* Open netCDF file... */
7747 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7748 WARN("Cannot open file!");
7749 return 0;
7750 }
7751
7752 /* Read coordinates of meteo data... */
7753 read_met_nc_grid(filename, ncid, ctl, met);
7754
7755 /* Read surface data... */
7756 read_met_nc_surface(ncid, ctl, met);
7757
7758 /* Read meteo data on vertical levels... */
7759 read_met_nc_levels(ncid, ctl, met);
7760
7761 /* Close file... */
7762 NC(nc_close(ncid));
7763
7764 /* Return success... */
7765 return 1;
7766}
void read_met_nc_surface(const int ncid, const ctl_t *ctl, met_t *met)
Reads surface meteorological data from a netCDF file and stores it in the meteorological data structu...
Definition: mptrac.c:8422
void read_met_nc_grid(const char *filename, const int ncid, const ctl_t *ctl, met_t *met)
Reads meteorological grid information from a NetCDF file.
Definition: mptrac.c:8074
void read_met_nc_levels(const int ncid, const ctl_t *ctl, met_t *met)
Reads meteorological variables at different vertical levels from a NetCDF file.
Definition: mptrac.c:8208
Here is the call graph for this function:

◆ read_met_nc_2d()

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

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

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

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

The function performs the following steps:

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

Definition at line 7770 of file mptrac.c.

7782 {
7783
7784 char varsel[LEN];
7785
7786 float offset, scalfac;
7787
7788 int varid;
7789
7790 /* Check if variable exists... */
7791 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
7792 sprintf(varsel, "%s", varname);
7793 else if (varname2 != NULL
7794 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
7795 sprintf(varsel, "%s", varname2);
7796 else if (varname3 != NULL
7797 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
7798 sprintf(varsel, "%s", varname3);
7799 else if (varname4 != NULL
7800 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
7801 sprintf(varsel, "%s", varname4);
7802 else if (varname5 != NULL
7803 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
7804 sprintf(varsel, "%s", varname5);
7805 else if (varname6 != NULL
7806 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
7807 sprintf(varsel, "%s", varname6);
7808 else
7809 return 0;
7810
7811 /* Read packed data... */
7812 if (ctl->met_nc_scale
7813 && nc_get_att_float(ncid, varid, "add_offset", &offset) == NC_NOERR
7814 && nc_get_att_float(ncid, varid, "scale_factor",
7815 &scalfac) == NC_NOERR) {
7816
7817 /* Allocate... */
7818 short *help;
7819 ALLOC(help, short,
7820 EX * EY * EP);
7821
7822 /* Read fill value and missing value... */
7823 short fillval, missval;
7824 if (nc_get_att_short(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
7825 fillval = 0;
7826 if (nc_get_att_short(ncid, varid, "missing_value", &missval) != NC_NOERR)
7827 missval = 0;
7828
7829 /* Write info... */
7830 LOG(2, "Read 2-D variable: %s"
7831 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
7832 varsel, fillval, missval, scalfac, offset);
7833
7834 /* Read data... */
7835 NC(nc_get_var_short(ncid, varid, help));
7836
7837 /* Check meteo data layout... */
7838 if (ctl->met_convention != 0)
7839 ERRMSG("Meteo data layout not implemented for packed netCDF files!");
7840
7841 /* Copy and check data... */
7842#pragma omp parallel for default(shared) num_threads(12)
7843 for (int ix = 0; ix < met->nx; ix++)
7844 for (int iy = 0; iy < met->ny; iy++) {
7845 if (init)
7846 dest[ix][iy] = 0;
7847 const short aux = help[ARRAY_2D(iy, ix, met->nx)];
7848 if ((fillval == 0 || aux != fillval)
7849 && (missval == 0 || aux != missval)
7850 && fabsf(aux * scalfac + offset) < 1e14f)
7851 dest[ix][iy] += scl * (aux * scalfac + offset);
7852 else
7853 dest[ix][iy] = NAN;
7854 }
7855
7856 /* Free... */
7857 free(help);
7858 }
7859
7860 /* Unpacked data... */
7861 else {
7862
7863 /* Allocate... */
7864 float *help;
7865 ALLOC(help, float,
7866 EX * EY);
7867
7868 /* Read fill value and missing value... */
7869 float fillval, missval;
7870 if (nc_get_att_float(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
7871 fillval = 0;
7872 if (nc_get_att_float(ncid, varid, "missing_value", &missval) != NC_NOERR)
7873 missval = 0;
7874
7875 /* Write info... */
7876 LOG(2, "Read 2-D variable: %s (FILL = %g, MISS = %g)",
7877 varsel, fillval, missval);
7878
7879 /* Read data... */
7880 NC(nc_get_var_float(ncid, varid, help));
7881
7882 /* Check meteo data layout... */
7883 if (ctl->met_convention == 0) {
7884
7885 /* Copy and check data (ordering: lat, lon)... */
7886#pragma omp parallel for default(shared) num_threads(12)
7887 for (int ix = 0; ix < met->nx; ix++)
7888 for (int iy = 0; iy < met->ny; iy++) {
7889 if (init)
7890 dest[ix][iy] = 0;
7891 const float aux = help[ARRAY_2D(iy, ix, met->nx)];
7892 if ((fillval == 0 || aux != fillval)
7893 && (missval == 0 || aux != missval)
7894 && fabsf(aux) < 1e14f)
7895 dest[ix][iy] += scl * aux;
7896 else
7897 dest[ix][iy] = NAN;
7898 }
7899
7900 } else {
7901
7902 /* Copy and check data (ordering: lon, lat)... */
7903#pragma omp parallel for default(shared) num_threads(12)
7904 for (int iy = 0; iy < met->ny; iy++)
7905 for (int ix = 0; ix < met->nx; ix++) {
7906 if (init)
7907 dest[ix][iy] = 0;
7908 const float aux = help[ARRAY_2D(ix, iy, met->ny)];
7909 if ((fillval == 0 || aux != fillval)
7910 && (missval == 0 || aux != missval)
7911 && fabsf(aux) < 1e14f)
7912 dest[ix][iy] += scl * aux;
7913 else
7914 dest[ix][iy] = NAN;
7915 }
7916 }
7917
7918 /* Free... */
7919 free(help);
7920 }
7921
7922 /* Return... */
7923 return 1;
7924}
int met_nc_scale
Check netCDF scaling factors (0=no, 1=yes).
Definition: mptrac.h:2576
int met_convention
Meteo data layout (0=[lev, lat, lon], 1=[lon, lat, lev]).
Definition: mptrac.h:2562

◆ read_met_nc_3d()

int read_met_nc_3d ( const int  ncid,
const char *  varname,
const char *  varname2,
const char *  varname3,
const char *  varname4,
const ctl_t ctl,
const met_t met,
float  dest[EX][EY][EP],
const float  scl 
)

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

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

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

The function performs the following steps:

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

Definition at line 7928 of file mptrac.c.

7937 {
7938
7939 char varsel[LEN];
7940
7941 float offset, scalfac;
7942
7943 int varid;
7944
7945 /* Check if variable exists... */
7946 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
7947 sprintf(varsel, "%s", varname);
7948 else if (varname2 != NULL
7949 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
7950 sprintf(varsel, "%s", varname2);
7951 else if (varname3 != NULL
7952 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
7953 sprintf(varsel, "%s", varname3);
7954 else if (varname4 != NULL
7955 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
7956 sprintf(varsel, "%s", varname4);
7957 else
7958 return 0;
7959
7960 /* Read packed data... */
7961 if (ctl->met_nc_scale
7962 && nc_get_att_float(ncid, varid, "add_offset", &offset) == NC_NOERR
7963 && nc_get_att_float(ncid, varid, "scale_factor",
7964 &scalfac) == NC_NOERR) {
7965
7966 /* Allocate... */
7967 short *help;
7968 ALLOC(help, short,
7969 EX * EY * EP);
7970
7971 /* Read fill value and missing value... */
7972 short fillval, missval;
7973 if (nc_get_att_short(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
7974 fillval = 0;
7975 if (nc_get_att_short(ncid, varid, "missing_value", &missval) != NC_NOERR)
7976 missval = 0;
7977
7978 /* Write info... */
7979 LOG(2, "Read 3-D variable: %s "
7980 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
7981 varsel, fillval, missval, scalfac, offset);
7982
7983 /* Read data... */
7984 NC(nc_get_var_short(ncid, varid, help));
7985
7986 /* Check meteo data layout... */
7987 if (ctl->met_convention != 0)
7988 ERRMSG("Meteo data layout not implemented for packed netCDF files!");
7989
7990 /* Copy and check data... */
7991#pragma omp parallel for default(shared) num_threads(12)
7992 for (int ix = 0; ix < met->nx; ix++)
7993 for (int iy = 0; iy < met->ny; iy++)
7994 for (int ip = 0; ip < met->np; ip++) {
7995 const short aux = help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)];
7996 if ((fillval == 0 || aux != fillval)
7997 && (missval == 0 || aux != missval)
7998 && fabsf(aux * scalfac + offset) < 1e14f)
7999 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
8000 else
8001 dest[ix][iy][ip] = NAN;
8002 }
8003
8004 /* Free... */
8005 free(help);
8006 }
8007
8008 /* Unpacked data... */
8009 else {
8010
8011 /* Allocate... */
8012 float *help;
8013 ALLOC(help, float,
8014 EX * EY * EP);
8015
8016 /* Read fill value and missing value... */
8017 float fillval, missval;
8018 if (nc_get_att_float(ncid, varid, "_FillValue", &fillval) != NC_NOERR)
8019 fillval = 0;
8020 if (nc_get_att_float(ncid, varid, "missing_value", &missval) != NC_NOERR)
8021 missval = 0;
8022
8023 /* Write info... */
8024 LOG(2, "Read 3-D variable: %s (FILL = %g, MISS = %g)",
8025 varsel, fillval, missval);
8026
8027 /* Read data... */
8028 NC(nc_get_var_float(ncid, varid, help));
8029
8030 /* Check meteo data layout... */
8031 if (ctl->met_convention == 0) {
8032
8033 /* Copy and check data (ordering: lev, lat, lon)... */
8034#pragma omp parallel for default(shared) num_threads(12)
8035 for (int ix = 0; ix < met->nx; ix++)
8036 for (int iy = 0; iy < met->ny; iy++)
8037 for (int ip = 0; ip < met->np; ip++) {
8038 const float aux = help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)];
8039 if ((fillval == 0 || aux != fillval)
8040 && (missval == 0 || aux != missval)
8041 && fabsf(aux) < 1e14f)
8042 dest[ix][iy][ip] = scl * aux;
8043 else
8044 dest[ix][iy][ip] = NAN;
8045 }
8046
8047 } else {
8048
8049 /* Copy and check data (ordering: lon, lat, lev)... */
8050#pragma omp parallel for default(shared) num_threads(12)
8051 for (int ip = 0; ip < met->np; ip++)
8052 for (int iy = 0; iy < met->ny; iy++)
8053 for (int ix = 0; ix < met->nx; ix++) {
8054 const float aux = help[ARRAY_3D(ix, iy, met->ny, ip, met->np)];
8055 if ((fillval == 0 || aux != fillval)
8056 && (missval == 0 || aux != missval)
8057 && fabsf(aux) < 1e14f)
8058 dest[ix][iy][ip] = scl * aux;
8059 else
8060 dest[ix][iy][ip] = NAN;
8061 }
8062 }
8063
8064 /* Free... */
8065 free(help);
8066 }
8067
8068 /* Return... */
8069 return 1;
8070}

◆ read_met_nc_grid()

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

Reads meteorological grid information from a NetCDF file.

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

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

The function performs the following steps:

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

Definition at line 8074 of file mptrac.c.

8078 {
8079
8080 char levname[LEN], tstr[10];
8081
8082 double rtime = 0, r, r2;
8083
8084 int varid, year2, mon2, day2, hour2, min2, sec2,
8085 year, mon, day, hour, min, sec;
8086
8087 size_t np;
8088
8089 /* Set timer... */
8090 SELECT_TIMER("READ_MET_NC_GRID", "INPUT", NVTX_READ);
8091 LOG(2, "Read meteo grid information...");
8092
8093 /* MPTRAC meteo files... */
8094 if (ctl->met_clams == 0) {
8095
8096 /* Get time from filename... */
8097 met->time = time_from_filename(filename, 16);
8098
8099 /* Check time information from data file... */
8100 jsec2time(met->time, &year, &mon, &day, &hour, &min, &sec, &r);
8101 if (nc_inq_varid(ncid, "time", &varid) == NC_NOERR) {
8102 NC(nc_get_var_double(ncid, varid, &rtime));
8103 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
8104 WARN("Time information in meteo file does not match filename!");
8105 } else
8106 WARN("Time information in meteo file is missing!");
8107 }
8108
8109 /* CLaMS meteo files... */
8110 else {
8111
8112 /* Read time from file... */
8113 NC_GET_DOUBLE("time", &rtime, 0);
8114
8115 /* Get time from filename (considering the century)... */
8116 if (rtime < 0)
8117 sprintf(tstr, "19%.2s", &filename[strlen(filename) - 11]);
8118 else
8119 sprintf(tstr, "20%.2s", &filename[strlen(filename) - 11]);
8120 year = atoi(tstr);
8121 sprintf(tstr, "%.2s", &filename[strlen(filename) - 9]);
8122 mon = atoi(tstr);
8123 sprintf(tstr, "%.2s", &filename[strlen(filename) - 7]);
8124 day = atoi(tstr);
8125 sprintf(tstr, "%.2s", &filename[strlen(filename) - 5]);
8126 hour = atoi(tstr);
8127 time2jsec(year, mon, day, hour, 0, 0, 0, &met->time);
8128 }
8129
8130 /* Check time... */
8131 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
8132 || day < 1 || day > 31 || hour < 0 || hour > 23)
8133 ERRMSG("Cannot read time from filename!");
8134 jsec2time(met->time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
8135 LOG(2, "Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
8136 met->time, year2, mon2, day2, hour2, min2);
8137
8138 /* Get grid dimensions... */
8139 NC_INQ_DIM("lon", &met->nx, 2, EX);
8140 LOG(2, "Number of longitudes: %d", met->nx);
8141
8142 NC_INQ_DIM("lat", &met->ny, 2, EY);
8143 LOG(2, "Number of latitudes: %d", met->ny);
8144
8145 int dimid2;
8146 sprintf(levname, "plev");
8147 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
8148 sprintf(levname, "lev");
8149 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
8150 sprintf(levname, "hybrid");
8151 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
8152 sprintf(levname, "hybrid_level");
8153
8154 NC_INQ_DIM(levname, &met->np, 1, EP);
8155 if (met->np == 1) {
8156 sprintf(levname, "lev_2");
8157 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR) {
8158 sprintf(levname, "plev");
8159 NC(nc_inq_dimid(ncid, levname, &dimid2));
8160 }
8161 NC(nc_inq_dimlen(ncid, dimid2, &np));
8162 met->np = (int) np;
8163 }
8164 LOG(2, "Number of levels: %d", met->np);
8165 if (met->np < 2 || met->np > EP)
8166 ERRMSG("Number of levels out of range!");
8167
8168 /* Read longitudes and latitudes... */
8169 NC_GET_DOUBLE("lon", met->lon, 1);
8170 LOG(2, "Longitudes: %g, %g ... %g deg",
8171 met->lon[0], met->lon[1], met->lon[met->nx - 1]);
8172 NC_GET_DOUBLE("lat", met->lat, 1);
8173 LOG(2, "Latitudes: %g, %g ... %g deg",
8174 met->lat[0], met->lat[1], met->lat[met->ny - 1]);
8175
8176 /* Check grid spacing... */
8177 for (int ix = 2; ix < met->nx; ix++)
8178 if (fabs
8179 (fabs(met->lon[ix] - met->lon[ix - 1]) -
8180 fabs(met->lon[1] - met->lon[0])) > 0.001)
8181 ERRMSG("No regular grid spacing in longitudes!");
8182 for (int iy = 2; iy < met->ny; iy++)
8183 if (fabs
8184 (fabs(met->lat[iy] - met->lat[iy - 1]) -
8185 fabs(met->lat[1] - met->lat[0])) > 0.001) {
8186 WARN("No regular grid spacing in latitudes!");
8187 break;
8188 }
8189
8190 /* Read pressure levels... */
8191 if (ctl->met_np <= 0) {
8192 NC_GET_DOUBLE(levname, met->p, 1);
8193 for (int ip = 0; ip < met->np; ip++)
8194 met->p[ip] /= 100.;
8195 LOG(2, "Altitude levels: %g, %g ... %g km",
8196 Z(met->p[0]), Z(met->p[1]), Z(met->p[met->np - 1]));
8197 LOG(2, "Pressure levels: %g, %g ... %g hPa",
8198 met->p[0], met->p[1], met->p[met->np - 1]);
8199 }
8200
8201 /* Read hybrid levels... */
8202 if (strcasecmp(levname, "hybrid") == 0)
8203 NC_GET_DOUBLE("hybrid", met->hybrid, 1);
8204}
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:9609
double time_from_filename(const char *filename, const int offset)
Extracts and converts a timestamp from a filename to Julian seconds.
Definition: mptrac.c:9708
Here is the call graph for this function:

◆ read_met_nc_levels()

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

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

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

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

The function performs the following steps:

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

Definition at line 8208 of file mptrac.c.

8211 {
8212
8213 /* Set timer... */
8214 SELECT_TIMER("READ_MET_NC_LEVELS", "INPUT", NVTX_READ);
8215 LOG(2, "Read level data...");
8216
8217 /* Read temperature... */
8218 if (!read_met_nc_3d(ncid, "t", "T", "temp", "TEMP", ctl, met, met->t, 1.0))
8219 ERRMSG("Cannot read temperature!");
8220
8221 /* Read horizontal wind and vertical velocity... */
8222 if (!read_met_nc_3d(ncid, "u", "U", NULL, NULL, ctl, met, met->u, 1.0))
8223 ERRMSG("Cannot read zonal wind!");
8224 if (!read_met_nc_3d(ncid, "v", "V", NULL, NULL, ctl, met, met->v, 1.0))
8225 ERRMSG("Cannot read meridional wind!");
8226 if (!read_met_nc_3d
8227 (ncid, "w", "W", "omega", "OMEGA", ctl, met, met->w, 0.01f))
8228 WARN("Cannot read vertical velocity!");
8229
8230 /* Read water vapor... */
8231 if (!ctl->met_relhum) {
8232 if (!read_met_nc_3d
8233 (ncid, "q", "Q", "sh", "SH", ctl, met, met->h2o, (float) (MA / MH2O)))
8234 WARN("Cannot read specific humidity!");
8235 } else {
8236 if (!read_met_nc_3d
8237 (ncid, "rh", "RH", NULL, NULL, ctl, met, met->h2o, 0.01f))
8238 WARN("Cannot read relative humidity!");
8239#pragma omp parallel for default(shared) collapse(2)
8240 for (int ix = 0; ix < met->nx; ix++)
8241 for (int iy = 0; iy < met->ny; iy++)
8242 for (int ip = 0; ip < met->np; ip++) {
8243 double pw = met->h2o[ix][iy][ip] * PSAT(met->t[ix][iy][ip]);
8244 met->h2o[ix][iy][ip] =
8245 (float) (pw / (met->p[ip] - (1.0 - EPS) * pw));
8246 }
8247 }
8248
8249 /* Read ozone... */
8250 if (!read_met_nc_3d
8251 (ncid, "o3", "O3", NULL, NULL, ctl, met, met->o3, (float) (MA / MO3)))
8252 WARN("Cannot read ozone data!");
8253
8254 /* Read cloud data... */
8255 if (!read_met_nc_3d
8256 (ncid, "clwc", "CLWC", NULL, NULL, ctl, met, met->lwc, 1.0))
8257 WARN("Cannot read cloud liquid water content!");
8258 if (!read_met_nc_3d
8259 (ncid, "crwc", "CRWC", NULL, NULL, ctl, met, met->rwc, 1.0))
8260 WARN("Cannot read cloud rain water content!");
8261 if (!read_met_nc_3d
8262 (ncid, "ciwc", "CIWC", NULL, NULL, ctl, met, met->iwc, 1.0))
8263 WARN("Cannot read cloud ice water content!");
8264 if (!read_met_nc_3d
8265 (ncid, "cswc", "CSWC", NULL, NULL, ctl, met, met->swc, 1.0))
8266 WARN("Cannot read cloud snow water content!");
8267 if (!read_met_nc_3d(ncid, "cc", "CC", NULL, NULL, ctl, met, met->cc, 1.0))
8268 WARN("Cannot read cloud cover!");
8269
8270 /* Read zeta and zeta_dot... */
8271 if (!read_met_nc_3d
8272 (ncid, "ZETA", "zeta", NULL, NULL, ctl, met, met->zetal, 1.0))
8273 WARN("Cannot read ZETA!");
8274 if (!read_met_nc_3d
8275 (ncid, "ZETA_DOT_TOT", "ZETA_DOT_clr", "zeta_dot_clr",
8276 NULL, ctl, met, met->zeta_dotl, 0.00001157407f))
8277 WARN("Cannot read ZETA_DOT!");
8278
8279 /* Store velocities on model levels... */
8280 if (ctl->met_vert_coord != 0) {
8281 for (int ix = 0; ix < met->nx; ix++)
8282 for (int iy = 0; iy < met->ny; iy++)
8283 for (int ip = 0; ip < met->np; ip++) {
8284 met->ul[ix][iy][ip] = met->u[ix][iy][ip];
8285 met->vl[ix][iy][ip] = met->v[ix][iy][ip];
8286 met->wl[ix][iy][ip] = met->w[ix][iy][ip];
8287 }
8288
8289 /* Save number of model levels... */
8290 met->npl = met->np;
8291 }
8292
8293 /* Get pressure on model levels... */
8294 if (ctl->met_np > 0 || ctl->met_vert_coord != 0) {
8295
8296 /* Read 3-D pressure field... */
8297 if (ctl->met_vert_coord == 1) {
8298 if (!read_met_nc_3d
8299 (ncid, "pl", "PL", "pressure", "PRESSURE", ctl, met, met->pl,
8300 0.01f))
8301 if (!read_met_nc_3d
8302 (ncid, "press", "PRESS", NULL, NULL, ctl, met, met->pl, 1.0))
8303 ERRMSG("Cannot read pressure on model levels!");
8304 }
8305
8306 /* Use a and b coefficients for full levels... */
8307 else if (ctl->met_vert_coord == 2 || ctl->met_vert_coord == 3) {
8308
8309 /* Grid level coefficients... */
8310 double hyam[EP], hybm[EP];
8311
8312 /* Read coefficients from file... */
8313 if (ctl->met_vert_coord == 2) {
8314 int varid;
8315 if (nc_inq_varid(ncid, "hyam", &varid) == NC_NOERR
8316 && nc_inq_varid(ncid, "hybm", &varid) == NC_NOERR) {
8317 NC_GET_DOUBLE("hyam", hyam, 1);
8318 NC_GET_DOUBLE("hybm", hybm, 1);
8319 } else if (nc_inq_varid(ncid, "a_hybrid_level", &varid) == NC_NOERR
8320 && nc_inq_varid(ncid, "b_hybrid_level",
8321 &varid) == NC_NOERR) {
8322 NC_GET_DOUBLE("a_hybrid_level", hyam, 1);
8323 NC_GET_DOUBLE("b_hybrid_level", hybm, 1);
8324 } else
8325 ERRMSG("Cannot read a and b level coefficients from netCDF file!");
8326 }
8327
8328 /* Use control parameters... */
8329 else if (ctl->met_vert_coord == 3) {
8330
8331 /* Check number of levels... */
8332 if (met->np != ctl->met_nlev)
8333 ERRMSG("Mismatch in number of model levels!");
8334
8335 /* Copy parameters... */
8336 for (int ip = 0; ip < met->np; ip++) {
8337 hyam[ip] = ctl->met_lev_hyam[ip];
8338 hybm[ip] = ctl->met_lev_hybm[ip];
8339 }
8340 }
8341
8342 /* Calculate pressure... */
8343 for (int ix = 0; ix < met->nx; ix++)
8344 for (int iy = 0; iy < met->ny; iy++)
8345 for (int ip = 0; ip < met->np; ip++)
8346 met->pl[ix][iy][ip] =
8347 (float) (hyam[ip] / 100. + hybm[ip] * met->ps[ix][iy]);
8348 }
8349
8350 /* Use a and b coefficients for half levels... */
8351 else if (ctl->met_vert_coord == 4) {
8352
8353 /* Grid level coefficients... */
8354 double hyam[EP], hybm[EP];
8355
8356 /* Use control parameters... */
8357 for (int ip = 0; ip < met->np + 1; ip++) {
8358 hyam[ip] = ctl->met_lev_hyam[ip];
8359 hybm[ip] = ctl->met_lev_hybm[ip];
8360 }
8361
8362 /* Check number of levels... */
8363 if (met->np + 1 != ctl->met_nlev)
8364 ERRMSG("Mismatch in number of model levels!");
8365
8366 /* Calculate pressure... */
8367#pragma omp parallel for default(shared) collapse(2)
8368 for (int ix = 0; ix < met->nx; ix++)
8369 for (int iy = 0; iy < met->ny; iy++)
8370 for (int ip = 0; ip < met->np; ip++) {
8371 double p0 = hyam[ip] / 100. + hybm[ip] * met->ps[ix][iy];
8372 double p1 = hyam[ip + 1] / 100. + hybm[ip + 1] * met->ps[ix][iy];
8373 met->pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
8374 }
8375 }
8376
8377 /* Check ordering of pressure levels... */
8378 for (int ix = 0; ix < met->nx; ix++)
8379 for (int iy = 0; iy < met->ny; iy++)
8380 for (int ip = 1; ip < met->np; ip++)
8381 if ((met->pl[ix][iy][0] > met->pl[ix][iy][1]
8382 && met->pl[ix][iy][ip - 1] <= met->pl[ix][iy][ip])
8383 || (met->pl[ix][iy][0] < met->pl[ix][iy][1]
8384 && met->pl[ix][iy][ip - 1] >= met->pl[ix][iy][ip]))
8385 ERRMSG("Pressure profiles are not monotonic!");
8386 }
8387
8388 /* Interpolate from model levels to pressure levels... */
8389 if (ctl->met_np > 0) {
8390
8391 /* Check pressure on model levels... */
8392 if (met->pl[0][0][0] <= 0)
8393 ERRMSG("Pressure on model levels is missing, check MET_VERT_COORD!");
8394
8395 /* Interpolate variables... */
8396 read_met_ml2pl(ctl, met, met->t, "T");
8397 read_met_ml2pl(ctl, met, met->u, "U");
8398 read_met_ml2pl(ctl, met, met->v, "V");
8399 read_met_ml2pl(ctl, met, met->w, "W");
8400 read_met_ml2pl(ctl, met, met->h2o, "H2O");
8401 read_met_ml2pl(ctl, met, met->o3, "O3");
8402 read_met_ml2pl(ctl, met, met->lwc, "LWC");
8403 read_met_ml2pl(ctl, met, met->rwc, "RWC");
8404 read_met_ml2pl(ctl, met, met->iwc, "IWC");
8405 read_met_ml2pl(ctl, met, met->swc, "SWC");
8406 read_met_ml2pl(ctl, met, met->cc, "CC");
8407
8408 /* Set new pressure levels... */
8409 met->np = ctl->met_np;
8410 for (int ip = 0; ip < met->np; ip++)
8411 met->p[ip] = ctl->met_p[ip];
8412 }
8413
8414 /* Check ordering of pressure levels... */
8415 for (int ip = 1; ip < met->np; ip++)
8416 if (met->p[ip - 1] < met->p[ip])
8417 ERRMSG("Pressure levels must be descending!");
8418}
void read_met_ml2pl(const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname)
Reads global meteorological information from a grib file.
Definition: mptrac.c:7612
int read_met_nc_3d(const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const ctl_t *ctl, const met_t *met, float dest[EX][EY][EP], const float scl)
Reads a 3-dimensional meteorological variable from a NetCDF file.
Definition: mptrac.c:7928
#define MH2O
Molar mass of water vapor [g/mol].
Definition: mptrac.h:224
#define MO3
Molar mass of ozone [g/mol].
Definition: mptrac.h:229
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:2566
Here is the call graph for this function:

◆ read_met_nc_surface()

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

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

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

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

The function performs the following steps:

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

Definition at line 8422 of file mptrac.c.

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

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

8560 {
8561
8562 /* Set timer... */
8563 SELECT_TIMER("READ_MET_PBL", "METPROC", NVTX_READ);
8564 LOG(2, "Calculate planetary boundary layer...");
8565
8566 /* Convert PBL height from meteo file to pressure... */
8567 if (ctl->met_pbl == 1) {
8568
8569 /* Loop over grid points... */
8570#pragma omp parallel for default(shared) collapse(2)
8571 for (int ix = 0; ix < met->nx; ix++)
8572 for (int iy = 0; iy < met->ny; iy++) {
8573
8574 /* Get pressure at top of PBL... */
8575 const float z = met->zs[ix][iy] + met->pbl[ix][iy];
8576 const int ip = locate_irr_float(met->z[ix][iy], met->np, z, 0);
8577 met->pbl[ix][iy] =
8578 (float) (LIN(met->z[ix][iy][ip], met->p[ip],
8579 met->z[ix][iy][ip + 1], met->p[ip + 1], z));
8580 }
8581 }
8582
8583 /* Determine PBL based on Richardson number... */
8584 else if (ctl->met_pbl == 2) {
8585
8586 /* Parameters used to estimate the height of the PBL
8587 (e.g., Vogelezang and Holtslag, 1996; Seidel et al., 2012)... */
8588 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
8589
8590 /* Loop over grid points... */
8591#pragma omp parallel for default(shared) collapse(2)
8592 for (int ix = 0; ix < met->nx; ix++)
8593 for (int iy = 0; iy < met->ny; iy++) {
8594
8595 /* Set bottom level of PBL... */
8596 const double pbl_bot = met->ps[ix][iy] * exp(-dz / H0);
8597
8598 /* Find lowest level near the bottom... */
8599 int ip;
8600 for (ip = 1; ip < met->np; ip++)
8601 if (met->p[ip] < pbl_bot)
8602 break;
8603
8604 /* Get near surface data... */
8605 const double h2os = LIN(met->p[ip - 1], met->h2o[ix][iy][ip - 1],
8606 met->p[ip], met->h2o[ix][iy][ip], pbl_bot);
8607 const double tvs = THETAVIRT(pbl_bot, met->ts[ix][iy], h2os);
8608
8609 /* Init... */
8610 double rib_old = 0;
8611
8612 /* Loop over levels... */
8613 for (; ip < met->np; ip++) {
8614
8615 /* Get squared horizontal wind speed... */
8616 double vh2 = SQR(met->u[ix][iy][ip] - met->us[ix][iy])
8617 + SQR(met->v[ix][iy][ip] - met->vs[ix][iy]);
8618 vh2 = MAX(vh2, SQR(umin));
8619
8620 /* Calculate bulk Richardson number... */
8621 const double rib =
8622 G0 * 1e3 * (met->z[ix][iy][ip] - met->zs[ix][iy]) / tvs
8623 * (THETAVIRT(met->p[ip], met->t[ix][iy][ip],
8624 met->h2o[ix][iy][ip]) - tvs) / vh2;
8625
8626 /* Check for critical value... */
8627 if (rib >= rib_crit) {
8628 met->pbl[ix][iy] = (float) (LIN(rib_old, met->p[ip - 1],
8629 rib, met->p[ip], rib_crit));
8630 if (met->pbl[ix][iy] > pbl_bot)
8631 met->pbl[ix][iy] = (float) pbl_bot;
8632 break;
8633 }
8634
8635 /* Save Richardson number... */
8636 rib_old = rib;
8637 }
8638 }
8639 }
8640
8641 /* Determine PBL based on potential temperature... */
8642 if (ctl->met_pbl == 3) {
8643
8644 /* Parameters used to estimate the height of the PBL
8645 (following HYSPLIT model)... */
8646 const double dtheta = 2.0, zmin = 0.1;
8647
8648 /* Loop over grid points... */
8649#pragma omp parallel for default(shared) collapse(2)
8650 for (int ix = 0; ix < met->nx; ix++)
8651 for (int iy = 0; iy < met->ny; iy++) {
8652
8653 /* Potential temperature at the surface... */
8654 const double theta0 = THETA(met->ps[ix][iy], met->ts[ix][iy]);
8655
8656 /* Find topmost level where theta exceeds surface value by 2 K... */
8657 int ip;
8658 for (ip = met->np - 2; ip > 0; ip--)
8659 if (met->p[ip] >= 300.)
8660 if (met->p[ip] > met->ps[ix][iy]
8661 || THETA(met->p[ip], met->t[ix][iy][ip]) <= theta0 + dtheta)
8662 break;
8663
8664 /* Interpolate... */
8665 met->pbl[ix][iy]
8666 = (float) (LIN(THETA(met->p[ip + 1], met->t[ix][iy][ip + 1]),
8667 met->p[ip + 1],
8668 THETA(met->p[ip], met->t[ix][iy][ip]),
8669 met->p[ip], theta0 + dtheta));
8670
8671 /* Check minimum value... */
8672 double pbl_min = met->ps[ix][iy] * exp(-zmin / H0);
8673 if (met->pbl[ix][iy] > pbl_min || met->p[ip] > met->ps[ix][iy])
8674 met->pbl[ix][iy] = (float) pbl_min;
8675 }
8676 }
8677
8678 /* Loop over grid points... */
8679#pragma omp parallel for default(shared) collapse(2)
8680 for (int ix = 0; ix < met->nx; ix++)
8681 for (int iy = 0; iy < met->ny; iy++) {
8682
8683 /* Check minimum value... */
8684 double pbl_min = met->ps[ix][iy] * exp(-ctl->met_pbl_min / H0);
8685 met->pbl[ix][iy] = MIN(met->pbl[ix][iy], (float) pbl_min);
8686
8687 /* Check maximum value... */
8688 double pbl_max = met->ps[ix][iy] * exp(-ctl->met_pbl_max / H0);
8689 met->pbl[ix][iy] = MAX(met->pbl[ix][iy], (float) pbl_max);
8690 }
8691}
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 8695 of file mptrac.c.

8696 {
8697
8698 /* Set timer... */
8699 SELECT_TIMER("READ_MET_PERIODIC", "METPROC", NVTX_READ);
8700 LOG(2, "Apply periodic boundary conditions...");
8701
8702 /* Check longitudes... */
8703 if (!(fabs(met->lon[met->nx - 1] - met->lon[0]
8704 + met->lon[1] - met->lon[0] - 360) < 0.01))
8705 return;
8706
8707 /* Increase longitude counter... */
8708 if ((++met->nx) >= EX)
8709 ERRMSG("Cannot create periodic boundary conditions!");
8710
8711 /* Set longitude... */
8712 met->lon[met->nx - 1] = met->lon[met->nx - 2] + met->lon[1] - met->lon[0];
8713
8714 /* Loop over latitudes and pressure levels... */
8715#pragma omp parallel for default(shared)
8716 for (int iy = 0; iy < met->ny; iy++) {
8717 met->ps[met->nx - 1][iy] = met->ps[0][iy];
8718 met->zs[met->nx - 1][iy] = met->zs[0][iy];
8719 met->ts[met->nx - 1][iy] = met->ts[0][iy];
8720 met->us[met->nx - 1][iy] = met->us[0][iy];
8721 met->vs[met->nx - 1][iy] = met->vs[0][iy];
8722 met->ess[met->nx - 1][iy] = met->ess[0][iy];
8723 met->nss[met->nx - 1][iy] = met->nss[0][iy];
8724 met->shf[met->nx - 1][iy] = met->shf[0][iy];
8725 met->lsm[met->nx - 1][iy] = met->lsm[0][iy];
8726 met->sst[met->nx - 1][iy] = met->sst[0][iy];
8727 met->pbl[met->nx - 1][iy] = met->pbl[0][iy];
8728 met->cape[met->nx - 1][iy] = met->cape[0][iy];
8729 met->cin[met->nx - 1][iy] = met->cin[0][iy];
8730 for (int ip = 0; ip < met->np; ip++) {
8731 met->t[met->nx - 1][iy][ip] = met->t[0][iy][ip];
8732 met->u[met->nx - 1][iy][ip] = met->u[0][iy][ip];
8733 met->v[met->nx - 1][iy][ip] = met->v[0][iy][ip];
8734 met->w[met->nx - 1][iy][ip] = met->w[0][iy][ip];
8735 met->h2o[met->nx - 1][iy][ip] = met->h2o[0][iy][ip];
8736 met->o3[met->nx - 1][iy][ip] = met->o3[0][iy][ip];
8737 met->lwc[met->nx - 1][iy][ip] = met->lwc[0][iy][ip];
8738 met->rwc[met->nx - 1][iy][ip] = met->rwc[0][iy][ip];
8739 met->iwc[met->nx - 1][iy][ip] = met->iwc[0][iy][ip];
8740 met->swc[met->nx - 1][iy][ip] = met->swc[0][iy][ip];
8741 met->cc[met->nx - 1][iy][ip] = met->cc[0][iy][ip];
8742 }
8743 for (int ip = 0; ip < met->npl; ip++) {
8744 met->ul[met->nx - 1][iy][ip] = met->ul[0][iy][ip];
8745 met->vl[met->nx - 1][iy][ip] = met->vl[0][iy][ip];
8746 met->wl[met->nx - 1][iy][ip] = met->wl[0][iy][ip];
8747 met->pl[met->nx - 1][iy][ip] = met->pl[0][iy][ip];
8748 met->zetal[met->nx - 1][iy][ip] = met->zetal[0][iy][ip];
8749 met->zeta_dotl[met->nx - 1][iy][ip] = met->zeta_dotl[0][iy][ip];
8750 }
8751 }
8752}

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

8757 {
8758
8759 /* Set timer... */
8760 SELECT_TIMER("READ_MET_POLAR_WINDS", "METPROC", NVTX_READ);
8761 LOG(2, "Apply fix for polar winds...");
8762
8763 /* Check latitudes... */
8764 if (fabs(met->lat[0]) < 89.999 || fabs(met->lat[met->ny - 1]) < 89.999)
8765 return;
8766
8767 /* Loop over hemispheres... */
8768 for (int ihem = 0; ihem < 2; ihem++) {
8769
8770 /* Set latitude indices... */
8771 int i89 = 1, i90 = 0, sign = 1;
8772 if (ihem == 1) {
8773 i89 = met->ny - 2;
8774 i90 = met->ny - 1;
8775 }
8776 if (met->lat[i90] < 0)
8777 sign = -1;
8778
8779 /* Look-up table of cosinus and sinus... */
8780 double clon[EX], slon[EX];
8781#pragma omp parallel for default(shared)
8782 for (int ix = 0; ix < met->nx; ix++) {
8783 clon[ix] = cos(sign * DEG2RAD(met->lon[ix]));
8784 slon[ix] = sin(sign * DEG2RAD(met->lon[ix]));
8785 }
8786
8787 /* Loop over levels... */
8788#pragma omp parallel for default(shared)
8789 for (int ip = 0; ip < met->np; ip++) {
8790
8791 /* Transform 89 degree u and v winds into Cartesian coordinates and take the mean... */
8792 double vel89x = 0, vel89y = 0;
8793 for (int ix = 0; ix < met->nx; ix++) {
8794 vel89x +=
8795 (met->u[ix][i89][ip] * clon[ix] -
8796 met->v[ix][i89][ip] * slon[ix]) / met->nx;
8797 vel89y +=
8798 (met->u[ix][i89][ip] * slon[ix] +
8799 met->v[ix][i89][ip] * clon[ix]) / met->nx;
8800 }
8801
8802 /* Replace 90 degree winds by 89 degree mean... */
8803 for (int ix = 0; ix < met->nx; ix++) {
8804 met->u[ix][i90][ip]
8805 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
8806 met->v[ix][i90][ip]
8807 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
8808 }
8809 }
8810 }
8811}

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

8816 {
8817
8818 double pows[EP];
8819
8820 /* Set timer... */
8821 SELECT_TIMER("READ_MET_PV", "METPROC", NVTX_READ);
8822 LOG(2, "Calculate potential vorticity...");
8823
8824 /* Set powers... */
8825#pragma omp parallel for default(shared)
8826 for (int ip = 0; ip < met->np; ip++)
8827 pows[ip] = pow(1000. / met->p[ip], 0.286);
8828
8829 /* Loop over grid points... */
8830#pragma omp parallel for default(shared)
8831 for (int ix = 0; ix < met->nx; ix++) {
8832
8833 /* Set indices... */
8834 const int ix0 = MAX(ix - 1, 0);
8835 const int ix1 = MIN(ix + 1, met->nx - 1);
8836
8837 /* Loop over grid points... */
8838 for (int iy = 0; iy < met->ny; iy++) {
8839
8840 /* Set indices... */
8841 const int iy0 = MAX(iy - 1, 0);
8842 const int iy1 = MIN(iy + 1, met->ny - 1);
8843
8844 /* Set auxiliary variables... */
8845 const double latr = 0.5 * (met->lat[iy1] + met->lat[iy0]);
8846 const double dx = 1000. * DEG2DX(met->lon[ix1] - met->lon[ix0], latr);
8847 const double dy = 1000. * DEG2DY(met->lat[iy1] - met->lat[iy0]);
8848 const double c0 = cos(DEG2RAD(met->lat[iy0]));
8849 const double c1 = cos(DEG2RAD(met->lat[iy1]));
8850 const double cr = cos(DEG2RAD(latr));
8851 const double vort = 2 * 7.2921e-5 * sin(DEG2RAD(latr));
8852
8853 /* Loop over grid points... */
8854 for (int ip = 0; ip < met->np; ip++) {
8855
8856 /* Get gradients in longitude... */
8857 const double dtdx
8858 = (met->t[ix1][iy][ip] - met->t[ix0][iy][ip]) * pows[ip] / dx;
8859 const double dvdx = (met->v[ix1][iy][ip] - met->v[ix0][iy][ip]) / dx;
8860
8861 /* Get gradients in latitude... */
8862 const double dtdy
8863 = (met->t[ix][iy1][ip] - met->t[ix][iy0][ip]) * pows[ip] / dy;
8864 const double dudy
8865 = (met->u[ix][iy1][ip] * c1 - met->u[ix][iy0][ip] * c0) / dy;
8866
8867 /* Set indices... */
8868 const int ip0 = MAX(ip - 1, 0);
8869 const int ip1 = MIN(ip + 1, met->np - 1);
8870
8871 /* Get gradients in pressure... */
8872 double dtdp, dudp, dvdp;
8873 const double dp0 = 100. * (met->p[ip] - met->p[ip0]);
8874 const double dp1 = 100. * (met->p[ip1] - met->p[ip]);
8875 if (ip != ip0 && ip != ip1) {
8876 double denom = dp0 * dp1 * (dp0 + dp1);
8877 dtdp = (dp0 * dp0 * met->t[ix][iy][ip1] * pows[ip1]
8878 - dp1 * dp1 * met->t[ix][iy][ip0] * pows[ip0]
8879 + (dp1 * dp1 - dp0 * dp0) * met->t[ix][iy][ip] * pows[ip])
8880 / denom;
8881 dudp = (dp0 * dp0 * met->u[ix][iy][ip1]
8882 - dp1 * dp1 * met->u[ix][iy][ip0]
8883 + (dp1 * dp1 - dp0 * dp0) * met->u[ix][iy][ip])
8884 / denom;
8885 dvdp = (dp0 * dp0 * met->v[ix][iy][ip1]
8886 - dp1 * dp1 * met->v[ix][iy][ip0]
8887 + (dp1 * dp1 - dp0 * dp0) * met->v[ix][iy][ip])
8888 / denom;
8889 } else {
8890 const double denom = dp0 + dp1;
8891 dtdp =
8892 (met->t[ix][iy][ip1] * pows[ip1] -
8893 met->t[ix][iy][ip0] * pows[ip0]) / denom;
8894 dudp = (met->u[ix][iy][ip1] - met->u[ix][iy][ip0]) / denom;
8895 dvdp = (met->v[ix][iy][ip1] - met->v[ix][iy][ip0]) / denom;
8896 }
8897
8898 /* Calculate PV... */
8899 met->pv[ix][iy][ip] = (float)
8900 (1e6 * G0 *
8901 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
8902 }
8903 }
8904 }
8905
8906 /* Fix for polar regions... */
8907#pragma omp parallel for default(shared)
8908 for (int ix = 0; ix < met->nx; ix++)
8909 for (int ip = 0; ip < met->np; ip++) {
8910 met->pv[ix][0][ip]
8911 = met->pv[ix][1][ip]
8912 = met->pv[ix][2][ip];
8913 met->pv[ix][met->ny - 1][ip]
8914 = met->pv[ix][met->ny - 2][ip]
8915 = met->pv[ix][met->ny - 3][ip];
8916 }
8917}
#define DEG2DY(dlat)
Convert a latitude difference to a distance in the y-direction (north-south).
Definition: mptrac.h:483
#define DEG2DX(dlon, lat)
Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude.
Definition: mptrac.h:462

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

8922 {
8923
8924 /* Set timer... */
8925 SELECT_TIMER("READ_MET_OZONE", "METPROC", NVTX_READ);
8926 LOG(2, "Calculate total column ozone...");
8927
8928 /* Loop over columns... */
8929#pragma omp parallel for default(shared) collapse(2)
8930 for (int ix = 0; ix < met->nx; ix++)
8931 for (int iy = 0; iy < met->ny; iy++) {
8932
8933 /* Integrate... */
8934 double cd = 0;
8935 for (int ip = 1; ip < met->np; ip++)
8936 if (met->p[ip - 1] <= met->ps[ix][iy]) {
8937 const double vmr =
8938 0.5 * (met->o3[ix][iy][ip - 1] + met->o3[ix][iy][ip]);
8939 const double dp = met->p[ip - 1] - met->p[ip];
8940 cd += vmr * MO3 / MA * dp * 1e2 / G0;
8941 }
8942
8943 /* Convert to Dobson units... */
8944 met->o3c[ix][iy] = (float) (cd / 2.1415e-5);
8945 }
8946}

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

8952 {
8953
8954 met_t *help;
8955
8956 /* Check parameters... */
8957 if (ctl->met_dp <= 1 && ctl->met_dx <= 1 && ctl->met_dy <= 1
8958 && ctl->met_sp <= 1 && ctl->met_sx <= 1 && ctl->met_sy <= 1)
8959 return;
8960
8961 /* Set timer... */
8962 SELECT_TIMER("READ_MET_SAMPLE", "METPROC", NVTX_READ);
8963 LOG(2, "Downsampling of meteo data...");
8964
8965 /* Allocate... */
8966 ALLOC(help, met_t, 1);
8967
8968 /* Copy data... */
8969 help->nx = met->nx;
8970 help->ny = met->ny;
8971 help->np = met->np;
8972 memcpy(help->lon, met->lon, sizeof(met->lon));
8973 memcpy(help->lat, met->lat, sizeof(met->lat));
8974 memcpy(help->p, met->p, sizeof(met->p));
8975
8976 /* Smoothing... */
8977 for (int ix = 0; ix < met->nx; ix += ctl->met_dx) {
8978 for (int iy = 0; iy < met->ny; iy += ctl->met_dy) {
8979 for (int ip = 0; ip < met->np; ip += ctl->met_dp) {
8980 help->ps[ix][iy] = 0;
8981 help->zs[ix][iy] = 0;
8982 help->ts[ix][iy] = 0;
8983 help->us[ix][iy] = 0;
8984 help->vs[ix][iy] = 0;
8985 help->ess[ix][iy] = 0;
8986 help->nss[ix][iy] = 0;
8987 help->shf[ix][iy] = 0;
8988 help->lsm[ix][iy] = 0;
8989 help->sst[ix][iy] = 0;
8990 help->pbl[ix][iy] = 0;
8991 help->cape[ix][iy] = 0;
8992 help->cin[ix][iy] = 0;
8993 help->t[ix][iy][ip] = 0;
8994 help->u[ix][iy][ip] = 0;
8995 help->v[ix][iy][ip] = 0;
8996 help->w[ix][iy][ip] = 0;
8997 help->h2o[ix][iy][ip] = 0;
8998 help->o3[ix][iy][ip] = 0;
8999 help->lwc[ix][iy][ip] = 0;
9000 help->rwc[ix][iy][ip] = 0;
9001 help->iwc[ix][iy][ip] = 0;
9002 help->swc[ix][iy][ip] = 0;
9003 help->cc[ix][iy][ip] = 0;
9004 float wsum = 0;
9005 for (int ix2 = ix - ctl->met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
9006 ix2++) {
9007 int ix3 = ix2;
9008 if (ix3 < 0)
9009 ix3 += met->nx;
9010 else if (ix3 >= met->nx)
9011 ix3 -= met->nx;
9012
9013 for (int iy2 = MAX(iy - ctl->met_sy + 1, 0);
9014 iy2 <= MIN(iy + ctl->met_sy - 1, met->ny - 1); iy2++)
9015 for (int ip2 = MAX(ip - ctl->met_sp + 1, 0);
9016 ip2 <= MIN(ip + ctl->met_sp - 1, met->np - 1); ip2++) {
9017 float w = (1.0f - (float) abs(ix - ix2) / (float) ctl->met_sx)
9018 * (1.0f - (float) abs(iy - iy2) / (float) ctl->met_sy)
9019 * (1.0f - (float) abs(ip - ip2) / (float) ctl->met_sp);
9020 help->ps[ix][iy] += w * met->ps[ix3][iy2];
9021 help->zs[ix][iy] += w * met->zs[ix3][iy2];
9022 help->ts[ix][iy] += w * met->ts[ix3][iy2];
9023 help->us[ix][iy] += w * met->us[ix3][iy2];
9024 help->vs[ix][iy] += w * met->vs[ix3][iy2];
9025 help->ess[ix][iy] += w * met->ess[ix3][iy2];
9026 help->nss[ix][iy] += w * met->nss[ix3][iy2];
9027 help->shf[ix][iy] += w * met->shf[ix3][iy2];
9028 help->lsm[ix][iy] += w * met->lsm[ix3][iy2];
9029 help->sst[ix][iy] += w * met->sst[ix3][iy2];
9030 help->pbl[ix][iy] += w * met->pbl[ix3][iy2];
9031 help->cape[ix][iy] += w * met->cape[ix3][iy2];
9032 help->cin[ix][iy] += w * met->cin[ix3][iy2];
9033 help->t[ix][iy][ip] += w * met->t[ix3][iy2][ip2];
9034 help->u[ix][iy][ip] += w * met->u[ix3][iy2][ip2];
9035 help->v[ix][iy][ip] += w * met->v[ix3][iy2][ip2];
9036 help->w[ix][iy][ip] += w * met->w[ix3][iy2][ip2];
9037 help->h2o[ix][iy][ip] += w * met->h2o[ix3][iy2][ip2];
9038 help->o3[ix][iy][ip] += w * met->o3[ix3][iy2][ip2];
9039 help->lwc[ix][iy][ip] += w * met->lwc[ix3][iy2][ip2];
9040 help->rwc[ix][iy][ip] += w * met->rwc[ix3][iy2][ip2];
9041 help->iwc[ix][iy][ip] += w * met->iwc[ix3][iy2][ip2];
9042 help->swc[ix][iy][ip] += w * met->swc[ix3][iy2][ip2];
9043 help->cc[ix][iy][ip] += w * met->cc[ix3][iy2][ip2];
9044 wsum += w;
9045 }
9046 }
9047 help->ps[ix][iy] /= wsum;
9048 help->zs[ix][iy] /= wsum;
9049 help->ts[ix][iy] /= wsum;
9050 help->us[ix][iy] /= wsum;
9051 help->vs[ix][iy] /= wsum;
9052 help->ess[ix][iy] /= wsum;
9053 help->nss[ix][iy] /= wsum;
9054 help->shf[ix][iy] /= wsum;
9055 help->lsm[ix][iy] /= wsum;
9056 help->sst[ix][iy] /= wsum;
9057 help->pbl[ix][iy] /= wsum;
9058 help->cape[ix][iy] /= wsum;
9059 help->cin[ix][iy] /= wsum;
9060 help->t[ix][iy][ip] /= wsum;
9061 help->u[ix][iy][ip] /= wsum;
9062 help->v[ix][iy][ip] /= wsum;
9063 help->w[ix][iy][ip] /= wsum;
9064 help->h2o[ix][iy][ip] /= wsum;
9065 help->o3[ix][iy][ip] /= wsum;
9066 help->lwc[ix][iy][ip] /= wsum;
9067 help->rwc[ix][iy][ip] /= wsum;
9068 help->iwc[ix][iy][ip] /= wsum;
9069 help->swc[ix][iy][ip] /= wsum;
9070 help->cc[ix][iy][ip] /= wsum;
9071 }
9072 }
9073 }
9074
9075 /* Downsampling... */
9076 met->nx = 0;
9077 for (int ix = 0; ix < help->nx; ix += ctl->met_dx) {
9078 met->lon[met->nx] = help->lon[ix];
9079 met->ny = 0;
9080 for (int iy = 0; iy < help->ny; iy += ctl->met_dy) {
9081 met->lat[met->ny] = help->lat[iy];
9082 met->ps[met->nx][met->ny] = help->ps[ix][iy];
9083 met->zs[met->nx][met->ny] = help->zs[ix][iy];
9084 met->ts[met->nx][met->ny] = help->ts[ix][iy];
9085 met->us[met->nx][met->ny] = help->us[ix][iy];
9086 met->vs[met->nx][met->ny] = help->vs[ix][iy];
9087 met->ess[met->nx][met->ny] = help->ess[ix][iy];
9088 met->nss[met->nx][met->ny] = help->nss[ix][iy];
9089 met->shf[met->nx][met->ny] = help->shf[ix][iy];
9090 met->lsm[met->nx][met->ny] = help->lsm[ix][iy];
9091 met->sst[met->nx][met->ny] = help->sst[ix][iy];
9092 met->pbl[met->nx][met->ny] = help->pbl[ix][iy];
9093 met->cape[met->nx][met->ny] = help->cape[ix][iy];
9094 met->cin[met->nx][met->ny] = help->cin[ix][iy];
9095 met->np = 0;
9096 for (int ip = 0; ip < help->np; ip += ctl->met_dp) {
9097 met->p[met->np] = help->p[ip];
9098 met->t[met->nx][met->ny][met->np] = help->t[ix][iy][ip];
9099 met->u[met->nx][met->ny][met->np] = help->u[ix][iy][ip];
9100 met->v[met->nx][met->ny][met->np] = help->v[ix][iy][ip];
9101 met->w[met->nx][met->ny][met->np] = help->w[ix][iy][ip];
9102 met->h2o[met->nx][met->ny][met->np] = help->h2o[ix][iy][ip];
9103 met->o3[met->nx][met->ny][met->np] = help->o3[ix][iy][ip];
9104 met->lwc[met->nx][met->ny][met->np] = help->lwc[ix][iy][ip];
9105 met->rwc[met->nx][met->ny][met->np] = help->rwc[ix][iy][ip];
9106 met->iwc[met->nx][met->ny][met->np] = help->iwc[ix][iy][ip];
9107 met->swc[met->nx][met->ny][met->np] = help->swc[ix][iy][ip];
9108 met->cc[met->nx][met->ny][met->np] = help->cc[ix][iy][ip];
9109 met->np++;
9110 }
9111 met->ny++;
9112 }
9113 met->nx++;
9114 }
9115
9116 /* Free... */
9117 free(help);
9118}
int met_dp
Stride for pressure levels.
Definition: mptrac.h:2652
int met_sy
Smoothing for latitudes.
Definition: mptrac.h:2658
int met_sx
Smoothing for longitudes.
Definition: mptrac.h:2655
int met_dx
Stride for longitudes.
Definition: mptrac.h:2646
int met_sp
Smoothing for pressure levels.
Definition: mptrac.h:2661
int met_dy
Stride for latitudes.
Definition: mptrac.h:2649

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

9125 {
9126
9127 double p2[200], pv[EP], pv2[200], t[EP], t2[200], th[EP],
9128 th2[200], z[EP], z2[200];
9129
9130 /* Set timer... */
9131 SELECT_TIMER("READ_MET_TROPO", "METPROC", NVTX_READ);
9132 LOG(2, "Calculate tropopause...");
9133
9134 /* Get altitude and pressure profiles... */
9135#pragma omp parallel for default(shared)
9136 for (int iz = 0; iz < met->np; iz++)
9137 z[iz] = Z(met->p[iz]);
9138#pragma omp parallel for default(shared)
9139 for (int iz = 0; iz <= 190; iz++) {
9140 z2[iz] = 4.5 + 0.1 * iz;
9141 p2[iz] = P(z2[iz]);
9142 }
9143
9144 /* Do not calculate tropopause... */
9145 if (ctl->met_tropo == 0)
9146#pragma omp parallel for default(shared) collapse(2)
9147 for (int ix = 0; ix < met->nx; ix++)
9148 for (int iy = 0; iy < met->ny; iy++)
9149 met->pt[ix][iy] = NAN;
9150
9151 /* Use tropopause climatology... */
9152 else if (ctl->met_tropo == 1) {
9153#pragma omp parallel for default(shared) collapse(2)
9154 for (int ix = 0; ix < met->nx; ix++)
9155 for (int iy = 0; iy < met->ny; iy++)
9156 met->pt[ix][iy] = (float) clim_tropo(clim, met->time, met->lat[iy]);
9157 }
9158
9159 /* Use cold point... */
9160 else if (ctl->met_tropo == 2) {
9161
9162 /* Loop over grid points... */
9163#pragma omp parallel for default(shared) private(t,t2) collapse(2)
9164 for (int ix = 0; ix < met->nx; ix++)
9165 for (int iy = 0; iy < met->ny; iy++) {
9166
9167 /* Interpolate temperature profile... */
9168 for (int iz = 0; iz < met->np; iz++)
9169 t[iz] = met->t[ix][iy][iz];
9170 spline(z, t, met->np, z2, t2, 171, ctl->met_tropo_spline);
9171
9172 /* Find minimum... */
9173 int iz = (int) gsl_stats_min_index(t2, 1, 171);
9174 if (iz > 0 && iz < 170)
9175 met->pt[ix][iy] = (float) p2[iz];
9176 else
9177 met->pt[ix][iy] = NAN;
9178 }
9179 }
9180
9181 /* Use WMO definition... */
9182 else if (ctl->met_tropo == 3 || ctl->met_tropo == 4) {
9183
9184 /* Loop over grid points... */
9185#pragma omp parallel for default(shared) private(t,t2) collapse(2)
9186 for (int ix = 0; ix < met->nx; ix++)
9187 for (int iy = 0; iy < met->ny; iy++) {
9188
9189 /* Interpolate temperature profile... */
9190 int iz;
9191 for (iz = 0; iz < met->np; iz++)
9192 t[iz] = met->t[ix][iy][iz];
9193 spline(z, t, met->np, z2, t2, 191, ctl->met_tropo_spline);
9194
9195 /* Find 1st tropopause... */
9196 met->pt[ix][iy] = NAN;
9197 for (iz = 0; iz <= 170; iz++) {
9198 int found = 1;
9199 for (int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
9200 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
9201 found = 0;
9202 break;
9203 }
9204 if (found) {
9205 if (iz > 0 && iz < 170)
9206 met->pt[ix][iy] = (float) p2[iz];
9207 break;
9208 }
9209 }
9210
9211 /* Find 2nd tropopause... */
9212 if (ctl->met_tropo == 4) {
9213 met->pt[ix][iy] = NAN;
9214 for (; iz <= 170; iz++) {
9215 int found = 1;
9216 for (int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
9217 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
9218 found = 0;
9219 break;
9220 }
9221 if (found)
9222 break;
9223 }
9224 for (; iz <= 170; iz++) {
9225 int found = 1;
9226 for (int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
9227 if (LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
9228 found = 0;
9229 break;
9230 }
9231 if (found) {
9232 if (iz > 0 && iz < 170)
9233 met->pt[ix][iy] = (float) p2[iz];
9234 break;
9235 }
9236 }
9237 }
9238 }
9239 }
9240
9241 /* Use dynamical tropopause... */
9242 else if (ctl->met_tropo == 5) {
9243
9244 /* Loop over grid points... */
9245#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
9246 for (int ix = 0; ix < met->nx; ix++)
9247 for (int iy = 0; iy < met->ny; iy++) {
9248
9249 /* Interpolate potential vorticity profile... */
9250 for (int iz = 0; iz < met->np; iz++)
9251 pv[iz] = met->pv[ix][iy][iz];
9252 spline(z, pv, met->np, z2, pv2, 171, ctl->met_tropo_spline);
9253
9254 /* Interpolate potential temperature profile... */
9255 for (int iz = 0; iz < met->np; iz++)
9256 th[iz] = THETA(met->p[iz], met->t[ix][iy][iz]);
9257 spline(z, th, met->np, z2, th2, 171, ctl->met_tropo_spline);
9258
9259 /* Find dynamical tropopause... */
9260 met->pt[ix][iy] = NAN;
9261 for (int iz = 0; iz <= 170; iz++)
9262 if (fabs(pv2[iz]) >= ctl->met_tropo_pv
9263 || th2[iz] >= ctl->met_tropo_theta) {
9264 if (iz > 0 && iz < 170)
9265 met->pt[ix][iy] = (float) p2[iz];
9266 break;
9267 }
9268 }
9269 }
9270
9271 else
9272 ERRMSG("Cannot calculate tropopause!");
9273
9274 /* Interpolate temperature, geopotential height, and water vapor... */
9275#pragma omp parallel for default(shared) collapse(2)
9276 for (int ix = 0; ix < met->nx; ix++)
9277 for (int iy = 0; iy < met->ny; iy++) {
9278 double h2ot, tt, zt;
9280 intpol_met_space_3d(met, met->t, met->pt[ix][iy], met->lon[ix],
9281 met->lat[iy], &tt, ci, cw, 1);
9282 intpol_met_space_3d(met, met->z, met->pt[ix][iy], met->lon[ix],
9283 met->lat[iy], &zt, ci, cw, 0);
9284 intpol_met_space_3d(met, met->h2o, met->pt[ix][iy], met->lon[ix],
9285 met->lat[iy], &h2ot, ci, cw, 0);
9286 met->tt[ix][iy] = (float) tt;
9287 met->zt[ix][iy] = (float) zt;
9288 met->h2ot[ix][iy] = (float) h2ot;
9289 }
9290}
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:9500
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
Definition: mptrac.h:927
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 9294 of file mptrac.c.

9302 {
9303
9304 /* Write info... */
9305 LOG(1, "Read observation data: %s", filename);
9306
9307 /* Read data... */
9308 if (ctl->obs_type == 0)
9309 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
9310 else if (ctl->obs_type == 1)
9311 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
9312 else
9313 ERRMSG("Set OBS_TYPE to 0 or 1!");
9314
9315 /* Check time... */
9316 for (int i = 1; i < *nobs; i++)
9317 if (rt[i] < rt[i - 1])
9318 ERRMSG("Time must be ascending!");
9319
9320 /* Write info... */
9321 int n = *nobs;
9322 double mini, maxi;
9323 LOG(2, "Number of observations: %d", *nobs);
9324 gsl_stats_minmax(&mini, &maxi, rt, 1, (size_t) n);
9325 LOG(2, "Time range: %.2f ... %.2f s", mini, maxi);
9326 gsl_stats_minmax(&mini, &maxi, rz, 1, (size_t) n);
9327 LOG(2, "Altitude range: %g ... %g km", mini, maxi);
9328 gsl_stats_minmax(&mini, &maxi, rlon, 1, (size_t) n);
9329 LOG(2, "Longitude range: %g ... %g deg", mini, maxi);
9330 gsl_stats_minmax(&mini, &maxi, rlat, 1, (size_t) n);
9331 LOG(2, "Latitude range: %g ... %g deg", mini, maxi);
9332 gsl_stats_minmax(&mini, &maxi, robs, 1, (size_t) n);
9333 LOG(2, "Observation range: %g ... %g", mini, maxi);
9334}
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:9338
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:9366
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 9338 of file mptrac.c.

9345 {
9346
9347 /* Open observation data file... */
9348 FILE *in;
9349 if (!(in = fopen(filename, "r")))
9350 ERRMSG("Cannot open file!");
9351
9352 /* Read observations... */
9353 char line[LEN];
9354 while (fgets(line, LEN, in))
9355 if (sscanf(line, "%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
9356 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
9357 if ((++(*nobs)) >= NOBS)
9358 ERRMSG("Too many observations!");
9359
9360 /* Close observation data file... */
9361 fclose(in);
9362}
#define NOBS
Maximum number of observation data points.
Definition: mptrac.h:303

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

9373 {
9374
9375 int ncid, varid;
9376
9377 /* Open netCDF file... */
9378 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
9379 ERRMSG("Cannot open file!");
9380
9381 /* Read the observations from the NetCDF file... */
9382 NC_INQ_DIM("nobs", nobs, 1, NOBS);
9383 NC_GET_DOUBLE("time", rt, 1);
9384 NC_GET_DOUBLE("alt", rz, 1);
9385 NC_GET_DOUBLE("lon", rlon, 1);
9386 NC_GET_DOUBLE("lat", rlat, 1);
9387 NC_GET_DOUBLE("obs", robs, 1);
9388
9389 /* Close file... */
9390 NC(nc_close(ncid));
9391}

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

9402 {
9403
9404 FILE *in = NULL;
9405
9406 char fullname1[LEN], fullname2[LEN], rval[LEN];
9407
9408 int contain = 0, i;
9409
9410 /* Open file... */
9411 if (filename[strlen(filename) - 1] != '-')
9412 if (!(in = fopen(filename, "r")))
9413 ERRMSG("Cannot open file!");
9414
9415 /* Set full variable name... */
9416 if (arridx >= 0) {
9417 sprintf(fullname1, "%s[%d]", varname, arridx);
9418 sprintf(fullname2, "%s[*]", varname);
9419 } else {
9420 sprintf(fullname1, "%s", varname);
9421 sprintf(fullname2, "%s", varname);
9422 }
9423
9424 /* Read data... */
9425 if (in != NULL) {
9426 char dummy[LEN], line[LEN], rvarname[LEN];
9427 while (fgets(line, LEN, in)) {
9428 if (sscanf(line, "%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
9429 if (strcasecmp(rvarname, fullname1) == 0 ||
9430 strcasecmp(rvarname, fullname2) == 0) {
9431 contain = 1;
9432 break;
9433 }
9434 }
9435 }
9436 for (i = 1; i < argc - 1; i++)
9437 if (strcasecmp(argv[i], fullname1) == 0 ||
9438 strcasecmp(argv[i], fullname2) == 0) {
9439 sprintf(rval, "%s", argv[i + 1]);
9440 contain = 1;
9441 break;
9442 }
9443
9444 /* Close file... */
9445 if (in != NULL)
9446 fclose(in);
9447
9448 /* Check for missing variables... */
9449 if (!contain) {
9450 if (strlen(defvalue) > 0)
9451 sprintf(rval, "%s", defvalue);
9452 else
9453 ERRMSG("Missing variable %s!\n", fullname1);
9454 }
9455
9456 /* Write info... */
9457 LOG(1, "%s = %s", fullname1, rval);
9458
9459 /* Return values... */
9460 if (value != NULL)
9461 sprintf(value, "%s", rval);
9462 return atof(rval);
9463}

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

9471 {
9472
9473 /* Convert particle radius from microns to m... */
9474 const double rp_help = rp * 1e-6;
9475
9476 /* Density of dry air [kg / m^3]... */
9477 const double rho = RHO(p, T);
9478
9479 /* Dynamic viscosity of air [kg / (m s)]... */
9480 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
9481
9482 /* Thermal velocity of an air molecule [m / s]... */
9483 const double v = sqrt(8. * KB * T / (M_PI * 4.8096e-26));
9484
9485 /* Mean free path of an air molecule [m]... */
9486 const double lambda = 2. * eta / (rho * v);
9487
9488 /* Knudsen number for air (dimensionless)... */
9489 const double K = lambda / rp_help;
9490
9491 /* Cunningham slip-flow correction (dimensionless)... */
9492 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
9493
9494 /* Sedimentation velocity [m / s]... */
9495 return 2. * SQR(rp_help) * (rhop - rho) * G0 / (9. * eta) * G;
9496}
#define KB
Boltzmann constant [kg m^2/(K s^2)].
Definition: mptrac.h:214

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

9507 {
9508
9509 /* Cubic spline interpolation... */
9510 if (method == 1) {
9511
9512 /* Allocate... */
9513 gsl_interp_accel *acc = gsl_interp_accel_alloc();
9514 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (size_t) n);
9515
9516 /* Interpolate profile... */
9517 gsl_spline_init(s, x, y, (size_t) n);
9518 for (int i = 0; i < n2; i++)
9519 if (x2[i] <= x[0])
9520 y2[i] = y[0];
9521 else if (x2[i] >= x[n - 1])
9522 y2[i] = y[n - 1];
9523 else
9524 y2[i] = gsl_spline_eval(s, x2[i], acc);
9525
9526 /* Free... */
9527 gsl_spline_free(s);
9528 gsl_interp_accel_free(acc);
9529 }
9530
9531 /* Linear interpolation... */
9532 else {
9533 for (int i = 0; i < n2; i++)
9534 if (x2[i] <= x[0])
9535 y2[i] = y[0];
9536 else if (x2[i] >= x[n - 1])
9537 y2[i] = y[n - 1];
9538 else {
9539 int idx = locate_irr(x, n, x2[i]);
9540 y2[i] = LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
9541 }
9542 }
9543}
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 9547 of file mptrac.c.

9549 {
9550
9551 if (n <= 0)
9552 return 0;
9553
9554 float mean = 0, var = 0;
9555
9556 for (int i = 0; i < n; ++i) {
9557 mean += data[i];
9558 var += SQR(data[i]);
9559 }
9560
9561 var = var / (float) n - SQR(mean / (float) n);
9562
9563 return (var > 0 ? sqrtf(var) : 0);
9564}

◆ sza_calc()

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

Calculates the solar zenith angle.

This function calculates the solar zenith angle, which is the angle between the zenith (straight up) and the line connecting the observer to the center of the sun.

Parameters
secSeconds elapsed since 2000-01-01T12:00Z.
lonObserver's longitude in degrees.
latObserver's latitude in degrees.
Returns
The solar zenith angle in radians.

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

Note
This function assumes that the input longitude and latitude are given in degrees.
Author
Lars Hoffmann

Definition at line 9568 of file mptrac.c.

9571 {
9572
9573 /* Number of days and fraction with respect to 2000-01-01T12:00Z... */
9574 const double D = sec / 86400 - 0.5;
9575
9576 /* Geocentric apparent ecliptic longitude [rad]... */
9577 const double g = DEG2RAD(357.529 + 0.98560028 * D);
9578 const double q = 280.459 + 0.98564736 * D;
9579 const double L = DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
9580
9581 /* Mean obliquity of the ecliptic [rad]... */
9582 const double e = DEG2RAD(23.439 - 0.00000036 * D);
9583
9584 /* Declination [rad]... */
9585 const double sindec = sin(e) * sin(L);
9586
9587 /* Right ascension [rad]... */
9588 const double ra = atan2(cos(e) * sin(L), cos(L));
9589
9590 /* Greenwich Mean Sidereal Time [h]... */
9591 const double GMST = 18.697374558 + 24.06570982441908 * D;
9592
9593 /* Local Sidereal Time [h]... */
9594 const double LST = GMST + lon / 15;
9595
9596 /* Hour angle [rad]... */
9597 const double h = LST / 12 * M_PI - ra;
9598
9599 /* Convert latitude... */
9600 const double lat_help = DEG2RAD(lat);
9601
9602 /* Return solar zenith angle [rad]... */
9603 return acos(sin(lat_help) * sindec +
9604 cos(lat_help) * sqrt(1 - SQR(sindec)) * cos(h));
9605}

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

9617 {
9618
9619 struct tm t0, t1;
9620
9621 t0.tm_year = 100;
9622 t0.tm_mon = 0;
9623 t0.tm_mday = 1;
9624 t0.tm_hour = 0;
9625 t0.tm_min = 0;
9626 t0.tm_sec = 0;
9627
9628 t1.tm_year = year - 1900;
9629 t1.tm_mon = mon - 1;
9630 t1.tm_mday = day;
9631 t1.tm_hour = hour;
9632 t1.tm_min = min;
9633 t1.tm_sec = sec;
9634
9635 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
9636}

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

9643 {
9644
9645 static char names[NTIMER][100], groups[NTIMER][100];
9646
9647 static double rt_name[NTIMER], rt_group[NTIMER],
9648 rt_min[NTIMER], rt_max[NTIMER], dt, t0, t1;
9649
9650 static int iname = -1, igroup = -1, nname, ngroup, ct_name[NTIMER];
9651
9652 /* Get time... */
9653 t1 = omp_get_wtime();
9654 dt = t1 - t0;
9655
9656 /* Add elapsed time to current timers... */
9657 if (iname >= 0) {
9658 rt_name[iname] += dt;
9659 rt_min[iname] = (ct_name[iname] <= 0 ? dt : MIN(rt_min[iname], dt));
9660 rt_max[iname] = (ct_name[iname] <= 0 ? dt : MAX(rt_max[iname], dt));
9661 ct_name[iname]++;
9662 }
9663 if (igroup >= 0)
9664 rt_group[igroup] += t1 - t0;
9665
9666 /* Report timers... */
9667 if (output) {
9668 for (int i = 0; i < nname; i++)
9669 LOG(1, "TIMER_%s = %.3f s (min= %g s, mean= %g s,"
9670 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
9671 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
9672 for (int i = 0; i < ngroup; i++)
9673 LOG(1, "TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
9674 double total = 0.0;
9675 for (int i = 0; i < nname; i++)
9676 total += rt_name[i];
9677 LOG(1, "TIMER_TOTAL = %.3f s", total);
9678 }
9679
9680 /* Identify IDs of next timer... */
9681 for (iname = 0; iname < nname; iname++)
9682 if (strcasecmp(name, names[iname]) == 0)
9683 break;
9684 for (igroup = 0; igroup < ngroup; igroup++)
9685 if (strcasecmp(group, groups[igroup]) == 0)
9686 break;
9687
9688 /* Check whether this is a new timer... */
9689 if (iname >= nname) {
9690 sprintf(names[iname], "%s", name);
9691 if ((++nname) >= NTIMER)
9692 ERRMSG("Too many timers!");
9693 }
9694
9695 /* Check whether this is a new group... */
9696 if (igroup >= ngroup) {
9697 sprintf(groups[igroup], "%s", group);
9698 if ((++ngroup) >= NTIMER)
9699 ERRMSG("Too many groups!");
9700 }
9701
9702 /* Save starting time... */
9703 t0 = t1;
9704}
#define NTIMER
Maximum number of timers.
Definition: mptrac.h:2035

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

9710 {
9711
9712 char tstr[10];
9713
9714 double t;
9715
9716 /* Get time from filename... */
9717 int len = (int) strlen(filename);
9718 sprintf(tstr, "%.4s", &filename[len - offset]);
9719 int year = atoi(tstr);
9720 sprintf(tstr, "%.2s", &filename[len - offset + 5]);
9721 int mon = atoi(tstr);
9722 sprintf(tstr, "%.2s", &filename[len - offset + 8]);
9723 int day = atoi(tstr);
9724 sprintf(tstr, "%.2s", &filename[len - offset + 11]);
9725 int hour = atoi(tstr);
9726 sprintf(tstr, "%.2s", &filename[len - offset + 14]);
9727 int min = atoi(tstr);
9728
9729 /* Check time... */
9730 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
9731 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
9732 ERRMSG("Cannot read time from filename!");
9733
9734 /* Convert time to Julian seconds... */
9735 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
9736
9737 /* Return time... */
9738 return t;
9739}
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 9743 of file mptrac.c.

9746 {
9747
9748 /* Get tropopause pressure... */
9749 const double pt = clim_tropo(clim, atm->time[ip], atm->lat[ip]);
9750
9751 /* Get pressure range... */
9752 const double p1 = pt * 0.866877899;
9753 const double p0 = pt / 0.866877899;
9754
9755 /* Get weighting factor... */
9756 if (atm->p[ip] > p0)
9757 return 1;
9758 else if (atm->p[ip] < p1)
9759 return 0;
9760 else
9761 return LIN(p0, 1.0, p1, 0.0, atm->p[ip]);
9762}
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 9766 of file mptrac.c.

9770 {
9771
9772 FILE *out;
9773
9774 /* Set time interval for output... */
9775 const double t0 = t - 0.5 * ctl->dt_mod;
9776 const double t1 = t + 0.5 * ctl->dt_mod;
9777
9778 /* Check if gnuplot output is requested... */
9779 if (ctl->atm_gpfile[0] != '-') {
9780
9781 /* Create gnuplot pipe... */
9782 if (!(out = popen("gnuplot", "w")))
9783 ERRMSG("Cannot create pipe to gnuplot!");
9784
9785 /* Set plot filename... */
9786 fprintf(out, "set out \"%s.png\"\n", filename);
9787
9788 /* Set time string... */
9789 double r;
9790 int year, mon, day, hour, min, sec;
9791 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
9792 fprintf(out, "timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
9793 year, mon, day, hour, min);
9794
9795 /* Dump gnuplot file to pipe... */
9796 FILE *in;
9797 if (!(in = fopen(ctl->atm_gpfile, "r")))
9798 ERRMSG("Cannot open file!");
9799 char line[LEN];
9800 while (fgets(line, LEN, in))
9801 fprintf(out, "%s", line);
9802 fclose(in);
9803 }
9804
9805 else {
9806
9807 /* Create file... */
9808 if (!(out = fopen(filename, "w")))
9809 ERRMSG("Cannot create file!");
9810 }
9811
9812 /* Write header... */
9813 fprintf(out,
9814 "# $1 = time [s]\n"
9815 "# $2 = altitude [km]\n"
9816 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
9817 for (int iq = 0; iq < ctl->nq; iq++)
9818 fprintf(out, "# $%i = %s [%s]\n", iq + 5, ctl->qnt_name[iq],
9819 ctl->qnt_unit[iq]);
9820 fprintf(out, "\n");
9821
9822 /* Write data... */
9823 for (int ip = 0; ip < atm->np; ip += ctl->atm_stride) {
9824
9825 /* Check time... */
9826 if (ctl->atm_filter == 2 && (atm->time[ip] < t0 || atm->time[ip] > t1))
9827 continue;
9828
9829 /* Write output... */
9830 fprintf(out, "%.2f %g %g %g", atm->time[ip], Z(atm->p[ip]),
9831 atm->lon[ip], atm->lat[ip]);
9832 for (int iq = 0; iq < ctl->nq; iq++) {
9833 fprintf(out, " ");
9834 if (ctl->atm_filter == 1 && (atm->time[ip] < t0 || atm->time[ip] > t1))
9835 fprintf(out, ctl->qnt_format[iq], NAN);
9836 else
9837 fprintf(out, ctl->qnt_format[iq], atm->q[iq][ip]);
9838 }
9839 fprintf(out, "\n");
9840 }
9841
9842 /* Close file... */
9843 fclose(out);
9844}
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 9848 of file mptrac.c.

9851 {
9852
9853 FILE *out;
9854
9855 /* Create file... */
9856 if (!(out = fopen(filename, "w")))
9857 ERRMSG("Cannot create file!");
9858
9859 /* Write version of binary data... */
9860 int version = 100;
9861 FWRITE(&version, int,
9862 1,
9863 out);
9864
9865 /* Write data... */
9866 FWRITE(&atm->np, int,
9867 1,
9868 out);
9869 FWRITE(atm->time, double,
9870 (size_t) atm->np,
9871 out);
9872 FWRITE(atm->p, double,
9873 (size_t) atm->np,
9874 out);
9875 FWRITE(atm->lon, double,
9876 (size_t) atm->np,
9877 out);
9878 FWRITE(atm->lat, double,
9879 (size_t) atm->np,
9880 out);
9881 for (int iq = 0; iq < ctl->nq; iq++)
9882 FWRITE(atm->q[iq], double,
9883 (size_t) atm->np,
9884 out);
9885
9886 /* Write final flag... */
9887 int final = 999;
9888 FWRITE(&final, int,
9889 1,
9890 out);
9891
9892 /* Close file... */
9893 fclose(out);
9894}

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

9901 {
9902
9903 int tid, pid, ncid, varid;
9904 size_t start[2], count[2];
9905
9906 /* Create file... */
9907 nc_create(filename, NC_NETCDF4, &ncid);
9908
9909 /* Define dimensions... */
9910 NC(nc_def_dim(ncid, "time", 1, &tid));
9911 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
9912
9913 /* Define variables and their attributes... */
9914 int dim_ids[2] = { tid, pid };
9915 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
9916 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
9917 NC_DEF_VAR("LAT", NC_DOUBLE, 1, &pid, "Latitude", "deg",
9918 ctl->atm_nc_level, 0);
9919 NC_DEF_VAR("LON", NC_DOUBLE, 1, &pid, "Longitude", "deg",
9920 ctl->atm_nc_level, 0);
9921 NC_DEF_VAR("PRESS", NC_DOUBLE, 1, &pid, "Pressure", "hPa",
9922 ctl->atm_nc_level, 0);
9923 NC_DEF_VAR("ZETA", NC_DOUBLE, 1, &pid, "Zeta", "K", ctl->atm_nc_level, 0);
9924 for (int iq = 0; iq < ctl->nq; iq++)
9925 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
9926 ctl->qnt_name[iq], ctl->qnt_unit[iq],
9927 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
9928
9929 /* Define global attributes... */
9930 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
9931 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
9932
9933 /* End definitions... */
9934 NC(nc_enddef(ncid));
9935
9936 /* Write data... */
9937 NC_PUT_DOUBLE("time", atm->time, 0);
9938 NC_PUT_DOUBLE("LAT", atm->lat, 0);
9939 NC_PUT_DOUBLE("LON", atm->lon, 0);
9940 NC_PUT_DOUBLE("PRESS", atm->p, 0);
9941 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 0);
9942 for (int iq = 0; iq < ctl->nq; iq++)
9943 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
9944
9945 /* Close file... */
9946 NC(nc_close(ncid));
9947}
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
Definition: mptrac.h:1299
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units, level, quant)
Define a NetCDF variable with attributes.
Definition: mptrac.h:1132
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
Write double precision data to a NetCDF variable.
Definition: mptrac.h:1213

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

9955 {
9956
9957 /* Global Counter... */
9958 static size_t out_cnt = 0;
9959
9960 double r, r_start, r_stop;
9961 int year, mon, day, hour, min, sec;
9962 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
9963 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
9964 char filename_out[2 * LEN] = "traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
9965
9966 int ncid, varid, tid, pid, cid;
9967 int dim_ids[2];
9968
9969 /* time, nparc */
9970 size_t start[2];
9971 size_t count[2];
9972
9973 /* Determine start and stop times of calculation... */
9974 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
9975 jsec2time(ctl->t_start, &year_start, &mon_start, &day_start, &hour_start,
9976 &min_start, &sec_start, &r_start);
9977 jsec2time(ctl->t_stop, &year_stop, &mon_stop, &day_stop, &hour_stop,
9978 &min_stop, &sec_stop, &r_stop);
9979
9980 sprintf(filename_out,
9981 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
9982 year_start % 100, mon_start, day_start, hour_start,
9983 year_stop % 100, mon_stop, day_stop, hour_stop);
9984 LOG(1, "Write traj file: %s", filename_out);
9985
9986 /* Define hyperslap for the traj_file... */
9987 start[0] = out_cnt;
9988 start[1] = 0;
9989 count[0] = 1;
9990 count[1] = (size_t) atm->np;
9991
9992 /* Create the file at the first timestep... */
9993 if (out_cnt == 0) {
9994
9995 /* Create file... */
9996 nc_create(filename_out, NC_NETCDF4, &ncid);
9997
9998 /* Define dimensions... */
9999 NC(nc_def_dim(ncid, "time", NC_UNLIMITED, &tid));
10000 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
10001 NC(nc_def_dim(ncid, "TMDT", 7, &cid));
10002 dim_ids[0] = tid;
10003 dim_ids[1] = pid;
10004
10005 /* Define variables and their attributes... */
10006 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
10007 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
10008 NC_DEF_VAR("LAT", NC_DOUBLE, 2, dim_ids, "Latitude", "deg",
10009 ctl->atm_nc_level, 0);
10010 NC_DEF_VAR("LON", NC_DOUBLE, 2, dim_ids, "Longitude", "deg",
10011 ctl->atm_nc_level, 0);
10012 NC_DEF_VAR("PRESS", NC_DOUBLE, 2, dim_ids, "Pressure", "hPa",
10013 ctl->atm_nc_level, 0);
10014 NC_DEF_VAR("ZETA", NC_DOUBLE, 2, dim_ids, "Zeta", "K",
10015 ctl->atm_nc_level, 0);
10016 for (int iq = 0; iq < ctl->nq; iq++)
10017 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
10018 ctl->qnt_name[iq], ctl->qnt_unit[iq],
10019 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
10020
10021 /* Define global attributes... */
10022 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
10023 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
10024
10025 /* End definitions... */
10026 NC(nc_enddef(ncid));
10027 NC(nc_close(ncid));
10028 }
10029
10030 /* Increment global counter to change hyperslap... */
10031 out_cnt++;
10032
10033 /* Open file... */
10034 NC(nc_open(filename_out, NC_WRITE, &ncid));
10035
10036 /* Write data... */
10037 NC_PUT_DOUBLE("time", atm->time, 1);
10038 NC_PUT_DOUBLE("LAT", atm->lat, 1);
10039 NC_PUT_DOUBLE("LON", atm->lon, 1);
10040 NC_PUT_DOUBLE("PRESS", atm->p, 1);
10041 if (ctl->advect_vert_coord == 1) {
10042 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta], 1);
10043 } else if (ctl->qnt_zeta >= 0) {
10044 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 1);
10045 }
10046 for (int iq = 0; iq < ctl->nq; iq++)
10047 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 1);
10048
10049 /* Close file... */
10050 NC(nc_close(ncid));
10051
10052 /* At the last time step create the init_fix_YYYYMMDDHH file... */
10053 if ((year == year_stop) && (mon == mon_stop)
10054 && (day == day_stop) && (hour == hour_stop)) {
10055
10056 /* Set filename... */
10057 char filename_init[2 * LEN] = "./init_fix_YYYYMMDDHH.nc";
10058 sprintf(filename_init, "%s/init_fix_%02d%02d%02d%02d.nc",
10059 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
10060 LOG(1, "Write init file: %s", filename_init);
10061
10062 /* Create file... */
10063 nc_create(filename_init, NC_NETCDF4, &ncid);
10064
10065 /* Define dimensions... */
10066 NC(nc_def_dim(ncid, "time", 1, &tid));
10067 NC(nc_def_dim(ncid, "NPARTS", (size_t) atm->np, &pid));
10068 dim_ids[0] = tid;
10069 dim_ids[1] = pid;
10070
10071 /* Define variables and their attributes... */
10072 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "Time",
10073 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
10074 NC_DEF_VAR("LAT", NC_DOUBLE, 1, &pid, "Latitude", "deg",
10075 ctl->atm_nc_level, 0);
10076 NC_DEF_VAR("LON", NC_DOUBLE, 1, &pid, "Longitude", "deg",
10077 ctl->atm_nc_level, 0);
10078 NC_DEF_VAR("PRESS", NC_DOUBLE, 1, &pid, "Pressure", "hPa",
10079 ctl->atm_nc_level, 0);
10080 NC_DEF_VAR("ZETA", NC_DOUBLE, 1, &pid, "Zeta", "K", ctl->atm_nc_level, 0);
10081 for (int iq = 0; iq < ctl->nq; iq++)
10082 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 2, dim_ids,
10083 ctl->qnt_name[iq], ctl->qnt_unit[iq],
10084 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
10085
10086 /* Define global attributes... */
10087 NC_PUT_ATT_GLOBAL("exp_VERTCOOR_name", "zeta");
10088 NC_PUT_ATT_GLOBAL("model", "MPTRAC");
10089
10090 /* End definitions... */
10091 NC(nc_enddef(ncid));
10092
10093 /* Write data... */
10094 NC_PUT_DOUBLE("time", atm->time, 0);
10095 NC_PUT_DOUBLE("LAT", atm->lat, 0);
10096 NC_PUT_DOUBLE("LON", atm->lon, 0);
10097 NC_PUT_DOUBLE("PRESS", atm->p, 0);
10098 NC_PUT_DOUBLE("ZETA", atm->q[ctl->qnt_zeta_d], 0);
10099 for (int iq = 0; iq < ctl->nq; iq++)
10100 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
10101
10102 /* Close file... */
10103 NC(nc_close(ncid));
10104 }
10105}
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 10109 of file mptrac.c.

10112 {
10113
10114 int ncid, obsid, varid;
10115
10116 size_t start[2], count[2];
10117
10118 /* Create file... */
10119 NC(nc_create(filename, NC_NETCDF4, &ncid));
10120
10121 /* Define dimensions... */
10122 NC(nc_def_dim(ncid, "obs", (size_t) atm->np, &obsid));
10123
10124 /* Define variables and their attributes... */
10125 NC_DEF_VAR("time", NC_DOUBLE, 1, &obsid, "time",
10126 "seconds since 2000-01-01 00:00:00 UTC", ctl->atm_nc_level, 0);
10127 NC_DEF_VAR("press", NC_DOUBLE, 1, &obsid, "pressure", "hPa",
10128 ctl->atm_nc_level, 0);
10129 NC_DEF_VAR("lon", NC_DOUBLE, 1, &obsid, "longitude", "degrees_east",
10130 ctl->atm_nc_level, 0);
10131 NC_DEF_VAR("lat", NC_DOUBLE, 1, &obsid, "latitude", "degrees_north",
10132 ctl->atm_nc_level, 0);
10133 for (int iq = 0; iq < ctl->nq; iq++)
10134 NC_DEF_VAR(ctl->qnt_name[iq], NC_DOUBLE, 1, &obsid,
10135 ctl->qnt_longname[iq], ctl->qnt_unit[iq],
10136 ctl->atm_nc_level, ctl->atm_nc_quant[iq]);
10137
10138 /* Define global attributes... */
10139 NC_PUT_ATT_GLOBAL("featureType", "point");
10140
10141 /* End definitions... */
10142 NC(nc_enddef(ncid));
10143
10144 /* Write data... */
10145 NC_PUT_DOUBLE("time", atm->time, 0);
10146 NC_PUT_DOUBLE("press", atm->p, 0);
10147 NC_PUT_DOUBLE("lon", atm->lon, 0);
10148 NC_PUT_DOUBLE("lat", atm->lat, 0);
10149 for (int iq = 0; iq < ctl->nq; iq++)
10150 NC_PUT_DOUBLE(ctl->qnt_name[iq], atm->q[iq], 0);
10151
10152 /* Close file... */
10153 NC(nc_close(ncid));
10154}

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

10162 {
10163
10164 static FILE *out;
10165
10166 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
10167 *area, dlon, dlat, dz, x[NCSI], y[NCSI], obsstdn[NCSI], kz[EP], kw[EP];
10168
10169 static int *obscount, nobs, nk;
10170
10171 static int ct[NENS], cx[NENS], cy[NENS], cz[NENS], n[NENS];
10172
10173 const int ensemble = (ctl->nens > 0);
10174
10175 /* Set timer */
10176 SELECT_TIMER("WRITE_CSI", "OUTPUT", NVTX_WRITE);
10177
10178 /* Check quantities... */
10179 if (ctl->qnt_m < 0)
10180 ERRMSG("Need quantity mass!");
10181 if (ensemble) {
10182 if (ctl->qnt_ens < 0)
10183 ERRMSG("Missing ensemble IDs!");
10184 if (ctl->nens > NENS)
10185 ERRMSG("Too many ensembles!");
10186 }
10187
10188 /* Init... */
10189 if (t == ctl->t_start) {
10190
10191 /* Allocate.. */
10192 ALLOC(area, double,
10193 ctl->csi_ny);
10194 ALLOC(rt, double,
10195 NOBS);
10196 ALLOC(rz, double,
10197 NOBS);
10198 ALLOC(rlon, double,
10199 NOBS);
10200 ALLOC(rlat, double,
10201 NOBS);
10202 ALLOC(robs, double,
10203 NOBS);
10204
10205 /* Read observation data... */
10206 read_obs(ctl->csi_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
10207
10208 /* Read kernel data... */
10209 if (ctl->csi_kernel[0] != '-')
10210 read_kernel(ctl->csi_kernel, kz, kw, &nk);
10211
10212 /* Create new file... */
10213 LOG(1, "Write CSI%s data: %s", ensemble ? " ensemble" : "", filename);
10214 if (!(out = fopen(filename, "w")))
10215 ERRMSG("Cannot create file!");
10216
10217 /* Write header... */
10218 fprintf(out,
10219 "# $1 = time [s]\n"
10220 "# $2 = ensemble ID\n"
10221 "# $3 = number of hits (cx)\n"
10222 "# $4 = number of misses (cy)\n"
10223 "# $5 = number of false alarms (cz)\n"
10224 "# $6 = number of observations (cx + cy)\n"
10225 "# $7 = number of forecasts (cx + cz)\n"
10226 "# $8 = bias (%%)\n"
10227 "# $9 = POD (%%)\n"
10228 "# $10 = FAR (%%)\n"
10229 "# $11 = CSI (%%)\n"
10230 "# $12 = hits by random chance\n"
10231 "# $13 = ETS (%%)\n"
10232 "# $14 = Pearson R\n"
10233 "# $15 = Spearman R\n"
10234 "# $16 = mean error [kg/m²]\n"
10235 "# $17 = RMSE [kg/m²]\n"
10236 "# $18 = MAE [kg/m²]\n"
10237 "# $19 = log-likelihood\n" "# $20 = number of points\n\n");
10238
10239 /* Set grid box size... */
10240 dz = (ctl->csi_z1 - ctl->csi_z0) / ctl->csi_nz;
10241 dlon = (ctl->csi_lon1 - ctl->csi_lon0) / ctl->csi_nx;
10242 dlat = (ctl->csi_lat1 - ctl->csi_lat0) / ctl->csi_ny;
10243
10244 /* Set horizontal coordinates... */
10245 for (int iy = 0; iy < ctl->csi_ny; iy++) {
10246 double lat = ctl->csi_lat0 + dlat * (iy + 0.5);
10247 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.0) * cos(DEG2RAD(lat));
10248 }
10249 }
10250
10251 /* Set time interval... */
10252 double t0 = t - 0.5 * ctl->dt_mod;
10253 double t1 = t + 0.5 * ctl->dt_mod;
10254
10255 /* Allocate... */
10256 int grid_size = ctl->csi_nx * ctl->csi_ny * ctl->csi_nz;
10257 ALLOC(modmean, double,
10258 (ensemble ? ctl->nens : 1) * grid_size);
10259 ALLOC(obsmean, double,
10260 grid_size);
10261 ALLOC(obscount, int,
10262 grid_size);
10263 ALLOC(obsstd, double,
10264 grid_size);
10265
10266 /* Init... */
10267 for (int i = 0; i < (ensemble ? ctl->nens : 1); i++)
10268 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
10269
10270 /* Loop over observations... */
10271 for (int i = 0; i < nobs; i++) {
10272 if (rt[i] < t0 || rt[i] >= t1 || !isfinite(robs[i]))
10273 continue;
10274
10275 /* Calculate indices... */
10276 int ix = (int) ((rlon[i] - ctl->csi_lon0) / dlon);
10277 int iy = (int) ((rlat[i] - ctl->csi_lat0) / dlat);
10278 int iz = (int) ((rz[i] - ctl->csi_z0) / dz);
10279 if (ix < 0 || ix >= ctl->csi_nx || iy < 0 || iy >= ctl->csi_ny || iz < 0
10280 || iz >= ctl->csi_nz)
10281 continue;
10282
10283 /* Get mean observation index... */
10284 const int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
10285 obsmean[idx] += robs[i];
10286 obsstd[idx] += SQR(robs[i]);
10287 obscount[idx]++;
10288 }
10289
10290 /* Analyze model data... */
10291 for (int ip = 0; ip < atm->np; ip++) {
10292
10293 /* Check time... */
10294 if (atm->time[ip] < t0 || atm->time[ip] > t1)
10295 continue;
10296
10297 /* Get ensemble ID... */
10298 int ens_id = ensemble ? (int) atm->q[ctl->qnt_ens][ip] : 0;
10299 if (ens_id < 0 || ens_id >= (ensemble ? ctl->nens : 1))
10300 ERRMSG("Ensemble ID out of range!");
10301
10302 /* Get indices... */
10303 int ix = (int) ((atm->lon[ip] - ctl->csi_lon0) / dlon);
10304 int iy = (int) ((atm->lat[ip] - ctl->csi_lat0) / dlat);
10305 int iz = (int) ((Z(atm->p[ip]) - ctl->csi_z0) / dz);
10306 if (ix < 0 || ix >= ctl->csi_nx || iy < 0 || iy >= ctl->csi_ny || iz < 0
10307 || iz >= ctl->csi_nz)
10308 continue;
10309
10310 /* Get total mass in grid cell... */
10311 int idx =
10312 ens_id * grid_size + ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
10313 modmean[idx] +=
10314 kernel_weight(kz, kw, nk, atm->p[ip]) * atm->q[ctl->qnt_m][ip];
10315 }
10316
10317 /* Analyze all grid cells... */
10318 for (int ix = 0; ix < ctl->csi_nx; ix++)
10319 for (int iy = 0; iy < ctl->csi_ny; iy++)
10320 for (int iz = 0; iz < ctl->csi_nz; iz++) {
10321
10322 /* Calculate mean observation index... */
10323 int idx = ARRAY_3D(ix, iy, ctl->csi_ny, iz, ctl->csi_nz);
10324 if (obscount[idx]) {
10325 obsmean[idx] /= obscount[idx];
10326 obsstd[idx] = sqrt(obsstd[idx] - SQR(obsmean[idx]));
10327 }
10328
10329 /* Calculate model mean per ensemble... */
10330 for (int e = 0; e < (ensemble ? ctl->nens : 1); e++) {
10331 int midx = e * grid_size + idx;
10332 if (modmean[midx] > 0)
10333 modmean[midx] /= (1e6 * area[iy]);
10334 }
10335
10336 /* Check number of observations... */
10337 if (obscount[idx]) {
10338
10339 /* Calculate CSI... */
10340 for (int e = 0; e < (ensemble ? ctl->nens : 1); e++) {
10341 int midx = e * grid_size + idx;
10342 ct[e]++;
10343 if (obsmean[idx] >= ctl->csi_obsmin
10344 && modmean[midx] >= ctl->csi_modmin)
10345 cx[e]++;
10346 else if (obsmean[idx] >= ctl->csi_obsmin)
10347 cy[e]++;
10348 else if (modmean[midx] >= ctl->csi_modmin)
10349 cz[e]++;
10350
10351 /* Save data for other verification statistics... */
10352 if (obsmean[idx] >= ctl->csi_obsmin
10353 || modmean[midx] >= ctl->csi_modmin) {
10354 x[n[e]] = modmean[midx];
10355 y[n[e]] = obsmean[idx];
10356 if (modmean[midx] >= ctl->csi_modmin)
10357 obsstdn[n[e]] = obsstd[idx];
10358 if ((++n[e]) >= NCSI)
10359 ERRMSG("Too many points for statistics!");
10360 }
10361 }
10362 }
10363 }
10364
10365 /* Write output... */
10366 if (fmod(t, ctl->csi_dt_out) == 0) {
10367 for (int e = 0; e < (ensemble ? ctl->nens : 1); e++) {
10368
10369 if (n[e] == 0)
10370 continue;
10371
10372 /* Calculate verification statistics
10373 (https://www.cawcr.gov.au/projects/verification/) ... */
10374 static double work[2 * NCSI], work2[2 * NCSI];
10375 int n_obs = cx[e] + cy[e];
10376 int n_for = cx[e] + cz[e];
10377 double cx_rd = (ct[e] > 0) ? (1. * n_obs * n_for) / ct[e] : NAN;
10378 double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
10379 double pod = (n_obs > 0) ? 100. * cx[e] / n_obs : NAN;
10380 double far = (n_for > 0) ? 100. * cz[e] / n_for : NAN;
10381 double csi =
10382 (cx[e] + cy[e] + cz[e] >
10383 0) ? 100. * cx[e] / (cx[e] + cy[e] + cz[e]) : NAN;
10384 double ets =
10385 (cx[e] + cy[e] + cz[e] - cx_rd >
10386 0) ? 100. * (cx[e] - cx_rd) / (cx[e] + cy[e] + cz[e] - cx_rd) : NAN;
10387 double rho_p = gsl_stats_correlation(x, 1, y, 1, (size_t) n[e]);
10388 double rho_s = gsl_stats_spearman(x, 1, y, 1, (size_t) n[e], work);
10389 for (int i = 0; i < n[e]; i++) {
10390 work[i] = x[i] - y[i];
10391 work2[i] = (obsstdn[i] != 0) ? work[i] / obsstdn[i] : 0;
10392 }
10393 double mean = gsl_stats_mean(work, 1, (size_t) n[e]);
10394 double rmse = gsl_stats_sd_with_fixed_mean(work, 1, (size_t) n[e], 0.0);
10395 double absdev = gsl_stats_absdev_m(work, 1, (size_t) n[e], 0.0);
10396 double loglikelihood = gsl_stats_tss(work2, 1, (size_t) n[e]) * -0.5;
10397
10398 /* Write... */
10399 fprintf(out,
10400 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
10401 t, ensemble ? e : -999, cx[e], cy[e], cz[e], n_obs, n_for, bias,
10402 pod, far, csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
10403 loglikelihood, n[e]);
10404
10405 /* Set counters to zero... */
10406 ct[e] = cx[e] = cy[e] = cz[e] = n[e] = 0;
10407 }
10408 }
10409
10410 /* Free... */
10411 free(modmean);
10412 free(obsmean);
10413 free(obscount);
10414 free(obsstd);
10415
10416 /* Finalize... */
10417 if (t == ctl->t_stop) {
10418
10419 /* Close output file... */
10420 fclose(out);
10421
10422 /* Free... */
10423 free(area);
10424 free(rt);
10425 free(rz);
10426 free(rlon);
10427 free(rlat);
10428 free(robs);
10429 }
10430}
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:9294
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:6432
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:1731
#define NENS
Maximum number of data points for ensemble analysis.
Definition: mptrac.h:298
#define NCSI
Maximum number of data points for CSI calculation.
Definition: mptrac.h:278
Here is the call graph for this function:

◆ write_ens()

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

Writes ensemble data to a file.

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

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

The function performs the following steps:

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

Definition at line 10434 of file mptrac.c.

10438 {
10439
10440 static FILE *out;
10441
10442 static double dummy, lat, lon, qm[NQ][NENS], qs[NQ][NENS], xm[NENS][3],
10443 x[3], zm[NENS];
10444
10445 static int n[NENS];
10446
10447 /* Set timer... */
10448 SELECT_TIMER("WRITE_ENS", "OUTPUT", NVTX_WRITE);
10449
10450 /* Check quantities... */
10451 if (ctl->qnt_ens < 0)
10452 ERRMSG("Missing ensemble IDs!");
10453
10454 /* Set time interval... */
10455 const double t0 = t - 0.5 * ctl->dt_mod;
10456 const double t1 = t + 0.5 * ctl->dt_mod;
10457
10458 /* Init... */
10459 for (int i = 0; i < NENS; i++) {
10460 for (int iq = 0; iq < ctl->nq; iq++)
10461 qm[iq][i] = qs[iq][i] = 0;
10462 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
10463 n[i] = 0;
10464 }
10465
10466 /* Loop over air parcels... */
10467 for (int ip = 0; ip < atm->np; ip++) {
10468
10469 /* Check time... */
10470 if (atm->time[ip] < t0 || atm->time[ip] > t1)
10471 continue;
10472
10473 /* Check ensemble ID... */
10474 if (atm->q[ctl->qnt_ens][ip] < 0 || atm->q[ctl->qnt_ens][ip] >= NENS)
10475 ERRMSG("Ensemble ID is out of range!");
10476
10477 /* Get means... */
10478 geo2cart(0, atm->lon[ip], atm->lat[ip], x);
10479 for (int iq = 0; iq < ctl->nq; iq++) {
10480 qm[iq][ctl->qnt_ens] += atm->q[iq][ip];
10481 qs[iq][ctl->qnt_ens] += SQR(atm->q[iq][ip]);
10482 }
10483 xm[ctl->qnt_ens][0] += x[0];
10484 xm[ctl->qnt_ens][1] += x[1];
10485 xm[ctl->qnt_ens][2] += x[2];
10486 zm[ctl->qnt_ens] += Z(atm->p[ip]);
10487 n[ctl->qnt_ens]++;
10488 }
10489
10490 /* Create file... */
10491 LOG(1, "Write ensemble data: %s", filename);
10492 if (!(out = fopen(filename, "w")))
10493 ERRMSG("Cannot create file!");
10494
10495 /* Write header... */
10496 fprintf(out,
10497 "# $1 = time [s]\n"
10498 "# $2 = altitude [km]\n"
10499 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
10500 for (int iq = 0; iq < ctl->nq; iq++)
10501 fprintf(out, "# $%d = %s (mean) [%s]\n", 5 + iq,
10502 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
10503 for (int iq = 0; iq < ctl->nq; iq++)
10504 fprintf(out, "# $%d = %s (sigma) [%s]\n", 5 + ctl->nq + iq,
10505 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
10506 fprintf(out, "# $%d = number of members\n\n", 5 + 2 * ctl->nq);
10507
10508 /* Write data... */
10509 for (int i = 0; i < NENS; i++)
10510 if (n[i] > 0) {
10511 cart2geo(xm[i], &dummy, &lon, &lat);
10512 fprintf(out, "%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
10513 for (int iq = 0; iq < ctl->nq; iq++) {
10514 fprintf(out, " ");
10515 fprintf(out, ctl->qnt_format[iq], qm[iq][i] / n[i]);
10516 }
10517 for (int iq = 0; iq < ctl->nq; iq++) {
10518 fprintf(out, " ");
10519 double var = qs[iq][i] / n[i] - SQR(qm[iq][i] / n[i]);
10520 fprintf(out, ctl->qnt_format[iq], (var > 0 ? sqrt(var) : 0));
10521 }
10522 fprintf(out, " %d\n", n[i]);
10523 }
10524
10525 /* Close file... */
10526 fclose(out);
10527}
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 10531 of file mptrac.c.

10537 {
10538
10539 static double kz[EP], kw[EP];
10540
10541 static int nk;
10542
10543 double *cd, *mean[NQ], *sigma[NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
10544
10545 int *ixs, *iys, *izs, *np;
10546
10547 /* Set timer... */
10548 SELECT_TIMER("WRITE_GRID", "OUTPUT", NVTX_WRITE);
10549
10550 /* Write info... */
10551 LOG(1, "Write grid data: %s", filename);
10552
10553 /* Init... */
10554 if (t == ctl->t_start) {
10555
10556 /* Read kernel data... */
10557 if (ctl->grid_kernel[0] != '-')
10558 read_kernel(ctl->grid_kernel, kz, kw, &nk);
10559 }
10560
10561 /* Allocate... */
10562 ALLOC(cd, double,
10563 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10564 for (int iq = 0; iq < ctl->nq; iq++) {
10565 ALLOC(mean[iq], double,
10566 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10567 ALLOC(sigma[iq], double,
10568 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10569 }
10570 ALLOC(vmr_impl, double,
10571 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10572 ALLOC(z, double,
10573 ctl->grid_nz);
10574 ALLOC(lon, double,
10575 ctl->grid_nx);
10576 ALLOC(lat, double,
10577 ctl->grid_ny);
10578 ALLOC(area, double,
10579 ctl->grid_ny);
10580 ALLOC(press, double,
10581 ctl->grid_nz);
10582 ALLOC(np, int,
10583 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10584 ALLOC(ixs, int,
10585 atm->np);
10586 ALLOC(iys, int,
10587 atm->np);
10588 ALLOC(izs, int,
10589 atm->np);
10590
10591 /* Set grid box size... */
10592 const double dz = (ctl->grid_z1 - ctl->grid_z0) / ctl->grid_nz;
10593 const double dlon = (ctl->grid_lon1 - ctl->grid_lon0) / ctl->grid_nx;
10594 const double dlat = (ctl->grid_lat1 - ctl->grid_lat0) / ctl->grid_ny;
10595
10596 /* Set vertical coordinates... */
10597#pragma omp parallel for default(shared)
10598 for (int iz = 0; iz < ctl->grid_nz; iz++) {
10599 z[iz] = ctl->grid_z0 + dz * (iz + 0.5);
10600 press[iz] = P(z[iz]);
10601 }
10602
10603 /* Set horizontal coordinates... */
10604 for (int ix = 0; ix < ctl->grid_nx; ix++)
10605 lon[ix] = ctl->grid_lon0 + dlon * (ix + 0.5);
10606#pragma omp parallel for default(shared)
10607 for (int iy = 0; iy < ctl->grid_ny; iy++) {
10608 lat[iy] = ctl->grid_lat0 + dlat * (iy + 0.5);
10609 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
10610 }
10611
10612 /* Set time interval for output... */
10613 const double t0 = t - 0.5 * ctl->dt_mod;
10614 const double t1 = t + 0.5 * ctl->dt_mod;
10615
10616 /* Get grid box indices... */
10617#pragma omp parallel for default(shared)
10618 for (int ip = 0; ip < atm->np; ip++) {
10619 ixs[ip] = (int) ((atm->lon[ip] - ctl->grid_lon0) / dlon);
10620 iys[ip] = (int) ((atm->lat[ip] - ctl->grid_lat0) / dlat);
10621 izs[ip] = (int) ((Z(atm->p[ip]) - ctl->grid_z0) / dz);
10622 if (atm->time[ip] < t0 || atm->time[ip] > t1
10623 || ixs[ip] < 0 || ixs[ip] >= ctl->grid_nx
10624 || iys[ip] < 0 || iys[ip] >= ctl->grid_ny
10625 || izs[ip] < 0 || izs[ip] >= ctl->grid_nz)
10626 izs[ip] = -1;
10627 }
10628
10629 /* Average data... */
10630 for (int ip = 0; ip < atm->np; ip++)
10631 if (izs[ip] >= 0) {
10632 int idx =
10633 ARRAY_3D(ixs[ip], iys[ip], ctl->grid_ny, izs[ip], ctl->grid_nz);
10634 double kernel = kernel_weight(kz, kw, nk, atm->p[ip]);
10635 np[idx]++;
10636 for (int iq = 0; iq < ctl->nq; iq++) {
10637 mean[iq][idx] += kernel * atm->q[iq][ip];
10638 sigma[iq][idx] += SQR(kernel * atm->q[iq][ip]);
10639 }
10640 }
10641
10642 /* Calculate column density and volume mixing ratio... */
10643#pragma omp parallel for default(shared)
10644 for (int ix = 0; ix < ctl->grid_nx; ix++)
10645 for (int iy = 0; iy < ctl->grid_ny; iy++)
10646 for (int iz = 0; iz < ctl->grid_nz; iz++) {
10647
10648 /* Get grid index... */
10649 int idx = ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz);
10650
10651 /* Calculate column density... */
10652 cd[idx] = NAN;
10653 if (ctl->qnt_m >= 0)
10654 cd[idx] = mean[ctl->qnt_m][idx] / (1e6 * area[iy]);
10655
10656 /* Calculate volume mixing ratio (implicit)... */
10657 vmr_impl[idx] = NAN;
10658 if (ctl->qnt_m >= 0 && ctl->molmass > 0 && met0 != NULL
10659 && met1 != NULL) {
10660 vmr_impl[idx] = 0;
10661 if (mean[ctl->qnt_m][idx] > 0) {
10662
10663 /* Get temperature... */
10664 double temp;
10666 intpol_met_time_3d(met0, met0->t, met1, met1->t, t, press[iz],
10667 lon[ix], lat[iy], &temp, ci, cw, 1);
10668
10669 /* Calculate volume mixing ratio... */
10670 vmr_impl[idx] =
10671 MA / ctl->molmass * cd[idx] / (RHO(press[iz], temp) * dz * 1e3);
10672 }
10673 }
10674
10675 /* Calculate mean... */
10676 if (np[idx] > 0)
10677 for (int iq = 0; iq < ctl->nq; iq++) {
10678 mean[iq][idx] /= np[idx];
10679 double var = sigma[iq][idx] / np[idx] - SQR(mean[iq][idx]);
10680 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
10681 } else
10682 for (int iq = 0; iq < ctl->nq; iq++) {
10683 mean[iq][idx] = NAN;
10684 sigma[iq][idx] = NAN;
10685 }
10686 }
10687
10688 /* Write ASCII data... */
10689 if (ctl->grid_type == 0)
10690 write_grid_asc(filename, ctl, cd, mean, sigma, vmr_impl,
10691 t, z, lon, lat, area, dz, np);
10692
10693 /* Write netCDF data... */
10694 else if (ctl->grid_type == 1)
10695 write_grid_nc(filename, ctl, cd, mean, sigma, vmr_impl,
10696 t, z, lon, lat, area, dz, np);
10697
10698 /* Error message... */
10699 else
10700 ERRMSG("Grid data format GRID_TYPE unknown!");
10701
10702 /* Free... */
10703 free(cd);
10704 for (int iq = 0; iq < ctl->nq; iq++) {
10705 free(mean[iq]);
10706 free(sigma[iq]);
10707 }
10708 free(vmr_impl);
10709 free(z);
10710 free(lon);
10711 free(lat);
10712 free(area);
10713 free(press);
10714 free(np);
10715 free(ixs);
10716 free(iys);
10717 free(izs);
10718}
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:10722
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:10826
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 10722 of file mptrac.c.

10735 {
10736
10737 FILE *out;
10738
10739 /* Check if gnuplot output is requested... */
10740 if (ctl->grid_gpfile[0] != '-') {
10741
10742 /* Create gnuplot pipe... */
10743 if (!(out = popen("gnuplot", "w")))
10744 ERRMSG("Cannot create pipe to gnuplot!");
10745
10746 /* Set plot filename... */
10747 fprintf(out, "set out \"%s.png\"\n", filename);
10748
10749 /* Set time string... */
10750 double r;
10751 int year, mon, day, hour, min, sec;
10752 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
10753 fprintf(out, "timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
10754 year, mon, day, hour, min);
10755
10756 /* Dump gnuplot file to pipe... */
10757 FILE *in;
10758 char line[LEN];
10759 if (!(in = fopen(ctl->grid_gpfile, "r")))
10760 ERRMSG("Cannot open file!");
10761 while (fgets(line, LEN, in))
10762 fprintf(out, "%s", line);
10763 fclose(in);
10764 }
10765
10766 else {
10767
10768 /* Create file... */
10769 if (!(out = fopen(filename, "w")))
10770 ERRMSG("Cannot create file!");
10771 }
10772
10773 /* Write header... */
10774 fprintf(out,
10775 "# $1 = time [s]\n"
10776 "# $2 = altitude [km]\n"
10777 "# $3 = longitude [deg]\n"
10778 "# $4 = latitude [deg]\n"
10779 "# $5 = surface area [km^2]\n"
10780 "# $6 = layer depth [km]\n"
10781 "# $7 = column density (implicit) [kg/m^2]\n"
10782 "# $8 = volume mixing ratio (implicit) [ppv]\n"
10783 "# $9 = number of particles [1]\n");
10784 for (int iq = 0; iq < ctl->nq; iq++)
10785 fprintf(out, "# $%i = %s (mean) [%s]\n", 10 + iq, ctl->qnt_name[iq],
10786 ctl->qnt_unit[iq]);
10787 if (ctl->grid_stddev)
10788 for (int iq = 0; iq < ctl->nq; iq++)
10789 fprintf(out, "# $%i = %s (stddev) [%s]\n", 10 + ctl->nq + iq,
10790 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
10791 fprintf(out, "\n");
10792
10793 /* Write data... */
10794 for (int ix = 0; ix < ctl->grid_nx; ix++) {
10795 if (ix > 0 && ctl->grid_ny > 1 && !ctl->grid_sparse)
10796 fprintf(out, "\n");
10797 for (int iy = 0; iy < ctl->grid_ny; iy++) {
10798 if (iy > 0 && ctl->grid_nz > 1 && !ctl->grid_sparse)
10799 fprintf(out, "\n");
10800 for (int iz = 0; iz < ctl->grid_nz; iz++) {
10801 int idx = ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz);
10802 if (!ctl->grid_sparse || vmr_impl[idx] > 0) {
10803 fprintf(out, "%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
10804 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
10805 for (int iq = 0; iq < ctl->nq; iq++) {
10806 fprintf(out, " ");
10807 fprintf(out, ctl->qnt_format[iq], mean[iq][idx]);
10808 }
10809 if (ctl->grid_stddev)
10810 for (int iq = 0; iq < ctl->nq; iq++) {
10811 fprintf(out, " ");
10812 fprintf(out, ctl->qnt_format[iq], sigma[iq][idx]);
10813 }
10814 fprintf(out, "\n");
10815 }
10816 }
10817 }
10818 }
10819
10820 /* Close file... */
10821 fclose(out);
10822}
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 10826 of file mptrac.c.

10839 {
10840
10841 char longname[2 * LEN], varname[2 * LEN];
10842
10843 double *help;
10844
10845 int *help2, ncid, dimid[10], varid;
10846
10847 size_t start[2], count[2];
10848
10849 /* Allocate... */
10850 ALLOC(help, double,
10851 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10852 ALLOC(help2, int,
10853 ctl->grid_nx * ctl->grid_ny * ctl->grid_nz);
10854
10855 /* Create file... */
10856 NC(nc_create(filename, NC_NETCDF4, &ncid));
10857
10858 /* Define dimensions... */
10859 NC(nc_def_dim(ncid, "time", 1, &dimid[0]));
10860 NC(nc_def_dim(ncid, "z", (size_t) ctl->grid_nz, &dimid[1]));
10861 NC(nc_def_dim(ncid, "lat", (size_t) ctl->grid_ny, &dimid[2]));
10862 NC(nc_def_dim(ncid, "lon", (size_t) ctl->grid_nx, &dimid[3]));
10863 NC(nc_def_dim(ncid, "dz", 1, &dimid[4]));
10864
10865 /* Define variables and their attributes... */
10866 NC_DEF_VAR("time", NC_DOUBLE, 1, &dimid[0], "time",
10867 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
10868 NC_DEF_VAR("z", NC_DOUBLE, 1, &dimid[1], "altitude", "km", 0, 0);
10869 NC_DEF_VAR("lat", NC_DOUBLE, 1, &dimid[2], "latitude", "degrees_north", 0,
10870 0);
10871 NC_DEF_VAR("lon", NC_DOUBLE, 1, &dimid[3], "longitude", "degrees_east", 0,
10872 0);
10873 NC_DEF_VAR("dz", NC_DOUBLE, 1, &dimid[1], "layer depth", "km", 0, 0);
10874 NC_DEF_VAR("area", NC_DOUBLE, 1, &dimid[2], "surface area", "km**2", 0, 0);
10875
10876 NC_DEF_VAR("cd", NC_FLOAT, 4, dimid, "column density", "kg m**-2",
10877 ctl->grid_nc_level, 0);
10878 NC_DEF_VAR("vmr_impl", NC_FLOAT, 4, dimid,
10879 "volume mixing ratio (implicit)", "ppv", ctl->grid_nc_level, 0);
10880 NC_DEF_VAR("np", NC_INT, 4, dimid, "number of particles", "1", 0, 0);
10881 for (int iq = 0; iq < ctl->nq; iq++) {
10882 sprintf(varname, "%s_mean", ctl->qnt_name[iq]);
10883 sprintf(longname, "%s (mean)", ctl->qnt_longname[iq]);
10884 NC_DEF_VAR(varname, NC_DOUBLE, 4, dimid, longname, ctl->qnt_unit[iq],
10885 ctl->grid_nc_level, ctl->grid_nc_quant[iq]);
10886 if (ctl->grid_stddev) {
10887 sprintf(varname, "%s_stddev", ctl->qnt_name[iq]);
10888 sprintf(longname, "%s (stddev)", ctl->qnt_longname[iq]);
10889 NC_DEF_VAR(varname, NC_DOUBLE, 4, dimid, longname, ctl->qnt_unit[iq],
10890 ctl->grid_nc_level, ctl->grid_nc_quant[iq]);
10891 }
10892 }
10893 /* End definitions... */
10894 NC(nc_enddef(ncid));
10895
10896 /* Write data... */
10897 NC_PUT_DOUBLE("time", &t, 0);
10898 NC_PUT_DOUBLE("lon", lon, 0);
10899 NC_PUT_DOUBLE("lat", lat, 0);
10900 NC_PUT_DOUBLE("z", z, 0);
10901 NC_PUT_DOUBLE("area", area, 0);
10902 NC_PUT_DOUBLE("dz", &dz, 0);
10903
10904 for (int ix = 0; ix < ctl->grid_nx; ix++)
10905 for (int iy = 0; iy < ctl->grid_ny; iy++)
10906 for (int iz = 0; iz < ctl->grid_nz; iz++)
10907 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
10908 cd[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
10909 NC_PUT_DOUBLE("cd", help, 0);
10910
10911 for (int ix = 0; ix < ctl->grid_nx; ix++)
10912 for (int iy = 0; iy < ctl->grid_ny; iy++)
10913 for (int iz = 0; iz < ctl->grid_nz; iz++)
10914 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
10915 vmr_impl[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
10916 NC_PUT_DOUBLE("vmr_impl", help, 0);
10917
10918 for (int ix = 0; ix < ctl->grid_nx; ix++)
10919 for (int iy = 0; iy < ctl->grid_ny; iy++)
10920 for (int iz = 0; iz < ctl->grid_nz; iz++)
10921 help2[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
10922 np[ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
10923 NC_PUT_INT("np", help2, 0);
10924
10925 for (int iq = 0; iq < ctl->nq; iq++) {
10926 sprintf(varname, "%s_mean", ctl->qnt_name[iq]);
10927 for (int ix = 0; ix < ctl->grid_nx; ix++)
10928 for (int iy = 0; iy < ctl->grid_ny; iy++)
10929 for (int iz = 0; iz < ctl->grid_nz; iz++)
10930 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
10931 mean[iq][ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
10932 NC_PUT_DOUBLE(varname, help, 0);
10933 }
10934
10935 if (ctl->grid_stddev)
10936 for (int iq = 0; iq < ctl->nq; iq++) {
10937 sprintf(varname, "%s_stddev", ctl->qnt_name[iq]);
10938 for (int ix = 0; ix < ctl->grid_nx; ix++)
10939 for (int iy = 0; iy < ctl->grid_ny; iy++)
10940 for (int iz = 0; iz < ctl->grid_nz; iz++)
10941 help[ARRAY_3D(iz, iy, ctl->grid_ny, ix, ctl->grid_nx)] =
10942 sigma[iq][ARRAY_3D(ix, iy, ctl->grid_ny, iz, ctl->grid_nz)];
10943 NC_PUT_DOUBLE(varname, help, 0);
10944 }
10945
10946 /* Close file... */
10947 NC(nc_close(ncid));
10948
10949 /* Free... */
10950 free(help);
10951 free(help2);
10952}
#define NC_PUT_INT(varname, ptr, hyperslab)
Write integer data to a NetCDF variable.
Definition: mptrac.h:1260

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

10959 {
10960
10961 /* Create file... */
10962 FILE *out;
10963 if (!(out = fopen(filename, "w")))
10964 ERRMSG("Cannot create file!");
10965
10966 /* Write type of binary data... */
10967 FWRITE(&ctl->met_type, int,
10968 1,
10969 out);
10970
10971 /* Write version of binary data... */
10972 int version = 103;
10973 FWRITE(&version, int,
10974 1,
10975 out);
10976
10977 /* Write grid data... */
10978 FWRITE(&met->time, double,
10979 1,
10980 out);
10981 FWRITE(&met->nx, int,
10982 1,
10983 out);
10984 FWRITE(&met->ny, int,
10985 1,
10986 out);
10987 FWRITE(&met->np, int,
10988 1,
10989 out);
10990 FWRITE(met->lon, double,
10991 (size_t) met->nx,
10992 out);
10993 FWRITE(met->lat, double,
10994 (size_t) met->ny,
10995 out);
10996 FWRITE(met->p, double,
10997 (size_t) met->np,
10998 out);
10999
11000 /* Write surface data... */
11001 write_met_bin_2d(out, met, met->ps, "PS");
11002 write_met_bin_2d(out, met, met->ts, "TS");
11003 write_met_bin_2d(out, met, met->zs, "ZS");
11004 write_met_bin_2d(out, met, met->us, "US");
11005 write_met_bin_2d(out, met, met->vs, "VS");
11006 write_met_bin_2d(out, met, met->ess, "ESS");
11007 write_met_bin_2d(out, met, met->nss, "NSS");
11008 write_met_bin_2d(out, met, met->shf, "SHF");
11009 write_met_bin_2d(out, met, met->lsm, "LSM");
11010 write_met_bin_2d(out, met, met->sst, "SST");
11011 write_met_bin_2d(out, met, met->pbl, "PBL");
11012 write_met_bin_2d(out, met, met->pt, "PT");
11013 write_met_bin_2d(out, met, met->tt, "TT");
11014 write_met_bin_2d(out, met, met->zt, "ZT");
11015 write_met_bin_2d(out, met, met->h2ot, "H2OT");
11016 write_met_bin_2d(out, met, met->pct, "PCT");
11017 write_met_bin_2d(out, met, met->pcb, "PCB");
11018 write_met_bin_2d(out, met, met->cl, "CL");
11019 write_met_bin_2d(out, met, met->plcl, "PLCL");
11020 write_met_bin_2d(out, met, met->plfc, "PLFC");
11021 write_met_bin_2d(out, met, met->pel, "PEL");
11022 write_met_bin_2d(out, met, met->cape, "CAPE");
11023 write_met_bin_2d(out, met, met->cin, "CIN");
11024 write_met_bin_2d(out, met, met->o3c, "O3C");
11025
11026 /* Write level data... */
11027 write_met_bin_3d(out, ctl, met, met->z, "Z",
11028 (ctl->met_zfp_tol_z <= 0 ? ctl->met_zfp_prec : 0),
11029 ctl->met_zfp_tol_z);
11030 write_met_bin_3d(out, ctl, met, met->t, "T",
11031 (ctl->met_zfp_tol_t <= 0 ? ctl->met_zfp_prec : 0),
11032 ctl->met_zfp_tol_t);
11033 write_met_bin_3d(out, ctl, met, met->u, "U", ctl->met_zfp_prec, 0);
11034 write_met_bin_3d(out, ctl, met, met->v, "V", ctl->met_zfp_prec, 0);
11035 write_met_bin_3d(out, ctl, met, met->w, "W", ctl->met_zfp_prec, 0);
11036 write_met_bin_3d(out, ctl, met, met->pv, "PV", ctl->met_zfp_prec, 0);
11037 write_met_bin_3d(out, ctl, met, met->h2o, "H2O", ctl->met_zfp_prec, 0);
11038 write_met_bin_3d(out, ctl, met, met->o3, "O3", ctl->met_zfp_prec, 0);
11039 write_met_bin_3d(out, ctl, met, met->lwc, "LWC", ctl->met_zfp_prec, 0);
11040 write_met_bin_3d(out, ctl, met, met->rwc, "RWC", ctl->met_zfp_prec, 0);
11041 write_met_bin_3d(out, ctl, met, met->iwc, "IWC", ctl->met_zfp_prec, 0);
11042 write_met_bin_3d(out, ctl, met, met->swc, "SWC", ctl->met_zfp_prec, 0);
11043 write_met_bin_3d(out, ctl, met, met->cc, "CC", ctl->met_zfp_prec, 0);
11044
11045 /* Write final flag... */
11046 int final = 999;
11047 FWRITE(&final, int,
11048 1,
11049 out);
11050
11051 /* Close file... */
11052 fclose(out);
11053}
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:11086
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:11057
int met_zfp_prec
ZFP compression precision for all variables, except z and T.
Definition: mptrac.h:2588
double met_zfp_tol_t
ZFP compression tolerance for temperature.
Definition: mptrac.h:2591
double met_zfp_tol_z
ZFP compression tolerance for geopotential height.
Definition: mptrac.h:2594
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 11057 of file mptrac.c.

11061 {
11062
11063 float *help;
11064
11065 /* Allocate... */
11066 ALLOC(help, float,
11067 EX * EY);
11068
11069 /* Copy data... */
11070 for (int ix = 0; ix < met->nx; ix++)
11071 for (int iy = 0; iy < met->ny; iy++)
11072 help[ARRAY_2D(ix, iy, met->ny)] = var[ix][iy];
11073
11074 /* Write uncompressed data... */
11075 LOG(2, "Write 2-D variable: %s (uncompressed)", varname);
11076 FWRITE(help, float,
11077 (size_t) (met->nx * met->ny),
11078 out);
11079
11080 /* Free... */
11081 free(help);
11082}

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

11093 {
11094
11095 float *help;
11096
11097 /* Allocate... */
11098 ALLOC(help, float,
11099 EX * EY * EP);
11100
11101 /* Copy data... */
11102#pragma omp parallel for default(shared) collapse(2)
11103 for (int ix = 0; ix < met->nx; ix++)
11104 for (int iy = 0; iy < met->ny; iy++)
11105 for (int ip = 0; ip < met->np; ip++)
11106 help[ARRAY_3D(ix, iy, met->ny, ip, met->np)] = var[ix][iy][ip];
11107
11108 /* Write uncompressed data... */
11109 if (ctl->met_type == 1) {
11110 LOG(2, "Write 3-D variable: %s (uncompressed)", varname);
11111 FWRITE(help, float,
11112 (size_t) (met->nx * met->ny * met->np),
11113 out);
11114 }
11115
11116 /* Write packed data... */
11117 else if (ctl->met_type == 2)
11118 compress_pck(varname, help, (size_t) (met->ny * met->nx),
11119 (size_t) met->np, 0, out);
11120
11121 /* Write zfp data... */
11122#ifdef ZFP
11123 else if (ctl->met_type == 3) {
11124 FWRITE(&precision, int,
11125 1,
11126 out);
11127 FWRITE(&tolerance, double,
11128 1,
11129 out);
11130 compress_zfp(varname, help, met->np, met->ny, met->nx, precision,
11131 tolerance, 0, out);
11132 }
11133#endif
11134
11135 /* Write zstd data... */
11136#ifdef ZSTD
11137 else if (ctl->met_type == 4)
11138 compress_zstd(varname, help, (size_t) (met->np * met->ny * met->nx), 0,
11139 ctl->met_zstd_level, out);
11140#endif
11141
11142 /* Write cmultiscale data... */
11143#ifdef CMS
11144 else if (ctl->met_type == 5) {
11145 compress_cms(ctl, varname, help, (size_t) met->nx, (size_t) met->ny,
11146 (size_t) met->np, 0, out);
11147 }
11148#endif
11149
11150 /* Unknown method... */
11151 else {
11152 ERRMSG("MET_TYPE not supported!");
11153 LOG(3, "%d %g", precision, tolerance);
11154 }
11155
11156 /* Free... */
11157 free(help);
11158}
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 11162 of file mptrac.c.

11165 {
11166
11167 /* Create file... */
11168 int ncid, varid;
11169 size_t start[4], count[4];
11170 nc_create(filename, NC_NETCDF4, &ncid);
11171
11172 /* Define dimensions... */
11173 int tid, lonid, latid, levid;
11174 NC(nc_def_dim(ncid, "time", 1, &tid));
11175 NC(nc_def_dim(ncid, "lon", (size_t) met->nx, &lonid));
11176 NC(nc_def_dim(ncid, "lat", (size_t) met->ny, &latid));
11177 NC(nc_def_dim(ncid, "lev", (size_t) met->np, &levid));
11178
11179 /* Define grid... */
11180 NC_DEF_VAR("time", NC_DOUBLE, 1, &tid, "time",
11181 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
11182 NC_DEF_VAR("lon", NC_DOUBLE, 1, &lonid, "longitude", "degrees_east", 0, 0);
11183 NC_DEF_VAR("lat", NC_DOUBLE, 1, &latid, "latitude", "degrees_north", 0, 0);
11184 NC_DEF_VAR("lev", NC_DOUBLE, 1, &levid, "pressure", "Pa", 0, 0);
11185
11186 /* Define surface variables... */
11187 int dimid2[2] = { latid, lonid };
11188 NC_DEF_VAR("sp", NC_FLOAT, 2, dimid2, "Surface pressure", "Pa",
11189 ctl->met_nc_level, 0);
11190 NC_DEF_VAR("z", NC_FLOAT, 2, dimid2, "Geopotential", "m**2 s**-2",
11191 ctl->met_nc_level, 0);
11192 NC_DEF_VAR("t2m", NC_FLOAT, 2, dimid2, "2 metre temperature", "K",
11193 ctl->met_nc_level, 0);
11194 NC_DEF_VAR("u10m", NC_FLOAT, 2, dimid2, "10 metre U wind component",
11195 "m s**-1", ctl->met_nc_level, 0);
11196 NC_DEF_VAR("v10m", NC_FLOAT, 2, dimid2, "10 metre V wind component",
11197 "m s**-1", ctl->met_nc_level, 0);
11198 NC_DEF_VAR("iews", NC_FLOAT, 2, dimid2,
11199 "Instantaneous eastward turbulent surface stress", "N m**-2",
11200 ctl->met_nc_level, 0);
11201 NC_DEF_VAR("inss", NC_FLOAT, 2, dimid2,
11202 "Instantaneous northward turbulent surface stress", "N m**-2",
11203 ctl->met_nc_level, 0);
11204 NC_DEF_VAR("ishf", NC_FLOAT, 2, dimid2,
11205 "Instantaneous surface sensible heat flux", "W m**-1",
11206 ctl->met_nc_level, 0);
11207 NC_DEF_VAR("lsm", NC_FLOAT, 2, dimid2, "Land/sea mask", "-",
11208 ctl->met_nc_level, 0);
11209 NC_DEF_VAR("sstk", NC_FLOAT, 2, dimid2, "Sea surface temperature", "K",
11210 ctl->met_nc_level, 0);
11211 NC_DEF_VAR("blp", NC_FLOAT, 2, dimid2, "Boundary layer pressure", "Pa",
11212 ctl->met_nc_level, 0);
11213 NC_DEF_VAR("pt", NC_FLOAT, 2, dimid2, "Tropopause pressure", "Pa",
11214 ctl->met_nc_level, 0);
11215 NC_DEF_VAR("tt", NC_FLOAT, 2, dimid2, "Tropopause temperature", "K",
11216 ctl->met_nc_level, 0);
11217 NC_DEF_VAR("zt", NC_FLOAT, 2, dimid2, "Tropopause height", "m",
11218 ctl->met_nc_level, 0);
11219 NC_DEF_VAR("h2ot", NC_FLOAT, 2, dimid2, "Tropopause water vapor", "ppv",
11220 ctl->met_nc_level, 0);
11221 NC_DEF_VAR("pct", NC_FLOAT, 2, dimid2, "Cloud top pressure", "Pa",
11222 ctl->met_nc_level, 0);
11223 NC_DEF_VAR("pcb", NC_FLOAT, 2, dimid2, "Cloud bottom pressure", "Pa",
11224 ctl->met_nc_level, 0);
11225 NC_DEF_VAR("cl", NC_FLOAT, 2, dimid2, "Total column cloud water",
11226 "kg m**2", ctl->met_nc_level, 0);
11227 NC_DEF_VAR("plcl", NC_FLOAT, 2, dimid2,
11228 "Pressure at lifted condensation level (LCL)", "Pa",
11229 ctl->met_nc_level, 0);
11230 NC_DEF_VAR("plfc", NC_FLOAT, 2, dimid2,
11231 "Pressure at level of free convection (LFC)", "Pa",
11232 ctl->met_nc_level, 0);
11233 NC_DEF_VAR("pel", NC_FLOAT, 2, dimid2,
11234 "Pressure at equilibrium level (EL)", "Pa", ctl->met_nc_level,
11235 0);
11236 NC_DEF_VAR("cape", NC_FLOAT, 2, dimid2,
11237 "Convective available potential energy", "J kg**-1",
11238 ctl->met_nc_level, 0);
11239 NC_DEF_VAR("cin", NC_FLOAT, 2, dimid2, "Convective inhibition",
11240 "J kg**-1", ctl->met_nc_level, 0);
11241 NC_DEF_VAR("o3c", NC_FLOAT, 2, dimid2, "Total column ozone", "DU",
11242 ctl->met_nc_level, 0);
11243
11244 /* Define level data... */
11245 int dimid3[3] = { levid, latid, lonid };
11246 NC_DEF_VAR("t", NC_FLOAT, 3, dimid3, "Temperature", "K",
11247 ctl->met_nc_level, ctl->met_nc_quant);
11248 NC_DEF_VAR("u", NC_FLOAT, 3, dimid3, "U velocity", "m s**-1",
11249 ctl->met_nc_level, ctl->met_nc_quant);
11250 NC_DEF_VAR("v", NC_FLOAT, 3, dimid3, "V velocity", "m s**-1",
11251 ctl->met_nc_level, ctl->met_nc_quant);
11252 NC_DEF_VAR("w", NC_FLOAT, 3, dimid3, "Vertical velocity", "Pa s**-1",
11253 ctl->met_nc_level, ctl->met_nc_quant);
11254 NC_DEF_VAR("q", NC_FLOAT, 3, dimid3, "Specific humidity", "kg kg**-1",
11255 ctl->met_nc_level, ctl->met_nc_quant);
11256 NC_DEF_VAR("o3", NC_FLOAT, 3, dimid3, "Ozone mass mixing ratio",
11257 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
11258 NC_DEF_VAR("clwc", NC_FLOAT, 3, dimid3, "Cloud liquid water content",
11259 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
11260 NC_DEF_VAR("crwc", NC_FLOAT, 3, dimid3, "Cloud rain water content",
11261 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
11262 NC_DEF_VAR("ciwc", NC_FLOAT, 3, dimid3, "Cloud ice water content",
11263 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
11264 NC_DEF_VAR("cswc", NC_FLOAT, 3, dimid3, "Cloud snow water content",
11265 "kg kg**-1", ctl->met_nc_level, ctl->met_nc_quant);
11266 NC_DEF_VAR("cc", NC_FLOAT, 3, dimid3, "Cloud cover", "-",
11267 ctl->met_nc_level, ctl->met_nc_quant);
11268
11269 /* End definitions... */
11270 NC(nc_enddef(ncid));
11271
11272 /* Write grid data... */
11273 NC_PUT_DOUBLE("time", &met->time, 0);
11274 NC_PUT_DOUBLE("lon", met->lon, 0);
11275 NC_PUT_DOUBLE("lat", met->lat, 0);
11276 double phelp[EP];
11277 for (int ip = 0; ip < met->np; ip++)
11278 phelp[ip] = 100. * met->p[ip];
11279 NC_PUT_DOUBLE("lev", phelp, 0);
11280
11281 /* Write surface data... */
11282 write_met_nc_2d(ncid, "sp", met, met->ps, 100.0f);
11283 write_met_nc_2d(ncid, "z", met, met->zs, (float) (1000. * G0));
11284 write_met_nc_2d(ncid, "t2m", met, met->ts, 1.0f);
11285 write_met_nc_2d(ncid, "u10m", met, met->us, 1.0f);
11286 write_met_nc_2d(ncid, "v10m", met, met->vs, 1.0f);
11287 write_met_nc_2d(ncid, "iews", met, met->ess, 1.0f);
11288 write_met_nc_2d(ncid, "inss", met, met->nss, 1.0f);
11289 write_met_nc_2d(ncid, "ishf", met, met->shf, 1.0f);
11290 write_met_nc_2d(ncid, "lsm", met, met->lsm, 1.0f);
11291 write_met_nc_2d(ncid, "sstk", met, met->sst, 1.0f);
11292 write_met_nc_2d(ncid, "blp", met, met->pbl, 100.0f);
11293 write_met_nc_2d(ncid, "pt", met, met->pt, 100.0f);
11294 write_met_nc_2d(ncid, "tt", met, met->tt, 1.0f);
11295 write_met_nc_2d(ncid, "zt", met, met->zt, 1000.0f);
11296 write_met_nc_2d(ncid, "h2ot", met, met->h2ot, 1.0f);
11297 write_met_nc_2d(ncid, "pct", met, met->pct, 100.0f);
11298 write_met_nc_2d(ncid, "pcb", met, met->pcb, 100.0f);
11299 write_met_nc_2d(ncid, "cl", met, met->cl, 1.0f);
11300 write_met_nc_2d(ncid, "plcl", met, met->plcl, 100.0f);
11301 write_met_nc_2d(ncid, "plfc", met, met->plfc, 100.0f);
11302 write_met_nc_2d(ncid, "pel", met, met->pel, 100.0f);
11303 write_met_nc_2d(ncid, "cape", met, met->cape, 1.0f);
11304 write_met_nc_2d(ncid, "cin", met, met->cin, 1.0f);
11305 write_met_nc_2d(ncid, "o3c", met, met->o3c, 1.0f);
11306
11307 /* Write level data... */
11308 write_met_nc_3d(ncid, "t", met, met->t, 1.0f);
11309 write_met_nc_3d(ncid, "u", met, met->u, 1.0f);
11310 write_met_nc_3d(ncid, "v", met, met->v, 1.0f);
11311 write_met_nc_3d(ncid, "w", met, met->w, 100.0f);
11312 write_met_nc_3d(ncid, "q", met, met->h2o, (float) (MH2O / MA));
11313 write_met_nc_3d(ncid, "o3", met, met->o3, (float) (MO3 / MA));
11314 write_met_nc_3d(ncid, "clwc", met, met->lwc, 1.0f);
11315 write_met_nc_3d(ncid, "crwc", met, met->rwc, 1.0f);
11316 write_met_nc_3d(ncid, "ciwc", met, met->iwc, 1.0f);
11317 write_met_nc_3d(ncid, "cswc", met, met->swc, 1.0f);
11318 write_met_nc_3d(ncid, "cc", met, met->cc, 1.0f);
11319
11320 /* Close file... */
11321 NC(nc_close(ncid));
11322}
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:11326
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:11355
int met_nc_quant
Number of digits for quantization of netCDF meteo files (0=off).
Definition: mptrac.h:2582
int met_nc_level
zlib compression level of netCDF meteo files (0=off).
Definition: mptrac.h:2579
Here is the call graph for this function:

◆ write_met_nc_2d()

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

Writes a 2D meteorological variable to a NetCDF file.

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

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

Definition at line 11326 of file mptrac.c.

11331 {
11332
11333 int varid;
11334 size_t start[4], count[4];
11335
11336 /* Allocate... */
11337 float *help;
11338 ALLOC(help, float,
11339 EX * EY);
11340
11341 /* Copy data... */
11342 for (int ix = 0; ix < met->nx; ix++)
11343 for (int iy = 0; iy < met->ny; iy++)
11344 help[ARRAY_2D(iy, ix, met->nx)] = scl * var[ix][iy];
11345
11346 /* Write data... */
11347 NC_PUT_FLOAT(varname, help, 0);
11348
11349 /* Free... */
11350 free(help);
11351}
#define NC_PUT_FLOAT(varname, ptr, hyperslab)
Write a float array to a NetCDF file.
Definition: mptrac.h:1237

◆ write_met_nc_3d()

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

Writes a 3D meteorological variable to a NetCDF file.

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

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

Definition at line 11355 of file mptrac.c.

11360 {
11361
11362 int varid;
11363 size_t start[4], count[4];
11364
11365 /* Allocate... */
11366 float *help;
11367 ALLOC(help, float,
11368 EX * EY * EP);
11369
11370 /* Copy data... */
11371 for (int ix = 0; ix < met->nx; ix++)
11372 for (int iy = 0; iy < met->ny; iy++)
11373 for (int ip = 0; ip < met->np; ip++)
11374 help[ARRAY_3D(ip, iy, met->ny, ix, met->nx)] = scl * var[ix][iy][ip];
11375
11376 /* Write data... */
11377 NC_PUT_FLOAT(varname, help, 0);
11378
11379 /* Free... */
11380 free(help);
11381}

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

11391 {
11392
11393 static FILE *out;
11394
11395 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
11396 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
11397
11398 static int nobs, *obscount, ip, okay;
11399
11400 /* Set timer... */
11401 SELECT_TIMER("WRITE_PROF", "OUTPUT", NVTX_WRITE);
11402
11403 /* Init... */
11404 if (t == ctl->t_start) {
11405
11406 /* Check quantity index for mass... */
11407 if (ctl->qnt_m < 0)
11408 ERRMSG("Need quantity mass!");
11409
11410 /* Check molar mass... */
11411 if (ctl->molmass <= 0)
11412 ERRMSG("Specify molar mass!");
11413
11414 /* Allocate... */
11415 ALLOC(lon, double,
11416 ctl->prof_nx);
11417 ALLOC(lat, double,
11418 ctl->prof_ny);
11419 ALLOC(area, double,
11420 ctl->prof_ny);
11421 ALLOC(z, double,
11422 ctl->prof_nz);
11423 ALLOC(press, double,
11424 ctl->prof_nz);
11425 ALLOC(rt, double,
11426 NOBS);
11427 ALLOC(rz, double,
11428 NOBS);
11429 ALLOC(rlon, double,
11430 NOBS);
11431 ALLOC(rlat, double,
11432 NOBS);
11433 ALLOC(robs, double,
11434 NOBS);
11435
11436 /* Read observation data... */
11437 read_obs(ctl->prof_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
11438
11439 /* Create new output file... */
11440 LOG(1, "Write profile data: %s", filename);
11441 if (!(out = fopen(filename, "w")))
11442 ERRMSG("Cannot create file!");
11443
11444 /* Write header... */
11445 fprintf(out,
11446 "# $1 = time [s]\n"
11447 "# $2 = altitude [km]\n"
11448 "# $3 = longitude [deg]\n"
11449 "# $4 = latitude [deg]\n"
11450 "# $5 = pressure [hPa]\n"
11451 "# $6 = temperature [K]\n"
11452 "# $7 = volume mixing ratio [ppv]\n"
11453 "# $8 = H2O volume mixing ratio [ppv]\n"
11454 "# $9 = O3 volume mixing ratio [ppv]\n"
11455 "# $10 = observed BT index [K]\n"
11456 "# $11 = number of observations\n");
11457
11458 /* Set grid box size... */
11459 dz = (ctl->prof_z1 - ctl->prof_z0) / ctl->prof_nz;
11460 dlon = (ctl->prof_lon1 - ctl->prof_lon0) / ctl->prof_nx;
11461 dlat = (ctl->prof_lat1 - ctl->prof_lat0) / ctl->prof_ny;
11462
11463 /* Set vertical coordinates... */
11464 for (int iz = 0; iz < ctl->prof_nz; iz++) {
11465 z[iz] = ctl->prof_z0 + dz * (iz + 0.5);
11466 press[iz] = P(z[iz]);
11467 }
11468
11469 /* Set horizontal coordinates... */
11470 for (int ix = 0; ix < ctl->prof_nx; ix++)
11471 lon[ix] = ctl->prof_lon0 + dlon * (ix + 0.5);
11472 for (int iy = 0; iy < ctl->prof_ny; iy++) {
11473 lat[iy] = ctl->prof_lat0 + dlat * (iy + 0.5);
11474 area[iy] = dlat * dlon * SQR(RE * M_PI / 180.) * cos(DEG2RAD(lat[iy]));
11475 }
11476 }
11477
11478 /* Set time interval... */
11479 const double t0 = t - 0.5 * ctl->dt_mod;
11480 const double t1 = t + 0.5 * ctl->dt_mod;
11481
11482 /* Allocate... */
11483 ALLOC(mass, double,
11484 ctl->prof_nx * ctl->prof_ny * ctl->prof_nz);
11485 ALLOC(obsmean, double,
11486 ctl->prof_nx * ctl->prof_ny);
11487 ALLOC(obscount, int,
11488 ctl->prof_nx * ctl->prof_ny);
11489
11490 /* Loop over observations... */
11491 for (int i = 0; i < nobs; i++) {
11492
11493 /* Check time... */
11494 if (rt[i] < t0)
11495 continue;
11496 else if (rt[i] >= t1)
11497 break;
11498
11499 /* Check observation data... */
11500 if (!isfinite(robs[i]))
11501 continue;
11502
11503 /* Calculate indices... */
11504 int ix = (int) ((rlon[i] - ctl->prof_lon0) / dlon);
11505 int iy = (int) ((rlat[i] - ctl->prof_lat0) / dlat);
11506
11507 /* Check indices... */
11508 if (ix < 0 || ix >= ctl->prof_nx || iy < 0 || iy >= ctl->prof_ny)
11509 continue;
11510
11511 /* Get mean observation index... */
11512 int idx = ARRAY_2D(ix, iy, ctl->prof_ny);
11513 obsmean[idx] += robs[i];
11514 obscount[idx]++;
11515 }
11516
11517 /* Analyze model data... */
11518 for (ip = 0; ip < atm->np; ip++) {
11519
11520 /* Check time... */
11521 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11522 continue;
11523
11524 /* Get indices... */
11525 int ix = (int) ((atm->lon[ip] - ctl->prof_lon0) / dlon);
11526 int iy = (int) ((atm->lat[ip] - ctl->prof_lat0) / dlat);
11527 int iz = (int) ((Z(atm->p[ip]) - ctl->prof_z0) / dz);
11528
11529 /* Check indices... */
11530 if (ix < 0 || ix >= ctl->prof_nx ||
11531 iy < 0 || iy >= ctl->prof_ny || iz < 0 || iz >= ctl->prof_nz)
11532 continue;
11533
11534 /* Get total mass in grid cell... */
11535 int idx = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
11536 mass[idx] += atm->q[ctl->qnt_m][ip];
11537 }
11538
11539 /* Extract profiles... */
11540 for (int ix = 0; ix < ctl->prof_nx; ix++)
11541 for (int iy = 0; iy < ctl->prof_ny; iy++) {
11542 int idx2 = ARRAY_2D(ix, iy, ctl->prof_ny);
11543 if (obscount[idx2] > 0) {
11544
11545 /* Check profile... */
11546 okay = 0;
11547 for (int iz = 0; iz < ctl->prof_nz; iz++) {
11548 int idx3 = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
11549 if (mass[idx3] > 0) {
11550 okay = 1;
11551 break;
11552 }
11553 }
11554 if (!okay)
11555 continue;
11556
11557 /* Write output... */
11558 fprintf(out, "\n");
11559
11560 /* Loop over altitudes... */
11561 for (int iz = 0; iz < ctl->prof_nz; iz++) {
11562
11563 /* Get temperature, water vapor, and ozone... */
11565 intpol_met_time_3d(met0, met0->t, met1, met1->t, t, press[iz],
11566 lon[ix], lat[iy], &temp, ci, cw, 1);
11567 intpol_met_time_3d(met0, met0->h2o, met1, met1->h2o, t, press[iz],
11568 lon[ix], lat[iy], &h2o, ci, cw, 0);
11569 intpol_met_time_3d(met0, met0->o3, met1, met1->o3, t, press[iz],
11570 lon[ix], lat[iy], &o3, ci, cw, 0);
11571
11572 /* Calculate volume mixing ratio... */
11573 const int idx3 = ARRAY_3D(ix, iy, ctl->prof_ny, iz, ctl->prof_nz);
11574 vmr = MA / ctl->molmass * mass[idx3]
11575 / (RHO(press[iz], temp) * area[iy] * dz * 1e9);
11576
11577 /* Write output... */
11578 fprintf(out, "%.2f %g %g %g %g %g %g %g %g %g %d\n",
11579 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
11580 obsmean[idx2] / obscount[idx2], obscount[idx2]);
11581 }
11582 }
11583 }
11584
11585 /* Free... */
11586 free(mass);
11587 free(obsmean);
11588 free(obscount);
11589
11590 /* Finalize... */
11591 if (t == ctl->t_stop) {
11592
11593 /* Close output file... */
11594 fclose(out);
11595
11596 /* Free... */
11597 free(lon);
11598 free(lat);
11599 free(area);
11600 free(z);
11601 free(press);
11602 free(rt);
11603 free(rz);
11604 free(rlon);
11605 free(rlat);
11606 free(robs);
11607 }
11608}
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 11612 of file mptrac.c.

11618 {
11619
11620 static FILE *out;
11621
11622 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[EP],
11623 kw[EP];
11624
11625 static int nobs, nk;
11626
11627 /* Set timer... */
11628 SELECT_TIMER("WRITE_SAMPLE", "OUTPUT", NVTX_WRITE);
11629
11630 /* Init... */
11631 if (t == ctl->t_start) {
11632
11633 /* Allocate... */
11634 ALLOC(rt, double,
11635 NOBS);
11636 ALLOC(rz, double,
11637 NOBS);
11638 ALLOC(rlon, double,
11639 NOBS);
11640 ALLOC(rlat, double,
11641 NOBS);
11642 ALLOC(robs, double,
11643 NOBS);
11644
11645 /* Read observation data... */
11646 read_obs(ctl->sample_obsfile, ctl, rt, rz, rlon, rlat, robs, &nobs);
11647
11648 /* Read kernel data... */
11649 if (ctl->sample_kernel[0] != '-')
11650 read_kernel(ctl->sample_kernel, kz, kw, &nk);
11651
11652 /* Create output file... */
11653 LOG(1, "Write sample data: %s", filename);
11654 if (!(out = fopen(filename, "w")))
11655 ERRMSG("Cannot create file!");
11656
11657 /* Write header... */
11658 fprintf(out,
11659 "# $1 = time [s]\n"
11660 "# $2 = altitude [km]\n"
11661 "# $3 = longitude [deg]\n"
11662 "# $4 = latitude [deg]\n"
11663 "# $5 = surface area [km^2]\n"
11664 "# $6 = layer depth [km]\n"
11665 "# $7 = number of particles [1]\n"
11666 "# $8 = column density [kg/m^2]\n"
11667 "# $9 = volume mixing ratio [ppv]\n"
11668 "# $10 = observed BT index [K]\n\n");
11669
11670 /* Set latitude range, squared radius, and area... */
11671 dlat = DY2DEG(ctl->sample_dx);
11672 rmax2 = SQR(ctl->sample_dx);
11673 area = M_PI * rmax2;
11674 }
11675
11676 /* Set time interval for output... */
11677 const double t0 = t - 0.5 * ctl->dt_mod;
11678 const double t1 = t + 0.5 * ctl->dt_mod;
11679
11680 /* Loop over observations... */
11681 for (int i = 0; i < nobs; i++) {
11682
11683 /* Check time... */
11684 if (rt[i] < t0)
11685 continue;
11686 else if (rt[i] >= t1)
11687 break;
11688
11689 /* Calculate Cartesian coordinates... */
11690 double x0[3];
11691 geo2cart(0, rlon[i], rlat[i], x0);
11692
11693 /* Set pressure range... */
11694 const double rp = P(rz[i]);
11695 const double ptop = P(rz[i] + ctl->sample_dz);
11696 const double pbot = P(rz[i] - ctl->sample_dz);
11697
11698 /* Init... */
11699 double mass = 0;
11700 int np = 0;
11701
11702 /* Loop over air parcels... */
11703 //#pragma omp parallel for default(shared) reduction(+:mass,np)
11704 for (int ip = 0; ip < atm->np; ip++) {
11705
11706 /* Check time... */
11707 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11708 continue;
11709
11710 /* Check latitude... */
11711 if (fabs(rlat[i] - atm->lat[ip]) > dlat)
11712 continue;
11713
11714 /* Check horizontal distance... */
11715 double x1[3];
11716 geo2cart(0, atm->lon[ip], atm->lat[ip], x1);
11717 if (DIST2(x0, x1) > rmax2)
11718 continue;
11719
11720 /* Check pressure... */
11721 if (ctl->sample_dz > 0)
11722 if (atm->p[ip] > pbot || atm->p[ip] < ptop)
11723 continue;
11724
11725 /* Add mass... */
11726 if (ctl->qnt_m >= 0)
11727 mass +=
11728 kernel_weight(kz, kw, nk, atm->p[ip]) * atm->q[ctl->qnt_m][ip];
11729 np++;
11730 }
11731
11732 /* Calculate column density... */
11733 const double cd = mass / (1e6 * area);
11734
11735 /* Calculate volume mixing ratio... */
11736 double vmr = 0;
11737 if (ctl->molmass > 0 && ctl->sample_dz > 0) {
11738 if (mass > 0) {
11739
11740 /* Get temperature... */
11741 double temp;
11743 intpol_met_time_3d(met0, met0->t, met1, met1->t, rt[i], rp,
11744 rlon[i], rlat[i], &temp, ci, cw, 1);
11745
11746 /* Calculate volume mixing ratio... */
11747 vmr = MA / ctl->molmass * cd / (RHO(rp, temp) * ctl->sample_dz * 1e3);
11748 }
11749 } else
11750 vmr = NAN;
11751
11752 /* Write output... */
11753 fprintf(out, "%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
11754 rlon[i], rlat[i], area, ctl->sample_dz, np, cd, vmr, robs[i]);
11755 }
11756
11757 /* Finalize...... */
11758 if (t == ctl->t_stop) {
11759
11760 /* Close output file... */
11761 fclose(out);
11762
11763 /* Free... */
11764 free(rt);
11765 free(rz);
11766 free(rlon);
11767 free(rlat);
11768 free(robs);
11769 }
11770}
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 11774 of file mptrac.c.

11778 {
11779
11780 static FILE *out;
11781
11782 static double rmax2, x0[3], x1[3];
11783
11784 /* Set timer... */
11785 SELECT_TIMER("WRITE_STATION", "OUTPUT", NVTX_WRITE);
11786
11787 /* Init... */
11788 if (t == ctl->t_start) {
11789
11790 /* Write info... */
11791 LOG(1, "Write station data: %s", filename);
11792
11793 /* Create new file... */
11794 if (!(out = fopen(filename, "w")))
11795 ERRMSG("Cannot create file!");
11796
11797 /* Write header... */
11798 fprintf(out,
11799 "# $1 = time [s]\n"
11800 "# $2 = altitude [km]\n"
11801 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11802 for (int iq = 0; iq < ctl->nq; iq++)
11803 fprintf(out, "# $%i = %s [%s]\n", (iq + 5),
11804 ctl->qnt_name[iq], ctl->qnt_unit[iq]);
11805 fprintf(out, "\n");
11806
11807 /* Set geolocation and search radius... */
11808 geo2cart(0, ctl->stat_lon, ctl->stat_lat, x0);
11809 rmax2 = SQR(ctl->stat_r);
11810 }
11811
11812 /* Set time interval for output... */
11813 const double t0 = t - 0.5 * ctl->dt_mod;
11814 const double t1 = t + 0.5 * ctl->dt_mod;
11815
11816 /* Loop over air parcels... */
11817 for (int ip = 0; ip < atm->np; ip++) {
11818
11819 /* Check time... */
11820 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11821 continue;
11822
11823 /* Check time range for station output... */
11824 if (atm->time[ip] < ctl->stat_t0 || atm->time[ip] > ctl->stat_t1)
11825 continue;
11826
11827 /* Check station flag... */
11828 if (ctl->qnt_stat >= 0)
11829 if ((int) atm->q[ctl->qnt_stat][ip])
11830 continue;
11831
11832 /* Get Cartesian coordinates... */
11833 geo2cart(0, atm->lon[ip], atm->lat[ip], x1);
11834
11835 /* Check horizontal distance... */
11836 if (DIST2(x0, x1) > rmax2)
11837 continue;
11838
11839 /* Set station flag... */
11840 if (ctl->qnt_stat >= 0)
11841 atm->q[ctl->qnt_stat][ip] = 1;
11842
11843 /* Write data... */
11844 fprintf(out, "%.2f %g %g %g",
11845 atm->time[ip], Z(atm->p[ip]), atm->lon[ip], atm->lat[ip]);
11846 for (int iq = 0; iq < ctl->nq; iq++) {
11847 fprintf(out, " ");
11848 fprintf(out, ctl->qnt_format[iq], atm->q[iq][ip]);
11849 }
11850 fprintf(out, "\n");
11851 }
11852
11853 /* Close file... */
11854 if (t == ctl->t_stop)
11855 fclose(out);
11856}
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 11860 of file mptrac.c.

11864 {
11865
11866 FILE *out;
11867
11868 /* Set timer... */
11869 SELECT_TIMER("WRITE_VTK", "OUTPUT", NVTX_WRITE);
11870
11871 /* Write info... */
11872 LOG(1, "Write VTK data: %s", filename);
11873
11874 /* Set time interval for output... */
11875 const double t0 = t - 0.5 * ctl->dt_mod;
11876 const double t1 = t + 0.5 * ctl->dt_mod;
11877
11878 /* Create file... */
11879 if (!(out = fopen(filename, "w")))
11880 ERRMSG("Cannot create file!");
11881
11882 /* Count data points... */
11883 int np = 0;
11884 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
11885 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11886 continue;
11887 np++;
11888 }
11889
11890 /* Write header... */
11891 fprintf(out,
11892 "# vtk DataFile Version 3.0\n"
11893 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
11894
11895 /* Write point coordinates... */
11896 fprintf(out, "POINTS %d float\n", np);
11897 if (ctl->vtk_sphere) {
11898 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
11899 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11900 continue;
11901 const double radius = (RE + Z(atm->p[ip]) * ctl->vtk_scale
11902 + ctl->vtk_offset) / RE;
11903 const double coslat = cos(DEG2RAD(atm->lat[ip]));
11904 const double x = radius * coslat * cos(DEG2RAD(atm->lon[ip]));
11905 const double y = radius * coslat * sin(DEG2RAD(atm->lon[ip]));
11906 const double z = radius * sin(DEG2RAD(atm->lat[ip]));
11907 fprintf(out, "%g %g %g\n", x, y, z);
11908 }
11909 } else
11910 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
11911 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11912 continue;
11913 fprintf(out, "%g %g %g\n", atm->lon[ip], atm->lat[ip],
11914 Z(atm->p[ip]) * ctl->vtk_scale + ctl->vtk_offset);
11915 }
11916
11917 /* Write point data... */
11918 fprintf(out, "POINT_DATA %d\n", np);
11919 for (int iq = 0; iq < ctl->nq; iq++) {
11920 fprintf(out, "SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
11921 ctl->qnt_name[iq]);
11922 for (int ip = 0; ip < atm->np; ip += ctl->vtk_stride) {
11923 if (atm->time[ip] < t0 || atm->time[ip] > t1)
11924 continue;
11925 fprintf(out, "%g\n", atm->q[iq][ip]);
11926 }
11927 }
11928
11929 /* Close file... */
11930 fclose(out);
11931}