00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef ECMWFFILEDATA_H
00021 #define ECMWFFILEDATA_H
00022
00023 #include "gribfiledata.h"
00024 #include "meteofiledata.h"
00025 #include "interpolation.h"
00026 #include "earth_geometry.h"
00027
00033 class ECMWFFileData : public MeteoFileData, public GribFileData, public FileDataReader {
00034 protected:
00038 typedef enum {
00039 UNDEFINED = 0,
00040 ANALYSIS,
00041 FORECAST
00042 } ECMWFProductType;
00044 ECMWFProductType product_id;
00046 string version;
00048 int sz_x;
00050 int sz_y;
00052 float lat0;
00054 float lon0;
00055
00059 void set_time_coverage();
00064 void parse_filename(const string & short_filename);
00069 bool check_filename(const string & short_filename) const;
00073 void init_grid ();
00078 virtual void load_time_level() {;};
00079 public:
00081 static const unsigned short isobaric_level_pressures[];
00083 static const int nb_max_isobaric_level;
00087 static const double a_hybrid_91[92];
00088 static const double b_hybrid_91[92];
00090 static const int nb_level_hybrid_91;
00096 ECMWFFileData(const string &name, const string &mode="r");
00100 ~ECMWFFileData();
00105 void free_geolocation_data() {;};
00116 inline const bool get_index(const float &lat, const float& lon, const double &time, int * indexes);
00125 inline const bool get_index(const float &lat, const float& lon, int * indexes);
00136 inline const bool get_index(const float &lat, const float& lon, const float &p_lvl, int * indexes) {
00137 UnimplementedMethod e(__FILE__,__LINE__,__PRETTY_FUNCTION__);
00138 throw e;
00139 };
00145 inline const int get_lat_index(const float &lat) const;
00151 inline const int get_lon_index(const float &lon) const;
00152
00158 inline const float32 get_lat (const int &i_y) const;
00164 inline const float32 get_lon (const int &i_x) const;
00175 void * read_data(void * data, const char * sds_name, int * start=NULL, int * stride=NULL, int *edges=NULL, int rank=-1) {
00176 return this->GribFileData::read_data(data, sds_name, start, stride, edges, rank);
00177 };
00182 ECMWFProductType get_product_id() const {
00183 return product_id;
00184 };
00189 const string get_s_product_id () const {
00190 string s_prod_id ("");
00191 switch (product_id) {
00192 case UNDEFINED:
00193 s_prod_id = "UNDEFINED";
00194 break;
00195 case ANALYSIS:
00196 s_prod_id = "ANALYSIS";
00197 break;
00198 case FORECAST:
00199 s_prod_id = "FORECAST";
00200 break;
00201 default :
00202 g_exception e(__FILE__ , __LINE__ , "Invalid product type ID " + s_prod_id);
00203 throw e;
00204 };
00205 return s_prod_id;
00206 };
00211 int get_sz_x() const {
00212 return sz_x;
00213 }
00218 int get_sz_y() const {
00219 return sz_y;
00220 }
00225 const string get_grid_desc ();
00231 const vector <int> get_pressure_levels(const string & var_name);
00237 const int get_nb_pressure_levels (const string & var_name);
00245 void get_hybrid_level_pressures(const double &p_surf,
00246 double * v_p_hybrid) const {
00247 for (int i = 0 ; i < nb_level_hybrid_91 ; ++i)
00248 v_p_hybrid[i] = get_hybrid_level_pressure (i, p_surf);
00249 };
00257 const double get_hybrid_level_pressure (const int i_level, const double &p_surf) const {
00258 if (i_level < 0 || i_level > nb_level_hybrid_91 ) {
00259 g_exception e(__FILE__ , __LINE__ , "Invalid hybrid level number " + MyTools::to_string(i_level) + " Must in range [0, 91]");
00260 throw e;
00261 }
00262
00263 return .5 * ((a_hybrid_91 [i_level] + a_hybrid_91 [i_level+1]) * 0.01 + (b_hybrid_91 [i_level] + b_hybrid_91 [i_level+1]) * p_surf);
00264 };
00269 static const unsigned short* get_isobaric_level_pressures() {
00270 return isobaric_level_pressures;
00271 }
00282 template <typename Txout, typename Tyout, typename Txin, typename Tyin>
00283 void get_v_pres_on_alt (
00284 Tyout * v_out_pres, const Txout * v_alt, const int sz_alt,
00285 const Txin * v_geop, const Tyin * v_inpres, const int n_pres,
00286 const string interp_type = "linear");
00297 template <typename Txout, typename Txin, typename Tyin>
00298 double get_pres_on_alt (
00299 const Txout alt,
00300 const Txin * v_ingeop, const Tyin * v_inpres, const int sz_inpres,
00301 const string interp_type = "linear");
00308 double alt_to_geop (const double & alt) {
00309 return alt * Earth::g0;
00310 };
00317 template <typename Txout, typename Tyout>
00318 void get_abscissa_iso (Tyout * v_out_abs, const Txout * v_out_pres, const int sz_out_pres);
00319
00328 template <typename Txout, typename Tyout, typename Txin>
00329 void get_abscissa_hybrid (Tyout * v_out_abs, const Txout * v_out_pres, const int sz_out_pres,
00330 const Txin * v_in_pres, const int sz_in_pres);
00331
00341 template <typename Txout, typename Tyout, typename Txin, typename Tyin>
00342 void interp_on_pres (Tyout * v_out_var, const Txout * v_out_abs, const int sz_out,
00343 const Tyin * v_in_var, const Txin * v_in_pres, const int sz_in);
00344
00346 void close_data_file();
00347 void open_data_file();
00348
00349
00350 int get_n_dataset();
00351 string get_dataset_name(int i);
00352 int get_dataset_data_type(string sds_name);
00353 string get_values_attr_dataset(string sds_name,string attr);
00354 bool has_attr_dataset(string sds_name,string attr);
00356 };
00357
00358 const int ECMWFFileData::get_lat_index(const float & lat) const {
00359 if (lat < -90. || lat > 90.) {
00360 g_exception e(__FILE__ , __LINE__ , "Invalid latitude " + MyTools::to_string(lat));
00361 throw e;
00362 }
00363 return MyTools::round<int>(fabs(lat - lat0) / delta_lat);
00364 }
00365
00366 const float32 ECMWFFileData::get_lat(const int & i_y) const {
00367 return lat0 - i_y * delta_lat;
00368 }
00369 const float32 ECMWFFileData::get_lon(const int & i_x) const {
00370 float32 lon = lon0 + i_x * delta_lon;
00371 if (lon > 180.)
00372 lon -= 360.;
00373 return lon;
00374 }
00375 const int ECMWFFileData::get_lon_index(const float & _lon) const {
00376 if (_lon < -180. || _lon > 180.) {
00377 g_exception e(__FILE__ , __LINE__ , "Invalid longitude " + MyTools::to_string(_lon));
00378 throw e;
00379 }
00380
00381 float lon (_lon);
00382 if (lon < 0.)
00383 lon = 360. + lon;
00384 int ilon = MyTools::round<int>((lon - lon0) / delta_lon);
00385
00386 if (ilon == sz_x)
00387 ilon = 0;
00388 return ilon;
00389 }
00390
00391 const bool ECMWFFileData::get_index(const float & lat, const float & lon, int * indexes) {
00392 indexes [0] = get_lat_index(lat);
00393 indexes [1] = get_lon_index(lon);
00394 return true;
00395 }
00396
00397 const bool ECMWFFileData::get_index(const float & lat, const float & lon, const double & time, int * indexes) {
00398 return get_index (lat, lon, indexes);
00399 }
00400
00401 template <typename Txout, typename Tyout, typename Txin, typename Tyin>
00402 void ECMWFFileData::get_v_pres_on_alt(
00403 Tyout * v_outpres, const Txout * v_alt, const int sz_alt,
00404 const Txin * v_ingeop, const Tyin * v_inpres, const int sz_inpres,
00405 const string interp_type) {
00406
00407 double nan = numeric_limits<double>::signaling_NaN();
00408
00409 if (interp_type == "linear" || interp_type == "linear_log") {
00410 for (int i = 0 ; i < sz_alt ; ++i)
00411 v_outpres [i] = get_pres_on_alt (v_alt[i], v_ingeop, v_inpres, sz_inpres, interp_type) ;
00412 } else if (interp_type == "spline") {
00413
00414 int sz_in = sz_inpres - 1;
00415 double x_in [sz_in];
00416 copy (v_ingeop, v_ingeop + sz_in, x_in);
00417 double y_in [sz_in];
00418 copy (v_inpres, v_inpres + sz_in, y_in);
00419 int sz_out = sz_alt;
00420 double x_out [sz_out];
00421 for (int i = 0 ; i < sz_out ; ++i)
00422 x_out[i] = alt_to_geop (v_alt[i] * 1000.);
00423 double y_out [sz_out];
00424
00425
00426 spline_interp (y_out, x_out, sz_out,
00427 y_in, x_in, sz_in, nan);
00428
00429 copy (y_out, y_out + sz_out, v_outpres);
00430
00431 } else {
00432 g_exception e(__FILE__ , __LINE__ , "Invalid interpolation type " + interp_type);
00433 throw e;
00434 }
00435 }
00436
00437 template <typename Txout, typename Txin, typename Tyin>
00438 double ECMWFFileData::get_pres_on_alt (
00439 const Txout alt,
00440 const Txin * v_ingeop, const Tyin * v_inpres, const int sz_inpres,
00441 const string interp_type) {
00442
00443 double outgeop = alt_to_geop (alt * 1000.);
00444
00445 double nan = numeric_limits<double>::signaling_NaN();
00446
00447 if (outgeop < v_ingeop[0] || outgeop > v_ingeop [sz_inpres - 2])
00448 return nan;
00449
00450 int i = 0;
00451 while ((i < (sz_inpres - 2)) && (outgeop > v_ingeop[i]))
00452 ++i;
00453
00454 if (i >= (sz_inpres - 1))
00455 return nan;
00456 else {
00457 double outpres = nan;
00458
00459 if (interp_type == "linear") {
00460 outpres = v_inpres[i - 1] + (outgeop - v_ingeop[i - 1]) * (v_inpres[i] - v_inpres[i - 1])/(v_ingeop[i] - v_ingeop[i - 1]);
00461 } else if (interp_type == "linear_log") {
00462 outpres = log(v_inpres[i - 1]) + (log(outgeop) - log(v_ingeop[i - 1])) * (log(v_inpres[i]) - log(v_inpres[i - 1]))/(log(v_ingeop[i]) - log(v_ingeop[i - 1]));
00463 outpres = exp(outpres);
00464 } else {
00465 g_exception e(__FILE__ , __LINE__ , "Invalid interpolation type " + interp_type);
00466 throw e;
00467 }
00468 if (outpres < 0)
00469 outpres = nan;
00470
00471 return outpres;
00472 }
00473 }
00474
00475 template <typename Txout, typename Tyout>
00476 void ECMWFFileData::get_abscissa_iso(Tyout * v_out_abs, const Txout * v_out_pres, const int sz_out) {
00477 MyTools::get_log_abscissa_sequential (v_out_abs, v_out_pres, sz_out, isobaric_level_pressures, nb_max_isobaric_level - 1);
00478 }
00479
00480 template <typename Txout, typename Tyout, typename Txin>
00481 void ECMWFFileData::get_abscissa_hybrid (Tyout * v_out_abs, const Txout * v_out_pres, const int sz_out, const Txin * v_in_pres, const int sz_in) {
00482 MyTools::get_log_abscissa_sequential (v_out_abs, v_out_pres, sz_out, v_in_pres, sz_in);
00483 }
00484
00485 template <typename Txout, typename Tyout, typename Txin, typename Tyin>
00486 void ECMWFFileData::interp_on_pres(Tyout * v_out_var, const Txout * v_out_abs, const int sz_out, const Tyin * v_in_var, const Txin * v_in_pres, const int sz_in) {
00487
00488 Tyout nan = numeric_limits<Tyout>::signaling_NaN();
00489 int i1, i2;
00490 double y1, y2;
00491 double abs;
00492 for (int i = 0 ; i < sz_out ; ++i) {
00493 abs = v_out_abs [i];
00494 if (isnan(abs))
00495 v_out_var [i] = nan;
00496 else {
00497 i1 = long(floor(abs));
00498 i2 = i1 + 1;
00499 y1 = v_in_var [i1];
00500 y2 = v_in_var [i2];
00501 v_out_var [i] = y1 + (abs - i1) * (y2 - y1);
00502 }
00503 }
00504 }
00505
00506 #endif