11 #include "oops/util/abor1_cpp.h" 12 #include "oops/util/datetime_f.h" 13 #include "oops/util/Duration.h" 14 #include "oops/util/Logger.h" 24 #define checkRC(return_code, message, db_) { \ 25 if (return_code != ODBQL_OK) { \ 26 oops::Log::error() << __func__ << ": ODB ERROR: " << message << std::endl; \ 52 const std::size_t & Nlocs,
const std::size_t & Nobs,
53 const std::size_t & Nrecs,
const std::size_t & Nvars) {
61 oops::Log::trace() << __func__ <<
" fname_: " <<
fname_ <<
" fmode_: " <<
fmode_ << std::endl;
67 odbql_stmt *res =
nullptr;
69 int i, column, number_of_columns;
81 std::string errmsg =
"OdbApi constructor cannot open file: " +
fname_ 82 +
". Return code: " + std::to_string(rc);
87 }
else if (
fmode_ ==
"w") {
89 ABORT(
"Unimplemented file mode 'w' for OdbApiIO constructor");
90 }
else if (
fmode_ ==
"W") {
92 ABORT(
"Unimplemented file mode 'W' for OdbApiIO constructor");
95 oops::Log::error() << __func__ <<
": Must use one of: 'r', 'w', 'W'" << std::endl;
96 ABORT(
"Unrecognized file mode for OdbApiIO constructor");
113 std::string sqlstmt =
"SELECT count(*) FROM '" +
fname_ +
"';";
114 oops::Log::trace() << __func__ <<
" sql statement: " << sqlstmt << std::endl;
116 rc = odbql_prepare_v2(
db_, sqlstmt.c_str(), -1, &res, 0);
117 checkRC(rc,
"Failed to prepare statement to count records.",
db_);
125 rc = odbql_step(res);
128 if (rc == ODBQL_ROW) {
129 odbql_value*
pv = odbql_column_value(res, 0);
132 oops::Log::trace() << __func__ <<
" nlocs_ set to: " 133 << std::to_string(
nlocs_) << std::endl;
139 rc = odbql_finalize(res);
162 oops::Log::trace() << __func__ <<
" fname_: " <<
fname_ << std::endl;
163 if (
db_ !=
nullptr) {
168 int rc = odbql_close(
db_);
187 oops::Log::trace() << __func__ <<
" VarName: " << VarName << std::endl;
189 odbql_stmt *res =
nullptr;
191 std::string sql =
"SELECT " + VarName +
" FROM '" +
fname_ +
"';";
192 oops::Log::trace() << __func__ <<
" sql: " << sql << std::endl;
194 rc = odbql_prepare_v2(
db_, sql.c_str(), -1, &res, 0);
195 if (rc != ODBQL_OK) {
196 std::string errorString =
"ODB ERROR: error when preparing SQL statemtnt: " +
204 int columnType = odbql_column_type(res, 0);
212 odbql_value*
pv =
nullptr;
214 while (((rc = odbql_step(res)) != ODBQL_DONE) && (index <
nlocs_)) {
215 if (rc == ODBQL_ROW) {
216 pv = odbql_column_value(res, 0);
218 std::string errorString =
"ODB ERROR: unexpected NULL in a column of file: " +
fname_;
229 oops::Log::error() << __func__ <<
": odbql_step returned unimplemented code: " <<
230 std::to_string(rc) <<
" in file " <<
fname_ << std::endl;
232 ABORT(
"Encountered unimplemented odbql_step return code.");
238 switch (columnType) {
240 VarData[index] = (
T)odbql_value_int(
pv);
244 VarData[index] = (
T)odbql_value_double(
pv);
247 std::string errorString =
"Unimplemented data type for '" +
248 VarName +
"' in file " +
fname_;
257 oops::Log::trace() << __func__ <<
"finished sql: " << sql << std::endl;
259 rc = odbql_finalize(res);
267 oops::Log::trace() << __func__ <<
" VarName: " << VarName << std::endl;
268 ReadVarTemplate<int>(VarName, VarData);
274 oops::Log::trace() << __func__ <<
" VarName: " << VarName << std::endl;
275 ReadVarTemplate<float>(VarName, VarData);
281 oops::Log::trace() << __func__ <<
" VarName: " << VarName << std::endl;
282 ReadVarTemplate<double>(VarName, VarData);
288 oops::Log::trace() << __func__ <<
" VarName: " << VarName << std::endl;
301 oops::Log::trace() << __func__ <<
" VarName: " << VarName << std::endl;
314 oops::Log::trace() << __func__ <<
" VarName: " << VarName << std::endl;
327 oops::Log::trace() << __func__ << std::endl;
330 const std::string dateColumnName =
"date@odb";
331 const std::string timeColumnName =
"time@odb";
333 ReadVarTemplate<int>(dateColumnName, VarDate);
334 ReadVarTemplate<int>(timeColumnName, VarTime);
340 os <<
"OdbApi: In " << __FILE__ <<
" @ " << __LINE__ << std::endl;
std::size_t nobs_
number of unique observations
l_size ! loop over number of fields ke do je do i
std::size_t nlocs_
number of unique locations
odbql * db_
pointer to odbql object
OdbApiIO(const std::string &FileName, const std::string &FileMode, const std::size_t &Nlocs, const std::size_t &Nobs, const std::size_t &Nrecs, const std::size_t &Nvars)
std::string fname_
file name
#define checkRC(return_code, message, db_)
void WriteVar(const std::string &VarName, int *VarData)
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! MPP_TRANSMIT !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine MPP_TRANSMIT_(put_data, put_len, to_pe, get_data, get_len, from_pe, block, tag, recv_request, send_request)!a message-passing routine intended to be reminiscent equally of both MPI and SHMEM!put_data and get_data are contiguous MPP_TYPE_ arrays!at each call, your put_data array is put to to_pe 's get_data! your get_data array is got from from_pe 's put_data!i.e we assume that typically(e.g updating halo regions) each PE performs a put _and_ a get!special PE designations:! NULL_PE:to disable a put or a get(e.g at boundaries)! ANY_PE:if remote PE for the put or get is to be unspecific! ALL_PES:broadcast and collect operations(collect not yet implemented)!ideally we would not pass length, but this f77-style call performs better(arrays passed by address, not descriptor)!further, this permits< length > contiguous words from an array of any rank to be passed(avoiding f90 rank conformance check)!caller is responsible for completion checks(mpp_sync_self) before and after integer, intent(in) ::put_len, to_pe, get_len, from_pe MPP_TYPE_, intent(in) ::put_data(*) MPP_TYPE_, intent(out) ::get_data(*) logical, intent(in), optional ::block integer, intent(in), optional ::tag integer, intent(out), optional ::recv_request, send_request logical ::block_comm integer ::i MPP_TYPE_, allocatable, save ::local_data(:) !local copy used by non-parallel code(no SHMEM or MPI) integer ::comm_tag integer ::rsize if(.NOT.module_is_initialized) call mpp_error(FATAL, 'MPP_TRANSMIT:You must first call mpp_init.') if(to_pe.EQ.NULL_PE .AND. from_pe.EQ.NULL_PE) return block_comm=.true. if(PRESENT(block)) block_comm=block if(debug) then call SYSTEM_CLOCK(tick) write(stdout_unit,'(a, i18, a, i6, a, 2i6, 2i8)')&'T=', tick, ' PE=', pe, ' MPP_TRANSMIT begin:to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len end if comm_tag=DEFAULT_TAG if(present(tag)) comm_tag=tag!do put first and then get if(to_pe.GE.0 .AND. to_pe.LT.npes) then!use non-blocking sends if(debug .and.(current_clock.NE.0)) call SYSTEM_CLOCK(start_tick)!z1l:truly non-blocking send.! if(request(to_pe).NE.MPI_REQUEST_NULL) then !only one message from pe-> to_pe in queue *PE waiting for to_pe ! call error else get_len so only do gets but you cannot have a pure get with MPI call a get means do a wait to ensure put on remote PE is complete error call increase mpp_nml request_multiply call MPP_TRANSMIT get_len end if return end subroutine MPP_TRANSMIT_ ! MPP_BROADCAST ! subroutine but that doesn t allow !broadcast to a subset of PEs This version and mpp_transmit will remain !backward compatible intent(inout) & T
void ReadVar(const std::string &VarName, int *VarData)
std::string fmode_
file mode ("r" -> read, "w" -> overwrite, "W" -> create and write)
void ReadDateTime(int *VarDate, int *VarTime)
void ReadVarTemplate(const std::string &VarName, T *VarData)
std::size_t nrecs_
number of unique records
void print(std::ostream &os) const
std::size_t nvars_
number of unique variables