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 = two;
21 Real Fbeta = Real(4.0);
22 Real Fgamma = Real(0.284);
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]=zero;
40 weight2[i-1]=zero;
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+one)*(Falpha+Fbeta+one) /
58 ((Falpha+two)*(Falpha+Fbeta+two)*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(zero, one-Real(10.0)/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] > zero) {
74 nfast=i;
75 }
76
77 if ( (nfast>0) && (weight1[i-1] < zero) ) {
78 weight1[i-1] = zero;
79 }
80 }
81 wsum = zero;
82 shift = zero;
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 = zero;
108 shift = zero;
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 > one) {
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] = zero;
125 } else if (cff> zero) {
126 wsum=one-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 < Real(-1.0)) {
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] = zero;
137 } else if (cff < zero) {
138 wsum=one+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 = zero;
160 cff = zero;
161 for(int i=1;i<=nfast;i++) {
162 wsum=wsum+weight1[i-1];
163 cff=cff+weight2[i-1];
164 }
165
166 wsum = one / wsum;
167 cff = one / 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}
constexpr amrex::Real two
constexpr amrex::Real one
constexpr amrex::Real zero
int nfast
Number of fast steps to take.
Definition REMORA.H:1560
static amrex::Real fixed_dt
User specified fixed baroclinic time step.
Definition REMORA.H:1554
static amrex::Real fixed_fast_dt
User specified fixed barotropic time step.
Definition REMORA.H:1556
amrex::Vector< amrex::Real > vec_weight2
Weights for calculating avg2 in 2D advance.
Definition REMORA.H:610
amrex::Vector< amrex::Real > vec_weight1
Weights for calculating avg1 in 2D advance.
Definition REMORA.H:608
static int fixed_ndtfast_ratio
User specified, number of barotropic steps per baroclinic step.
Definition REMORA.H:1558
void set_weights(int lev)
Set weights for averaging 3D variables to 2D.