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

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

Referenced by GeneralAD::source_terms_cellcentered().

Here is the caller graph for this function: