URI:
       tNCFile.cc - pism - [fork] customized build of PISM, the parallel ice sheet model (tillflux branch)
  HTML git clone git://src.adamsgaard.dk/pism
   DIR Log
   DIR Files
   DIR Refs
   DIR LICENSE
       ---
       tNCFile.cc (8607B)
       ---
            1 // Copyright (C) 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 PISM Authors
            2 //
            3 // This file is part of PISM.
            4 //
            5 // PISM is free software; you can redistribute it and/or modify it under the
            6 // terms of the GNU General Public License as published by the Free Software
            7 // Foundation; either version 3 of the License, or (at your option) any later
            8 // version.
            9 //
           10 // PISM is distributed in the hope that it will be useful, but WITHOUT ANY
           11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
           12 // FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
           13 // details.
           14 //
           15 // You should have received a copy of the GNU General Public License
           16 // along with PISM; if not, write to the Free Software
           17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
           18 
           19 #include "NCFile.hh"
           20 
           21 #include <cstdio>               // fprintf, stderr, rename, remove
           22 #include "pism/util/pism_utilities.hh"
           23 #include "pism/util/error_handling.hh"
           24 #include "pism/util/IceGrid.hh"
           25 
           26 // The following is a stupid kludge necessary to make NetCDF 4.x work in
           27 // serial mode in an MPI program:
           28 #ifndef MPI_INCLUDED
           29 #define MPI_INCLUDED 1
           30 #endif
           31 #include <netcdf.h>
           32 
           33 namespace pism {
           34 namespace io {
           35 
           36 NCFile::NCFile(MPI_Comm c)
           37   : m_com(c), m_file_id(-1), m_define_mode(false) {
           38 }
           39 
           40 NCFile::~NCFile() {
           41   // empty
           42 }
           43 
           44 std::string NCFile::filename() const {
           45   return m_filename;
           46 }
           47 
           48 void NCFile::def_var_chunking_impl(const std::string &name,
           49                                    std::vector<size_t> &dimensions) const {
           50   (void) name;
           51   (void) dimensions;
           52   // the default implementation does nothing
           53 }
           54 
           55 
           56 void NCFile::open(const std::string &filename, IO_Mode mode) {
           57   this->open_impl(filename, mode);
           58   m_filename = filename;
           59   m_define_mode = false;
           60 }
           61 
           62 void NCFile::create(const std::string &filename) {
           63   this->create_impl(filename);
           64   m_filename = filename;
           65   m_define_mode = true;
           66 }
           67 
           68 void NCFile::sync() const {
           69   enddef();
           70   this->sync_impl();
           71 }
           72 
           73 void NCFile::close() {
           74   this->close_impl();
           75   m_filename.clear();
           76   m_file_id = -1;
           77 }
           78 
           79 void NCFile::enddef() const {
           80   if (m_define_mode) {
           81     this->enddef_impl();
           82     m_define_mode = false;
           83   }
           84 }
           85 
           86 void NCFile::redef() const {
           87   if (not m_define_mode) {
           88     this->redef_impl();
           89     m_define_mode = true;
           90   }
           91 }
           92 
           93 void NCFile::def_dim(const std::string &name, size_t length) const {
           94   redef();
           95   this->def_dim_impl(name, length);
           96 }
           97 
           98 void NCFile::inq_dimid(const std::string &dimension_name, bool &exists) const {
           99   this->inq_dimid_impl(dimension_name,exists);
          100 }
          101 
          102 void NCFile::inq_dimlen(const std::string &dimension_name, unsigned int &result) const {
          103   this->inq_dimlen_impl(dimension_name,result);
          104 }
          105 
          106 void NCFile::inq_unlimdim(std::string &result) const {
          107   this->inq_unlimdim_impl(result);
          108 }
          109 
          110 void NCFile::def_var(const std::string &name, IO_Type nctype,
          111                     const std::vector<std::string> &dims) const {
          112   redef();
          113   this->def_var_impl(name, nctype, dims);
          114 }
          115 
          116 void NCFile::def_var_chunking(const std::string &name,
          117                               std::vector<size_t> &dimensions) const {
          118   this->def_var_chunking_impl(name, dimensions);
          119 }
          120 
          121 
          122 void NCFile::get_vara_double(const std::string &variable_name,
          123                             const std::vector<unsigned int> &start,
          124                             const std::vector<unsigned int> &count,
          125                             double *ip) const {
          126 #if (Pism_DEBUG==1)
          127   if (start.size() != count.size()) {
          128     throw RuntimeError::formatted(PISM_ERROR_LOCATION,
          129                                   "start and count arrays have to have the same size");
          130   }
          131 #endif
          132 
          133   enddef();
          134   this->get_vara_double_impl(variable_name, start, count, ip);
          135 }
          136 
          137 void NCFile::put_vara_double(const std::string &variable_name,
          138                             const std::vector<unsigned int> &start,
          139                             const std::vector<unsigned int> &count,
          140                             const double *op) const {
          141 #if (Pism_DEBUG==1)
          142   if (start.size() != count.size()) {
          143     throw RuntimeError::formatted(PISM_ERROR_LOCATION,
          144                                   "start and count arrays have to have the same size");
          145   }
          146 #endif
          147 
          148   enddef();
          149   this->put_vara_double_impl(variable_name, start, count, op);
          150 }
          151 
          152 
          153 void NCFile::write_darray(const std::string &variable_name,
          154                           const IceGrid &grid,
          155                           unsigned int z_count,
          156                           unsigned int record,
          157                           const double *input) {
          158   enddef();
          159   this->write_darray_impl(variable_name, grid, z_count, record, input);
          160 }
          161 
          162 /*!
          163  * The default implementation computes start and count and calls put_vara_double()
          164  */
          165 void NCFile::write_darray_impl(const std::string &variable_name,
          166                                const IceGrid &grid,
          167                                unsigned int z_count,
          168                                unsigned int record,
          169                                const double *input) {
          170   std::vector<std::string> dims;
          171   this->inq_vardimid(variable_name, dims);
          172 
          173   unsigned int ndims = dims.size();
          174 
          175   bool time_dependent = ((z_count  > 1 and ndims == 4) or
          176                          (z_count == 1 and ndims == 3));
          177 
          178   std::vector<unsigned int> start, count;
          179 
          180   // time
          181   if (time_dependent) {
          182     start.push_back(record);
          183     count.push_back(1);
          184   }
          185 
          186   // y
          187   start.push_back(grid.ys());
          188   count.push_back(grid.ym());
          189 
          190   // x
          191   start.push_back(grid.xs());
          192   count.push_back(grid.xm());
          193 
          194   // z (these are not used when writing 2D fields)
          195   start.push_back(0);
          196   count.push_back(z_count);
          197 
          198   this->put_vara_double(variable_name, start, count, input);
          199 }
          200 
          201 
          202 void NCFile::get_varm_double(const std::string &variable_name,
          203                             const std::vector<unsigned int> &start,
          204                             const std::vector<unsigned int> &count,
          205                             const std::vector<unsigned int> &imap,
          206                             double *ip) const {
          207 
          208 #if (Pism_DEBUG==1)
          209   if (start.size() != count.size() or
          210       start.size() != imap.size()) {
          211     throw RuntimeError::formatted(PISM_ERROR_LOCATION,
          212                                   "start, count and imap arrays have to have the same size");
          213   }
          214 #endif
          215 
          216   enddef();
          217   this->get_varm_double_impl(variable_name, start, count, imap, ip);
          218 }
          219 
          220 void NCFile::inq_nvars(int &result) const {
          221   this->inq_nvars_impl(result);
          222 }
          223 
          224 void NCFile::inq_vardimid(const std::string &variable_name, std::vector<std::string> &result) const {
          225   this->inq_vardimid_impl(variable_name, result);
          226 }
          227 
          228 void NCFile::inq_varnatts(const std::string &variable_name, int &result) const {
          229   this->inq_varnatts_impl(variable_name, result);
          230 }
          231 
          232 void NCFile::inq_varid(const std::string &variable_name, bool &result) const {
          233   this->inq_varid_impl(variable_name, result);
          234 }
          235 
          236 void NCFile::inq_varname(unsigned int j, std::string &result) const {
          237   this->inq_varname_impl(j, result);
          238 }
          239 
          240 void NCFile::get_att_double(const std::string &variable_name,
          241                             const std::string &att_name,
          242                             std::vector<double> &result) const {
          243   this->get_att_double_impl(variable_name, att_name, result);
          244 }
          245 
          246 void NCFile::get_att_text(const std::string &variable_name,
          247                           const std::string &att_name,
          248                           std::string &result) const {
          249   this->get_att_text_impl(variable_name, att_name, result);
          250 }
          251 
          252 void NCFile::put_att_double(const std::string &variable_name,
          253                             const std::string &att_name,
          254                             IO_Type xtype,
          255                             const std::vector<double> &data) const {
          256   this->put_att_double_impl(variable_name, att_name, xtype, data);
          257 }
          258 
          259 void NCFile::put_att_text(const std::string &variable_name,
          260                           const std::string &att_name,
          261                           const std::string &value) const {
          262   this->put_att_text_impl(variable_name, att_name, value);
          263 }
          264 
          265 void NCFile::inq_attname(const std::string &variable_name,
          266                          unsigned int n,
          267                          std::string &result) const {
          268   this->inq_attname_impl(variable_name, n, result);
          269 }
          270 
          271 void NCFile::inq_atttype(const std::string &variable_name,
          272                          const std::string &att_name,
          273                          IO_Type &result) const {
          274   this->inq_atttype_impl(variable_name, att_name, result);
          275 }
          276 
          277 void NCFile::set_fill(int fillmode, int &old_modep) const {
          278   redef();
          279   this->set_fill_impl(fillmode, old_modep);
          280 }
          281 
          282 void NCFile::del_att(const std::string &variable_name, const std::string &att_name) const {
          283   this->del_att_impl(variable_name, att_name);
          284 }
          285 
          286 } // end of namespace io
          287 } // end of namespace pism