ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
WindFarm Class Reference

#include <ERF_WindFarm.H>

Inheritance diagram for WindFarm:
Collaboration diagram for WindFarm:

Public Member Functions

 WindFarm ()
 
virtual ~WindFarm ()=default
 
 WindFarm (int nlev, const WindFarmType &a_windfarm_type)
 
void read_tables (std::string windfarm_loc_table, std::string windfarm_spec_table, bool x_y, bool lat_lon, const amrex::Real windfarm_x_shift=zero, const amrex::Real windfarm_y_shift=zero)
 
void init_windfarm_lat_lon (const std::string windfarm_loc_table, const amrex::Real windfarm_x_shift, const amrex::Real windfarm_y_shift)
 
void init_windfarm_x_y (const std::string windfarm_loc_table)
 
void read_windfarm_locations_table (const std::string windfarm_loc_table, bool x_y, bool lat_lon, const amrex::Real windfarm_x_shift=zero, const amrex::Real windfarm_y_shift=zero)
 
void read_windfarm_spec_table (const std::string windfarm_spec_table)
 
void read_windfarm_blade_table (const std::string windfarm_blade_table)
 
void read_windfarm_airfoil_tables (const std::string windfarm_airfoil_tables, const std::string windfarm_blade_table)
 
void read_windfarm_spec_table_extra (const std::string windfarm_spec_table_extra)
 
void fill_Nturb_multifab (const amrex::Geometry &geom, amrex::MultiFab &mf_Nturb, std::unique_ptr< amrex::MultiFab > &z_phys_nd)
 
void fill_SMark_multifab (const amrex::Geometry &geom, amrex::MultiFab &mf_SMark, const amrex::Real &sampling_distance_by_D, const amrex::Real &turb_disk_angle, std::unique_ptr< amrex::MultiFab > &z_phys_cc)
 
void fill_SMark_multifab_mesoscale_models (const amrex::Geometry &geom, amrex::MultiFab &mf_SMark, const amrex::MultiFab &mf_Nturb, std::unique_ptr< amrex::MultiFab > &z_phys_cc)
 
void write_turbine_locations_vtk ()
 
void write_actuator_disks_vtk (const amrex::Geometry &geom, const amrex::Real &sampling_distance_by_D)
 
void advance (const amrex::Geometry &a_geom, const double &dt_advance, amrex::MultiFab &cons_in, amrex::MultiFab &mf_vars_windfarm, amrex::MultiFab &U_old, amrex::MultiFab &V_old, amrex::MultiFab &W_old, const amrex::MultiFab &mf_Nturb, const amrex::MultiFab &mf_SMark, const double &time) override
 
void set_turb_spec (const amrex::Real &a_rotor_rad, const amrex::Real &a_hub_height, const amrex::Real &a_thrust_coeff_standing, const amrex::Vector< amrex::Real > &a_wind_speed, const amrex::Vector< amrex::Real > &a_thrust_coeff, const amrex::Vector< amrex::Real > &a_power) override
 
void set_turb_loc (const amrex::Vector< amrex::Real > &a_xloc, const amrex::Vector< amrex::Real > &a_yloc) override
 
void set_turb_disk_angle (const amrex::Real &a_turb_disk_angle) override
 
void set_blade_spec (const amrex::Vector< amrex::Real > &a_bld_rad_loc, const amrex::Vector< amrex::Real > &a_bld_twist, const amrex::Vector< amrex::Real > &a_bld_chord) override
 
void set_blade_airfoil_spec (const amrex::Vector< amrex::Vector< amrex::Real >> &a_bld_airfoil_aoa, const amrex::Vector< amrex::Vector< amrex::Real >> &a_bld_airfoil_Cl, const amrex::Vector< amrex::Vector< amrex::Real >> &a_bld_airfoil_Cd) override
 
void set_turb_spec_extra (const amrex::Vector< amrex::Real > &a_velocity, const amrex::Vector< amrex::Real > &a_C_P, const amrex::Vector< amrex::Real > &a_C_T, const amrex::Vector< amrex::Real > &a_rotor_RPM, const amrex::Vector< amrex::Real > &a_blade_pitch) override
 
- Public Member Functions inherited from NullWindFarm
 NullWindFarm ()
 
virtual ~NullWindFarm ()=default
 
void get_turb_spec (amrex::Real &rotor_rad, amrex::Real &hub_height, amrex::Real &thrust_coeff_standing, amrex::Vector< amrex::Real > &wind_speed, amrex::Vector< amrex::Real > &thrust_coeff, amrex::Vector< amrex::Real > &power)
 
void get_turb_loc (amrex::Vector< amrex::Real > &xloc, amrex::Vector< amrex::Real > &yloc)
 
void get_turb_disk_angle (amrex::Real &turb_disk_angle)
 
void get_blade_spec (amrex::Vector< amrex::Real > &bld_rad_loc, amrex::Vector< amrex::Real > &bld_twist, amrex::Vector< amrex::Real > &bld_chord)
 
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)
 
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)
 

Protected Member Functions

template<class NewWindFarmModel >
void SetModel ()
 Create and set the specified windfarm model. More...
 

Protected Attributes

amrex::Vector< amrex::Realxloc
 
amrex::Vector< amrex::Realyloc
 
amrex::Vector< amrex::Realzloc
 
amrex::Real my_turb_disk_angle
 
amrex::Real hub_height
 
amrex::Real rotor_rad
 
amrex::Real thrust_coeff_standing
 
amrex::Real nominal_power
 
amrex::Vector< amrex::Realwind_speed
 
amrex::Vector< amrex::Realthrust_coeff
 
amrex::Vector< amrex::Realpower
 
amrex::Vector< amrex::Realbld_rad_loc
 
amrex::Vector< amrex::Realbld_twist
 
amrex::Vector< amrex::Realbld_chord
 
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
 
int n_bld_sections
 
amrex::Vector< amrex::Realvelocity
 
amrex::Vector< amrex::RealC_P
 
amrex::Vector< amrex::RealC_T
 
amrex::Vector< amrex::Realrotor_RPM
 
amrex::Vector< amrex::Realblade_pitch
 
- Protected Attributes inherited from NullWindFarm
amrex::Vector< amrex::Realm_xloc
 
amrex::Vector< amrex::Realm_yloc
 
amrex::Real m_turb_disk_angle
 
amrex::Real m_hub_height
 
amrex::Real m_rotor_rad
 
amrex::Real m_thrust_coeff_standing
 
amrex::Real m_nominal_power
 
amrex::Vector< amrex::Realm_wind_speed
 
amrex::Vector< amrex::Realm_thrust_coeff
 
amrex::Vector< amrex::Realm_power
 
amrex::Vector< amrex::Realm_bld_rad_loc
 
amrex::Vector< amrex::Realm_bld_twist
 
amrex::Vector< amrex::Realm_bld_chord
 
amrex::Vector< amrex::Vector< amrex::Real > > m_bld_airfoil_aoa
 
amrex::Vector< amrex::Vector< amrex::Real > > m_bld_airfoil_Cl
 
amrex::Vector< amrex::Vector< amrex::Real > > m_bld_airfoil_Cd
 
amrex::Vector< amrex::Realm_velocity
 
amrex::Vector< amrex::Realm_C_P
 
amrex::Vector< amrex::Realm_C_T
 
amrex::Vector< amrex::Realm_rotor_RPM
 
amrex::Vector< amrex::Realm_blade_pitch
 

Private Attributes

amrex::Vector< std::unique_ptr< NullWindFarm > > m_windfarm_model
 

Additional Inherited Members

- Static Public Member Functions inherited from NullWindFarm
static AMREX_GPU_DEVICE bool find_if_marked (amrex::Real x1, amrex::Real x2, amrex::Real y1, amrex::Real y2, amrex::Real x0, amrex::Real y0, amrex::Real nx, amrex::Real ny, amrex::Real d_hub_height, amrex::Real d_rotor_rad, amrex::Real z)
 

Constructor & Destructor Documentation

◆ WindFarm() [1/2]

WindFarm::WindFarm ( )
inline
18 {}

◆ ~WindFarm()

virtual WindFarm::~WindFarm ( )
virtualdefault

◆ WindFarm() [2/2]

WindFarm::WindFarm ( int  nlev,
const WindFarmType &  a_windfarm_type 
)
inline
24  {
25  m_windfarm_model.resize(nlev);
26  if (a_windfarm_type == WindFarmType::Fitch) {
27  SetModel<Fitch>();
28  amrex::Print() << "Fitch windfarm model!\n";
29  }
30  else if (a_windfarm_type == WindFarmType::EWP) {
31  SetModel<EWP>();
32  amrex::Print() << "EWP windfarm model!\n";
33  }
34  else if (a_windfarm_type == WindFarmType::SimpleAD) {
35  SetModel<SimpleAD>();
36  amrex::Print() << "Simplified actuator disk windfarm model!\n";
37  }
38  else if (a_windfarm_type == WindFarmType::GeneralAD) {
39  SetModel<GeneralAD>();
40  amrex::Print() << "Generalized actuator disk windfarm model!\n";
41  }
42  else {
43  amrex::Abort("WindFarm: Dont know this windfarm_type!") ;
44  }
45  }
amrex::Vector< std::unique_ptr< NullWindFarm > > m_windfarm_model
Definition: ERF_WindFarm.H:172

Member Function Documentation

◆ advance()

void WindFarm::advance ( const amrex::Geometry &  a_geom,
const double &  dt_advance,
amrex::MultiFab &  cons_in,
amrex::MultiFab &  mf_vars_windfarm,
amrex::MultiFab &  U_old,
amrex::MultiFab &  V_old,
amrex::MultiFab &  W_old,
const amrex::MultiFab &  mf_Nturb,
const amrex::MultiFab &  mf_SMark,
const double &  time 
)
inlineoverridevirtual

Implements NullWindFarm.

103  {
104  m_windfarm_model[0]->advance(a_geom, dt_advance, cons_in, mf_vars_windfarm,
105  U_old, V_old, W_old, mf_Nturb, mf_SMark, time);
106  }

◆ fill_Nturb_multifab()

void WindFarm::fill_Nturb_multifab ( const amrex::Geometry &  geom,
amrex::MultiFab &  mf_Nturb,
std::unique_ptr< amrex::MultiFab > &  z_phys_nd 
)
379 {
380 
381  zloc.resize(xloc.size(),zero);
382  Vector<int> is_counted;
383  is_counted.resize(xloc.size(),0);
384 
385  amrex::Gpu::DeviceVector<Real> d_xloc(xloc.size());
386  amrex::Gpu::DeviceVector<Real> d_yloc(yloc.size());
387  amrex::Gpu::DeviceVector<Real> d_zloc(xloc.size());
388  amrex::Gpu::DeviceVector<int> d_is_counted(xloc.size());
389  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, xloc.begin(), xloc.end(), d_xloc.begin());
390  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, yloc.begin(), yloc.end(), d_yloc.begin());
391  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, zloc.begin(), zloc.end(), d_zloc.begin());
392  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, is_counted.begin(), is_counted.end(), d_is_counted.begin());
393 
394  Real* d_xloc_ptr = d_xloc.data();
395  Real* d_yloc_ptr = d_yloc.data();
396  Real* d_zloc_ptr = d_zloc.data();
397  int* d_is_counted_ptr = d_is_counted.data();
398 
399  mf_Nturb.setVal(0);
400 
401  int i_lo = geom.Domain().smallEnd(0); int i_hi = geom.Domain().bigEnd(0);
402  int j_lo = geom.Domain().smallEnd(1); int j_hi = geom.Domain().bigEnd(1);
403  auto dx = geom.CellSizeArray();
404  if(dx[0]<= 1e-3 or dx[1]<=1e-3 or dx[2]<= 1e-3) {
405  Abort("The value of grid spacing for wind farm parametrization cannot be less than 1e-3 m. "
406  "It should be usually of order 1 m");
407  }
408  auto ProbLoArr = geom.ProbLoArray();
409  auto ProbHiArr = geom.ProbHiArray();
410  int num_turb = xloc.size();
411 
412  bool is_terrain = z_phys_nd ? true: false;
413 
414  // Initialize wind farm
415  for ( MFIter mfi(mf_Nturb,TilingIfNotGPU()); mfi.isValid(); ++mfi) {
416  const Box& bx = mfi.tilebox();
417  auto Nturb_array = mf_Nturb.array(mfi);
418  const Array4<const Real>& z_nd_arr = z_phys_nd->const_array(mfi);
419  int k0 = bx.smallEnd()[2];
420  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
421  int li = amrex::min(amrex::max(i, i_lo), i_hi);
422  int lj = amrex::min(amrex::max(j, j_lo), j_hi);
423 
424  Real x1 = ProbLoArr[0] + li*dx[0];
425  Real x2 = ProbLoArr[0] + (li+1)*dx[0];
426  Real y1 = ProbLoArr[1] + lj*dx[1];
427  Real y2 = ProbLoArr[1] + (lj+1)*dx[1];
428 
429  for(int it=0; it<num_turb; it++){
430  if( d_xloc_ptr[it]+1e-3 > x1 and d_xloc_ptr[it]+1e-3 < x2 and
431  d_yloc_ptr[it]+1e-3 > y1 and d_yloc_ptr[it]+1e-3 < y2){
432  Nturb_array(i,j,k,0) = Nturb_array(i,j,k,0) + 1;
433  // Perform atomic operations to ensure "increment only once"
434  if (is_terrain) {
435  int expected = 0;
436  int desired = 1;
437  // Atomic Compare-And-Swap: Increment only if d_is_counted_ptr[it] was 0
438  if (Gpu::Atomic::CAS(&d_is_counted_ptr[it], expected, desired) == expected) {
439  // The current thread successfully set d_is_counted_ptr[it] from 0 to 1
440  Gpu::Atomic::Add(&d_zloc_ptr[it], z_nd_arr(i, j, k0));
441  }
442  }
443  }
444  }
445  });
446  }
447 
448  Gpu::copy(Gpu::deviceToHost, d_zloc.begin(), d_zloc.end(), zloc.begin());
449  Gpu::copy(Gpu::deviceToHost, d_is_counted.begin(), d_is_counted.end(), is_counted.begin());
450 
451  amrex::ParallelAllReduce::Sum(zloc.data(),
452  zloc.size(),
453  amrex::ParallelContext::CommunicatorAll());
454 
455  amrex::ParallelAllReduce::Sum(is_counted.data(),
456  is_counted.size(),
457  amrex::ParallelContext::CommunicatorAll());
458 
459  for(int it=0;it<num_turb;it++) {
460  if(is_terrain and
461  xloc[it] > ProbLoArr[0] and
462  xloc[it] < ProbHiArr[0] and
463  yloc[it] > ProbLoArr[1] and
464  yloc[it] < ProbHiArr[1] ) {
465  if(is_counted[it] != 1) {
466  Abort("Wind turbine " + std::to_string(it) + "has been counted " + std::to_string(is_counted[it]) + " times" +
467  " It should have been counted only once. Aborting....");
468  }
469  }
470  }
471 
472  // Debugging
473  /*int my_rank = amrex::ParallelDescriptor::MyProc();
474 
475  for(int it=0;it<num_turb;it++) {
476  std::cout << "The value of zloc is " << my_rank << " " << zloc[it] << " " << is_counted[it] << "\n";
477  }*/
478 }
constexpr amrex::Real zero
Definition: ERF_Constants.H:8
const Real dx
Definition: ERF_InitCustomPert_ABL.H:23
ParallelFor(fab_box, [=] AMREX_GPU_DEVICE(int i, int j, int k) { qrcuten_arr(i, j, k)=Real(0);qscuten_arr(i, j, k)=Real(0);qicuten_arr(i, j, k)=Real(0);})
amrex::Real Real
Definition: ERF_ShocInterface.H:19
amrex::Vector< amrex::Real > yloc
Definition: ERF_WindFarm.H:153
amrex::Vector< amrex::Real > zloc
Definition: ERF_WindFarm.H:153
amrex::Vector< amrex::Real > xloc
Definition: ERF_WindFarm.H:153
Here is the call graph for this function:

◆ fill_SMark_multifab()

void WindFarm::fill_SMark_multifab ( const amrex::Geometry &  geom,
amrex::MultiFab &  mf_SMark,
const amrex::Real sampling_distance_by_D,
const amrex::Real turb_disk_angle,
std::unique_ptr< amrex::MultiFab > &  z_phys_cc 
)
538 {
539  // Copy turbine locations to device
540  Gpu::DeviceVector<Real> d_xloc(xloc.size());
541  Gpu::DeviceVector<Real> d_yloc(yloc.size());
542  Gpu::DeviceVector<Real> d_zloc(zloc.size());
543 
544  Gpu::copy(Gpu::hostToDevice, xloc.begin(), xloc.end(), d_xloc.begin());
545 
546  Gpu::copy(Gpu::hostToDevice, yloc.begin(), yloc.end(), d_yloc.begin());
547 
548  Gpu::copy(Gpu::hostToDevice, zloc.begin(), zloc.end(), d_zloc.begin());
549 
550  Real d_rotor_rad = rotor_rad;
551  Real d_hub_height = hub_height;
552  Real d_sampling_distance = sampling_distance_by_D * two * rotor_rad;
553 
554  Real* d_xloc_ptr = d_xloc.data();
555  Real* d_yloc_ptr = d_yloc.data();
556  Real* d_zloc_ptr = d_zloc.data();
557 
558  mf_SMark.setVal(-1.0);
559 
560  const int i_lo = geom.Domain().smallEnd(0);
561  const int i_hi = geom.Domain().bigEnd(0);
562  const int j_lo = geom.Domain().smallEnd(1);
563  const int j_hi = geom.Domain().bigEnd(1);
564  const int k_lo = geom.Domain().smallEnd(2);
565  const int k_hi = geom.Domain().bigEnd(2);
566 
567  auto dx = geom.CellSizeArray();
568  auto ProbLoArr = geom.ProbLoArray();
569 
570  const int num_turb = static_cast<int>(xloc.size());
571 
572  Real theta = turb_disk_angle * M_PI / Real(180.0) - myhalf * M_PI;
573 
576 
577  Real nx = -std::cos(theta);
578  Real ny = -std::sin(theta);
579 
580  // ------------------------------------------------------------
581  // Device-side overlap information
582  //
583  // overlap_info[0] = overlap flag
584  // overlap_info[1] = first turbine index
585  // overlap_info[2] = second turbine index
586  // ------------------------------------------------------------
587 
588  int h_overlap_info[3] = {0, -1, -1};
589 
590  Gpu::DeviceVector<int> d_overlap_info(3);
591 
592  Gpu::copy(Gpu::hostToDevice, h_overlap_info, h_overlap_info + 3, d_overlap_info.begin());
593 
594  int* d_overlap_info_ptr = d_overlap_info.data();
595 
596  // ------------------------------------------------------------
597  // Initialize wind farm
598  // ------------------------------------------------------------
599 
600  for (MFIter mfi(mf_SMark, TilingIfNotGPU()); mfi.isValid(); ++mfi)
601  {
602  const Box& gbx = mfi.growntilebox(1);
603 
604  auto SMark_array = mf_SMark.array(mfi);
605 
606  const Array4<const Real>& z_cc_arr = z_phys_cc->const_array(mfi);
607 
608  ParallelFor(
609  gbx,
610  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
611  {
612  int ii = amrex::min(amrex::max(i, i_lo), i_hi);
613  int jj = amrex::min(amrex::max(j, j_lo), j_hi);
614  int kk = amrex::min(amrex::max(k, k_lo), k_hi);
615 
616  // ------------------------------------------------
617  // Mesh-cell x/y extents
618  // ------------------------------------------------
619 
620  Real x1 = ProbLoArr[0] + ii * dx[0];
621  Real x2 = ProbLoArr[0] + (ii + 1) * dx[0];
622 
623  Real y1 = ProbLoArr[1] + jj * dx[1];
624  Real y2 = ProbLoArr[1] + (jj + 1) * dx[1];
625 
626  // ------------------------------------------------
627  // Cell-centered physical z
628  // ------------------------------------------------
629 
630  Real z = z_cc_arr(ii, jj, kk);
631 
632  int check_int = 0;
633  int first_turb = -1;
634 
635  for (int it = 0; it < num_turb; ++it)
636  {
637  Real z0 = d_zloc_ptr[it];
638 
639  // ------------------------------------------------
640  // Sampling point upstream/downstream of turbine
641  // ------------------------------------------------
642 
643  Real x0 = d_xloc_ptr[it] + d_sampling_distance * nx;
644 
645  Real y0 = d_yloc_ptr[it] + d_sampling_distance * ny;
646 
647  bool is_cell_marked =
649  x1, x2, y1, y2,
650  x0, y0,
651  nx, ny,
652  d_hub_height + z0,
653  d_rotor_rad,
654  z);
655 
656  if (is_cell_marked)
657  {
658  SMark_array(i, j, k, 0) = it;
659  }
660 
661  // ------------------------------------------------
662  // Actual turbine disk
663  // ------------------------------------------------
664 
665  x0 = d_xloc_ptr[it];
666  y0 = d_yloc_ptr[it];
667 
668  is_cell_marked =
670  x1, x2, y1, y2,
671  x0, y0,
672  nx, ny,
673  d_hub_height + z0,
674  d_rotor_rad,
675  z);
676 
677  if (is_cell_marked)
678  {
679  SMark_array(i, j, k, 1) = it;
680 
681  if (check_int == 0)
682  {
683  first_turb = it;
684  }
685 
686  ++check_int;
687 
688  // ------------------------------------------------
689  // More than one turbine disk marks this cell
690  // ------------------------------------------------
691 
692  if (check_int > 1)
693  {
694  // Set overlap flag.
695  amrex::Gpu::Atomic::Exch(&d_overlap_info_ptr[0], 1);
696 
697  // Save the turbine indices. Multiple threads
698  // may write these, so use atomics.
699  amrex::Gpu::Atomic::Exch(&d_overlap_info_ptr[1], first_turb);
700 
701  amrex::Gpu::Atomic::Exch(&d_overlap_info_ptr[2], it);
702  }
703  }
704  }
705  });
706  }
707 
708  // ------------------------------------------------------------
709  // Copy overlap information back to host.
710  // This also synchronizes the GPU work.
711  // ------------------------------------------------------------
712 
713  Gpu::copy(Gpu::deviceToHost, d_overlap_info.begin(), d_overlap_info.end(), h_overlap_info);
714 
715  // ------------------------------------------------------------
716  // Handle overlap on the HOST, not inside the GPU kernel.
717  // ------------------------------------------------------------
718 
719  if (h_overlap_info[0] != 0)
720  {
721  amrex::Error(
722  "Actuator disks with indices " + std::to_string(h_overlap_info[1]) +
723  " and " + std::to_string(h_overlap_info[2]) + " are overlapping. "
724  "Visualize actuator_disks.vtk and check the "
725  "windturbine locations input file. Exiting..");
726  }
727 }
constexpr amrex::Real two
Definition: ERF_Constants.H:10
constexpr amrex::Real myhalf
Definition: ERF_Constants.H:13
#define M_PI
Definition: ERF_HurricaneDiagnostics.cpp:26
Real z0
Definition: ERF_InitCustomPertVels_ScalarAdvDiff.H:8
static AMREX_GPU_DEVICE bool find_if_marked(amrex::Real x1, amrex::Real x2, amrex::Real y1, amrex::Real y2, amrex::Real x0, amrex::Real y0, amrex::Real nx, amrex::Real ny, amrex::Real d_hub_height, amrex::Real d_rotor_rad, amrex::Real z)
Definition: ERF_NullWindFarm.H:140
amrex::Real my_turb_disk_angle
Definition: ERF_WindFarm.H:154
amrex::Real hub_height
Definition: ERF_WindFarm.H:155
amrex::Real rotor_rad
Definition: ERF_WindFarm.H:155
void set_turb_disk_angle(const amrex::Real &a_turb_disk_angle) override
Definition: ERF_WindFarm.H:123
@ theta
Definition: ERF_SLM.H:20
Here is the call graph for this function:

◆ fill_SMark_multifab_mesoscale_models()

void WindFarm::fill_SMark_multifab_mesoscale_models ( const amrex::Geometry &  geom,
amrex::MultiFab &  mf_SMark,
const amrex::MultiFab &  mf_Nturb,
std::unique_ptr< amrex::MultiFab > &  z_phys_cc 
)
485 {
486  mf_SMark.setVal(-1.0);
487 
488  Real d_hub_height = hub_height;
489 
490  amrex::Gpu::DeviceVector<Real> d_xloc(xloc.size());
491  amrex::Gpu::DeviceVector<Real> d_yloc(yloc.size());
492  amrex::Gpu::DeviceVector<Real> d_zloc(xloc.size());
493  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, xloc.begin(), xloc.end(), d_xloc.begin());
494  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, yloc.begin(), yloc.end(), d_yloc.begin());
495  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, zloc.begin(), zloc.end(), d_zloc.begin());
496 
497  int i_lo = geom.Domain().smallEnd(0); int i_hi = geom.Domain().bigEnd(0);
498  int j_lo = geom.Domain().smallEnd(1); int j_hi = geom.Domain().bigEnd(1);
499  int k_lo = geom.Domain().smallEnd(2); int k_hi = geom.Domain().bigEnd(2);
500 
501  //auto dx = geom.CellSizeArray();
502  //auto ProbLoArr = geom.ProbLoArray();
503 
504  // Initialize wind farm
505  for ( MFIter mfi(mf_SMark,TilingIfNotGPU()); mfi.isValid(); ++mfi) {
506 
507  const Box& gbx = mfi.growntilebox(1);
508  auto SMark_array = mf_SMark.array(mfi);
509  auto Nturb_array = mf_Nturb.array(mfi);
510  const Array4<const Real>& z_nd_arr = z_phys_nd->const_array(mfi);
511  int k0 = std::max(gbx.smallEnd(2), geom.Domain().smallEnd(2));
512 
513  ParallelFor(gbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
514  if(Nturb_array(i,j,k,0) > 0) {
515  int li = amrex::min(amrex::max(i, i_lo), i_hi);
516  int lj = amrex::min(amrex::max(j, j_lo), j_hi);
517  int lk = amrex::min(amrex::max(k, k_lo), k_hi);
518 
519  Real z1 = z_nd_arr(li,lj,lk );
520  Real z2 = z_nd_arr(li,lj,lk+1);
521 
522  Real zturb = z_nd_arr(li,lj,k0) + d_hub_height;
523  if (zturb+1e-3 > z1 and zturb+1e-3 < z2) {
524  SMark_array(i,j,k,0) = one;
525  }
526  }
527  });
528  }
529 }
constexpr amrex::Real one
Definition: ERF_Constants.H:9
Here is the call graph for this function:

◆ init_windfarm_lat_lon()

void WindFarm::init_windfarm_lat_lon ( const std::string  windfarm_loc_table,
const amrex::Real  windfarm_x_shift,
const amrex::Real  windfarm_y_shift 
)
58 {
59 
60  // Read turbine locations from windturbines.txt
61  std::ifstream file(windfarm_loc_table);
62  if (!file.is_open()) {
63  amrex::Error("Wind turbines location table not found. Either the inputs is missing the"
64  " erf.windfarm_loc_table entry or the file specified in the entry " + windfarm_loc_table + " is missing.");
65  }
66  // Vector of vectors to store the matrix
67  Vector<Real> lat, lon;
68  Real value1, value2, value3;
69 
70  while (file >> value1 >> value2 >> value3) {
71 
72  if(std::fabs(value1) > Real(90.0)) {
73  amrex::Error("The value of latitude for entry " + std::to_string(lat.size() + 1) +
74  " in " + windfarm_loc_table + " should be within -90 and 90");
75  }
76 
77  if(std::fabs(value2) > Real(180.0)) {
78  amrex::Error("The value of longitude for entry " + std::to_string(lat.size() + 1) +
79  " in " + windfarm_loc_table + " should be within -180 and 180");
80  }
81  lat.push_back(value1);
82  lon.push_back(value2);
83  }
84  file.close();
85 
86  Real rad_earth = Real(6371.0e3); // Radius of the earth
87  Real m_per_deg_lat = rad_earth*two*M_PI/(two*Real(180.0));
88 
89  // Find the coordinates of average of min and max of the farm
90  // Rotate about that point
91  ParmParse pp("erf");
92  std::string fname_usgs;
93  auto valid_fname_USGS = pp.query("terrain_file_name_USGS",fname_usgs);
94  Real lon_ref, lat_ref;
95 
96  if (valid_fname_USGS) {
97  std::ifstream file_usgs(fname_usgs);
98  file_usgs >> lon_ref >> lat_ref;
99  file_usgs.close();
100  lon_ref = lon_ref*M_PI/Real(180.0);
101  lat_ref = lat_ref*M_PI/Real(180.0);
102  } else {
103  Real lat_min = *std::min_element(lat.begin(), lat.end());
104  Real lon_min = *std::min_element(lon.begin(), lon.end());
105 
106  lon_ref = lon_min*M_PI/Real(180.0);
107  lat_ref = lat_min*M_PI/Real(180.0);
108  }
109 
110 
111  for(int it=0;it<lat.size();it++){
112  lat[it] = lat[it]*M_PI/Real(180.0);
113  lon[it] = lon[it]*M_PI/Real(180.0);
114  Real delta_lat = (lat[it] - lat_ref);
115  Real delta_lon = (lon[it] - lon_ref);
116 
117  Real term1 = amrex::Math::powi<2>(sin(delta_lat/two));
118  Real term2 = cos(lat[it])*cos(lat_ref)*amrex::Math::powi<2>(sin(delta_lon/two));
119  Real dist = two*rad_earth*std::asin(std::sqrt(term1 + term2));
120  Real dy_turb = delta_lat * m_per_deg_lat * Real(180.0)/M_PI ;
121 
122  if(dist<dy_turb){
123  if(std::fabs(dist-dy_turb)<1e-8){
124  dist=dy_turb;
125  }
126  else{
127  Abort("The value of dist is less than dy_turb "+ std::to_string(dist) + " " + std::to_string(dy_turb));
128  }
129  }
130  Real tmp = amrex::Math::powi<2>(dist) - amrex::Math::powi<2>(dy_turb);
131 
132  if(std::fabs(tmp)<1e-8){
133  tmp = zero;
134  }
135  Real dx_turb = std::sqrt(tmp);
136 
137 
138  if(delta_lon >= zero) {
139  xloc.push_back(dx_turb);
140  }
141  else {
142  xloc.push_back(-dx_turb);
143  }
144  yloc.push_back(dy_turb);
145  }
146 
147  for(int it = 0;it<xloc.size(); it++){
148  xloc[it] = xloc[it] + windfarm_x_shift;
149  yloc[it] = yloc[it] + windfarm_y_shift;
150  }
151 }
ParmParse pp("prob")
@ tmp
Definition: ERF_AdvanceWSM6.cpp:114
Here is the call graph for this function:

◆ init_windfarm_x_y()

void WindFarm::init_windfarm_x_y ( const std::string  windfarm_loc_table)
155 {
156  // Read turbine locations from windturbines.txt
157  std::ifstream file(windfarm_loc_table);
158  if (!file.is_open()) {
159  amrex::Error("Wind turbines location table not found. Either the inputs is missing the"
160  " erf.windfarm_loc_table entry or the file specified in the entry " + windfarm_loc_table + " is missing.");
161  }
162  // Vector of vectors to store the matrix
163  Real value1, value2;
164 
165  while (file >> value1 >> value2) {
166  value1 = value1 + 1e-3;
167  value2 = value2 + 1e-3;
168  xloc.push_back(value1);
169  yloc.push_back(value2);
170  }
171  file.close();
172 }

◆ read_tables()

void WindFarm::read_tables ( std::string  windfarm_loc_table,
std::string  windfarm_spec_table,
bool  x_y,
bool  lat_lon,
const amrex::Real  windfarm_x_shift = zero,
const amrex::Real  windfarm_y_shift = zero 
)

Read in the turbine locations in latitude-longitude from windturbines.txt and convert it into x and y coordinates in metres

Parameters
levInteger specifying the current level
24 {
25  amrex::Print() << "Reading wind turbine locations table" << "\n";
26  read_windfarm_locations_table(windfarm_loc_table,
27  x_y, lat_lon,
28  windfarm_x_shift, windfarm_y_shift);
29 
30  amrex::Print() << "Reading wind turbine specifications table" << "\n";
31  read_windfarm_spec_table(windfarm_spec_table);
32 }
void read_windfarm_spec_table(const std::string windfarm_spec_table)
Definition: ERF_WindFarm.cpp:176
void read_windfarm_locations_table(const std::string windfarm_loc_table, bool x_y, bool lat_lon, const amrex::Real windfarm_x_shift=zero, const amrex::Real windfarm_y_shift=zero)
Definition: ERF_WindFarm.cpp:35

◆ read_windfarm_airfoil_tables()

void WindFarm::read_windfarm_airfoil_tables ( const std::string  windfarm_airfoil_tables,
const std::string  windfarm_blade_table 
)
298 {
299  DIR* dir;
300  struct dirent* entry;
301  std::vector<std::string> files;
302 
303  // Check if directory exists
304  if ((dir = opendir(windfarm_airfoil_tables.c_str())) == nullptr) {
305  Abort("You are using a generalized actuator disk model based on blade element theory. This needs info of airfoil"
306  " cross sections over the span of the blade. There needs to be an entry erf.airfoil_tables which is the directory that"
307  " contains the angle of attack, Cl, Cd data for each airfoil cross-section. Either the entry is missing or the directory specified"
308  " in the entry - " + windfarm_airfoil_tables + " is missing. Exiting...");
309  }
310 
311  // Loop through directory entries and collect filenames
312  while ((entry = readdir(dir)) != nullptr) {
313  // Skip special directory entries "." and ".."
314  if (std::string(entry->d_name) == "." || std::string(entry->d_name) == "..") {
315  continue;
316  }
317  files.emplace_back(windfarm_airfoil_tables + "/" + entry->d_name); // Add file path to vector
318  }
319 
320  // Close the directory
321  closedir(dir);
322 
323  if (files.empty()) {
324  Abort("It seems the directory containing the info of airfoil cross sections of the blades - " + windfarm_airfoil_tables +
325  " is empty. Exiting...");
326  }
327 
328  if(files.size() != static_cast<long double>(n_bld_sections)) {
329  printf("There are %d airfoil sections in the last column of %s. But the number"
330  " of files in %s is only %ld.\n", n_bld_sections, windfarm_blade_table.c_str(),
331  windfarm_airfoil_tables.c_str(), files.size());
332  Abort("The number of blade sections from " + windfarm_blade_table + " should match the number of"
333  " files in " + windfarm_airfoil_tables + ". Exiting...");
334  }
335 
336  // Sort filenames in lexicographical (alphabetical) order
337  std::sort(files.begin(), files.end());
338 
339  // Process each file
340  int count = 0;
344  for (const auto& filePath : files) {
345  std::ifstream filename(filePath.c_str());
346 
347  if (!filename.is_open()) {
348  std::cerr << "Failed to open file: " << filePath << std::endl;
349  continue; // Move on to the next file
350  }
351 
352  std::cout << "Reading file: " << filePath << std::endl;
353 
354  std::string line;
355  for (int i = 0; i < 54; ++i) {
356  if (std::getline(filename, line)) { // Read one line into the array
357  }
358  }
359 
360  Real var1, var2, var3, temp;
361 
362  while(filename >> var1 >> var2 >> var3 >> temp) {
363  bld_airfoil_aoa[count].push_back(var1);
364  bld_airfoil_Cl[count].push_back(var2);
365  bld_airfoil_Cd[count].push_back(var3);
366  //int idx = bld_airfoil_aoa.size()-1;
367  //printf("Values are = %0.15g %0.15g %0.15g\n", bld_airfoil_aoa[idx], bld_airfoil_Cl[idx], bld_airfoil_Cd[idx]);
368  }
369  count++;
370  }
371 
373 }
amrex::Vector< amrex::Vector< amrex::Real > > bld_airfoil_Cl
Definition: ERF_WindFarm.H:158
amrex::Vector< amrex::Vector< amrex::Real > > bld_airfoil_aoa
Definition: ERF_WindFarm.H:158
amrex::Vector< amrex::Vector< amrex::Real > > bld_airfoil_Cd
Definition: ERF_WindFarm.H:158
int n_bld_sections
Definition: ERF_WindFarm.H:159
void set_blade_airfoil_spec(const amrex::Vector< amrex::Vector< amrex::Real >> &a_bld_airfoil_aoa, const amrex::Vector< amrex::Vector< amrex::Real >> &a_bld_airfoil_Cl, const amrex::Vector< amrex::Vector< amrex::Real >> &a_bld_airfoil_Cd) override
Definition: ERF_WindFarm.H:135

◆ read_windfarm_blade_table()

void WindFarm::read_windfarm_blade_table ( const std::string  windfarm_blade_table)
225 {
226  std::ifstream filename(windfarm_blade_table);
227  std::string line;
228  Real temp, var1, var2, var3;
229  if (!filename.is_open()) {
230  Error("You are using a generalized actuator disk model based on blade element theory. This needs info of blades."
231  " An entry erf.windfarm_blade_table is needed. Either the entry is missing or the file specified"
232  " in the entry - " + windfarm_blade_table + " is missing.");
233  }
234  else {
235  Print() << "Reading in wind farm blade table: " << windfarm_blade_table << "\n";
236 
237  // First 6 lines are comments
238 
239  for (int i = 0; i < 6; ++i) {
240  if (std::getline(filename, line)) { // Read one line into the array
241  }
242  }
243 
244  while(filename >> var1 >> temp >> temp >> temp >> var2 >> var3 >> temp) {
245  bld_rad_loc.push_back(var1);
246  bld_twist.push_back(var2);
247  bld_chord.push_back(var3);
248  //int idx = bld_rad_loc.size()-1;
249  //printf("Values are = %0.15g %0.15g %0.15g\n", bld_rad_loc[idx], bld_twist[idx], bld_chord[idx]);
250  }
252  n_bld_sections = bld_rad_loc.size();
253  }
254 }
void set_blade_spec(const amrex::Vector< amrex::Real > &a_bld_rad_loc, const amrex::Vector< amrex::Real > &a_bld_twist, const amrex::Vector< amrex::Real > &a_bld_chord) override
Definition: ERF_WindFarm.H:128
amrex::Vector< amrex::Real > bld_twist
Definition: ERF_WindFarm.H:157
amrex::Vector< amrex::Real > bld_chord
Definition: ERF_WindFarm.H:157
amrex::Vector< amrex::Real > bld_rad_loc
Definition: ERF_WindFarm.H:157

◆ read_windfarm_locations_table()

void WindFarm::read_windfarm_locations_table ( const std::string  windfarm_loc_table,
bool  x_y,
bool  lat_lon,
const amrex::Real  windfarm_x_shift = zero,
const amrex::Real  windfarm_y_shift = zero 
)
39 {
40  if(x_y) {
41  init_windfarm_x_y(windfarm_loc_table);
42  }
43  else if(lat_lon) {
44  init_windfarm_lat_lon(windfarm_loc_table, windfarm_x_shift, windfarm_y_shift);
45  }
46  else {
47  amrex::Abort("Are you using windfarms? For windfarm simulations, the inputs need to have an"
48  " entry erf.windfarm_loc_type which should be either lat_lon or x_y. \n");
49  }
50 
52 }
void set_turb_loc(const amrex::Vector< amrex::Real > &a_xloc, const amrex::Vector< amrex::Real > &a_yloc) override
Definition: ERF_WindFarm.H:117
void init_windfarm_x_y(const std::string windfarm_loc_table)
Definition: ERF_WindFarm.cpp:154
void init_windfarm_lat_lon(const std::string windfarm_loc_table, const amrex::Real windfarm_x_shift, const amrex::Real windfarm_y_shift)
Definition: ERF_WindFarm.cpp:55

◆ read_windfarm_spec_table()

void WindFarm::read_windfarm_spec_table ( const std::string  windfarm_spec_table)
177 {
178  //The first line is the number of pairs entries for the power curve and thrust coefficient.
179  //The second line gives first the height in meters of the turbine hub, second, the diameter in
180  //meters of the rotor, third the standing thrust coefficient, and fourth the nominal power of
181  //the turbine in MW.
182  //The remaining lines contain the three values of: wind speed, thrust coefficient, and power production in kW.
183 
184  // Read turbine data from wind-turbine-1.tbl
185  std::ifstream file_turb_table(windfarm_spec_table);
186  if (!file_turb_table.is_open()) {
187  Error("Wind farm specifications table not found. Either the inputs is missing the "
188  "erf.windfarm_spec_table entry or the file specified in the entry - " + windfarm_spec_table + " is missing.");
189  }
190  else {
191  Print() << "Reading in wind farm specifications table: " << windfarm_spec_table << "\n";
192  }
193 
194  int nlines;
195  file_turb_table >> nlines;
196  wind_speed.resize(nlines);
197  thrust_coeff.resize(nlines);
198  power.resize(nlines);
199 
200  Real rotor_dia;
201  file_turb_table >> hub_height >> rotor_dia >> thrust_coeff_standing >> nominal_power;
202  rotor_rad = rotor_dia*myhalf;
203  if(rotor_rad > hub_height) {
204  Abort("The blade length is more than the hub height. Check the second line in wind-turbine-1.tbl. Aborting.....");
205  }
206  if(thrust_coeff_standing > one) {
207  Abort("The standing thrust coefficient is greater than one. Check the second line in wind-turbine-1.tbl. Aborting.....");
208  }
209 
210  for(int iline=0;iline<nlines;iline++){
211  file_turb_table >> wind_speed[iline] >> thrust_coeff[iline] >> power[iline];
212  if(thrust_coeff[iline] > one) {
213  Abort("The thrust coefficient is greater than one. Check wind-turbine-1.tbl. Aborting.....");
214  }
215  }
216  file_turb_table.close();
217 
220 
221 }
amrex::Vector< amrex::Real > wind_speed
Definition: ERF_WindFarm.H:156
amrex::Vector< amrex::Real > thrust_coeff
Definition: ERF_WindFarm.H:156
amrex::Real nominal_power
Definition: ERF_WindFarm.H:155
void set_turb_spec(const amrex::Real &a_rotor_rad, const amrex::Real &a_hub_height, const amrex::Real &a_thrust_coeff_standing, const amrex::Vector< amrex::Real > &a_wind_speed, const amrex::Vector< amrex::Real > &a_thrust_coeff, const amrex::Vector< amrex::Real > &a_power) override
Definition: ERF_WindFarm.H:108
amrex::Real thrust_coeff_standing
Definition: ERF_WindFarm.H:155
amrex::Vector< amrex::Real > power
Definition: ERF_WindFarm.H:156

◆ read_windfarm_spec_table_extra()

void WindFarm::read_windfarm_spec_table_extra ( const std::string  windfarm_spec_table_extra)
258 {
259  // Open the file
260  std::ifstream file(windfarm_spec_table_extra);
261 
262  // Check if file opened successfully
263  if (!file.is_open()) {
264  Abort("Error: You are using generalized wind farms option. This requires an input file erf.windfarm_spec_table_extra."
265  " Either this entry is missing in the inputs or the file specified -" + windfarm_spec_table_extra + " does"
266  " not exist. Exiting...");
267  } else {
268  printf("Reading in windfarm_spec_table_extra %s", windfarm_spec_table_extra.c_str());
269  }
270 
271  // Ignore the first line (header)
272  std::string header;
273  std::getline(file, header);
274 
275  // Variables to hold each row's values
276  double V, Cp, Ct, rpm, pitch, temp;
277 
278  // Read the file row by row
279  while (file >> V) {
280  char comma; // To ignore the commas
281  file >> comma >> Cp >> comma >> Ct >> comma >> temp >> comma >> temp >> comma
282  >> temp >> comma >> rpm >> comma >> pitch >> comma >> temp;
283 
284  velocity.push_back(V);
285  C_P.push_back(Cp);
286  C_T.push_back(Ct);
287  rotor_RPM.push_back(rpm);
288  blade_pitch.push_back(pitch);
289  }
290 
292 }
amrex::Vector< amrex::Real > blade_pitch
Definition: ERF_WindFarm.H:160
void set_turb_spec_extra(const amrex::Vector< amrex::Real > &a_velocity, const amrex::Vector< amrex::Real > &a_C_P, const amrex::Vector< amrex::Real > &a_C_T, const amrex::Vector< amrex::Real > &a_rotor_RPM, const amrex::Vector< amrex::Real > &a_blade_pitch) override
Definition: ERF_WindFarm.H:142
amrex::Vector< amrex::Real > velocity
Definition: ERF_WindFarm.H:160
amrex::Vector< amrex::Real > C_P
Definition: ERF_WindFarm.H:160
amrex::Vector< amrex::Real > C_T
Definition: ERF_WindFarm.H:160
amrex::Vector< amrex::Real > rotor_RPM
Definition: ERF_WindFarm.H:160
@ V
Definition: ERF_IndexDefines.H:124

◆ set_blade_airfoil_spec()

void WindFarm::set_blade_airfoil_spec ( const amrex::Vector< amrex::Vector< amrex::Real >> &  a_bld_airfoil_aoa,
const amrex::Vector< amrex::Vector< amrex::Real >> &  a_bld_airfoil_Cl,
const amrex::Vector< amrex::Vector< amrex::Real >> &  a_bld_airfoil_Cd 
)
inlineoverridevirtual

Reimplemented from NullWindFarm.

138  {
139  m_windfarm_model[0]->set_blade_airfoil_spec(a_bld_airfoil_aoa, a_bld_airfoil_Cl, a_bld_airfoil_Cd);
140  }

◆ set_blade_spec()

void WindFarm::set_blade_spec ( const amrex::Vector< amrex::Real > &  a_bld_rad_loc,
const amrex::Vector< amrex::Real > &  a_bld_twist,
const amrex::Vector< amrex::Real > &  a_bld_chord 
)
inlineoverridevirtual

Reimplemented from NullWindFarm.

131  {
132  m_windfarm_model[0]->set_blade_spec(a_bld_rad_loc, a_bld_twist, a_bld_chord);
133  }

◆ set_turb_disk_angle()

void WindFarm::set_turb_disk_angle ( const amrex::Real a_turb_disk_angle)
inlineoverridevirtual

Reimplemented from NullWindFarm.

124  {
125  m_windfarm_model[0]->set_turb_disk_angle(a_turb_disk_angle);
126  }

◆ set_turb_loc()

void WindFarm::set_turb_loc ( const amrex::Vector< amrex::Real > &  a_xloc,
const amrex::Vector< amrex::Real > &  a_yloc 
)
inlineoverridevirtual

Reimplemented from NullWindFarm.

119  {
120  m_windfarm_model[0]->set_turb_loc(a_xloc, a_yloc);
121  }

◆ set_turb_spec()

void WindFarm::set_turb_spec ( const amrex::Real a_rotor_rad,
const amrex::Real a_hub_height,
const amrex::Real a_thrust_coeff_standing,
const amrex::Vector< amrex::Real > &  a_wind_speed,
const amrex::Vector< amrex::Real > &  a_thrust_coeff,
const amrex::Vector< amrex::Real > &  a_power 
)
inlineoverridevirtual

Reimplemented from NullWindFarm.

112  {
113  m_windfarm_model[0]->set_turb_spec(a_rotor_rad, a_hub_height, a_thrust_coeff_standing,
114  a_wind_speed, a_thrust_coeff, a_power);
115  }

◆ set_turb_spec_extra()

void WindFarm::set_turb_spec_extra ( const amrex::Vector< amrex::Real > &  a_velocity,
const amrex::Vector< amrex::Real > &  a_C_P,
const amrex::Vector< amrex::Real > &  a_C_T,
const amrex::Vector< amrex::Real > &  a_rotor_RPM,
const amrex::Vector< amrex::Real > &  a_blade_pitch 
)
inlineoverridevirtual

Reimplemented from NullWindFarm.

147  {
148  m_windfarm_model[0]->set_turb_spec_extra(a_velocity, a_C_P, a_C_T, a_rotor_RPM, a_blade_pitch);
149  }

◆ SetModel()

template<class NewWindFarmModel >
void WindFarm::SetModel ( )
inlineprotected

Create and set the specified windfarm model.

165  {
166  for (int lev(0); lev<m_windfarm_model.size(); ++lev) {
167  m_windfarm_model[lev] = std::make_unique<NewWindFarmModel>();
168  }
169  }

◆ write_actuator_disks_vtk()

void WindFarm::write_actuator_disks_vtk ( const amrex::Geometry &  geom,
const amrex::Real sampling_distance_by_D 
)
751 {
752 
753  Real sampling_distance = sampling_distance_by_D*two*rotor_rad;
754 
755  if (ParallelDescriptor::IOProcessor()){
756  FILE *file_actuator_disks_all, *file_actuator_disks_in_dom, *file_averaging_disks_in_dom;
757  file_actuator_disks_all = fopen("actuator_disks_all.vtk","w");
758  fprintf(file_actuator_disks_all, "%s\n","# vtk DataFile Version 3.0");
759  fprintf(file_actuator_disks_all, "%s\n","Actuator Disks");
760  fprintf(file_actuator_disks_all, "%s\n","ASCII");
761  fprintf(file_actuator_disks_all, "%s\n","DATASET POLYDATA");
762 
763  file_actuator_disks_in_dom = fopen("actuator_disks_in_dom.vtk","w");
764  fprintf(file_actuator_disks_in_dom, "%s\n","# vtk DataFile Version 3.0");
765  fprintf(file_actuator_disks_in_dom, "%s\n","Actuator Disks");
766  fprintf(file_actuator_disks_in_dom, "%s\n","ASCII");
767  fprintf(file_actuator_disks_in_dom, "%s\n","DATASET POLYDATA");
768 
769  file_averaging_disks_in_dom = fopen("averaging_disks_in_dom.vtk","w");
770  fprintf(file_averaging_disks_in_dom, "%s\n","# vtk DataFile Version 3.0");
771  fprintf(file_averaging_disks_in_dom, "%s\n","Actuator Disks");
772  fprintf(file_averaging_disks_in_dom, "%s\n","ASCII");
773  fprintf(file_averaging_disks_in_dom, "%s\n","DATASET POLYDATA");
774 
775 
776  int npts = 100;
777  fprintf(file_actuator_disks_all, "%s %ld %s\n", "POINTS", xloc.size()*npts, "float");
778  auto ProbLoArr = geom.ProbLoArray();
779  auto ProbHiArr = geom.ProbHiArray();
780  int num_turb_in_dom = 0;
781 
782  // Find the number of turbines inside the specified computational domain
783 
784  for(int it=0; it<xloc.size(); it++){
785  Real x = xloc[it];
786  Real y = yloc[it];
787  if(x > ProbLoArr[0] and x < ProbHiArr[0] and y > ProbLoArr[1] and y < ProbHiArr[1]) {
788  num_turb_in_dom++;
789  }
790  }
791  fprintf(file_actuator_disks_in_dom, "%s %ld %s\n", "POINTS", static_cast<long int>(num_turb_in_dom*npts), "float");
792  fprintf(file_averaging_disks_in_dom, "%s %ld %s\n", "POINTS", static_cast<long int>(num_turb_in_dom*npts), "float");
793 
794  Real nx = std::cos(my_turb_disk_angle+myhalf*M_PI);
795  Real ny = std::sin(my_turb_disk_angle+myhalf*M_PI);
796 
797  Real nx1 = -std::cos(my_turb_disk_angle);
798  Real ny1 = -std::sin(my_turb_disk_angle);
799 
800  for(int it=0; it<xloc.size(); it++){
801  for(int pt=0;pt<100;pt++){
802  Real x, y, z, xavg, yavg;
803  Real theta = two*M_PI/npts*pt;
804  x = xloc[it] + rotor_rad*cos(theta)*nx;
805  y = yloc[it] + rotor_rad*cos(theta)*ny;
806  z = hub_height + zloc[it] + rotor_rad*sin(theta);
807 
808  xavg = xloc[it] + sampling_distance*nx1 + rotor_rad*cos(theta)*nx;
809  yavg = yloc[it] + sampling_distance*ny1 + rotor_rad*cos(theta)*ny;
810 
811  fprintf(file_actuator_disks_all, "%0.15g %0.15g %0.15g\n", x, y, z);
812  if(xloc[it] > ProbLoArr[0] and xloc[it] < ProbHiArr[0] and yloc[it] > ProbLoArr[1] and yloc[it] < ProbHiArr[1]) {
813  fprintf(file_actuator_disks_in_dom, "%0.15g %0.15g %0.15g\n", x, y, z);
814  fprintf(file_averaging_disks_in_dom, "%0.15g %0.15g %0.15g\n", xavg, yavg, z);
815  }
816  }
817  }
818  fprintf(file_actuator_disks_all, "%s %ld %ld\n", "LINES", xloc.size()*(npts-1), static_cast<long int>(xloc.size()*(npts-1)*3));
819  fprintf(file_actuator_disks_in_dom, "%s %ld %ld\n", "LINES", static_cast<long int>(num_turb_in_dom*(npts-1)), static_cast<long int>(num_turb_in_dom*(npts-1)*3));
820  fprintf(file_averaging_disks_in_dom, "%s %ld %ld\n", "LINES", static_cast<long int>(num_turb_in_dom*(npts-1)), static_cast<long int>(num_turb_in_dom*(npts-1)*3));
821  for(int it=0; it<xloc.size(); it++){
822  for(int pt=0;pt<99;pt++){
823  fprintf(file_actuator_disks_all, "%ld %ld %ld\n",
824  static_cast<long int>(2),
825  static_cast<long int>(it*npts+pt),
826  static_cast<long int>(it*npts+pt+1));
827  }
828  }
829  for(int it=0; it<num_turb_in_dom; it++){
830  for(int pt=0;pt<99;pt++){
831  fprintf(file_actuator_disks_in_dom, "%ld %ld %ld\n",
832  static_cast<long int>(2),
833  static_cast<long int>(it*npts+pt),
834  static_cast<long int>(it*npts+pt+1));
835  }
836  }
837 
838  for(int it=0; it<num_turb_in_dom; it++){
839  for(int pt=0;pt<99;pt++){
840  fprintf(file_averaging_disks_in_dom, "%ld %ld %ld\n",
841  static_cast<long int>(2),
842  static_cast<long int>(it*npts+pt),
843  static_cast<long int>(it*npts+pt+1));
844  }
845  }
846 
847  fclose(file_actuator_disks_all);
848  fclose(file_actuator_disks_in_dom);
849  fclose(file_averaging_disks_in_dom);
850  }
851 }

◆ write_turbine_locations_vtk()

void WindFarm::write_turbine_locations_vtk ( )
731 {
732  if (ParallelDescriptor::IOProcessor()){
733  FILE* file_turbloc_vtk;
734  file_turbloc_vtk = fopen("turbine_locations.vtk","w");
735  fprintf(file_turbloc_vtk, "%s\n","# vtk DataFile Version 3.0");
736  fprintf(file_turbloc_vtk, "%s\n","Wind turbine locations");
737  fprintf(file_turbloc_vtk, "%s\n","ASCII");
738  fprintf(file_turbloc_vtk, "%s\n","DATASET POLYDATA");
739  fprintf(file_turbloc_vtk, "%s %ld %s\n", "POINTS", xloc.size(), "float");
740  for(int it=0; it<xloc.size(); it++){
741  fprintf(file_turbloc_vtk, "%0.15g %0.15g %0.15g\n", xloc[it], yloc[it], hub_height);
742  }
743  fclose(file_turbloc_vtk);
744  }
745 }

Member Data Documentation

◆ blade_pitch

amrex::Vector<amrex::Real> WindFarm::blade_pitch
protected

◆ bld_airfoil_aoa

amrex::Vector<amrex::Vector<amrex::Real> > WindFarm::bld_airfoil_aoa
protected

◆ bld_airfoil_Cd

amrex::Vector<amrex::Vector<amrex::Real> > WindFarm::bld_airfoil_Cd
protected

◆ bld_airfoil_Cl

amrex::Vector<amrex::Vector<amrex::Real> > WindFarm::bld_airfoil_Cl
protected

◆ bld_chord

amrex::Vector<amrex::Real> WindFarm::bld_chord
protected

◆ bld_rad_loc

amrex::Vector<amrex::Real> WindFarm::bld_rad_loc
protected

◆ bld_twist

amrex::Vector<amrex::Real> WindFarm::bld_twist
protected

◆ C_P

amrex::Vector<amrex::Real> WindFarm::C_P
protected

◆ C_T

amrex::Vector<amrex::Real> WindFarm::C_T
protected

◆ hub_height

amrex::Real WindFarm::hub_height
protected

◆ m_windfarm_model

amrex::Vector<std::unique_ptr<NullWindFarm> > WindFarm::m_windfarm_model
private

◆ my_turb_disk_angle

amrex::Real WindFarm::my_turb_disk_angle
protected

◆ n_bld_sections

int WindFarm::n_bld_sections
protected

◆ nominal_power

amrex::Real WindFarm::nominal_power
protected

◆ power

amrex::Vector<amrex::Real> WindFarm::power
protected

◆ rotor_rad

amrex::Real WindFarm::rotor_rad
protected

◆ rotor_RPM

amrex::Vector<amrex::Real> WindFarm::rotor_RPM
protected

◆ thrust_coeff

amrex::Vector<amrex::Real> WindFarm::thrust_coeff
protected

◆ thrust_coeff_standing

amrex::Real WindFarm::thrust_coeff_standing
protected

◆ velocity

amrex::Vector<amrex::Real> WindFarm::velocity
protected

◆ wind_speed

amrex::Vector<amrex::Real> WindFarm::wind_speed
protected

◆ xloc

amrex::Vector<amrex::Real> WindFarm::xloc
protected

◆ yloc

amrex::Vector<amrex::Real> WindFarm::yloc
protected

◆ zloc

amrex::Vector<amrex::Real> WindFarm::zloc
protected

The documentation for this class was generated from the following files: