AUSTAL (modified)
TalInp.c
/*===================================================================== TalInp.c
*
* Read Input for AUSTAL
* =====================
*
* All data given by TA Luft are defined in this module
* =====================================================
*
* Copyright (C) Umweltbundesamt, Dessau-Roßlau, Germany, 2002-2024
* Copyright (C) Janicke Consulting, 88662 Überlingen, Germany, 2002-2024
* Email: info@austal.de
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* last change: 2024-01-17 uj
*
*============================================================================*/
char *TalInpVersion = "3.3.0";
static char *eMODn = "TalInp";
static int CHECK = 0;
char AbsoluteWindLibPath[256] = ""; //bp
char SettingsPath[256] = ""; //bp
#ifdef DIAM //bp
static int numprocs=1; //bp
#else //bp
extern int numprocs; //bp
#endif //bp
static int StdLogLevel = 3; //-2006-10-20
static int StdDspLevel = 2; //-2006-10-20
#include
#include
#include
#include
#include
#include
#ifdef __linux__
#include
#include
#include
#define AUSTALx "austal" //bp
#define TALDIA "taldia"
#define VDISP "vdisp"
#else
#include
#define AUSTALx "austal.exe" //bp
#define TALDIA "taldia.exe"
#define VDISP "vdisp.exe"
#endif
#include "IBJmsg.h"
#include "IBJary.h"
#include "IBJtxt.h"
#include "IBJdmn.h"
#include "IBJgk.h"
#include "IBJntr.h"
#include "IBJnls.h" //-2008-12-19
#include "TalAKT.h"
#include "TalAKS.h"
#include "TalUtl.h"
#include "TalRgl.h"
#include "TalDef.h"
#include "TalZet.h"
#include "TalDMK.h"
#include "TalStt.h"
#include "TalInp.h"
#include "TalInp.nls"
#include "TalMat.h"
#include "TalCfg.h"
//////////////////////////////////////////////////////////////
// default CRC codes, status: 2024-01-17
//////////////////////////////////////////////////////////////
#define RGL_CRC_GK "58afd278"
#define RGL_CRC_UTM "e9ea3bcd"
#define SETTINGS_CRC "b853d6c4"
#define BESMAX_CRC "2c0102a0"
//////////////////////////////////////////////////////////////
#define vLOG(a) MsgQuiet=2*(StdDspLevel<(a))-1, MsgVerbose=(StdLogLevel>=(a)), vMsg
#define TE(i) ((AKTREC*)AryPtrX(&TIPary, i))->t
#define RA(i) ((AKTREC*)AryPtrX(&TIPary, i))->iRa
#define UA(i) ((AKTREC*)AryPtrX(&TIPary, i))->fUa
#define KL(i) ((AKTREC*)AryPtrX(&TIPary, i))->iKl
typedef struct {
int iLine; // line number in input file
char *_name; // parameter name + buffer for tokens
int nTokens; // number of tokens
char **_tokens; // array of pointers to tokens
int type; // type of tokens (TIP_STRING or TIP_NUMBER)
double *_dd; // array of values or NULL
} TIPREC;
typedef struct { //-2018-10-29
double t; // end time of the 1 hour interval (GMT+1)
float fPr; // precipitation in mm/h
} PRCREC;
// these unit specifications must be applied in the settings file
#define U_GM3 "g/m3" //-2008-07-22
#define U_UGM3 "ug/m3" //-2008-07-22
#define U_PGM3 "pg/m3" //-2019-02-19
#define U_MGM3 "mg/m3" //-2008-07-22
#define U_1M3 "1/m3" //-2019-02-19
#define U_GM2D "g/(m2*d)" //-2008-07-22
#define U_1M2S "1/(m2*s)" //-2019-02-19
#define U_MGM2D "mg/(m2*d)" //-2008-07-22
#define U_UGM2D "ug/(m2*d)" //-2008-07-22
#define U_PGM2D "pg/(m2*d)" //-2019-02-19
#define U_KGHAA "kg/(ha*a)" //-2008-07-22
#define U_PERC "%" //-2008-07-22
double TipEpsilon = 1.e-4;
int TipMaxIter = 200;
int cNO, cNO2, cODOR, nADDODOR;
int TipTrbExt = 0;
//
// parameters that may be defined as time-dependent (beside ua, ra, lm, emission rates)
static char *VarPrm = "vq,tq,zq,rq,sq,lq,ts,hm,ri,iq"; //-2015-12-01 //-2018-10-04
//
// default vertical grid above ground for TA Luft
static double Hh[] = { 0, 3, 6, 10, 16, 25, 40, 65, 100, 150, 200, 300, 400, 500,
600, 700, 800, 1000, 1200, 1500 };
//
// default vertical grid above ground for VDI 3783/1 //-2024-01-17
static double Hh37831[] = { 0, 2, 4, 6, 10, 16, 25, 40, 65, 100, 150, 200, 300,
400, 500, 600, 700, 800, 900, 1000, 1500 };
//
static double BodyDda[] = { 32, 16, 8, 4, 2 };
static double BodyDza[] = { 6, 4, 3, 3, 2 };
static double BodyDd, BodyDz, BodyHmax;
static double FinestGridZmin = 20.; //-2019-02-04
static double BodyRatio = 5; //-2004-07
static double TurbRatio = 10; //-2004-07
static ARYDSC BM;
static double BMx0, BMy0, BMdd, BMdz;
static double DdMin = 16.0; //-2004-11-02
static double RadMin = 1000;
static double RadRatio = 50;
static int NxyMax = 400; //-2023-07-17
static int nz0TAL=9, iZ0;
static double z0TAL[9] = { 0.01, 0.02, 0.05, 0.10, 0.20, 0.50, 1.0, 1.5, 2.0 };
static float lmTAL[6][9] = //-2018-10-04
{ { 5, 7, 9, 13, 17, 28, 44, 60, 77 },
{ 25, 31, 44, 59, 81, 133, 207, 280, 358 },
{ 354, 448, 631, 842, 1160, 1893, 2951, 4000, 5107 },
{ -37, -47, -66, -88, -122, -199, -310, -420, -536 },
{ -15, -19, -27, -36, -49, -80, -125, -170, -217 },
{ -6, -8, -11, -15, -20, -33, -52, -70, -89 } };
static int Xflags; //-2008-08-08
static TXTSTR LogCheck = { NULL, 0 };
//-----------------------------------------------------------------------------
TIPDAT TI;
ARYDSC TipVar;
ARYDSC TIPary;
ARYDSC PRCary; //-2018-10-29
FILE *TipMsgFile;
int TalMode;
static int PrmMode;
static TXTSTR TxtUser, TxtSystem;
static char Path[256], Home[256];
static int Write_z=0, Write_l=0;
static int nVarParm, nUsrParm; //-2011-12-02
static DMNFRMREC *TipFrmTab;
//================================================================= xcodeUnits
static void xcodeUnits() { //-2008-07-22
STTSPCREC *tsr; //-2011-11-23
char *uc, *un;
int i;
for (i=0; i tsr = SttSpcTab + i;
if (*tsr->name == 0)
break;
uc = tsr->uc;
un = tsr->un;
if (!strcmp(uc, U_GM3)) strcpy(uc, _U_GM3_);
else if (!strcmp(uc, U_MGM3)) strcpy(uc, _U_MGM3_);
else if (!strcmp(uc, U_UGM3)) strcpy(uc, _U_UGM3_);
else if (!strcmp(uc, U_PGM3)) strcpy(uc, _U_PGM3_);
else if (!strcmp(uc, U_1M3)) strcpy(uc, _U_1M3_);
else if (!strcmp(uc, U_PERC)) strcpy(uc, _U_PERC_);
if (!strcmp(un, U_GM2D)) strcpy(un, _U_GM2D_);
else if (!strcmp(un, U_MGM2D)) strcpy(un, _U_MGM2D_);
else if (!strcmp(un, U_UGM2D)) strcpy(un, _U_UGM2D_);
else if (!strcmp(un, U_PGM2D)) strcpy(un, _U_PGM2D_);
else if (!strcmp(un, U_1M2S)) strcpy(un, _U_1M2S_);
else if (!strcmp(un, U_KGHAA)) strcpy(un, _U_KGHAA_);
else if (!strcmp(un, U_PERC)) strcpy(un, _U_PERC_);
}
}
//================================================================= isUndefined
static int isUndefined( double d ) {
return (d == HUGE_VAL);
}
//=============================================================== TipBlmVersion
//
float TipBlmVersion( void )
{
dP(TipBlmVersion);
float vrs = 5.3; //-2018-10-04
char *pc_blm, *pc_noshear;
pc_blm = strstr(TI.os, "Blm="); //-2006-02-13
pc_noshear = strstr(TI.os, "NOSHEAR");
if (!NOSTANDARD) {
if (pc_blm || pc_noshear) eX(1);
}
else {
if (pc_blm && pc_noshear) eX(2);
if (pc_blm)
sscanf(pc_blm+4, "%f", &vrs);
else if (pc_noshear)
vrs = 5.2;
}
return vrs;
eX_1:
eMSG(_blm_nostandard_required_);
eX_2:
eMSG(_blm_explicit_);
}
//================================================================== TipZ0index
//
int TipZ0index( double z0 ) {
int i;
for (i=0; i if (z0 < 0.5*(z0TAL[i] + z0TAL[i+1])) break;
}
return i;
}
//================================================================== TipKMclass
//
int TipKMclass( double z0, double lm ) {
int k;
int iz = TipZ0index(z0);
double rlm = 1/lm;
for (k=0; k<5; k++) {
if (rlm > 0.5*(1/lmTAL[k][iz] + 1/lmTAL[k+1][iz])) break;
}
return k+1;
}
//====================================================================== TipMOvalue
//
double TipMOvalue( double z0, int kl ) {
int iz = TipZ0index(z0);
int ik = kl-1;
if (ik<0 || ik>5) ik = 2;
return lmTAL[ik][iz];
}
//-----------------------------------------------------------------------------------
static int check_tab( void ) {
int i, emitted;
STTSPCREC *p;
for (i=0; i emitted = TipSpcEmitted(i);
p = SttSpcTab + i;
if (TalMode & TIP_SCINOTAT) {
p->dy = -1;
p->dd = -1;
p->dh = -1;
p->dn = -1;
}
if (emitted) {
if (!strcmp(p->unit, "Bq")) TalMode |= TIP_GAMMA;
if (p->de > 0) TalMode |= TIP_DECAY;
if (StdLogLevel > 3)
fprintf(MsgFile, "%-5s: vd=%6.4f m/s, wf=%10.2e 1/s, we=%3.1f\n", p->name, p->vd, p->wf, p->we);
}
}
if (StdLogLevel > 3) {
char s[8];
sprintf(s, " 1234u");
for (i=1; i<=5; i++)
fprintf(MsgFile, "-%c : vd=%6.4f m/s, wf=%10.2e 1/s, we=%3.1f, vs=%6.4f m/s\n",
s[i], SttVdVec[i], SttWfVec[i], SttWeVec[i], SttVsVec[i]);
fprintf(MsgFile, "\n");
}
return i;
}
//================================================================= getCmpIndex
static int getCmpIndex( char *n ) {
int i;
for (i=0; i if (!strcmp(n, SttCmpNames[i]))
return i;
}
return -1; //-2011-11-23
}
//================================================================== init_index
static void init_index( void ) {
cNO2 = getCmpIndex("no2");
cNO = getCmpIndex("no");
cODOR = getCmpIndex("odor");
}
//======================================================================= parse
static int parse( char *line, TIPREC *pp ) {
dP(parse);
int i, n, l;
char *p1, c, tk[256];
if (!pp) eX(2);
pp->_name = NULL;
pp->nTokens = 0;
pp->_tokens = NULL;
pp->type = TIP_NUMBER;
pp->_dd = NULL;
if (line==NULL || !*line) return 0;
l = strlen(line);
for (i=l-1; i>0; i--)
if (line[i] <= ' ') line[i] = 0;
else break;
pp->_name = ALLOC(l+1); if (!pp->_name) eX(1);
strcpy(pp->_name, line);
for (p1=pp->_name; (isalnum(*p1) || *p1=='-' || *p1 == '_'); p1++); //-2008-03-10
if (!*p1) return 0;
*p1++ = 0;
if (!*pp->_name) return 0;
pp->_tokens = _MsgTokens(p1, " ;\t\r\n"); //-2024-01-17
if (!pp->_tokens) return 0;
for (n=0; ; n++)
if (!pp->_tokens[n]) break;
if (n == 0) return 0;
pp->nTokens = n;
for (i=0; i c = *pp->_tokens[i];
if (!isdigit(c) && c!='-' && c!='+' && c!='?')
pp->type = TIP_STRING;
}
if (pp->type == TIP_NUMBER) {
char *tail;
pp->_dd = ALLOC(n*sizeof(double));
for (i=0; i strncpy(tk, pp->_tokens[i], 255); //-2003-07-07
tk[255] = 0;
if (tk[0] == '?') {
pp->_dd[i] = HUGE_VAL;
}
else {
for (p1=tk; (*p1); p1++) if (*p1 == ',') *p1 = '.'; //-2003-07-07
pp->_dd[i] = strtod(tk, &tail);
if (*tail) {
FREE(pp->_dd);
pp->type = TIP_STRING;
break;
}
}
}
}
if (pp->type == TIP_STRING) {
for (i=0; i MsgUnquote(pp->_tokens[i]); //-2001-09-04
}
return pp->type;
eX_1: eX_2:
eMSG(_internal_error_);
}
static int TipIsConstant( TIPREC *tr ) {
int i;
if (!tr || tr->type==TIP_STRING || !tr->_dd) return 1;
for (i=0; inTokens; i++)
if (tr->_dd[i] == HUGE_VAL) return 0;
return 1;
}
static int TipMustBeConstant( char *name ) { //-2001-12-27
int i;
if (strstr(VarPrm, name)) return 0;
for (i=0; i if (!strcmp(SttCmpNames[i], name)) return 0; //-2002-01-06
}
return 1;
}
static char *missing_value( char *msg ) {
sprintf(msg, "%s", _missing_value_);
return msg;
}
static char *too_many_values( char *msg ) {
sprintf(msg, "%s", _too_many_values_);
return msg;
}
static char *size_exceeded( char *msg ) {
sprintf(msg, "%s", _string_too_long_);
return msg;
}
static char *unknown_name( char *msg ) {
sprintf(msg, "%s", _unknown_name_);
return msg;
}
static char *not_a_valid_number( char *msg ) {
sprintf(msg, "%s", _not_a_valid_number_);
return msg;
}
static char *must_be_constant( char *msg ) {
sprintf(msg, "%s", _must_be_constant_);
return msg;
}
static char *improper_count( char *msg, int n, int m ) {
sprintf(msg, _improper_count_$$_, n, m);
return msg;
}
static char *set_value( double *pv, TIPREC t, char *msg ) {
dQ(set_value);
if (t.nTokens < 1) missing_value(msg);
else if (t.nTokens > 1) too_many_values(msg);
else if (t.type != TIP_NUMBER) not_a_valid_number(msg);
else *pv = t._dd[0];
if (t._dd) FREE(t._dd);
return msg;
}
static char *set_integer( int *pi, TIPREC t, char *msg ) {
dQ(set_integer);
if (t.nTokens < 1) missing_value(msg);
else if (t.nTokens > 1) too_many_values(msg);
else if (t.type != TIP_NUMBER) not_a_valid_number(msg);
else *pi = t._dd[0];
if (t._dd) {
FREE(t._dd);
t._dd = NULL;
}
return msg;
}
static char *set_string( char *s, TIPREC t, char *msg ) {
if (t.nTokens < 1) missing_value(msg);
else if (t.nTokens > 1) too_many_values(msg);
else if (strlen(t._tokens[0]) > 255) size_exceeded(msg);
else strcpy(s, t._tokens[0]);
return msg;
}
static char *set_vector( double **ppv, TIPREC t, int *pn, char *msg ) {
if ((pn) && *pn==0) *pn = t.nTokens;
if (t.nTokens < 1) missing_value(msg);
else if (t.nTokens != *pn) improper_count(msg, *pn, t.nTokens);
else if (t.type != TIP_NUMBER) not_a_valid_number(msg);
else *ppv = t._dd;
return msg;
}
static char *set_ivector( int **ppi, TIPREC t, int *pn, char *msg ) {
dQ(set_ivector);
int i;
if ((pn) && *pn==0) *pn = t.nTokens;
if (t.nTokens < 1) missing_value(msg);
else if (t.nTokens != *pn) improper_count(msg, *pn, t.nTokens);
else if (t.type != TIP_NUMBER) not_a_valid_number(msg);
else {
*ppi = ALLOC(t.nTokens*sizeof(int));
for (i=0; i }
if (t._dd) {
FREE(t._dd);
t._dd = NULL;
}
return msg;
}
static int checkvar( int check, double *pd, int n, char *name, int *pi ) {
int k, j;
TIPVAR *ptv;
char *pc, grp[40], nm[40];
if (!pd)
return 0;
for (k=0; k if (!isUndefined(pd[k]))
continue;
if (check) { //-2005-09-27
(*pi)++;
continue;
}
ptv = AryPtrX(&TipVar, *pi);
(*pi)++; //-2007-04-23
strcpy(nm, name);
sprintf(ptv->name, "%02d.%s", k+1, nm);
if (strstr(VarPrm, nm)) {
if (!strcmp(nm, "zq")) strcpy(nm, "wl"); //-2018-10-04
else if (!strcmp(nm, "rq")) strcpy(nm, "rh"); //-2002-12-10
else if (!strcmp(nm, "sq")) strcpy(nm, "vw"); //-2018-10-04
else if (!strcmp(nm, "lq")) strcpy(nm, "lw"); //-2002-12-10
else if (!strcmp(nm, "tq")) strcpy(nm, "tt"); //-2002-12-10
sprintf(ptv->lasn, "%s.%02d", nm, k+1);
}
else {
strcpy(grp, "gas");
pc = strchr(nm, '-');
if (pc) { // dust component
for (j=1; j<6; j++) //-2005-09-27
if (!strcmp(pc, SttGrpXten[j])) {
strcpy(grp, SttGroups[j]);
break;
}
}
sprintf(ptv->lasn, "Eq.%02d.%s.%s", k+1, grp, nm);
}
ptv->p = pd+k;
}
return (check != 0); //-2005-09-27
}
//============================================================== analyse
static char *analyse( TIPREC t ) {
static char msg[256];
int i;
*msg = 0;
if (CHECK) {
vMsg("NAME=%s, TYPE=%d", t._name, t.type);
for (i=0; i vMsg("");
}
if (!strcmp(t._name, "ti")) set_string(TI.ti, t, msg);
else if (!strcmp(t._name, "as")) set_string(TI.as, t, msg);
else if (!strcmp(t._name, "az")) set_string(TI.az, t, msg);
else if (!strcmp(t._name, "os")) set_string(TI.os, t, msg);
else if (!strcmp(t._name, "gh")) set_string(TI.gh, t, msg);
else if (!strcmp(t._name, "in")) set_integer(&TI.in, t, msg); //-2020-10-14
else if (!strcmp(t._name, "ib")) set_integer(&TI.ib, t, msg); //-2020-10-14
else if (!strcmp(t._name, "gx")) set_value(&TI.gx, t, msg);
else if (!strcmp(t._name, "gy")) set_value(&TI.gy, t, msg);
else if (!strcmp(t._name, "ux")) set_value(&TI.ux, t, msg);
else if (!strcmp(t._name, "uy")) set_value(&TI.uy, t, msg);
else if (!strcmp(t._name, "nx")) set_ivector(&TI.nx, t, &TI.nn, msg);
else if (!strcmp(t._name, "ny")) set_ivector(&TI.ny, t, &TI.nn, msg);
else if (!strcmp(t._name, "nz")) set_ivector(&TI.nz, t, &TI.nn, msg);
else if (!strcmp(t._name, "dd")) set_vector(&TI.dd, t, &TI.nn, msg);
else if (!strcmp(t._name, "x0")) set_vector(&TI.x0, t, &TI.nn, msg);
else if (!strcmp(t._name, "x1")) set_vector(&TI.x1, t, &TI.nn, msg);
else if (!strcmp(t._name, "x2")) set_vector(&TI.x2, t, &TI.nn, msg);
else if (!strcmp(t._name, "x3")) set_vector(&TI.x3, t, &TI.nn, msg);
else if (!strcmp(t._name, "y0")) set_vector(&TI.y0, t, &TI.nn, msg);
else if (!strcmp(t._name, "y1")) set_vector(&TI.y1, t, &TI.nn, msg);
else if (!strcmp(t._name, "y2")) set_vector(&TI.y2, t, &TI.nn, msg);
else if (!strcmp(t._name, "y3")) set_vector(&TI.y3, t, &TI.nn, msg);
else if (!strcmp(t._name, "z0")) set_value(&TI.z0, t, msg);
else if (!strcmp(t._name, "d0")) set_value(&TI.d0, t, msg);
else if (!strcmp(t._name, "xa")) set_value(&TI.xa, t, msg);
else if (!strcmp(t._name, "ya")) set_value(&TI.ya, t, msg);
else if (!strcmp(t._name, "ha")) set_value(&TI.ha, t, msg);
else if (!strcmp(t._name, "hm")) set_value(&TI.hm, t, msg);
else if (!strcmp(t._name, "ri")) { //-2018-10-02
if (PrmMode & TIP_TALDIA)
; // ignore "ri" if input file is read by TALdia //-2014-06-26
else
set_value(&TI.ri, t, msg); //-2014-01-21
}
else if (!strcmp(t._name, "ie")) set_value(&TI.ie, t, msg);
else if (!strcmp(t._name, "mh")) set_value(&TI.mh, t, msg);
else if (!strcmp(t._name, "im")) set_integer(&TI.im, t, msg);
else if (!strcmp(t._name, "qs")) set_integer(&TI.qs, t, msg);
else if (!strcmp(t._name, "qb")) set_integer(&TI.qb, t, msg);
else if (!strcmp(t._name, "sd")) set_integer(&TI.sd, t, msg);
else if (!strcmp(t._name, "hh")) set_vector(&TI.hh, t, &TI.nhh, msg);
else if (!strcmp(t._name, "xp")) set_vector(&TI.xp, t, &TI.np, msg);
else if (!strcmp(t._name, "yp")) set_vector(&TI.yp, t, &TI.np, msg);
else if (!strcmp(t._name, "hp")) set_vector(&TI.hp, t, &TI.np, msg);
else if (!strcmp(t._name, "aq")) set_vector(&TI.aq, t, &TI.nq, msg);
else if (!strcmp(t._name, "bq")) set_vector(&TI.bq, t, &TI.nq, msg);
else if (!strcmp(t._name, "cq")) set_vector(&TI.cq, t, &TI.nq, msg);
else if (!strcmp(t._name, "hq")) set_vector(&TI.hq, t, &TI.nq, msg);
else if (!strcmp(t._name, "dq")) set_vector(&TI.dq, t, &TI.nq, msg);
else if (!strcmp(t._name, "vq")) set_vector(&TI.vq, t, &TI.nq, msg);
else if (!strcmp(t._name, "tq")) set_vector(&TI.tq, t, &TI.nq, msg);
else if (!strcmp(t._name, "zq")) set_vector(&TI.zq, t, &TI.nq, msg); //-2018-10-04
else if (!strcmp(t._name, "rq")) set_vector(&TI.rq, t, &TI.nq, msg);
else if (!strcmp(t._name, "sq")) set_vector(&TI.sq, t, &TI.nq, msg); //-2018-10-04
else if (!strcmp(t._name, "lq")) set_vector(&TI.lq, t, &TI.nq, msg);
else if (!strcmp(t._name, "ts")) set_vector(&TI.ts, t, &TI.nq, msg); //-2018-10-04
else if (!strcmp(t._name, "rf")) set_vector(&TI.rf, t, &TI.nq, msg); //-2024-01-17
else if (!strcmp(t._name, "wq")) set_vector(&TI.wq, t, &TI.nq, msg);
else if (!strcmp(t._name, "xq")) set_vector(&TI.xq, t, &TI.nq, msg);
else if (!strcmp(t._name, "yq")) set_vector(&TI.yq, t, &TI.nq, msg);
else if (!strcmp(t._name, "iq")) set_vector(&TI.iq, t, &TI.nq, msg); //-2015-12-01
else if (!strcmp(t._name, "xb")) set_vector(&TI.xb, t, &TI.nb, msg);
else if (!strcmp(t._name, "yb")) set_vector(&TI.yb, t, &TI.nb, msg);
else if (!strcmp(t._name, "ab")) set_vector(&TI.ab, t, &TI.nb, msg);
else if (!strcmp(t._name, "bb")) set_vector(&TI.bb, t, &TI.nb, msg);
else if (!strcmp(t._name, "cb")) set_vector(&TI.cb, t, &TI.nb, msg);
else if (!strcmp(t._name, "wb")) set_vector(&TI.wb, t, &TI.nb, msg);
else if (!strcmp(t._name, "rb")) set_string(TI.bf, t, msg);
else if (!strcmp(t._name, "settingspath")) //bp
{ //bp
*msg = 0; //bp
} //bp
else if (!strcmp(t._name, "libpath")) //bp
{ //bp
strcpy(AbsoluteWindLibPath, t._tokens[0]); //bp
*msg = 0; //bp
} //bp
else {
for (i=0; i if (!strcmp(t._name, SttCmpNames[i])) {
set_vector(&TI.cmp[i], t, &TI.nq, msg);
break;
}
}
if (i >= SttCmpCount) unknown_name(msg);
}
if (!*msg && TipMustBeConstant(t._name) && !TipIsConstant(&t)) { //-2002-01-06
must_be_constant(msg);
}
return msg;
}
//=============================================================== TipSpcIndex
int TipSpcIndex( char *cmp_name ) {
char s[16], *pc;
int ks;
strcpy(s, cmp_name);
pc = strchr(s, '-');
if (pc) *pc = 0;
for (pc=s; (*pc); pc++) *pc = tolower(*pc);
for (ks=0; ks if (!strcmp(SttSpcTab[ks].name, s)) return ks;
}
return -1;
}
//============================================================= TipSpcEmitted
int TipSpcEmitted( int ks )
{
int ic, l;
char name[40];
if (ks<0 || ks>=SttSpcCount) return 0;
strcpy(name, SttSpcTab[ks].name);
if (!*name) return 0;
for (ic=0; ic if (!strcmp(SttCmpNames[ic], name) && (TI.cmp[ic])) return 1;
}
strcat(name, "-");
l = strlen(name);
for (ic=0; ic if (!strncmp(SttCmpNames[ic], name, l) && (TI.cmp[ic])) return 1;
}
return 0;
}
//=================================================================== TipRead
static int TipRead( char *path )
{
dP(TipRead);
FILE *f, *m;
int n=0, scanning=0, buflen=32000;
TIPREC t;
char *buf, *msg, name[256];
if (CHECK) vMsg("TipRead(%s) ...", path);
m = (MsgFile) ? MsgFile : stdout;
sprintf(name, "%s/%s", path, "austal.txt");
buf = ALLOC(buflen); if (!buf) eX(3);
f = fopen(name, "rb");
if (!f) {
vMsg(_cant_read_file_$_, name);
exit(2);
}
fprintf(m, "%s", _start_input_);
while (fgets(buf, buflen, f)) {
n++;
if (strlen(buf) >= buflen-2) eX(1);
if (!isalpha(*buf)) continue;
if (0 > parse(buf, &t)) eX(2);
fprintf(m, "> %s\n", buf); //-2001-06-09
MsgLow(t._name);
msg = analyse(t);
FREE(t._name);
FREE(t._tokens);
if (*msg) {
vMsg(_error_input_line_$$$_, n, buf, msg);
scanning = 1;
}
}
fclose(f);
fprintf(m, "%s", _end_input_);
FREE(buf);
fprintf(m, "\n");
if (scanning) return -1;
return n;
eX_1:
eMSG(_buffer_overflow_$_, n);
eX_2: eX_3:
eMSG(_internal_error_);
}
//============================================================= TipInitialize
//
static int TipInitialize( void ) {
dP(TipInitialize);
if (CHECK) vMsg("TipInitialize() ...");
TI.qs = 0; //-2020-10-14
TI.in = 3600;
TI.ib = 0; //-2024-01-17
TI.average = 24;
TI.qb = 0;
TI.gx = 0;
TI.gy = 0;
TI.ux = 0;
TI.uy = 0;
TI.dd = NULL;
TI.x0 = NULL;
TI.x1 = NULL;
TI.x2 = NULL;
TI.x3 = NULL;
TI.y0 = NULL;
TI.y1 = NULL;
TI.y2 = NULL;
TI.y3 = NULL;
TI.z0 = HUGE_VAL;
TI.d0 = HUGE_VAL;
TI.xq = NULL; //-2018-10-04
TI.yq = NULL; //-2018-10-04
TI.aq = NULL;
TI.bq = NULL;
TI.cq = NULL;
TI.hq = NULL;
TI.dq = NULL;
TI.vq = NULL;
TI.zq = NULL; //-2018-10-04
TI.rq = NULL; //-2018-10-04
TI.sq = NULL; //-2018-10-04
TI.lq = NULL; //-2018-10-04
TI.rf = NULL; //-2024-01-17
TI.ts = NULL; //-2018-10-04
TI.wq = NULL;
TI.iq = NULL; //-2015-12-01
TI.ha = 0; //-2002-04-16
TI.hm = 0;
TI.sc = 0; //-2011-11-23
TI.ri = -HUGE_VAL; //-2014-01-21
TI.xa = HUGE_VAL;
TI.ya = HUGE_VAL;
TI.sd = 11111;
TI.im = TipMaxIter; //-2008-10-20
TI.ie = TipEpsilon; //-2008-10-20
TI.mh = HUGE_VAL;
TI.npmax = 100; //bp //-2007-02-03
TI.xb = NULL;
TI.yb = NULL;
TI.ab = NULL;
TI.bb = NULL;
TI.cb = NULL;
TI.wb = NULL;
TI.xbmin = NULL;
TI.xbmax = NULL;
TI.ybmin = NULL;
TI.ybmax = NULL;
TI.dmk = ALLOC(9*sizeof(double)); if (!TI.dmk) return -1;
TI.dmk[0] = 6.0; // strength of recirculation
TI.dmk[1] = 1.0; // weighting of wind direction
TI.dmk[2] = 0.3; // strength of recirculation
TI.dmk[3] = 0.05; // Cut-Off
TI.dmk[4] = 0.7; // reduction of z-component
TI.dmk[5] = 1.2; // vertical relative extension
TI.dmk[6] = 15.0; // opening angle
TI.dmk[7] = 0.5; // strength of additional circulation
TI.dmk[8] = 0.3; // strength of additional turbulence
strcpy(TI.lc, "C"); //-2014-01-21
xcodeUnits(); //-2008-07-22
//bp TI.cmp = (double**)ALLOC(SttCmpCount*sizeof(double*)); //-2005-08-25
TI.cmp = (double**)ALLOC((SttCmpCount+1)*sizeof(double*)); //bp //-2005-08-25
init_index();
nADDODOR = SttCmpCount - 1 - cODOR; //-2024-01-17
if (nADDODOR > TIP_ADDODOR) eX(1);
return 0;
eX_1:
eMSG("maximum number of rated odorants exceeded (%d)!", TIP_ADDODOR);
}
//============================================================= TipCorine
//
static double TipCorine( int nq, double *xq, double *yq, double *hq, double *cq )
{ dP(TipCorine);
FILE *m;
double z0, z0m, z0g, x, y, h;
char *_buf=NULL;
char crc[16];
int n;
if (CHECK) vMsg("TipCorine(%d, ...) ...", nq);
m = (MsgFile) ? MsgFile : stdout;
z0m = 0;
z0g = 0;
n = TrlReadHeader(Home, TI.ggcs);
fprintf(m, "\n");
sprintf(crc, "%08x", RglCRC);
if ((strstr(RglFile, "gk") && !strcmp(crc, RGL_CRC_GK)) || //-2011-06-29
(strstr(RglFile, "utm") && !strcmp(crc, RGL_CRC_UTM)))
fprintf(m, _standard_register_$$_, RglFile, RglCRC);
else
vMsg(_nonstandard_register_$$_, RglFile, RglCRC);
vLOG(4)(_roughness2_$$_, RglGGCS, RglDelta);
vLOG(4)(_roughness3_$$$$_, RglXmin, RglXmax, RglYmin, RglYmax);
if (n)
return n;
for (n=0; n x = TI.gx + xq[n];
y = TI.gy + yq[n];
h = hq[n] + 0.5*cq[n];
if (h < 10.) h = 10.; //-2008-09-05
z0 = TrlGetZ0(TI.ggcs, x, y, 15*h, &_buf); //-2018-11-22
if (RglMrd > 0 && MsgFile) {
fprintf(MsgFile, _gkconverted_$$$$$$_, RglMrd, n+1, x, y, RglX, RglY); //-2006-11-21
}
if (z0 <= 0) {
TrlReadHeader(NULL, NULL);
return z0;
}
vLOG(4)(_roughness4_$$$$_, n+1, x, y, h);
vLOG(4)(_roughness5_$$$$_, RglA, RglB, _buf, z0);
z0m += z0*h*h;
z0g += h*h;
}
TrlReadHeader(NULL, NULL);
if (z0g > 0) z0m /= z0g;
return z0m;
}
//============================================================== checkSurface
//
#define ZZ(i,j) *(float*)AryPtrX(&dsc, i, j)
static float getMaxDif( ARYDSC dsc, int n ) {
int i, j, i1, i2, j1, j2;
float dz, dzmax;
if (dsc.numdm != 2) return -1;
if (n < 1) n = 1;
i1 = dsc.bound[0].low;
i2 = dsc.bound[0].hgh;
j1 = dsc.bound[1].low;
j2 = dsc.bound[1].hgh;
dzmax = 0;
for (i=i1; i<=i2; i++) {
for (j=j1+n; j<=j2; j++) {
dz = ZZ(i,j)-ZZ(i,j-n);
dz = (dz < 0) ? -dz : dz;
if (dz > dzmax) dzmax = dz;
}
}
for (j=j1; j<=j2; j++) {
for (i=i1+n; i<=i2; i++) {
dz = ZZ(i,j)-ZZ(i-n,j);
dz = (dz < 0) ? -dz : dz;
if (dz > dzmax) dzmax = dz;
}
}
return dzmax;
}
static float getMeanHeight( ARYDSC dsc ) {
int i, j, i1, i2, j1, j2;
float h;
if (dsc.numdm != 2) return -9999;
i1 = dsc.bound[0].low;
i2 = dsc.bound[0].hgh;
j1 = dsc.bound[1].low;
j2 = dsc.bound[1].hgh;
h = 0;
for (i=i1; i<=i2; i++)
for (j=j1; j<=j2; j++)
h += ZZ(i,j);
h /= (i2-i1+1)*(j2-j1+1);
return h;
}
static int checkSurface( int n ) {
dP(checkSurface);
char fn[256], gn[256];
char *ggcs=NULL; //-2008-12-11
TXTSTR usr = { NULL, 0 };
TXTSTR sys = { NULL, 0 };
int nx, ny;
double x0, y0, dd, d1, d2, gx, gy;
ARYDSC dsc;
sprintf(fn, "%s/zg%02d.dmna", Path, n+(TI.nn>1));
if (!TutFileExists(fn)) {
if (*TI.gh == '*') eX(10);
if (TutMakeName(fn, Path, TI.gh) < 0) eX(10); //-2001-11-23
if (!TutFileExists(fn)) eX(10);
return 0;
}
sprintf(gn, "%s/zg%02d", Path, n+(TI.nn>1));
memset(&dsc, 0, sizeof(ARYDSC));
DmnRead(gn, &usr, &sys, &dsc); eG(1);
if (dsc.numdm != 2) eX(2);
if (dsc.bound[0].low!=0 || dsc.bound[1].low!=0) eX(3);
nx = dsc.bound[0].hgh;
ny = dsc.bound[1].hgh;
if (1 > DmnGetDouble(usr.s, "xmin|x0", "%lf", &x0, 1)) eX(4);
if (1 > DmnGetDouble(usr.s, "ymin|y0", "%lf", &y0, 1)) eX(5);
if (1 > DmnGetDouble(usr.s, "dd|delt|delta", "%lf", &dd, 1)) eX(6);
if (1 > DmnGetDouble(usr.s, "gakrx|refx", "%lf", &gx, 1)) gx = 0; //-2008-12-11
if (1 > DmnGetDouble(usr.s, "gakry|refy", "%lf", &gy, 1)) gy = 0; //-2008-12-11
if (1 > DmnGetString(usr.s, "ggcs", &ggcs, 0)) ggcs = NULL; //-2008-12-11
if (TI.gx != gx) eX(16);
if (TI.gy != gy) eX(17);
if (ggcs && strcmp(TI.ggcs, ggcs)) eX(18); //-2008-12-11
if (TI.nx[n] != nx) eX(11);
if (TI.ny[n] != ny) eX(12);
if (TI.dd[n] != dd) eX(13);
if (TI.x0[n] != x0) eX(14);
if (TI.y0[n] != y0) eX(15);
if (isUndefined(TI.mh)) TI.mh = getMeanHeight(dsc);
d1 = getMaxDif(dsc, 1)/dd;
d2 = getMaxDif(dsc, 2)/(2*dd);
if (MsgFile) {
fprintf(MsgFile, "%s", _maximum_steepness_);
if (TI.nn > 1) fprintf(MsgFile, _within_grid_$_, n+1);
fprintf(MsgFile, _steepness_is_$$_, d1, d2);
}
AryFree(&dsc);
return 1;
eX_10:
eMSG(_no_surface_file_$_, fn); //-2003-06-24
eX_1:
eMSG(_cant_read_file_$_, fn);
eX_2: eX_3:
eMSG(_improper_file_structure_$_, fn);
eX_4: eX_5: eX_6:
eMSG(_missing_grid_parameters_$_, fn);
eX_11: eX_12: eX_13: eX_14: eX_15: eX_16: eX_17: eX_18: //-2008-12-11
eMSG(_inconsistent_grid_parameters_$_, fn);
}
#undef ZZ
//============================================================== makeSurface
//
static int makeSurface( int n ) {
dP(makeSurface);
char fn[256];
NTRREC nrec, irec;
double rx0, rx3, ry0, ry3, gx0, gx3, gy0, gy3;
float d1, d2;
int meridr, meridg;
char locale[256]="C";
if (TutMakeName(fn, Path, TI.gh) < 0) eX(10); //-2001-11-23
if (NtrReadFile(fn) < 0) eX(1); //-2001-10-01
irec = NtrGetInRec();
meridr = (TI.gx+TI.x0[n])/1000000;
meridg = (irec.gkx+irec.xmin)/1000000;
if (meridr != meridg) eX(3);
rx0 = TI.gx + TI.x0[n];
rx3 = TI.gx + TI.x3[n];
ry0 = TI.gy + TI.y0[n];
ry3 = TI.gy + TI.y3[n];
gx0 = irec.gkx + irec.xmin;
gx3 = irec.gkx + irec.xmax;
gy0 = irec.gky + irec.ymin;
gy3 = irec.gky + irec.ymax;
if (rx0gx3 || ry0gy3) eX(4);
nrec.nx = TI.nx[n]+1;
nrec.ny = TI.ny[n]+1;
nrec.xmin = TI.x0[n];
nrec.ymin = TI.y0[n];
nrec.delta = TI.dd[n];
nrec.gkx = TI.gx;
nrec.gky = TI.gy;
strcpy(nrec.ggcs, TI.ggcs); //-2008-12-11
NtrSetOutRec(nrec);
sprintf(fn, "%s/zg%02d", Path, n+(TI.nn>1));
//
if (*TI.lc) { //-2003-07-07
strcpy(locale, setlocale(LC_NUMERIC, NULL));
setlocale(LC_NUMERIC, TI.lc);
}
NtrWriteFile(fn); eG(2);
if (*TI.lc) setlocale(LC_NUMERIC, locale); //-2003-07-07
//
if (isUndefined(TI.mh)) TI.mh = getMeanHeight(NtrDsc);
d1 = getMaxDif(NtrDsc, 1)/TI.dd[n];
d2 = getMaxDif(NtrDsc, 2)/(2*TI.dd[n]);
if (MsgFile) {
fprintf(MsgFile, "%s", _maximum_steepness_);
if (TI.nn > 1) fprintf(MsgFile, _within_grid_$_, n+1);
fprintf(MsgFile, _steepness_is_$$_, d1, d2);
}
AryFree(&NtrDsc);
return 0;
eX_10: eX_1:
eMSG(_cant_read_surface_file_$_, fn);
eX_2:
eMSG(_cant_write_surface_profile_$_, fn);
eX_3:
eMSG(_inconsistent_systems_);
eX_4:
if (MsgFile) {
fprintf(MsgFile, _computational_area_$$$$_, rx0, rx3, ry0, ry3);
fprintf(MsgFile, _surface_area_$$$$_, gx0, gx3, gy0, gy3);
}
eMSG(_not_inside_surface_);
}
//============================================================== getNesting
//
static int getNesting( int nq, double *xm, double *ym, double *hq,
double *aq, double *bq, double *cq,
int nb, double *xb0, double *xb3, double *yb0,
double *yb3, double ddb, double gd[10][5] ) {
int i, j, n, k, kstart, gdset;
double d, dmin, xmin, xmax, ymin, ymax, x0, x3, y0, y3, h;
double a, b, r, x, y;
double rfac = 20;
double ddq = gd[0][0];
if (nq < 1) return -1;
xmin = gd[0][1];
xmax = gd[0][2];
ymin = gd[0][3];
ymax = gd[0][4];
dmin = (nb) ? ddb : ddq;
if (dmin <= 0) return -2;
xmin /= dmin;
xmax /= dmin;
ymin /= dmin;
ymax /= dmin;
d = 1;
kstart = 0;
gdset = -1;
if (nb) {
for (kstart=0; kstart<=1; kstart++) {
gd[kstart][0] = d;
d *= 2;
gd[kstart][1] = d*floor((xb0[kstart]/dmin)/d);
gd[kstart][2] = d*ceil((xb3[kstart]/dmin)/d);
gd[kstart][3] = d*floor((yb0[kstart]/dmin)/d);
gd[kstart][4] = d*ceil((yb3[kstart]/dmin)/d);
gdset = kstart;
if (d*dmin > ddq) {
d /= 2;
rfac *= ddq/(d*dmin);
break;
}
}
}
for (k=kstart; k<10; k++) {
x0 = x3 = xm[0]/dmin;
y0 = y3 = ym[0]/dmin;
for (n=0; n x = xm[n]/dmin;
y = ym[n]/dmin;
a = aq[n]/dmin;
b = bq[n]/dmin;
r = 0.5*sqrt(a*a+b*b);
h = (hq[n] + 0.5*cq[n])/dmin;
if (d <= 0.5*h) continue;
a = rfac*d + r;
if (x-a < x0) x0 = x-a;
if (x+a > x3) x3 = x+a;
if (y-a < y0) y0 = y-a;
if (y+a > y3) y3 = y+a;
}
if (k <= gdset) { //-2004-11-10
if (gd[k][1] < x0) x0 = gd[k][1];
if (gd[k][2] > x3) x3 = gd[k][2];
if (gd[k][3] < y0) y0 = gd[k][3];
if (gd[k][4] > y3) y3 = gd[k][4];
}
/*
if (k > 0) { //-2004-11-12
if (gd[k-1][1] < x0) x0 = gd[k-1][1];
if (gd[k-1][2] > x3) x3 = gd[k-1][2];
if (gd[k-1][3] < y0) y0 = gd[k-1][3];
if (gd[k-1][4] > y3) y3 = gd[k-1][4];
}
*/
gd[k][0] = d;
d *= 2;
x0 = d*floor(x0/d);
x3 = d*ceil(x3/d);
y0 = d*floor(y0/d);
y3 = d*ceil(y3/d);
if (x0 <= xmin+d) x0 = d*floor(xmin/d);
if (x3 >= xmax-d) x3 = d*ceil(xmax/d);
if (y0 <= ymin+d) y0 = d*floor(ymin/d);
if (y3 >= ymax-d) y3 = d*ceil(ymax/d);
if (k > 0) { //-2004-11-30
if (gd[k-1][1] < x0) x0 = d*floor(gd[k-1][1]/d);
if (gd[k-1][2] > x3) x3 = d*ceil(gd[k-1][2]/d);
if (gd[k-1][3] < y0) y0 = d*floor(gd[k-1][3]/d);
if (gd[k-1][4] > y3) y3 = d*ceil(gd[k-1][4]/d);
}
gd[k][1] = x0;
gd[k][2] = x3;
gd[k][3] = y0;
gd[k][4] = y3;
if (x0<=xmin && x3>=xmax && y0<=ymin && y3>=ymax) break;
}
if (k <= 9) k++;
for (i=0; i for (j=0; j<5; j++)
gd[i][j] *= dmin;
//
// add guard cells for inner grids
//
for (i=0; i d = gd[i][0]; //-2004-10-25
gd[i][1] -= 2*d;
gd[i][2] += 2*d;
gd[i][3] -= 2*d;
gd[i][4] += 2*d;
}
//
// check and possibly adjust or remove outer grid
//
d = 0.01;
n = 0;
if (k > 1) { //-2004-10-25
if (gd[k-1][1] + d >= gd[k-2][1]) {
gd[k-1][1] = gd[k-2][1];
n++;
}
if (gd[k-1][2] - d <= gd[k-2][2]) {
gd[k-1][2] = gd[k-2][2];
n++;
}
if (gd[k-1][3] + d >= gd[k-2][3]) {
gd[k-1][3] = gd[k-2][3];
n++;
}
if (gd[k-1][4] - d <= gd[k-2][4]) {
gd[k-1][4] = gd[k-2][4];
n++;
}
if (n == 4) k--;
}
return k;
}
//============================================================= checkGrid
//
static int overlap( int i, int j ) {
double xi1, xi2, yi1, yi2;
double xj1, xj2, yj1, yj2;
xi1 = TI.x1[i];
xi2 = TI.x2[i];
yi1 = TI.y1[i];
yi2 = TI.y2[i];
xj1 = TI.x1[j];
xj2 = TI.x2[j];
yj1 = TI.y1[j];
yj2 = TI.y2[j];
if (xi2 <= xj1) return 0;
if (xi1 >= xj2) return 0;
if (yi2 <= yj1) return 0;
if (yi1 >= yj2) return 0;
return 1;
}
static int checkGrid( void ) {
dP(checkGrid);
int n, nn, m, nx, ny, i, j;
double ddmin, ddmax, dd, x, y;
nn = TI.nn;
if (nn < 1) eX(1);
if (!TI.dd) eX(2);
TI.gl = ALLOC(nn*sizeof(int)); if (!TI.gl) eX(42);
TI.gi = ALLOC(nn*sizeof(int)); if (!TI.gi) eX(43);
//
// check spacing: smallest mesh width first
//
ddmax = ddmin = TI.dd[0]; //-2002-03-26
for (n=0; n dd = TI.dd[n];
if (dd == ddmax) continue;
if (dd < ddmax) eX(3);
if (dd != 2*ddmax) eX(4);
ddmax = dd;
}
dd = ddmax;
i = (nn > 1);
if (i && TI.dd[nn-2]==ddmax) eX(44); //-2002-09-21
m = i;
for (n=nn-1; n>=0; n--) {
if (TI.dd[n] < dd) {
m++;
i = 1;
dd = TI.dd[n];
}
TI.gl[n] = m;
TI.gi[n] = i++;
}
if (!TI.x0) eX(5);
if (!TI.y0) eX(6);
//
// check alignment: lower left border
//
for (n=0; n dd = 2*TI.dd[n];
for (m=n+1; m if (TI.dd[m] > dd) break;
if (fmod(TI.x0[n]-TI.x0[m], TI.dd[m]) != 0) eX(7);
if (fmod(TI.y0[n]-TI.y0[m], TI.dd[m]) != 0) eX(8);
}
}
//
// check alignment: right border
//
if (TI.nx) {
for (n=0; n if (TI.nx[n] < 1) eX(10);
dd = TI.dd[n];
if (dd }
}
if (TI.x3) {
for (n=0; n dd = TI.dd[n];
if (TI.nx) {
if (TI.x3[n] != TI.x0[n]+TI.nx[n]*dd) eX(12);
}
else {
if (fmod(TI.x3[n], dd) != 0) eX(13); //-2001-11-03
for (m=n+1; m if (TI.dd[m] > 2*dd) break;
if (fmod(TI.x3[n]-TI.x0[m], TI.dd[m]) != 0) eX(14);
}
}
}
}
else { // set right border
if (!TI.nx) eX(15);
TI.x3 = ALLOC(nn*sizeof(double)); if (!TI.x3) eX(16);
for (n=0; n TI.x3[n] = TI.x0[n] + TI.nx[n]*TI.dd[n];
}
if (!TI.nx) { // set number of x-intervals
TI.nx = ALLOC(nn*sizeof(int)); if (!TI.nx) eX(17);
for (n=0; n TI.nx[n] = (int)((TI.x3[n]-TI.x0[n])/TI.dd[n]+0.5);
}
// check number of x-intervals
for (n=0; n NxyMax) eX(51);
//
if (TI.x1) { // check inner left border
for (n=0; n if (fmod(TI.x1[n]-TI.x0[n], TI.dd[n]) != 0) eX(18); //-2005-05-12
}
else { // set inner left border
TI.x1 = ALLOC(nn*sizeof(double)); if (!TI.x1) eX(19);
for (n=0; n }
if (TI.x2) { // check inner right border
for (n=0; n if (fmod(TI.x3[n]-TI.x2[n], TI.dd[n]) != 0) eX(20); //-2005-05-12
}
else { // set inner right border
TI.x2 = ALLOC(nn*sizeof(double)); if (!TI.x2) eX(21);
for (n=0; n }
//
// check alignment: upper border
//
if (TI.ny) {
for (n=0; n if (TI.ny[n] < 1) eX(30);
dd = TI.dd[n];
if (dd }
}
if (TI.y3) {
for (n=0; n dd = TI.dd[n];
if (TI.ny) {
if (TI.y3[n] != TI.y0[n]+TI.ny[n]*dd) eX(32);
}
else {
if (fmod(TI.y3[n], dd) != 0) eX(33); //-2001-11-03
for (m=n+1; m if (TI.dd[m] > 2*dd) break;
if (fmod(TI.y3[n]-TI.y0[m], TI.dd[m]) != 0) eX(34);
}
}
}
}
else { // set upper border
if (!TI.ny) eX(35);
TI.y3 = ALLOC(nn*sizeof(double)); if (!TI.y3) eX(36);
for (n=0; n TI.y3[n] = TI.y0[n] + TI.ny[n]*TI.dd[n];
}
if (!TI.ny) { // set number of y-intervals
TI.ny = ALLOC(nn*sizeof(int)); if (!TI.ny) eX(37);
for (n=0; n TI.ny[n] = (int)((TI.y3[n]-TI.y0[n])/TI.dd[n]+0.5);
}
// check number of y-intervals
for (n=0; n NxyMax) eX(52);
//
if (TI.y1) { // check lower inner border
for (n=0; n if (fmod(TI.y1[n]-TI.y0[n], TI.dd[n]) != 0) eX(38); //-2005-05-12
}
else { // set lower inner border
TI.y1 = ALLOC(nn*sizeof(double)); if (!TI.y1) eX(39);
for (n=0; n }
if (TI.y2) { // check upper inner border
for (n=0; n if (fmod(TI.y3[n]-TI.y2[n], TI.dd[n]) != 0) eX(40); //-2005-05-12
}
else { // set upper inner border
TI.y2 = ALLOC(nn*sizeof(double)); if (!TI.y2) eX(41);
for (n=0; n }
//
// check overlap of inner regions
//
for (n=0; n dd = TI.dd[n];
for (m=n+1; m if (dd < TI.dd[m]) break;
if (overlap(n, m)) {
vMsg(_no_overlap_$$_, n+1, m+1);
}
}
}
//
// check inclusion of finer grids
//
for (n=0; n dd = TI.dd[n];
if (dd == ddmax) break;
nx = TI.nx[n];
ny = TI.ny[n];
for (i=0; i x = TI.x0[n] + (i+0.5)*dd;
for (j=0; j y = TI.y0[n] + (j+0.5)*dd;
for (m=n+1; m if (TI.dd[m] == dd) continue;
if (TI.dd[m] > 2*dd) eX(50);
if (x>TI.x0[m] && xTI.y0[m] && y }
if (m >= nn) eX(50); //-2003-10-02
}
}
}
return 0;
//
eX_16: eX_17: eX_19: eX_21: eX_36: eX_37: eX_39: eX_41: eX_42: eX_43:
eMSG(_internal_error_);
eX_1: eX_2:
eMSG(_no_grid_);
eX_3:
eMSG(_increasing_mesh_width_required_);
eX_4:
eMSG(_factor_2_required_);
eX_5:
eMSG(_no_western_border_);
eX_6:
eMSG(_no_southern_border_);
eX_7:
eMSG(_improper_western_border_$_, n+1);
eX_8:
eMSG(_improper_southern_border_$_, n+1);
eX_10:
eMSG(_invalid_nx_$_, n+1);
eX_11:
eMSG(_even_nx_required_$_, n+1);
eX_12: eX_13:
eMSG(_improper_eastern_border_$_, n+1);
eX_14:
eMSG(_invalid_eastern_border_$_, n+1);
eX_15:
eMSG(_missing_nx_);
eX_18:
eMSG(_improper_x1_$_, n+1);
eX_20:
eMSG(_improper_x2_$_, n+1);
eX_30:
eMSG(_invalid_ny_$_, n+1);
eX_31:
eMSG(_even_ny_required_$_, n+1);
eX_32: eX_33:
eMSG(_improper_northern_border_$_, n+1);
eX_34:
eMSG(_invalid_northern_border_$_, n+1);
eX_35:
eMSG(_missing_ny_);
eX_38:
eMSG(_improper_y1_$_, n+1);
eX_40:
eMSG(_improper_y2_$_, n+1);
eX_44:
eMSG(_only_one_coarse_grid_);
eX_50:
eMSG(_$_not_within_coarse_grid_, n+1);
eX_51:
eMSG(_nx_too_large_$$_, n+1, NxyMax);
eX_52:
eMSG(_ny_too_large_$$_, n+1, NxyMax);
}
//============================================================== TipCheck
//
/* - not used? uj 2018-10-04
static TIPVAR *get_varptr( char *name ) { //-2005-09-23
TIPVAR *ptv = NULL;
int i;
if (!TipVar.start)
return NULL;
for (i=0; i ptv = AryPtrX(&TipVar, i);
if (!ptv)
return NULL;
if (!strcmp(name, ptv->name))
break;
ptv = NULL; //-2006-12-13
}
return ptv;
}
*/
int TipLogCheck(char *id, int sum) {
if (id != NULL) {
TXTSTR st = { NULL, 0 };
TxtPrintf(&st, "%s %-8s %08x\n", _checksum_, id, sum);
TxtCat(&LogCheck, st.s);
}
return 0;
}
static int TipCheck( char *path, int write_z ) {
dP(TipCheck);
char name[256], s[1024], elnm[40], fname[1024], prcname[1024]; //-2018-20-29
char locale[256]="C";
int i, j, i1, i2, k, n, l, emission, d=0, kpmax, rc, check; //-2011-11-23
int iq; //-2015-12-01
int make_surface=0, check_surface=0, series_exists=0;
int make_grid=0, make_nz=0, round_z0=1; //-2015-12-15
double x, y, z, xmin, ymin, xmax, ymax, z0, h, dz, r, co, si;
double f1, f2, f3, f4, f5, f6, f7, f8, f9;
double dd, dh, gd[10][5];
double hh[100];
DMNFRMREC *pfr;
TIPVAR *ptv;
TXTSTR syshdr = { NULL, 0 };
TXTSTR usrhdr = { NULL, 0 };
if (CHECK) vMsg("TipCheck(%s, %d) ...", path, write_z);
//
// check values
//
strcpy(locale, setlocale(LC_NUMERIC, NULL)); //-2008-10-17
if (*TI.os) { //-2004-07-09
char *ps;
for (ps=TI.os; (*ps); ps++) if (*ps == ',') *ps = '.'; //-2003-07-07
if (strstr(TI.os, "SCINOTAT")) { //-2003-02-21
TalMode |= TIP_SCINOTAT;
}
if (strstr(TI.os, "NOSTANDARD") || strstr(TI.os, "NONSTANDARD")) //-2008-08-27
TalMode |= TIP_NOSTANDARD;
if (strstr(TI.os, "NOTALUFT") || strstr(TI.os, "NONTALUFT")) //-2020-10-14
TalMode |= TIP_NOTALUFT;
if (strstr(TI.os, "BESMAX")) //-2024-01-17
TalMode |= TIP_BESMAX;
}
check_tab(); //-2005-08-25
if (!*TI.lc) strcpy(TI.lc, "C"); //-2003-07-07
else if (strcmp(TI.lc, "german") && strcmp(TI.lc, "C")) eX(242);
MsgSetLocale(TI.lc); //-2008-10-17
//////////////////////////////////////////////////////////////////////////////
// BESMAX
//////////////////////////////////////////////////////////////////////////////
if (BESMAX) { //-2024-01-17
int ixx;
STTSPCREC *pr;
unsigned int icrc;
char crc[16];
FILE *f;
//
vMsg(_besmax_);
//
// check substance
ixx = getCmpIndex("xx");
if (!TI.cmp[ixx]) {
vMsg(_besmax_xx_required_);
return -1;
}
for (i=0; i if (i != ixx && TI.cmp[i]) {
vMsg(_besmax_only_xx_allowed_);
return -1;
}
//
// adjust evaluation
pr = SttSpcTab + TipSpcIndex("xx");
pr->ry = 0;
pr->rn = 0;
pr->rd = 0;
pr->dh = -1;
pr->nh = 0;
pr->vd = 0;
pr->wf = 0;
strcpy(pr->uc, _U_MGM3_);
pr->fc = 1.e3;
pr->rh = 1;
if (isUndefined(TI.z0))
TI.z0 = 0.5;
if (isUndefined(TI.d0))
TI.d0 = 3.0;
if (isUndefined(TI.ha) || TI.ha == 0)
TI.ha = 13.0;
//
// checks
if (TI.z0 != 0.5) {
vMsg(_besmax_invalid_z0_);
return -1;
}
if (TI.d0 != 3.0) {
vMsg(_besmax_invalid_d0_);
return -1;
}
if (TI.ha != 13.0) {
vMsg(_besmax_invalid_ha_);
return -1;
}
//
// aks check
if (!*TI.as) {
vMsg(_besmax_as_notdefined_);
return -1;
}
if (TutMakeName(name, Path, TI.as) < 0) eX(10);
f = fopen(name, "rb");
if (!f) {
vMsg(_besmax_as_notfound_, name);
return -1;
}
icrc = TutGetCrc(name);
sprintf(crc, "%08x", icrc);
if (strcmp(crc, BESMAX_CRC)) {
vMsg(_besmax_as_modified_, BESMAX_CRC);
}
}
//////////////////////////////////////////////////////////////////////////////
// NOTALUFT
//////////////////////////////////////////////////////////////////////////////
if (NOTALUFT) { //-2020-10-14
vMsg(_notaluft_);
TI.average = 1;
if (strstr(TI.os, "VDI37831")) {
TalMode |= TIP_VDI37831;
if (TI.ib == 0)
TI.ib = 60.;
}
else if (TI.ib == 0)
TI.ib = 3600.;
}
//////////////////////////////////////////////////////////////////////////////
// TALUFT
//////////////////////////////////////////////////////////////////////////////
if (!NOTALUFT) {
if (TI.ib == 0)
TI.ib = 3600.;
int not_allowed = 0;
if (strstr(TI.os, "VDI37831")) {
vMsg(_$_notal_ignored_, "VDI37831");
not_allowed++;
}
if (TI.in != 3600) {
vMsg(_$_notal_ignored_, "in");
TI.in = 3600;
not_allowed++;
}
if (TI.ib != 3600) {
vMsg(_$_notal_ignored_, "ib");
TI.ib = 3600;
not_allowed++;
}
if (not_allowed)
return -1;
}
//////////////////////////////////////////////////////////////////////////////
// NOSTANDARD
//////////////////////////////////////////////////////////////////////////////
if (NOSTANDARD) {
char *pc;
int kref, kmax;
int d;
vMsg(_nostandard_);
setlocale(LC_NUMERIC, "C"); //-2008-10-17
if (strstr(TI.os, "LIB2")) TalMode |= TIP_LIB2;
else if (strstr(TI.os, "LIB36")) TalMode |= TIP_LIB36;
pc = strstr(TI.os, "Kref=");
if (pc) {
kref = 1;
sscanf(pc+5, "%d", &kref);
if (kref < 0) kref = 1;
if (TI.kp < kref) TI.kp = kref;
}
pc = strstr(TI.os, "Kmax=");
if (pc) {
kmax = 1;
sscanf(pc+5, "%d", &kmax);
if (kmax <= 0) kmax = 1;
if (TI.kp < kmax) TI.kp = kmax;
}
if (strstr(TI.os, "SORRELAX")) {
TalMode |= TIP_SORRELAX; //-2006-02-06
}
pc = strstr(TI.os, "BS="); //-2004-06-10
if (pc) sscanf(pc+3, "%lf", &SttOdorThreshold);
pc = strstr(TI.os, "SRCTRB="); //-2018-10-04
if (pc) sscanf(pc+7, "%lf", &SttSrcTurbulence);
pc = strstr(TI.os, "Average="); //-2007-02-03
if (pc) {
d = TI.average;
sscanf(pc+8, "%d", &d);
if (d > 0) TI.average = d;
}
pc = strstr(TI.os, "MntMax="); //-2007-02-03
if (pc) {
d = TI.npmax;
sscanf(pc+7, "%d", &d);
if (d > 200) d = 200;
if (d > TI.npmax) TI.npmax = d;
}
pc = strstr(TI.os, "DMKp=");
if (pc) {
n = sscanf(pc+5, "{%lf;%lf;%lf;%lf;%lf;%lf;%lf;%lf;%lf}",
&f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &f9);
if (n != 9) eX(300);
TI.dmk[0] = f1;
TI.dmk[1] = f2;
TI.dmk[2] = f3;
TI.dmk[3] = f4;
TI.dmk[4] = f5;
TI.dmk[5] = f6;
TI.dmk[6] = f7;
TI.dmk[7] = f8;
TI.dmk[8] = f9;
}
if (!isUndefined(TI.hm) && TI.hm != 0) {
vMsg(_$_not_time_dependent_, "hm"); //-2011-12-02
TI.hm = 0;
}
}
//
// complain about parameters that have been set but require NOSTANDARD
else { //-2002-03-26
int not_allowed = 0; //-2011-12-16
if (strstr(TI.os, "WriteSeries")) { //-2024-01-17
vMsg(_$_option_ignored_, "WriteSeries");
not_allowed++;
}
if (strstr(TI.os, "Average=")) { //-2024-01-17
vMsg(_$_option_ignored_, "Average");
not_allowed++;
}
if (strstr(TI.os, "Glat=")) { //-2024-01-17
vMsg(_$_option_ignored_, "Glat");
not_allowed++;
}
if (strstr(TI.os, "Ta=")) { //-2024-01-17
vMsg(_$_option_ignored_, "Ta");
not_allowed++;
}
if (strstr(TI.os, "Rh=")) { //-2024-01-17
vMsg(_$_option_ignored_, "Rh");
not_allowed++;
}
if (strstr(TI.os, "MntMax=")) { //-2024-01-17
vMsg(_$_option_ignored_, "MntMax");
not_allowed++;
}
if (strstr(TI.os, "BS=")) { //-2024-01-17
vMsg(_$_option_ignored_, "BS");
not_allowed++;
}
if (strstr(TI.os, "Vd=")) { //-2024-01-17
vMsg(_$_option_ignored_, "Vd");
not_allowed++;
}
if (strstr(TI.os, "Vs=")) { //-2024-01-17
vMsg(_$_option_ignored_, "Vs");
not_allowed++;
}
if (strstr(TI.os, "Wf=")) { //-2024-01-17
vMsg(_$_option_ignored_, "Wf");
not_allowed++;
}
if (strstr(TI.os, "We=")) { //-2024-01-17
vMsg(_$_option_ignored_, "We");
not_allowed++;
}
if (strstr(TI.os, "DMKp=")) { //-2024-01-17
vMsg(_$_option_ignored_, "DMKp");
not_allowed++;
}
if (strstr(TI.os, "Kref=")) { //-2024-01-17
vMsg(_$_option_ignored_, "Kref");
not_allowed++;
}
if (strstr(TI.os, "Kmax=")) { //-2024-01-17
vMsg(_$_option_ignored_, "Kmax");
not_allowed++;
}
if (strstr(TI.os, "SRCTRB=")) { //-2024-01-17
vMsg(_$_option_ignored_, "SRCTRB");
not_allowed++;
}
if (strstr(TI.os, "WETDRIFT")) { //-2023-07-17
vMsg(_$_option_ignored_, "WETDRIFT");
not_allowed++;
}
if (strstr(TI.os, "NOSHEAR")) { //-2023-07-17
vMsg(_$_option_ignored_, "NOSHEAR");
not_allowed++;
}
if (strstr(TI.os, "NOSTDW")) { //-2023-07-17
vMsg(_$_option_ignored_, "NOSTDW");
not_allowed++;
}
if (strstr(TI.os, "SORRELAX")) { //-2023-07-17
vMsg(_$_option_ignored_, "SORRELAX");
not_allowed++;
}
if (strstr(TI.os, "SPECTRUM")) { //-2023-07-17
vMsg(_$_option_ignored_, "SPECTRUM");
not_allowed++;
}
if (strstr(TI.os, "LIB2")) { //-2024-01-17
vMsg(_$_option_ignored_, "LIB2");
not_allowed++;
}
if (strstr(TI.os, "LIB36")) { //-2024-01-17
vMsg(_$_option_ignored_, "LIB36");
not_allowed++;
}
if (TI.hm != 0) {
vMsg(_$_ignored_, "hm"); //-2008-10-20
TI.hm = 0;
not_allowed++;
}
if (TI.ie != TipEpsilon) {
vMsg(_$_ignored_, "ie"); //-2008-10-20
TI.ie = TipEpsilon;
not_allowed++;
}
if (TI.im != TipMaxIter) {
vMsg(_$_ignored_, "im"); //-2008-10-20
TI.im = TipMaxIter;
not_allowed++;
}
if (TI.mh != HUGE_VAL) {
vMsg(_$_ignored_, "mh"); //-2008-10-20
TI.mh = HUGE_VAL;
not_allowed++;
}
if (TI.x1 != NULL) {
vMsg(_$_ignored_, "x1"); //-2008-10-20
FREE(TI.x1);
TI.x1 = NULL;
not_allowed++;
}
if (TI.x2 != NULL) {
vMsg(_$_ignored_, "x2"); //-2008-10-20
FREE(TI.x2);
TI.x2 = NULL;
not_allowed++;
}
if (TI.x3 != NULL) {
vMsg(_$_ignored_, "x3"); //-2008-10-20
FREE(TI.x3);
TI.x3 = NULL;
not_allowed++;
}
if (TI.y1 != NULL) {
vMsg(_$_ignored_, "y1"); //-2008-10-20
FREE(TI.y1);
TI.y1 = NULL;
not_allowed++;
}
if (TI.y2 != NULL) {
vMsg(_$_ignored_, "y2"); //-2008-10-20
FREE(TI.y2);
TI.y2 = NULL;
not_allowed++;
}
if (TI.y3 != NULL) {
vMsg(_$_ignored_, "y3"); //-2008-10-20
FREE(TI.y3);
TI.y3 = NULL;
not_allowed++;
}
if (TI.hh != NULL) {
vMsg(_$_ignored_, "hh"); //-2012-04-06
FREE(TI.hh);
TI.hh = NULL;
not_allowed++;
}
if (TI.ts != NULL && !VDI37831) {
vMsg(_$_ignored_, "ts"); //-2018-10-04
FREE(TI.ts);
TI.ts = NULL;
not_allowed++;
}
if (BESMAX && strstr(TI.os, "NSUB5")) {
vMsg(_$_ignored_, "NSUB5");
not_allowed++;
}
if (VDI37831 && TI.ib != 60.) {
vMsg(_$_ignored_, "ib");
not_allowed++;
}
if (not_allowed) //-2011-12-16
return -1;
}
// end complain
//
// interval concentration
if (TI.in < 5 || TI.in > 3600) { //-2020-10-14
vMsg(_in_out_of_range_);
return -1;
}
//
// interval boundary layer model
if (TI.ib < 60 || TI.ib > 3600) { //-2020-10-14
vMsg(_ib_out_of_range_);
return -1;
}
if (TI.ib != 60 && VDI37831 && !NOSTANDARD) { //-2024-01-17
vMsg(_ib_60_required_);
return -1;
}
//
// mixing height variation only with time series
if (TI.hm != 0 && *TI.as) {
vMsg(_hm_not_with_aks_); //-2018-10-04
TI.hm = 0;
return -1;
}
//
// precipitation must be set time dependent
if (!*TI.as && TI.ri != -HUGE_VAL && !isUndefined(TI.ri)) { //-2014-01-21
vMsg(_ri_time_dependent_);
return -1;
}
//
// coordinate system
//
if ((TI.gx!=0 || TI.gy!=0) && (TI.ux!=0 || TI.uy!=0)) {
vMsg(_mixed_systems_);
return -1;
}
else if ((TI.gx==0 && TI.gy==0) && (TI.ux==0 && TI.uy==0))
strcpy(TI.ggcs, "");
else if ((TI.gx==0 && TI.gy==0) && (TI.ux!=0)) { //-2008-12-04
strcpy(TI.ggcs, "UTM");
TI.gx = TI.ux;
TI.gy = TI.uy;
if (TI.gx < 1000000) TI.gx += 32000000; //-2008-12-07
}
else if ((TI.gx!=0 && TI.gy!=0) && (TI.ux==0 && TI.uy==0))
strcpy(TI.ggcs, "GK");
else {
vMsg(_incomplete_coordinates_);
return -1;
}
//
if (isUndefined(TI.z0)) {
if (strlen(TI.ggcs) == 0) {
vMsg(_missing_z0_);
return -1;
}
}
else if (TI.z0 < 0) {
vMsg(_invalid_z0_);
return -1;
}
//
vMsg("Anzahl CPUs: %d ", numprocs); //bp
if (!NOSTANDARD) { //-2024-01-17
if ((!BESMAX && !VDI37831 && TI.qs>4) || (BESMAX && TI.qs>12) || (VDI37831 && TI.qs>16)) {
vMsg(_invalid_qs_);
return -1;
}
}
if (TI.qs < -4) {
vMsg(_invalid_qs_);
return -1;
}
//
// sources
//
if (TI.nq < 1) {
vMsg(_no_sources_);
return -1;
}
TI.xm = ALLOC(TI.nq*sizeof(double)); if (!TI.xm) eX(1);
TI.ym = ALLOC(TI.nq*sizeof(double)); if (!TI.ym) eX(2);
if (!TI.hq) {
vMsg(_no_stack_height_);
return -1;
}
if (!TI.iq) { //-2015-12-01
TI.iq = ALLOC(TI.nq*sizeof(double)); if (!TI.iq) eX(13);
}
if (!TI.aq) {
TI.aq = ALLOC(TI.nq*sizeof(double)); if (!TI.aq) eX(3);
}
if (!TI.bq) {
TI.bq = ALLOC(TI.nq*sizeof(double)); if (!TI.bq) eX(4);
}
if (!TI.cq) {
TI.cq = ALLOC(TI.nq*sizeof(double)); if (!TI.cq) eX(5);
}
if (!TI.dq) {
TI.dq = ALLOC(TI.nq*sizeof(double)); if (!TI.dq) eX(6);
}
if (!TI.vq) {
TI.vq = ALLOC(TI.nq*sizeof(double)); if (!TI.vq) eX(8);
}
if (!TI.tq) {
TI.tq = ALLOC(TI.nq*sizeof(double)); if (!TI.tq) eX(7);
for (n=0; n }
if (!TI.zq) { //-2018-10-04
TI.zq = ALLOC(TI.nq*sizeof(double)); if (!TI.zq) eX(7);
}
if (!TI.rq) {
TI.rq = ALLOC(TI.nq*sizeof(double)); if (!TI.rq) eX(7);
}
if (!TI.sq) { //-2018-10-04
TI.sq = ALLOC(TI.nq*sizeof(double)); if (!TI.sq) eX(7);
}
if (!TI.lq) {
TI.lq = ALLOC(TI.nq*sizeof(double)); if (!TI.lq) eX(7);
}
if (!TI.rf) { //-2024-01-17
TI.rf = ALLOC(TI.nq*sizeof(double)); if (!TI.rf) eX(7);
for (n=0; n }
if (!TI.ts) { //-2018-10-04
TI.ts = ALLOC(TI.nq*sizeof(double)); if (!TI.ts) eX(7);
for (n=0; n }
if (!TI.wq) {
TI.wq = ALLOC(TI.nq*sizeof(double)); if (!TI.wq) eX(9);
}
if (!TI.xq) {
TI.xq = ALLOC(TI.nq*sizeof(double)); if (!TI.xq) eX(10);
}
if (!TI.yq) {
TI.yq = ALLOC(TI.nq*sizeof(double)); if (!TI.yq) eX(11);
}
if (cNO2 >= 0 && cNO >= 0 && !TI.cmp[cNO2] && TI.cmp[cNO]) { //2011-11-23
TI.cmp[cNO2] = ALLOC(TI.nq*sizeof(double)); if (!TI.cmp[cNO2]) eX(12);
}
for (n=0; n if (fabs(TI.xq[n]) > TIP_MAXLENGTH) { strcpy(s, "xq"); eX(240); }
if (fabs(TI.yq[n]) > TIP_MAXLENGTH) { strcpy(s, "yq"); eX(240); }
if (TI.hq[n]<0 || TI.hq[n]>900) { //-2019-03-05
vMsg(_invalid_stack_height_$_, n+1);
return -1;
}
if (TI.hq[n] < 10 && TI.iq[n] < 1 && !NOTALUFT) { //-2015-12-01 -2020-10-14
vMsg(_low_stack_height_$_, n+1);
}
if (TI.aq[n] < 0) {
vMsg(_invalid_aq_$_, n+1);
return -1;
}
if (TI.bq[n] < 0) {
vMsg(_invalid_bq_$_, n+1);
return -1;
}
if (TI.cq[n]<0 || TI.cq[n]+TI.hq[n]>900) { //-2019-03-05
vMsg(_invalid_cq_$_, n+1);
return -1;
}
if (TI.dq[n] < 0) {
vMsg(_invalid_dq_$_, n+1);
return -1;
}
if (TI.ts[n] < 0 && TI.vq[n] > 0 && TI.dq[n] == 0) { //-2024-01-17
vMsg(_invalid_dq_with_vq_$_, n+1);
return -1;
}
if (TI.ts[n] < 0 && TI.dq[n] > 0 && TI.vq[n] == 0) { //-2024-01-17
vMsg(_invalid_vq_with_dq_$_, n+1);
return -1;
}
if (TI.vq[n] < 0 && !VDI37831) { //-2020-10-14
vMsg(_invalid_vq_$_, n+1);
return -1;
}
if (TI.wq[n]<-360 || TI.wq[n]>360) {
vMsg(_invalid_wq_$_, n+1);
return -1;
}
co = cos(TI.wq[n]/RADIAN);
si = sin(TI.wq[n]/RADIAN);
TI.xm[n] = TI.xq[n] + 0.5*(TI.aq[n]*co - TI.bq[n]*si); //-2001-09-04
TI.ym[n] = TI.yq[n] + 0.5*(TI.bq[n]*co + TI.aq[n]*si); //-2001-09-04
//
if (TI.iq[n] != 0) { //-2015-12-01
if (!isUndefined(TI.iq[n])) {
iq = TI.iq[n];
if (iq != TI.iq[n]) {
vMsg(_invalid_iq_$_, n+1);
return -1;
}
sprintf(fname, "%s/%02d/e%04d.dmna", Path, n+1, iq);
if (!TutFileExists(fname)) {
vMsg(_missing_grid_src_file_$_, fname);
return -1;
}
}
else {
sprintf(fname, "%s/%02d", Path, n+1);
if (!TutDirExists(fname)) {
vMsg(_missing_grid_src_dir_$_, fname);
return -1;
}
}
}
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// check for buildings //-2004-07
//
if (TI.nb > 0 && strlen(TI.bf) > 0) eX(312);
if (TI.nb > 0 || strlen(TI.bf) > 0) {
TI.xbmin = ALLOC(2*sizeof(double)); if (!TI.xbmin) eX(301);
TI.xbmax = ALLOC(2*sizeof(double)); if (!TI.xbmax) eX(301);
TI.ybmin = ALLOC(2*sizeof(double)); if (!TI.ybmin) eX(301);
TI.ybmax = ALLOC(2*sizeof(double)); if (!TI.ybmax) eX(301);
BodyHmax = 0;
}
if (!TI.xb) {
TI.xb = ALLOC(TI.nb*sizeof(double)); if (!TI.xb) eX(301);
}
if (!TI.yb) {
TI.yb = ALLOC(TI.nb*sizeof(double)); if (!TI.yb) eX(301);
}
if (!TI.ab) {
TI.ab = ALLOC(TI.nb*sizeof(double)); if (!TI.ab) eX(301);
}
if (!TI.bb) {
TI.bb = ALLOC(TI.nb*sizeof(double)); if (!TI.bb) eX(301);
}
if (!TI.cb) {
TI.cb = ALLOC(TI.nb*sizeof(double)); if (!TI.cb) eX(301);
}
if (!TI.wb) {
TI.wb = ALLOC(TI.nb*sizeof(double)); if (!TI.wb) eX(301);
}
for (n=0; n if (fabs(TI.xb[n]) > TIP_MAXLENGTH) { strcpy(s, "xb"); eX(240); }
if (fabs(TI.yb[n]) > TIP_MAXLENGTH) { strcpy(s, "yb"); eX(240); }
if (TI.ab[n] < 0 ) {
vMsg(_invalid_ab_$_, n+1);
return -1;
}
if (TI.bb[n] < 0 && TI.ab[n] != 0) {
vMsg(_improper_ab_$_, n+1);
return -1;
}
if (TI.cb[n] < 0) {
vMsg(_invalid_cb_$_, n+1);
return -1;
}
co = cos(TI.wb[n]/RADIAN); //-2004-12-14
si = sin(TI.wb[n]/RADIAN); //-2004-12-14
if (TI.bb[n] > 0) {
x = TI.xb[n] + 0.5*(TI.ab[n]*co - TI.bb[n]*si);
y = TI.yb[n] + 0.5*(TI.bb[n]*co + TI.ab[n]*si);
z = 0.5*sqrt(TI.ab[n]*TI.ab[n] + TI.bb[n]*TI.bb[n]);
}
else {
x = TI.xb[n];
y = TI.yb[n];
z = -0.5*TI.bb[n];
}
if (TI.cb[n] > BodyHmax) BodyHmax = TI.cb[n];
for (l=0; l<=1; l++) {
if (l == 0)
r = z + BodyRatio*TI.cb[n];
else
r = z + TurbRatio*TI.cb[n];
xmin = x - r;
xmax = x + r;
ymin = y - r;
ymax = y + r;
if (n == 0) {
TI.xbmin[l] = xmin;
TI.xbmax[l] = xmax;
TI.ybmin[l] = ymin;
TI.ybmax[l] = ymax;
}
else {
if (xmin < TI.xbmin[l]) TI.xbmin[l]= xmin;
if (xmax > TI.xbmax[l]) TI.xbmax[l] = xmax;
if (ymin < TI.ybmin[l]) TI.ybmin[l] = ymin;
if (ymax > TI.ybmax[l]) TI.ybmax[l] = ymax;
}
}
}
memset(&BM, 0, sizeof(ARYDSC));
if (strlen(TI.bf) > 0) {
TI.nb = -1;
if (TutMakeName(name, Path, TI.bf) < 0) eX(10);
strcpy(TI.bf, name); //-2008-01-25
rc = DmnRead(name, &usrhdr, &syshdr, &BM); if (rc != 1) eX(320);
if (BM.numdm != 2 || BM.elmsz != sizeof(int)) eX(321);
if (DmnFrmTab->dt != inDAT) eX(327);
rc = DmnGetDouble(usrhdr.s, "dz", "%lf", &BMdz, 1);
if (rc != 1 || BMdz < 1) eX(322);
rc = DmnGetDouble(usrhdr.s, "x0|xmin", "%lf", &BMx0, 1);
if (rc != 1) eX(323);
rc = DmnGetDouble(usrhdr.s, "y0|ymin", "%lf", &BMy0, 1);
if (rc != 1) eX(324);
rc = DmnGetDouble(usrhdr.s, "dd|delta|delt", "%lf", &BMdd, 1);
if (rc != 1 || BMdz < 1) eX(325);
if (fabs(BMx0) > TIP_MAXLENGTH || fabs(BMy0) > TIP_MAXLENGTH) eX(326);
n = 0;
for (i=BM.bound[0].low; i<=BM.bound[0].hgh; i++)
for (j=BM.bound[1].low; j<=BM.bound[1].hgh; j++) {
k = *(int *)AryPtr(&BM, i, j);
if (k == 0) continue;
x = BMx0 + (i-BM.bound[0].low+0.5)*BMdd;
y = BMy0 + (j-BM.bound[1].low+0.5)*BMdd;
z = k * BMdz;
if (z > BodyHmax) BodyHmax = z;
for (l=0; l<=1; l++) {
r = (l==0) ? BMdd/2 + BodyRatio*z : BMdd/2 + TurbRatio*z;
xmin = x - r;
xmax = x + r;
ymin = y - r;
ymax = y + r;
if (n == 0) {
TI.xbmin[l] = xmin;
TI.xbmax[l] = xmax;
TI.ybmin[l] = ymin;
TI.ybmax[l] = ymax;
}
else {
if (xmin < TI.xbmin[l]) TI.xbmin[l] = xmin;
if (xmax > TI.xbmax[l]) TI.xbmax[l] = xmax;
if (ymin < TI.ybmin[l]) TI.ybmin[l] = ymin;
if (ymax > TI.ybmax[l]) TI.ybmax[l] = ymax;
}
}
n++;
}
TI.nb = -n;
}
if (TI.nb) {
vMsg(_maximum_height_$_, BodyHmax);
if (BodyHmax == 0)
TI.nb = 0;
else {
TalMode |= TIP_BODIES;
TalMode |= TIP_NESTING;
// checkBodiesAndSources(); deprecated for TA Luft 2021 -2021-07-03
if (TI.qb>1 || TI.qb<-3) {
vMsg(_invalid_qb_);
return -1;
}
BodyDd = BodyDda[3+TI.qb];
BodyDz = BodyDza[3+TI.qb];
}
}
if (strstr(TI.os, "-NESTING"))
TalMode &= ~TIP_NESTING;
else if (strstr(TI.os, "NESTING"))
TalMode |= TIP_NESTING;
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//
// check and/or define grid
//
if (TI.nn > 0) { //-2001-10-24
for (n=0; n if ((TI.x0) && (fabs(TI.x0[n])>TIP_MAXLENGTH)) { strcpy(s, "x0"); eX(240); }
if ((TI.y0) && (fabs(TI.y0[n])>TIP_MAXLENGTH)) { strcpy(s, "y0"); eX(240); }
}
checkGrid(); eG(213);
if (*TI.gh) check_surface = 1;
if (!TI.nz) {
TI.nz = ALLOC(TI.nn*sizeof(int)); if (!TI.nz) eX(234);
}
}
else {
make_grid = 1;
dd = TI.hq[0] + 0.5*TI.cq[0]; //-2001-10-18
for (n=1; n dh = TI.hq[n] + 0.5*TI.cq[n]; //-2001-10-18
if (dd > dh) dd = dh;
}
if (BESMAX) { //-2024-01-17
dd = floor(0.5*dd);
if (dd < 0.5*DdMin)
dd = 0.5*DdMin;
}
else {
dd = floor(dd);
if (dd < DdMin)
dd = DdMin;
}
xmin = TI.xm[0]; //-2002-07-13
xmax = TI.xm[0];
ymin = TI.ym[0];
ymax = TI.ym[0];
for (n=0; n double x, y, r;
r = RadRatio*TI.hq[n]; //-2002-07-13
if (r < RadMin) r = RadMin; //-2002-07-13
x = TI.xm[n] - r;
if (x < xmin) xmin = x;
x = TI.xm[n] + r;
if (x > xmax) xmax = x;
y = TI.ym[n] - r;
if (y < ymin) ymin = y;
y = TI.ym[n] + r;
if (y > ymax) ymax = y;
}
if (!(TalMode & TIP_NESTING) && (TalMode & TIP_BODIES)) {
dd = BodyDd;
if (TI.xbmin[1] < xmin) xmin = TI.xbmin[1];
if (TI.xbmax[1] > xmax) xmax = TI.xbmax[1];
if (TI.ybmin[1] < ymin) ymin = TI.ybmin[1];
if (TI.ybmax[1] > ymax) ymax = TI.ybmax[1];
}
xmin = dd*floor(xmin/dd+0.001);
xmax = dd*ceil(xmax/dd-0.001);
ymin = dd*floor(ymin/dd+0.001);
ymax = dd*ceil(ymax/dd-0.001);
if (BESMAX && TI.nq == 1) { //-2024-01-17
// source in centre of grid cell
xmin -= 0.5*dd;
xmax += 0.5*dd;
ymin -= 0.5*dd;
ymax += 0.5*dd;
}
gd[0][0] = dd;
gd[0][1] = xmin;
gd[0][2] = xmax;
gd[0][3] = ymin;
gd[0][4] = ymax;
if (TalMode & TIP_NESTING) {
TI.nn = getNesting(TI.nq, TI.xm, TI.ym, TI.hq, TI.aq, TI.bq, TI.cq,
TI.nb, TI.xbmin, TI.xbmax, TI.ybmin, TI.ybmax,
BodyDd, gd);
}
else TI.nn = 1;
TI.dd = ALLOC(TI.nn*sizeof(double)); if (!TI.dd) eX(220);
TI.x0 = ALLOC(TI.nn*sizeof(double)); if (!TI.x0) eX(221);
TI.x1 = ALLOC(TI.nn*sizeof(double)); if (!TI.x1) eX(222);
TI.x2 = ALLOC(TI.nn*sizeof(double)); if (!TI.x2) eX(223);
TI.x3 = ALLOC(TI.nn*sizeof(double)); if (!TI.x3) eX(224);
TI.y0 = ALLOC(TI.nn*sizeof(double)); if (!TI.y0) eX(225);
TI.y1 = ALLOC(TI.nn*sizeof(double)); if (!TI.y1) eX(226);
TI.y2 = ALLOC(TI.nn*sizeof(double)); if (!TI.y2) eX(227);
TI.y3 = ALLOC(TI.nn*sizeof(double)); if (!TI.y3) eX(228);
TI.gl = ALLOC(TI.nn*sizeof(int)); if (!TI.gl) eX(229);
TI.gi = ALLOC(TI.nn*sizeof(int)); if (!TI.gi) eX(230);
TI.nx = ALLOC(TI.nn*sizeof(int)); if (!TI.nx) eX(231);
TI.ny = ALLOC(TI.nn*sizeof(int)); if (!TI.ny) eX(232);
TI.nz = ALLOC(TI.nn*sizeof(int)); if (!TI.nz) eX(233);
for (n=0; n TI.dd[n] = gd[n][0];
TI.x0[n] = gd[n][1];
TI.x1[n] = gd[n][1];
TI.x2[n] = gd[n][2];
TI.x3[n] = gd[n][2];
TI.y0[n] = gd[n][3];
TI.y1[n] = gd[n][3];
TI.y2[n] = gd[n][4];
TI.y3[n] = gd[n][4];
TI.nx[n] = (int)((TI.x3[n]-TI.x0[n])/TI.dd[n] + 0.5);
TI.ny[n] = (int)((TI.y3[n]-TI.y0[n])/TI.dd[n] + 0.5);
TI.nz[n] = 0;
TI.gl[n] = TI.nn - n - (TI.nn==1);
TI.gi[n] = (TI.nn > 1);
}
if (*TI.gh) check_surface = 1; //-2003-10-12
}
TipTrbExt = (TalMode & TIP_NESTING) && (TalMode & TIP_BODIES);
if (TipTrbExt
&& TI.nn > 1
&& TI.x0[0] <= TI.xbmin[1] //-2005-03-16
&& TI.x3[0] >= TI.xbmax[1] //-2005-03-16
&& TI.y0[0] <= TI.ybmin[1] //-2005-03-16
&& TI.y3[0] >= TI.ybmax[1]) TipTrbExt = 0; //-2005-03-16
if (CHECK) for (n=0; n "n=%d (%d,%d), dd=%1.1lf, x0=%1.0lf, x3=%1.0lf, nx=%d, y0=%1.0lf, y3=%1.0lf, ny=%d\n",
n, TI.gl[n], TI.gi[n], TI.dd[n], TI.x0[n], TI.x3[n], TI.nx[n], TI.y0[n], TI.y3[n], TI.ny[n]);
//
// set vertical grid //-2004-07
if (TI.hh && NOSTANDARD) { //-2002-08-02
if (TI.nhh < 2) {
vMsg(_no_vertical_grid_);
return -1;
}
if (TI.hh[0] != 0) {
vMsg(_invalid_footpoint_);
return -1;
}
for (k=1; k if (TI.hh[k] <= TI.hh[k-1]) {
vMsg(_invalid_vertical_grid_);
return -1;
}
}
}
else {
if (TI.hh) { //-2002-08-02
FREE(TI.hh);
vMsg(_hh_ignored_);
}
if (!TI.nb) {
if (VDI37831) {
TI.nhh = sizeof(Hh37831)/sizeof(double);
TI.hh = ALLOC(sizeof(Hh37831)); if (!TI.hh) eX(20);
memcpy(TI.hh, Hh37831, sizeof(Hh37831));
}
else {
TI.nhh = sizeof(Hh)/sizeof(double);
TI.hh = ALLOC(sizeof(Hh)); if (!TI.hh) eX(20);
memcpy(TI.hh, Hh, sizeof(Hh));
}
}
else {
double *hused = (VDI37831) ? Hh37831 : Hh;
n = (VDI37831) ? sizeof(Hh37831)/sizeof(double) : sizeof(Hh)/sizeof(double);
// (almost) equal intervals in the lower part
hh[0] = 0;
hh[1] = (VDI37831) ? 2 : 3;
k = 1;
z = BodyDz * (int)(2.0*BodyHmax/BodyDz + 0.5);
if (z < FinestGridZmin) //-2019-01-04
z = FinestGridZmin;
while (hh[k] ++k;
hh[k] = hh[k-1]+BodyDz;
}
// check for next valid height of the default vertical grid
for (i=0; i if (hused[i] >= hh[k]) break;
if (i >= n-1) eX(400);
if (hused[i]-hh[k] < BodyDz) {
++k;
++i;
hh[k] = hh[k-1]+BodyDz;
}
// fill gap from equal spacing to default vertical grid
dz = floor(BodyDz*1.5);
while (hused[i]-(hh[k]+dz) >= dz && k<99) {
++k;
hh[k] = hh[k-1]+dz;
dz = floor(dz*1.5);
}
// continue with default vertical grid
k++;
while (i hh[k] = hused[i];
++k;
++i;
}
if (i!=n) eX(401);
TI.nhh = k;
TI.hh = ALLOC(k*sizeof(double)); if (!TI.hh) eX(20);
*s = 0;
for (i=0; i TI.hh[i] = hh[i];
sprintf(s, "%s %6.1f", s, hh[i]);
if ((i+1)%10 == 0) strcat(s, "\n");
}
if (i%10 != 0) strcat(s, "\n");
fprintf(MsgFile, _vertical_grid_$_, s);
fprintf(MsgFile, "----------------------------------------------------------------------\n");
}
}
// set vertical grid extent
TI.nzmax = TI.nhh - 1;
if (!TI.nb || TI.nn == 1) {
for (n=0; n TI.nz[n] = TI.nzmax;
}
else {
if (TI.nz[0] <= 0) {
make_nz = 1; //-2005-03-16
for (i=0; i if (TI.hh[i] >= 2*BodyHmax) break;
if (i >= TI.nhh) eX(404);
TI.nz[0] = i;
}
for (i=0; i if (TI.nz[i] <= 0)
TI.nz[i] = TI.nzmax;
}
// check
if (TI.nz[1] < TI.nzmax) eX(408); //-2006-02-11
for (i=0; i if (TI.nz[i] > TI.nzmax) eX(405);
if (i > 0 && TI.nz[i] < TI.nz[i-1]) eX(406);
if (i == 0 && TI.hh[TI.nz[i]] < 2*BodyHmax) eX(407);
}
// set user defined nzmax
TI.nzmax = 0;
for (i=0; i if (TI.nz[i] > TI.nzmax)
TI.nzmax = TI.nz[i];
}
if (TI.kp > TI.nzmax)
TI.kp = TI.nzmax;
if (make_grid || make_nz) { //-2005-03-16
fprintf(MsgFile, "%s", _computational_grid_);
fprintf(MsgFile, "dd");
for (n=0; n fprintf(MsgFile, "\n");
fprintf(MsgFile, "x0");
for (n=0; n fprintf(MsgFile, "\n");
fprintf(MsgFile, "nx");
for (n=0; n fprintf(MsgFile, "\n");
fprintf(MsgFile, "y0");
for (n=0; n fprintf(MsgFile, "\n");
fprintf(MsgFile, "ny");
for (n=0; n fprintf(MsgFile, "\n");
fprintf(MsgFile, "nz");
for (n=0; n fprintf(MsgFile, "\n");
fprintf(MsgFile, "--");
for (n=0; n fprintf(MsgFile, "\n");
checkGrid(); eG(313);
}
// end set vertical grid
//
// check anemometer position -2002-01-12, 2005-03-16 moved to here
//
if (TI.xa==HUGE_VAL || TI.ya==HUGE_VAL) {
if (*TI.gh || TI.nb) { eX(214); }
else {
TI.xa = TI.x0[0];
TI.ya = TI.y0[0];
}
}
else {
if (fabs(TI.xa) > TIP_MAXLENGTH) { strcpy(s, "xa"); eX(240); }
if (fabs(TI.ya) > TIP_MAXLENGTH) { strcpy(s, "ya"); eX(240); }
}
for (n=0; n if (TI.xa>=TI.x0[n] && TI.xa<=TI.x3[n]
&& TI.ya>=TI.y0[n] && TI.ya<=TI.y3[n]) break;
}
if (n >= TI.nn) eX(215);
//
if (*TI.gh) { // complex terrain: all surfaces defined?
if (check_surface && !make_surface) {
for (n=0; n k = checkSurface(n); eG(210);
if (!k) {
if (n == 0) make_surface = 1;
else if (!make_surface) eX(212);
}
}
}
if (make_surface) {
for (n=0; n makeSurface(n); eG(211);
}
}
else {
if (TI.nn == 1)
vMsg(_use_existing_zg_);
else if (TI.nn > 1)
vMsg(_use_existing_zgs_);
}
}
if (isUndefined(TI.mh)) TI.mh = 0;
for (n=0; n if (CHECK) printf("source %d, xm=%1.0lf, ym=%1.0lf\n", n+1, TI.xm[n], TI.ym[n]);
for (i=0; i if (TI.xm[n]>TI.x1[i] && TI.xm[n]TI.y1[i] && TI.ym[n] if (i >= TI.nn) {
vMsg(_source_outside_$_, n+1);
return -1;
}
}
if (isUndefined(TI.z0)) {
TI.z0 = TipCorine(TI.nq, TI.xm, TI.ym, TI.hq, TI.cq);
if (TI.z0 <= 0) {
vMsg(_no_z0_reason_);
if (TI.z0 == RGLE_FILE)
vMsg(_z0_file_not_found_$_, RglFile);
else if (TI.z0 == RGLE_XMIN)
vMsg(_z0_no_xmin_$_, RglFile);
else if (TI.z0 == RGLE_YMIN)
vMsg(_z0_no_ymin_$_, RglFile);
else if (TI.z0 == RGLE_DELT)
vMsg(_z0_no_delt_$_, RglFile);
else if (TI.z0 == RGLE_GGCS)
vMsg(_z0_no_ggcs_$_, RglFile);
else if (TI.z0 == RGLE_DIMS)
vMsg(_z0_not_2d_$_, RglFile);
else if (TI.z0 == RGLE_ILOW)
vMsg(_z0_invalid_low_bound_j_$_, RglFile);
else if (TI.z0 == RGLE_JIND)
vMsg(_z0_invalid_bounds_i_$_, RglFile);
else if (TI.z0 == RGLE_SEQN)
vMsg(_z0_no_sequ_$_, RglFile);
else if (TI.z0 == RGLE_SEQU)
vMsg(_z0_invalid_sequ_$_, RglFile);
else if (TI.z0 == RGLE_CSNE)
vMsg(_z0_improper_ggcs_$$$_, RglFile, RglGGCS, TI.ggcs);
else if (TI.z0 == RGLE_GKGK)
vMsg(_z0_invalid_source_$$$_, RglX, RglY, RglMrd);
else if (TI.z0 == RGLE_POUT) {
vMsg(_z0_source_outside_$$$_, RglX, RglY, RglFile);
vMsg(_z0_allowed_range_$$$$_, RglXmin, RglXmax, RglYmin, RglYmax);
}
else if (TI.z0 == RGLE_SECT)
vMsg(_z0_error_$_, RglFile);
else
vMsg(_z0_unspecified_error_);
vMsg("");
return -1;
}
if (MsgFile)
fprintf(MsgFile, _z0_average_z0_$_, TI.z0);
else
vMsg(_z0_average_z0_$_, TI.z0);
}
else round_z0 = !NOSTANDARD;
iZ0 = TipZ0index(TI.z0); //-2001-06-27
z0 = z0TAL[iZ0]; //
if (z0!=TI.z0 && round_z0) {
vMsg(_z0_rounded_$_, z0); //
TI.z0 = z0; //
} //
if (isUndefined(TI.d0)) TI.d0 = 6*TI.z0;
else if (TI.d0 < 0) {
vMsg(_invalid_d0_);
return -1;
}
//
// check definition of odor emissions //-2008-03-10
//
emission = 0;
if (cODOR >= 0) {
for (i=0; i if (TI.cmp[cODOR+i+1] != NULL)
emission++; // rated odor component
}
if (emission > 0) {
double* oe = TI.cmp[cODOR];
if (oe != NULL) {
vMsg(_source_strength_ignored_);
}
else {
oe = ALLOC(TI.nq*sizeof(double));
TI.cmp[cODOR] = oe;
}
for (n=0; n oe[n] = 0;
TalMode |= TIP_ODORMOD;
}
}
//
// check variable parameters
//
AryFree(&TipVar);
nVarParm = 0;
nUsrParm = 0;
emission = 0;
for (check=1; check>=0; check--) { //-2005-09-23
int nv = 0; //-2006-12-13
checkvar(check, TI.vq, TI.nq, "vq", &nv); //-2006-12-13
checkvar(check, TI.tq, TI.nq, "tq", &nv); //-2006-12-13
checkvar(check, TI.zq, TI.nq, "zq", &nv); //-2018-10-04
checkvar(check, TI.rq, TI.nq, "rq", &nv); //-2006-12-13
checkvar(check, TI.sq, TI.nq, "sq", &nv); //-2018-10-04
checkvar(check, TI.lq, TI.nq, "lq", &nv); //-2011-11-23
checkvar(check, TI.ts, TI.nq, "ts", &nv); //-2018-10-04
checkvar(check, TI.iq, TI.nq, "iq", &nv); //-2015-12-01
for (n=0; n strcpy(name, SttCmpNames[n]);
k = checkvar(check, TI.cmp[n], TI.nq, name, &nv); //-2006-12-13
if (check && k) {
emission++;
}
}
if (check) {
if (!emission) {
vMsg(_no_emissions_);
return -1;
}
nUsrParm = nv;
if (isUndefined(TI.hm))
nv++;
if (isUndefined(TI.ri))
nv++;
nVarParm = nv; //-2006-12-13
AryCreate(&TipVar, sizeof(TIPVAR), 1, 0, nVarParm-1); eG(21);
}
else { // optional parameters -2011-12-08
if (isUndefined(TI.hm)) {
ptv = AryPtrX(&TipVar, nv);
strcpy(ptv->name, "hm");
ptv->p = &TI.hm;
nv++;
}
if (isUndefined(TI.ri)) {
ptv = AryPtrX(&TipVar, nv);
strcpy(ptv->name, "ri");
ptv->p = &TI.ri;
nv++;
}
}
}
if (nUsrParm > 0) TalMode |= TIP_VARIABLE;
//
// check monitor points
//
if (TI.np > 0) {
if (TI.np > TI.npmax) eX(241); //-2006-10-17
if (TI.xp && TI.yp) {
for (i=0; i for (n=0; n if (TI.xp[i]>TI.x0[n] && TI.xp[i]TI.y0[n] && TI.yp[i] break;
if (n >= TI.nn) {
vMsg(_monitor_outside_$_, i+1);
return -1; //-2002-02-26
}
}
}
else {
vMsg(_missing_xy_);
return -1;
}
if (!TI.hp) {
TI.hp = ALLOC(TI.np*sizeof(double));
for (i=0; i }
// check maximum height of monitor points (for nzdos) 2001-08-03
//
kpmax = 1;
for (i=0; i h = TI.hp[i];
for (k=0; k<=TI.nzmax; k++) if (h < TI.hh[k]) break;
if (k > TI.nzmax) {
vMsg(_monitor_above_$_, i+1);
return -1;
}
if (k > kpmax) kpmax = k;
}
if (TI.kp < kpmax) TI.kp = kpmax;
}
//
// read and check time series
//
if (TipFrmTab) FREE(TipFrmTab);
TipFrmTab = NULL;
strcpy(name, path);
strcat(name, "/");
strcat(name, CfgSeriesString); //-2008-07-28
strcat(name, ".dmna");
if (write_z) {
if (!*TI.az) {
vMsg(_missing_akterm_);
return -1;
}
TalMode |= TIP_SERIES; //-2002-01-02
}
else {
series_exists = TutFileExists(name);
if (series_exists || *TI.az) TalMode |= TIP_SERIES;
else
if (*TI.as) TalMode |= TIP_STAT;
else {
vMsg(_missing_meteo_);
return -1;
}
if (TalMode & TIP_VARIABLE) {
if ((TalMode & TIP_SERIES) && !series_exists) {
vMsg(_missing_series_$_, name);
return -1;
}
if (TalMode & TIP_STAT) {
char fname[256];
int n, k=0, quiet, verbose;
TIPVAR *ptv;
ARYDSC *pa;
for (n=0; n ptv = AryPtrX(&TipVar, n);
sprintf(fname, "%s/%s.dmna", path, ptv->name);
if (!TutFileExists(fname)) {
vMsg(_missing_table_$$_, ptv->name, fname);
k++;
}
}
if (k)
return -1;
for (n=0; n ptv = AryPtrX(&TipVar, n);
sprintf(fname, "%s/%s.dmna", path, ptv->name);
quiet = MsgQuiet; MsgQuiet = 1;
verbose = MsgVerbose; MsgVerbose = 1;
pa = &(ptv->dsc);
DmnRead(fname, NULL, NULL, pa);
MsgQuiet = quiet;
MsgVerbose = verbose;
if (MsgCode < 0) {
vMsg(_cant_read_file_$_, fname);
vMsg(_see_log_);
MsgCode = 0;
return -2;
}
if (pa->numdm!=2 || pa->elmsz!=4
|| pa->bound[0].low!=1 || pa->bound[0].hgh!=6
|| pa->bound[1].low!=1 || pa->bound[1].hgh!=9) {
vMsg(_invalid_structure_$_, fname);
return -2;
}
} // for n
}
}
}
if (TalMode & TIP_SERIES) { // ------------ work with time series --------
TatArgument(path);
/* TatArgument("-u0.7"); */ // 2013-01-11 (does not work with german locale)
sprintf(s, "-f%s", TI.az);
TatArgument(s);
sprintf(s, "-z%1.3lf,%1.3lf", TI.z0, TI.d0);
TatArgument(s);
sprintf(s, "-a%1.0lf,%1.0lf,%1.1lf", TI.xa, TI.ya, TI.ha); //-2002-04-16
TatArgument(s);
TatArgument(NULL);
}
//if (!series_exists && NOTALUFT) eX(130); //-2020-10-14
if (series_exists) { // --------- time series provided by user -------------
int quiet, verbose, ostd;
double t1, t2;
int uses_hm = 0;
int uses_ri = 0;
int off_hm, off_ri;
char *p;
//
quiet = MsgQuiet;
MsgQuiet = 1;
verbose = MsgVerbose;
MsgVerbose = 1;
DmnRead(name, &TxtUser, &TxtSystem, &TIPary);
MsgQuiet = quiet;
MsgVerbose = verbose;
if (MsgCode < 0) {
vMsg(_cant_read_time_series_$_, name);
vMsg(_see_log_);
MsgCode = 0;
return -2;
}
vMsg(_using_series_$_, name);
TipLogCheck("SERIES", TutMakeCrc(TIPary.start, TIPary.ttlsz)); //-2011-12-07
TipFrmTab = DmnFrmTab; if (!TipFrmTab) eX(26);
DmnFrmTab = NULL;
if (TIPary.numdm != 1) eX(105);
i1 = TIPary.bound[0].low;
i2 = TIPary.bound[0].hgh;
if (i2-i1+1 > MNT_NUMVAL) {
vMsg(_series_too_long_$_, MNT_NUMVAL);
return -3;
}
ostd = 0;
//
// mandatory parameters
//
strcpy(elnm, "te");
pfr = DmnFrmPointer(TipFrmTab, elnm); if (!pfr) eX(101);
if (pfr->offset != ostd) eX(111);
if (pfr->dt != ltDAT) eX(121);
ostd += sizeof(double);
strcpy(elnm, "ra");
pfr = DmnFrmPointer(TipFrmTab, elnm); if (!pfr) eX(102);
if (pfr->offset != ostd) eX(112);
if (pfr->dt != flDAT) eX(122);
ostd += sizeof(float);
strcpy(elnm, "ua");
pfr = DmnFrmPointer(TipFrmTab, elnm); if (!pfr) eX(103);
if (pfr->offset != ostd) eX(113);
if (pfr->dt != flDAT) eX(123); //-2001-06-27
ostd += sizeof(float);
strcpy(elnm, "lm");
pfr = DmnFrmPointer(TipFrmTab, elnm); if (!pfr) eX(104);
if (pfr->offset != ostd) eX(114);
if (pfr->dt != flDAT) eX(124);
ostd += sizeof(float);
//
// optional parameters -2011-12-02
//
off_hm = -1;
strcpy(elnm, "hm");
pfr = DmnFrmPointer(TipFrmTab, elnm);
if (pfr) {
if (pfr->dt != flDAT) eX(116);
off_hm = pfr->offset;
}
off_ri = -1;
strcpy(elnm, "ri");
pfr = DmnFrmPointer(TipFrmTab, elnm);
if (pfr) {
if (pfr->dt != flDAT) eX(116);
off_ri = pfr->offset;
}
if (off_hm > 0 || off_ri > 0) {
for (i=i1; i<=i2; i++) {
p = AryPtrX(&TIPary, i);
if (off_hm > 0) {
float hm = *(float*)(p + off_hm);
if (hm > 0)
uses_hm = 1;
}
if (off_ri > 0) {
float ri = *(float*)(p + off_ri);
if (ri >= 0)
uses_ri = 1;
}
} // for i
}
// -2011-12-02
if (isUndefined(TI.hm)) { // values expected
if (!uses_hm) eX(250)
else
TalMode |= TIP_HM_USED;
}
//else if (uses_hm)
// vMsg(_HM_in_$_ignored_, "\"time series\"");
// -2011-12-02
if (isUndefined(TI.ri)) { // values expected
if (!uses_ri) eX(251)
else
TalMode |= TIP_RI_USED;
}
else if (uses_ri && !(PrmMode & TIP_TALDIA)) //-2021-10-11
vMsg(_RI_in_$_ignored_, "DMNA");
//
// variable parameters
//
for (i=0; i ptv = AryPtrX(&TipVar, i);
strcpy(elnm, ptv->name);
pfr = DmnFrmPointer(TipFrmTab, ptv->name); if (!pfr) eX(106);
if (pfr->dt != flDAT) eX(116);
ptv->o = pfr->offset;
ptv->i = (pfr->offset - ostd)/sizeof(float); //-2011-12-19
}
//
// anemometer height vector
if (TI.ha <= 0) {
float havec[9];
i = DmnGetFloat(TxtUser.s, "ha", "%f", havec, 9);
if (i == 9) {
TI.ha = havec[iZ0];
vMsg(_using_ha_$_, TI.ha);
}
}
//
// ignore az/as
if (*TI.az) vMsg(_ignoring_az_$_, TI.az);
*TI.az = 0;
if (*TI.as) vMsg(_ignoring_as_$_, TI.as); //-2001-12-14
*TI.as = 0;
//
// for standard TA Luft application check that
// time intervals in series are constant
if (!NOTALUFT) { //-2020-10-14
t1 = *(double*) AryPtrX(&TIPary, i1);
for (i=i1+1; i<=i2; i++) { //-2001-12-14
t2 = *(double*) AryPtrX(&TIPary, i);
n = (int)(MsgDateSeconds(t1, t2) + 0.5);
if (n != TI.in) eX(120); //-2007-02-03
t1 = t2;
}
}
}
else if (*TI.az) { // ------------------ AKTerm provided by user ------------------
int nn, nt, elmsz, akt;
akt = TatReadAKTerm();
if (akt < 0)
return -1;
nt = AKTary.bound[0].hgh;
if (nt > MNT_NUMVAL) {
vMsg(_akterm_too_long_$_, MNT_NUMVAL);
return -3;
}
// -2011-12-02
if (isUndefined(TI.hm)) { // values expected
if (0 == (akt & 0x01)) eX(260)
else
TalMode |= TIP_HM_USED;
}
//else if (akt & 0x01)
// vMsg(_HM_in_$_ignored_, "\"AKTerm\"");
// -2011-12-02
if (isUndefined(TI.ri)) { // values expected
if (0 == (akt & 0x02)) { //-2018-10-29
AKTREC *pdst;
PRCREC *psrc;
strcpy(prcname, path);
strcat(prcname, "/");
strcat(prcname, CfgPrecString);
strcat(prcname, ".dmna");
if (!TutFileExists(prcname)) eX(261);
//
DmnRead(prcname, &TxtUser, &TxtSystem, &PRCary); eG(262);
vMsg(_precfile_read_$$$_, prcname, PRCary.bound[0].low, PRCary.bound[0].hgh);
if (nt != PRCary.bound[0].hgh) eX(263);
for (i=1; i<=nt; i++) {
pdst = AryPtrX(&AKTary, i);
psrc = AryPtrX(&PRCary, i);
//
// In AKT record pdst, the C representation of time as double
// is interpreted as GMT+01:00. On the other hand, the DMNA routines
// transform time correctly to default GMT+00:00. Therefore one hour
// must be added to align DMNA times to AKT times.
//
// Note that tmzn entries in niederschlag.dmna of type "UTC" are not
// recognized, interpreted as GMT+00:00 and cause an error.
// The tmzn entry should be "GMT+01:00".
//
psrc->t += 1./24.; //-2019-10-18
//
if (fabs(psrc->t-pdst->t) > 1.e-6) eX(264);
pdst->fPr = psrc->fPr;
}
}
TalMode |= TIP_RI_USED;
}
else if ( (akt & 0x02) && !(PrmMode & TIP_TALDIA)) //-2021-10-11
vMsg(_RI_in_$_ignored_, "AKTerm");
//
nn = TatCheckZtr();
if (TI.ha <= 0) { //-2002-04-16
TI.ha = TatGetHa(iZ0);
vMsg(_using_ha_$_, TI.ha);
}
vMsg(_availability_$_, 100 - (nn*100.0)/nt);
{ // extend the transformed AKTerm
//bp int len = 40; no VLA for vs-compiler
int len = 40;
char *_frm;
char **forms;
char s[40];//bp
char form[40];//bp //-2011-12-08
char form_hm[40];//bp //-2011-12-08
char form_ri[40];//bp //-2011-12-08
char *form_iq = "%3.0f"; //-2015-12-01
AKTREC *psrc;
TMSREC *pdst;
int nf, ihm=-1, iri=-1; //-2011-11-22
int l4 = AKTary.elmsz - sizeof(int) - sizeof(float); //-2011-12-08
forms = ALLOC(6*sizeof(char*)); //-2011-12-08
elmsz = l4 + nVarParm*sizeof(float); //-2011-12-08
AryCreate(&TIPary, elmsz, 1, 1, nt); eG(22);
nf = DmnGetString(AKTheader, "form", forms, 6); //-2011-11-22
if (nf != 6) eX(23);
n = 4;
for (i=0; i n += strlen(forms[i])+3;
n += 22*nVarParm;
_frm = ALLOC(n); if (!_frm) eX(24); //-2014-06-26
for (i=0; i strcpy(form, forms[i]);
FREE(forms[i]); //-2011-12-08
if (!strncmp(form, "hm%", 3)) {
strcpy(form_hm, form);
continue;
}
if (!strncmp(form, "ri%", 3)) {
strcpy(form_ri, form);
continue;
}
strcat(_frm, " \"");
if (!strncmp(form, "kl%", 3))
strcat(_frm, "lm%7.1f");
else
strcat(_frm, form);
strcat(_frm, "\"");
}
FREE(forms);
for (i=0; i ptv = AryPtrX(&TipVar, i);
strcpy(s, " \"");
if (!strcmp(ptv->name, "hm")) { //-2011-12-08
strcat(s, form_hm);
ihm = i;
}
else if (!strcmp(ptv->name, "ri")) { //-2011-12-08
strcat(s, form_ri);
iri = i;
}
else if (!strcmp(ptv->name+2, ".iq")) { //-2015-12-01
strcat(s, ptv->name);
strcat(s, form_iq);
}
else {
strcat(s, ptv->name);
strcat(s, "%10.3e");
}
strcat(s, "\"");
strcat(_frm, s);
ptv->i = i;
ptv->o = l4 + i*sizeof(float);
}
if (CHECK) vMsg("New format:%s<<<\n", _frm);
TipFrmTab = DmnAnaForm(_frm, &TIPary.elmsz); if (!TipFrmTab) eX(28);
TxtCpy(&TxtSystem, "form "); //-2014-01-28
TxtCat(&TxtSystem, _frm);
TxtCat(&TxtSystem, "\n");
FREE(_frm);
for (i=1; i<=nt; i++) {
pdst = AryPtrX(&TIPary, i);
psrc = AryPtrX(&AKTary, i);
pdst->t = psrc->t;
pdst->fRa = psrc->fRa;
pdst->fUa = psrc->fUa;
k = psrc->iKl - 1;
pdst->fLm = (k<0 || k>5) ? 0 : lmTAL[k][iZ0]; //-2001-07-12
if (ihm >= 0)
pdst->fPrm[ihm] = psrc->fHm; //-2011-12-08
if (iri >= 0)
pdst->fPrm[iri] = psrc->fPr; //-2011-12-08
}
AryFree(&AKTary);
}
if (write_z) { // write generated time series
char s[1024], t[512]; //-2008-10-17
sprintf(t, "locl \"%s\"\n", TI.lc); //-2008-10-17 -2014-01-28
TxtCat(&TxtSystem, t); //-2008-10-17
strcpy(name, path);
strcat(name, "/");
strcat(name, CfgSeriesString);
TxtCat(&TxtSystem, "mode \"text\"\n"); //-2014-01-28
strcpy(s, "ha");
for (i=0; i sprintf(t, " %1.1f", TatGetHa(i)); //-2014-01-28
strcat(s, t);
}
strcat(s, "\n");
TxtCat(&TxtSystem, s);
sprintf(s, "z0 %3.2lf\n", TI.z0); TxtCat(&TxtSystem, s); //-2002-06-19 -2014-01-28
sprintf(s, "d0 %3.2lf\n", TI.d0); TxtCat(&TxtSystem, s); //-2014-01-28
sprintf(s, "artp \"ZA\"\n"); TxtCat(&TxtSystem, s); //-2008-12-04 -2014-01-28
DmnWrite(name, TxtSystem.s, &TIPary); eG(100);
vMsg(_series_written_$_, name);
TxtClr(&TxtSystem);
}
}
if (TI.ha <= 0) { //-2002-04-16
TI.ha = 10 + TI.d0;
vMsg(_using_ha_$_, TI.ha);
}
if (TalMode & TIP_STAT) { //--------------- AKS provided by user -----------
if (TI.ri != -HUGE_VAL && TI.ri != 0.) eX(265); //-2018-10-29
TalAKS(Path);
//
if (BESMAX) { //-2024-01-17
if (TI.nq==1 && !TI.nb && !TI.gh[0]) {
fprintf(MsgFile, _besmax_1dir_);
sprintf(s, "-S"); // only one direction
TalAKS(s);
TI.qs -= 6;
}
else if (NOSTANDARD && strstr(TI.os, "NSUB5")) {
fprintf(MsgFile, _besmax_nsub5_);
sprintf(s, "-s%d", 5); // 5 subsectors at 2 deg
TalAKS(s);
}
else {
sprintf(s, "-s%d", 2); // 2 subsectors at 5 deg
TalAKS(s);
}
}
//
sprintf(s, "-f%s", TI.as);
TalAKS(s);
sprintf(s, "-z%1.3lf,%1.3lf", TI.z0, TI.d0);
TalAKS(s);
sprintf(s, "-a%1.0lf,%1.0lf,%1.1lf", TI.xa, TI.ya, TI.ha); //-2002-04-16
TalAKS(s);
if (cNO >= 0 && TI.cmp[cNO]) TalAKS("-n");
d = TasRead();
if (d > 0) { //-2011-12-20
TalMode |= TIP_RI_USED;
d = 0;
}
}
if (TalMode & TIP_SERIES) {
i1 = TIPary.bound[0].low;
i2 = TIPary.bound[0].hgh;
TI.t1 = *(double*) AryPtrX(&TIPary, i1);
TI.t2 = *(double*) AryPtrX(&TIPary, i2);
TI.t1 = MsgDateLastHour(TI.t1); //-2020-10-14
}
setlocale(LC_NUMERIC, locale); //-2008-10-17
return d;
eX_1: eX_2: eX_3: eX_4: eX_5: eX_6: eX_7: eX_8: eX_9: eX_10: eX_11: eX_12:
eX_13:
eX_20: eX_21: eX_22: eX_23: eX_24: eX_26: eX_28:
eX_220: eX_221: eX_222: eX_223: eX_224: eX_225: eX_226: eX_227: eX_228:
eX_229: eX_230: eX_231: eX_232: eX_233: eX_234:
eX_301:
eMSG(_internal_error_);
eX_100:
vMsg(_akterm_not_written_$_, name);
MsgCode = 0;
return -100;
eX_105:
eMSG(_invalid_structure_series_$_, name);
eX_101: eX_102: eX_103: eX_104:
vMsg(_missing_element_$_, elnm);
DmnPrnForm(TipFrmTab, name);
return MsgSource=ePGMs, MsgCode;
eX_111: eX_112: eX_113: eX_114:
vMsg(_wrong_position_$_, elnm);
DmnPrnForm(TipFrmTab, name);
return MsgSource=ePGMs, MsgCode;
eX_121: eX_122: eX_123: eX_124:
vMsg(_wrong_type_$_, elnm);
DmnPrnForm(TipFrmTab, name);
return MsgSource=ePGMs, MsgCode;
eX_106:
eMSG(_missing_parameter_$_, elnm);
eX_116:
eMSG(_float_expected_$_, elnm);
eX_120:
eMSG(_invalid_interval_$$_, i-i1+1, TI.in);
//eX_130:
// eMSG(_interval_requires_series_);
eX_210:
eMSG(_improper_profile_$_, n+1);
eX_211:
eMSG(_profile_not_created_$_, n+1);
eX_212:
eMSG(_incomplete_profiles_);
eX_213: eX_313:
eMSG(_error_grid_);
eX_214:
eMSG(_anemometer_required_);
eX_215:
eMSG(_anemometer_outside_);
eX_240:
eMSG(_no_absolute_value_$_, s);
eX_241:
eMSG(_too_many_points_);
eX_242:
eMSG(_invalid_lc_);
eX_250:
eMSG(_no_valid_HM_in_$_, "DMNA");
eX_251:
eMSG(_no_valid_RI_in_$_, "DMNA");
eX_260:
eMSG(_no_valid_HM_in_$_, "AKTerm");
eX_261: //-2018-10-29
eMSG(_no_prec_file_$_, prcname);
eX_262: //-2018-10-29
eMSG(_cant_read_prec_file_$_, prcname);
eX_263: //-2018-10-29
eMSG(_incomp_prec_series_size_);
eX_264: //-2018-10-29
eMSG(_incomp_prec_series_time_);
eX_265: //-2018-10-29
eMSG(_ri_not_with_aks_);
eX_300:
eMSG(_invalid_dmkp_);
eX_312:
eMSG(_duplicate_definition_);
eX_320:
eMSG(_no_raster_$_, TI.bf);
eX_321:
eMSG(_raster_dimension_);
eX_327:
eMSG(_raster_integer_);
eX_322:
eMSG(_raster_dz_);
eX_323: eX_324: eX_325: eX_326:
eMSG(_raster_x0_);
eX_400: eX_401:
eMSG(_vertical_grid_size_);
eX_404:
eMSG(_vertical_grid_low_);
eX_405:
eMSG(_invalid_nz_);
eX_406:
eMSG(_small_nz_);
eX_407:
eMSG(_finest_grid_low_);
eX_408:
eMSG(_coarse_grid_low_);
}
//================================================================== TipMain
//
int TipMain( char *s ) {
dP(TipMain);
char fname[512];
char buf[512]; //bp
FILE *f; //bp
TIPREC t; //bp
char sttname[32];
int n, pid;
static int create_lib=0;
if (!MsgFile) {
if (TipMsgFile) MsgFile = TipMsgFile;
MsgVerbose = 1;
MsgBreak = '\'';
}
if (CHECK) vMsg("TipMain(%s)", (s) ? s : "NULL");
if (s && *s) {
if (s[0] == '-')
switch (s[1]) {
case 'S': strcpy(Home, s+4); //bp
break; //bp
case 'H': strcpy(Home, s+2);
if (!*Home) strcpy(Home, ".");
break;
case 'l': create_lib = 1;
sscanf(s+2, "%d", &create_lib);
if (create_lib > 0) TalMode |= TIP_LIBRARY;
else TalMode &= ~TIP_LIBRARY;
break;
case 'M': sscanf(s+2, "%x", &PrmMode); //-2014-06-26
break;
case 'v': sscanf(s+2, "%d,%d", &StdDspLevel, &StdLogLevel); //-2006-10-20
break;
case 'w': Write_l = 1;
sscanf(s+2, "%d", &Write_l);
//if (Write_l) TalMode |= TIP_WRITE_L; -2023-07-17, not used
//else TalMode &= ~TIP_WRITE_L; -2023-07-17, not used
break;
case 'x': Xflags = 0; //-2008-08-08
sscanf(s+2, "%x", &Xflags);
break;
case 'z': Write_z = 1;
create_lib = -1; //-2005-03-18
sscanf(s+2, "%d", &Write_z);
//if (Write_z) TalMode |= TIP_WRITE_Z; -2023-07-17, not used
//else TalMode &= ~TIP_WRITE_Z; -2023-07-17, not used
break;
default: ;
}
else {
if (strlen(s) > 240) eX(20);
strcpy(Path, s);
MsgCheckPath(Path);
}
return 0;
}
// -2011-12-07
sprintf(fname, "%s/%s", Home, AUSTALx); //bp
TipLogCheck("AUSTAL", TutGetCrc(fname));
sprintf(fname, "%s/%s", Home, TALDIA);
TipLogCheck("TALDIA", TutGetCrc(fname));
//
sprintf(fname, "%s/%s", Path, "austal.txt"); //bp
f = fopen(fname, "rb"); //bp
while (fgets(buf, 512, f)) { //bp
parse(buf, &t); //bp
if (strcmp(t._name, "settingspath") == 0) //bp
{ //bp
strcpy(SettingsPath, t._tokens[0]); //bp
FREE(t._name); //bp
FREE(t._tokens); //bp
break; //bp
} //bp
} //bp
fclose(f); //bp
strcpy(sttname, "austal");
if (strlen(SettingsPath) == 0) //bp
sprintf(SettingsPath, "%s/%s.settings", Home, sttname); //bp
n = TutGetCrc(SettingsPath); //bp
TipLogCheck("SETTINGS", n);
sprintf(fname, "%08x", n);
if (strcmp(fname, SETTINGS_CRC))
{ //bp
strcpy(fname, SettingsPath); //bp
strtok (fname,"."); //bp
vMsg(_nostandard_settings_$_, fname); //bp
} //bp
//
n = SttRead(SettingsPath, sttname); //bp -2011-11-23 -2014-01-21
if (n < 0)
return -1;
//
n = TipInitialize();
if (n < 0) //-2024-01-17
return -1;
//
n = TipRead(Path);
if (n < 0)
return -1;
//
if ((*TI.bf || TI.xb || *TI.gh) && create_lib>=0) { // complex terrain
//bp sprintf(fname, "%s/lib", Path);
sprintf(fname, "%s", AbsoluteWindLibPath); //bp
if (TutDirExists(fname)) {
if (TalMode & TIP_LIBRARY) {
n = TutDirClearOnDemand(fname); if (n < 0) eX(10);
}
else vMsg(_using_library_);
}
else {
n = TutDirMake(fname); if (n < 0) eX(11);
create_lib = 1;
}
if (create_lib > 0) { // make library
char gname[256] = "\"";
char gpath[256] = "\"";
char *lan, lanopt[256]; //-2008-12-19
fflush(stdout);
if (*NlsLanOption) { //-2008-12-19
sprintf(lanopt, "--language=%s", NlsLanOption);
lan = lanopt;
}
else //-2008-12-19
lan = NULL;
sprintf(fname, "%s/%s", Home, TALDIA); //-2002-07-03
strcat(gname, fname);
strcat(gname, "\"");
strcat(gpath, Path);
strcat(gpath, "\"");
#ifdef __linux__
n = fork();
if (n == 0) execl(fname,
fname, Path, "-B~../lib", "-w30000", lan, NULL); //-2008-12-19
if (n != -1) pid = wait(&n);
#else
n = spawnl(P_WAIT, fname,
gname, gpath, "-B~../lib", "-w30000", lan, NULL); //-2008-12-19
#endif
if (n) {
sprintf(fname, "%s", AbsoluteWindLibPath); //bp
//bp sprintf(fname, "%s/lib", Path); //-2006-11-06
TutDirClear(fname);
TutDirRemove(fname);
if (n > 0) eX(12);
eX(13);
}
if (TalMode & TIP_LIBRARY) {
vMsg(_library_created_);
return 1;
}
}
}
else if (*TI.bf==0 && !TI.xb && *TI.gh==0 && create_lib>0)
return 2;
if (Write_l) {
strcpy(fname, Path);
strcat(fname, "/work");
n = TutDirMake(fname); if (n < 0) eX(1);
if (n > 0 && (Xflags & 0x20) == 0) { //-2008-08-08
n = TutDirClear(fname); if (n < 0) eX(2);
}
}
n = TipCheck(Path, Write_z);
fprintf(MsgFile, "\n%s", LogCheck.s);
if (n < 0)
return -1;
if (n > 0)
return 1; //-2002-03-28
if (Write_z) { //-2001-05-09 lj
if (!nVarParm) vMsg(_no_variable_parameters_);
return 1;
}
if (Write_l) {
n = TdfWrite(Path, &TIPary, TipFrmTab, TalMode);
if (n < 0) eX(4); //-2007-02-03
if (n>=0 && (*TI.gh>0)) {
n = TdfCopySurface(Path); if (n <= 0) eX(3); //-2001-09-15
}
}
if (TipFrmTab) FREE(TipFrmTab);
TipFrmTab = NULL;
return 0;
eX_1:
eMSG(_directory_$_not_created_, fname);
eX_2:
eMSG(_not_cleared_$_, fname);
eX_3:
eMSG(_missing_profiles_);
eX_4:
eMSG(_cant_write_defs_);
eX_10:
eMSG(_library_not_cleared_);
eX_11:
eMSG(_libdir_not_created_);
eX_12:
eMSG(_library_not_created_$_, n);
eX_13:
eMSG(_taldia_not_run_);
eX_20:
eMSG(_pathname_too_long_);
}
#ifdef MAIN //##########################################################
//================================================================== main
int main( int argc, char *argv[] ) {
char lfile[256];
int n;
if (argc > 1) {
for (n=1; n strcpy(lfile, Path);
strcat(lfile, "/LasTal.log");
MsgFile = fopen(lfile, "w");
}
MsgVerbose = 1;
MsgBreak = '\'';
vMsg("LasTal Version %s %s", TalInpVersion, IBJstamp(__DATE__, __TIME__));
if (argc < 2) {
vMsg("usage: LasTal {-z | -w}");
exit(0);
}
n = TipMain(NULL);
if (n < 0) vMsg("Program LasTal aborted!");
else vMsg("Program LasTal finished.");
if (MsgFile) fclose(MsgFile);
return 0;
}
#endif //#################################################################
/*=========================================================================
* history:
*
* 2001-04-15 0.1.0 lj created
* 2001-05-01 0.2.1 lj AKS
* 2001-05-03 0.2.2 lj monitor points
* 2001-05-04 0.2.3 lj format string of AKTerm
* 2001-05-09 0.2.4 lj return(1) if option "-z"
* 2001-05-11 0.2.5 lj write ha+d0 in wetter.def
* 2001-05-24 0.2.6 lj definition of not emittable components
* 2001-05-30 0.3.0 lj new definition of species names and components
* 2001-06-09 0.5.0 lj logging of input file
* 2001-06-27 0.5.3 lj ua represented as float
* 2001-06-28 0.5.4 lj lm instead of kl in zeitreihe.dmna
* 2001-06-29 0.5.5 lj hq less 10 allowed (warning only), nh3 added
* 2001-07-09 0.6.0 lj release candidate
* 2001-07-12 0.6.1 lj set Lm=0 for missing data
* 2001-07-14 0.6.2 lj check on missing zeitreihe.dmna
* 2001-07-20 0.6.3 lj determination of z0 using CORINE
* 2001-08-03 0.6.4 lj parameter TI.kp (for nzdos)
* 2001-08-14 0.7.0 lj conversion of GauÃ-Krüger coordinates
* 2001-09-04 0.7.1 lj MsgUnquote() instead of MsgDequote() for input strings
* calculation of source center corrected
* 2001-09-17 0.8.0 lj working with complex terrain
* 2001-10-18 0.8.1 lj computational area at least 2000 m squared
* 2001-10-30 0.8.2 lj nested grids
* 2001-11-02 0.8.3 lj component nox
* 2001-11-03 0.8.4 lj grid alignment relaxed
* 2001-11-05 0.9.0 lj release candidate
* 2001-11-23 0.9.1 lj absolute path for "gh" allowed
* 2001-12-14 0.9.2 lj time interval length checked
* 2002-01-03 0.10.2 lj default value of sq[] = -1
* 2002-01-12 0.10.4 lj check anemometer position (and other positions)
* 2002-02-26 0.10.5 lj counting of monitor points corrected
* 2002-03-11 0.11.1 lj new input parameter : mixing height hm
* 2002-03-28 0.11.2 lj return from input check corrected
* 2002-04-16 0.12.0 lj ha not incremented by d0
* 2002-07-03 0.13.1 lj modifications for linux
* 2002-07-13 0.13.2 lj calculation of nested grids corrected
* 2002-07-30 0.13.3 lj number of decimals for deposition of pm = 4
* 2002-08-01 0.13.4 lj time dependent hm; hh requires NOSTANDARD
* 2002-08-15 0.13.5 lj setting of x0 and y0 checked
* 2002-09-21 0.13.6 lj checking of nested grids improved
* 2002-09-23 0.13.7 lj input parameters lq, rq, tq
* 2002-09-24 1.0.0 lj final release candidate
* 2002-12-06 1.0.3 lj check of Np (less or equal 10)
* 2002-12-10 1.0.4 lj parameter lq, rq, tq allowed to vary with time
* 2003-01-22 1.0.5 lj blanks in file names allowed
* 2003-02-21 1.1.1 lj optional scientific notation, species "xx"
* 2003-06-24 1.1.7 lj error message corrected
* 2003-07-07 1.1.8 lj localisation
* 2003-10-02 1.1.11 lj check of inclusion of finer grids corrected
* lj nesting of grids corrected, check added
* 2003-10-12 1.1.12 lj don't "make" a surface if zg00 is given
* 2003-12-05 1.1.13 lj check on length of time series (less or equal MNT_NUMVAL) added
* 2004-07 2.1.1 uj buildings included
* 2004-09-10 2.1.2 lj check of grid nesting
* 2004-10-25 2.1.4 lj guard cells for grids (1 for outer, 2 for inner)
* lj z0 from CORINE always rounded
* lj optional factors Ftv
* 2004-11-02 2.1.5 uj min dd without buildings changed from 15m to 16m
* 2004-11-12 2.1.6 uj additional check included in getNesting()
* 2004-11-30 2.1.8 uj additional check included in getNesting()
* explicit reference to TA Luft for warning h less 1.2hq
* 2004-12-14 2.1.9 uj wb, da in degree
* 2005-01-10 2.1.10 uj checkBodiesandSources: hq min. 10 m for distance
* 2005-02-21 2.1.11 uj unused makePlainSurface() removed
* 2005-03-16 2.1.12 uj check xa/ya moved, check TrbExt corrected
* 2005-03-17 2.2.0 uj version number upgrade
* 2005-03-18 lj no wind lib created with option -z
* 2005-04-13 2.2.1 lj option -z for flat terrain corrected
* 2006-02-06 2.2.7 uj nonstandard option SORRELAX
* 2006-02-11 uj check if user-defined nz extends to hh_max
* 2006-02-15 2.2.9 lj freeing of strings
* 2006-10-11 2.2.15 lj TI.im defaults to 200
* 2006-10-12 2.2.16 uj number of monitor points increased to 20
* extension to UTM coordinates
* 2006-10-20 2.2.17 uj verbose modus
* 2006-10-20 2.3.0 lj externalization of strings
* 2006-11-06 uj clear lib corrected
* 2006-11-21 2.3.3 uj write out GK-converted source coordinates
* 2007-02-03 2.3.5 uj time interval revised, error if WriteDefs fails
* maximum np adjustable from outside
* 2007-03-08 uj minimum h for z0 calculation
* 2008-01-25 2.3.7 uj allow absolute path for rb
* 2008-03-10 2.4.0 lj evaluation of rated odor frequencies
* 2008-04-17 2.4.1 lj merged with 2.3.x
* 2008-08-27 2.4.3 lj NONSTANDARD optionally
* 2008-09-23 lj 2 additional odor substances
* 2008-10-17 lj uses MsgSetLocale()
* 2008-10-20 2.4.4 lj nonstandard: hm, ie, im, mh, x1, x2, x3, y1, y2, y3
* 2008-12-04 2.4.5 lj lq actually treated as variable parameter
* writes "artp" into header of time series
* 2008-12-07 lj UTM uses zone 32 if ux has no prefix
* 2008-12-11 lj parameter "ggcs" in NTRREC
* 2011-06-17 2.4.10 uj maximum stack height increased to 500
* 2011-06-29 uj check and report if standard roughness register is used
* 2011-07-07 2.5.0 uj version number upgrade
* 2011-09-12 2.5.1 uj TipBlmVersion
* 2011-11-23 2.6.0 lj settings from ARTM
* 2011-12-07 lj check sums
* 2011-12-14 lj "ri" requires NOSTANDARD
* 2011-12-16 lj abort if required option NOSTANDARD is missing
* 2012-04-06 2.6.3 uj complain if NOSTANDARD is missing for "hh"
* 2012-10-30 2.6.5 uj read/write superposition factors
* 2013-01-11 uj invalid umin parsing removed
* 2014-01-21 2.6.9 uj CfgWet
* 2014-06-26 2.6.11 uj accept "ri" if called by TALdia, eX/eG adjusted
* 2015-12-01 2.7.0 lj grid source index "iq"
* 2015-12-15 2.7.1 lj only 1 grid source
* 2018-10-02 3.0.0 uj austal
* 2018-10-29 3.0.1 lj separate precipitation time series
* 2018-11-22 3.0.2 uj radius for z0 determination set to 15*h
* 2019-02-04 3.0.3 uj finest grid up to at least 20 m
* 2019-10-18 3.0.4 uj time zone adjusted reading precipitation file
* 2020-10-14 3.1.0 uj NOTALUFT extensions
* 2021-06-23 3.1.1 uj settings crc code (adjusted odorants)
* 2021-07-03 uj check for hq less 1.2 cb deprecated
* 2021-08-05 3.1.2 uj settings crc code (odorant comment)
* 2021-10-11 3.1.3 uj skip "ri ignored" warning for TALdia
* 2024-01-17 3.3.0 uj BESMAX consistent calculation
* unused "sh" removed
* heavy gas coupling VDI 3783/1 E (2024)
*============================================================================*/
*
* Read Input for AUSTAL
* =====================
*
* All data given by TA Luft are defined in this module
* =====================================================
*
* Copyright (C) Umweltbundesamt, Dessau-Roßlau, Germany, 2002-2024
* Copyright (C) Janicke Consulting, 88662 Überlingen, Germany, 2002-2024
* Email: info@austal.de
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* last change: 2024-01-17 uj
*
*============================================================================*/
char *TalInpVersion = "3.3.0";
static char *eMODn = "TalInp";
static int CHECK = 0;
char AbsoluteWindLibPath[256] = ""; //bp
char SettingsPath[256] = ""; //bp
#ifdef DIAM //bp
static int numprocs=1; //bp
#else //bp
extern int numprocs; //bp
#endif //bp
static int StdLogLevel = 3; //-2006-10-20
static int StdDspLevel = 2; //-2006-10-20
#include
#include
#include
#include
#include
#include
#ifdef __linux__
#include
#include
#include
#define AUSTALx "austal" //bp
#define TALDIA "taldia"
#define VDISP "vdisp"
#else
#include
#define AUSTALx "austal.exe" //bp
#define TALDIA "taldia.exe"
#define VDISP "vdisp.exe"
#endif
#include "IBJmsg.h"
#include "IBJary.h"
#include "IBJtxt.h"
#include "IBJdmn.h"
#include "IBJgk.h"
#include "IBJntr.h"
#include "IBJnls.h" //-2008-12-19
#include "TalAKT.h"
#include "TalAKS.h"
#include "TalUtl.h"
#include "TalRgl.h"
#include "TalDef.h"
#include "TalZet.h"
#include "TalDMK.h"
#include "TalStt.h"
#include "TalInp.h"
#include "TalInp.nls"
#include "TalMat.h"
#include "TalCfg.h"
//////////////////////////////////////////////////////////////
// default CRC codes, status: 2024-01-17
//////////////////////////////////////////////////////////////
#define RGL_CRC_GK "58afd278"
#define RGL_CRC_UTM "e9ea3bcd"
#define SETTINGS_CRC "b853d6c4"
#define BESMAX_CRC "2c0102a0"
//////////////////////////////////////////////////////////////
#define vLOG(a) MsgQuiet=2*(StdDspLevel<(a))-1, MsgVerbose=(StdLogLevel>=(a)), vMsg
#define TE(i) ((AKTREC*)AryPtrX(&TIPary, i))->t
#define RA(i) ((AKTREC*)AryPtrX(&TIPary, i))->iRa
#define UA(i) ((AKTREC*)AryPtrX(&TIPary, i))->fUa
#define KL(i) ((AKTREC*)AryPtrX(&TIPary, i))->iKl
typedef struct {
int iLine; // line number in input file
char *_name; // parameter name + buffer for tokens
int nTokens; // number of tokens
char **_tokens; // array of pointers to tokens
int type; // type of tokens (TIP_STRING or TIP_NUMBER)
double *_dd; // array of values or NULL
} TIPREC;
typedef struct { //-2018-10-29
double t; // end time of the 1 hour interval (GMT+1)
float fPr; // precipitation in mm/h
} PRCREC;
// these unit specifications must be applied in the settings file
#define U_GM3 "g/m3" //-2008-07-22
#define U_UGM3 "ug/m3" //-2008-07-22
#define U_PGM3 "pg/m3" //-2019-02-19
#define U_MGM3 "mg/m3" //-2008-07-22
#define U_1M3 "1/m3" //-2019-02-19
#define U_GM2D "g/(m2*d)" //-2008-07-22
#define U_1M2S "1/(m2*s)" //-2019-02-19
#define U_MGM2D "mg/(m2*d)" //-2008-07-22
#define U_UGM2D "ug/(m2*d)" //-2008-07-22
#define U_PGM2D "pg/(m2*d)" //-2019-02-19
#define U_KGHAA "kg/(ha*a)" //-2008-07-22
#define U_PERC "%" //-2008-07-22
double TipEpsilon = 1.e-4;
int TipMaxIter = 200;
int cNO, cNO2, cODOR, nADDODOR;
int TipTrbExt = 0;
//
// parameters that may be defined as time-dependent (beside ua, ra, lm, emission rates)
static char *VarPrm = "vq,tq,zq,rq,sq,lq,ts,hm,ri,iq"; //-2015-12-01 //-2018-10-04
//
// default vertical grid above ground for TA Luft
static double Hh[] = { 0, 3, 6, 10, 16, 25, 40, 65, 100, 150, 200, 300, 400, 500,
600, 700, 800, 1000, 1200, 1500 };
//
// default vertical grid above ground for VDI 3783/1 //-2024-01-17
static double Hh37831[] = { 0, 2, 4, 6, 10, 16, 25, 40, 65, 100, 150, 200, 300,
400, 500, 600, 700, 800, 900, 1000, 1500 };
//
static double BodyDda[] = { 32, 16, 8, 4, 2 };
static double BodyDza[] = { 6, 4, 3, 3, 2 };
static double BodyDd, BodyDz, BodyHmax;
static double FinestGridZmin = 20.; //-2019-02-04
static double BodyRatio = 5; //-2004-07
static double TurbRatio = 10; //-2004-07
static ARYDSC BM;
static double BMx0, BMy0, BMdd, BMdz;
static double DdMin = 16.0; //-2004-11-02
static double RadMin = 1000;
static double RadRatio = 50;
static int NxyMax = 400; //-2023-07-17
static int nz0TAL=9, iZ0;
static double z0TAL[9] = { 0.01, 0.02, 0.05, 0.10, 0.20, 0.50, 1.0, 1.5, 2.0 };
static float lmTAL[6][9] = //-2018-10-04
{ { 5, 7, 9, 13, 17, 28, 44, 60, 77 },
{ 25, 31, 44, 59, 81, 133, 207, 280, 358 },
{ 354, 448, 631, 842, 1160, 1893, 2951, 4000, 5107 },
{ -37, -47, -66, -88, -122, -199, -310, -420, -536 },
{ -15, -19, -27, -36, -49, -80, -125, -170, -217 },
{ -6, -8, -11, -15, -20, -33, -52, -70, -89 } };
static int Xflags; //-2008-08-08
static TXTSTR LogCheck = { NULL, 0 };
//-----------------------------------------------------------------------------
TIPDAT TI;
ARYDSC TipVar;
ARYDSC TIPary;
ARYDSC PRCary; //-2018-10-29
FILE *TipMsgFile;
int TalMode;
static int PrmMode;
static TXTSTR TxtUser, TxtSystem;
static char Path[256], Home[256];
static int Write_z=0, Write_l=0;
static int nVarParm, nUsrParm; //-2011-12-02
static DMNFRMREC *TipFrmTab;
//================================================================= xcodeUnits
static void xcodeUnits() { //-2008-07-22
STTSPCREC *tsr; //-2011-11-23
char *uc, *un;
int i;
for (i=0; i
if (*tsr->name == 0)
break;
uc = tsr->uc;
un = tsr->un;
if (!strcmp(uc, U_GM3)) strcpy(uc, _U_GM3_);
else if (!strcmp(uc, U_MGM3)) strcpy(uc, _U_MGM3_);
else if (!strcmp(uc, U_UGM3)) strcpy(uc, _U_UGM3_);
else if (!strcmp(uc, U_PGM3)) strcpy(uc, _U_PGM3_);
else if (!strcmp(uc, U_1M3)) strcpy(uc, _U_1M3_);
else if (!strcmp(uc, U_PERC)) strcpy(uc, _U_PERC_);
if (!strcmp(un, U_GM2D)) strcpy(un, _U_GM2D_);
else if (!strcmp(un, U_MGM2D)) strcpy(un, _U_MGM2D_);
else if (!strcmp(un, U_UGM2D)) strcpy(un, _U_UGM2D_);
else if (!strcmp(un, U_PGM2D)) strcpy(un, _U_PGM2D_);
else if (!strcmp(un, U_1M2S)) strcpy(un, _U_1M2S_);
else if (!strcmp(un, U_KGHAA)) strcpy(un, _U_KGHAA_);
else if (!strcmp(un, U_PERC)) strcpy(un, _U_PERC_);
}
}
//================================================================= isUndefined
static int isUndefined( double d ) {
return (d == HUGE_VAL);
}
//=============================================================== TipBlmVersion
//
float TipBlmVersion( void )
{
dP(TipBlmVersion);
float vrs = 5.3; //-2018-10-04
char *pc_blm, *pc_noshear;
pc_blm = strstr(TI.os, "Blm="); //-2006-02-13
pc_noshear = strstr(TI.os, "NOSHEAR");
if (!NOSTANDARD) {
if (pc_blm || pc_noshear) eX(1);
}
else {
if (pc_blm && pc_noshear) eX(2);
if (pc_blm)
sscanf(pc_blm+4, "%f", &vrs);
else if (pc_noshear)
vrs = 5.2;
}
return vrs;
eX_1:
eMSG(_blm_nostandard_required_);
eX_2:
eMSG(_blm_explicit_);
}
//================================================================== TipZ0index
//
int TipZ0index( double z0 ) {
int i;
for (i=0; i
}
return i;
}
//================================================================== TipKMclass
//
int TipKMclass( double z0, double lm ) {
int k;
int iz = TipZ0index(z0);
double rlm = 1/lm;
for (k=0; k<5; k++) {
if (rlm > 0.5*(1/lmTAL[k][iz] + 1/lmTAL[k+1][iz])) break;
}
return k+1;
}
//====================================================================== TipMOvalue
//
double TipMOvalue( double z0, int kl ) {
int iz = TipZ0index(z0);
int ik = kl-1;
if (ik<0 || ik>5) ik = 2;
return lmTAL[ik][iz];
}
//-----------------------------------------------------------------------------------
static int check_tab( void ) {
int i, emitted;
STTSPCREC *p;
for (i=0; i
p = SttSpcTab + i;
if (TalMode & TIP_SCINOTAT) {
p->dy = -1;
p->dd = -1;
p->dh = -1;
p->dn = -1;
}
if (emitted) {
if (!strcmp(p->unit, "Bq")) TalMode |= TIP_GAMMA;
if (p->de > 0) TalMode |= TIP_DECAY;
if (StdLogLevel > 3)
fprintf(MsgFile, "%-5s: vd=%6.4f m/s, wf=%10.2e 1/s, we=%3.1f\n", p->name, p->vd, p->wf, p->we);
}
}
if (StdLogLevel > 3) {
char s[8];
sprintf(s, " 1234u");
for (i=1; i<=5; i++)
fprintf(MsgFile, "-%c : vd=%6.4f m/s, wf=%10.2e 1/s, we=%3.1f, vs=%6.4f m/s\n",
s[i], SttVdVec[i], SttWfVec[i], SttWeVec[i], SttVsVec[i]);
fprintf(MsgFile, "\n");
}
return i;
}
//================================================================= getCmpIndex
static int getCmpIndex( char *n ) {
int i;
for (i=0; i
return i;
}
return -1; //-2011-11-23
}
//================================================================== init_index
static void init_index( void ) {
cNO2 = getCmpIndex("no2");
cNO = getCmpIndex("no");
cODOR = getCmpIndex("odor");
}
//======================================================================= parse
static int parse( char *line, TIPREC *pp ) {
dP(parse);
int i, n, l;
char *p1, c, tk[256];
if (!pp) eX(2);
pp->_name = NULL;
pp->nTokens = 0;
pp->_tokens = NULL;
pp->type = TIP_NUMBER;
pp->_dd = NULL;
if (line==NULL || !*line) return 0;
l = strlen(line);
for (i=l-1; i>0; i--)
if (line[i] <= ' ') line[i] = 0;
else break;
pp->_name = ALLOC(l+1); if (!pp->_name) eX(1);
strcpy(pp->_name, line);
for (p1=pp->_name; (isalnum(*p1) || *p1=='-' || *p1 == '_'); p1++); //-2008-03-10
if (!*p1) return 0;
*p1++ = 0;
if (!*pp->_name) return 0;
pp->_tokens = _MsgTokens(p1, " ;\t\r\n"); //-2024-01-17
if (!pp->_tokens) return 0;
for (n=0; ; n++)
if (!pp->_tokens[n]) break;
if (n == 0) return 0;
pp->nTokens = n;
for (i=0; i
if (!isdigit(c) && c!='-' && c!='+' && c!='?')
pp->type = TIP_STRING;
}
if (pp->type == TIP_NUMBER) {
char *tail;
pp->_dd = ALLOC(n*sizeof(double));
for (i=0; i
tk[255] = 0;
if (tk[0] == '?') {
pp->_dd[i] = HUGE_VAL;
}
else {
for (p1=tk; (*p1); p1++) if (*p1 == ',') *p1 = '.'; //-2003-07-07
pp->_dd[i] = strtod(tk, &tail);
if (*tail) {
FREE(pp->_dd);
pp->type = TIP_STRING;
break;
}
}
}
}
if (pp->type == TIP_STRING) {
for (i=0; i
}
return pp->type;
eX_1: eX_2:
eMSG(_internal_error_);
}
static int TipIsConstant( TIPREC *tr ) {
int i;
if (!tr || tr->type==TIP_STRING || !tr->_dd) return 1;
for (i=0; i
if (tr->_dd[i] == HUGE_VAL) return 0;
return 1;
}
static int TipMustBeConstant( char *name ) { //-2001-12-27
int i;
if (strstr(VarPrm, name)) return 0;
for (i=0; i
}
return 1;
}
static char *missing_value( char *msg ) {
sprintf(msg, "%s", _missing_value_);
return msg;
}
static char *too_many_values( char *msg ) {
sprintf(msg, "%s", _too_many_values_);
return msg;
}
static char *size_exceeded( char *msg ) {
sprintf(msg, "%s", _string_too_long_);
return msg;
}
static char *unknown_name( char *msg ) {
sprintf(msg, "%s", _unknown_name_);
return msg;
}
static char *not_a_valid_number( char *msg ) {
sprintf(msg, "%s", _not_a_valid_number_);
return msg;
}
static char *must_be_constant( char *msg ) {
sprintf(msg, "%s", _must_be_constant_);
return msg;
}
static char *improper_count( char *msg, int n, int m ) {
sprintf(msg, _improper_count_$$_, n, m);
return msg;
}
static char *set_value( double *pv, TIPREC t, char *msg ) {
dQ(set_value);
if (t.nTokens < 1) missing_value(msg);
else if (t.nTokens > 1) too_many_values(msg);
else if (t.type != TIP_NUMBER) not_a_valid_number(msg);
else *pv = t._dd[0];
if (t._dd) FREE(t._dd);
return msg;
}
static char *set_integer( int *pi, TIPREC t, char *msg ) {
dQ(set_integer);
if (t.nTokens < 1) missing_value(msg);
else if (t.nTokens > 1) too_many_values(msg);
else if (t.type != TIP_NUMBER) not_a_valid_number(msg);
else *pi = t._dd[0];
if (t._dd) {
FREE(t._dd);
t._dd = NULL;
}
return msg;
}
static char *set_string( char *s, TIPREC t, char *msg ) {
if (t.nTokens < 1) missing_value(msg);
else if (t.nTokens > 1) too_many_values(msg);
else if (strlen(t._tokens[0]) > 255) size_exceeded(msg);
else strcpy(s, t._tokens[0]);
return msg;
}
static char *set_vector( double **ppv, TIPREC t, int *pn, char *msg ) {
if ((pn) && *pn==0) *pn = t.nTokens;
if (t.nTokens < 1) missing_value(msg);
else if (t.nTokens != *pn) improper_count(msg, *pn, t.nTokens);
else if (t.type != TIP_NUMBER) not_a_valid_number(msg);
else *ppv = t._dd;
return msg;
}
static char *set_ivector( int **ppi, TIPREC t, int *pn, char *msg ) {
dQ(set_ivector);
int i;
if ((pn) && *pn==0) *pn = t.nTokens;
if (t.nTokens < 1) missing_value(msg);
else if (t.nTokens != *pn) improper_count(msg, *pn, t.nTokens);
else if (t.type != TIP_NUMBER) not_a_valid_number(msg);
else {
*ppi = ALLOC(t.nTokens*sizeof(int));
for (i=0; i
if (t._dd) {
FREE(t._dd);
t._dd = NULL;
}
return msg;
}
static int checkvar( int check, double *pd, int n, char *name, int *pi ) {
int k, j;
TIPVAR *ptv;
char *pc, grp[40], nm[40];
if (!pd)
return 0;
for (k=0; k
continue;
if (check) { //-2005-09-27
(*pi)++;
continue;
}
ptv = AryPtrX(&TipVar, *pi);
(*pi)++; //-2007-04-23
strcpy(nm, name);
sprintf(ptv->name, "%02d.%s", k+1, nm);
if (strstr(VarPrm, nm)) {
if (!strcmp(nm, "zq")) strcpy(nm, "wl"); //-2018-10-04
else if (!strcmp(nm, "rq")) strcpy(nm, "rh"); //-2002-12-10
else if (!strcmp(nm, "sq")) strcpy(nm, "vw"); //-2018-10-04
else if (!strcmp(nm, "lq")) strcpy(nm, "lw"); //-2002-12-10
else if (!strcmp(nm, "tq")) strcpy(nm, "tt"); //-2002-12-10
sprintf(ptv->lasn, "%s.%02d", nm, k+1);
}
else {
strcpy(grp, "gas");
pc = strchr(nm, '-');
if (pc) { // dust component
for (j=1; j<6; j++) //-2005-09-27
if (!strcmp(pc, SttGrpXten[j])) {
strcpy(grp, SttGroups[j]);
break;
}
}
sprintf(ptv->lasn, "Eq.%02d.%s.%s", k+1, grp, nm);
}
ptv->p = pd+k;
}
return (check != 0); //-2005-09-27
}
//============================================================== analyse
static char *analyse( TIPREC t ) {
static char msg[256];
int i;
*msg = 0;
if (CHECK) {
vMsg("NAME=%s, TYPE=%d", t._name, t.type);
for (i=0; i
}
if (!strcmp(t._name, "ti")) set_string(TI.ti, t, msg);
else if (!strcmp(t._name, "as")) set_string(TI.as, t, msg);
else if (!strcmp(t._name, "az")) set_string(TI.az, t, msg);
else if (!strcmp(t._name, "os")) set_string(TI.os, t, msg);
else if (!strcmp(t._name, "gh")) set_string(TI.gh, t, msg);
else if (!strcmp(t._name, "in")) set_integer(&TI.in, t, msg); //-2020-10-14
else if (!strcmp(t._name, "ib")) set_integer(&TI.ib, t, msg); //-2020-10-14
else if (!strcmp(t._name, "gx")) set_value(&TI.gx, t, msg);
else if (!strcmp(t._name, "gy")) set_value(&TI.gy, t, msg);
else if (!strcmp(t._name, "ux")) set_value(&TI.ux, t, msg);
else if (!strcmp(t._name, "uy")) set_value(&TI.uy, t, msg);
else if (!strcmp(t._name, "nx")) set_ivector(&TI.nx, t, &TI.nn, msg);
else if (!strcmp(t._name, "ny")) set_ivector(&TI.ny, t, &TI.nn, msg);
else if (!strcmp(t._name, "nz")) set_ivector(&TI.nz, t, &TI.nn, msg);
else if (!strcmp(t._name, "dd")) set_vector(&TI.dd, t, &TI.nn, msg);
else if (!strcmp(t._name, "x0")) set_vector(&TI.x0, t, &TI.nn, msg);
else if (!strcmp(t._name, "x1")) set_vector(&TI.x1, t, &TI.nn, msg);
else if (!strcmp(t._name, "x2")) set_vector(&TI.x2, t, &TI.nn, msg);
else if (!strcmp(t._name, "x3")) set_vector(&TI.x3, t, &TI.nn, msg);
else if (!strcmp(t._name, "y0")) set_vector(&TI.y0, t, &TI.nn, msg);
else if (!strcmp(t._name, "y1")) set_vector(&TI.y1, t, &TI.nn, msg);
else if (!strcmp(t._name, "y2")) set_vector(&TI.y2, t, &TI.nn, msg);
else if (!strcmp(t._name, "y3")) set_vector(&TI.y3, t, &TI.nn, msg);
else if (!strcmp(t._name, "z0")) set_value(&TI.z0, t, msg);
else if (!strcmp(t._name, "d0")) set_value(&TI.d0, t, msg);
else if (!strcmp(t._name, "xa")) set_value(&TI.xa, t, msg);
else if (!strcmp(t._name, "ya")) set_value(&TI.ya, t, msg);
else if (!strcmp(t._name, "ha")) set_value(&TI.ha, t, msg);
else if (!strcmp(t._name, "hm")) set_value(&TI.hm, t, msg);
else if (!strcmp(t._name, "ri")) { //-2018-10-02
if (PrmMode & TIP_TALDIA)
; // ignore "ri" if input file is read by TALdia //-2014-06-26
else
set_value(&TI.ri, t, msg); //-2014-01-21
}
else if (!strcmp(t._name, "ie")) set_value(&TI.ie, t, msg);
else if (!strcmp(t._name, "mh")) set_value(&TI.mh, t, msg);
else if (!strcmp(t._name, "im")) set_integer(&TI.im, t, msg);
else if (!strcmp(t._name, "qs")) set_integer(&TI.qs, t, msg);
else if (!strcmp(t._name, "qb")) set_integer(&TI.qb, t, msg);
else if (!strcmp(t._name, "sd")) set_integer(&TI.sd, t, msg);
else if (!strcmp(t._name, "hh")) set_vector(&TI.hh, t, &TI.nhh, msg);
else if (!strcmp(t._name, "xp")) set_vector(&TI.xp, t, &TI.np, msg);
else if (!strcmp(t._name, "yp")) set_vector(&TI.yp, t, &TI.np, msg);
else if (!strcmp(t._name, "hp")) set_vector(&TI.hp, t, &TI.np, msg);
else if (!strcmp(t._name, "aq")) set_vector(&TI.aq, t, &TI.nq, msg);
else if (!strcmp(t._name, "bq")) set_vector(&TI.bq, t, &TI.nq, msg);
else if (!strcmp(t._name, "cq")) set_vector(&TI.cq, t, &TI.nq, msg);
else if (!strcmp(t._name, "hq")) set_vector(&TI.hq, t, &TI.nq, msg);
else if (!strcmp(t._name, "dq")) set_vector(&TI.dq, t, &TI.nq, msg);
else if (!strcmp(t._name, "vq")) set_vector(&TI.vq, t, &TI.nq, msg);
else if (!strcmp(t._name, "tq")) set_vector(&TI.tq, t, &TI.nq, msg);
else if (!strcmp(t._name, "zq")) set_vector(&TI.zq, t, &TI.nq, msg); //-2018-10-04
else if (!strcmp(t._name, "rq")) set_vector(&TI.rq, t, &TI.nq, msg);
else if (!strcmp(t._name, "sq")) set_vector(&TI.sq, t, &TI.nq, msg); //-2018-10-04
else if (!strcmp(t._name, "lq")) set_vector(&TI.lq, t, &TI.nq, msg);
else if (!strcmp(t._name, "ts")) set_vector(&TI.ts, t, &TI.nq, msg); //-2018-10-04
else if (!strcmp(t._name, "rf")) set_vector(&TI.rf, t, &TI.nq, msg); //-2024-01-17
else if (!strcmp(t._name, "wq")) set_vector(&TI.wq, t, &TI.nq, msg);
else if (!strcmp(t._name, "xq")) set_vector(&TI.xq, t, &TI.nq, msg);
else if (!strcmp(t._name, "yq")) set_vector(&TI.yq, t, &TI.nq, msg);
else if (!strcmp(t._name, "iq")) set_vector(&TI.iq, t, &TI.nq, msg); //-2015-12-01
else if (!strcmp(t._name, "xb")) set_vector(&TI.xb, t, &TI.nb, msg);
else if (!strcmp(t._name, "yb")) set_vector(&TI.yb, t, &TI.nb, msg);
else if (!strcmp(t._name, "ab")) set_vector(&TI.ab, t, &TI.nb, msg);
else if (!strcmp(t._name, "bb")) set_vector(&TI.bb, t, &TI.nb, msg);
else if (!strcmp(t._name, "cb")) set_vector(&TI.cb, t, &TI.nb, msg);
else if (!strcmp(t._name, "wb")) set_vector(&TI.wb, t, &TI.nb, msg);
else if (!strcmp(t._name, "rb")) set_string(TI.bf, t, msg);
else if (!strcmp(t._name, "settingspath")) //bp
{ //bp
*msg = 0; //bp
} //bp
else if (!strcmp(t._name, "libpath")) //bp
{ //bp
strcpy(AbsoluteWindLibPath, t._tokens[0]); //bp
*msg = 0; //bp
} //bp
else {
for (i=0; i
set_vector(&TI.cmp[i], t, &TI.nq, msg);
break;
}
}
if (i >= SttCmpCount) unknown_name(msg);
}
if (!*msg && TipMustBeConstant(t._name) && !TipIsConstant(&t)) { //-2002-01-06
must_be_constant(msg);
}
return msg;
}
//=============================================================== TipSpcIndex
int TipSpcIndex( char *cmp_name ) {
char s[16], *pc;
int ks;
strcpy(s, cmp_name);
pc = strchr(s, '-');
if (pc) *pc = 0;
for (pc=s; (*pc); pc++) *pc = tolower(*pc);
for (ks=0; ks
}
return -1;
}
//============================================================= TipSpcEmitted
int TipSpcEmitted( int ks )
{
int ic, l;
char name[40];
if (ks<0 || ks>=SttSpcCount) return 0;
strcpy(name, SttSpcTab[ks].name);
if (!*name) return 0;
for (ic=0; ic
}
strcat(name, "-");
l = strlen(name);
for (ic=0; ic
}
return 0;
}
//=================================================================== TipRead
static int TipRead( char *path )
{
dP(TipRead);
FILE *f, *m;
int n=0, scanning=0, buflen=32000;
TIPREC t;
char *buf, *msg, name[256];
if (CHECK) vMsg("TipRead(%s) ...", path);
m = (MsgFile) ? MsgFile : stdout;
sprintf(name, "%s/%s", path, "austal.txt");
buf = ALLOC(buflen); if (!buf) eX(3);
f = fopen(name, "rb");
if (!f) {
vMsg(_cant_read_file_$_, name);
exit(2);
}
fprintf(m, "%s", _start_input_);
while (fgets(buf, buflen, f)) {
n++;
if (strlen(buf) >= buflen-2) eX(1);
if (!isalpha(*buf)) continue;
if (0 > parse(buf, &t)) eX(2);
fprintf(m, "> %s\n", buf); //-2001-06-09
MsgLow(t._name);
msg = analyse(t);
FREE(t._name);
FREE(t._tokens);
if (*msg) {
vMsg(_error_input_line_$$$_, n, buf, msg);
scanning = 1;
}
}
fclose(f);
fprintf(m, "%s", _end_input_);
FREE(buf);
fprintf(m, "\n");
if (scanning) return -1;
return n;
eX_1:
eMSG(_buffer_overflow_$_, n);
eX_2: eX_3:
eMSG(_internal_error_);
}
//============================================================= TipInitialize
//
static int TipInitialize( void ) {
dP(TipInitialize);
if (CHECK) vMsg("TipInitialize() ...");
TI.qs = 0; //-2020-10-14
TI.in = 3600;
TI.ib = 0; //-2024-01-17
TI.average = 24;
TI.qb = 0;
TI.gx = 0;
TI.gy = 0;
TI.ux = 0;
TI.uy = 0;
TI.dd = NULL;
TI.x0 = NULL;
TI.x1 = NULL;
TI.x2 = NULL;
TI.x3 = NULL;
TI.y0 = NULL;
TI.y1 = NULL;
TI.y2 = NULL;
TI.y3 = NULL;
TI.z0 = HUGE_VAL;
TI.d0 = HUGE_VAL;
TI.xq = NULL; //-2018-10-04
TI.yq = NULL; //-2018-10-04
TI.aq = NULL;
TI.bq = NULL;
TI.cq = NULL;
TI.hq = NULL;
TI.dq = NULL;
TI.vq = NULL;
TI.zq = NULL; //-2018-10-04
TI.rq = NULL; //-2018-10-04
TI.sq = NULL; //-2018-10-04
TI.lq = NULL; //-2018-10-04
TI.rf = NULL; //-2024-01-17
TI.ts = NULL; //-2018-10-04
TI.wq = NULL;
TI.iq = NULL; //-2015-12-01
TI.ha = 0; //-2002-04-16
TI.hm = 0;
TI.sc = 0; //-2011-11-23
TI.ri = -HUGE_VAL; //-2014-01-21
TI.xa = HUGE_VAL;
TI.ya = HUGE_VAL;
TI.sd = 11111;
TI.im = TipMaxIter; //-2008-10-20
TI.ie = TipEpsilon; //-2008-10-20
TI.mh = HUGE_VAL;
TI.npmax = 100; //bp //-2007-02-03
TI.xb = NULL;
TI.yb = NULL;
TI.ab = NULL;
TI.bb = NULL;
TI.cb = NULL;
TI.wb = NULL;
TI.xbmin = NULL;
TI.xbmax = NULL;
TI.ybmin = NULL;
TI.ybmax = NULL;
TI.dmk = ALLOC(9*sizeof(double)); if (!TI.dmk) return -1;
TI.dmk[0] = 6.0; // strength of recirculation
TI.dmk[1] = 1.0; // weighting of wind direction
TI.dmk[2] = 0.3; // strength of recirculation
TI.dmk[3] = 0.05; // Cut-Off
TI.dmk[4] = 0.7; // reduction of z-component
TI.dmk[5] = 1.2; // vertical relative extension
TI.dmk[6] = 15.0; // opening angle
TI.dmk[7] = 0.5; // strength of additional circulation
TI.dmk[8] = 0.3; // strength of additional turbulence
strcpy(TI.lc, "C"); //-2014-01-21
xcodeUnits(); //-2008-07-22
//bp TI.cmp = (double**)ALLOC(SttCmpCount*sizeof(double*)); //-2005-08-25
TI.cmp = (double**)ALLOC((SttCmpCount+1)*sizeof(double*)); //bp //-2005-08-25
init_index();
nADDODOR = SttCmpCount - 1 - cODOR; //-2024-01-17
if (nADDODOR > TIP_ADDODOR) eX(1);
return 0;
eX_1:
eMSG("maximum number of rated odorants exceeded (%d)!", TIP_ADDODOR);
}
//============================================================= TipCorine
//
static double TipCorine( int nq, double *xq, double *yq, double *hq, double *cq )
{ dP(TipCorine);
FILE *m;
double z0, z0m, z0g, x, y, h;
char *_buf=NULL;
char crc[16];
int n;
if (CHECK) vMsg("TipCorine(%d, ...) ...", nq);
m = (MsgFile) ? MsgFile : stdout;
z0m = 0;
z0g = 0;
n = TrlReadHeader(Home, TI.ggcs);
fprintf(m, "\n");
sprintf(crc, "%08x", RglCRC);
if ((strstr(RglFile, "gk") && !strcmp(crc, RGL_CRC_GK)) || //-2011-06-29
(strstr(RglFile, "utm") && !strcmp(crc, RGL_CRC_UTM)))
fprintf(m, _standard_register_$$_, RglFile, RglCRC);
else
vMsg(_nonstandard_register_$$_, RglFile, RglCRC);
vLOG(4)(_roughness2_$$_, RglGGCS, RglDelta);
vLOG(4)(_roughness3_$$$$_, RglXmin, RglXmax, RglYmin, RglYmax);
if (n)
return n;
for (n=0; n
y = TI.gy + yq[n];
h = hq[n] + 0.5*cq[n];
if (h < 10.) h = 10.; //-2008-09-05
z0 = TrlGetZ0(TI.ggcs, x, y, 15*h, &_buf); //-2018-11-22
if (RglMrd > 0 && MsgFile) {
fprintf(MsgFile, _gkconverted_$$$$$$_, RglMrd, n+1, x, y, RglX, RglY); //-2006-11-21
}
if (z0 <= 0) {
TrlReadHeader(NULL, NULL);
return z0;
}
vLOG(4)(_roughness4_$$$$_, n+1, x, y, h);
vLOG(4)(_roughness5_$$$$_, RglA, RglB, _buf, z0);
z0m += z0*h*h;
z0g += h*h;
}
TrlReadHeader(NULL, NULL);
if (z0g > 0) z0m /= z0g;
return z0m;
}
//============================================================== checkSurface
//
#define ZZ(i,j) *(float*)AryPtrX(&dsc, i, j)
static float getMaxDif( ARYDSC dsc, int n ) {
int i, j, i1, i2, j1, j2;
float dz, dzmax;
if (dsc.numdm != 2) return -1;
if (n < 1) n = 1;
i1 = dsc.bound[0].low;
i2 = dsc.bound[0].hgh;
j1 = dsc.bound[1].low;
j2 = dsc.bound[1].hgh;
dzmax = 0;
for (i=i1; i<=i2; i++) {
for (j=j1+n; j<=j2; j++) {
dz = ZZ(i,j)-ZZ(i,j-n);
dz = (dz < 0) ? -dz : dz;
if (dz > dzmax) dzmax = dz;
}
}
for (j=j1; j<=j2; j++) {
for (i=i1+n; i<=i2; i++) {
dz = ZZ(i,j)-ZZ(i-n,j);
dz = (dz < 0) ? -dz : dz;
if (dz > dzmax) dzmax = dz;
}
}
return dzmax;
}
static float getMeanHeight( ARYDSC dsc ) {
int i, j, i1, i2, j1, j2;
float h;
if (dsc.numdm != 2) return -9999;
i1 = dsc.bound[0].low;
i2 = dsc.bound[0].hgh;
j1 = dsc.bound[1].low;
j2 = dsc.bound[1].hgh;
h = 0;
for (i=i1; i<=i2; i++)
for (j=j1; j<=j2; j++)
h += ZZ(i,j);
h /= (i2-i1+1)*(j2-j1+1);
return h;
}
static int checkSurface( int n ) {
dP(checkSurface);
char fn[256], gn[256];
char *ggcs=NULL; //-2008-12-11
TXTSTR usr = { NULL, 0 };
TXTSTR sys = { NULL, 0 };
int nx, ny;
double x0, y0, dd, d1, d2, gx, gy;
ARYDSC dsc;
sprintf(fn, "%s/zg%02d.dmna", Path, n+(TI.nn>1));
if (!TutFileExists(fn)) {
if (*TI.gh == '*') eX(10);
if (TutMakeName(fn, Path, TI.gh) < 0) eX(10); //-2001-11-23
if (!TutFileExists(fn)) eX(10);
return 0;
}
sprintf(gn, "%s/zg%02d", Path, n+(TI.nn>1));
memset(&dsc, 0, sizeof(ARYDSC));
DmnRead(gn, &usr, &sys, &dsc); eG(1);
if (dsc.numdm != 2) eX(2);
if (dsc.bound[0].low!=0 || dsc.bound[1].low!=0) eX(3);
nx = dsc.bound[0].hgh;
ny = dsc.bound[1].hgh;
if (1 > DmnGetDouble(usr.s, "xmin|x0", "%lf", &x0, 1)) eX(4);
if (1 > DmnGetDouble(usr.s, "ymin|y0", "%lf", &y0, 1)) eX(5);
if (1 > DmnGetDouble(usr.s, "dd|delt|delta", "%lf", &dd, 1)) eX(6);
if (1 > DmnGetDouble(usr.s, "gakrx|refx", "%lf", &gx, 1)) gx = 0; //-2008-12-11
if (1 > DmnGetDouble(usr.s, "gakry|refy", "%lf", &gy, 1)) gy = 0; //-2008-12-11
if (1 > DmnGetString(usr.s, "ggcs", &ggcs, 0)) ggcs = NULL; //-2008-12-11
if (TI.gx != gx) eX(16);
if (TI.gy != gy) eX(17);
if (ggcs && strcmp(TI.ggcs, ggcs)) eX(18); //-2008-12-11
if (TI.nx[n] != nx) eX(11);
if (TI.ny[n] != ny) eX(12);
if (TI.dd[n] != dd) eX(13);
if (TI.x0[n] != x0) eX(14);
if (TI.y0[n] != y0) eX(15);
if (isUndefined(TI.mh)) TI.mh = getMeanHeight(dsc);
d1 = getMaxDif(dsc, 1)/dd;
d2 = getMaxDif(dsc, 2)/(2*dd);
if (MsgFile) {
fprintf(MsgFile, "%s", _maximum_steepness_);
if (TI.nn > 1) fprintf(MsgFile, _within_grid_$_, n+1);
fprintf(MsgFile, _steepness_is_$$_, d1, d2);
}
AryFree(&dsc);
return 1;
eX_10:
eMSG(_no_surface_file_$_, fn); //-2003-06-24
eX_1:
eMSG(_cant_read_file_$_, fn);
eX_2: eX_3:
eMSG(_improper_file_structure_$_, fn);
eX_4: eX_5: eX_6:
eMSG(_missing_grid_parameters_$_, fn);
eX_11: eX_12: eX_13: eX_14: eX_15: eX_16: eX_17: eX_18: //-2008-12-11
eMSG(_inconsistent_grid_parameters_$_, fn);
}
#undef ZZ
//============================================================== makeSurface
//
static int makeSurface( int n ) {
dP(makeSurface);
char fn[256];
NTRREC nrec, irec;
double rx0, rx3, ry0, ry3, gx0, gx3, gy0, gy3;
float d1, d2;
int meridr, meridg;
char locale[256]="C";
if (TutMakeName(fn, Path, TI.gh) < 0) eX(10); //-2001-11-23
if (NtrReadFile(fn) < 0) eX(1); //-2001-10-01
irec = NtrGetInRec();
meridr = (TI.gx+TI.x0[n])/1000000;
meridg = (irec.gkx+irec.xmin)/1000000;
if (meridr != meridg) eX(3);
rx0 = TI.gx + TI.x0[n];
rx3 = TI.gx + TI.x3[n];
ry0 = TI.gy + TI.y0[n];
ry3 = TI.gy + TI.y3[n];
gx0 = irec.gkx + irec.xmin;
gx3 = irec.gkx + irec.xmax;
gy0 = irec.gky + irec.ymin;
gy3 = irec.gky + irec.ymax;
if (rx0
nrec.nx = TI.nx[n]+1;
nrec.ny = TI.ny[n]+1;
nrec.xmin = TI.x0[n];
nrec.ymin = TI.y0[n];
nrec.delta = TI.dd[n];
nrec.gkx = TI.gx;
nrec.gky = TI.gy;
strcpy(nrec.ggcs, TI.ggcs); //-2008-12-11
NtrSetOutRec(nrec);
sprintf(fn, "%s/zg%02d", Path, n+(TI.nn>1));
//
if (*TI.lc) { //-2003-07-07
strcpy(locale, setlocale(LC_NUMERIC, NULL));
setlocale(LC_NUMERIC, TI.lc);
}
NtrWriteFile(fn); eG(2);
if (*TI.lc) setlocale(LC_NUMERIC, locale); //-2003-07-07
//
if (isUndefined(TI.mh)) TI.mh = getMeanHeight(NtrDsc);
d1 = getMaxDif(NtrDsc, 1)/TI.dd[n];
d2 = getMaxDif(NtrDsc, 2)/(2*TI.dd[n]);
if (MsgFile) {
fprintf(MsgFile, "%s", _maximum_steepness_);
if (TI.nn > 1) fprintf(MsgFile, _within_grid_$_, n+1);
fprintf(MsgFile, _steepness_is_$$_, d1, d2);
}
AryFree(&NtrDsc);
return 0;
eX_10: eX_1:
eMSG(_cant_read_surface_file_$_, fn);
eX_2:
eMSG(_cant_write_surface_profile_$_, fn);
eX_3:
eMSG(_inconsistent_systems_);
eX_4:
if (MsgFile) {
fprintf(MsgFile, _computational_area_$$$$_, rx0, rx3, ry0, ry3);
fprintf(MsgFile, _surface_area_$$$$_, gx0, gx3, gy0, gy3);
}
eMSG(_not_inside_surface_);
}
//============================================================== getNesting
//
static int getNesting( int nq, double *xm, double *ym, double *hq,
double *aq, double *bq, double *cq,
int nb, double *xb0, double *xb3, double *yb0,
double *yb3, double ddb, double gd[10][5] ) {
int i, j, n, k, kstart, gdset;
double d, dmin, xmin, xmax, ymin, ymax, x0, x3, y0, y3, h;
double a, b, r, x, y;
double rfac = 20;
double ddq = gd[0][0];
if (nq < 1) return -1;
xmin = gd[0][1];
xmax = gd[0][2];
ymin = gd[0][3];
ymax = gd[0][4];
dmin = (nb) ? ddb : ddq;
if (dmin <= 0) return -2;
xmin /= dmin;
xmax /= dmin;
ymin /= dmin;
ymax /= dmin;
d = 1;
kstart = 0;
gdset = -1;
if (nb) {
for (kstart=0; kstart<=1; kstart++) {
gd[kstart][0] = d;
d *= 2;
gd[kstart][1] = d*floor((xb0[kstart]/dmin)/d);
gd[kstart][2] = d*ceil((xb3[kstart]/dmin)/d);
gd[kstart][3] = d*floor((yb0[kstart]/dmin)/d);
gd[kstart][4] = d*ceil((yb3[kstart]/dmin)/d);
gdset = kstart;
if (d*dmin > ddq) {
d /= 2;
rfac *= ddq/(d*dmin);
break;
}
}
}
for (k=kstart; k<10; k++) {
x0 = x3 = xm[0]/dmin;
y0 = y3 = ym[0]/dmin;
for (n=0; n
y = ym[n]/dmin;
a = aq[n]/dmin;
b = bq[n]/dmin;
r = 0.5*sqrt(a*a+b*b);
h = (hq[n] + 0.5*cq[n])/dmin;
if (d <= 0.5*h) continue;
a = rfac*d + r;
if (x-a < x0) x0 = x-a;
if (x+a > x3) x3 = x+a;
if (y-a < y0) y0 = y-a;
if (y+a > y3) y3 = y+a;
}
if (k <= gdset) { //-2004-11-10
if (gd[k][1] < x0) x0 = gd[k][1];
if (gd[k][2] > x3) x3 = gd[k][2];
if (gd[k][3] < y0) y0 = gd[k][3];
if (gd[k][4] > y3) y3 = gd[k][4];
}
/*
if (k > 0) { //-2004-11-12
if (gd[k-1][1] < x0) x0 = gd[k-1][1];
if (gd[k-1][2] > x3) x3 = gd[k-1][2];
if (gd[k-1][3] < y0) y0 = gd[k-1][3];
if (gd[k-1][4] > y3) y3 = gd[k-1][4];
}
*/
gd[k][0] = d;
d *= 2;
x0 = d*floor(x0/d);
x3 = d*ceil(x3/d);
y0 = d*floor(y0/d);
y3 = d*ceil(y3/d);
if (x0 <= xmin+d) x0 = d*floor(xmin/d);
if (x3 >= xmax-d) x3 = d*ceil(xmax/d);
if (y0 <= ymin+d) y0 = d*floor(ymin/d);
if (y3 >= ymax-d) y3 = d*ceil(ymax/d);
if (k > 0) { //-2004-11-30
if (gd[k-1][1] < x0) x0 = d*floor(gd[k-1][1]/d);
if (gd[k-1][2] > x3) x3 = d*ceil(gd[k-1][2]/d);
if (gd[k-1][3] < y0) y0 = d*floor(gd[k-1][3]/d);
if (gd[k-1][4] > y3) y3 = d*ceil(gd[k-1][4]/d);
}
gd[k][1] = x0;
gd[k][2] = x3;
gd[k][3] = y0;
gd[k][4] = y3;
if (x0<=xmin && x3>=xmax && y0<=ymin && y3>=ymax) break;
}
if (k <= 9) k++;
for (i=0; i
gd[i][j] *= dmin;
//
// add guard cells for inner grids
//
for (i=0; i
gd[i][1] -= 2*d;
gd[i][2] += 2*d;
gd[i][3] -= 2*d;
gd[i][4] += 2*d;
}
//
// check and possibly adjust or remove outer grid
//
d = 0.01;
n = 0;
if (k > 1) { //-2004-10-25
if (gd[k-1][1] + d >= gd[k-2][1]) {
gd[k-1][1] = gd[k-2][1];
n++;
}
if (gd[k-1][2] - d <= gd[k-2][2]) {
gd[k-1][2] = gd[k-2][2];
n++;
}
if (gd[k-1][3] + d >= gd[k-2][3]) {
gd[k-1][3] = gd[k-2][3];
n++;
}
if (gd[k-1][4] - d <= gd[k-2][4]) {
gd[k-1][4] = gd[k-2][4];
n++;
}
if (n == 4) k--;
}
return k;
}
//============================================================= checkGrid
//
static int overlap( int i, int j ) {
double xi1, xi2, yi1, yi2;
double xj1, xj2, yj1, yj2;
xi1 = TI.x1[i];
xi2 = TI.x2[i];
yi1 = TI.y1[i];
yi2 = TI.y2[i];
xj1 = TI.x1[j];
xj2 = TI.x2[j];
yj1 = TI.y1[j];
yj2 = TI.y2[j];
if (xi2 <= xj1) return 0;
if (xi1 >= xj2) return 0;
if (yi2 <= yj1) return 0;
if (yi1 >= yj2) return 0;
return 1;
}
static int checkGrid( void ) {
dP(checkGrid);
int n, nn, m, nx, ny, i, j;
double ddmin, ddmax, dd, x, y;
nn = TI.nn;
if (nn < 1) eX(1);
if (!TI.dd) eX(2);
TI.gl = ALLOC(nn*sizeof(int)); if (!TI.gl) eX(42);
TI.gi = ALLOC(nn*sizeof(int)); if (!TI.gi) eX(43);
//
// check spacing: smallest mesh width first
//
ddmax = ddmin = TI.dd[0]; //-2002-03-26
for (n=0; n
if (dd == ddmax) continue;
if (dd < ddmax) eX(3);
if (dd != 2*ddmax) eX(4);
ddmax = dd;
}
dd = ddmax;
i = (nn > 1);
if (i && TI.dd[nn-2]==ddmax) eX(44); //-2002-09-21
m = i;
for (n=nn-1; n>=0; n--) {
if (TI.dd[n] < dd) {
m++;
i = 1;
dd = TI.dd[n];
}
TI.gl[n] = m;
TI.gi[n] = i++;
}
if (!TI.x0) eX(5);
if (!TI.y0) eX(6);
//
// check alignment: lower left border
//
for (n=0; n
for (m=n+1; m
if (fmod(TI.x0[n]-TI.x0[m], TI.dd[m]) != 0) eX(7);
if (fmod(TI.y0[n]-TI.y0[m], TI.dd[m]) != 0) eX(8);
}
}
//
// check alignment: right border
//
if (TI.nx) {
for (n=0; n
dd = TI.dd[n];
if (dd
}
if (TI.x3) {
for (n=0; n
if (TI.nx) {
if (TI.x3[n] != TI.x0[n]+TI.nx[n]*dd) eX(12);
}
else {
if (fmod(TI.x3[n], dd) != 0) eX(13); //-2001-11-03
for (m=n+1; m
if (fmod(TI.x3[n]-TI.x0[m], TI.dd[m]) != 0) eX(14);
}
}
}
}
else { // set right border
if (!TI.nx) eX(15);
TI.x3 = ALLOC(nn*sizeof(double)); if (!TI.x3) eX(16);
for (n=0; n
}
if (!TI.nx) { // set number of x-intervals
TI.nx = ALLOC(nn*sizeof(int)); if (!TI.nx) eX(17);
for (n=0; n
}
// check number of x-intervals
for (n=0; n
//
if (TI.x1) { // check inner left border
for (n=0; n
}
else { // set inner left border
TI.x1 = ALLOC(nn*sizeof(double)); if (!TI.x1) eX(19);
for (n=0; n
if (TI.x2) { // check inner right border
for (n=0; n
}
else { // set inner right border
TI.x2 = ALLOC(nn*sizeof(double)); if (!TI.x2) eX(21);
for (n=0; n
//
// check alignment: upper border
//
if (TI.ny) {
for (n=0; n
dd = TI.dd[n];
if (dd
}
if (TI.y3) {
for (n=0; n
if (TI.ny) {
if (TI.y3[n] != TI.y0[n]+TI.ny[n]*dd) eX(32);
}
else {
if (fmod(TI.y3[n], dd) != 0) eX(33); //-2001-11-03
for (m=n+1; m
if (fmod(TI.y3[n]-TI.y0[m], TI.dd[m]) != 0) eX(34);
}
}
}
}
else { // set upper border
if (!TI.ny) eX(35);
TI.y3 = ALLOC(nn*sizeof(double)); if (!TI.y3) eX(36);
for (n=0; n
}
if (!TI.ny) { // set number of y-intervals
TI.ny = ALLOC(nn*sizeof(int)); if (!TI.ny) eX(37);
for (n=0; n
}
// check number of y-intervals
for (n=0; n
//
if (TI.y1) { // check lower inner border
for (n=0; n
}
else { // set lower inner border
TI.y1 = ALLOC(nn*sizeof(double)); if (!TI.y1) eX(39);
for (n=0; n
if (TI.y2) { // check upper inner border
for (n=0; n
}
else { // set upper inner border
TI.y2 = ALLOC(nn*sizeof(double)); if (!TI.y2) eX(41);
for (n=0; n
//
// check overlap of inner regions
//
for (n=0; n
for (m=n+1; m
if (overlap(n, m)) {
vMsg(_no_overlap_$$_, n+1, m+1);
}
}
}
//
// check inclusion of finer grids
//
for (n=0; n
if (dd == ddmax) break;
nx = TI.nx[n];
ny = TI.ny[n];
for (i=0; i
for (j=0; j
for (m=n+1; m
if (TI.dd[m] > 2*dd) eX(50);
if (x>TI.x0[m] && x
if (m >= nn) eX(50); //-2003-10-02
}
}
}
return 0;
//
eX_16: eX_17: eX_19: eX_21: eX_36: eX_37: eX_39: eX_41: eX_42: eX_43:
eMSG(_internal_error_);
eX_1: eX_2:
eMSG(_no_grid_);
eX_3:
eMSG(_increasing_mesh_width_required_);
eX_4:
eMSG(_factor_2_required_);
eX_5:
eMSG(_no_western_border_);
eX_6:
eMSG(_no_southern_border_);
eX_7:
eMSG(_improper_western_border_$_, n+1);
eX_8:
eMSG(_improper_southern_border_$_, n+1);
eX_10:
eMSG(_invalid_nx_$_, n+1);
eX_11:
eMSG(_even_nx_required_$_, n+1);
eX_12: eX_13:
eMSG(_improper_eastern_border_$_, n+1);
eX_14:
eMSG(_invalid_eastern_border_$_, n+1);
eX_15:
eMSG(_missing_nx_);
eX_18:
eMSG(_improper_x1_$_, n+1);
eX_20:
eMSG(_improper_x2_$_, n+1);
eX_30:
eMSG(_invalid_ny_$_, n+1);
eX_31:
eMSG(_even_ny_required_$_, n+1);
eX_32: eX_33:
eMSG(_improper_northern_border_$_, n+1);
eX_34:
eMSG(_invalid_northern_border_$_, n+1);
eX_35:
eMSG(_missing_ny_);
eX_38:
eMSG(_improper_y1_$_, n+1);
eX_40:
eMSG(_improper_y2_$_, n+1);
eX_44:
eMSG(_only_one_coarse_grid_);
eX_50:
eMSG(_$_not_within_coarse_grid_, n+1);
eX_51:
eMSG(_nx_too_large_$$_, n+1, NxyMax);
eX_52:
eMSG(_ny_too_large_$$_, n+1, NxyMax);
}
//============================================================== TipCheck
//
/* - not used? uj 2018-10-04
static TIPVAR *get_varptr( char *name ) { //-2005-09-23
TIPVAR *ptv = NULL;
int i;
if (!TipVar.start)
return NULL;
for (i=0; i
if (!ptv)
return NULL;
if (!strcmp(name, ptv->name))
break;
ptv = NULL; //-2006-12-13
}
return ptv;
}
*/
int TipLogCheck(char *id, int sum) {
if (id != NULL) {
TXTSTR st = { NULL, 0 };
TxtPrintf(&st, "%s %-8s %08x\n", _checksum_, id, sum);
TxtCat(&LogCheck, st.s);
}
return 0;
}
static int TipCheck( char *path, int write_z ) {
dP(TipCheck);
char name[256], s[1024], elnm[40], fname[1024], prcname[1024]; //-2018-20-29
char locale[256]="C";
int i, j, i1, i2, k, n, l, emission, d=0, kpmax, rc, check; //-2011-11-23
int iq; //-2015-12-01
int make_surface=0, check_surface=0, series_exists=0;
int make_grid=0, make_nz=0, round_z0=1; //-2015-12-15
double x, y, z, xmin, ymin, xmax, ymax, z0, h, dz, r, co, si;
double f1, f2, f3, f4, f5, f6, f7, f8, f9;
double dd, dh, gd[10][5];
double hh[100];
DMNFRMREC *pfr;
TIPVAR *ptv;
TXTSTR syshdr = { NULL, 0 };
TXTSTR usrhdr = { NULL, 0 };
if (CHECK) vMsg("TipCheck(%s, %d) ...", path, write_z);
//
// check values
//
strcpy(locale, setlocale(LC_NUMERIC, NULL)); //-2008-10-17
if (*TI.os) { //-2004-07-09
char *ps;
for (ps=TI.os; (*ps); ps++) if (*ps == ',') *ps = '.'; //-2003-07-07
if (strstr(TI.os, "SCINOTAT")) { //-2003-02-21
TalMode |= TIP_SCINOTAT;
}
if (strstr(TI.os, "NOSTANDARD") || strstr(TI.os, "NONSTANDARD")) //-2008-08-27
TalMode |= TIP_NOSTANDARD;
if (strstr(TI.os, "NOTALUFT") || strstr(TI.os, "NONTALUFT")) //-2020-10-14
TalMode |= TIP_NOTALUFT;
if (strstr(TI.os, "BESMAX")) //-2024-01-17
TalMode |= TIP_BESMAX;
}
check_tab(); //-2005-08-25
if (!*TI.lc) strcpy(TI.lc, "C"); //-2003-07-07
else if (strcmp(TI.lc, "german") && strcmp(TI.lc, "C")) eX(242);
MsgSetLocale(TI.lc); //-2008-10-17
//////////////////////////////////////////////////////////////////////////////
// BESMAX
//////////////////////////////////////////////////////////////////////////////
if (BESMAX) { //-2024-01-17
int ixx;
STTSPCREC *pr;
unsigned int icrc;
char crc[16];
FILE *f;
//
vMsg(_besmax_);
//
// check substance
ixx = getCmpIndex("xx");
if (!TI.cmp[ixx]) {
vMsg(_besmax_xx_required_);
return -1;
}
for (i=0; i
vMsg(_besmax_only_xx_allowed_);
return -1;
}
//
// adjust evaluation
pr = SttSpcTab + TipSpcIndex("xx");
pr->ry = 0;
pr->rn = 0;
pr->rd = 0;
pr->dh = -1;
pr->nh = 0;
pr->vd = 0;
pr->wf = 0;
strcpy(pr->uc, _U_MGM3_);
pr->fc = 1.e3;
pr->rh = 1;
if (isUndefined(TI.z0))
TI.z0 = 0.5;
if (isUndefined(TI.d0))
TI.d0 = 3.0;
if (isUndefined(TI.ha) || TI.ha == 0)
TI.ha = 13.0;
//
// checks
if (TI.z0 != 0.5) {
vMsg(_besmax_invalid_z0_);
return -1;
}
if (TI.d0 != 3.0) {
vMsg(_besmax_invalid_d0_);
return -1;
}
if (TI.ha != 13.0) {
vMsg(_besmax_invalid_ha_);
return -1;
}
//
// aks check
if (!*TI.as) {
vMsg(_besmax_as_notdefined_);
return -1;
}
if (TutMakeName(name, Path, TI.as) < 0) eX(10);
f = fopen(name, "rb");
if (!f) {
vMsg(_besmax_as_notfound_, name);
return -1;
}
icrc = TutGetCrc(name);
sprintf(crc, "%08x", icrc);
if (strcmp(crc, BESMAX_CRC)) {
vMsg(_besmax_as_modified_, BESMAX_CRC);
}
}
//////////////////////////////////////////////////////////////////////////////
// NOTALUFT
//////////////////////////////////////////////////////////////////////////////
if (NOTALUFT) { //-2020-10-14
vMsg(_notaluft_);
TI.average = 1;
if (strstr(TI.os, "VDI37831")) {
TalMode |= TIP_VDI37831;
if (TI.ib == 0)
TI.ib = 60.;
}
else if (TI.ib == 0)
TI.ib = 3600.;
}
//////////////////////////////////////////////////////////////////////////////
// TALUFT
//////////////////////////////////////////////////////////////////////////////
if (!NOTALUFT) {
if (TI.ib == 0)
TI.ib = 3600.;
int not_allowed = 0;
if (strstr(TI.os, "VDI37831")) {
vMsg(_$_notal_ignored_, "VDI37831");
not_allowed++;
}
if (TI.in != 3600) {
vMsg(_$_notal_ignored_, "in");
TI.in = 3600;
not_allowed++;
}
if (TI.ib != 3600) {
vMsg(_$_notal_ignored_, "ib");
TI.ib = 3600;
not_allowed++;
}
if (not_allowed)
return -1;
}
//////////////////////////////////////////////////////////////////////////////
// NOSTANDARD
//////////////////////////////////////////////////////////////////////////////
if (NOSTANDARD) {
char *pc;
int kref, kmax;
int d;
vMsg(_nostandard_);
setlocale(LC_NUMERIC, "C"); //-2008-10-17
if (strstr(TI.os, "LIB2")) TalMode |= TIP_LIB2;
else if (strstr(TI.os, "LIB36")) TalMode |= TIP_LIB36;
pc = strstr(TI.os, "Kref=");
if (pc) {
kref = 1;
sscanf(pc+5, "%d", &kref);
if (kref < 0) kref = 1;
if (TI.kp < kref) TI.kp = kref;
}
pc = strstr(TI.os, "Kmax=");
if (pc) {
kmax = 1;
sscanf(pc+5, "%d", &kmax);
if (kmax <= 0) kmax = 1;
if (TI.kp < kmax) TI.kp = kmax;
}
if (strstr(TI.os, "SORRELAX")) {
TalMode |= TIP_SORRELAX; //-2006-02-06
}
pc = strstr(TI.os, "BS="); //-2004-06-10
if (pc) sscanf(pc+3, "%lf", &SttOdorThreshold);
pc = strstr(TI.os, "SRCTRB="); //-2018-10-04
if (pc) sscanf(pc+7, "%lf", &SttSrcTurbulence);
pc = strstr(TI.os, "Average="); //-2007-02-03
if (pc) {
d = TI.average;
sscanf(pc+8, "%d", &d);
if (d > 0) TI.average = d;
}
pc = strstr(TI.os, "MntMax="); //-2007-02-03
if (pc) {
d = TI.npmax;
sscanf(pc+7, "%d", &d);
if (d > 200) d = 200;
if (d > TI.npmax) TI.npmax = d;
}
pc = strstr(TI.os, "DMKp=");
if (pc) {
n = sscanf(pc+5, "{%lf;%lf;%lf;%lf;%lf;%lf;%lf;%lf;%lf}",
&f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &f9);
if (n != 9) eX(300);
TI.dmk[0] = f1;
TI.dmk[1] = f2;
TI.dmk[2] = f3;
TI.dmk[3] = f4;
TI.dmk[4] = f5;
TI.dmk[5] = f6;
TI.dmk[6] = f7;
TI.dmk[7] = f8;
TI.dmk[8] = f9;
}
if (!isUndefined(TI.hm) && TI.hm != 0) {
vMsg(_$_not_time_dependent_, "hm"); //-2011-12-02
TI.hm = 0;
}
}
//
// complain about parameters that have been set but require NOSTANDARD
else { //-2002-03-26
int not_allowed = 0; //-2011-12-16
if (strstr(TI.os, "WriteSeries")) { //-2024-01-17
vMsg(_$_option_ignored_, "WriteSeries");
not_allowed++;
}
if (strstr(TI.os, "Average=")) { //-2024-01-17
vMsg(_$_option_ignored_, "Average");
not_allowed++;
}
if (strstr(TI.os, "Glat=")) { //-2024-01-17
vMsg(_$_option_ignored_, "Glat");
not_allowed++;
}
if (strstr(TI.os, "Ta=")) { //-2024-01-17
vMsg(_$_option_ignored_, "Ta");
not_allowed++;
}
if (strstr(TI.os, "Rh=")) { //-2024-01-17
vMsg(_$_option_ignored_, "Rh");
not_allowed++;
}
if (strstr(TI.os, "MntMax=")) { //-2024-01-17
vMsg(_$_option_ignored_, "MntMax");
not_allowed++;
}
if (strstr(TI.os, "BS=")) { //-2024-01-17
vMsg(_$_option_ignored_, "BS");
not_allowed++;
}
if (strstr(TI.os, "Vd=")) { //-2024-01-17
vMsg(_$_option_ignored_, "Vd");
not_allowed++;
}
if (strstr(TI.os, "Vs=")) { //-2024-01-17
vMsg(_$_option_ignored_, "Vs");
not_allowed++;
}
if (strstr(TI.os, "Wf=")) { //-2024-01-17
vMsg(_$_option_ignored_, "Wf");
not_allowed++;
}
if (strstr(TI.os, "We=")) { //-2024-01-17
vMsg(_$_option_ignored_, "We");
not_allowed++;
}
if (strstr(TI.os, "DMKp=")) { //-2024-01-17
vMsg(_$_option_ignored_, "DMKp");
not_allowed++;
}
if (strstr(TI.os, "Kref=")) { //-2024-01-17
vMsg(_$_option_ignored_, "Kref");
not_allowed++;
}
if (strstr(TI.os, "Kmax=")) { //-2024-01-17
vMsg(_$_option_ignored_, "Kmax");
not_allowed++;
}
if (strstr(TI.os, "SRCTRB=")) { //-2024-01-17
vMsg(_$_option_ignored_, "SRCTRB");
not_allowed++;
}
if (strstr(TI.os, "WETDRIFT")) { //-2023-07-17
vMsg(_$_option_ignored_, "WETDRIFT");
not_allowed++;
}
if (strstr(TI.os, "NOSHEAR")) { //-2023-07-17
vMsg(_$_option_ignored_, "NOSHEAR");
not_allowed++;
}
if (strstr(TI.os, "NOSTDW")) { //-2023-07-17
vMsg(_$_option_ignored_, "NOSTDW");
not_allowed++;
}
if (strstr(TI.os, "SORRELAX")) { //-2023-07-17
vMsg(_$_option_ignored_, "SORRELAX");
not_allowed++;
}
if (strstr(TI.os, "SPECTRUM")) { //-2023-07-17
vMsg(_$_option_ignored_, "SPECTRUM");
not_allowed++;
}
if (strstr(TI.os, "LIB2")) { //-2024-01-17
vMsg(_$_option_ignored_, "LIB2");
not_allowed++;
}
if (strstr(TI.os, "LIB36")) { //-2024-01-17
vMsg(_$_option_ignored_, "LIB36");
not_allowed++;
}
if (TI.hm != 0) {
vMsg(_$_ignored_, "hm"); //-2008-10-20
TI.hm = 0;
not_allowed++;
}
if (TI.ie != TipEpsilon) {
vMsg(_$_ignored_, "ie"); //-2008-10-20
TI.ie = TipEpsilon;
not_allowed++;
}
if (TI.im != TipMaxIter) {
vMsg(_$_ignored_, "im"); //-2008-10-20
TI.im = TipMaxIter;
not_allowed++;
}
if (TI.mh != HUGE_VAL) {
vMsg(_$_ignored_, "mh"); //-2008-10-20
TI.mh = HUGE_VAL;
not_allowed++;
}
if (TI.x1 != NULL) {
vMsg(_$_ignored_, "x1"); //-2008-10-20
FREE(TI.x1);
TI.x1 = NULL;
not_allowed++;
}
if (TI.x2 != NULL) {
vMsg(_$_ignored_, "x2"); //-2008-10-20
FREE(TI.x2);
TI.x2 = NULL;
not_allowed++;
}
if (TI.x3 != NULL) {
vMsg(_$_ignored_, "x3"); //-2008-10-20
FREE(TI.x3);
TI.x3 = NULL;
not_allowed++;
}
if (TI.y1 != NULL) {
vMsg(_$_ignored_, "y1"); //-2008-10-20
FREE(TI.y1);
TI.y1 = NULL;
not_allowed++;
}
if (TI.y2 != NULL) {
vMsg(_$_ignored_, "y2"); //-2008-10-20
FREE(TI.y2);
TI.y2 = NULL;
not_allowed++;
}
if (TI.y3 != NULL) {
vMsg(_$_ignored_, "y3"); //-2008-10-20
FREE(TI.y3);
TI.y3 = NULL;
not_allowed++;
}
if (TI.hh != NULL) {
vMsg(_$_ignored_, "hh"); //-2012-04-06
FREE(TI.hh);
TI.hh = NULL;
not_allowed++;
}
if (TI.ts != NULL && !VDI37831) {
vMsg(_$_ignored_, "ts"); //-2018-10-04
FREE(TI.ts);
TI.ts = NULL;
not_allowed++;
}
if (BESMAX && strstr(TI.os, "NSUB5")) {
vMsg(_$_ignored_, "NSUB5");
not_allowed++;
}
if (VDI37831 && TI.ib != 60.) {
vMsg(_$_ignored_, "ib");
not_allowed++;
}
if (not_allowed) //-2011-12-16
return -1;
}
// end complain
//
// interval concentration
if (TI.in < 5 || TI.in > 3600) { //-2020-10-14
vMsg(_in_out_of_range_);
return -1;
}
//
// interval boundary layer model
if (TI.ib < 60 || TI.ib > 3600) { //-2020-10-14
vMsg(_ib_out_of_range_);
return -1;
}
if (TI.ib != 60 && VDI37831 && !NOSTANDARD) { //-2024-01-17
vMsg(_ib_60_required_);
return -1;
}
//
// mixing height variation only with time series
if (TI.hm != 0 && *TI.as) {
vMsg(_hm_not_with_aks_); //-2018-10-04
TI.hm = 0;
return -1;
}
//
// precipitation must be set time dependent
if (!*TI.as && TI.ri != -HUGE_VAL && !isUndefined(TI.ri)) { //-2014-01-21
vMsg(_ri_time_dependent_);
return -1;
}
//
// coordinate system
//
if ((TI.gx!=0 || TI.gy!=0) && (TI.ux!=0 || TI.uy!=0)) {
vMsg(_mixed_systems_);
return -1;
}
else if ((TI.gx==0 && TI.gy==0) && (TI.ux==0 && TI.uy==0))
strcpy(TI.ggcs, "");
else if ((TI.gx==0 && TI.gy==0) && (TI.ux!=0)) { //-2008-12-04
strcpy(TI.ggcs, "UTM");
TI.gx = TI.ux;
TI.gy = TI.uy;
if (TI.gx < 1000000) TI.gx += 32000000; //-2008-12-07
}
else if ((TI.gx!=0 && TI.gy!=0) && (TI.ux==0 && TI.uy==0))
strcpy(TI.ggcs, "GK");
else {
vMsg(_incomplete_coordinates_);
return -1;
}
//
if (isUndefined(TI.z0)) {
if (strlen(TI.ggcs) == 0) {
vMsg(_missing_z0_);
return -1;
}
}
else if (TI.z0 < 0) {
vMsg(_invalid_z0_);
return -1;
}
//
vMsg("Anzahl CPUs: %d ", numprocs); //bp
if (!NOSTANDARD) { //-2024-01-17
if ((!BESMAX && !VDI37831 && TI.qs>4) || (BESMAX && TI.qs>12) || (VDI37831 && TI.qs>16)) {
vMsg(_invalid_qs_);
return -1;
}
}
if (TI.qs < -4) {
vMsg(_invalid_qs_);
return -1;
}
//
// sources
//
if (TI.nq < 1) {
vMsg(_no_sources_);
return -1;
}
TI.xm = ALLOC(TI.nq*sizeof(double)); if (!TI.xm) eX(1);
TI.ym = ALLOC(TI.nq*sizeof(double)); if (!TI.ym) eX(2);
if (!TI.hq) {
vMsg(_no_stack_height_);
return -1;
}
if (!TI.iq) { //-2015-12-01
TI.iq = ALLOC(TI.nq*sizeof(double)); if (!TI.iq) eX(13);
}
if (!TI.aq) {
TI.aq = ALLOC(TI.nq*sizeof(double)); if (!TI.aq) eX(3);
}
if (!TI.bq) {
TI.bq = ALLOC(TI.nq*sizeof(double)); if (!TI.bq) eX(4);
}
if (!TI.cq) {
TI.cq = ALLOC(TI.nq*sizeof(double)); if (!TI.cq) eX(5);
}
if (!TI.dq) {
TI.dq = ALLOC(TI.nq*sizeof(double)); if (!TI.dq) eX(6);
}
if (!TI.vq) {
TI.vq = ALLOC(TI.nq*sizeof(double)); if (!TI.vq) eX(8);
}
if (!TI.tq) {
TI.tq = ALLOC(TI.nq*sizeof(double)); if (!TI.tq) eX(7);
for (n=0; n
if (!TI.zq) { //-2018-10-04
TI.zq = ALLOC(TI.nq*sizeof(double)); if (!TI.zq) eX(7);
}
if (!TI.rq) {
TI.rq = ALLOC(TI.nq*sizeof(double)); if (!TI.rq) eX(7);
}
if (!TI.sq) { //-2018-10-04
TI.sq = ALLOC(TI.nq*sizeof(double)); if (!TI.sq) eX(7);
}
if (!TI.lq) {
TI.lq = ALLOC(TI.nq*sizeof(double)); if (!TI.lq) eX(7);
}
if (!TI.rf) { //-2024-01-17
TI.rf = ALLOC(TI.nq*sizeof(double)); if (!TI.rf) eX(7);
for (n=0; n
if (!TI.ts) { //-2018-10-04
TI.ts = ALLOC(TI.nq*sizeof(double)); if (!TI.ts) eX(7);
for (n=0; n
if (!TI.wq) {
TI.wq = ALLOC(TI.nq*sizeof(double)); if (!TI.wq) eX(9);
}
if (!TI.xq) {
TI.xq = ALLOC(TI.nq*sizeof(double)); if (!TI.xq) eX(10);
}
if (!TI.yq) {
TI.yq = ALLOC(TI.nq*sizeof(double)); if (!TI.yq) eX(11);
}
if (cNO2 >= 0 && cNO >= 0 && !TI.cmp[cNO2] && TI.cmp[cNO]) { //2011-11-23
TI.cmp[cNO2] = ALLOC(TI.nq*sizeof(double)); if (!TI.cmp[cNO2]) eX(12);
}
for (n=0; n
if (fabs(TI.yq[n]) > TIP_MAXLENGTH) { strcpy(s, "yq"); eX(240); }
if (TI.hq[n]<0 || TI.hq[n]>900) { //-2019-03-05
vMsg(_invalid_stack_height_$_, n+1);
return -1;
}
if (TI.hq[n] < 10 && TI.iq[n] < 1 && !NOTALUFT) { //-2015-12-01 -2020-10-14
vMsg(_low_stack_height_$_, n+1);
}
if (TI.aq[n] < 0) {
vMsg(_invalid_aq_$_, n+1);
return -1;
}
if (TI.bq[n] < 0) {
vMsg(_invalid_bq_$_, n+1);
return -1;
}
if (TI.cq[n]<0 || TI.cq[n]+TI.hq[n]>900) { //-2019-03-05
vMsg(_invalid_cq_$_, n+1);
return -1;
}
if (TI.dq[n] < 0) {
vMsg(_invalid_dq_$_, n+1);
return -1;
}
if (TI.ts[n] < 0 && TI.vq[n] > 0 && TI.dq[n] == 0) { //-2024-01-17
vMsg(_invalid_dq_with_vq_$_, n+1);
return -1;
}
if (TI.ts[n] < 0 && TI.dq[n] > 0 && TI.vq[n] == 0) { //-2024-01-17
vMsg(_invalid_vq_with_dq_$_, n+1);
return -1;
}
if (TI.vq[n] < 0 && !VDI37831) { //-2020-10-14
vMsg(_invalid_vq_$_, n+1);
return -1;
}
if (TI.wq[n]<-360 || TI.wq[n]>360) {
vMsg(_invalid_wq_$_, n+1);
return -1;
}
co = cos(TI.wq[n]/RADIAN);
si = sin(TI.wq[n]/RADIAN);
TI.xm[n] = TI.xq[n] + 0.5*(TI.aq[n]*co - TI.bq[n]*si); //-2001-09-04
TI.ym[n] = TI.yq[n] + 0.5*(TI.bq[n]*co + TI.aq[n]*si); //-2001-09-04
//
if (TI.iq[n] != 0) { //-2015-12-01
if (!isUndefined(TI.iq[n])) {
iq = TI.iq[n];
if (iq != TI.iq[n]) {
vMsg(_invalid_iq_$_, n+1);
return -1;
}
sprintf(fname, "%s/%02d/e%04d.dmna", Path, n+1, iq);
if (!TutFileExists(fname)) {
vMsg(_missing_grid_src_file_$_, fname);
return -1;
}
}
else {
sprintf(fname, "%s/%02d", Path, n+1);
if (!TutDirExists(fname)) {
vMsg(_missing_grid_src_dir_$_, fname);
return -1;
}
}
}
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// check for buildings //-2004-07
//
if (TI.nb > 0 && strlen(TI.bf) > 0) eX(312);
if (TI.nb > 0 || strlen(TI.bf) > 0) {
TI.xbmin = ALLOC(2*sizeof(double)); if (!TI.xbmin) eX(301);
TI.xbmax = ALLOC(2*sizeof(double)); if (!TI.xbmax) eX(301);
TI.ybmin = ALLOC(2*sizeof(double)); if (!TI.ybmin) eX(301);
TI.ybmax = ALLOC(2*sizeof(double)); if (!TI.ybmax) eX(301);
BodyHmax = 0;
}
if (!TI.xb) {
TI.xb = ALLOC(TI.nb*sizeof(double)); if (!TI.xb) eX(301);
}
if (!TI.yb) {
TI.yb = ALLOC(TI.nb*sizeof(double)); if (!TI.yb) eX(301);
}
if (!TI.ab) {
TI.ab = ALLOC(TI.nb*sizeof(double)); if (!TI.ab) eX(301);
}
if (!TI.bb) {
TI.bb = ALLOC(TI.nb*sizeof(double)); if (!TI.bb) eX(301);
}
if (!TI.cb) {
TI.cb = ALLOC(TI.nb*sizeof(double)); if (!TI.cb) eX(301);
}
if (!TI.wb) {
TI.wb = ALLOC(TI.nb*sizeof(double)); if (!TI.wb) eX(301);
}
for (n=0; n
if (fabs(TI.yb[n]) > TIP_MAXLENGTH) { strcpy(s, "yb"); eX(240); }
if (TI.ab[n] < 0 ) {
vMsg(_invalid_ab_$_, n+1);
return -1;
}
if (TI.bb[n] < 0 && TI.ab[n] != 0) {
vMsg(_improper_ab_$_, n+1);
return -1;
}
if (TI.cb[n] < 0) {
vMsg(_invalid_cb_$_, n+1);
return -1;
}
co = cos(TI.wb[n]/RADIAN); //-2004-12-14
si = sin(TI.wb[n]/RADIAN); //-2004-12-14
if (TI.bb[n] > 0) {
x = TI.xb[n] + 0.5*(TI.ab[n]*co - TI.bb[n]*si);
y = TI.yb[n] + 0.5*(TI.bb[n]*co + TI.ab[n]*si);
z = 0.5*sqrt(TI.ab[n]*TI.ab[n] + TI.bb[n]*TI.bb[n]);
}
else {
x = TI.xb[n];
y = TI.yb[n];
z = -0.5*TI.bb[n];
}
if (TI.cb[n] > BodyHmax) BodyHmax = TI.cb[n];
for (l=0; l<=1; l++) {
if (l == 0)
r = z + BodyRatio*TI.cb[n];
else
r = z + TurbRatio*TI.cb[n];
xmin = x - r;
xmax = x + r;
ymin = y - r;
ymax = y + r;
if (n == 0) {
TI.xbmin[l] = xmin;
TI.xbmax[l] = xmax;
TI.ybmin[l] = ymin;
TI.ybmax[l] = ymax;
}
else {
if (xmin < TI.xbmin[l]) TI.xbmin[l]= xmin;
if (xmax > TI.xbmax[l]) TI.xbmax[l] = xmax;
if (ymin < TI.ybmin[l]) TI.ybmin[l] = ymin;
if (ymax > TI.ybmax[l]) TI.ybmax[l] = ymax;
}
}
}
memset(&BM, 0, sizeof(ARYDSC));
if (strlen(TI.bf) > 0) {
TI.nb = -1;
if (TutMakeName(name, Path, TI.bf) < 0) eX(10);
strcpy(TI.bf, name); //-2008-01-25
rc = DmnRead(name, &usrhdr, &syshdr, &BM); if (rc != 1) eX(320);
if (BM.numdm != 2 || BM.elmsz != sizeof(int)) eX(321);
if (DmnFrmTab->dt != inDAT) eX(327);
rc = DmnGetDouble(usrhdr.s, "dz", "%lf", &BMdz, 1);
if (rc != 1 || BMdz < 1) eX(322);
rc = DmnGetDouble(usrhdr.s, "x0|xmin", "%lf", &BMx0, 1);
if (rc != 1) eX(323);
rc = DmnGetDouble(usrhdr.s, "y0|ymin", "%lf", &BMy0, 1);
if (rc != 1) eX(324);
rc = DmnGetDouble(usrhdr.s, "dd|delta|delt", "%lf", &BMdd, 1);
if (rc != 1 || BMdz < 1) eX(325);
if (fabs(BMx0) > TIP_MAXLENGTH || fabs(BMy0) > TIP_MAXLENGTH) eX(326);
n = 0;
for (i=BM.bound[0].low; i<=BM.bound[0].hgh; i++)
for (j=BM.bound[1].low; j<=BM.bound[1].hgh; j++) {
k = *(int *)AryPtr(&BM, i, j);
if (k == 0) continue;
x = BMx0 + (i-BM.bound[0].low+0.5)*BMdd;
y = BMy0 + (j-BM.bound[1].low+0.5)*BMdd;
z = k * BMdz;
if (z > BodyHmax) BodyHmax = z;
for (l=0; l<=1; l++) {
r = (l==0) ? BMdd/2 + BodyRatio*z : BMdd/2 + TurbRatio*z;
xmin = x - r;
xmax = x + r;
ymin = y - r;
ymax = y + r;
if (n == 0) {
TI.xbmin[l] = xmin;
TI.xbmax[l] = xmax;
TI.ybmin[l] = ymin;
TI.ybmax[l] = ymax;
}
else {
if (xmin < TI.xbmin[l]) TI.xbmin[l] = xmin;
if (xmax > TI.xbmax[l]) TI.xbmax[l] = xmax;
if (ymin < TI.ybmin[l]) TI.ybmin[l] = ymin;
if (ymax > TI.ybmax[l]) TI.ybmax[l] = ymax;
}
}
n++;
}
TI.nb = -n;
}
if (TI.nb) {
vMsg(_maximum_height_$_, BodyHmax);
if (BodyHmax == 0)
TI.nb = 0;
else {
TalMode |= TIP_BODIES;
TalMode |= TIP_NESTING;
// checkBodiesAndSources(); deprecated for TA Luft 2021 -2021-07-03
if (TI.qb>1 || TI.qb<-3) {
vMsg(_invalid_qb_);
return -1;
}
BodyDd = BodyDda[3+TI.qb];
BodyDz = BodyDza[3+TI.qb];
}
}
if (strstr(TI.os, "-NESTING"))
TalMode &= ~TIP_NESTING;
else if (strstr(TI.os, "NESTING"))
TalMode |= TIP_NESTING;
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//
// check and/or define grid
//
if (TI.nn > 0) { //-2001-10-24
for (n=0; n
if ((TI.y0) && (fabs(TI.y0[n])>TIP_MAXLENGTH)) { strcpy(s, "y0"); eX(240); }
}
checkGrid(); eG(213);
if (*TI.gh) check_surface = 1;
if (!TI.nz) {
TI.nz = ALLOC(TI.nn*sizeof(int)); if (!TI.nz) eX(234);
}
}
else {
make_grid = 1;
dd = TI.hq[0] + 0.5*TI.cq[0]; //-2001-10-18
for (n=1; n
if (dd > dh) dd = dh;
}
if (BESMAX) { //-2024-01-17
dd = floor(0.5*dd);
if (dd < 0.5*DdMin)
dd = 0.5*DdMin;
}
else {
dd = floor(dd);
if (dd < DdMin)
dd = DdMin;
}
xmin = TI.xm[0]; //-2002-07-13
xmax = TI.xm[0];
ymin = TI.ym[0];
ymax = TI.ym[0];
for (n=0; n
r = RadRatio*TI.hq[n]; //-2002-07-13
if (r < RadMin) r = RadMin; //-2002-07-13
x = TI.xm[n] - r;
if (x < xmin) xmin = x;
x = TI.xm[n] + r;
if (x > xmax) xmax = x;
y = TI.ym[n] - r;
if (y < ymin) ymin = y;
y = TI.ym[n] + r;
if (y > ymax) ymax = y;
}
if (!(TalMode & TIP_NESTING) && (TalMode & TIP_BODIES)) {
dd = BodyDd;
if (TI.xbmin[1] < xmin) xmin = TI.xbmin[1];
if (TI.xbmax[1] > xmax) xmax = TI.xbmax[1];
if (TI.ybmin[1] < ymin) ymin = TI.ybmin[1];
if (TI.ybmax[1] > ymax) ymax = TI.ybmax[1];
}
xmin = dd*floor(xmin/dd+0.001);
xmax = dd*ceil(xmax/dd-0.001);
ymin = dd*floor(ymin/dd+0.001);
ymax = dd*ceil(ymax/dd-0.001);
if (BESMAX && TI.nq == 1) { //-2024-01-17
// source in centre of grid cell
xmin -= 0.5*dd;
xmax += 0.5*dd;
ymin -= 0.5*dd;
ymax += 0.5*dd;
}
gd[0][0] = dd;
gd[0][1] = xmin;
gd[0][2] = xmax;
gd[0][3] = ymin;
gd[0][4] = ymax;
if (TalMode & TIP_NESTING) {
TI.nn = getNesting(TI.nq, TI.xm, TI.ym, TI.hq, TI.aq, TI.bq, TI.cq,
TI.nb, TI.xbmin, TI.xbmax, TI.ybmin, TI.ybmax,
BodyDd, gd);
}
else TI.nn = 1;
TI.dd = ALLOC(TI.nn*sizeof(double)); if (!TI.dd) eX(220);
TI.x0 = ALLOC(TI.nn*sizeof(double)); if (!TI.x0) eX(221);
TI.x1 = ALLOC(TI.nn*sizeof(double)); if (!TI.x1) eX(222);
TI.x2 = ALLOC(TI.nn*sizeof(double)); if (!TI.x2) eX(223);
TI.x3 = ALLOC(TI.nn*sizeof(double)); if (!TI.x3) eX(224);
TI.y0 = ALLOC(TI.nn*sizeof(double)); if (!TI.y0) eX(225);
TI.y1 = ALLOC(TI.nn*sizeof(double)); if (!TI.y1) eX(226);
TI.y2 = ALLOC(TI.nn*sizeof(double)); if (!TI.y2) eX(227);
TI.y3 = ALLOC(TI.nn*sizeof(double)); if (!TI.y3) eX(228);
TI.gl = ALLOC(TI.nn*sizeof(int)); if (!TI.gl) eX(229);
TI.gi = ALLOC(TI.nn*sizeof(int)); if (!TI.gi) eX(230);
TI.nx = ALLOC(TI.nn*sizeof(int)); if (!TI.nx) eX(231);
TI.ny = ALLOC(TI.nn*sizeof(int)); if (!TI.ny) eX(232);
TI.nz = ALLOC(TI.nn*sizeof(int)); if (!TI.nz) eX(233);
for (n=0; n
TI.x0[n] = gd[n][1];
TI.x1[n] = gd[n][1];
TI.x2[n] = gd[n][2];
TI.x3[n] = gd[n][2];
TI.y0[n] = gd[n][3];
TI.y1[n] = gd[n][3];
TI.y2[n] = gd[n][4];
TI.y3[n] = gd[n][4];
TI.nx[n] = (int)((TI.x3[n]-TI.x0[n])/TI.dd[n] + 0.5);
TI.ny[n] = (int)((TI.y3[n]-TI.y0[n])/TI.dd[n] + 0.5);
TI.nz[n] = 0;
TI.gl[n] = TI.nn - n - (TI.nn==1);
TI.gi[n] = (TI.nn > 1);
}
if (*TI.gh) check_surface = 1; //-2003-10-12
}
TipTrbExt = (TalMode & TIP_NESTING) && (TalMode & TIP_BODIES);
if (TipTrbExt
&& TI.nn > 1
&& TI.x0[0] <= TI.xbmin[1] //-2005-03-16
&& TI.x3[0] >= TI.xbmax[1] //-2005-03-16
&& TI.y0[0] <= TI.ybmin[1] //-2005-03-16
&& TI.y3[0] >= TI.ybmax[1]) TipTrbExt = 0; //-2005-03-16
if (CHECK) for (n=0; n
n, TI.gl[n], TI.gi[n], TI.dd[n], TI.x0[n], TI.x3[n], TI.nx[n], TI.y0[n], TI.y3[n], TI.ny[n]);
//
// set vertical grid //-2004-07
if (TI.hh && NOSTANDARD) { //-2002-08-02
if (TI.nhh < 2) {
vMsg(_no_vertical_grid_);
return -1;
}
if (TI.hh[0] != 0) {
vMsg(_invalid_footpoint_);
return -1;
}
for (k=1; k
vMsg(_invalid_vertical_grid_);
return -1;
}
}
}
else {
if (TI.hh) { //-2002-08-02
FREE(TI.hh);
vMsg(_hh_ignored_);
}
if (!TI.nb) {
if (VDI37831) {
TI.nhh = sizeof(Hh37831)/sizeof(double);
TI.hh = ALLOC(sizeof(Hh37831)); if (!TI.hh) eX(20);
memcpy(TI.hh, Hh37831, sizeof(Hh37831));
}
else {
TI.nhh = sizeof(Hh)/sizeof(double);
TI.hh = ALLOC(sizeof(Hh)); if (!TI.hh) eX(20);
memcpy(TI.hh, Hh, sizeof(Hh));
}
}
else {
double *hused = (VDI37831) ? Hh37831 : Hh;
n = (VDI37831) ? sizeof(Hh37831)/sizeof(double) : sizeof(Hh)/sizeof(double);
// (almost) equal intervals in the lower part
hh[0] = 0;
hh[1] = (VDI37831) ? 2 : 3;
k = 1;
z = BodyDz * (int)(2.0*BodyHmax/BodyDz + 0.5);
if (z < FinestGridZmin) //-2019-01-04
z = FinestGridZmin;
while (hh[k]
hh[k] = hh[k-1]+BodyDz;
}
// check for next valid height of the default vertical grid
for (i=0; i
if (i >= n-1) eX(400);
if (hused[i]-hh[k] < BodyDz) {
++k;
++i;
hh[k] = hh[k-1]+BodyDz;
}
// fill gap from equal spacing to default vertical grid
dz = floor(BodyDz*1.5);
while (hused[i]-(hh[k]+dz) >= dz && k<99) {
++k;
hh[k] = hh[k-1]+dz;
dz = floor(dz*1.5);
}
// continue with default vertical grid
k++;
while (i
++k;
++i;
}
if (i!=n) eX(401);
TI.nhh = k;
TI.hh = ALLOC(k*sizeof(double)); if (!TI.hh) eX(20);
*s = 0;
for (i=0; i
sprintf(s, "%s %6.1f", s, hh[i]);
if ((i+1)%10 == 0) strcat(s, "\n");
}
if (i%10 != 0) strcat(s, "\n");
fprintf(MsgFile, _vertical_grid_$_, s);
fprintf(MsgFile, "----------------------------------------------------------------------\n");
}
}
// set vertical grid extent
TI.nzmax = TI.nhh - 1;
if (!TI.nb || TI.nn == 1) {
for (n=0; n
}
else {
if (TI.nz[0] <= 0) {
make_nz = 1; //-2005-03-16
for (i=0; i
if (i >= TI.nhh) eX(404);
TI.nz[0] = i;
}
for (i=0; i
TI.nz[i] = TI.nzmax;
}
// check
if (TI.nz[1] < TI.nzmax) eX(408); //-2006-02-11
for (i=0; i
if (i > 0 && TI.nz[i] < TI.nz[i-1]) eX(406);
if (i == 0 && TI.hh[TI.nz[i]] < 2*BodyHmax) eX(407);
}
// set user defined nzmax
TI.nzmax = 0;
for (i=0; i
TI.nzmax = TI.nz[i];
}
if (TI.kp > TI.nzmax)
TI.kp = TI.nzmax;
if (make_grid || make_nz) { //-2005-03-16
fprintf(MsgFile, "%s", _computational_grid_);
fprintf(MsgFile, "dd");
for (n=0; n
fprintf(MsgFile, "x0");
for (n=0; n
fprintf(MsgFile, "nx");
for (n=0; n
fprintf(MsgFile, "y0");
for (n=0; n
fprintf(MsgFile, "ny");
for (n=0; n
fprintf(MsgFile, "nz");
for (n=0; n
fprintf(MsgFile, "--");
for (n=0; n
checkGrid(); eG(313);
}
// end set vertical grid
//
// check anemometer position -2002-01-12, 2005-03-16 moved to here
//
if (TI.xa==HUGE_VAL || TI.ya==HUGE_VAL) {
if (*TI.gh || TI.nb) { eX(214); }
else {
TI.xa = TI.x0[0];
TI.ya = TI.y0[0];
}
}
else {
if (fabs(TI.xa) > TIP_MAXLENGTH) { strcpy(s, "xa"); eX(240); }
if (fabs(TI.ya) > TIP_MAXLENGTH) { strcpy(s, "ya"); eX(240); }
}
for (n=0; n
&& TI.ya>=TI.y0[n] && TI.ya<=TI.y3[n]) break;
}
if (n >= TI.nn) eX(215);
//
if (*TI.gh) { // complex terrain: all surfaces defined?
if (check_surface && !make_surface) {
for (n=0; n
if (!k) {
if (n == 0) make_surface = 1;
else if (!make_surface) eX(212);
}
}
}
if (make_surface) {
for (n=0; n
}
}
else {
if (TI.nn == 1)
vMsg(_use_existing_zg_);
else if (TI.nn > 1)
vMsg(_use_existing_zgs_);
}
}
if (isUndefined(TI.mh)) TI.mh = 0;
for (n=0; n
for (i=0; i
vMsg(_source_outside_$_, n+1);
return -1;
}
}
if (isUndefined(TI.z0)) {
TI.z0 = TipCorine(TI.nq, TI.xm, TI.ym, TI.hq, TI.cq);
if (TI.z0 <= 0) {
vMsg(_no_z0_reason_);
if (TI.z0 == RGLE_FILE)
vMsg(_z0_file_not_found_$_, RglFile);
else if (TI.z0 == RGLE_XMIN)
vMsg(_z0_no_xmin_$_, RglFile);
else if (TI.z0 == RGLE_YMIN)
vMsg(_z0_no_ymin_$_, RglFile);
else if (TI.z0 == RGLE_DELT)
vMsg(_z0_no_delt_$_, RglFile);
else if (TI.z0 == RGLE_GGCS)
vMsg(_z0_no_ggcs_$_, RglFile);
else if (TI.z0 == RGLE_DIMS)
vMsg(_z0_not_2d_$_, RglFile);
else if (TI.z0 == RGLE_ILOW)
vMsg(_z0_invalid_low_bound_j_$_, RglFile);
else if (TI.z0 == RGLE_JIND)
vMsg(_z0_invalid_bounds_i_$_, RglFile);
else if (TI.z0 == RGLE_SEQN)
vMsg(_z0_no_sequ_$_, RglFile);
else if (TI.z0 == RGLE_SEQU)
vMsg(_z0_invalid_sequ_$_, RglFile);
else if (TI.z0 == RGLE_CSNE)
vMsg(_z0_improper_ggcs_$$$_, RglFile, RglGGCS, TI.ggcs);
else if (TI.z0 == RGLE_GKGK)
vMsg(_z0_invalid_source_$$$_, RglX, RglY, RglMrd);
else if (TI.z0 == RGLE_POUT) {
vMsg(_z0_source_outside_$$$_, RglX, RglY, RglFile);
vMsg(_z0_allowed_range_$$$$_, RglXmin, RglXmax, RglYmin, RglYmax);
}
else if (TI.z0 == RGLE_SECT)
vMsg(_z0_error_$_, RglFile);
else
vMsg(_z0_unspecified_error_);
vMsg("");
return -1;
}
if (MsgFile)
fprintf(MsgFile, _z0_average_z0_$_, TI.z0);
else
vMsg(_z0_average_z0_$_, TI.z0);
}
else round_z0 = !NOSTANDARD;
iZ0 = TipZ0index(TI.z0); //-2001-06-27
z0 = z0TAL[iZ0]; //
if (z0!=TI.z0 && round_z0) {
vMsg(_z0_rounded_$_, z0); //
TI.z0 = z0; //
} //
if (isUndefined(TI.d0)) TI.d0 = 6*TI.z0;
else if (TI.d0 < 0) {
vMsg(_invalid_d0_);
return -1;
}
//
// check definition of odor emissions //-2008-03-10
//
emission = 0;
if (cODOR >= 0) {
for (i=0; i
emission++; // rated odor component
}
if (emission > 0) {
double* oe = TI.cmp[cODOR];
if (oe != NULL) {
vMsg(_source_strength_ignored_);
}
else {
oe = ALLOC(TI.nq*sizeof(double));
TI.cmp[cODOR] = oe;
}
for (n=0; n
TalMode |= TIP_ODORMOD;
}
}
//
// check variable parameters
//
AryFree(&TipVar);
nVarParm = 0;
nUsrParm = 0;
emission = 0;
for (check=1; check>=0; check--) { //-2005-09-23
int nv = 0; //-2006-12-13
checkvar(check, TI.vq, TI.nq, "vq", &nv); //-2006-12-13
checkvar(check, TI.tq, TI.nq, "tq", &nv); //-2006-12-13
checkvar(check, TI.zq, TI.nq, "zq", &nv); //-2018-10-04
checkvar(check, TI.rq, TI.nq, "rq", &nv); //-2006-12-13
checkvar(check, TI.sq, TI.nq, "sq", &nv); //-2018-10-04
checkvar(check, TI.lq, TI.nq, "lq", &nv); //-2011-11-23
checkvar(check, TI.ts, TI.nq, "ts", &nv); //-2018-10-04
checkvar(check, TI.iq, TI.nq, "iq", &nv); //-2015-12-01
for (n=0; n
k = checkvar(check, TI.cmp[n], TI.nq, name, &nv); //-2006-12-13
if (check && k) {
emission++;
}
}
if (check) {
if (!emission) {
vMsg(_no_emissions_);
return -1;
}
nUsrParm = nv;
if (isUndefined(TI.hm))
nv++;
if (isUndefined(TI.ri))
nv++;
nVarParm = nv; //-2006-12-13
AryCreate(&TipVar, sizeof(TIPVAR), 1, 0, nVarParm-1); eG(21);
}
else { // optional parameters -2011-12-08
if (isUndefined(TI.hm)) {
ptv = AryPtrX(&TipVar, nv);
strcpy(ptv->name, "hm");
ptv->p = &TI.hm;
nv++;
}
if (isUndefined(TI.ri)) {
ptv = AryPtrX(&TipVar, nv);
strcpy(ptv->name, "ri");
ptv->p = &TI.ri;
nv++;
}
}
}
if (nUsrParm > 0) TalMode |= TIP_VARIABLE;
//
// check monitor points
//
if (TI.np > 0) {
if (TI.np > TI.npmax) eX(241); //-2006-10-17
if (TI.xp && TI.yp) {
for (i=0; i
if (n >= TI.nn) {
vMsg(_monitor_outside_$_, i+1);
return -1; //-2002-02-26
}
}
}
else {
vMsg(_missing_xy_);
return -1;
}
if (!TI.hp) {
TI.hp = ALLOC(TI.np*sizeof(double));
for (i=0; i
// check maximum height of monitor points (for nzdos) 2001-08-03
//
kpmax = 1;
for (i=0; i
for (k=0; k<=TI.nzmax; k++) if (h < TI.hh[k]) break;
if (k > TI.nzmax) {
vMsg(_monitor_above_$_, i+1);
return -1;
}
if (k > kpmax) kpmax = k;
}
if (TI.kp < kpmax) TI.kp = kpmax;
}
//
// read and check time series
//
if (TipFrmTab) FREE(TipFrmTab);
TipFrmTab = NULL;
strcpy(name, path);
strcat(name, "/");
strcat(name, CfgSeriesString); //-2008-07-28
strcat(name, ".dmna");
if (write_z) {
if (!*TI.az) {
vMsg(_missing_akterm_);
return -1;
}
TalMode |= TIP_SERIES; //-2002-01-02
}
else {
series_exists = TutFileExists(name);
if (series_exists || *TI.az) TalMode |= TIP_SERIES;
else
if (*TI.as) TalMode |= TIP_STAT;
else {
vMsg(_missing_meteo_);
return -1;
}
if (TalMode & TIP_VARIABLE) {
if ((TalMode & TIP_SERIES) && !series_exists) {
vMsg(_missing_series_$_, name);
return -1;
}
if (TalMode & TIP_STAT) {
char fname[256];
int n, k=0, quiet, verbose;
TIPVAR *ptv;
ARYDSC *pa;
for (n=0; n
sprintf(fname, "%s/%s.dmna", path, ptv->name);
if (!TutFileExists(fname)) {
vMsg(_missing_table_$$_, ptv->name, fname);
k++;
}
}
if (k)
return -1;
for (n=0; n
sprintf(fname, "%s/%s.dmna", path, ptv->name);
quiet = MsgQuiet; MsgQuiet = 1;
verbose = MsgVerbose; MsgVerbose = 1;
pa = &(ptv->dsc);
DmnRead(fname, NULL, NULL, pa);
MsgQuiet = quiet;
MsgVerbose = verbose;
if (MsgCode < 0) {
vMsg(_cant_read_file_$_, fname);
vMsg(_see_log_);
MsgCode = 0;
return -2;
}
if (pa->numdm!=2 || pa->elmsz!=4
|| pa->bound[0].low!=1 || pa->bound[0].hgh!=6
|| pa->bound[1].low!=1 || pa->bound[1].hgh!=9) {
vMsg(_invalid_structure_$_, fname);
return -2;
}
} // for n
}
}
}
if (TalMode & TIP_SERIES) { // ------------ work with time series --------
TatArgument(path);
/* TatArgument("-u0.7"); */ // 2013-01-11 (does not work with german locale)
sprintf(s, "-f%s", TI.az);
TatArgument(s);
sprintf(s, "-z%1.3lf,%1.3lf", TI.z0, TI.d0);
TatArgument(s);
sprintf(s, "-a%1.0lf,%1.0lf,%1.1lf", TI.xa, TI.ya, TI.ha); //-2002-04-16
TatArgument(s);
TatArgument(NULL);
}
//if (!series_exists && NOTALUFT) eX(130); //-2020-10-14
if (series_exists) { // --------- time series provided by user -------------
int quiet, verbose, ostd;
double t1, t2;
int uses_hm = 0;
int uses_ri = 0;
int off_hm, off_ri;
char *p;
//
quiet = MsgQuiet;
MsgQuiet = 1;
verbose = MsgVerbose;
MsgVerbose = 1;
DmnRead(name, &TxtUser, &TxtSystem, &TIPary);
MsgQuiet = quiet;
MsgVerbose = verbose;
if (MsgCode < 0) {
vMsg(_cant_read_time_series_$_, name);
vMsg(_see_log_);
MsgCode = 0;
return -2;
}
vMsg(_using_series_$_, name);
TipLogCheck("SERIES", TutMakeCrc(TIPary.start, TIPary.ttlsz)); //-2011-12-07
TipFrmTab = DmnFrmTab; if (!TipFrmTab) eX(26);
DmnFrmTab = NULL;
if (TIPary.numdm != 1) eX(105);
i1 = TIPary.bound[0].low;
i2 = TIPary.bound[0].hgh;
if (i2-i1+1 > MNT_NUMVAL) {
vMsg(_series_too_long_$_, MNT_NUMVAL);
return -3;
}
ostd = 0;
//
// mandatory parameters
//
strcpy(elnm, "te");
pfr = DmnFrmPointer(TipFrmTab, elnm); if (!pfr) eX(101);
if (pfr->offset != ostd) eX(111);
if (pfr->dt != ltDAT) eX(121);
ostd += sizeof(double);
strcpy(elnm, "ra");
pfr = DmnFrmPointer(TipFrmTab, elnm); if (!pfr) eX(102);
if (pfr->offset != ostd) eX(112);
if (pfr->dt != flDAT) eX(122);
ostd += sizeof(float);
strcpy(elnm, "ua");
pfr = DmnFrmPointer(TipFrmTab, elnm); if (!pfr) eX(103);
if (pfr->offset != ostd) eX(113);
if (pfr->dt != flDAT) eX(123); //-2001-06-27
ostd += sizeof(float);
strcpy(elnm, "lm");
pfr = DmnFrmPointer(TipFrmTab, elnm); if (!pfr) eX(104);
if (pfr->offset != ostd) eX(114);
if (pfr->dt != flDAT) eX(124);
ostd += sizeof(float);
//
// optional parameters -2011-12-02
//
off_hm = -1;
strcpy(elnm, "hm");
pfr = DmnFrmPointer(TipFrmTab, elnm);
if (pfr) {
if (pfr->dt != flDAT) eX(116);
off_hm = pfr->offset;
}
off_ri = -1;
strcpy(elnm, "ri");
pfr = DmnFrmPointer(TipFrmTab, elnm);
if (pfr) {
if (pfr->dt != flDAT) eX(116);
off_ri = pfr->offset;
}
if (off_hm > 0 || off_ri > 0) {
for (i=i1; i<=i2; i++) {
p = AryPtrX(&TIPary, i);
if (off_hm > 0) {
float hm = *(float*)(p + off_hm);
if (hm > 0)
uses_hm = 1;
}
if (off_ri > 0) {
float ri = *(float*)(p + off_ri);
if (ri >= 0)
uses_ri = 1;
}
} // for i
}
// -2011-12-02
if (isUndefined(TI.hm)) { // values expected
if (!uses_hm) eX(250)
else
TalMode |= TIP_HM_USED;
}
//else if (uses_hm)
// vMsg(_HM_in_$_ignored_, "\"time series\"");
// -2011-12-02
if (isUndefined(TI.ri)) { // values expected
if (!uses_ri) eX(251)
else
TalMode |= TIP_RI_USED;
}
else if (uses_ri && !(PrmMode & TIP_TALDIA)) //-2021-10-11
vMsg(_RI_in_$_ignored_, "DMNA");
//
// variable parameters
//
for (i=0; i
strcpy(elnm, ptv->name);
pfr = DmnFrmPointer(TipFrmTab, ptv->name); if (!pfr) eX(106);
if (pfr->dt != flDAT) eX(116);
ptv->o = pfr->offset;
ptv->i = (pfr->offset - ostd)/sizeof(float); //-2011-12-19
}
//
// anemometer height vector
if (TI.ha <= 0) {
float havec[9];
i = DmnGetFloat(TxtUser.s, "ha", "%f", havec, 9);
if (i == 9) {
TI.ha = havec[iZ0];
vMsg(_using_ha_$_, TI.ha);
}
}
//
// ignore az/as
if (*TI.az) vMsg(_ignoring_az_$_, TI.az);
*TI.az = 0;
if (*TI.as) vMsg(_ignoring_as_$_, TI.as); //-2001-12-14
*TI.as = 0;
//
// for standard TA Luft application check that
// time intervals in series are constant
if (!NOTALUFT) { //-2020-10-14
t1 = *(double*) AryPtrX(&TIPary, i1);
for (i=i1+1; i<=i2; i++) { //-2001-12-14
t2 = *(double*) AryPtrX(&TIPary, i);
n = (int)(MsgDateSeconds(t1, t2) + 0.5);
if (n != TI.in) eX(120); //-2007-02-03
t1 = t2;
}
}
}
else if (*TI.az) { // ------------------ AKTerm provided by user ------------------
int nn, nt, elmsz, akt;
akt = TatReadAKTerm();
if (akt < 0)
return -1;
nt = AKTary.bound[0].hgh;
if (nt > MNT_NUMVAL) {
vMsg(_akterm_too_long_$_, MNT_NUMVAL);
return -3;
}
// -2011-12-02
if (isUndefined(TI.hm)) { // values expected
if (0 == (akt & 0x01)) eX(260)
else
TalMode |= TIP_HM_USED;
}
//else if (akt & 0x01)
// vMsg(_HM_in_$_ignored_, "\"AKTerm\"");
// -2011-12-02
if (isUndefined(TI.ri)) { // values expected
if (0 == (akt & 0x02)) { //-2018-10-29
AKTREC *pdst;
PRCREC *psrc;
strcpy(prcname, path);
strcat(prcname, "/");
strcat(prcname, CfgPrecString);
strcat(prcname, ".dmna");
if (!TutFileExists(prcname)) eX(261);
//
DmnRead(prcname, &TxtUser, &TxtSystem, &PRCary); eG(262);
vMsg(_precfile_read_$$$_, prcname, PRCary.bound[0].low, PRCary.bound[0].hgh);
if (nt != PRCary.bound[0].hgh) eX(263);
for (i=1; i<=nt; i++) {
pdst = AryPtrX(&AKTary, i);
psrc = AryPtrX(&PRCary, i);
//
// In AKT record pdst, the C representation of time as double
// is interpreted as GMT+01:00. On the other hand, the DMNA routines
// transform time correctly to default GMT+00:00. Therefore one hour
// must be added to align DMNA times to AKT times.
//
// Note that tmzn entries in niederschlag.dmna of type "UTC" are not
// recognized, interpreted as GMT+00:00 and cause an error.
// The tmzn entry should be "GMT+01:00".
//
psrc->t += 1./24.; //-2019-10-18
//
if (fabs(psrc->t-pdst->t) > 1.e-6) eX(264);
pdst->fPr = psrc->fPr;
}
}
TalMode |= TIP_RI_USED;
}
else if ( (akt & 0x02) && !(PrmMode & TIP_TALDIA)) //-2021-10-11
vMsg(_RI_in_$_ignored_, "AKTerm");
//
nn = TatCheckZtr();
if (TI.ha <= 0) { //-2002-04-16
TI.ha = TatGetHa(iZ0);
vMsg(_using_ha_$_, TI.ha);
}
vMsg(_availability_$_, 100 - (nn*100.0)/nt);
{ // extend the transformed AKTerm
//bp int len = 40; no VLA for vs-compiler
int len = 40;
char *_frm;
char **forms;
char s[40];//bp
char form[40];//bp //-2011-12-08
char form_hm[40];//bp //-2011-12-08
char form_ri[40];//bp //-2011-12-08
char *form_iq = "%3.0f"; //-2015-12-01
AKTREC *psrc;
TMSREC *pdst;
int nf, ihm=-1, iri=-1; //-2011-11-22
int l4 = AKTary.elmsz - sizeof(int) - sizeof(float); //-2011-12-08
forms = ALLOC(6*sizeof(char*)); //-2011-12-08
elmsz = l4 + nVarParm*sizeof(float); //-2011-12-08
AryCreate(&TIPary, elmsz, 1, 1, nt); eG(22);
nf = DmnGetString(AKTheader, "form", forms, 6); //-2011-11-22
if (nf != 6) eX(23);
n = 4;
for (i=0; i
n += 22*nVarParm;
_frm = ALLOC(n); if (!_frm) eX(24); //-2014-06-26
for (i=0; i
FREE(forms[i]); //-2011-12-08
if (!strncmp(form, "hm%", 3)) {
strcpy(form_hm, form);
continue;
}
if (!strncmp(form, "ri%", 3)) {
strcpy(form_ri, form);
continue;
}
strcat(_frm, " \"");
if (!strncmp(form, "kl%", 3))
strcat(_frm, "lm%7.1f");
else
strcat(_frm, form);
strcat(_frm, "\"");
}
FREE(forms);
for (i=0; i
strcpy(s, " \"");
if (!strcmp(ptv->name, "hm")) { //-2011-12-08
strcat(s, form_hm);
ihm = i;
}
else if (!strcmp(ptv->name, "ri")) { //-2011-12-08
strcat(s, form_ri);
iri = i;
}
else if (!strcmp(ptv->name+2, ".iq")) { //-2015-12-01
strcat(s, ptv->name);
strcat(s, form_iq);
}
else {
strcat(s, ptv->name);
strcat(s, "%10.3e");
}
strcat(s, "\"");
strcat(_frm, s);
ptv->i = i;
ptv->o = l4 + i*sizeof(float);
}
if (CHECK) vMsg("New format:%s<<<\n", _frm);
TipFrmTab = DmnAnaForm(_frm, &TIPary.elmsz); if (!TipFrmTab) eX(28);
TxtCpy(&TxtSystem, "form "); //-2014-01-28
TxtCat(&TxtSystem, _frm);
TxtCat(&TxtSystem, "\n");
FREE(_frm);
for (i=1; i<=nt; i++) {
pdst = AryPtrX(&TIPary, i);
psrc = AryPtrX(&AKTary, i);
pdst->t = psrc->t;
pdst->fRa = psrc->fRa;
pdst->fUa = psrc->fUa;
k = psrc->iKl - 1;
pdst->fLm = (k<0 || k>5) ? 0 : lmTAL[k][iZ0]; //-2001-07-12
if (ihm >= 0)
pdst->fPrm[ihm] = psrc->fHm; //-2011-12-08
if (iri >= 0)
pdst->fPrm[iri] = psrc->fPr; //-2011-12-08
}
AryFree(&AKTary);
}
if (write_z) { // write generated time series
char s[1024], t[512]; //-2008-10-17
sprintf(t, "locl \"%s\"\n", TI.lc); //-2008-10-17 -2014-01-28
TxtCat(&TxtSystem, t); //-2008-10-17
strcpy(name, path);
strcat(name, "/");
strcat(name, CfgSeriesString);
TxtCat(&TxtSystem, "mode \"text\"\n"); //-2014-01-28
strcpy(s, "ha");
for (i=0; i
strcat(s, t);
}
strcat(s, "\n");
TxtCat(&TxtSystem, s);
sprintf(s, "z0 %3.2lf\n", TI.z0); TxtCat(&TxtSystem, s); //-2002-06-19 -2014-01-28
sprintf(s, "d0 %3.2lf\n", TI.d0); TxtCat(&TxtSystem, s); //-2014-01-28
sprintf(s, "artp \"ZA\"\n"); TxtCat(&TxtSystem, s); //-2008-12-04 -2014-01-28
DmnWrite(name, TxtSystem.s, &TIPary); eG(100);
vMsg(_series_written_$_, name);
TxtClr(&TxtSystem);
}
}
if (TI.ha <= 0) { //-2002-04-16
TI.ha = 10 + TI.d0;
vMsg(_using_ha_$_, TI.ha);
}
if (TalMode & TIP_STAT) { //--------------- AKS provided by user -----------
if (TI.ri != -HUGE_VAL && TI.ri != 0.) eX(265); //-2018-10-29
TalAKS(Path);
//
if (BESMAX) { //-2024-01-17
if (TI.nq==1 && !TI.nb && !TI.gh[0]) {
fprintf(MsgFile, _besmax_1dir_);
sprintf(s, "-S"); // only one direction
TalAKS(s);
TI.qs -= 6;
}
else if (NOSTANDARD && strstr(TI.os, "NSUB5")) {
fprintf(MsgFile, _besmax_nsub5_);
sprintf(s, "-s%d", 5); // 5 subsectors at 2 deg
TalAKS(s);
}
else {
sprintf(s, "-s%d", 2); // 2 subsectors at 5 deg
TalAKS(s);
}
}
//
sprintf(s, "-f%s", TI.as);
TalAKS(s);
sprintf(s, "-z%1.3lf,%1.3lf", TI.z0, TI.d0);
TalAKS(s);
sprintf(s, "-a%1.0lf,%1.0lf,%1.1lf", TI.xa, TI.ya, TI.ha); //-2002-04-16
TalAKS(s);
if (cNO >= 0 && TI.cmp[cNO]) TalAKS("-n");
d = TasRead();
if (d > 0) { //-2011-12-20
TalMode |= TIP_RI_USED;
d = 0;
}
}
if (TalMode & TIP_SERIES) {
i1 = TIPary.bound[0].low;
i2 = TIPary.bound[0].hgh;
TI.t1 = *(double*) AryPtrX(&TIPary, i1);
TI.t2 = *(double*) AryPtrX(&TIPary, i2);
TI.t1 = MsgDateLastHour(TI.t1); //-2020-10-14
}
setlocale(LC_NUMERIC, locale); //-2008-10-17
return d;
eX_1: eX_2: eX_3: eX_4: eX_5: eX_6: eX_7: eX_8: eX_9: eX_10: eX_11: eX_12:
eX_13:
eX_20: eX_21: eX_22: eX_23: eX_24: eX_26: eX_28:
eX_220: eX_221: eX_222: eX_223: eX_224: eX_225: eX_226: eX_227: eX_228:
eX_229: eX_230: eX_231: eX_232: eX_233: eX_234:
eX_301:
eMSG(_internal_error_);
eX_100:
vMsg(_akterm_not_written_$_, name);
MsgCode = 0;
return -100;
eX_105:
eMSG(_invalid_structure_series_$_, name);
eX_101: eX_102: eX_103: eX_104:
vMsg(_missing_element_$_, elnm);
DmnPrnForm(TipFrmTab, name);
return MsgSource=ePGMs, MsgCode;
eX_111: eX_112: eX_113: eX_114:
vMsg(_wrong_position_$_, elnm);
DmnPrnForm(TipFrmTab, name);
return MsgSource=ePGMs, MsgCode;
eX_121: eX_122: eX_123: eX_124:
vMsg(_wrong_type_$_, elnm);
DmnPrnForm(TipFrmTab, name);
return MsgSource=ePGMs, MsgCode;
eX_106:
eMSG(_missing_parameter_$_, elnm);
eX_116:
eMSG(_float_expected_$_, elnm);
eX_120:
eMSG(_invalid_interval_$$_, i-i1+1, TI.in);
//eX_130:
// eMSG(_interval_requires_series_);
eX_210:
eMSG(_improper_profile_$_, n+1);
eX_211:
eMSG(_profile_not_created_$_, n+1);
eX_212:
eMSG(_incomplete_profiles_);
eX_213: eX_313:
eMSG(_error_grid_);
eX_214:
eMSG(_anemometer_required_);
eX_215:
eMSG(_anemometer_outside_);
eX_240:
eMSG(_no_absolute_value_$_, s);
eX_241:
eMSG(_too_many_points_);
eX_242:
eMSG(_invalid_lc_);
eX_250:
eMSG(_no_valid_HM_in_$_, "DMNA");
eX_251:
eMSG(_no_valid_RI_in_$_, "DMNA");
eX_260:
eMSG(_no_valid_HM_in_$_, "AKTerm");
eX_261: //-2018-10-29
eMSG(_no_prec_file_$_, prcname);
eX_262: //-2018-10-29
eMSG(_cant_read_prec_file_$_, prcname);
eX_263: //-2018-10-29
eMSG(_incomp_prec_series_size_);
eX_264: //-2018-10-29
eMSG(_incomp_prec_series_time_);
eX_265: //-2018-10-29
eMSG(_ri_not_with_aks_);
eX_300:
eMSG(_invalid_dmkp_);
eX_312:
eMSG(_duplicate_definition_);
eX_320:
eMSG(_no_raster_$_, TI.bf);
eX_321:
eMSG(_raster_dimension_);
eX_327:
eMSG(_raster_integer_);
eX_322:
eMSG(_raster_dz_);
eX_323: eX_324: eX_325: eX_326:
eMSG(_raster_x0_);
eX_400: eX_401:
eMSG(_vertical_grid_size_);
eX_404:
eMSG(_vertical_grid_low_);
eX_405:
eMSG(_invalid_nz_);
eX_406:
eMSG(_small_nz_);
eX_407:
eMSG(_finest_grid_low_);
eX_408:
eMSG(_coarse_grid_low_);
}
//================================================================== TipMain
//
int TipMain( char *s ) {
dP(TipMain);
char fname[512];
char buf[512]; //bp
FILE *f; //bp
TIPREC t; //bp
char sttname[32];
int n, pid;
static int create_lib=0;
if (!MsgFile) {
if (TipMsgFile) MsgFile = TipMsgFile;
MsgVerbose = 1;
MsgBreak = '\'';
}
if (CHECK) vMsg("TipMain(%s)", (s) ? s : "NULL");
if (s && *s) {
if (s[0] == '-')
switch (s[1]) {
case 'S': strcpy(Home, s+4); //bp
break; //bp
case 'H': strcpy(Home, s+2);
if (!*Home) strcpy(Home, ".");
break;
case 'l': create_lib = 1;
sscanf(s+2, "%d", &create_lib);
if (create_lib > 0) TalMode |= TIP_LIBRARY;
else TalMode &= ~TIP_LIBRARY;
break;
case 'M': sscanf(s+2, "%x", &PrmMode); //-2014-06-26
break;
case 'v': sscanf(s+2, "%d,%d", &StdDspLevel, &StdLogLevel); //-2006-10-20
break;
case 'w': Write_l = 1;
sscanf(s+2, "%d", &Write_l);
//if (Write_l) TalMode |= TIP_WRITE_L; -2023-07-17, not used
//else TalMode &= ~TIP_WRITE_L; -2023-07-17, not used
break;
case 'x': Xflags = 0; //-2008-08-08
sscanf(s+2, "%x", &Xflags);
break;
case 'z': Write_z = 1;
create_lib = -1; //-2005-03-18
sscanf(s+2, "%d", &Write_z);
//if (Write_z) TalMode |= TIP_WRITE_Z; -2023-07-17, not used
//else TalMode &= ~TIP_WRITE_Z; -2023-07-17, not used
break;
default: ;
}
else {
if (strlen(s) > 240) eX(20);
strcpy(Path, s);
MsgCheckPath(Path);
}
return 0;
}
// -2011-12-07
sprintf(fname, "%s/%s", Home, AUSTALx); //bp
TipLogCheck("AUSTAL", TutGetCrc(fname));
sprintf(fname, "%s/%s", Home, TALDIA);
TipLogCheck("TALDIA", TutGetCrc(fname));
//
sprintf(fname, "%s/%s", Path, "austal.txt"); //bp
f = fopen(fname, "rb"); //bp
while (fgets(buf, 512, f)) { //bp
parse(buf, &t); //bp
if (strcmp(t._name, "settingspath") == 0) //bp
{ //bp
strcpy(SettingsPath, t._tokens[0]); //bp
FREE(t._name); //bp
FREE(t._tokens); //bp
break; //bp
} //bp
} //bp
fclose(f); //bp
strcpy(sttname, "austal");
if (strlen(SettingsPath) == 0) //bp
sprintf(SettingsPath, "%s/%s.settings", Home, sttname); //bp
n = TutGetCrc(SettingsPath); //bp
TipLogCheck("SETTINGS", n);
sprintf(fname, "%08x", n);
if (strcmp(fname, SETTINGS_CRC))
{ //bp
strcpy(fname, SettingsPath); //bp
strtok (fname,"."); //bp
vMsg(_nostandard_settings_$_, fname); //bp
} //bp
//
n = SttRead(SettingsPath, sttname); //bp -2011-11-23 -2014-01-21
if (n < 0)
return -1;
//
n = TipInitialize();
if (n < 0) //-2024-01-17
return -1;
//
n = TipRead(Path);
if (n < 0)
return -1;
//
if ((*TI.bf || TI.xb || *TI.gh) && create_lib>=0) { // complex terrain
//bp sprintf(fname, "%s/lib", Path);
sprintf(fname, "%s", AbsoluteWindLibPath); //bp
if (TutDirExists(fname)) {
if (TalMode & TIP_LIBRARY) {
n = TutDirClearOnDemand(fname); if (n < 0) eX(10);
}
else vMsg(_using_library_);
}
else {
n = TutDirMake(fname); if (n < 0) eX(11);
create_lib = 1;
}
if (create_lib > 0) { // make library
char gname[256] = "\"";
char gpath[256] = "\"";
char *lan, lanopt[256]; //-2008-12-19
fflush(stdout);
if (*NlsLanOption) { //-2008-12-19
sprintf(lanopt, "--language=%s", NlsLanOption);
lan = lanopt;
}
else //-2008-12-19
lan = NULL;
sprintf(fname, "%s/%s", Home, TALDIA); //-2002-07-03
strcat(gname, fname);
strcat(gname, "\"");
strcat(gpath, Path);
strcat(gpath, "\"");
#ifdef __linux__
n = fork();
if (n == 0) execl(fname,
fname, Path, "-B~../lib", "-w30000", lan, NULL); //-2008-12-19
if (n != -1) pid = wait(&n);
#else
n = spawnl(P_WAIT, fname,
gname, gpath, "-B~../lib", "-w30000", lan, NULL); //-2008-12-19
#endif
if (n) {
sprintf(fname, "%s", AbsoluteWindLibPath); //bp
//bp sprintf(fname, "%s/lib", Path); //-2006-11-06
TutDirClear(fname);
TutDirRemove(fname);
if (n > 0) eX(12);
eX(13);
}
if (TalMode & TIP_LIBRARY) {
vMsg(_library_created_);
return 1;
}
}
}
else if (*TI.bf==0 && !TI.xb && *TI.gh==0 && create_lib>0)
return 2;
if (Write_l) {
strcpy(fname, Path);
strcat(fname, "/work");
n = TutDirMake(fname); if (n < 0) eX(1);
if (n > 0 && (Xflags & 0x20) == 0) { //-2008-08-08
n = TutDirClear(fname); if (n < 0) eX(2);
}
}
n = TipCheck(Path, Write_z);
fprintf(MsgFile, "\n%s", LogCheck.s);
if (n < 0)
return -1;
if (n > 0)
return 1; //-2002-03-28
if (Write_z) { //-2001-05-09 lj
if (!nVarParm) vMsg(_no_variable_parameters_);
return 1;
}
if (Write_l) {
n = TdfWrite(Path, &TIPary, TipFrmTab, TalMode);
if (n < 0) eX(4); //-2007-02-03
if (n>=0 && (*TI.gh>0)) {
n = TdfCopySurface(Path); if (n <= 0) eX(3); //-2001-09-15
}
}
if (TipFrmTab) FREE(TipFrmTab);
TipFrmTab = NULL;
return 0;
eX_1:
eMSG(_directory_$_not_created_, fname);
eX_2:
eMSG(_not_cleared_$_, fname);
eX_3:
eMSG(_missing_profiles_);
eX_4:
eMSG(_cant_write_defs_);
eX_10:
eMSG(_library_not_cleared_);
eX_11:
eMSG(_libdir_not_created_);
eX_12:
eMSG(_library_not_created_$_, n);
eX_13:
eMSG(_taldia_not_run_);
eX_20:
eMSG(_pathname_too_long_);
}
#ifdef MAIN //##########################################################
//================================================================== main
int main( int argc, char *argv[] ) {
char lfile[256];
int n;
if (argc > 1) {
for (n=1; n
strcat(lfile, "/LasTal.log");
MsgFile = fopen(lfile, "w");
}
MsgVerbose = 1;
MsgBreak = '\'';
vMsg("LasTal Version %s %s", TalInpVersion, IBJstamp(__DATE__, __TIME__));
if (argc < 2) {
vMsg("usage: LasTal
exit(0);
}
n = TipMain(NULL);
if (n < 0) vMsg("Program LasTal aborted!");
else vMsg("Program LasTal finished.");
if (MsgFile) fclose(MsgFile);
return 0;
}
#endif //#################################################################
/*=========================================================================
* history:
*
* 2001-04-15 0.1.0 lj created
* 2001-05-01 0.2.1 lj AKS
* 2001-05-03 0.2.2 lj monitor points
* 2001-05-04 0.2.3 lj format string of AKTerm
* 2001-05-09 0.2.4 lj return(1) if option "-z"
* 2001-05-11 0.2.5 lj write ha+d0 in wetter.def
* 2001-05-24 0.2.6 lj definition of not emittable components
* 2001-05-30 0.3.0 lj new definition of species names and components
* 2001-06-09 0.5.0 lj logging of input file
* 2001-06-27 0.5.3 lj ua represented as float
* 2001-06-28 0.5.4 lj lm instead of kl in zeitreihe.dmna
* 2001-06-29 0.5.5 lj hq less 10 allowed (warning only), nh3 added
* 2001-07-09 0.6.0 lj release candidate
* 2001-07-12 0.6.1 lj set Lm=0 for missing data
* 2001-07-14 0.6.2 lj check on missing zeitreihe.dmna
* 2001-07-20 0.6.3 lj determination of z0 using CORINE
* 2001-08-03 0.6.4 lj parameter TI.kp (for nzdos)
* 2001-08-14 0.7.0 lj conversion of GauÃ-Krüger coordinates
* 2001-09-04 0.7.1 lj MsgUnquote() instead of MsgDequote() for input strings
* calculation of source center corrected
* 2001-09-17 0.8.0 lj working with complex terrain
* 2001-10-18 0.8.1 lj computational area at least 2000 m squared
* 2001-10-30 0.8.2 lj nested grids
* 2001-11-02 0.8.3 lj component nox
* 2001-11-03 0.8.4 lj grid alignment relaxed
* 2001-11-05 0.9.0 lj release candidate
* 2001-11-23 0.9.1 lj absolute path for "gh" allowed
* 2001-12-14 0.9.2 lj time interval length checked
* 2002-01-03 0.10.2 lj default value of sq[] = -1
* 2002-01-12 0.10.4 lj check anemometer position (and other positions)
* 2002-02-26 0.10.5 lj counting of monitor points corrected
* 2002-03-11 0.11.1 lj new input parameter : mixing height hm
* 2002-03-28 0.11.2 lj return from input check corrected
* 2002-04-16 0.12.0 lj ha not incremented by d0
* 2002-07-03 0.13.1 lj modifications for linux
* 2002-07-13 0.13.2 lj calculation of nested grids corrected
* 2002-07-30 0.13.3 lj number of decimals for deposition of pm = 4
* 2002-08-01 0.13.4 lj time dependent hm; hh requires NOSTANDARD
* 2002-08-15 0.13.5 lj setting of x0 and y0 checked
* 2002-09-21 0.13.6 lj checking of nested grids improved
* 2002-09-23 0.13.7 lj input parameters lq, rq, tq
* 2002-09-24 1.0.0 lj final release candidate
* 2002-12-06 1.0.3 lj check of Np (less or equal 10)
* 2002-12-10 1.0.4 lj parameter lq, rq, tq allowed to vary with time
* 2003-01-22 1.0.5 lj blanks in file names allowed
* 2003-02-21 1.1.1 lj optional scientific notation, species "xx"
* 2003-06-24 1.1.7 lj error message corrected
* 2003-07-07 1.1.8 lj localisation
* 2003-10-02 1.1.11 lj check of inclusion of finer grids corrected
* lj nesting of grids corrected, check added
* 2003-10-12 1.1.12 lj don't "make" a surface if zg00 is given
* 2003-12-05 1.1.13 lj check on length of time series (less or equal MNT_NUMVAL) added
* 2004-07 2.1.1 uj buildings included
* 2004-09-10 2.1.2 lj check of grid nesting
* 2004-10-25 2.1.4 lj guard cells for grids (1 for outer, 2 for inner)
* lj z0 from CORINE always rounded
* lj optional factors Ftv
* 2004-11-02 2.1.5 uj min dd without buildings changed from 15m to 16m
* 2004-11-12 2.1.6 uj additional check included in getNesting()
* 2004-11-30 2.1.8 uj additional check included in getNesting()
* explicit reference to TA Luft for warning h less 1.2hq
* 2004-12-14 2.1.9 uj wb, da in degree
* 2005-01-10 2.1.10 uj checkBodiesandSources: hq min. 10 m for distance
* 2005-02-21 2.1.11 uj unused makePlainSurface() removed
* 2005-03-16 2.1.12 uj check xa/ya moved, check TrbExt corrected
* 2005-03-17 2.2.0 uj version number upgrade
* 2005-03-18 lj no wind lib created with option -z
* 2005-04-13 2.2.1 lj option -z for flat terrain corrected
* 2006-02-06 2.2.7 uj nonstandard option SORRELAX
* 2006-02-11 uj check if user-defined nz extends to hh_max
* 2006-02-15 2.2.9 lj freeing of strings
* 2006-10-11 2.2.15 lj TI.im defaults to 200
* 2006-10-12 2.2.16 uj number of monitor points increased to 20
* extension to UTM coordinates
* 2006-10-20 2.2.17 uj verbose modus
* 2006-10-20 2.3.0 lj externalization of strings
* 2006-11-06 uj clear lib corrected
* 2006-11-21 2.3.3 uj write out GK-converted source coordinates
* 2007-02-03 2.3.5 uj time interval revised, error if WriteDefs fails
* maximum np adjustable from outside
* 2007-03-08 uj minimum h for z0 calculation
* 2008-01-25 2.3.7 uj allow absolute path for rb
* 2008-03-10 2.4.0 lj evaluation of rated odor frequencies
* 2008-04-17 2.4.1 lj merged with 2.3.x
* 2008-08-27 2.4.3 lj NONSTANDARD optionally
* 2008-09-23 lj 2 additional odor substances
* 2008-10-17 lj uses MsgSetLocale()
* 2008-10-20 2.4.4 lj nonstandard: hm, ie, im, mh, x1, x2, x3, y1, y2, y3
* 2008-12-04 2.4.5 lj lq actually treated as variable parameter
* writes "artp" into header of time series
* 2008-12-07 lj UTM uses zone 32 if ux has no prefix
* 2008-12-11 lj parameter "ggcs" in NTRREC
* 2011-06-17 2.4.10 uj maximum stack height increased to 500
* 2011-06-29 uj check and report if standard roughness register is used
* 2011-07-07 2.5.0 uj version number upgrade
* 2011-09-12 2.5.1 uj TipBlmVersion
* 2011-11-23 2.6.0 lj settings from ARTM
* 2011-12-07 lj check sums
* 2011-12-14 lj "ri" requires NOSTANDARD
* 2011-12-16 lj abort if required option NOSTANDARD is missing
* 2012-04-06 2.6.3 uj complain if NOSTANDARD is missing for "hh"
* 2012-10-30 2.6.5 uj read/write superposition factors
* 2013-01-11 uj invalid umin parsing removed
* 2014-01-21 2.6.9 uj CfgWet
* 2014-06-26 2.6.11 uj accept "ri" if called by TALdia, eX/eG adjusted
* 2015-12-01 2.7.0 lj grid source index "iq"
* 2015-12-15 2.7.1 lj only 1 grid source
* 2018-10-02 3.0.0 uj austal
* 2018-10-29 3.0.1 lj separate precipitation time series
* 2018-11-22 3.0.2 uj radius for z0 determination set to 15*h
* 2019-02-04 3.0.3 uj finest grid up to at least 20 m
* 2019-10-18 3.0.4 uj time zone adjusted reading precipitation file
* 2020-10-14 3.1.0 uj NOTALUFT extensions
* 2021-06-23 3.1.1 uj settings crc code (adjusted odorants)
* 2021-07-03 uj check for hq less 1.2 cb deprecated
* 2021-08-05 3.1.2 uj settings crc code (odorant comment)
* 2021-10-11 3.1.3 uj skip "ri ignored" warning for TALdia
* 2024-01-17 3.3.0 uj BESMAX consistent calculation
* unused "sh" removed
* heavy gas coupling VDI 3783/1 E (2024)
*============================================================================*/