• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

/home/pascal/depot/filedata/src/ecmwffiledata.h

00001 /***************************************************************************
00002  *   Copyright (C) 2005 by Nicolas PASCAL   *
00003  *   nicolas.pascal@icare.univ-lille1.fr   *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
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 // cout << "i_level=" << i_level << " a=[" << a_hybrid_91 [i_level] << "," << a_hybrid_91 [i_level+1] << "] b=[" << b_hybrid_91 [i_level] << "," << b_hybrid_91 [i_level+1] << "] psurf=" << p_surf << " -> " << .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) << endl;
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 //     vector<int> get_dataset_dimension(const string &sds_name);
00349 //     void get_dataset_fill_value(const string &name,void *fillvalue);
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     // longitudes as [-180, 180] -> [0, 360[
00381     float lon (_lon);
00382     if (lon < 0.)
00383         lon = 360. + lon;
00384     int ilon = MyTools::round<int>((lon - lon0) / delta_lon);
00385     // treat extreme case of longitudes in range [-delta_lon/2, 0]
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     // extrapolation forbidden -> NaN returned if out of range
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         // computations made in double. Last geopotential is ignored because set on a virtual pressure of 0 hPa. This is the reason of the "- 1" in size of the input pressures vector
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.); // * 1000 : km -> m;
00423         double y_out [sz_out];
00424         // compute spline interp
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     // geopotential of searched altitude
00443     double outgeop = alt_to_geop (alt * 1000.); // * 1000 : km -> m;
00444     // extrapolation forbidden -> NaN returned if out of range
00445     double nan = numeric_limits<double>::signaling_NaN();
00446     // last geopotential is ignored because set on a virtual pressure of 0 hPa -> -2
00447     if (outgeop < v_ingeop[0] || outgeop > v_ingeop [sz_inpres - 2])
00448         return nan;
00449     // process to linear interpolation of pressure
00450     int i = 0;
00451     while ((i < (sz_inpres - 2)) && (outgeop > v_ingeop[i]))
00452         ++i;
00453 //     if (i >= (sz_inpres - 2))
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 // cout << alt << " " << outgeop << " v_ingeop=[" << v_ingeop[i - 1] << "," << v_ingeop[i] << "] v_inpres=[" << v_inpres[i - 1] << "," << v_inpres[i] << "] -> " << outpres << endl;
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     // extrapolation forbidden -> NaN returned if out of range
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

Generated on Thu Feb 14 2013 17:59:03 for filedata.kdevelop by  doxygen 1.7.1