FV3 Bundle
DolphChebyshev.cc
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2009-2016 ECMWF.
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  * In applying this licence, ECMWF does not waive the privileges and immunities
7  * granted to it by virtue of its status as an intergovernmental organisation nor
8  * does it submit to any jurisdiction.
9  */
10 
12 
13 #include <cmath>
14 #include <vector>
15 
16 #include "eckit/config/Configuration.h"
17 #include "oops/util/DateTime.h"
18 #include "oops/util/Duration.h"
19 
20 namespace oops {
21 
22 // -----------------------------------------------------------------------------
23 
24 static WeightMaker<DolphChebyshev> makerDolph_("DolphChebyshev");
25 
26 // -----------------------------------------------------------------------------
27 
28 DolphChebyshev::DolphChebyshev(const eckit::Configuration & config) {
29  tau_ = util::Duration(config.getString("cutoff"));
30 }
31 
32 // -----------------------------------------------------------------------------
33 
34 std::map< util::DateTime, double > DolphChebyshev::setWeights(const util::DateTime & bgn,
35  const util::DateTime & end,
36  const util::Duration & dt) {
37  const double pi = 4.0*std::atan(1.0);
38  const util::Duration window(end-bgn);
39  const int nstep = window.toSeconds() / dt.toSeconds();
40  ASSERT(window.toSeconds() == dt.toSeconds()*nstep);
41 
42  const int M = nstep/2;
43  const int N = 2*M + 1;
44 
45  const int tt = tau_.toSeconds() / dt.toSeconds();
46  ASSERT(tau_.toSeconds() == dt.toSeconds()*tt);
47  ASSERT(tt > 1);
48  const double thetas = 2.0 * pi / tt;
49  const double x0 = 1.0 / std::cos(thetas/2.0);
50  const double rr = 1.0 / std::cosh(nstep * std::acosh(x0));
51 
52  std::vector<double> w(M+1);
53  for (int n = 0; n <= M; ++n) {
54  double tn = 2.0 * pi * n / N;
55  double sum = 0.0;
56  for (int m = 1; m <= M; ++m) {
57  double xx = x0 * std::cos(pi * m / N);
58  double t2m = 0.0;
59  double tnm2 = 1.0;
60  double tnm1 = xx;
61  for (int kk = 2; kk <= 2 * M; ++kk) {
62  t2m = 2.0 * xx * tnm1 - tnm2;
63  tnm2 = tnm1;
64  tnm1 = t2m;
65  }
66  sum += t2m * std::cos(m*tn);
67  }
68  w[n] = (1.0 + 2.0 * rr * sum) / N;
69  }
70 
71  std::map< util::DateTime, double > weights;
72  double checksum = 0.0;
73  util::DateTime now(bgn);
74  for (int jj = -M; jj <= M; ++jj) {
75  int n = std::abs(jj);
76  weights[now] = w[n];
77  checksum += w[n];
78  now += dt;
79  }
80  ASSERT(now == end+dt);
81  ASSERT(std::abs(checksum-1.0) < 1.0e-8);
82 
83  return weights;
84 }
85 
86 // -----------------------------------------------------------------------------
87 
88 } // namespace oops
89 
util::Duration tau_
************************************************************************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 end
integer, parameter m
The namespace for the main oops code.
real(fp), parameter, public e
std::map< util::DateTime, double > setWeights(const util::DateTime &, const util::DateTime &, const util::Duration &)
enddo ! cludge for now
static WeightMaker< DolphChebyshev > makerDolph_("DolphChebyshev")
DolphChebyshev(const eckit::Configuration &)