NCFile.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