ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_AdvanceGeneralAD.cpp File Reference
#include <ERF_GeneralAD.H>
#include <ERF_IndexDefines.H>
#include <ERF_Interpolation_1D.H>
#include <cmath>
#include <ERF_NumericalConstants.H>
Include dependency graph for ERF_AdvanceGeneralAD.cpp:

Functions

AMREX_FORCE_INLINE AMREX_GPU_DEVICE int find_rad_loc_index (const Real rad, const Real *bld_rad_loc, const int n_bld_sections)
 
AMREX_FORCE_INLINE AMREX_GPU_DEVICE std::array< Real, 2 > compute_source_terms_Fn_Ft (const Real rad, const Real avg_vel, const Real *bld_rad_loc, const Real *bld_twist, const Real *bld_chord, int n_bld_sections, const Real *bld_airfoil_aoa, const Real *bld_airfoil_Cl, const Real *bld_airfoil_Cd, const int n_pts_airfoil, const Real *velocity, const Real *rotor_RPM, const Real *blade_pitch, const int n_spec_extra)
 

Function Documentation

◆ compute_source_terms_Fn_Ft()

AMREX_FORCE_INLINE AMREX_GPU_DEVICE std::array<Real,2> compute_source_terms_Fn_Ft ( const Real  rad,
const Real  avg_vel,
const Real bld_rad_loc,
const Real bld_twist,
const Real bld_chord,
int  n_bld_sections,
const Real bld_airfoil_aoa,
const Real bld_airfoil_Cl,
const Real bld_airfoil_Cd,
const int  n_pts_airfoil,
const Real velocity,
const Real rotor_RPM,
const Real blade_pitch,
const int  n_spec_extra 
)
227 {
228 
229  Real rpm = interpolate_1d(velocity, rotor_RPM, avg_vel, n_spec_extra);
230  Real pitch = interpolate_1d(velocity, blade_pitch, avg_vel, n_spec_extra);
231 
232  Real Omega = rpm/Real(60.0)*two*PI;
233  Real rho = Real(1.226);
234 
235  Real B = three;
236  Real rhub = two;
237  Real rtip = Real(63.5);
238 
239  Real twist = interpolate_1d(bld_rad_loc, bld_twist, rad, n_bld_sections);
240  Real c = interpolate_1d(bld_rad_loc, bld_chord, rad, n_bld_sections);
241 
242  // Iteration procedure
243 
244  Real s = myhalf*c*B/(PI*rad);
245 
246  Real at, an, V1, Vt, Vr, psi, L, D, Cn, Ct;
247  Real ftip, fhub, F, Cl, Cd, at_new, an_new;
248 
249  at = Real(0.1);
250  an = Real(0.1);
251 
252  bool is_converged = false;
253 
254  for(int i=0;i<100;i++) {
255  V1 = avg_vel*(1-an);
256  Vt = Omega*(one+at)*rad;
257  Vr = std::pow(V1*V1+Vt*Vt,myhalf);
258 
259  psi = std::atan2(V1,Vt);
260 
261  Real aoa = psi*Real(180.0)/PI - twist + pitch;
262 
263  Cl = interpolate_1d(bld_airfoil_aoa, bld_airfoil_Cl, aoa, n_pts_airfoil);
264  Cd = interpolate_1d(bld_airfoil_aoa, bld_airfoil_Cd, aoa, n_pts_airfoil);
265 
266  //Cl = Real(1.37);
267  //Cd = Real(0.014);
268 
269  //printf("rad, aoa, Cl, Cd = %0.15g %0.15g %0.15g %0.15g\n", rad, aoa, Cl, Cd);
270 
271  Cn = Cl*std::cos(psi) + Cd*std::sin(psi);
272  Ct = Cl*std::sin(psi) - Cd*std::cos(psi);
273 
274  ftip = B*(rtip-rad)/(two*rad*std::sin(psi)+Real(1e-10));
275  fhub = B*(rad-rhub)/(two*rad*std::sin(psi)+Real(1e-10));
276 
277  AMREX_ALWAYS_ASSERT(std::fabs(std::exp(-fhub))<=one);
278  AMREX_ALWAYS_ASSERT(std::fabs(std::exp(-ftip))<=one);
279 
280  F = two/PI*(std::acos(std::exp(-ftip)) + std::acos(std::exp(-fhub)) );
281 
282  at_new = one/ ( Real(4.0)*F*std::sin(psi)*std::cos(psi)/(s*Ct+Real(1e-10)) - one );
283  an_new = one/ ( one + Real(4.0)*F*amrex::Math::powi<2>(std::sin(psi))/(s*Cn + Real(1e-10)) );
284  at_new = std::max(Real(0.), at_new);
285 
286  if(std::fabs(at_new-at) < Real(1e-5) and std::fabs(an_new-an) < Real(1e-5)) {
287  //printf("Converged at, an = %d %0.15g %0.15g %0.15g\n",i, at, an, psi);
288  at = at_new;
289  an = an_new;
290  is_converged = true;
291  break;
292  }
293  at = at_new;
294  an = an_new;
295  //printf("Iteration, at, an = %0.15g %0.15g %0.15g\n",at, an, psi);
296  }
297 
298  if(!is_converged) {
299  Abort("The iteration procedure for the generalized actuator disk did not converge. Exiting...");
300  }
301 
302  // Iterations converged. Now compute Ft, Fn
303 
304  L = myhalf*rho*Vr*Vr*c*Cl;
305  D = myhalf*rho*Vr*Vr*c*Cd;
306 
307  Real Fn = L*std::cos(psi) + D*std::sin(psi);
308  Real Ft = L*std::sin(psi) - D*std::cos(psi);
309 
310  //printf("Fn and Ft %0.15g %0.15g %0.15g %0.15g\n", L, D, std::cos(psi), std::sin(psi));
311 
312  std::array<Real, 2> Fn_and_Ft;
313  Fn_and_Ft[0] = Fn;
314  Fn_and_Ft[1] = Ft;
315 
316  return Fn_and_Ft;
317 
318  //exit(0);
319 }
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
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:14
constexpr amrex::Real three
Definition: ERF_NumericalConstants.H:32
constexpr amrex::Real two
Definition: ERF_NumericalConstants.H:31
constexpr amrex::Real one
Definition: ERF_NumericalConstants.H:30
constexpr amrex::Real myhalf
Definition: ERF_NumericalConstants.H:34
constexpr amrex::Real PI
Definition: ERF_NumericalConstants.H:39
amrex::Real Real
Definition: ERF_ShocInterface.H:19
@ rho
Definition: ERF_Kessler.H:25

Referenced by GeneralAD::source_terms_cellcentered().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_rad_loc_index()

AMREX_FORCE_INLINE AMREX_GPU_DEVICE int find_rad_loc_index ( const Real  rad,
const Real bld_rad_loc,
const int  n_bld_sections 
)
183 {
184  // Find the index of the radial location
185  int index=-1;
186  Real rhub = two;
187  Real rad_from_hub = rad - rhub;
188  if(rad_from_hub < zero) {
189  index = 0;
190  }
191  else {
192  for(int i=0;i<n_bld_sections;i++){
193  if(bld_rad_loc[i] > rad) {
194  index = i;
195  break;
196  }
197  }
198  }
199  if(index == -1 and rad > bld_rad_loc[n_bld_sections-1]) {
200  index = n_bld_sections-1;
201  }
202  if(index == -1) {
203  //printf("The radial section is at %0.15g m\n",rad);
204  Abort("Could not find index of the radial section.");
205  }
206 
207  return index;
208 }
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:29

Referenced by GeneralAD::source_terms_cellcentered().

Here is the caller graph for this function: