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

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 
)
177 {
178  // Find the index of the radial location
179  int index=-1;
180  Real rhub = 2.0;
181  Real rad_from_hub = rad - rhub;
182  if(rad_from_hub < 0.0) {
183  index = 0;
184  }
185  else {
186  for(int i=0;i<n_bld_sections;i++){
187  if(bld_rad_loc[i] > rad) {
188  index = i;
189  break;
190  }
191  }
192  }
193  if(index == -1 and rad > bld_rad_loc[n_bld_sections-1]) {
194  index = n_bld_sections-1;
195  }
196  if(index == -1) {
197  //printf("The radial section is at %0.15g m\n",rad);
198  Abort("Could not find index of the radial section.");
199  }
200 
201  return index;
202 }

Referenced by GeneralAD::source_terms_cellcentered().

Here is the caller graph for this function: