337 Gpu::DeviceVector<Real> d_xloc(
xloc.size());
338 Gpu::DeviceVector<Real> d_yloc(
yloc.size());
339 Gpu::copy(Gpu::hostToDevice,
xloc.begin(),
xloc.end(), d_xloc.begin());
340 Gpu::copy(Gpu::hostToDevice,
yloc.begin(),
yloc.end(), d_yloc.begin());
342 auto dx = geom.CellSizeArray();
345 const amrex::Box& domain = geom.Domain();
346 auto ProbLoArr = geom.ProbLoArray();
347 int domlo_x = domain.smallEnd(0);
348 int domhi_x = domain.bigEnd(0) + 1;
349 int domlo_y = domain.smallEnd(1);
350 int domhi_y = domain.bigEnd(1) + 1;
351 int domlo_z = domain.smallEnd(2);
352 int domhi_z = domain.bigEnd(2) + 1;
355 mf_vars_generalAD.setVal(0.0);
357 long unsigned int nturbs =
xloc.size();
365 Gpu::DeviceVector<Real> d_freestream_velocity(nturbs);
366 Gpu::DeviceVector<Real> d_disk_cell_count(nturbs);
370 Real* d_xloc_ptr = d_xloc.data();
371 Real* d_yloc_ptr = d_yloc.data();
372 Real* d_freestream_velocity_ptr = d_freestream_velocity.data();
373 Real* d_disk_cell_count_ptr = d_disk_cell_count.data();
377 Gpu::DeviceVector<Real> d_bld_rad_loc(n_bld_sections);
378 Gpu::DeviceVector<Real> d_bld_twist(n_bld_sections);
379 Gpu::DeviceVector<Real> d_bld_chord(n_bld_sections);
382 Gpu::copy(Gpu::hostToDevice,
bld_twist.begin(),
bld_twist.end(), d_bld_twist.begin());
383 Gpu::copy(Gpu::hostToDevice,
bld_chord.begin(),
bld_chord.end(), d_bld_chord.begin());
385 Real* bld_rad_loc_ptr = d_bld_rad_loc.data();
386 Real* bld_twist_ptr = d_bld_twist.data();
387 Real* bld_chord_ptr = d_bld_chord.data();
389 Vector<Gpu::DeviceVector<Real>> d_bld_airfoil_aoa(n_bld_sections);
390 Vector<Gpu::DeviceVector<Real>> d_bld_airfoil_Cl(n_bld_sections);
391 Vector<Gpu::DeviceVector<Real>> d_bld_airfoil_Cd(n_bld_sections);
395 for(
int i=0;i<n_bld_sections;i++){
396 d_bld_airfoil_aoa[i].resize(n_pts_airfoil);
397 d_bld_airfoil_Cl[i].resize(n_pts_airfoil);
398 d_bld_airfoil_Cd[i].resize(n_pts_airfoil);
404 Vector<Real*> hp_bld_airfoil_aoa, hp_bld_airfoil_Cl, hp_bld_airfoil_Cd;
405 for (
auto & v :d_bld_airfoil_aoa) {
406 hp_bld_airfoil_aoa.push_back(v.data());
408 for (
auto & v :d_bld_airfoil_Cl) {
409 hp_bld_airfoil_Cl.push_back(v.data());
411 for (
auto & v :d_bld_airfoil_Cd) {
412 hp_bld_airfoil_Cd.push_back(v.data());
415 Gpu::AsyncArray<Real*> aoa(hp_bld_airfoil_aoa.data(), n_bld_sections);
416 Gpu::AsyncArray<Real*> Cl(hp_bld_airfoil_Cl.data(), n_bld_sections);
417 Gpu::AsyncArray<Real*> Cd(hp_bld_airfoil_Cd.data(), n_bld_sections);
419 auto d_bld_airfoil_aoa_ptr = aoa.data();
420 auto d_bld_airfoil_Cl_ptr = Cl.data();
421 auto d_bld_airfoil_Cd_ptr = Cd.data();
425 Gpu::DeviceVector<Real> d_velocity(n_spec_extra);
426 Gpu::DeviceVector<Real> d_rotor_RPM(n_spec_extra);
427 Gpu::DeviceVector<Real> d_blade_pitch(n_spec_extra);
429 Gpu::copy(Gpu::hostToDevice,
velocity.begin(),
velocity.end(), d_velocity.begin());
430 Gpu::copy(Gpu::hostToDevice,
rotor_RPM.begin(),
rotor_RPM.end(), d_rotor_RPM.begin());
433 auto d_velocity_ptr = d_velocity.data();
434 auto d_rotor_RPM_ptr = d_rotor_RPM.data();
435 auto d_blade_pitch_ptr = d_blade_pitch.data();
437 for ( MFIter mfi(cons_in,TilingIfNotGPU()); mfi.isValid(); ++mfi) {
439 const Box& gbx = mfi.growntilebox(1);
440 auto SMark_array = mf_SMark.array(mfi);
441 auto generalAD_array = mf_vars_generalAD.array(mfi);
443 ParallelFor(gbx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept {
444 int ii = amrex::min(amrex::max(i, domlo_x), domhi_x);
445 int jj = amrex::min(amrex::max(j, domlo_y), domhi_y);
446 int kk = amrex::min(amrex::max(k, domlo_z), domhi_z);
448 Real
x = ProbLoArr[0] + (ii+0.5)*dx[0];
449 Real
y = ProbLoArr[1] + (jj+0.5)*dx[1];
450 Real
z = ProbLoArr[2] + (kk+0.5)*dx[2];
455 Real source_x = 0.0, source_y = 0.0, source_z = 0.0;
456 std::array<Real,2> Fn_and_Ft;
458 for(
long unsigned int it=0;it<nturbs;it++) {
459 Real avg_vel = d_freestream_velocity_ptr[it]/(d_disk_cell_count_ptr[it] + 1e-10);
460 Real phi = d_turb_disk_angle;
463 if(SMark_array(ii,jj,kk,1) ==
static_cast<double>(it)) {
467 Real rad = std::pow( (
x-d_xloc_ptr[it])*(
x-d_xloc_ptr[it]) +
468 (
y-d_yloc_ptr[it])*(
y-d_yloc_ptr[it]) +
469 (
z-d_hub_height)*(
z-d_hub_height), 0.5 );
476 if(rad >= 2.0 and rad <= d_rotor_rad) {
482 Real vec_proj = (
x-d_xloc_ptr[it])*(std::sin(phi)) +
483 (
y-d_yloc_ptr[it])*(-std::cos(phi));
486 Real zeta = std::atan2(
z-d_hub_height, vec_proj);
493 d_bld_airfoil_aoa_ptr[index],
494 d_bld_airfoil_Cl_ptr[index],
495 d_bld_airfoil_Cd_ptr[index],
502 Real Fn = 3.0*Fn_and_Ft[0];
503 Real Ft = 3.0*Fn_and_Ft[1];
506 Real Fx = Fn*std::cos(phi) + Ft*std::sin(zeta)*std::sin(phi);
507 Real Fy = Fn*std::sin(phi) - Ft*std::sin(zeta)*std::cos(phi);
508 Real Fz = -Ft*std::cos(zeta);
512 source_x = -Fx/(2.0*
PI*rad*dx[0])*1.0/std::pow(2.0*
PI,0.5);
513 source_y = -Fy/(2.0*
PI*rad*dx[0])*1.0/std::pow(2.0*
PI,0.5);
514 source_z = -Fz/(2.0*
PI*rad*dx[0])*1.0/std::pow(2.0*
PI,0.5);
523 amrex::Error(
"Actuator disks are overlapping. Visualize actuator_disks.vtk "
524 "and check the windturbine locations input file. Exiting..");
527 generalAD_array(i,j,k,0) = source_x;
528 generalAD_array(i,j,k,1) = source_y;
529 generalAD_array(i,j,k,2) = source_z;
AMREX_FORCE_INLINE AMREX_GPU_DEVICE int find_rad_loc_index(const Real rad, const Real *bld_rad_loc, const int n_bld_sections)
Definition: ERF_AdvanceGeneralAD.cpp:174
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)
Definition: ERF_AdvanceGeneralAD.cpp:207
constexpr amrex::Real PI
Definition: ERF_Constants.H:6
amrex::Vector< amrex::Vector< amrex::Real > > bld_airfoil_Cl
Definition: ERF_GeneralAD.H:53
amrex::Vector< amrex::Real > velocity
Definition: ERF_GeneralAD.H:54
amrex::Vector< amrex::Real > blade_pitch
Definition: ERF_GeneralAD.H:54
amrex::Vector< amrex::Real > C_P
Definition: ERF_GeneralAD.H:54
amrex::Vector< amrex::Real > bld_twist
Definition: ERF_GeneralAD.H:52
amrex::Vector< amrex::Real > bld_chord
Definition: ERF_GeneralAD.H:52
amrex::Vector< amrex::Real > bld_rad_loc
Definition: ERF_GeneralAD.H:52
amrex::Real turb_disk_angle
Definition: ERF_GeneralAD.H:48
amrex::Vector< amrex::Real > C_T
Definition: ERF_GeneralAD.H:54
amrex::Vector< amrex::Vector< amrex::Real > > bld_airfoil_aoa
Definition: ERF_GeneralAD.H:53
amrex::Vector< amrex::Real > rotor_RPM
Definition: ERF_GeneralAD.H:54
amrex::Vector< amrex::Vector< amrex::Real > > bld_airfoil_Cd
Definition: ERF_GeneralAD.H:53
void get_turb_spec_extra(amrex::Vector< amrex::Real > &velocity, amrex::Vector< amrex::Real > &C_P, amrex::Vector< amrex::Real > &C_T, amrex::Vector< amrex::Real > &rotor_RPM, amrex::Vector< amrex::Real > &blade_pitch)
Definition: ERF_NullWindFarm.H:126
void get_blade_airfoil_spec(amrex::Vector< amrex::Vector< amrex::Real >> &bld_airfoil_aoa, amrex::Vector< amrex::Vector< amrex::Real >> &bld_airfoil_Cl, amrex::Vector< amrex::Vector< amrex::Real >> &bld_airfoil_Cd)
Definition: ERF_NullWindFarm.H:117
void get_turb_disk_angle(amrex::Real &turb_disk_angle)
Definition: ERF_NullWindFarm.H:103
void get_blade_spec(amrex::Vector< amrex::Real > &bld_rad_loc, amrex::Vector< amrex::Real > &bld_twist, amrex::Vector< amrex::Real > &bld_chord)
Definition: ERF_NullWindFarm.H:108