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=0.0, const amrex::Real windfarm_y_shift=0.0)
 
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=0.0, const amrex::Real windfarm_y_shift=0.0)
 
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 amrex::Real &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 amrex::Real &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::Real > xloc
 
amrex::Vector< amrex::Real > yloc
 
amrex::Vector< amrex::Real > zloc
 
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::Real > wind_speed
 
amrex::Vector< amrex::Real > thrust_coeff
 
amrex::Vector< amrex::Real > power
 
amrex::Vector< amrex::Real > bld_rad_loc
 
amrex::Vector< amrex::Real > bld_twist
 
amrex::Vector< amrex::Real > bld_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::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 Attributes inherited from NullWindFarm
amrex::Vector< amrex::Real > m_xloc
 
amrex::Vector< amrex::Real > m_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::Real > m_wind_speed
 
amrex::Vector< amrex::Real > m_thrust_coeff
 
amrex::Vector< amrex::Real > m_power
 
amrex::Vector< amrex::Real > m_bld_rad_loc
 
amrex::Vector< amrex::Real > m_bld_twist
 
amrex::Vector< amrex::Real > m_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::Real > m_velocity
 
amrex::Vector< amrex::Real > m_C_P
 
amrex::Vector< amrex::Real > m_C_T
 
amrex::Vector< amrex::Real > m_rotor_RPM
 
amrex::Vector< amrex::Real > m_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 amrex::Real &  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 amrex::Real &  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(),0.0);
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 mesh 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) ? z_phys_nd->const_array(mfi) : Array4<Real>{};
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 }
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

◆ 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 
)
542 {
543  amrex::Gpu::DeviceVector<Real> d_xloc(xloc.size());
544  amrex::Gpu::DeviceVector<Real> d_yloc(yloc.size());
545  amrex::Gpu::DeviceVector<Real> d_zloc(yloc.size());
546  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, xloc.begin(), xloc.end(), d_xloc.begin());
547  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, yloc.begin(), yloc.end(), d_yloc.begin());
548  amrex::Gpu::copyAsync(amrex::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*2.0*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  int i_lo = geom.Domain().smallEnd(0); int i_hi = geom.Domain().bigEnd(0);
561  int j_lo = geom.Domain().smallEnd(1); int j_hi = geom.Domain().bigEnd(1);
562  int k_lo = geom.Domain().smallEnd(2); int k_hi = geom.Domain().bigEnd(2);
563  auto dx = geom.CellSizeArray();
564  auto ProbLoArr = geom.ProbLoArray();
565  int num_turb = xloc.size();
566 
567  Real theta = turb_disk_angle*M_PI/180.0-0.5*M_PI;
568 
571 
572  Real nx = -std::cos(theta);
573  Real ny = -std::sin(theta);
574 
575  // Initialize wind farm
576  for ( MFIter mfi(mf_SMark,TilingIfNotGPU()); mfi.isValid(); ++mfi) {
577  //const Box& bx = mfi.tilebox();
578  const Box& gbx = mfi.growntilebox(1);
579  auto SMark_array = mf_SMark.array(mfi);
580 
581  const Array4<const Real>& z_cc_arr = (z_phys_cc) ? z_phys_cc->const_array(mfi) : Array4<Real>{};
582 
583  ParallelFor(gbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
584  int ii = amrex::min(amrex::max(i, i_lo), i_hi);
585  int jj = amrex::min(amrex::max(j, j_lo), j_hi);
586  int kk = amrex::min(amrex::max(k, k_lo), k_hi);
587 
588  // The x and y extents of the current mesh cell
589 
590  Real x1 = ProbLoArr[0] + ii*dx[0];
591  Real x2 = ProbLoArr[0] + (ii+1)*dx[0];
592  Real y1 = ProbLoArr[1] + jj*dx[1];
593  Real y2 = ProbLoArr[1] + (jj+1)*dx[1];
594 
595  // The mesh cell centered z value
596 
597  Real z = (z_cc_arr) ? z_cc_arr(ii,jj,kk) : ProbLoArr[2] + (kk+0.5) * dx[2];
598 
599  int turb_indices_overlap[2];
600  int check_int = 0;
601  for(int it=0; it<num_turb; it++){
602  Real x0 = d_xloc_ptr[it] + d_sampling_distance*nx;
603  Real y0 = d_yloc_ptr[it] + d_sampling_distance*ny;
604 
605  Real z0 = 0.0;
606  if(z_cc_arr) {
607  z0 = d_zloc_ptr[it];
608  }
609 
610  bool is_cell_marked = find_if_marked(x1, x2, y1, y2, x0, y0,
611  nx, ny, d_hub_height+z0, d_rotor_rad, z);
612  if(is_cell_marked) {
613  SMark_array(i,j,k,0) = it;
614  }
615  x0 = d_xloc_ptr[it];
616  y0 = d_yloc_ptr[it];
617 
618  is_cell_marked = find_if_marked(x1, x2, y1, y2, x0, y0,
619  nx, ny, d_hub_height+z0, d_rotor_rad, z);
620  if(is_cell_marked) {
621  SMark_array(i,j,k,1) = it;
622  turb_indices_overlap[check_int] = it;
623  check_int++;
624  if(check_int > 1){
625  printf("Actuator disks with indices %d and %d are overlapping\n",
626  turb_indices_overlap[0],turb_indices_overlap[1]);
627  amrex::Error("Actuator disks are overlapping. Visualize actuator_disks.vtk "
628  " and check the windturbine locations input file. Exiting..");
629  }
630  }
631  }
632  });
633  }
634 }
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_MM5.H:20

◆ 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& bx = mfi.tilebox();
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) ? z_phys_nd->const_array(mfi) : Array4<Real>{};
511  int k0 = bx.smallEnd()[2];
512 
513  ParallelFor(bx, [=] 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) ? z_nd_arr(li,lj,lk) : ProbLoArr[2] + lk * dx[2];
520  Real z2 = (z_nd_arr) ? z_nd_arr(li,lj,lk+1) : ProbLoArr[2] + (lk+1) * dx[2];
521 
522  Real zturb;
523  if(z_nd_arr) {
524  zturb = z_nd_arr(li,lj,k0) + d_hub_height;
525  } else {
526  zturb = d_hub_height;
527  }
528  if(zturb+1e-3 > z1 and zturb+1e-3 < z2) {
529  SMark_array(i,j,k,0) = 1.0;
530  }
531  }
532  });
533  }
534 }

◆ 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) > 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) > 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 = 6371.0e3; // Radius of the earth
87  Real m_per_deg_lat = rad_earth*2.0*M_PI/(2.0*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/180.0;
101  lat_ref = lat_ref*M_PI/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/180.0;
107  lat_ref = lat_min*M_PI/180.0;
108  }
109 
110 
111  for(int it=0;it<lat.size();it++){
112  lat[it] = lat[it]*M_PI/180.0;
113  lon[it] = lon[it]*M_PI/180.0;
114  Real delta_lat = (lat[it] - lat_ref);
115  Real delta_lon = (lon[it] - lon_ref);
116 
117  Real term1 = std::pow(sin(delta_lat/2.0),2);
118  Real term2 = cos(lat[it])*cos(lat_ref)*std::pow(sin(delta_lon/2.0),2);
119  Real dist = 2.0*rad_earth*std::asin(std::sqrt(term1 + term2));
120  Real dy_turb = delta_lat * m_per_deg_lat * 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 = std::pow(dist,2) - std::pow(dy_turb,2);
131 
132  if(std::fabs(tmp)<1e-8){
133  tmp = 0.0;
134  }
135  Real dx_turb = std::sqrt(tmp);
136 
137 
138  if(delta_lon >= 0.0) {
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 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real pp(amrex::Real y)
Definition: ERF_MicrophysicsUtils.H:219
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 = 0.0,
const amrex::Real  windfarm_y_shift = 0.0 
)

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_locations_table(const std::string windfarm_loc_table, bool x_y, bool lat_lon, const amrex::Real windfarm_x_shift=0.0, const amrex::Real windfarm_y_shift=0.0)
Definition: ERF_WindFarm.cpp:35
void read_windfarm_spec_table(const std::string windfarm_spec_table)
Definition: ERF_WindFarm.cpp:176

◆ 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 = 0.0,
const amrex::Real  windfarm_y_shift = 0.0 
)
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*0.5;
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 > 1.0) {
207  Abort("The standing thrust coefficient is greater than 1. 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] > 1.0) {
213  Abort("The thrust coefficient is greater than 1. 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:98

◆ 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 
)
658 {
659 
660  Real sampling_distance = sampling_distance_by_D*2.0*rotor_rad;
661 
662  if (ParallelDescriptor::IOProcessor()){
663  FILE *file_actuator_disks_all, *file_actuator_disks_in_dom, *file_averaging_disks_in_dom;
664  file_actuator_disks_all = fopen("actuator_disks_all.vtk","w");
665  fprintf(file_actuator_disks_all, "%s\n","# vtk DataFile Version 3.0");
666  fprintf(file_actuator_disks_all, "%s\n","Actuator Disks");
667  fprintf(file_actuator_disks_all, "%s\n","ASCII");
668  fprintf(file_actuator_disks_all, "%s\n","DATASET POLYDATA");
669 
670  file_actuator_disks_in_dom = fopen("actuator_disks_in_dom.vtk","w");
671  fprintf(file_actuator_disks_in_dom, "%s\n","# vtk DataFile Version 3.0");
672  fprintf(file_actuator_disks_in_dom, "%s\n","Actuator Disks");
673  fprintf(file_actuator_disks_in_dom, "%s\n","ASCII");
674  fprintf(file_actuator_disks_in_dom, "%s\n","DATASET POLYDATA");
675 
676  file_averaging_disks_in_dom = fopen("averaging_disks_in_dom.vtk","w");
677  fprintf(file_averaging_disks_in_dom, "%s\n","# vtk DataFile Version 3.0");
678  fprintf(file_averaging_disks_in_dom, "%s\n","Actuator Disks");
679  fprintf(file_averaging_disks_in_dom, "%s\n","ASCII");
680  fprintf(file_averaging_disks_in_dom, "%s\n","DATASET POLYDATA");
681 
682 
683  int npts = 100;
684  fprintf(file_actuator_disks_all, "%s %ld %s\n", "POINTS", xloc.size()*npts, "float");
685  auto ProbLoArr = geom.ProbLoArray();
686  auto ProbHiArr = geom.ProbHiArray();
687  int num_turb_in_dom = 0;
688 
689  // Find the number of turbines inside the specified computational domain
690 
691  for(int it=0; it<xloc.size(); it++){
692  Real x = xloc[it];
693  Real y = yloc[it];
694  if(x > ProbLoArr[0] and x < ProbHiArr[0] and y > ProbLoArr[1] and y < ProbHiArr[1]) {
695  num_turb_in_dom++;
696  }
697  }
698  fprintf(file_actuator_disks_in_dom, "%s %ld %s\n", "POINTS", static_cast<long int>(num_turb_in_dom*npts), "float");
699  fprintf(file_averaging_disks_in_dom, "%s %ld %s\n", "POINTS", static_cast<long int>(num_turb_in_dom*npts), "float");
700 
701  Real nx = std::cos(my_turb_disk_angle+0.5*M_PI);
702  Real ny = std::sin(my_turb_disk_angle+0.5*M_PI);
703 
704  Real nx1 = -std::cos(my_turb_disk_angle);
705  Real ny1 = -std::sin(my_turb_disk_angle);
706 
707  for(int it=0; it<xloc.size(); it++){
708  for(int pt=0;pt<100;pt++){
709  Real x, y, z, xavg, yavg;
710  Real theta = 2.0*M_PI/npts*pt;
711  x = xloc[it] + rotor_rad*cos(theta)*nx;
712  y = yloc[it] + rotor_rad*cos(theta)*ny;
713  z = hub_height + zloc[it] + rotor_rad*sin(theta);
714 
715  xavg = xloc[it] + sampling_distance*nx1 + rotor_rad*cos(theta)*nx;
716  yavg = yloc[it] + sampling_distance*ny1 + rotor_rad*cos(theta)*ny;
717 
718  fprintf(file_actuator_disks_all, "%0.15g %0.15g %0.15g\n", x, y, z);
719  if(xloc[it] > ProbLoArr[0] and xloc[it] < ProbHiArr[0] and yloc[it] > ProbLoArr[1] and yloc[it] < ProbHiArr[1]) {
720  fprintf(file_actuator_disks_in_dom, "%0.15g %0.15g %0.15g\n", x, y, z);
721  fprintf(file_averaging_disks_in_dom, "%0.15g %0.15g %0.15g\n", xavg, yavg, z);
722  }
723  }
724  }
725  fprintf(file_actuator_disks_all, "%s %ld %ld\n", "LINES", xloc.size()*(npts-1), static_cast<long int>(xloc.size()*(npts-1)*3));
726  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));
727  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));
728  for(int it=0; it<xloc.size(); it++){
729  for(int pt=0;pt<99;pt++){
730  fprintf(file_actuator_disks_all, "%ld %ld %ld\n",
731  static_cast<long int>(2),
732  static_cast<long int>(it*npts+pt),
733  static_cast<long int>(it*npts+pt+1));
734  }
735  }
736  for(int it=0; it<num_turb_in_dom; it++){
737  for(int pt=0;pt<99;pt++){
738  fprintf(file_actuator_disks_in_dom, "%ld %ld %ld\n",
739  static_cast<long int>(2),
740  static_cast<long int>(it*npts+pt),
741  static_cast<long int>(it*npts+pt+1));
742  }
743  }
744 
745  for(int it=0; it<num_turb_in_dom; it++){
746  for(int pt=0;pt<99;pt++){
747  fprintf(file_averaging_disks_in_dom, "%ld %ld %ld\n",
748  static_cast<long int>(2),
749  static_cast<long int>(it*npts+pt),
750  static_cast<long int>(it*npts+pt+1));
751  }
752  }
753 
754  fclose(file_actuator_disks_all);
755  fclose(file_actuator_disks_in_dom);
756  fclose(file_averaging_disks_in_dom);
757  }
758 }

◆ write_turbine_locations_vtk()

void WindFarm::write_turbine_locations_vtk ( )
638 {
639  if (ParallelDescriptor::IOProcessor()){
640  FILE* file_turbloc_vtk;
641  file_turbloc_vtk = fopen("turbine_locations.vtk","w");
642  fprintf(file_turbloc_vtk, "%s\n","# vtk DataFile Version 3.0");
643  fprintf(file_turbloc_vtk, "%s\n","Wind turbine locations");
644  fprintf(file_turbloc_vtk, "%s\n","ASCII");
645  fprintf(file_turbloc_vtk, "%s\n","DATASET POLYDATA");
646  fprintf(file_turbloc_vtk, "%s %ld %s\n", "POINTS", xloc.size(), "float");
647  for(int it=0; it<xloc.size(); it++){
648  fprintf(file_turbloc_vtk, "%0.15g %0.15g %0.15g\n", xloc[it], yloc[it], hub_height);
649  }
650  fclose(file_turbloc_vtk);
651  }
652 }

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: