161 {
162
163 static ctl_t ctl;
164 static atm_t atm_apr, atm_clim, atm_i;
165 static obs_t obs_i, obs_meas;
167 static ret_t ret;
168
169 static FILE *in, *out;
170
171 static char filename[LEN], filename2[2 * LEN];
172
174 z[NP];
175
176 static int channel[ND], n, ntask = -1, rank, size;
177
178
179
180
181
182
183 MPI_Init(&argc, &argv);
184 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
185 MPI_Comm_size(MPI_COMM_WORLD, &size);
186
187
188 TIMER("total", 1);
189
190
191 if (argc < 3)
192 ERRMSG("Give parameters: <ctl> <filelist>");
193
194
195 read_ctl(argc, argv, &ctl);
196 read_ret(argc, argv, &ctl, &ret);
197
198
199 tbl_t *tbl = read_tbl(&ctl);
200
201
202 const int nz = (int) scan_ctl(argc, argv, "NZ", -1, "", NULL);
203 if (nz > NP)
204 ERRMSG("Too many altitudes!");
205 for (int iz = 0; iz < nz; iz++)
206 z[iz] = scan_ctl(argc, argv, "Z", iz, "", NULL);
207
208
209 const int track0 = (int) scan_ctl(argc, argv, "TRACK_MIN", -1, "0", NULL);
210 const int track1 = (int) scan_ctl(argc, argv, "TRACK_MAX", -1, "134", NULL);
211
212
213 const int xtrack0 = (int) scan_ctl(argc, argv, "XTRACK_MIN", -1, "0", NULL);
214 const int xtrack1 =
215 (int) scan_ctl(argc, argv, "XTRACK_MAX", -1, "89", NULL);
216
217
218 const double sx = scan_ctl(argc, argv, "SX", -1, "8", NULL);
219 const double sy = scan_ctl(argc, argv, "SY", -1, "2", NULL);
220
221
222
223
224
225
226 printf("Read filelist: %s\n", argv[2]);
227 if (!(in = fopen(argv[2], "r")))
228 ERRMSG("Cannot open filelist!");
229
230
231 while (fscanf(in, "%s", filename) != EOF) {
232
233
234 if ((++ntask) % size != rank)
235 continue;
236
237
238 printf("Retrieve file %s on rank %d of %d (with %d threads)...\n",
239 filename, rank + 1, size, omp_get_max_threads());
240
241
242
243
244
245
247
248
249 for (int id = 0; id < ctl.nd; id++) {
250 channel[id] = -999;
252 if (fabs(ctl.nu[
id] - ncd.
l1_nu[i]) < 0.1)
253 channel[id] = i;
254 if (channel[id] < 0)
255 ERRMSG("Cannot identify radiance channel!");
256 }
257
258
261
262
263 atm_clim.np = nz;
264 for (int iz = 0; iz < nz; iz++)
265 atm_clim.z[iz] = z[iz];
266 climatology(&ctl, &atm_clim);
267
268
269
270
271
272
273 for (int track = track0; track <= track1; track++) {
274
275
276 TIMER("retrieval", 1);
277
278
279 for (int xtrack = xtrack0; xtrack <= xtrack1; xtrack++) {
280
281
282 obs_meas.nr = 1;
283 obs_meas.time[0] = ncd.
l1_time[track][xtrack];
284 obs_meas.obsz[0] = ncd.
l1_sat_z[track];
287 obs_meas.vplon[0] = ncd.
l1_lon[track][xtrack];
288 obs_meas.vplat[0] = ncd.
l1_lat[track][xtrack];
289 for (int id = 0; id < ctl.nd; id++)
290 obs_meas.rad[
id][0] = ncd.
l1_rad[track][xtrack][channel[
id]];
291
292
293 for (int id = 0; id < ctl.nd; id++)
294 if (ctl.nu[id] >= 2000)
295 obs_meas.rad[id][0] = GSL_NAN;
296
297
298 copy_atm(&ctl, &atm_apr, &atm_clim, 0);
299 for (int ip = 0; ip < atm_apr.np; ip++) {
300 atm_apr.time[ip] = obs_meas.time[0];
301 atm_apr.lon[ip] = obs_meas.vplon[0];
302 atm_apr.lat[ip] = obs_meas.vplat[0];
303 }
304
305
306 init_l2(&ncd, track, xtrack, &ctl, &atm_apr);
307
308
309 optimal_estimation(&ret, &ctl, tbl, &obs_meas, &obs_i,
310 &atm_apr, &atm_i, &chisq[track][xtrack]);
311
312
313 for (int id = 0; id < ctl.nd; id++)
314 obs_meas.rad[id][0] = obs_i.rad[id][0]
315 = ncd.
l1_rad[track][xtrack][channel[
id]];
316 formod(&ctl, tbl, &atm_i, &obs_i);
317
318
319 n = 0;
320 ni[track][xtrack] = 0;
321 for (int id = 0; id < ctl.nd; id++)
322 if (ctl.nu[id] >= 2000 && gsl_finite(obs_meas.rad[id][0])) {
323 ni[track][xtrack] +=
324 (BRIGHT(obs_meas.rad[
id][0], ncd.
l1_nu[channel[
id]])
325 - BRIGHT(obs_i.rad[
id][0], ncd.
l1_nu[channel[
id]]));
326 n++;
327 }
328 ni[track][xtrack] /= n;
329 }
330
331
332 TIMER("retrieval", 3);
333 }
334
335
336
337
338
339
340 sprintf(filename2, "%s.nlte.tab", filename);
341
342
343 printf("Write non-LTE data: %s\n", filename2);
344 if (!(out = fopen(filename2, "w")))
345 ERRMSG("Cannot create file!");
346
347
348 fprintf(out,
349 "# $1 = time (seconds since 2000-01-01, 00:00 UTC)\n"
350 "# $2 = longitude [deg]\n"
351 "# $3 = latitude [deg]\n"
352 "# $4 = solar zenith angle [deg]\n"
353 "# $5 = non-LTE index [K]\n" "# $6 = chi^2 of retrieval fit\n");
354
355
356 for (int track = track0; track <= track1; track++) {
357 fprintf(out, "\n");
358 for (int xtrack = xtrack0; xtrack <= xtrack1; xtrack++)
359 fprintf(out,
"%.2f %g %g %g %g %g\n",ncd.
l1_time[track][xtrack],
361 RAD2DEG(acos(cos_sza(ncd.
l1_time[track][xtrack],
362 ncd.
l1_lon[track][xtrack],
363 ncd.
l1_lat[track][xtrack]))),
364 ni[track][xtrack], chisq[track][xtrack]);
365 }
366
367
368 fclose(out);
369
370
371 printf("Retrieval finished on rank %d of %d!\n", rank, size);
372 }
373
374
375 fclose(in);
376
377
378 free(tbl);
379
380
381 TIMER("total", 3);
382
383
384 printf("MEMORY_ATM = %g MByte\n", 4. * sizeof(atm_t) / 1024. / 1024.);
385 printf("MEMORY_CTL = %g MByte\n", 1. * sizeof(ctl_t) / 1024. / 1024.);
386 printf(
"MEMORY_NCD = %g MByte\n", 1. *
sizeof(
ncd_t) / 1024. / 1024.);
387 printf("MEMORY_OBS = %g MByte\n", 3. * sizeof(atm_t) / 1024. / 1024.);
388 printf("MEMORY_RET = %g MByte\n", 1. * sizeof(ret_t) / 1024. / 1024.);
389 printf("MEMORY_TBL = %g MByte\n", 1. * sizeof(tbl_t) / 1024. / 1024.);
390
391
392 printf("SIZE_TASKS = %d\n", size);
393 printf("SIZE_THREADS = %d\n", omp_get_max_threads());
394
395
396 MPI_Finalize();
397
398 return EXIT_SUCCESS;
399}
void fill_gaps(double x[L2_NTRACK][L2_NXTRACK][L2_NLAY], double cx, double cy)
Fill data gaps in L2 data.
#define L1_NXTRACK
Across-track size of AIRS radiance granule (don't change).
#define L1_NTRACK
Along-track size of AIRS radiance granule (don't change).
void read_nc(char *filename, ncd_t *ncd)
Read netCDF file.
#define L1_NCHAN
Number of AIRS radiance channels (don't change).
void init_l2(ncd_t *ncd, int track, int xtrack, ctl_t *ctl, atm_t *atm)
Initialize with AIRS Level-2 data.