REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA_set_weights.cpp
Go to the documentation of this file.
1#include <cmath>
2#include <REMORA_DataStruct.H>
3#include <REMORA.H>
5
6using namespace amrex;
7
8/**
9 * @param[in ] lev level to operate on
10 */
11void REMORA::set_weights (int /*lev*/) {
12
13 Real gamma, scale;
14 Real wsum, shift, cff;
15
16 //HACK should possibly store fixed_ndtfast elsewhere
17 int ndtfast=fixed_ndtfast_ratio>0 ? fixed_ndtfast_ratio : static_cast<int>(fixed_fast_dt / fixed_dt);
18
19 //From mod_scalars
20 Real Falpha = 2.0_rt;
21 Real Fbeta = 4.0_rt;
22 Real Fgamma = 0.284_rt;
23
24 vec_weight1.resize(2*ndtfast+1);
25 vec_weight2.resize(2*ndtfast+1);
26
27 auto weight1 = vec_weight1.dataPtr();
28 auto weight2 = vec_weight2.dataPtr();
29
30//
31//=======================================================================
32// Compute time-averaging filter for barotropic fields.
33//=======================================================================
34//
35// Initialize both sets of weights to zero.
36//
37 nfast=0;
38 for(int i=1;i<=2*ndtfast;i++) {
39 weight1[i-1]=0.0_rt;
40 weight2[i-1]=0.0_rt;
41 }
42//
43//-----------------------------------------------------------------------
44// Power-law shape filters.
45//-----------------------------------------------------------------------
46//
47// The power-law shape filters are given by:
48//
49// F(xi)=xi^Falpha*(1-xi^Fbeta)-Fgamma*xi
50//
51// where xi=scale*i/ndtfast; and scale, Falpha, Fbeta, Fgamma, and
52// normalization are chosen to yield the correct zeroth-order
53// (normalization), first-order (consistency), and second-order moments,
54// resulting in overall second-order temporal accuracy for time-averaged
55// barotropic motions resolved by baroclinic time step.
56//
57 scale=(Falpha+1.0_rt)*(Falpha+Fbeta+1.0_rt) /
58 ((Falpha+2.0_rt)*(Falpha+Fbeta+2.0_rt)*Real(ndtfast));
59 //
60 // Find center of gravity of the primary weighting shape function and
61 // iteratively adjust "scale" to place the centroid exactly at
62 // "ndtfast".
63 //
64 gamma = Fgamma*max(0.0_rt, 1.0_rt-10.0_rt/Real(ndtfast));
65
66 for (int iter=1;iter<=16;iter++) {
67 nfast=0;
68 for(int i=1;i<=2*ndtfast;i++) {
69 cff=scale*Real(i);
70
71 weight1[i-1]=Real(pow(cff,Falpha)-pow(cff,(Falpha+Fbeta)))-gamma*cff;
72
73 if (weight1[i-1] > 0.0_rt) {
74 nfast=i;
75 }
76
77 if ( (nfast>0) && (weight1[i-1] < 0.0_rt) ) {
78 weight1[i-1] = 0.0_rt;
79 }
80 }
81 wsum = 0.0_rt;
82 shift = 0.0_rt;
83 for(int i=1;i<=nfast;i++) {
84 wsum=wsum+weight1[i-1];
85 shift=shift+weight1[i-1]*Real(i);
86 }
87 scale *= shift/(wsum*Real(ndtfast));
88 }
89//
90//-----------------------------------------------------------------------
91// Post-processing of primary weights.
92//-----------------------------------------------------------------------
93//
94// Although it is assumed that the initial settings of the primary
95// weights has its center of gravity "reasonably close" to NDTFAST,
96// it may be not so according to the discrete rules of integration.
97// The following procedure is designed to put the center of gravity
98// exactly to NDTFAST by computing mismatch (NDTFAST-shift) and
99// applying basically an upstream advection of weights to eliminate
100// the mismatch iteratively. Once this procedure is complete primary
101// weights are normalized.
102//
103// Find center of gravity of the primary weights and subsequently
104// calculate the mismatch to be compensated.
105//
106 for (int iter=1;iter<=ndtfast;iter++) {
107 wsum = 0.0_rt;
108 shift = 0.0_rt;
109 for(int i=1;i<=nfast;i++) {
110 wsum=wsum+weight1[i-1];
111 shift=shift+Real(i)*weight1[i-1];
112 }
113 shift=shift/wsum;
114 cff=Real(ndtfast)-shift;
115 //
116 // Apply advection step using either whole, or fractional shifts.
117 // Notice that none of the four loops here is reversible.
118 //
119 if (cff > 1.0_rt) {
120 nfast=nfast+1;
121 for (int i=nfast;i>=2;i--) {
122 weight1[i-1]=weight1[i-1-1];
123 }
124 weight1[1-1] = 0.0_rt;
125 } else if (cff> 0.0_rt) {
126 wsum=1.0_rt-cff;
127 for (int i=nfast;i>=2;i--) {
128 weight1[i-1]=wsum*weight1[i-1]+cff*weight1[i-1-1];
129 }
130 weight1[1-1]=wsum*weight1[1-1];
131 } else if (cff < -1.0_rt) {
132 nfast=nfast-1;
133 for (int i=1;i<=nfast;i++) {
134 weight1[i-1]=weight1[i+1-1];
135 }
136 weight1[nfast+1-1] = 0.0_rt;
137 } else if (cff < 0.0_rt) {
138 wsum=1.0_rt+cff;
139 for (int i=1;i<=nfast-1;i++) {
140 weight1[i-1]=wsum*weight1[i-1]-cff*weight1[i+1-1];
141 }
142 weight1[nfast-1]=wsum*weight1[nfast-1];
143 }
144 }
145
146 // Set SECONDARY weights assuming that backward Euler time step is used
147 // for free surface. Notice that array weight2[i] is assumed to
148 // have all-zero status at entry in this segment of code.
149 for(int j=1;j<=nfast;j++) {
150 cff=weight1[j-1];
151 for(int i=1;i<=j;i++) {
152 weight2[i-1]=weight2[i-1]+cff;
153 }
154 }
155
156 //
157 // Normalize both set of weights.
158 //
159 wsum = 0.0_rt;
160 cff = 0.0_rt;
161 for(int i=1;i<=nfast;i++) {
162 wsum=wsum+weight1[i-1];
163 cff=cff+weight2[i-1];
164 }
165
166 wsum = 1.0_rt / wsum;
167 cff = 1.0_rt / cff;
168
169 for(int i=1;i<=nfast;i++) {
170 weight1[i-1]=wsum*weight1[i-1];
171 weight2[i-1]=cff*weight2[i-1];
172 }
173//
174// Report weights.
175//
176#if 0
177 Real cff1, cff2;
178 if (ParallelDescriptor::IOProcessor()) {
179 Print().SetPrecision(18)<<ParallelDescriptor::NProcs()<<" "<<ndtfast<<" "<<nfast<<" "<<wsum<<std::endl;
180 cff=0.0_rt;
181 cff1=0.0_rt;
182 cff2=0.0_rt;
183 wsum=0.0_rt;
184 shift=0.0_rt;
185 for(int i=1;i<=nfast;i++) {
186 cff=cff+weight1[i-1];
187 cff1=cff1+weight1[i-1]*Real(i);
188 cff2=cff2+weight1[i-1]*Real(i*i);
189 wsum=wsum+weight2[i-1];
190 shift=shift+weight2[i-1]*(Real(i)-0.5_rt);
191 Print().SetPrecision(18)<<"i="<<i<<" "<<weight1[i-1]<<" "<<weight2[i-1]<<" "<<cff<<" "<<wsum<<std::endl;
192 }
193 cff1=cff1/Real(ndtfast);
194 cff2=cff2/(Real(ndtfast)*Real(ndtfast));
195 shift=shift/Real(ndtfast);
196 Print().SetPrecision(18)<<ndtfast <<" "<< nfast<<" "<<Real(nfast)/Real(ndtfast)<<std::endl;
197 Print().SetPrecision(18)<<cff1<<" "<<cff2<<" "<<shift<<" "<<cff<<" "<<wsum<<" "<<Fgamma<<" "<<gamma<<std::endl;
198 if (cff2<1.0_rt001_rt) Print()<<"\n\n\n"<<std::endl;
199 }
200#endif
201}
int nfast
Number of fast steps to take.
Definition REMORA.H:1180
static amrex::Real fixed_dt
User specified fixed baroclinic time step.
Definition REMORA.H:1174
static amrex::Real fixed_fast_dt
User specified fixed barotropic time step.
Definition REMORA.H:1176
amrex::Vector< amrex::Real > vec_weight2
Weights for calculating avg2 in 2D advance.
Definition REMORA.H:399
amrex::Vector< amrex::Real > vec_weight1
Weights for calculating avg1 in 2D advance.
Definition REMORA.H:397
static int fixed_ndtfast_ratio
User specified, number of barotropic steps per baroclinic step.
Definition REMORA.H:1178
void set_weights(int lev)
Set weights for averaging 3D variables to 2D.