43 NC(nc_def_var(ncid, varname, type, ndims, dimid, varid));
46 NC(nc_put_att_text(ncid, *varid,
"long_name", strlen(longname), longname));
49 NC(nc_put_att_text(ncid, *varid,
"units", strlen(unit), unit));
52 NC(nc_put_att_double(ncid, *varid,
"_FillValue", type, 1, &dp));
65 ALLOC(met0,
met_t, 1);
66 ALLOC(met1,
met_t, 1);
69 for (
int ids = 0; ids < gps->
nds; ids++) {
72 for (
int iz = 0; iz < gps->
nz[ids]; iz++) {
75 get_met(metbase, dt_met, gps->
time[ids], met0, met1);
80 gps->
lon[ids][iz], gps->
lat[ids][iz], &t);
83 gps->
pt[ids][iz] = gps->
t[ids][iz] - t;
100 for (
int ids = 0; ids < gps->
nds; ids++) {
104 for (
int iz = 0; iz < gps->
nz[ids]; iz++)
105 gps->
pt[ids][iz] = 0;
108 const double dlat = dx * 180. / (M_PI * RE) / 2.3548;
109 const double dlon = dy * 180. / 2.3548
110 / (M_PI * RE * cos(gps->
lat[ids][gps->
nz[ids] / 2] * M_PI / 180.));
113 for (
int ids2 = 0; ids2 < gps->
nds; ids2++) {
114 const double w = exp(-0.5 * gsl_pow_2((gps->
lon[ids][gps->
nz[ids] / 2]
116 gps->
lon[ids2][gps->
nz[ids2] /
118 - 0.5 * gsl_pow_2((gps->
lat[ids][gps->
nz[ids] / 2]
120 gps->
lat[ids2][gps->
nz[ids2] /
123 for (
int iz = 0; iz < gps->
nz[ids]; iz++)
124 gps->
pt[ids][iz] += w * gps->
t[ids2][iz];
129 for (
int iz = 0; iz < gps->
nz[ids]; iz++)
130 gps->
pt[ids][iz] = gps->
t[ids][iz] - gps->
pt[ids][iz] / wsum;
146 ERRMSG(
"Too many altitudes!");
149 for (
int ids = 0; ids < gps->
nds; ids++) {
152 for (
int iz = 0; iz < nz; iz++) {
155 z[iz] = LIN(0.0, zmin, nz - 1.0, zmax, (
double) iz);
158 const int iz2 = locate_irr(gps->
z[ids], gps->
nz[ids], z[iz]);
161 lon[iz] = LIN(gps->
z[ids][iz2], gps->
lon[ids][iz2],
162 gps->
z[ids][iz2 + 1], gps->
lon[ids][iz2 + 1], z[iz]);
163 lat[iz] = LIN(gps->
z[ids][iz2], gps->
lat[ids][iz2],
164 gps->
z[ids][iz2 + 1], gps->
lat[ids][iz2 + 1], z[iz]);
165 p[iz] = LIN(gps->
z[ids][iz2], gps->
p[ids][iz2],
166 gps->
z[ids][iz2 + 1], gps->
p[ids][iz2 + 1], z[iz]);
167 t[iz] = LIN(gps->
z[ids][iz2], gps->
t[ids][iz2],
168 gps->
z[ids][iz2 + 1], gps->
t[ids][iz2 + 1], z[iz]);
169 wv[iz] = LIN(gps->
z[ids][iz2], gps->
wv[ids][iz2],
170 gps->
z[ids][iz2 + 1], gps->
wv[ids][iz2 + 1], z[iz]);
171 pt[iz] = LIN(gps->
z[ids][iz2], gps->
pt[ids][iz2],
172 gps->
z[ids][iz2 + 1], gps->
pt[ids][iz2 + 1], z[iz]);
177 for (
int iz = 0; iz < nz; iz++) {
178 gps->
z[ids][iz] = z[iz];
179 gps->
lon[ids][iz] = lon[iz];
180 gps->
lat[ids][iz] = lat[iz];
181 gps->
p[ids][iz] = p[iz];
182 gps->
t[ids][iz] = t[iz];
183 gps->
wv[ids][iz] = wv[iz];
184 gps->
pt[ids][iz] = pt[iz];
214 if (t > met1->
time) {
215 memcpy(met0, met1,
sizeof(
met_t));
232 int year, mon, day, hour, min, sec;
236 t6 = floor(t / dt_met) * dt_met;
238 t6 = ceil(t / dt_met) * dt_met;
241 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
244 sprintf(filename,
"%s_%d_%02d_%02d_%02d.nc", metbase, year, mon, day, hour);
260 double aux00 = wp * (array[ix][iy][ip] - array[ix][iy][ip + 1])
261 + array[ix][iy][ip + 1];
262 double aux01 = wp * (array[ix][iy + 1][ip] - array[ix][iy + 1][ip + 1])
263 + array[ix][iy + 1][ip + 1];
264 double aux10 = wp * (array[ix + 1][iy][ip] - array[ix + 1][iy][ip + 1])
265 + array[ix + 1][iy][ip + 1];
267 wp * (array[ix + 1][iy + 1][ip] - array[ix + 1][iy + 1][ip + 1])
268 + array[ix + 1][iy + 1][ip + 1];
271 aux00 = wy * (aux00 - aux01) + aux01;
272 aux11 = wy * (aux10 - aux11) + aux11;
273 *var = wx * (aux00 - aux11) + aux11;
286 if (met->
lon[met->
nx - 1] > 180 && lon < 0)
290 const int ip = locate_irr(met->
p, met->
np, p);
291 const int ix = locate_reg(met->
lon, met->
nx, lon);
292 const int iy = locate_reg(met->
lat, met->
ny, lat);
295 const double wp = (met->
p[ip + 1] - p) / (met->
p[ip + 1] - met->
p[ip]);
297 (met->
lon[ix + 1] - lon) / (met->
lon[ix + 1] - met->
lon[ix]);
299 (met->
lat[iy + 1] - lat) / (met->
lat[iy + 1] - met->
lat[iy]);
323 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
326 *t = wt * (t0 - t1) + t1;
338 for (
int ids = 0; ids < gps->
nds; ids++) {
342 (int) (dz / fabs((gps->
z[ids][0] - gps->
z[ids][gps->
nz[ids] - 1])
343 / (gps->
nz[ids] - 1.0)) + 0.5);
344 nham = GSL_MAX(GSL_MIN(nham,
NZ), 2);
345 for (
int iham = 0; iham < nham; iham++)
346 ham[iham] = 0.54 + 0.46 * cos(M_PI * iham / (nham - 1.0));
349 for (
int iz = 0; iz < gps->
nz[ids]; iz++) {
352 gps->
pt[ids][iz] = ham[0] * gps->
t[ids][iz];
353 double wsum = ham[0];
356 for (
int iham = 1; iham < nham; iham++) {
359 if (iz - iham < 0 || iz + iham >= gps->
nz[ids])
363 if (!gsl_finite(gps->
t[ids][iz - iham]) ||
364 !gsl_finite(gps->
t[ids][iz + iham]))
368 if (gsl_finite(gps->
th[ids]) && gps->
th[ids] > 0)
369 if ((gps->
z[ids][iz] >= gps->
th[ids]
370 && gps->
z[ids][iz - iham] < gps->
th[ids])
371 || (gps->
z[ids][iz] <= gps->
th[ids]
372 && gps->
z[ids][iz + iham] > gps->
th[ids]))
377 += ham[iham] * (gps->
t[ids][iz - iham] + gps->
t[ids][iz + iham]);
378 wsum += 2 * ham[iham];
382 gps->
pt[ids][iz] = gps->
t[ids][iz] - gps->
pt[ids][iz] / wsum;
393 double ham[
NZ], pt[
NZ];
396 for (
int ids = 0; ids < gps->
nds; ids++) {
400 (int) (dz / fabs((gps->
z[ids][0] - gps->
z[ids][gps->
nz[ids] - 1])
401 / (gps->
nz[ids] - 1.0)) + 0.5);
402 nham = GSL_MAX(GSL_MIN(nham,
NZ), 2);
403 for (
int iham = 0; iham < nham; iham++)
404 ham[iham] = 0.54 + 0.46 * cos(M_PI * iham / (nham - 1.0));
407 for (
int iz = 0; iz < gps->
nz[ids]; iz++) {
410 pt[iz] = ham[0] * gps->
pt[ids][iz];
411 double wsum = ham[0];
414 for (
int iham = 1; iham < nham; iham++) {
417 if (iz - iham < 0 || iz + iham >= gps->
nz[ids])
421 if (!gsl_finite(gps->
t[ids][iz - iham]) ||
422 !gsl_finite(gps->
t[ids][iz + iham]))
427 += ham[iham] * (gps->
pt[ids][iz - iham] + gps->
pt[ids][iz + iham]);
428 wsum += 2 * ham[iham];
436 for (
int iz = 0; iz < gps->
nz[ids]; iz++)
437 gps->
pt[ids][iz] = pt[iz];
452 for (
int ids = 0; ids < gps->
nds; ids++) {
455 for (
int iz = 0; iz < gps->
nz[ids]; iz++)
456 bg[iz] = gps->
pt[ids][iz];
459 poly_help(gps->
z[ids], bg, gps->
nz[ids], dim, zmin, zmax);
462 for (
int iz = 0; iz < gps->
nz[ids]; iz++)
463 gps->
pt[ids][iz] -= bg[iz];
477 gsl_multifit_linear_workspace *work;
479 gsl_vector *c, *x, *y;
481 double chisq, xx2[
NZ], yy2[
NZ];
486 for (
size_t i = 0; i < (size_t) n; i++)
487 if (xx[i] >= xmin && xx[i] <= xmax && gsl_finite(yy[i])) {
492 if ((
int) n2 < dim) {
493 for (
size_t i = 0; i < (size_t) n; i++)
499 work = gsl_multifit_linear_alloc((
size_t) n2, (
size_t) dim);
500 cov = gsl_matrix_alloc((
size_t) dim, (
size_t) dim);
501 X = gsl_matrix_alloc((
size_t) n2, (
size_t) dim);
502 c = gsl_vector_alloc((
size_t) dim);
503 x = gsl_vector_alloc((
size_t) n2);
504 y = gsl_vector_alloc((
size_t) n2);
507 for (
size_t i = 0; i < (size_t) n2; i++) {
508 gsl_vector_set(x, i, xx2[i]);
509 gsl_vector_set(y, i, yy2[i]);
510 for (
size_t i2 = 0; i2 < (size_t) dim; i2++)
511 gsl_matrix_set(X, i, i2, pow(gsl_vector_get(x, i), (
double) i2));
513 gsl_multifit_linear(X, y, c, cov, &chisq, work);
514 for (
size_t i = 0; i < (size_t) n; i++)
515 yy[i] = gsl_poly_eval(c->data, (
int) dim, xx[i]);
518 gsl_multifit_linear_free(work);
519 gsl_matrix_free(cov);
534 double t0, t1, zmin = 1e100, zmax = -1e100;
536 int ncid, dimid, dimid2, varid;
541 printf(
"Read GPS-RO profile: %s\n", filename);
542 NC(nc_open(filename, NC_NOWRITE, &ncid));
545 NC(nc_inq_dimid(ncid,
"MSL_alt", &dimid));
546 NC(nc_inq_dimlen(ncid, dimid, &nz));
547 gps->
nz[gps->
nds] = (int) nz;
549 ERRMSG(
"Too many altitudes!");
552 if (nc_get_att_text(ncid, NC_GLOBAL,
"bad", bad) == NC_NOERR)
559 if (nc_get_att_double(ncid, NC_GLOBAL,
"start_time", &t0) == NC_NOERR
560 && nc_get_att_double(ncid, NC_GLOBAL,
"stop_time", &t1) == NC_NOERR)
561 gps->
time[gps->
nds] = 0.5 * (t0 + t1) - 630720000.0;
563 NC(nc_inq_varid(ncid,
"Time", &varid));
564 NC(nc_get_var_double(ncid, varid, &gps->
time[gps->
nds]));
565 gps->
time[gps->
nds] -= 630720000.0;
569 NC(nc_inq_varid(ncid,
"MSL_alt", &varid));
570 NC(nc_get_var_double(ncid, varid, gps->
z[gps->
nds]));
571 NC(nc_inq_varid(ncid,
"Lon", &varid));
572 NC(nc_get_var_double(ncid, varid, gps->
lon[gps->
nds]));
573 NC(nc_inq_var(ncid, varid, NULL, NULL, NULL, &dimid2, NULL));
575 for (
size_t iz = 1; iz < nz; iz++)
577 NC(nc_inq_varid(ncid,
"Lat", &varid));
578 NC(nc_get_var_double(ncid, varid, gps->
lat[gps->
nds]));
579 NC(nc_inq_var(ncid, varid, NULL, NULL, NULL, &dimid2, NULL));
581 for (
size_t iz = 1; iz < nz; iz++)
583 NC(nc_inq_varid(ncid,
"Pres", &varid));
584 NC(nc_get_var_double(ncid, varid, gps->
p[gps->
nds]));
585 NC(nc_inq_varid(ncid,
"Temp", &varid));
586 NC(nc_get_var_double(ncid, varid, gps->
t[gps->
nds]));
587 if (nc_inq_varid(ncid,
"Vp", &varid) == NC_NOERR)
588 NC(nc_get_var_double(ncid, varid, gps->
wv[gps->
nds]));
591 for (
size_t iz = 0; iz < nz; iz++)
592 if (gps->
p[gps->
nds][iz] != -999 && gps->
t[gps->
nds][iz] != -999) {
593 zmin = GSL_MIN(zmin, gps->
z[gps->
nds][iz]);
594 zmax = GSL_MAX(zmax, gps->
z[gps->
nds][iz]);
596 if (zmin > 5 || zmax < 35) {
602 for (
size_t iz = 0; iz < nz; iz++)
603 if (gps->
lon[gps->
nds][iz] == -999 ||
604 gps->
lat[gps->
nds][iz] == -999 ||
605 gps->
p[gps->
nds][iz] == -999 ||
606 gps->
t[gps->
nds][iz] == -999 || gps->
wv[gps->
nds][iz] == -999) {
607 gps->
lon[gps->
nds][iz] = GSL_NAN;
608 gps->
lat[gps->
nds][iz] = GSL_NAN;
609 gps->
p[gps->
nds][iz] = GSL_NAN;
610 gps->
t[gps->
nds][iz] = GSL_NAN;
611 gps->
wv[gps->
nds][iz] = GSL_NAN;
615 for (
size_t iz = 0; iz < nz; iz++)
616 gps->
t[gps->
nds][iz] += 273.15;
619 for (
size_t iz = 0; iz < nz; iz++)
620 gps->
wv[gps->
nds][iz] /= gps->
p[gps->
nds][iz];
627 ERRMSG(
"Too many profiles!");
636 int ids, ncid, dimid, varid;
638 size_t start[2], count[2], nds, nz;
641 printf(
"Read GPS-RO file: %s\n", filename);
642 NC(nc_open(filename, NC_NOWRITE, &ncid));
645 NC(nc_inq_dimid(ncid,
"NDS", &dimid));
646 NC(nc_inq_dimlen(ncid, dimid, &nds));
647 gps->
nds = (int) nds;
649 ERRMSG(
"Too many profiles!");
651 NC(nc_inq_dimid(ncid,
"NZ", &dimid));
652 NC(nc_inq_dimlen(ncid, dimid, &nz));
654 ERRMSG(
"Too many profiles!");
657 for (ids = 0; ids < gps->
nds; ids++) {
660 start[0] = (size_t) ids;
666 gps->
nz[ids] = (int) nz;
669 NC(nc_inq_varid(ncid,
"time", &varid));
670 NC(nc_get_vara_double(ncid, varid, start, count, &gps->
time[ids]));
672 NC(nc_inq_varid(ncid,
"z", &varid));
673 NC(nc_get_vara_double(ncid, varid, start, count, gps->
z[ids]));
675 NC(nc_inq_varid(ncid,
"lon", &varid));
676 NC(nc_get_vara_double(ncid, varid, start, count, gps->
lon[ids]));
678 NC(nc_inq_varid(ncid,
"lat", &varid));
679 NC(nc_get_vara_double(ncid, varid, start, count, gps->
lat[ids]));
681 NC(nc_inq_varid(ncid,
"p", &varid));
682 NC(nc_get_vara_double(ncid, varid, start, count, gps->
p[ids]));
684 NC(nc_inq_varid(ncid,
"t", &varid));
685 NC(nc_get_vara_double(ncid, varid, start, count, gps->
t[ids]));
687 NC(nc_inq_varid(ncid,
"wv", &varid));
688 NC(nc_get_vara_double(ncid, varid, start, count, gps->
wv[ids]));
690 NC(nc_inq_varid(ncid,
"pt", &varid));
691 NC(nc_get_vara_double(ncid, varid, start, count, gps->
pt[ids]));
693 NC(nc_inq_varid(ncid,
"th", &varid));
694 NC(nc_get_vara_double(ncid, varid, start, count, &gps->
th[ids]));
709 int dimid, ncid, varid, year, mon, day, hour;
714 printf(
"Read meteorological data: %s\n", filename);
717 sprintf(tstr,
"%.4s", &filename[strlen(filename) - 16]);
719 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 11]);
721 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 8]);
723 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 5]);
725 time2jsec(year, mon, day, hour, 0, 0, 0, &met->
time);
728 NC(nc_open(filename, NC_NOWRITE, &ncid));
731 NC(nc_inq_dimid(ncid,
"lon", &dimid));
732 NC(nc_inq_dimlen(ncid, dimid, &nx));
734 ERRMSG(
"Too many longitudes!");
736 NC(nc_inq_dimid(ncid,
"lat", &dimid));
737 NC(nc_inq_dimlen(ncid, dimid, &ny));
739 ERRMSG(
"Too many latitudes!");
741 NC(nc_inq_dimid(ncid,
"lev", &dimid));
742 NC(nc_inq_dimlen(ncid, dimid, &np));
744 ERRMSG(
"Too many levels!");
752 NC(nc_inq_varid(ncid,
"lon", &varid));
753 NC(nc_get_var_double(ncid, varid, met->
lon));
754 NC(nc_inq_varid(ncid,
"lat", &varid));
755 NC(nc_get_var_double(ncid, varid, met->
lat));
761 NC(nc_inq_varid(ncid,
"lev", &varid));
762 NC(nc_get_var_double(ncid, varid, met->
p));
763 for (
int ip = 0; ip < met->
np; ip++)
770 for (
int ip = 1; ip < met->
np; ip++)
771 if (met->
p[ip - 1] < met->
p[ip])
772 ERRMSG(
"Pressure levels must be descending!");
787 for (
int ix = 0; ix < met->
nx; ix++)
788 for (
int iy = 0; iy < met->
ny; iy++) {
792 for (ip0 = met->
np - 1; ip0 >= 0; ip0--)
793 if (!gsl_finite(met->
t[ix][iy][ip0]))
797 for (
int ip = ip0; ip >= 0; ip--)
798 met->
t[ix][iy][ip] = met->
t[ix][iy][ip + 1];
812 static float help[
EX *
EY *
EP];
817 if (nc_inq_varid(ncid, varname, &varid) != NC_NOERR)
818 if (nc_inq_varid(ncid, varname2, &varid) != NC_NOERR)
822 NC(nc_get_var_float(ncid, varid, help));
825 for (
int ip = 0; ip < met->
np; ip++)
826 for (
int iy = 0; iy < met->
ny; iy++)
827 for (
int ix = 0; ix < met->
nx; ix++) {
828 dest[ix][iy][ip] = scl * help[n++];
829 if (fabs(dest[ix][iy][ip] / scl) > 1e14)
830 dest[ix][iy][ip] = GSL_NAN;
840 if (!(fabs(met->
lon[met->
nx - 1] - met->
lon[0]
841 + met->
lon[1] - met->
lon[0] - 360) < 0.01))
845 if ((++met->
nx) >
EX)
846 ERRMSG(
"Cannot create periodic boundary conditions!");
852 for (
int iy = 0; iy < met->
ny; iy++)
853 for (
int ip = 0; ip < met->
np; ip++)
854 met->
t[met->
nx - 1][iy][ip] = met->
t[0][iy][ip];
872 gsl_interp_accel *acc = gsl_interp_accel_alloc();
873 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (
size_t) n);
876 gsl_spline_init(s, x, y, (
size_t) n);
877 for (
int i = 0; i < n2; i++)
880 else if (x2[i] >= x[n - 1])
883 y2[i] = gsl_spline_eval(s, x2[i], acc);
887 gsl_interp_accel_free(acc);
892 for (
int i = 0; i < n2; i++)
895 else if (x2[i] >= x[n - 1])
898 int idx = locate_irr(x, n, x2[i]);
899 y2[i] = LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
910 for (
int ids = 0; ids < gps->
nds; ids++) {
913 gps->
th[ids] = GSL_NAN;
917 8 - 4 * fabs(cos((90 - gps->
lat[ids][gps->
nz[ids] / 2]) * M_PI / 180));
920 for (
int iz = 0; iz < gps->
nz[ids]; iz++)
921 if (gps->
z[ids][iz] >= zmin && gps->
z[ids][iz] <= 20.0) {
923 for (
int iz2 = iz + 1; iz2 < gps->
nz[ids]; iz2++)
924 if (gps->
z[ids][iz2] - gps->
z[ids][iz] <= 2.0)
925 if (!gsl_finite(gps->
t[ids][iz]) ||
926 !gsl_finite(gps->
t[ids][iz2]) ||
927 (gps->
t[ids][iz2] - gps->
t[ids][iz])
928 / (gps->
z[ids][iz2] - gps->
z[ids][iz]) < -2.0)
931 gps->
th[ids] = gps->
z[ids][iz];
945#pragma omp parallel for default(shared)
946 for (
int ids = 0; ids < gps->
nds; ids++) {
953 gps->
tlon[ids] = NAN;
954 gps->
tlat[ids] = NAN;
959 for (
int iz = 0; iz < gps->
nz[ids]; iz++)
960 if (gsl_finite(gps->
p[ids][iz]) && gsl_finite(gps->
t[ids][iz])
961 && gsl_finite(gps->
z[ids][iz])
962 && gps->
z[ids][iz] >= 4.0 && gps->
z[ids][iz] <= 24.0) {
963 h[nz] = gps->
z[ids][iz];
964 t[nz] = gps->
t[ids][iz];
965 z[nz] =
Z(gps->
p[ids][iz]);
966 q[nz] = gps->
wv[ids][iz];
967 lon[nz] = gps->
lon[ids][iz];
968 lat[nz] = gps->
lat[ids][iz];
969 if (nz > 0 && z[nz] <= z[nz - 1])
970 ERRMSG(
"Profiles must be ascending!");
972 ERRMSG(
"Too many height levels!");
974 if (z[0] > 4.5 || z[nz - 1] < 23.5)
975 WARN(
"Vertical profile is incomplete!");
978 double h2[200], p2[200], t2[200], z2[200], q2[200];
979 for (
int iz = 0; iz <= 190; iz++) {
980 z2[iz] = 4.5 + 0.1 * iz;
985 spline(z, t, nz, z2, t2, 191, 1);
986 spline(z, h, nz, z2, h2, 191, 1);
987 spline(z, q, nz, z2, q2, 191, 1);
990 if (met_tropo == 2) {
993 int iz = (int) gsl_stats_min_index(t2, 1, 171);
994 if (iz > 0 && iz < 170) {
995 gps->
tp[ids] = p2[iz];
996 gps->
th[ids] = h2[iz];
997 gps->
tt[ids] = t2[iz];
998 gps->
tq[ids] = q2[iz];
1003 else if (met_tropo == 3 || met_tropo == 4) {
1007 for (iz = 0; iz <= 170; iz++) {
1009 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
1010 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
1015 if (iz > 0 && iz < 170) {
1016 gps->
tp[ids] = p2[iz];
1017 gps->
th[ids] = h2[iz];
1018 gps->
tt[ids] = t2[iz];
1019 gps->
tq[ids] = q2[iz];
1026 if (met_tropo == 4) {
1035 for (; iz <= 170; iz++) {
1037 for (
int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
1038 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
1045 for (; iz <= 170; iz++) {
1047 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
1048 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
1053 if (iz > 0 && iz < 170) {
1054 gps->
tp[ids] = p2[iz];
1055 gps->
th[ids] = h2[iz];
1056 gps->
tt[ids] = t2[iz];
1057 gps->
tq[ids] = q2[iz];
1066 if (gsl_finite(gps->
th[ids]))
1067 for (
int iz = 0; iz < nz - 1; iz++)
1068 if (gps->
th[ids] >= h[iz] && gps->
th[ids] < h[iz + 1]) {
1069 gps->
tlon[ids] = lon[iz];
1070 gps->
tlat[ids] = lat[iz];
1082 static double help[
NDS *
NZ];
1084 int ncid, dimid[2], time_id, z_id, lon_id, lat_id, p_id, t_id,
1085 pt_id, wv_id, th_id, nzmax = 0;
1088 printf(
"Write GPS-RO file: %s\n", filename);
1089 NC(nc_create(filename, NC_CLOBBER, &ncid));
1092 NC(nc_def_dim(ncid,
"NDS", (
size_t) gps->
nds, &dimid[0]));
1093 for (
int ids = 0; ids < gps->
nds; ids++)
1094 nzmax = GSL_MAX(nzmax, gps->
nz[ids]);
1095 NC(nc_def_dim(ncid,
"NZ", (
size_t) nzmax, &dimid[1]));
1098 add_var(ncid,
"time",
"s",
"time (seconds since 2000-01-01T00:00Z)",
1099 NC_DOUBLE, dimid, &time_id, 1);
1100 add_var(ncid,
"z",
"km",
"altitude", NC_FLOAT, dimid, &z_id, 2);
1101 add_var(ncid,
"lon",
"deg",
"longitude", NC_FLOAT, dimid, &lon_id, 2);
1102 add_var(ncid,
"lat",
"deg",
"latitude", NC_FLOAT, dimid, &lat_id, 2);
1103 add_var(ncid,
"p",
"hPa",
"pressure", NC_FLOAT, dimid, &p_id, 2);
1104 add_var(ncid,
"t",
"K",
"temperature", NC_FLOAT, dimid, &t_id, 2);
1105 add_var(ncid,
"wv",
"ppv",
"water vapor volume mixing ratio",
1106 NC_FLOAT, dimid, &wv_id, 2);
1107 add_var(ncid,
"pt",
"K",
"temperature perturbation",
1108 NC_FLOAT, dimid, &pt_id, 2);
1109 add_var(ncid,
"th",
"km",
"tropopause height", NC_FLOAT, dimid, &th_id, 1);
1112 NC(nc_enddef(ncid));
1115 NC(nc_put_var_double(ncid, time_id, gps->
time));
1116 NC(nc_put_var_double(ncid, th_id, gps->
th));
1117 for (
int ids = 0; ids < gps->
nds; ids++)
1118 for (
int iz = 0; iz < gps->
nz[ids]; iz++)
1119 help[ids * nzmax + iz] = gps->
z[ids][iz];
1120 NC(nc_put_var_double(ncid, z_id, help));
1121 for (
int ids = 0; ids < gps->
nds; ids++)
1122 for (
int iz = 0; iz < gps->
nz[ids]; iz++)
1123 help[ids * nzmax + iz] = gps->
lon[ids][iz];
1124 NC(nc_put_var_double(ncid, lon_id, help));
1125 for (
int ids = 0; ids < gps->
nds; ids++)
1126 for (
int iz = 0; iz < gps->
nz[ids]; iz++)
1127 help[ids * nzmax + iz] = gps->
lat[ids][iz];
1128 NC(nc_put_var_double(ncid, lat_id, help));
1129 for (
int ids = 0; ids < gps->
nds; ids++)
1130 for (
int iz = 0; iz < gps->
nz[ids]; iz++)
1131 help[ids * nzmax + iz] = gps->
p[ids][iz];
1132 NC(nc_put_var_double(ncid, p_id, help));
1133 for (
int ids = 0; ids < gps->
nds; ids++)
1134 for (
int iz = 0; iz < gps->
nz[ids]; iz++)
1135 help[ids * nzmax + iz] = gps->
t[ids][iz];
1136 NC(nc_put_var_double(ncid, t_id, help));
1137 for (
int ids = 0; ids < gps->
nds; ids++)
1138 for (
int iz = 0; iz < gps->
nz[ids]; iz++)
1139 help[ids * nzmax + iz] = gps->
wv[ids][iz];
1140 NC(nc_put_var_double(ncid, wv_id, help));
1141 for (
int ids = 0; ids < gps->
nds; ids++)
1142 for (
int iz = 0; iz < gps->
nz[ids]; iz++)
1143 help[ids * nzmax + iz] = gps->
pt[ids][iz];
1144 NC(nc_put_var_double(ncid, pt_id, help));
void read_met_extrapolate(met_t *met)
Extrapolate meteorological data at lower boundary.
void intpol_met_space(met_t *met, double p, double lon, double lat, double *t)
Spatial interpolation of meteorological data.
void write_gps(char *filename, gps_t *gps)
Write GPS-RO data file.
void read_met_periodic(met_t *met)
Create meteorological data with periodic boundary conditions.
void gauss(gps_t *gps, double dx, double dy)
Calculate horizontal Gaussian mean to extract perturbations.
void read_met(char *filename, met_t *met)
Read meteorological data file.
void intpol_met_time(met_t *met0, met_t *met1, double ts, double p, double lon, double lat, double *t)
Temporal interpolation of meteorological data.
void spline(const double *x, const double *y, const int n, const double *x2, double *y2, const int n2, const int method)
Performs spline interpolation or linear interpolation.
void poly(gps_t *gps, int dim, double zmin, double zmax)
Remove polynomial fit from perturbation profile.
void grid_gps(gps_t *gps, double zmin, double zmax, int nz)
Interpolate GPS data to regular altitude grid.
void intpol_met_3d(float array[EX][EY][EP], int ip, int ix, int iy, double wp, double wx, double wy, double *var)
Linear interpolation of 3-D meteorological data.
void add_var(int ncid, const char *varname, const char *unit, const char *longname, int type, int dimid[], int *varid, int ndims)
Add variable to netCDF file.
void get_met(char *metbase, double dt_met, double t, met_t *met0, met_t *met1)
Get meteorological data for given timestep.
void read_gps(char *filename, gps_t *gps)
Read GPS-RO data file.
void hamming_low_pass(gps_t *gps, double dz)
Apply vertical Hamming filter to extract perturbations.
void detrend_met(gps_t *gps, char *metbase, double dt_met)
Detrending by means of meteo data.
void read_gps_prof(char *filename, gps_t *gps)
Read GPS-RO profile.
void get_met_help(double t, int direct, char *metbase, double dt_met, char *filename)
Get meteorological data for timestep.
void hamming_high_pass(gps_t *gps, double dz)
Apply vertical Hamming filter to reduce noise.
void tropopause_spline(gps_t *gps, int met_tropo)
Find tropopause height using cubic spline interpolation.
void poly_help(double *xx, double *yy, int n, int dim, double xmin, double xmax)
Auxiliary function for polynomial interpolation.
void read_met_help(int ncid, char *varname, char *varname2, met_t *met, float dest[EX][EY][EP], float scl)
Read and convert variable from meteorological data file.
void tropopause(gps_t *gps)
Find tropopause height.
GPS Code Collection library declarations.
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
#define NC(cmd)
Execute netCDF library command and check result.
#define EY
Maximum number of latitudes for meteorological data.
#define Z(p)
Convert pressure to altitude.
#define P(z)
Compute pressure at given altitude.
#define NZ
Maximum number of altitudes per GPS-RO profile.
#define EX
Maximum number of longitudes for meteorological data.
#define NDS
Maximum number of GPS-RO profiles.
#define EP
Maximum number of pressure levels for meteorological data.
double time[NDS]
Time (seconds since 2000-01-01T00:00Z).
double pt[NDS][NZ]
Temperature perturbation [K].
double tlon[NDS]
Tropopause longitude [deg].
double tt[NDS]
Tropopause temperature [K].
double t[NDS][NZ]
Temperature [K].
double tp[NDS]
Tropopause pressure [hPa].
double wv[NDS][NZ]
Water vapor volume mixing ratio [ppm].
int nz[NDS]
Number of altitudes per profile.
double lon[NDS][NZ]
Longitude [deg].
int nds
Number of profiles.
double p[NDS][NZ]
Pressure [hPa].
double th[NDS]
Tropopause height [km].
double z[NDS][NZ]
Altitude [km].
double tlat[NDS]
Tropopause latitude [deg].
double lat[NDS][NZ]
Latitude [deg].
double tq[NDS]
Tropopause water vapor [ppmv].
int nx
Number of longitudes.
int ny
Number of latitudes.
int np
Number of pressure levels.
float t[EX][EY][EP]
Temperature [K].
double lon[EX]
Longitude [deg].
double lat[EY]
Latitude [deg].
double p[EP]
Pressure [hPa].