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)
 
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)
 
void write_turbine_locations_vtk ()
 
void write_actuator_disks_vtk (const amrex::Geometry &geom)
 
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::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:164

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.

95  {
96  m_windfarm_model[0]->advance(a_geom, dt_advance, cons_in, mf_vars_windfarm,
97  U_old, V_old, W_old, mf_Nturb, mf_SMark, time);
98  }

◆ fill_Nturb_multifab()

void WindFarm::fill_Nturb_multifab ( const amrex::Geometry &  geom,
amrex::MultiFab &  mf_Nturb 
)
355 {
356 
357  amrex::Gpu::DeviceVector<Real> d_xloc(xloc.size());
358  amrex::Gpu::DeviceVector<Real> d_yloc(yloc.size());
359  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, xloc.begin(), xloc.end(), d_xloc.begin());
360  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, yloc.begin(), yloc.end(), d_yloc.begin());
361 
362  Real* d_xloc_ptr = d_xloc.data();
363  Real* d_yloc_ptr = d_yloc.data();
364 
365  mf_Nturb.setVal(0);
366 
367  int i_lo = geom.Domain().smallEnd(0); int i_hi = geom.Domain().bigEnd(0);
368  int j_lo = geom.Domain().smallEnd(1); int j_hi = geom.Domain().bigEnd(1);
369  auto dx = geom.CellSizeArray();
370  if(dx[0]<= 1e-3 or dx[1]<=1e-3 or dx[2]<= 1e-3) {
371  Abort("The value of mesh spacing for wind farm parametrization cannot be less than 1e-3 m. "
372  "It should be usually of order 1 m");
373  }
374  auto ProbLoArr = geom.ProbLoArray();
375  int num_turb = xloc.size();
376 
377  // Initialize wind farm
378  for ( MFIter mfi(mf_Nturb,TilingIfNotGPU()); mfi.isValid(); ++mfi) {
379  const Box& bx = mfi.tilebox();
380  auto Nturb_array = mf_Nturb.array(mfi);
381  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
382  int li = amrex::min(amrex::max(i, i_lo), i_hi);
383  int lj = amrex::min(amrex::max(j, j_lo), j_hi);
384 
385  Real x1 = ProbLoArr[0] + li*dx[0];
386  Real x2 = ProbLoArr[0] + (li+1)*dx[0];
387  Real y1 = ProbLoArr[1] + lj*dx[1];
388  Real y2 = ProbLoArr[1] + (lj+1)*dx[1];
389 
390  for(int it=0; it<num_turb; it++){
391  if( d_xloc_ptr[it]+1e-3 > x1 and d_xloc_ptr[it]+1e-3 < x2 and
392  d_yloc_ptr[it]+1e-3 > y1 and d_yloc_ptr[it]+1e-3 < y2){
393  Nturb_array(i,j,k,0) = Nturb_array(i,j,k,0) + 1;
394  }
395  }
396  });
397  }
398 }
amrex::Vector< amrex::Real > yloc
Definition: ERF_WindFarm.H:145
amrex::Vector< amrex::Real > xloc
Definition: ERF_WindFarm.H:145

◆ 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 
)
405 {
406  amrex::Gpu::DeviceVector<Real> d_xloc(xloc.size());
407  amrex::Gpu::DeviceVector<Real> d_yloc(yloc.size());
408  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, xloc.begin(), xloc.end(), d_xloc.begin());
409  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, yloc.begin(), yloc.end(), d_yloc.begin());
410 
411  Real d_rotor_rad = rotor_rad;
412  Real d_hub_height = hub_height;
413  Real d_sampling_distance = sampling_distance_by_D*2.0*rotor_rad;
414 
415  Real* d_xloc_ptr = d_xloc.data();
416  Real* d_yloc_ptr = d_yloc.data();
417 
418  mf_SMark.setVal(-1.0);
419 
420  int i_lo = geom.Domain().smallEnd(0); int i_hi = geom.Domain().bigEnd(0);
421  int j_lo = geom.Domain().smallEnd(1); int j_hi = geom.Domain().bigEnd(1);
422  int k_lo = geom.Domain().smallEnd(2); int k_hi = geom.Domain().bigEnd(2);
423  auto dx = geom.CellSizeArray();
424  auto ProbLoArr = geom.ProbLoArray();
425  int num_turb = xloc.size();
426 
427  Real theta = turb_disk_angle*M_PI/180.0-0.5*M_PI;
428 
431 
432  Real nx = -std::cos(theta);
433  Real ny = -std::sin(theta);
434 
435  // Initialize wind farm
436  for ( MFIter mfi(mf_SMark,TilingIfNotGPU()); mfi.isValid(); ++mfi) {
437  const Box& bx = mfi.tilebox();
438  auto SMark_array = mf_SMark.array(mfi);
439  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
440  int ii = amrex::min(amrex::max(i, i_lo), i_hi);
441  int jj = amrex::min(amrex::max(j, j_lo), j_hi);
442  int kk = amrex::min(amrex::max(k, k_lo), k_hi);
443 
444  Real x1 = ProbLoArr[0] + ii*dx[0];
445  Real x2 = ProbLoArr[0] + (ii+1)*dx[0];
446  Real y1 = ProbLoArr[1] + jj*dx[1];
447  Real y2 = ProbLoArr[1] + (jj+1)*dx[1];
448 
449  Real z = ProbLoArr[2] + (kk+0.5) * dx[2];
450 
451  int turb_indices_overlap[2];
452  int check_int = 0;
453  for(int it=0; it<num_turb; it++){
454  Real x0 = d_xloc_ptr[it] + d_sampling_distance*nx;
455  Real y0 = d_yloc_ptr[it] + d_sampling_distance*ny;
456 
457  bool is_cell_marked = find_if_marked(x1, x2, y1, y2, x0, y0,
458  nx, ny, d_hub_height, d_rotor_rad, z);
459  if(is_cell_marked) {
460  SMark_array(i,j,k,0) = it;
461  }
462  x0 = d_xloc_ptr[it];
463  y0 = d_yloc_ptr[it];
464  //printf("Values are %d, %0.15g, %0.15g\n", it, x0, y0);
465 
466  is_cell_marked = find_if_marked(x1, x2, y1, y2, x0, y0,
467  nx, ny, d_hub_height, d_rotor_rad, z);
468  if(is_cell_marked) {
469  SMark_array(i,j,k,1) = it;
470  turb_indices_overlap[check_int] = it;
471  check_int++;
472  if(check_int > 1){
473  printf("Actuator disks with indices %d and %d are overlapping\n",
474  turb_indices_overlap[0],turb_indices_overlap[1]);
475  amrex::Error("Actuator disks are overlapping. Visualize actuator_disks.vtk "
476  " and check the windturbine locations input file. Exiting..");
477  }
478  }
479  }
480  });
481  }
482 }
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:146
amrex::Real hub_height
Definition: ERF_WindFarm.H:147
amrex::Real rotor_rad
Definition: ERF_WindFarm.H:147
void set_turb_disk_angle(const amrex::Real &a_turb_disk_angle) override
Definition: ERF_WindFarm.H:115
@ theta
Definition: ERF_MM5.H:20

◆ 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 
)
57 {
58 
59  // Read turbine locations from windturbines.txt
60  std::ifstream file(windfarm_loc_table);
61  if (!file.is_open()) {
62  amrex::Error("Wind turbines location table not found. Either the inputs is missing the"
63  " erf.windfarm_loc_table entry or the file specified in the entry " + windfarm_loc_table + " is missing.");
64  }
65  // Vector of vectors to store the matrix
66  Vector<Real> lat, lon;
67  Real value1, value2, value3;
68 
69  while (file >> value1 >> value2 >> value3) {
70 
71  if(std::fabs(value1) > 90.0) {
72  amrex::Error("The value of latitude for entry " + std::to_string(lat.size() + 1) +
73  " in " + windfarm_loc_table + " should be within -90 and 90");
74  }
75 
76  if(std::fabs(value2) > 180.0) {
77  amrex::Error("The value of longitude for entry " + std::to_string(lat.size() + 1) +
78  " in " + windfarm_loc_table + " should be within -180 and 180");
79  }
80  lat.push_back(value1);
81  lon.push_back(value2);
82  }
83  file.close();
84 
85  Real rad_earth = 6371.0e3; // Radius of the earth
86 
87  // Find the coordinates of average of min and max of the farm
88  // Rotate about that point
89 
90  Real lat_min = *std::min_element(lat.begin(), lat.end());
91  Real lat_max = *std::max_element(lat.begin(), lat.end());
92  Real lon_min = *std::min_element(lon.begin(), lon.end());
93  Real lon_max = *std::max_element(lon.begin(), lon.end());
94 
95  Real lat_cen = 0.5*(lat_min+lat_max)*M_PI/180.0;
96  Real lon_cen = 0.5*(lon_min+lon_max)*M_PI/180.0;
97 
98  // (lat_lo, lon_lo) is mapped to (0,0)
99 
100 
101  for(int it=0;it<lat.size();it++){
102  lat[it] = lat[it]*M_PI/180.0;
103  lon[it] = lon[it]*M_PI/180.0;
104  Real delta_lat = (lat[it] - lat_cen);
105  Real delta_lon = (lon[it] - lon_cen);
106 
107  Real term1 = std::pow(sin(delta_lat/2.0),2);
108  Real term2 = cos(lat[it])*cos(lat_cen)*std::pow(sin(delta_lon/2.0),2);
109  Real dist = 2.0*rad_earth*std::asin(std::sqrt(term1 + term2));
110  Real dy_turb = (lat[it] - lat_cen) * 111000.0 * 180.0/M_PI ;
111  Real dx_turb = std::sqrt(std::pow(dist,2) - std::pow(dy_turb,2));
112  if(delta_lon >= 0.0) {
113  xloc.push_back(dx_turb);
114  }
115  else {
116  xloc.push_back(-dx_turb);
117  }
118  yloc.push_back(dy_turb);
119  }
120 
121  Real xloc_min = *std::min_element(xloc.begin(),xloc.end());
122  Real yloc_min = *std::min_element(yloc.begin(),yloc.end());
123 
124  for(int it = 0;it<xloc.size(); it++){
125  xloc[it] = xloc[it] - xloc_min + windfarm_x_shift;
126  yloc[it] = yloc[it] - yloc_min + windfarm_y_shift;
127  }
128 }

◆ init_windfarm_x_y()

void WindFarm::init_windfarm_x_y ( const std::string  windfarm_loc_table)
132 {
133  // Read turbine locations from windturbines.txt
134  std::ifstream file(windfarm_loc_table);
135  if (!file.is_open()) {
136  amrex::Error("Wind turbines location table not found. Either the inputs is missing the"
137  " erf.windfarm_loc_table entry or the file specified in the entry " + windfarm_loc_table + " is missing.");
138  }
139  // Vector of vectors to store the matrix
140  Real value1, value2;
141 
142  while (file >> value1 >> value2) {
143  value1 = value1 + 1e-3;
144  value2 = value2 + 1e-3;
145  xloc.push_back(value1);
146  yloc.push_back(value2);
147  }
148  file.close();
149 }

◆ 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
23 {
24  amrex::Print() << "Reading wind turbine locations table" << "\n";
25  read_windfarm_locations_table(windfarm_loc_table,
26  x_y, lat_lon,
27  windfarm_x_shift, windfarm_y_shift);
28 
29  amrex::Print() << "Reading wind turbine specifications table" << "\n";
30  read_windfarm_spec_table(windfarm_spec_table);
31 }
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_InitWindFarm.cpp:34
void read_windfarm_spec_table(const std::string windfarm_spec_table)
Definition: ERF_InitWindFarm.cpp:153

◆ read_windfarm_airfoil_tables()

void WindFarm::read_windfarm_airfoil_tables ( const std::string  windfarm_airfoil_tables,
const std::string  windfarm_blade_table 
)
275 {
276  DIR* dir;
277  struct dirent* entry;
278  std::vector<std::string> files;
279 
280  // Check if directory exists
281  if ((dir = opendir(windfarm_airfoil_tables.c_str())) == nullptr) {
282  Abort("You are using a generalized actuator disk model based on blade element theory. This needs info of airfoil"
283  " cross sections over the span of the blade. There needs to be an entry erf.airfoil_tables which is the directory that"
284  " contains the angle of attack, Cl, Cd data for each airfoil cross-section. Either the entry is missing or the directory specified"
285  " in the entry - " + windfarm_airfoil_tables + " is missing. Exiting...");
286  }
287 
288  // Loop through directory entries and collect filenames
289  while ((entry = readdir(dir)) != nullptr) {
290  // Skip special directory entries "." and ".."
291  if (std::string(entry->d_name) == "." || std::string(entry->d_name) == "..") {
292  continue;
293  }
294  files.emplace_back(windfarm_airfoil_tables + "/" + entry->d_name); // Add file path to vector
295  }
296 
297  // Close the directory
298  closedir(dir);
299 
300  if (files.empty()) {
301  Abort("It seems the directory containing the info of airfoil cross sections of the blades - " + windfarm_airfoil_tables +
302  " is empty. Exiting...");
303  }
304 
305  if(files.size() != static_cast<long double>(n_bld_sections)) {
306  printf("There are %d airfoil sections in the last column of %s. But the number"
307  " of files in %s is only %ld.\n", n_bld_sections, windfarm_blade_table.c_str(),
308  windfarm_airfoil_tables.c_str(), files.size());
309  Abort("The number of blade sections from " + windfarm_blade_table + " should match the number of"
310  " files in " + windfarm_airfoil_tables + ". Exiting...");
311  }
312 
313  // Sort filenames in lexicographical (alphabetical) order
314  std::sort(files.begin(), files.end());
315 
316  // Process each file
317  int count = 0;
321  for (const auto& filePath : files) {
322  std::ifstream filename(filePath.c_str());
323 
324  if (!filename.is_open()) {
325  std::cerr << "Failed to open file: " << filePath << std::endl;
326  continue; // Move on to the next file
327  }
328 
329  std::cout << "Reading file: " << filePath << std::endl;
330 
331  std::string line;
332  for (int i = 0; i < 54; ++i) {
333  if (std::getline(filename, line)) { // Read one line into the array
334  }
335  }
336 
337  Real var1, var2, var3, temp;
338 
339  while(filename >> var1 >> var2 >> var3 >> temp) {
340  bld_airfoil_aoa[count].push_back(var1);
341  bld_airfoil_Cl[count].push_back(var2);
342  bld_airfoil_Cd[count].push_back(var3);
343  //int idx = bld_airfoil_aoa.size()-1;
344  //printf("Values are = %0.15g %0.15g %0.15g\n", bld_airfoil_aoa[idx], bld_airfoil_Cl[idx], bld_airfoil_Cd[idx]);
345  }
346  count++;
347  }
348 
350 }
amrex::Vector< amrex::Vector< amrex::Real > > bld_airfoil_Cl
Definition: ERF_WindFarm.H:150
amrex::Vector< amrex::Vector< amrex::Real > > bld_airfoil_aoa
Definition: ERF_WindFarm.H:150
amrex::Vector< amrex::Vector< amrex::Real > > bld_airfoil_Cd
Definition: ERF_WindFarm.H:150
int n_bld_sections
Definition: ERF_WindFarm.H:151
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:127

◆ read_windfarm_blade_table()

void WindFarm::read_windfarm_blade_table ( const std::string  windfarm_blade_table)
202 {
203  std::ifstream filename(windfarm_blade_table);
204  std::string line;
205  Real temp, var1, var2, var3;
206  if (!filename.is_open()) {
207  Error("You are using a generalized actuator disk model based on blade element theory. This needs info of blades."
208  " An entry erf.windfarm_blade_table is needed. Either the entry is missing or the file specified"
209  " in the entry - " + windfarm_blade_table + " is missing.");
210  }
211  else {
212  Print() << "Reading in wind farm blade table: " << windfarm_blade_table << "\n";
213 
214  // First 6 lines are comments
215 
216  for (int i = 0; i < 6; ++i) {
217  if (std::getline(filename, line)) { // Read one line into the array
218  }
219  }
220 
221  while(filename >> var1 >> temp >> temp >> temp >> var2 >> var3 >> temp) {
222  bld_rad_loc.push_back(var1);
223  bld_twist.push_back(var2);
224  bld_chord.push_back(var3);
225  //int idx = bld_rad_loc.size()-1;
226  //printf("Values are = %0.15g %0.15g %0.15g\n", bld_rad_loc[idx], bld_twist[idx], bld_chord[idx]);
227  }
229  n_bld_sections = bld_rad_loc.size();
230  }
231 }
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:120
amrex::Vector< amrex::Real > bld_twist
Definition: ERF_WindFarm.H:149
amrex::Vector< amrex::Real > bld_chord
Definition: ERF_WindFarm.H:149
amrex::Vector< amrex::Real > bld_rad_loc
Definition: ERF_WindFarm.H:149

◆ 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 
)
38 {
39  if(x_y) {
40  init_windfarm_x_y(windfarm_loc_table);
41  }
42  else if(lat_lon) {
43  init_windfarm_lat_lon(windfarm_loc_table, windfarm_x_shift, windfarm_y_shift);
44  }
45  else {
46  amrex::Abort("Are you using windfarms? For windfarm simulations, the inputs need to have an"
47  " entry erf.windfarm_loc_type which should be either lat_lon or x_y. \n");
48  }
49 
51 }
void set_turb_loc(const amrex::Vector< amrex::Real > &a_xloc, const amrex::Vector< amrex::Real > &a_yloc) override
Definition: ERF_WindFarm.H:109
void init_windfarm_x_y(const std::string windfarm_loc_table)
Definition: ERF_InitWindFarm.cpp:131
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_InitWindFarm.cpp:54

◆ read_windfarm_spec_table()

void WindFarm::read_windfarm_spec_table ( const std::string  windfarm_spec_table)
154 {
155  //The first line is the number of pairs entries for the power curve and thrust coefficient.
156  //The second line gives first the height in meters of the turbine hub, second, the diameter in
157  //meters of the rotor, third the standing thrust coefficient, and fourth the nominal power of
158  //the turbine in MW.
159  //The remaining lines contain the three values of: wind speed, thrust coefficient, and power production in kW.
160 
161  // Read turbine data from wind-turbine-1.tbl
162  std::ifstream file_turb_table(windfarm_spec_table);
163  if (!file_turb_table.is_open()) {
164  Error("Wind farm specifications table not found. Either the inputs is missing the "
165  "erf.windfarm_spec_table entry or the file specified in the entry - " + windfarm_spec_table + " is missing.");
166  }
167  else {
168  Print() << "Reading in wind farm specifications table: " << windfarm_spec_table << "\n";
169  }
170 
171  int nlines;
172  file_turb_table >> nlines;
173  wind_speed.resize(nlines);
174  thrust_coeff.resize(nlines);
175  power.resize(nlines);
176 
177  Real rotor_dia;
178  file_turb_table >> hub_height >> rotor_dia >> thrust_coeff_standing >> nominal_power;
179  rotor_rad = rotor_dia*0.5;
180  if(rotor_rad > hub_height) {
181  Abort("The blade length is more than the hub height. Check the second line in wind-turbine-1.tbl. Aborting.....");
182  }
183  if(thrust_coeff_standing > 1.0) {
184  Abort("The standing thrust coefficient is greater than 1. Check the second line in wind-turbine-1.tbl. Aborting.....");
185  }
186 
187  for(int iline=0;iline<nlines;iline++){
188  file_turb_table >> wind_speed[iline] >> thrust_coeff[iline] >> power[iline];
189  if(thrust_coeff[iline] > 1.0) {
190  Abort("The thrust coefficient is greater than 1. Check wind-turbine-1.tbl. Aborting.....");
191  }
192  }
193  file_turb_table.close();
194 
197 
198 }
amrex::Vector< amrex::Real > wind_speed
Definition: ERF_WindFarm.H:148
amrex::Vector< amrex::Real > thrust_coeff
Definition: ERF_WindFarm.H:148
amrex::Real nominal_power
Definition: ERF_WindFarm.H:147
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:100
amrex::Real thrust_coeff_standing
Definition: ERF_WindFarm.H:147
amrex::Vector< amrex::Real > power
Definition: ERF_WindFarm.H:148

◆ read_windfarm_spec_table_extra()

void WindFarm::read_windfarm_spec_table_extra ( const std::string  windfarm_spec_table_extra)
235 {
236  // Open the file
237  std::ifstream file(windfarm_spec_table_extra);
238 
239  // Check if file opened successfully
240  if (!file.is_open()) {
241  Abort("Error: You are using generalized wind farms option. This requires an input file erf.windfarm_spec_table_extra."
242  " Either this entry is missing in the inputs or the file specified -" + windfarm_spec_table_extra + " does"
243  " not exist. Exiting...");
244  } else {
245  printf("Reading in windfarm_spec_table_extra %s", windfarm_spec_table_extra.c_str());
246  }
247 
248  // Ignore the first line (header)
249  std::string header;
250  std::getline(file, header);
251 
252  // Variables to hold each row's values
253  double V, Cp, Ct, rpm, pitch, temp;
254 
255  // Read the file row by row
256  while (file >> V) {
257  char comma; // To ignore the commas
258  file >> comma >> Cp >> comma >> Ct >> comma >> temp >> comma >> temp >> comma
259  >> temp >> comma >> rpm >> comma >> pitch >> comma >> temp;
260 
261  velocity.push_back(V);
262  C_P.push_back(Cp);
263  C_T.push_back(Ct);
264  rotor_RPM.push_back(rpm);
265  blade_pitch.push_back(pitch);
266  }
267 
269 }
amrex::Vector< amrex::Real > blade_pitch
Definition: ERF_WindFarm.H:152
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:134
amrex::Vector< amrex::Real > velocity
Definition: ERF_WindFarm.H:152
amrex::Vector< amrex::Real > C_P
Definition: ERF_WindFarm.H:152
amrex::Vector< amrex::Real > C_T
Definition: ERF_WindFarm.H:152
amrex::Vector< amrex::Real > rotor_RPM
Definition: ERF_WindFarm.H:152
@ 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.

130  {
131  m_windfarm_model[0]->set_blade_airfoil_spec(a_bld_airfoil_aoa, a_bld_airfoil_Cl, a_bld_airfoil_Cd);
132  }

◆ 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.

123  {
124  m_windfarm_model[0]->set_blade_spec(a_bld_rad_loc, a_bld_twist, a_bld_chord);
125  }

◆ set_turb_disk_angle()

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

Reimplemented from NullWindFarm.

116  {
117  m_windfarm_model[0]->set_turb_disk_angle(a_turb_disk_angle);
118  }

◆ 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.

111  {
112  m_windfarm_model[0]->set_turb_loc(a_xloc, a_yloc);
113  }

◆ 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.

104  {
105  m_windfarm_model[0]->set_turb_spec(a_rotor_rad, a_hub_height, a_thrust_coeff_standing,
106  a_wind_speed, a_thrust_coeff, a_power);
107  }

◆ 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.

139  {
140  m_windfarm_model[0]->set_turb_spec_extra(a_velocity, a_C_P, a_C_T, a_rotor_RPM, a_blade_pitch);
141  }

◆ SetModel()

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

Create and set the specified windfarm model.

157  {
158  for (int lev(0); lev<m_windfarm_model.size(); ++lev) {
159  m_windfarm_model[lev] = std::make_unique<NewWindFarmModel>();
160  }
161  }

◆ write_actuator_disks_vtk()

void WindFarm::write_actuator_disks_vtk ( const amrex::Geometry &  geom)
505 {
506 
507  if (ParallelDescriptor::IOProcessor()){
508  FILE *file_actuator_disks_all, *file_actuator_disks_in_dom;
509  file_actuator_disks_all = fopen("actuator_disks_all.vtk","w");
510  fprintf(file_actuator_disks_all, "%s\n","# vtk DataFile Version 3.0");
511  fprintf(file_actuator_disks_all, "%s\n","Actuator Disks");
512  fprintf(file_actuator_disks_all, "%s\n","ASCII");
513  fprintf(file_actuator_disks_all, "%s\n","DATASET POLYDATA");
514 
515  file_actuator_disks_in_dom = fopen("actuator_disks_in_dom.vtk","w");
516  fprintf(file_actuator_disks_in_dom, "%s\n","# vtk DataFile Version 3.0");
517  fprintf(file_actuator_disks_in_dom, "%s\n","Actuator Disks");
518  fprintf(file_actuator_disks_in_dom, "%s\n","ASCII");
519  fprintf(file_actuator_disks_in_dom, "%s\n","DATASET POLYDATA");
520 
521  int npts = 100;
522  fprintf(file_actuator_disks_all, "%s %ld %s\n", "POINTS", xloc.size()*npts, "float");
523  auto ProbLoArr = geom.ProbLoArray();
524  auto ProbHiArr = geom.ProbHiArray();
525  int num_turb_in_dom = 0;
526 
527  // Find the number of turbines inside the specified computational domain
528 
529  for(int it=0; it<xloc.size(); it++){
530  Real x = xloc[it];
531  Real y = yloc[it];
532  if(x > ProbLoArr[0] and x < ProbHiArr[0] and y > ProbLoArr[1] and y < ProbHiArr[1]) {
533  num_turb_in_dom++;
534  }
535  }
536  fprintf(file_actuator_disks_in_dom, "%s %ld %s\n", "POINTS", static_cast<long int>(num_turb_in_dom*npts), "float");
537 
538  Real nx = std::cos(my_turb_disk_angle+0.5*M_PI);
539  Real ny = std::sin(my_turb_disk_angle+0.5*M_PI);
540 
541  for(int it=0; it<xloc.size(); it++){
542  for(int pt=0;pt<100;pt++){
543  Real x, y, z;
544  Real theta = 2.0*M_PI/npts*pt;
545  x = xloc[it] + rotor_rad*cos(theta)*nx;
546  y = yloc[it] + rotor_rad*cos(theta)*ny;
547  z = hub_height + rotor_rad*sin(theta);
548  fprintf(file_actuator_disks_all, "%0.15g %0.15g %0.15g\n", x, y, z);
549  if(xloc[it] > ProbLoArr[0] and xloc[it] < ProbHiArr[0] and yloc[it] > ProbLoArr[1] and yloc[it] < ProbHiArr[1]) {
550  fprintf(file_actuator_disks_in_dom, "%0.15g %0.15g %0.15g\n", x, y, z);
551  }
552  }
553  }
554  fprintf(file_actuator_disks_all, "%s %ld %ld\n", "LINES", xloc.size()*(npts-1), static_cast<long int>(xloc.size()*(npts-1)*3));
555  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));
556  for(int it=0; it<xloc.size(); it++){
557  for(int pt=0;pt<99;pt++){
558  fprintf(file_actuator_disks_all, "%ld %ld %ld\n",
559  static_cast<long int>(2),
560  static_cast<long int>(it*npts+pt),
561  static_cast<long int>(it*npts+pt+1));
562  }
563  }
564  for(int it=0; it<num_turb_in_dom; it++){
565  for(int pt=0;pt<99;pt++){
566  fprintf(file_actuator_disks_in_dom, "%ld %ld %ld\n",
567  static_cast<long int>(2),
568  static_cast<long int>(it*npts+pt),
569  static_cast<long int>(it*npts+pt+1));
570  }
571  }
572 
573  fclose(file_actuator_disks_all);
574  fclose(file_actuator_disks_in_dom);
575  }
576 }

◆ write_turbine_locations_vtk()

void WindFarm::write_turbine_locations_vtk ( )
486 {
487  if (ParallelDescriptor::IOProcessor()){
488  FILE* file_turbloc_vtk;
489  file_turbloc_vtk = fopen("turbine_locations.vtk","w");
490  fprintf(file_turbloc_vtk, "%s\n","# vtk DataFile Version 3.0");
491  fprintf(file_turbloc_vtk, "%s\n","Wind turbine locations");
492  fprintf(file_turbloc_vtk, "%s\n","ASCII");
493  fprintf(file_turbloc_vtk, "%s\n","DATASET POLYDATA");
494  fprintf(file_turbloc_vtk, "%s %ld %s\n", "POINTS", xloc.size(), "float");
495  for(int it=0; it<xloc.size(); it++){
496  fprintf(file_turbloc_vtk, "%0.15g %0.15g %0.15g\n", xloc[it], yloc[it], hub_height);
497  }
498  fclose(file_turbloc_vtk);
499  }
500 }

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

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