ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_Interpolation_1D.H
Go to the documentation of this file.
1 #ifndef Initialization_1D_H
2 #define Initialization_1D_H
3 #include <AMReX_REAL.H>
4 
5 /**
6  * Interpolates 1D array beta at the location alpha_interp in the array alpha
7  * requiring 1D arrays alpha and beta to be the same size alpha_size.
8  * This routine assumes the alpha data are monotonic from lowest to highest.
9  */
10 
11 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
12 amrex::Real interpolate_1d (const amrex::Real* alpha, const amrex::Real* beta,
13  const amrex::Real alpha_interp, const int alpha_size)
14 {
15  amrex::Real beta_interp = -1.0e34;
16 
17  // If the interpolation point already exists in the array,
18  // just return it
19  for (int i = 0; i < alpha_size; ++i) {
20  if (alpha[i] == alpha_interp) {
21  beta_interp = beta[i];
22  return beta_interp;
23  }
24  }
25 
26  // We didn't find an exact match for alpha_interp in alpha,
27  // so we need linear interpolation/extrapolation
28  amrex::Real alpha_min = alpha[0];
29  amrex::Real alpha_max = alpha[alpha_size-1];
30  if (alpha_interp >= alpha_min && alpha_interp <= alpha_max) //interpolate
31  {
32  for (int i = 0; i < alpha_size; ++i)
33  {
34  if (alpha_interp >= alpha[i] && alpha_interp <= alpha[i + 1])
35  {
36  //y = y0 + (y1-y0)*(x-x0)/(x1-x0);
37  amrex::Real y0 = beta[i];
38  amrex::Real y1 = beta[i + 1];
39  amrex::Real x = alpha_interp;
40  amrex::Real x0 = alpha[i];
41  amrex::Real x1 = alpha[i + 1];
42  beta_interp = y0 + (y1 - y0)*(x - x0) / (x1 - x0);
43  return beta_interp;
44  }
45  }
46  }
47  else //extrapolate
48  {
49  // y = y0 + ((x - x0) / (x1 - x0)) * (y1 - y0)
50  int i = 0;
51  if (alpha_interp > alpha_max)
52  {
53  i = alpha_size-2;
54  }
55  else if (alpha_interp >= alpha_min)
56  {
57  amrex::Abort("interpolate_1d: we shouldn't be here!");
58  }
59 
60  amrex::Real y0 = beta[i];
61  amrex::Real y1 = beta[i + 1];
62  amrex::Real x = alpha_interp;
63  amrex::Real x0 = alpha[i];
64  amrex::Real x1 = alpha[i + 1];
65  beta_interp = y0 + ((x - x0) / (x1 - x0)) * (y1 - y0);
66  return beta_interp;
67  }
68 
69  return beta_interp;
70 }
71 
72 /*
73  * Interpolate between values from a vector of reals (e.g., zlevels_stag) to a
74  * new, expanded vector with refine_fac-1 new uniformly spaced points between
75  * the original values.
76  *
77  * Example:
78  * Vector<Real> tmp_orig = {0,1,2};
79  * Vector<Real> tmp(4);
80  * expand_and_interpolate_1d(tmp, tmp_orig, 2, false); // tmp == {0, 0.5, 1, 1.5, 2}
81  * expand_and_interpolate_1d(tmp, tmp_orig, 2, true); // tmp == {0.25, 0.75, 1.25, 1.75}
82  */
83 AMREX_FORCE_INLINE
84 void
85 expand_and_interpolate_1d (amrex::Vector<amrex::Real>& znew,
86  const amrex::Vector<amrex::Real>& zorig,
87  int refine_fac,
88  bool destag=false)
89 {
90  const int Nz = zorig.size();
91  const int Nz_refined = refine_fac*(Nz-1) + 1;
92  if (destag) {
93  AMREX_ALWAYS_ASSERT(znew.size() == Nz_refined-1);
94  } else {
95  AMREX_ALWAYS_ASSERT(znew.size() == Nz_refined);
96  }
97  amrex::Vector<amrex::Real> znew_stag(Nz_refined);
98  for (int k=0; k < Nz; ++k) {
99  znew_stag[refine_fac*k] = zorig[k];
100  }
101  if (refine_fac > 1) {
102  for (int k=0; k < Nz-1; ++k) {
103  amrex::Real z1 = zorig[k];
104  amrex::Real dz = zorig[k+1] - z1;
105  for (int koff=1; koff < refine_fac; ++koff) {
106  znew_stag[refine_fac*k + koff] = amrex::Real(koff)/refine_fac * dz + z1;
107  }
108  }
109  }
110  if (destag) {
111  for (int k=0; k < Nz_refined-1; ++k) {
112  znew[k] = 0.5*(znew_stag[k] + znew_stag[k+1]);
113  }
114  } else {
115  znew = znew_stag;
116  }
117 }
118 #endif
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real interpolate_1d(const amrex::Real *alpha, const amrex::Real *beta, const amrex::Real alpha_interp, const int alpha_size)
Definition: ERF_Interpolation_1D.H:12
AMREX_FORCE_INLINE void expand_and_interpolate_1d(amrex::Vector< amrex::Real > &znew, const amrex::Vector< amrex::Real > &zorig, int refine_fac, bool destag=false)
Definition: ERF_Interpolation_1D.H:85