ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_Interpolation_Bilinear.H
Go to the documentation of this file.
1 #ifndef ERF_INTERPOLATE_BILINEAR_H_
2 #define ERF_INTERPOLATE_BILINEAR_H_
3 
4 #include "AMReX_GpuPrint.H"
5 #include "ERF_DataStruct.H"
6 
7 /**
8  * Bilinear interpolation routines. There are different versions for
9  * different scenarios that take in a different argument list
10  */
11 
12 AMREX_FORCE_INLINE
13 AMREX_GPU_HOST_DEVICE
14 int get_single_index (int i, int j, int k,
15  int nx, int ny)
16 {
17 
18  int si = k*nx*ny + j*nx + i;
19  return si;
20 }
21 
22 AMREX_FORCE_INLINE
23 AMREX_GPU_HOST_DEVICE
24 int clamp_interp_index (int idx, int npts)
25 {
26  if (npts <= 1) {
27  return 0;
28  }
29 
30  return amrex::max(0, amrex::min(idx, npts - 2));
31 }
32 
33 // Lower index of the uniform-spacing interval holding x. A singleton
34 // dimension returns 0 before dividing, since its spacing is 0 or NaN.
35 AMREX_FORCE_INLINE
36 AMREX_GPU_HOST_DEVICE
38 {
39  if (npts <= 1) {
40  return 0;
41  }
42 
43  return clamp_interp_index(static_cast<int>(std::floor((x - x0) / dx)), npts);
44 }
45 
46 AMREX_FORCE_INLINE
47 AMREX_GPU_HOST_DEVICE
49 {
50  return (xhi > xlo) ? (x - xlo) / (xhi - xlo) : amrex::Real(0);
51 }
52 
53 AMREX_FORCE_INLINE
54 AMREX_GPU_HOST_DEVICE
55 void bilinear_interpolation (const amrex::Real* xvec, const amrex::Real* yvec, const amrex::Real* zvec,
56  const amrex::Real dxvec, const amrex::Real dyvec,
57  const int nx, const int ny, const int nz,
58  const amrex::Real x, const amrex::Real y, const amrex::Real z,
59  const amrex::Real* varvec,
60  amrex::Real& tmp_var)
61 {
62 
63  // Points outside the table, including heights below zvec[0], take the value at the
64  // nearest table edge; a negative z inside the table is interpolated like any other
65  amrex::Real x_interp = x;
66  amrex::Real y_interp = y;
67  amrex::Real z_interp = z;
68 
69  if (x_interp < xvec[0]) x_interp = xvec[0];
70  if (x_interp > xvec[nx-1]) x_interp = xvec[nx-1];
71 
72  if (y_interp < yvec[0]) y_interp = yvec[0];
73  if (y_interp > yvec[ny-1]) y_interp = yvec[ny-1];
74 
75  if (z_interp < zvec[0]) z_interp = zvec[0];
76  if (z_interp > zvec[nz-1]) z_interp = zvec[nz-1];
77 
78  int iloc = get_interp_index(x_interp, xvec[0], dxvec, nx);
79  int jloc = get_interp_index(y_interp, yvec[0], dyvec, ny);
80 
81  int kloc = 0;
82  if (nz > 1) {
83  kloc = nz - 2;
84  for (int k = 1; k < nz; ++k) {
85  if (zvec[k] >= z_interp) {
86  kloc = k - 1;
87  break;
88  }
89  }
90  }
91 
92  int ihi = (nx > 1) ? iloc + 1 : iloc;
93  int jhi = (ny > 1) ? jloc + 1 : jloc;
94  int khi = (nz > 1) ? kloc + 1 : kloc;
95 
96  amrex::Real xlo = xvec[iloc];
97  amrex::Real ylo = yvec[jloc];
98  amrex::Real zlo = zvec[kloc];
99 
100  amrex::Real w_x = get_interp_weight(x_interp, xlo, xvec[ihi]);
101  amrex::Real w_y = get_interp_weight(y_interp, ylo, yvec[jhi]);
102  amrex::Real w_z = get_interp_weight(z_interp, zlo, zvec[khi]);
103 
104  int ind0 = get_single_index(iloc,jloc,kloc,nx,ny);
105  int ind1 = get_single_index(ihi ,jloc,kloc,nx,ny);
106  int ind2 = get_single_index(ihi ,jhi ,kloc,nx,ny);
107  int ind3 = get_single_index(iloc,jhi ,kloc,nx,ny);
108  int ind4 = get_single_index(iloc,jloc,khi ,nx,ny);
109  int ind5 = get_single_index(ihi ,jloc,khi ,nx,ny);
110  int ind6 = get_single_index(ihi ,jhi ,khi ,nx,ny);
111  int ind7 = get_single_index(iloc,jhi ,khi ,nx,ny);
112 
113  tmp_var = (1-w_x)*(1-w_y)*(1-w_z)*varvec[ind0] + w_x*(1-w_y)*(1-w_z)*varvec[ind1] +
114  w_x*w_y*(1-w_z)*varvec[ind2] + (1-w_x)*w_y*(1-w_z)*varvec[ind3] +
115  (1-w_x)*(1-w_y)*w_z*varvec[ind4] + w_x*(1-w_y)*w_z*varvec[ind5] +
116  w_x*w_y*w_z*varvec[ind6] + (1-w_x)*w_y*w_z*varvec[ind7];
117 
118  //std::cout << "Variable value is " << tmp_var << "\n";
119 }
120 
121 AMREX_GPU_DEVICE
122 inline
123 amrex::Real interpolate_from_coarse (const amrex::Array4<const amrex::Real>& crse,
124  int n,
126  const amrex::Real* prob_lo_crse,
127  const amrex::Real* dx_crse)
128 {
129  // Convert to coarse grid index space
130  amrex::Real ic_real = (x - prob_lo_crse[0]) / dx_crse[0];
131  amrex::Real jc_real = (y - prob_lo_crse[1]) / dx_crse[1];
132  amrex::Real kc_real = (z - prob_lo_crse[2]) / dx_crse[2];
133 
134  int ic = static_cast<int>(amrex::Math::floor(ic_real));
135  int jc = static_cast<int>(amrex::Math::floor(jc_real));
136  int kc = static_cast<int>(amrex::Math::floor(kc_real));
137 
138  amrex::Real dx = ic_real - ic;
139  amrex::Real dy = jc_real - jc;
140  amrex::Real dz = kc_real - kc;
141 
142  // Trilinear interpolation
143  amrex::Real v000 = crse(ic, jc, kc, n);
144  amrex::Real v100 = crse(ic + 1, jc, kc, n);
145  amrex::Real v010 = crse(ic, jc + 1, kc, n);
146  amrex::Real v110 = crse(ic + 1, jc + 1, kc, n);
147  amrex::Real v001 = crse(ic, jc, kc + 1, n);
148  amrex::Real v101 = crse(ic + 1, jc, kc + 1, n);
149  amrex::Real v011 = crse(ic, jc + 1, kc + 1, n);
150  amrex::Real v111 = crse(ic + 1, jc + 1, kc + 1, n);
151 
152  amrex::Real v = v000 * (1 - dx) * (1 - dy) * (1 - dz) +
153  v100 * dx * (1 - dy) * (1 - dz) +
154  v010 * (1 - dx) * dy * (1 - dz) +
155  v110 * dx * dy * (1 - dz) +
156  v001 * (1 - dx) * (1 - dy) * dz +
157  v101 * dx * (1 - dy) * dz +
158  v011 * (1 - dx) * dy * dz +
159  v111 * dx * dy * dz;
160 
161  return v;
162 }
163 
164 AMREX_FORCE_INLINE
165 AMREX_GPU_HOST_DEVICE
166 void bilinear_interpolation_2d (const amrex::Real* xvec, const amrex::Real* yvec,
167  const amrex::Real dxvec, const amrex::Real dyvec,
168  const int nx, const int ny,
170  const amrex::Real* varvec,
171  amrex::Real& tmp_var)
172 {
173  if(x<xvec[0]) {
174  x = xvec[0];
175  }
176  if(x>xvec[nx-1]) {
177  x = xvec[nx-1];
178  }
179 
180  if(y<yvec[0]) {
181  y = yvec[0];
182  }
183  if(y>yvec[ny-1]) {
184  y = yvec[ny-1];
185  }
186 
187  int iloc = get_interp_index(x, xvec[0], dxvec, nx);
188  int jloc = get_interp_index(y, yvec[0], dyvec, ny);
189  int ihi = (nx > 1) ? iloc + 1 : iloc;
190  int jhi = (ny > 1) ? jloc + 1 : jloc;
191 
192  amrex::Real xlo = xvec[iloc];
193  amrex::Real ylo = yvec[jloc];
194 
195  amrex::Real w_x = get_interp_weight(x, xlo, xvec[ihi]);
196  amrex::Real w_y = get_interp_weight(y, ylo, yvec[jhi]);
197 
198  int ind0 = get_single_index(iloc,jloc,0,nx,ny);
199  int ind1 = get_single_index(ihi ,jloc,0,nx,ny);
200  int ind2 = get_single_index(ihi ,jhi ,0,nx,ny);
201  int ind3 = get_single_index(iloc,jhi ,0,nx,ny);
202 
203  tmp_var = (1-w_x)*(1-w_y)*varvec[ind0] + w_x*(1-w_y)*varvec[ind1] +
204  w_x*w_y*varvec[ind2] + (1-w_x)*w_y*varvec[ind3];
205 
206  //std::cout << "Variable value is " << tmp_var << "\n";
207 }
208 
209 
210 #endif
const int nx
Definition: ERF_InitCustomPertVels_CloudChamber.H:14
const int ny
Definition: ERF_InitCustomPertVels_CloudChamber.H:15
const Real dy
Definition: ERF_InitCustomPert_ABL.H:45
const Real dx
Definition: ERF_InitCustomPert_ABL.H:44
const int khi
Definition: ERF_InitCustomPert_Bubble.H:25
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int idx(int i, int j, int k, int nx, int ny)
Definition: ERF_InitForEnsemble.cpp:404
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE int get_interp_index(amrex::Real x, amrex::Real x0, amrex::Real dx, int npts)
Definition: ERF_Interpolation_Bilinear.H:37
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE void bilinear_interpolation_2d(const amrex::Real *xvec, const amrex::Real *yvec, const amrex::Real dxvec, const amrex::Real dyvec, const int nx, const int ny, amrex::Real x, amrex::Real y, const amrex::Real *varvec, amrex::Real &tmp_var)
Definition: ERF_Interpolation_Bilinear.H:166
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE int get_single_index(int i, int j, int k, int nx, int ny)
Definition: ERF_Interpolation_Bilinear.H:14
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE int clamp_interp_index(int idx, int npts)
Definition: ERF_Interpolation_Bilinear.H:24
AMREX_GPU_DEVICE amrex::Real interpolate_from_coarse(const amrex::Array4< const amrex::Real > &crse, int n, amrex::Real x, amrex::Real y, amrex::Real z, const amrex::Real *prob_lo_crse, const amrex::Real *dx_crse)
Definition: ERF_Interpolation_Bilinear.H:123
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE void bilinear_interpolation(const amrex::Real *xvec, const amrex::Real *yvec, const amrex::Real *zvec, const amrex::Real dxvec, const amrex::Real dyvec, const int nx, const int ny, const int nz, const amrex::Real x, const amrex::Real y, const amrex::Real z, const amrex::Real *varvec, amrex::Real &tmp_var)
Definition: ERF_Interpolation_Bilinear.H:55
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE amrex::Real get_interp_weight(amrex::Real x, amrex::Real xlo, amrex::Real xhi)
Definition: ERF_Interpolation_Bilinear.H:48
amrex::Real Real
Definition: ERF_ShocInterface.H:19
@ dz
Definition: ERF_AdvanceWDM6.cpp:273