AIRS Code Collection
Data Structures | Macros | Functions
issifm.c File Reference

Simulate AIRS observations based on atmospheric model output. More...

#include "libairs.h"

Go to the source code of this file.

Data Structures

struct  model_t
 Model data. More...
 

Macros

#define NZ   248
 Maximum number of model levels. More...
 
#define NLON   4080
 Maximum number of model longitudes. More...
 
#define NLAT   1402
 Maximum number of model latitudes. More...
 

Functions

void intpol (model_t *model, double z, double lon, double lat, double *p, double *t)
 Interpolation of model data. More...
 
void smooth (model_t *model)
 Smoothing of model data. More...
 
void write_nc (char *filename, wave_t *wave)
 Write wave struct to netCDF file. More...
 
int main (int argc, char *argv[])
 

Detailed Description

Simulate AIRS observations based on atmospheric model output.

Definition in file issifm.c.

Macro Definition Documentation

◆ NZ

#define NZ   248

Maximum number of model levels.

Definition at line 33 of file issifm.c.

◆ NLON

#define NLON   4080

Maximum number of model longitudes.

Definition at line 36 of file issifm.c.

◆ NLAT

#define NLAT   1402

Maximum number of model latitudes.

Definition at line 39 of file issifm.c.

Function Documentation

◆ intpol()

void intpol ( model_t model,
double  z,
double  lon,
double  lat,
double *  p,
double *  t 
)

Interpolation of model data.

Definition at line 619 of file issifm.c.

625 {
626
627 double zd[NZ];
628
629 int iz;
630
631 /* Adjust longitude... */
632 if (model->lon[model->nlon - 1] > 180)
633 if (lon < 0)
634 lon += 360;
635
636 /* Check horizontal range... */
637 if (lon < model->lon[0]
638 || lon > model->lon[model->nlon - 1]
639 || lat < GSL_MIN(model->lat[0], model->lat[model->nlat - 1])
640 || lat > GSL_MAX(model->lat[0], model->lat[model->nlat - 1])) {
641 *p = GSL_NAN;
642 *t = GSL_NAN;
643 return;
644 }
645
646 /* Get indices... */
647 int ilon = locate_irr(model->lon, model->nlon, lon);
648 int ilat = locate_irr(model->lat, model->nlat, lat);
649
650 /* Check data... */
651 if (!gsl_finite(model->z[ilon][ilat][0])
652 || !gsl_finite(model->z[ilon][ilat][model->nz - 1])
653 || !gsl_finite(model->z[ilon][ilat + 1][model->nz - 1])
654 || !gsl_finite(model->z[ilon][ilat + 1][model->nz - 1])
655 || !gsl_finite(model->z[ilon + 1][ilat][model->nz - 1])
656 || !gsl_finite(model->z[ilon + 1][ilat][model->nz - 1])
657 || !gsl_finite(model->z[ilon + 1][ilat + 1][model->nz - 1])
658 || !gsl_finite(model->z[ilon + 1][ilat + 1][model->nz - 1])) {
659 *p = GSL_NAN;
660 *t = GSL_NAN;
661 return;
662 }
663
664 /* Check vertical range... */
665 if (z >
666 GSL_MAX(model->z[ilon][ilat][0], model->z[ilon][ilat][model->nz - 1])
667 || z < GSL_MIN(model->z[ilon][ilat][0],
668 model->z[ilon][ilat][model->nz - 1])
669 || z > GSL_MAX(model->z[ilon][ilat + 1][0],
670 model->z[ilon][ilat + 1][model->nz - 1])
671 || z < GSL_MIN(model->z[ilon][ilat + 1][0],
672 model->z[ilon][ilat + 1][model->nz - 1])
673 || z > GSL_MAX(model->z[ilon + 1][ilat][0],
674 model->z[ilon + 1][ilat][model->nz - 1])
675 || z < GSL_MIN(model->z[ilon + 1][ilat][0],
676 model->z[ilon + 1][ilat][model->nz - 1])
677 || z > GSL_MAX(model->z[ilon + 1][ilat + 1][0],
678 model->z[ilon + 1][ilat + 1][model->nz - 1])
679 || z < GSL_MIN(model->z[ilon + 1][ilat + 1][0],
680 model->z[ilon + 1][ilat + 1][model->nz - 1]))
681 return;
682
683 /* Interpolate vertically... */
684 for (iz = 0; iz < model->nz; iz++)
685 zd[iz] = model->z[ilon][ilat][iz];
686 iz = locate_irr(zd, model->nz, z);
687 double p00 = LIN(model->z[ilon][ilat][iz], model->p[ilon][ilat][iz],
688 model->z[ilon][ilat][iz + 1], model->p[ilon][ilat][iz + 1],
689 z);
690 double t00 = LIN(model->z[ilon][ilat][iz], model->t[ilon][ilat][iz],
691 model->z[ilon][ilat][iz + 1], model->t[ilon][ilat][iz + 1],
692 z);
693
694 for (iz = 0; iz < model->nz; iz++)
695 zd[iz] = model->z[ilon][ilat + 1][iz];
696 iz = locate_irr(zd, model->nz, z);
697 double p01 = LIN(model->z[ilon][ilat + 1][iz], model->p[ilon][ilat + 1][iz],
698 model->z[ilon][ilat + 1][iz + 1],
699 model->p[ilon][ilat + 1][iz + 1], z);
700 double t01 = LIN(model->z[ilon][ilat + 1][iz], model->t[ilon][ilat + 1][iz],
701 model->z[ilon][ilat + 1][iz + 1],
702 model->t[ilon][ilat + 1][iz + 1],
703 z);
704
705 for (iz = 0; iz < model->nz; iz++)
706 zd[iz] = model->z[ilon + 1][ilat][iz];
707 iz = locate_irr(zd, model->nz, z);
708 double p10 = LIN(model->z[ilon + 1][ilat][iz], model->p[ilon + 1][ilat][iz],
709 model->z[ilon + 1][ilat][iz + 1],
710 model->p[ilon + 1][ilat][iz + 1], z);
711 double t10 = LIN(model->z[ilon + 1][ilat][iz], model->t[ilon + 1][ilat][iz],
712 model->z[ilon + 1][ilat][iz + 1],
713 model->t[ilon + 1][ilat][iz + 1],
714 z);
715
716 for (iz = 0; iz < model->nz; iz++)
717 zd[iz] = model->z[ilon + 1][ilat + 1][iz];
718 iz = locate_irr(zd, model->nz, z);
719 double p11 =
720 LIN(model->z[ilon + 1][ilat + 1][iz], model->p[ilon + 1][ilat + 1][iz],
721 model->z[ilon + 1][ilat + 1][iz + 1],
722 model->p[ilon + 1][ilat + 1][iz + 1], z);
723 double t11 =
724 LIN(model->z[ilon + 1][ilat + 1][iz], model->t[ilon + 1][ilat + 1][iz],
725 model->z[ilon + 1][ilat + 1][iz + 1],
726 model->t[ilon + 1][ilat + 1][iz + 1], z);
727
728 /* Interpolate horizontally... */
729 p00 = LIN(model->lon[ilon], p00, model->lon[ilon + 1], p10, lon);
730 p11 = LIN(model->lon[ilon], p01, model->lon[ilon + 1], p11, lon);
731 *p = LIN(model->lat[ilat], p00, model->lat[ilat + 1], p11, lat);
732
733 t00 = LIN(model->lon[ilon], t00, model->lon[ilon + 1], t10, lon);
734 t11 = LIN(model->lon[ilon], t01, model->lon[ilon + 1], t11, lon);
735 *t = LIN(model->lat[ilat], t00, model->lat[ilat + 1], t11, lat);
736}
#define NZ
Maximum number of model levels.
Definition: issifm.c:33
double lat[NLAT]
Latitude [deg].
Definition: issifm.c:61
float t[NLON][NLAT][NZ]
Temperature [K].
Definition: issifm.c:70
double lon[NLON]
Longitude [deg].
Definition: issifm.c:58
int nz
Number of vertical levels.
Definition: issifm.c:49
float z[NLON][NLAT][NZ]
Height [km].
Definition: issifm.c:73
int nlon
Number of longitudes.
Definition: issifm.c:52
int nlat
Number of latitudes.
Definition: issifm.c:55
float p[NLON][NLAT][NZ]
Pressure [hPa].
Definition: issifm.c:67

◆ smooth()

void smooth ( model_t model)

Smoothing of model data.

Definition at line 740 of file issifm.c.

741 {
742
743 static float hp[NLON][NLAT], ht[NLON][NLAT], hz[NLON][NLAT];
744
745 static double wx[10], wy[10];
746
747 const int dlon = 3, dlat = 3;
748
749 /* Set weights... */
750 const double dy = RE * M_PI / 180. * fabs(model->lat[1] - model->lat[0]);
751 for (int ilat = 0; ilat <= dlat; ilat++)
752 wy[ilat] = exp(-0.5 * POW2(ilat * dy * 2.35482 / 20.));
753
754 /* Loop over height levels... */
755 for (int iz = 0; iz < model->nz; iz++) {
756
757 /* Write info... */
758 printf("Smoothing level %d / %d ...\n", iz + 1, model->nz);
759
760 /* Copy data... */
761 for (int ilon = 0; ilon < model->nlon; ilon++)
762 for (int ilat = 0; ilat < model->nlat; ilat++) {
763 hp[ilon][ilat] = model->p[ilon][ilat][iz];
764 ht[ilon][ilat] = model->t[ilon][ilat][iz];
765 hz[ilon][ilat] = model->z[ilon][ilat][iz];
766 }
767
768 /* Loop over latitudes... */
769 for (int ilat = 0; ilat < model->nlat; ilat++) {
770
771 /* Set weights... */
772 const double dx =
773 RE * M_PI / 180. * cos(model->lat[ilat] * M_PI / 180.) *
774 fabs(model->lon[1] - model->lon[0]);
775 for (int ilon = 0; ilon <= dlon; ilon++)
776 wx[ilon] = exp(-0.5 * POW2(ilon * dx * 2.35482 / 20.));
777
778 /* Loop over longitudes... */
779 for (int ilon = 0; ilon < model->nlon; ilon++) {
780 float wsum = 0;
781 model->p[ilon][ilat][iz] = 0;
782 model->t[ilon][ilat][iz] = 0;
783 model->z[ilon][ilat][iz] = 0;
784 for (int ilon2 = GSL_MAX(ilon - dlon, 0);
785 ilon2 <= GSL_MIN(ilon + dlon, model->nlon - 1); ilon2++)
786 for (int ilat2 = GSL_MAX(ilat - dlat, 0);
787 ilat2 <= GSL_MIN(ilat + dlat, model->nlat - 1); ilat2++) {
788 float w = (float) (wx[abs(ilon2 - ilon)] * wy[abs(ilat2 - ilat)]);
789 model->p[ilon][ilat][iz] += w * hp[ilon2][ilat2];
790 model->t[ilon][ilat][iz] += w * ht[ilon2][ilat2];
791 model->z[ilon][ilat][iz] += w * hz[ilon2][ilat2];
792 wsum += w;
793 }
794 model->p[ilon][ilat][iz] /= wsum;
795 model->t[ilon][ilat][iz] /= wsum;
796 model->z[ilon][ilat][iz] /= wsum;
797 }
798 }
799 }
800}
#define NLAT
Maximum number of model latitudes.
Definition: issifm.c:39
#define NLON
Maximum number of model longitudes.
Definition: issifm.c:36

◆ write_nc()

void write_nc ( char *  filename,
wave_t wave 
)

Write wave struct to netCDF file.

Definition at line 804 of file issifm.c.

806 {
807
808 static double help[WX * WY];
809
810 int ncid, dimid[10], lon_id, lat_id, bt_id, pt_id, var_id;
811
812 /* Create netCDF file... */
813 NC(nc_create(filename, NC_CLOBBER, &ncid));
814
815 /* Set dimensions... */
816 NC(nc_def_dim(ncid, "NTRACK", (size_t) wave->ny, &dimid[0]));
817 NC(nc_def_dim(ncid, "NXTRACK", (size_t) wave->nx, &dimid[1]));
818
819 /* Add variables... */
820 NC(nc_def_var(ncid, "lon", NC_DOUBLE, 2, dimid, &lon_id));
821 add_att(ncid, lon_id, "deg", "footprint longitude");
822 NC(nc_def_var(ncid, "lat", NC_DOUBLE, 2, dimid, &lat_id));
823 add_att(ncid, lat_id, "deg", "footprint latitude");
824 NC(nc_def_var(ncid, "bt", NC_FLOAT, 2, dimid, &bt_id));
825 add_att(ncid, bt_id, "K", "brightness temperature");
826 NC(nc_def_var(ncid, "bt_pt", NC_FLOAT, 2, dimid, &pt_id));
827 add_att(ncid, pt_id, "K", "brightness temperature perturbation");
828 NC(nc_def_var(ncid, "bt_var", NC_FLOAT, 2, dimid, &var_id));
829 add_att(ncid, var_id, "K^2", "brightness temperature variance");
830
831 /* Leave define mode... */
832 NC(nc_enddef(ncid));
833
834 /* Write data... */
835 for (int ix = 0; ix < wave->nx; ix++)
836 for (int iy = 0; iy < wave->ny; iy++)
837 help[iy * wave->nx + ix] = wave->lon[ix][iy];
838 NC(nc_put_var_double(ncid, lon_id, help));
839 for (int ix = 0; ix < wave->nx; ix++)
840 for (int iy = 0; iy < wave->ny; iy++)
841 help[iy * wave->nx + ix] = wave->lat[ix][iy];
842 NC(nc_put_var_double(ncid, lat_id, help));
843 for (int ix = 0; ix < wave->nx; ix++)
844 for (int iy = 0; iy < wave->ny; iy++)
845 help[iy * wave->nx + ix] = wave->temp[ix][iy];
846 NC(nc_put_var_double(ncid, bt_id, help));
847 for (int ix = 0; ix < wave->nx; ix++)
848 for (int iy = 0; iy < wave->ny; iy++)
849 help[iy * wave->nx + ix] = wave->pt[ix][iy];
850 NC(nc_put_var_double(ncid, pt_id, help));
851 for (int ix = 0; ix < wave->nx; ix++)
852 for (int iy = 0; iy < wave->ny; iy++)
853 help[iy * wave->nx + ix] = wave->var[ix][iy];
854 NC(nc_put_var_double(ncid, var_id, help));
855
856 /* Close file... */
857 NC(nc_close(ncid));
858}
#define NC(cmd)
Execute netCDF library command and check result.
Definition: diff_apr.c:35
void add_att(int ncid, int varid, const char *unit, const char *long_name)
Add variable attributes to netCDF file.
Definition: libairs.c:30
#define WX
Across-track size of wave analysis data.
Definition: libairs.h:129
#define WY
Along-track size of wave analysis data.
Definition: libairs.h:132
int nx
Number of across-track values.
Definition: libairs.h:290
int ny
Number of along-track values.
Definition: libairs.h:293
double var[WX][WY]
Variance [K].
Definition: libairs.h:323
double temp[WX][WY]
Temperature [K].
Definition: libairs.h:314
double lon[WX][WY]
Longitude [deg].
Definition: libairs.h:302
double lat[WX][WY]
Latitude [deg].
Definition: libairs.h:305
double pt[WX][WY]
Perturbation [K].
Definition: libairs.h:320
Here is the call graph for this function:

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 103 of file issifm.c.

105 {
106
107 static ctl_t ctl;
108
109 static char kernel[LEN], pertname[LEN];
110
111 const double var_dh = 100.;
112
113 static double xo[3], xs[3], xm[3], hyam[NZ], hybm[NZ], kz[NSHAPE],
114 kw[NSHAPE], wsum;
115
116 static float *help;
117
118 static int init, ncid, dimid, varid, track0, track1, nk;
119
120 static size_t rs;
121
122 atm_t *atm;
123
124 obs_t *obs;
125
126 pert_t *pert;
127
128 wave_t *wave;
129
130 model_t *model;
131
132 /* ------------------------------------------------------------
133 Get control parameters...
134 ------------------------------------------------------------ */
135
136 /* Check arguments... */
137 if (argc < 8)
138 ERRMSG("Give parameters: <ctl> <model> <model.nc> <pert.nc>"
139 " <wave_airs.tab> <wave_model.tab> <wave_airs.nc> <wave_model.nc>");
140
141 /* Read control parameters... */
142 read_ctl(argc, argv, &ctl);
143 scan_ctl(argc, argv, "PERTNAME", -1, "4mu", pertname);
144 scan_ctl(argc, argv, "KERNEL", -1, "-", kernel);
145 const int extpol = (int) scan_ctl(argc, argv, "EXTPOL", -1, "0", NULL);
146 const int slant = (int) scan_ctl(argc, argv, "SLANT", -1, "1", NULL);
147 const double t_ovp = scan_ctl(argc, argv, "T_OVP", -1, "", NULL);
148
149 /* Set control parameters... */
150 ctl.write_bbt = 1;
151
152 /* Initialize look-up tables... */
153 tbl_t *tbl = read_tbl(&ctl);
154
155 /* ------------------------------------------------------------
156 Read model data...
157 ------------------------------------------------------------ */
158
159 /* Allocate... */
160 ALLOC(model, model_t, 1);
161 ALLOC(help, float,
162 NLON * NLAT * NZ);
163
164 /* Open file... */
165 printf("Read %s data: %s\n", argv[2], argv[3]);
166 NC(nc_open(argv[3], NC_NOWRITE, &ncid));
167
168 /* Check time... */
169 LOG(2, "Check time...");
170 if (nc_inq_dimid(ncid, "time", &dimid) != NC_NOERR)
171 NC(nc_inq_dimid(ncid, "time", &dimid));
172 NC(nc_inq_dimlen(ncid, dimid, &rs));
173 if (rs != 1)
174 ERRMSG("Only one time step is allowed!");
175
176 /* Read latitudes... */
177 LOG(2, "Read latitudes...");
178 if (nc_inq_dimid(ncid, "lat", &dimid) != NC_NOERR)
179 NC(nc_inq_dimid(ncid, "latitude", &dimid));
180 NC(nc_inq_dimlen(ncid, dimid, &rs));
181 model->nlat = (int) rs;
182 if (model->nlat > NLAT)
183 ERRMSG("Too many latitudes!");
184 if (nc_inq_varid(ncid, "lat", &varid) != NC_NOERR)
185 NC(nc_inq_varid(ncid, "latitude", &varid));
186 NC(nc_get_var_double(ncid, varid, model->lat));
187
188 /* Read longitudes... */
189 LOG(2, "Read longitudes...");
190 if (nc_inq_dimid(ncid, "lon", &dimid) != NC_NOERR)
191 NC(nc_inq_dimid(ncid, "longitude", &dimid));
192 NC(nc_inq_dimlen(ncid, dimid, &rs));
193 model->nlon = (int) rs;
194 if (model->nlon > NLON)
195 ERRMSG("Too many longitudes!");
196 if (nc_inq_varid(ncid, "lon", &varid))
197 NC(nc_inq_varid(ncid, "longitude", &varid));
198 NC(nc_get_var_double(ncid, varid, model->lon));
199
200 /* Read ICON data... */
201 if (strcasecmp(argv[2], "icon") == 0) {
202
203 /* Get height levels... */
204 LOG(2, "Read levels...");
205 NC(nc_inq_dimid(ncid, "height", &dimid));
206 NC(nc_inq_dimlen(ncid, dimid, &rs));
207 model->nz = (int) rs;
208 if (model->nz > NZ)
209 ERRMSG("Too many altitudes!");
210
211 /* Read height... */
212 LOG(2, "Read height...");
213 NC(nc_inq_varid(ncid, "z_mc", &varid));
214 NC(nc_get_var_float(ncid, varid, help));
215 for (int ilon = 0; ilon < model->nlon; ilon++)
216 for (int ilat = 0; ilat < model->nlat; ilat++)
217 for (int iz = 0; iz < model->nz; iz++)
218 model->z[ilon][ilat][iz] =
219 (float) (help[(iz * model->nlat + ilat) * model->nlon + ilon] /
220 1e3);
221
222 /* Read temperature... */
223 LOG(2, "Read temperature...");
224 NC(nc_inq_varid(ncid, "temp", &varid));
225 NC(nc_get_var_float(ncid, varid, help));
226 for (int ilon = 0; ilon < model->nlon; ilon++)
227 for (int ilat = 0; ilat < model->nlat; ilat++)
228 for (int iz = 0; iz < model->nz; iz++)
229 model->t[ilon][ilat][iz] =
230 help[(iz * model->nlat + ilat) * model->nlon + ilon];
231
232 /* Read pressure... */
233 LOG(2, "Read pressure...");
234 NC(nc_inq_varid(ncid, "pres", &varid));
235 NC(nc_get_var_float(ncid, varid, help));
236 for (int ilon = 0; ilon < model->nlon; ilon++)
237 for (int ilat = 0; ilat < model->nlat; ilat++)
238 for (int iz = 0; iz < model->nz; iz++)
239 model->p[ilon][ilat][iz] =
240 (float) (help[(iz * model->nlat + ilat) * model->nlon + ilon] /
241 1e2);
242 }
243
244 /* Read IFS data... */
245 else if (strcasecmp(argv[2], "ifs") == 0) {
246
247 /* Get height levels... */
248 LOG(2, "Read levels...");
249 NC(nc_inq_dimid(ncid, "lev_2", &dimid));
250 NC(nc_inq_dimlen(ncid, dimid, &rs));
251 model->nz = (int) rs;
252 if (model->nz > NZ)
253 ERRMSG("Too many altitudes!");
254
255 /* Read height... */
256 LOG(2, "Read height...");
257 NC(nc_inq_varid(ncid, "gh", &varid));
258 NC(nc_get_var_float(ncid, varid, help));
259 for (int ilon = 0; ilon < model->nlon; ilon++)
260 for (int ilat = 0; ilat < model->nlat; ilat++)
261 for (int iz = 0; iz < model->nz; iz++)
262 model->z[ilon][ilat][iz] =
263 (float) (help[(iz * model->nlat + ilat) * model->nlon + ilon] /
264 1e3);
265
266 /* Read temperature... */
267 LOG(2, "Read temperature...");
268 NC(nc_inq_varid(ncid, "t", &varid));
269 NC(nc_get_var_float(ncid, varid, help));
270 for (int ilon = 0; ilon < model->nlon; ilon++)
271 for (int ilat = 0; ilat < model->nlat; ilat++)
272 for (int iz = 0; iz < model->nz; iz++)
273 model->t[ilon][ilat][iz] =
274 help[(iz * model->nlat + ilat) * model->nlon + ilon];
275
276 /* Read surface pressure... */
277 LOG(2, "Read surface pressure...");
278 NC(nc_inq_varid(ncid, "lnsp", &varid));
279 NC(nc_get_var_float(ncid, varid, help));
280 for (int ilon = 0; ilon < model->nlon; ilon++)
281 for (int ilat = 0; ilat < model->nlat; ilat++)
282 model->ps[ilon][ilat] = (float) exp(help[ilat * model->nlon + ilon]);
283
284 /* Read grid coefficients... */
285 LOG(2, "Read grid coefficients...");
286 NC(nc_inq_varid(ncid, "hyam", &varid));
287 NC(nc_get_var_double(ncid, varid, hyam));
288 NC(nc_inq_varid(ncid, "hybm", &varid));
289 NC(nc_get_var_double(ncid, varid, hybm));
290
291 /* Calculate pressure... */
292 LOG(2, "Calculate pressure...");
293 for (int ilon = 0; ilon < model->nlon; ilon++)
294 for (int ilat = 0; ilat < model->nlat; ilat++)
295 for (int iz = 0; iz < model->nz; iz++)
296 model->p[ilon][ilat][iz]
297 = (float) ((hyam[iz] + hybm[iz] * model->ps[ilon][ilat]) / 100.);
298 }
299
300 /* Read UM data... */
301 else if (strcasecmp(argv[2], "um") == 0) {
302
303 /* Get height levels... */
304 LOG(2, "Read levels...");
305 if (nc_inq_dimid(ncid, "RHO_TOP_eta_rho", &dimid) != NC_NOERR)
306 NC(nc_inq_dimid(ncid, "RHO_eta_rho", &dimid));
307 NC(nc_inq_dimlen(ncid, dimid, &rs));
308 model->nz = (int) rs;
309 if (model->nz > NZ)
310 ERRMSG("Too many altitudes!");
311
312 /* Read height... */
313 LOG(2, "Read height...");
314 if (nc_inq_varid(ncid, "STASH_m01s15i102_2", &varid) != NC_NOERR)
315 NC(nc_inq_varid(ncid, "STASH_m01s15i102", &varid));
316 NC(nc_get_var_float(ncid, varid, help));
317 for (int ilon = 0; ilon < model->nlon; ilon++)
318 for (int ilat = 0; ilat < model->nlat; ilat++)
319 for (int iz = 0; iz < model->nz; iz++)
320 model->z[ilon][ilat][iz] =
321 (float) (help[(iz * model->nlat + ilat) * model->nlon + ilon] /
322 1e3);
323
324 /* Read temperature... */
325 LOG(2, "Read temperature...");
326 NC(nc_inq_varid(ncid, "STASH_m01s30i004", &varid));
327 NC(nc_get_var_float(ncid, varid, help));
328 for (int ilon = 0; ilon < model->nlon; ilon++)
329 for (int ilat = 0; ilat < model->nlat; ilat++)
330 for (int iz = 0; iz < model->nz; iz++)
331 model->t[ilon][ilat][iz] =
332 help[(iz * model->nlat + ilat) * model->nlon + ilon];
333
334 /* Read pressure... */
335 LOG(2, "Read pressure...");
336 NC(nc_inq_varid(ncid, "STASH_m01s00i407", &varid));
337 NC(nc_get_var_float(ncid, varid, help));
338 for (int ilon = 0; ilon < model->nlon; ilon++)
339 for (int ilat = 0; ilat < model->nlat; ilat++)
340 for (int iz = 0; iz < model->nz; iz++)
341 model->p[ilon][ilat][iz] =
342 0.01f * help[(iz * model->nlat + ilat) * model->nlon + ilon];
343 }
344
345 /* Read WRF data... */
346 else if (strcasecmp(argv[2], "wrf") == 0) {
347
348 /* Get height levels... */
349 LOG(2, "Read levels...");
350 NC(nc_inq_dimid(ncid, "bottom_top", &dimid));
351 NC(nc_inq_dimlen(ncid, dimid, &rs));
352 model->nz = (int) rs;
353 if (model->nz > NZ)
354 ERRMSG("Too many altitudes!");
355
356 /* Read height... */
357 LOG(2, "Read height...");
358 NC(nc_inq_varid(ncid, "z", &varid));
359 NC(nc_get_var_float(ncid, varid, help));
360 for (int ilon = 0; ilon < model->nlon; ilon++)
361 for (int ilat = 0; ilat < model->nlat; ilat++)
362 for (int iz = 0; iz < model->nz; iz++)
363 model->z[ilon][ilat][iz] =
364 (float) (help[(iz * model->nlat + ilat) * model->nlon + ilon] /
365 1e3);
366
367 /* Read temperature... */
368 LOG(2, "Read temperature...");
369 NC(nc_inq_varid(ncid, "tk", &varid));
370 NC(nc_get_var_float(ncid, varid, help));
371 for (int ilon = 0; ilon < model->nlon; ilon++)
372 for (int ilat = 0; ilat < model->nlat; ilat++)
373 for (int iz = 0; iz < model->nz; iz++)
374 model->t[ilon][ilat][iz] =
375 help[(iz * model->nlat + ilat) * model->nlon + ilon];
376
377 /* Read pressure... */
378 LOG(2, "Read pressure...");
379 NC(nc_inq_varid(ncid, "p", &varid));
380 NC(nc_get_var_float(ncid, varid, help));
381 for (int ilon = 0; ilon < model->nlon; ilon++)
382 for (int ilat = 0; ilat < model->nlat; ilat++)
383 for (int iz = 0; iz < model->nz; iz++)
384 model->p[ilon][ilat][iz] =
385 (float) (help[(iz * model->nlat + ilat) * model->nlon + ilon] /
386 1e2);
387 }
388
389 else
390 ERRMSG("Model type not supported!");
391
392 /* Close file... */
393 NC(nc_close(ncid));
394
395 /* Free... */
396 free(help);
397
398 /* Check data... */
399 LOG(2, "Checking...");
400 for (int ilon = 0; ilon < model->nlon; ilon++)
401 for (int ilat = 0; ilat < model->nlat; ilat++)
402 for (int iz = 0; iz < model->nz; iz++)
403 if (model->t[ilon][ilat][iz] <= 100
404 || model->t[ilon][ilat][iz] >= 400) {
405 model->p[ilon][ilat][iz] = GSL_NAN;
406 model->t[ilon][ilat][iz] = GSL_NAN;
407 model->z[ilon][ilat][iz] = GSL_NAN;
408 }
409
410 /* Smoothing of model data... */
411 LOG(2, "Smoothing...");
412 smooth(model);
413
414 /* Write info... */
415 for (int iz = 0; iz < model->nz; iz++)
416 printf("section_height: %d %g %g %g %g %g\n", iz,
417 model->z[model->nlon / 2][model->nlat / 2][iz],
418 model->lon[model->nlon / 2], model->lat[model->nlat / 2],
419 model->p[model->nlon / 2][model->nlat / 2][iz],
420 model->t[model->nlon / 2][model->nlat / 2][iz]);
421 for (int ilon = 0; ilon < model->nlon; ilon++)
422 printf("section_west_east: %d %g %g %g %g %g\n", ilon,
423 model->z[ilon][model->nlat / 2][model->nz / 2],
424 model->lon[ilon], model->lat[model->nlat / 2],
425 model->p[ilon][model->nlat / 2][model->nz / 2],
426 model->t[ilon][model->nlat / 2][model->nz / 2]);
427 for (int ilat = 0; ilat < model->nlat; ilat++)
428 printf("section_north_south: %d %g %g %g %g %g\n", ilat,
429 model->z[model->nlon / 2][ilat][model->nz / 2],
430 model->lon[model->nlon / 2], model->lat[ilat],
431 model->p[model->nlon / 2][ilat][model->nz / 2],
432 model->t[model->nlon / 2][ilat][model->nz / 2]);
433
434 /* ------------------------------------------------------------
435 Read AIRS perturbation data...
436 ------------------------------------------------------------ */
437
438 /* Allocate... */
439 ALLOC(atm, atm_t, 1);
440 ALLOC(obs, obs_t, 1);
441 ALLOC(pert, pert_t, 1);
442 ALLOC(wave, wave_t, 1);
443
444 /* Read perturbation data... */
445 read_pert(argv[4], pertname, pert);
446
447 /* Find track range... */
448 for (int itrack = 0; itrack < pert->ntrack; itrack++) {
449 if (pert->time[itrack][44] < t_ovp - 720 || itrack == 0)
450 track0 = itrack;
451 track1 = itrack;
452 if (pert->time[itrack][44] > t_ovp + 720)
453 break;
454 }
455
456 /* Convert to wave analysis struct... */
457 pert2wave(pert, wave, track0, track1, 0, pert->nxtrack - 1);
458
459 /* Estimate background... */
460 background_poly(wave, 5, 0);
461
462 /* Compute variance... */
463 variance(wave, var_dh);
464
465 /* Write observation wave struct... */
466 write_wave(argv[5], wave);
467 write_nc(argv[7], wave);
468
469 /* ------------------------------------------------------------
470 Run forward model...
471 ------------------------------------------------------------ */
472
473 /* Loop over AIRS geolocations... */
474 for (int itrack = track0; itrack <= track1; itrack++)
475 for (int ixtrack = 0; ixtrack < pert->nxtrack; ixtrack++) {
476
477 /* Write info... */
478 if (ixtrack == 0)
479 printf("Compute track %d / %d ...\n", itrack - track0 + 1,
480 track1 - track0 + 1);
481
482 /* Set observation data... */
483 obs->nr = 1;
484 obs->obsz[0] = 705;
485 obs->obslon[0] = pert->lon[itrack][44];
486 obs->obslat[0] = pert->lat[itrack][44];
487 obs->vpz[0] = 0;
488 obs->vplon[0] = pert->lon[itrack][ixtrack];
489 obs->vplat[0] = pert->lat[itrack][ixtrack];
490
491 /* Get Cartesian coordinates... */
492 geo2cart(obs->obsz[0], obs->obslon[0], obs->obslat[0], xo);
493 geo2cart(obs->vpz[0], obs->vplon[0], obs->vplat[0], xs);
494
495 /* Set profile for atmospheric data... */
496 if (slant) {
497 atm->np = 0;
498 for (double f = 0.0; f <= 1.0; f += 0.0002) {
499 xm[0] = f * xo[0] + (1 - f) * xs[0];
500 xm[1] = f * xo[1] + (1 - f) * xs[1];
501 xm[2] = f * xo[2] + (1 - f) * xs[2];
502 cart2geo(xm, &atm->z[atm->np], &atm->lon[atm->np],
503 &atm->lat[atm->np]);
504 atm->time[atm->np] = pert->time[itrack][ixtrack];
505 if (atm->z[atm->np] < 10)
506 continue;
507 else if (atm->z[atm->np] > 90)
508 break;
509 else if ((++atm->np) >= NP)
510 ERRMSG("Too many ray path data points!");
511 }
512 } else {
513 atm->np = 0;
514 for (double f = 10.0; f <= 90.0; f += 0.2) {
515 atm->time[atm->np] = pert->time[itrack][ixtrack];
516 atm->z[atm->np] = f;
517 atm->lon[atm->np] = pert->lon[itrack][ixtrack];
518 atm->lat[atm->np] = pert->lat[itrack][ixtrack];
519 if ((++atm->np) >= NP)
520 ERRMSG("Too many ray path data points!");
521 }
522 }
523
524 /* Initialize with climatological data... */
525 climatology(&ctl, atm);
526
527 /* Interpolate model data... */
528 for (int ip = 0; ip < atm->np; ip++)
529 intpol(model, atm->z[ip], atm->lon[ip], atm->lat[ip],
530 &atm->p[ip], &atm->t[ip]);
531
532 /* Check profile... */
533 int okay = 1;
534 for (int ip = 0; ip < atm->np; ip++)
535 if (!gsl_finite(atm->p[ip]) || !gsl_finite(atm->t[ip]))
536 okay = 0;
537 if (!okay)
538 pert->bt[itrack][ixtrack] = GSL_NAN;
539 else {
540
541 /* Use kernel function... */
542 if (kernel[0] != '-') {
543
544 /* Read kernel function... */
545 if (!init) {
546 init = 1;
547 read_shape(kernel, kz, kw, &nk);
548 if (kz[0] > kz[1])
549 ERRMSG("Kernel function must be ascending!");
550 }
551
552 /* Calculate mean temperature... */
553 pert->bt[itrack][ixtrack] = wsum = 0;
554 for (int ip = 0; ip < atm->np; ip++)
555 if (atm->z[ip] >= kz[0] && atm->z[ip] <= kz[nk - 1]) {
556 const int iz = locate_irr(kz, nk, atm->z[ip]);
557 const double w =
558 LIN(kz[iz], kw[iz], kz[iz + 1], kw[iz + 1], atm->z[ip]);
559 pert->bt[itrack][ixtrack] += w * atm->t[ip];
560 wsum += w;
561 }
562 pert->bt[itrack][ixtrack] /= wsum;
563 }
564
565 /* Use radiative transfer model... */
566 else {
567
568 /* Run forward model... */
569 formod(&ctl, tbl, atm, obs);
570
571 /* Get mean brightness temperature... */
572 pert->bt[itrack][ixtrack] = 0;
573 for (int id = 0; id < ctl.nd; id++)
574 pert->bt[itrack][ixtrack] += obs->rad[id][0] / ctl.nd;
575 }
576 }
577 }
578
579 /* Extrapolate... */
580 if (extpol)
581 for (int itrack = track0; itrack <= track1; itrack++) {
582 for (int ixtrack = 1; ixtrack < pert->nxtrack; ixtrack++)
583 if (!gsl_finite(pert->bt[itrack][ixtrack]))
584 pert->bt[itrack][ixtrack] = pert->bt[itrack][ixtrack - 1];
585 for (int ixtrack = pert->nxtrack - 2; ixtrack >= 0; ixtrack--)
586 if (!gsl_finite(pert->bt[itrack][ixtrack]))
587 pert->bt[itrack][ixtrack] = pert->bt[itrack][ixtrack + 1];
588 }
589
590 /* ------------------------------------------------------------
591 Write model perturbations...
592 ------------------------------------------------------------ */
593
594 /* Convert to wave analysis struct... */
595 pert2wave(pert, wave, track0, track1, 0, pert->nxtrack - 1);
596
597 /* Estimate background... */
598 background_poly(wave, 5, 0);
599
600 /* Compute variance... */
601 variance(wave, var_dh);
602
603 /* Write observation wave struct... */
604 write_wave(argv[6], wave);
605 write_nc(argv[8], wave);
606
607 /* Free... */
608 free(atm);
609 free(obs);
610 free(pert);
611 free(wave);
612 free(tbl);
613
614 return EXIT_SUCCESS;
615}
void intpol(model_t *model, double z, double lon, double lat, double *p, double *t)
Interpolation of model data.
Definition: issifm.c:619
void write_nc(char *filename, wave_t *wave)
Write wave struct to netCDF file.
Definition: issifm.c:804
void smooth(model_t *model)
Smoothing of model data.
Definition: issifm.c:740
void background_poly(wave_t *wave, int dim_x, int dim_y)
Get background based on polynomial fits.
Definition: libairs.c:126
void variance(wave_t *wave, double dh)
Compute local variance.
Definition: libairs.c:1584
void pert2wave(pert_t *pert, wave_t *wave, int track0, int track1, int xtrack0, int xtrack1)
Convert radiance perturbation data to wave analysis struct.
Definition: libairs.c:999
void read_pert(char *filename, char *pertname, pert_t *pert)
Read radiance perturbation data.
Definition: libairs.c:1137
void write_wave(char *filename, wave_t *wave)
Write wave analysis data.
Definition: libairs.c:1741
Model data.
Definition: issifm.c:46
float ps[NLON][NLAT]
Surface pressure [hPa].
Definition: issifm.c:64
Perturbation data.
Definition: libairs.h:205
double time[PERT_NTRACK][PERT_NXTRACK]
Time (seconds since 2000-01-01T00:00Z).
Definition: libairs.h:214
int ntrack
Number of along-track values.
Definition: libairs.h:208
int nxtrack
Number of across-track values.
Definition: libairs.h:211
double lon[PERT_NTRACK][PERT_NXTRACK]
Longitude [deg].
Definition: libairs.h:217
double bt[PERT_NTRACK][PERT_NXTRACK]
Brightness temperature (4 or 15 micron) [K].
Definition: libairs.h:226
double lat[PERT_NTRACK][PERT_NXTRACK]
Latitude [deg].
Definition: libairs.h:220
Wave analysis data.
Definition: libairs.h:287
Here is the call graph for this function: