source: palm/trunk/SOURCE/wind_turbine_model_mod.f90 @ 4573

Last change on this file since 4573 was 4537, checked in by oliver.maas, 4 years ago

reset n_turbines_max to 1E4 (10 000), because it was set to 1 000 in r4497 by mistake

  • Property svn:keywords set to Id
File size: 143.8 KB
RevLine 
[1820]1!> @file wind_turbine_model_mod.f90
[4497]2!--------------------------------------------------------------------------------------------------!
[2696]3! This file is part of the PALM model system.
[1819]4!
[4497]5! PALM is free software: you can redistribute it and/or modify it under the terms of the GNU General
6! Public License as published by the Free Software Foundation, either version 3 of the License, or
7! (at your option) any later version.
[1819]8!
[4497]9! PALM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
10! implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11! Public License for more details.
[1819]12!
[4497]13! You should have received a copy of the GNU General Public License along with PALM. If not, see
14! <http://www.gnu.org/licenses/>.
[1819]15!
[4481]16! Copyright 2009-2020 Carl von Ossietzky Universitaet Oldenburg
[4360]17! Copyright 1997-2020 Leibniz Universitaet Hannover
[4497]18!--------------------------------------------------------------------------------------------------!
[1819]19!
[4497]20!
[1819]21! Current revisions:
22! -----------------
[1913]23!
[4438]24!
[1913]25! Former revisions:
26! -----------------
27! $Id: wind_turbine_model_mod.f90 4537 2020-05-18 06:31:50Z oliver.maas $
[4537]28! reset n_turbines_max to 1E4 (10 000), because it was set to 1 000 in r4497 by mistake
29!
30! 4535 2020-05-15 12:07:23Z raasch
[4535]31! bugfix for restart data format query
32!
33! 4528 2020-05-11 14:14:09Z oliver.maas
[4528]34! added namelist parameter smearing_kernel_size
35!
36! 4497 2020-04-15 10:20:51Z raasch
[4497]37! file re-formatted to follow the PALM coding standard
38!
39!
40! 4495 2020-04-13 20:11:20Z raasch
[4495]41! restart data handling with MPI-IO added
42!
43! 4481 2020-03-31 18:55:54Z maronga
[4467]44! ASCII output cleanup
[4497]45!
[4467]46! 4465 2020-03-20 11:35:48Z maronga
[4497]47! Removed old ASCII outputm, some syntax layout adjustments, added output for rotor and tower
48! diameters. Added warning message in case of NetCDF 3 (no WTM output file will be produced).
49!
[4465]50! 4460 2020-03-12 16:47:30Z oliver.maas
[4460]51! allow for simulating up to 10 000 wind turbines
[4497]52!
[4460]53! 4459 2020-03-12 09:35:23Z oliver.maas
[4459]54! avoid division by zero in tip loss correction factor calculation
[4497]55!
[4459]56! 4457 2020-03-11 14:20:43Z raasch
[4457]57! use statement for exchange horiz added
[4497]58!
[4457]59! 4447 2020-03-06 11:05:30Z oliver.maas
[4447]60! renamed wind_turbine_parameters namelist variables
[4497]61!
[4447]62! 4438 2020-03-03 20:49:28Z suehring
[4438]63! Bugfix: shifted netcdf preprocessor directive to correct position
[4497]64!
[4438]65! 4436 2020-03-03 12:47:02Z oliver.maas
[4434]66! added optional netcdf data input for wtm array input parameters
[4497]67!
[4434]68! 4426 2020-02-27 10:02:19Z oliver.maas
[4497]69! define time as unlimited dimension so that no maximum number of time steps has to be given for
70! wtm_data_output
71!
[4426]72! 4423 2020-02-25 07:17:11Z maronga
[4423]73! Switched to serial output as data is aggerated before anyway.
[4497]74!
[4423]75! 4420 2020-02-24 14:13:56Z maronga
[4420]76! Added output control for wind turbine model
[4497]77!
[4420]78! 4412 2020-02-19 14:53:13Z maronga
[4412]79! Bugfix: corrected character length in dimension_names
[4497]80!
[4412]81! 4411 2020-02-18 14:28:02Z maronga
[4411]82! Added output in NetCDF format using DOM (only netcdf4-parallel is supported).
83! Old ASCII output is still available at the moment.
[4497]84!
[4411]85! 4360 2020-01-07 11:25:50Z suehring
[4497]86! Introduction of wall_flags_total_0, which currently sets bits based on static topography
87! information used in wall_flags_static_0
88!
[4346]89! 4343 2019-12-17 12:26:12Z oliver.maas
[4497]90! replaced <= by < in line 1464 to ensure that ialpha will not be greater than dlen
91!
[4343]92! 4329 2019-12-10 15:46:36Z motisi
[4329]93! Renamed wall_flags_0 to wall_flags_static_0
[4497]94!
[4329]95! 4326 2019-12-06 14:16:14Z oliver.maas
[4497]96! changed format of turbine control output to allow for higher torque and power values
97!
[4326]98! 4182 2019-08-22 15:20:23Z scharf
[4182]99! Corrected "Former revisions" section
[4497]100!
[4182]101! 4144 2019-08-06 09:11:47Z raasch
[4144]102! relational operators .EQ., .NE., etc. replaced by ==, /=, etc.
[4497]103!
[4144]104! 4056 2019-06-27 13:53:16Z Giersch
[4497]105! CASE DEFAULT action in wtm_actions needs to be CONTINUE. Otherwise an abort will happen for
106! location values that are not implemented as CASE statements but are already realized in the code
107! (e.g. pt-tendency)
108!
[4056]109! 3885 2019-04-11 11:29:34Z kanani
[4497]110! Changes related to global restructuring of location messages and introduction of additional debug
111! messages
112!
[3885]113! 3875 2019-04-08 17:35:12Z knoop
[3875]114! Addaped wtm_tendency to fit the module actions interface
[4497]115!
[3875]116! 3832 2019-03-28 13:16:58Z raasch
[3832]117! instrumented with openmp directives
[4497]118!
[3832]119! 3725 2019-02-07 10:11:02Z raasch
[3725]120! unused variables removed
[4497]121!
[3725]122! 3685 2019-01-21 01:02:11Z knoop
[3685]123! Some interface calls moved to module_interface + cleanup
[4497]124!
[3685]125! 3655 2019-01-07 16:51:22Z knoop
[3593]126! Replace degree symbol by 'degrees'
[4497]127!
[4182]128! 1914 2016-05-26 14:44:07Z witha
129! Initial revision
[3593]130!
[4497]131!
[1819]132! Description:
133! ------------
[4497]134!> This module calculates the effect of wind turbines on the flow fields. The initial version
135!> contains only the advanced actuator disk with rotation method (ADM-R).
[1819]136!> The wind turbines include the tower effect, can be yawed and tilted.
[4497]137!> The wind turbine model includes controllers for rotational speed, pitch and yaw.
138!> Currently some specifications of the NREL 5 MW reference turbine are hardcoded whereas most input
139!> data comes from separate files (currently external, planned to be included as namelist which will
140!> be read in automatically).
[1819]141!>
[3065]142!> @todo Replace dz(1) appropriatly to account for grid stretching
[1819]143!> @todo Revise code according to PALM Coding Standard
144!> @todo Implement ADM and ALM turbine models
145!> @todo Generate header information
[1917]146!> @todo Implement further parameter checks and error messages
[1819]147!> @todo Revise and add code documentation
148!> @todo Output turbine parameters as timeseries
149!> @todo Include additional output variables
[1864]150!> @todo Revise smearing the forces for turbines in yaw
151!> @todo Revise nacelle and tower parameterization
152!> @todo Allow different turbine types in one simulation
[1819]153!
[4497]154!--------------------------------------------------------------------------------------------------!
[1819]155 MODULE wind_turbine_model_mod
156
[4497]157    USE arrays_3d,                                                                                 &
[2553]158        ONLY:  tend, u, v, w, zu, zw
[1819]159
[4497]160    USE basic_constants_and_equations_mod,                                                         &
[2553]161        ONLY:  pi
[1819]162
[4497]163    USE control_parameters,                                                                        &
164        ONLY:  coupling_char,                                                                      &
165               debug_output,                                                                       &
166               dt_3d, dz, end_time, initializing_actions, message_string,                          &
167               origin_date_time, restart_data_format_output, time_since_reference_point,           &
168               wind_turbine
[1819]169
[4497]170    USE cpulog,                                                                                    &
[1819]171        ONLY:  cpu_log, log_point_s
172
[4411]173    USE data_output_module
[4497]174
175    USE grid_variables,                                                                            &
[1819]176        ONLY:  ddx, dx, ddy, dy
177
[4497]178    USE indices,                                                                                   &
179        ONLY:  nbgp, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg, nz,                       &
[4346]180               nzb, nzt, wall_flags_total_0
[1819]181
182    USE kinds
183
[4497]184    USE netcdf_data_input_mod,                                                                     &
185        ONLY:  check_existence,                                                                    &
186               close_input_file,                                                                   &
187               get_variable,                                                                       &
188               input_pids_wtm,                                                                     &
189               inquire_num_variables,                                                              &
190               inquire_variable_names,                                                             &
191               input_file_wtm,                                                                     &
192               num_var_pids,                                                                       &
193               open_read_file,                                                                     &
194               pids_id,                                                                            &
[4434]195               vars_pids
[4497]196
[1819]197    USE pegrid
198
[4495]199    USE restart_data_mpi_io_mod,                                                                   &
200        ONLY:  rrd_mpi_io_global_array, wrd_mpi_io_global_array
[1819]201
[4497]202       
[1819]203    IMPLICIT NONE
204
[1864]205    PRIVATE
[1819]206
[4497]207    CHARACTER(LEN=100) ::  variable_name  !< name of output variable
208    CHARACTER(LEN=30)  ::  nc_filename    !<
[4460]209
[4497]210
[4537]211    INTEGER(iwp), PARAMETER ::  n_turbines_max = 1E4  !< maximum number of turbines (for array allocation)
[4497]212
213
[1819]214!
215!-- Variables specified in the namelist wind_turbine_par
[4497]216    INTEGER(iwp) ::  n_airfoils = 8  !< number of airfoils of the used turbine model (for ADM-R and ALM)
217    INTEGER(iwp) ::  n_turbines = 1  !< number of turbines
[1819]218
[4497]219    LOGICAL ::  pitch_control       = .FALSE.  !< switch for use of pitch controller
220    LOGICAL ::  speed_control       = .FALSE.  !< switch for use of speed controller
221    LOGICAL ::  tip_loss_correction = .FALSE.  !< switch for use of tip loss correct.
222    LOGICAL ::  yaw_control         = .FALSE.  !< switch for use of yaw controller
223
224
225    LOGICAL ::  initial_write_coordinates = .FALSE.  !<
226
227
228    REAL(wp), DIMENSION(:), POINTER   ::  output_values_1d_pointer  !< pointer for 2d output array
229    REAL(wp), POINTER                 ::  output_values_0d_pointer  !< pointer for 2d output array
230    REAL(wp), DIMENSION(:), ALLOCATABLE, TARGET ::  output_values_1d_target  !< pointer for 2d output array
231    REAL(wp), TARGET                  ::  output_values_0d_target   !< pointer for 2d output array
232
233
234    REAL(wp) ::  dt_data_output_wtm = 0.0_wp  !< data output interval
235    REAL(wp) ::  time_wtm           = 0.0_wp  !< time since last data output
236
237
[4447]238    REAL(wp) ::  segment_length_tangential  = 1.0_wp  !< length of the segments, the rotor area is divided into
239                                                      !< (in tangential direction, as factor of MIN(dx,dy,dz))
240    REAL(wp) ::  segment_width_radial       = 0.5_wp  !< width of the segments, the rotor area is divided into
241                                                      !< (in radial direction, as factor of MIN(dx,dy,dz))
[4528]242   
243    REAL(wp) ::  smearing_kernel_size       = 2.0_wp  !< size of the smearing kernel as multiples of dx
244
[4447]245    REAL(wp) ::  time_turbine_on            = 0.0_wp  !< time at which turbines are started
[4497]246    REAL(wp) ::  tilt_angle                 = 0.0_wp  !< vertical tilt_angle of the rotor [degree] ( positive = backwards )
[1819]247
[4497]248                                                                                 !< ( clockwise, 0 = facing west )
[4460]249    REAL(wp), DIMENSION(1:n_turbines_max) ::  hub_x               = 9999999.9_wp !< position of hub in x-direction
250    REAL(wp), DIMENSION(1:n_turbines_max) ::  hub_y               = 9999999.9_wp !< position of hub in y-direction
251    REAL(wp), DIMENSION(1:n_turbines_max) ::  hub_z               = 9999999.9_wp !< position of hub in z-direction
252    REAL(wp), DIMENSION(1:n_turbines_max) ::  nacelle_radius      = 0.0_wp       !< nacelle diameter [m]
253!    REAL(wp), DIMENSION(1:n_turbines_max) ::  nacelle_cd          = 0.85_wp      !< drag coefficient for nacelle
254    REAL(wp), DIMENSION(1:n_turbines_max) ::  tower_cd            = 1.2_wp       !< drag coefficient for tower
[4497]255    REAL(wp), DIMENSION(1:n_turbines_max) ::  pitch_angle         = 0.0_wp       !< constant pitch angle
256    REAL(wp), DIMENSION(1:n_turbines_max) ::  rotor_radius        = 63.0_wp      !< rotor radius [m]
257    REAL(wp), DIMENSION(1:n_turbines_max), TARGET ::  rotor_speed = 0.9_wp       !< inital or constant rotor speed [rad/s]
258    REAL(wp), DIMENSION(1:n_turbines_max) ::  tower_diameter      = 0.0_wp       !< tower diameter [m]
259    REAL(wp), DIMENSION(1:n_turbines_max) ::  yaw_angle           = 0.0_wp       !< yaw angle [degree]
[1839]260
[4497]261
[1819]262!
263!-- Variables specified in the namelist for speed controller
264!-- Default values are from the NREL 5MW research turbine (Jonkman, 2008)
[4497]265    REAL(wp) ::  air_density               = 1.225_wp       !< Air density to convert to W [kg/m3]
266    REAL(wp) ::  gear_efficiency           = 1.0_wp         !< Loss between rotor and generator
267    REAL(wp) ::  gear_ratio                = 97.0_wp        !< Gear ratio from rotor to generator
268    REAL(wp) ::  generator_power_rated     = 5296610.0_wp   !< rated turbine power [W]
269    REAL(wp) ::  generator_inertia         = 534.116_wp     !< Inertia of the generator [kg*m2]
270    REAL(wp) ::  generator_efficiency      = 0.944_wp       !< Electric efficiency of the generator
271    REAL(wp) ::  generator_speed_rated     = 121.6805_wp    !< Rated generator speed [rad/s]
272    REAL(wp) ::  generator_torque_max      = 47402.91_wp    !< Maximum of the generator torque [Nm]
273    REAL(wp) ::  generator_torque_rate_max = 15000.0_wp     !< Max generator torque increase [Nm/s]
274    REAL(wp) ::  pitch_rate                = 8.0_wp         !< Max pitch rate [degree/s]
275    REAL(wp) ::  region_2_slope            = 2.332287_wp    !< Slope constant for region 2
276    REAL(wp) ::  region_2_min              = 91.21091_wp    !< Lower generator speed boundary of region 2 [rad/s]
277    REAL(wp) ::  region_15_min             = 70.16224_wp    !< Lower generator speed boundary of region 1.5 [rad/s]
278    REAL(wp) ::  rotor_inertia             = 34784179.0_wp  !< Inertia of the rotor [kg*m2]
[1819]279
[1839]280
[1912]281
[1819]282!
[4497]283!-- Variables specified in the namelist for yaw control:
284    REAL(wp) ::  yaw_misalignment_max = 0.08726_wp   !< maximum tolerated yaw missalignment [rad]
285    REAL(wp) ::  yaw_misalignment_min = 0.008726_wp  !< minimum yaw missalignment for which the actuator stops [rad]
286    REAL(wp) ::  yaw_speed            = 0.005236_wp  !< speed of the yaw actuator [rad/s]
[1819]287
288!
[4497]289!-- Variables for initialization of the turbine model:
290    INTEGER(iwp) ::  inot        !< turbine loop index (turbine id)
291    INTEGER(iwp) ::  nsegs_max   !< maximum number of segments (all turbines, required for allocation of arrays)
292    INTEGER(iwp) ::  nrings_max  !< maximum number of rings (all turbines, required for allocation of arrays)
293    INTEGER(iwp) ::  ring        !< ring loop index (ring number)
294    INTEGER(iwp) ::  upper_end   !<
[1819]295
[4497]296    INTEGER(iwp), DIMENSION(1) ::  lct  !<
[1819]297
[4497]298    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  i_hub    !< index belonging to x-position of the turbine
299    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  i_smear  !< index defining the area for the smearing of the forces (x-direction)
300    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  j_hub    !< index belonging to y-position of the turbine
301    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  j_smear  !< index defining the area for the smearing of the forces (y-direction)
302    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  k_hub    !< index belonging to hub height
303    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  k_smear  !< index defining the area for the smearing of the forces (z-direction)
304    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  nrings   !< number of rings per turbine
305    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  nsegs_total  !< total number of segments per turbine
[1819]306
[4497]307    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE ::  nsegs  !< number of segments per ring and turbine
[1819]308
[1912]309!
[4497]310!-  Parameters for the smearing from the rotor to the cartesian grid:
311    REAL(wp) ::  delta_t_factor  !<
312    REAL(wp) ::  eps_factor      !<
313    REAL(wp) ::  eps_min         !<
314    REAL(wp) ::  eps_min2        !<
315    REAL(wp) ::  pol_a           !< parameter for the polynomial smearing fct
316    REAL(wp) ::  pol_b           !< parameter for the polynomial smearing fct
[1839]317!
[4497]318!-- Variables for the calculation of lift and drag coefficients:
319    REAL(wp), DIMENSION(:), ALLOCATABLE  ::  ard      !<
320    REAL(wp), DIMENSION(:), ALLOCATABLE  ::  crd      !<
321    REAL(wp), DIMENSION(:), ALLOCATABLE  ::  delta_r  !< radial segment length
322    REAL(wp), DIMENSION(:), ALLOCATABLE  ::  lrd      !<
[1819]323
[4497]324    REAL(wp) ::  accu_cl_cd_tab = 0.1_wp  !< Accuracy of the interpolation of the lift and drag coeff [deg]
[1819]325
[4497]326    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: turb_cd_tab  !< table of the blade drag coefficient
327    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: turb_cl_tab  !< table of the blade lift coefficient
328
329    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  nac_cd_surf  !< 3d field of the tower drag coefficient
[1912]330    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  tow_cd_surf  !< 3d field of the nacelle drag coefficient
[1819]331
332!
[4497]333!-- Variables for the calculation of the forces:
334    REAL(wp) ::  cur_r       !<
335    REAL(wp) ::  phi_rotor   !<
336    REAL(wp) ::  pre_factor  !<
337    REAL(wp) ::  torque_seg  !<
338    REAL(wp) ::  u_int_l     !<
339    REAL(wp) ::  u_int_u     !<
340    REAL(wp) ::  u_rot       !<
341    REAL(wp) ::  v_int_l     !<
342    REAL(wp) ::  v_int_u     !<
343    REAL(wp) ::  w_int_l     !<
344    REAL(wp) ::  w_int_u     !<
[3832]345    !$OMP THREADPRIVATE (cur_r, phi_rotor, pre_factor, torque_seg, u_int_l, u_int_u, u_rot, &
346    !$OMP&               v_int_l, v_int_u, w_int_l, w_int_u)
[1912]347!
[4497]348!-  Tendencies from the nacelle and tower thrust:
349    REAL(wp) ::  tend_nac_x = 0.0_wp  !<
350    REAL(wp) ::  tend_nac_y = 0.0_wp  !<
351    REAL(wp) ::  tend_tow_x = 0.0_wp  !<
[1912]352    REAL(wp) ::  tend_tow_y = 0.0_wp  !<
[3832]353    !$OMP THREADPRIVATE (tend_nac_x, tend_tow_x, tend_nac_y, tend_tow_y)
[1819]354
[4497]355    REAL(wp), DIMENSION(:), ALLOCATABLE ::  alpha_attack  !<
356    REAL(wp), DIMENSION(:), ALLOCATABLE ::  chord         !<
357    REAL(wp), DIMENSION(:), ALLOCATABLE ::  phi_rel       !<
358    REAL(wp), DIMENSION(:), ALLOCATABLE ::  torque_total  !<
359    REAL(wp), DIMENSION(:), ALLOCATABLE ::  thrust_rotor  !<
360    REAL(wp), DIMENSION(:), ALLOCATABLE ::  turb_cd       !<
361    REAL(wp), DIMENSION(:), ALLOCATABLE ::  turb_cl       !<
362    REAL(wp), DIMENSION(:), ALLOCATABLE ::  vrel          !<
363    REAL(wp), DIMENSION(:), ALLOCATABLE ::  vtheta        !<
[1912]364
365    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rbx, rby, rbz     !< coordinates of the blade elements
366    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rotx, roty, rotz  !< normal vectors to the rotor coordinates
367
368!
[4497]369!-  Fields for the interpolation of velocities on the rotor grid:
370    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  u_int      !<
371    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  u_int_1_l  !<
372    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  v_int      !<
373    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  v_int_1_l  !<
374    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  w_int      !<
375    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  w_int_1_l  !<
376
[1912]377!
[4497]378!-  Rotor tendencies on the segments:
379    REAL(wp), DIMENSION(:), ALLOCATABLE :: thrust_seg    !<
380    REAL(wp), DIMENSION(:), ALLOCATABLE :: torque_seg_y  !<
381    REAL(wp), DIMENSION(:), ALLOCATABLE :: torque_seg_z  !<
[1912]382
383!
[4497]384!-  Rotor tendencies on the rings:
385    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  thrust_ring    !<
386    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  torque_ring_y  !<
387    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  torque_ring_z  !<
388
[1912]389!
[4497]390!-  Rotor tendencies on rotor grids for all turbines:
391    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  thrust     !<
392    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  torque_y   !<
393    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  torque_z   !<
[1912]394
395!
[4497]396!-  Rotor tendencies on coordinate grid:
397    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rot_tend_x  !<
398    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rot_tend_y  !<
399    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rot_tend_z  !<
400
401!
402!-  Variables for the rotation of the rotor coordinates:
[4460]403    REAL(wp), DIMENSION(1:n_turbines_max,1:3,1:3) ::  rot_coord_trans  !< matrix for rotation of rotor coordinates
[1819]404
[4497]405    REAL(wp), DIMENSION(1:3) ::  rot_eigen_rad  !<
406    REAL(wp), DIMENSION(1:3) ::  rot_eigen_azi  !<
407    REAL(wp), DIMENSION(1:3) ::  rot_eigen_nor  !<
408    REAL(wp), DIMENSION(1:3) ::  re             !<
409    REAL(wp), DIMENSION(1:3) ::  rea            !<
410    REAL(wp), DIMENSION(1:3) ::  ren            !<
411    REAL(wp), DIMENSION(1:3) ::  rote           !<
412    REAL(wp), DIMENSION(1:3) ::  rota           !<
413    REAL(wp), DIMENSION(1:3) ::  rotn           !<
414
[1839]415!
[4497]416!-- Fixed variables for the speed controller:
417    LOGICAL  ::  start_up = .TRUE.  !<
[1819]418
[4497]419    REAL(wp) ::  fcorner           !< corner freq for the controller low pass filter
420    REAL(wp) ::  om_rate            !< rotor speed change
421    REAL(wp) ::  region_25_min      !< min region 2.5
422    REAL(wp) ::  region_25_slope    !< slope in region 2.5
423    REAL(wp) ::  slope15            !< slope in region 1.5
424    REAL(wp) ::  trq_rate           !< torque change
425    REAL(wp) ::  vs_sysp            !<
426    REAL(wp) ::  lp_coeff           !< coeff for the controller low pass filter
[1819]427
[4497]428    REAL(wp), DIMENSION(n_turbines_max) :: rotor_speed_l = 0.0_wp  !< local rot speed [rad/s]
[2563]429
[1839]430!
[4497]431!-- Fixed variables for the yaw controller:
432    INTEGER(iwp)                          ::  wdlon           !<
433    INTEGER(iwp)                          ::  wdsho            !<
[1819]434
[4497]435    LOGICAL,  DIMENSION(1:n_turbines_max) ::  doyaw = .FALSE.  !<
436
437    REAL(wp), DIMENSION(:)  , ALLOCATABLE ::  u_inflow         !< wind speed at hub
438    REAL(wp), DIMENSION(:)  , ALLOCATABLE ::  u_inflow_l       !<
439    REAL(wp), DIMENSION(:)  , ALLOCATABLE ::  wdir             !< wind direction at hub
440    REAL(wp), DIMENSION(:)  , ALLOCATABLE ::  wdir_l           !<
441    REAL(wp), DIMENSION(:)  , ALLOCATABLE ::  wd2_l            !< local (cpu) short running avg of the wd
442    REAL(wp), DIMENSION(:)  , ALLOCATABLE ::  wd30_l           !< local (cpu) long running avg of the wd
[1912]443    REAL(wp), DIMENSION(:)  , ALLOCATABLE ::  yawdir           !< direction to yaw
[4447]444    REAL(wp), DIMENSION(:)  , ALLOCATABLE ::  yaw_angle_l      !< local (cpu) yaw angle
[4497]445
446    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  wd2              !<
[1912]447    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  wd30             !<
[1819]448
[4497]449
[2563]450!
[4497]451!-- Variables that have to be saved in the binary file for restarts:
452    REAL(wp), DIMENSION(1:n_turbines_max) ::  pitch_angle_old         = 0.0_wp  !< old constant pitch angle
[4460]453    REAL(wp), DIMENSION(1:n_turbines_max) ::  generator_speed         = 0.0_wp  !< curr. generator speed
454    REAL(wp), DIMENSION(1:n_turbines_max) ::  generator_speed_f       = 0.0_wp  !< filtered generator speed
455    REAL(wp), DIMENSION(1:n_turbines_max) ::  generator_speed_old     = 0.0_wp  !< last generator speed
456    REAL(wp), DIMENSION(1:n_turbines_max) ::  generator_speed_f_old   = 0.0_wp  !< last filtered generator speed
457    REAL(wp), DIMENSION(1:n_turbines_max) ::  torque_gen              = 0.0_wp  !< generator torque
458    REAL(wp), DIMENSION(1:n_turbines_max) ::  torque_gen_old          = 0.0_wp  !< last generator torque
[1819]459
[2563]460
[1839]461    SAVE
[1819]462
[1839]463
464    INTERFACE wtm_parin
465       MODULE PROCEDURE wtm_parin
466    END INTERFACE wtm_parin
[2563]467
[1912]468    INTERFACE wtm_check_parameters
469       MODULE PROCEDURE wtm_check_parameters
470    END INTERFACE wtm_check_parameters
[3875]471
[4411]472    INTERFACE wtm_data_output
473       MODULE PROCEDURE wtm_data_output
474    END INTERFACE wtm_data_output
[4497]475
[1839]476    INTERFACE wtm_init_arrays
477       MODULE PROCEDURE wtm_init_arrays
478    END INTERFACE wtm_init_arrays
479
480    INTERFACE wtm_init
481       MODULE PROCEDURE wtm_init
482    END INTERFACE wtm_init
[2553]483
[4411]484    INTERFACE wtm_init_output
485       MODULE PROCEDURE wtm_init_output
486    END INTERFACE wtm_init_output
[4497]487
[3875]488    INTERFACE wtm_actions
489       MODULE PROCEDURE wtm_actions
490       MODULE PROCEDURE wtm_actions_ij
491    END INTERFACE wtm_actions
[1819]492
[3875]493    INTERFACE wtm_rrd_global
[4495]494       MODULE PROCEDURE wtm_rrd_global_ftn
495       MODULE PROCEDURE wtm_rrd_global_mpi
[3875]496    END INTERFACE wtm_rrd_global
[1819]497
[3875]498    INTERFACE wtm_wrd_global
499       MODULE PROCEDURE wtm_wrd_global
500    END INTERFACE wtm_wrd_global
[2563]501
[3875]502
[4497]503    PUBLIC                                                                                         &
504           dt_data_output_wtm,                                                                     &
505           time_wtm,                                                                               &
[4420]506           wind_turbine
507
[4497]508    PUBLIC                                                                                         &
509           wtm_parin,                                                                              &
510           wtm_check_parameters,                                                                   &
511           wtm_data_output,                                                                        &
512           wtm_init_arrays,                                                                        &
513           wtm_init_output,                                                                        &
514           wtm_init,                                                                               &
515           wtm_actions,                                                                            &
516           wtm_rrd_global,                                                                         &
[3875]517           wtm_wrd_global
518
519
[1819]520 CONTAINS
521
522
[4497]523!--------------------------------------------------------------------------------------------------!
[1819]524! Description:
525! ------------
[1839]526!> Parin for &wind_turbine_par for wind turbine model
[4497]527!--------------------------------------------------------------------------------------------------!
528 SUBROUTINE wtm_parin
[1819]529
[4497]530    IMPLICIT NONE
[1819]531
[4497]532    CHARACTER(LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
[1839]533
[4497]534    NAMELIST /wind_turbine_parameters/                                                             &
535             air_density, tower_diameter, dt_data_output_wtm,                                      &
536                gear_efficiency, gear_ratio, generator_efficiency,                                 &
537                generator_inertia, rotor_inertia, yaw_misalignment_max,                            &
538                generator_torque_max, generator_torque_rate_max, yaw_misalignment_min,             &
539                region_15_min, region_2_min, n_airfoils, n_turbines,                               &
540                rotor_speed, yaw_angle, pitch_angle, pitch_control,                                &
541                generator_speed_rated, generator_power_rated, hub_x, hub_y, hub_z,                 &
542                nacelle_radius, rotor_radius, segment_length_tangential, segment_width_radial,     &
543                region_2_slope, speed_control, tilt_angle, time_turbine_on,                        &
[4528]544                smearing_kernel_size, tower_cd, pitch_rate,                                        &
[4497]545                yaw_control, yaw_speed, tip_loss_correction
546!                , nacelle_cd
[4447]547
[1819]548!
[4497]549!-- Try to find wind turbine model package:
550    REWIND ( 11 )
551    line = ' '
552    DO WHILE ( INDEX ( line, '&wind_turbine_parameters' ) == 0 )
553       READ ( 11, '(A)', END = 12 )  line
554    ENDDO
555    BACKSPACE ( 11 )
[1839]556
557!
[4497]558!-- Read user-defined namelist:
559    READ ( 11, wind_turbine_parameters, ERR = 10, END = 12 )
[2932]560!
[4497]561!-- Set flag that indicates that the wind turbine model is switched on:
562    wind_turbine = .TRUE.
[4465]563
[4497]564    GOTO 12
[2932]565
[4497]566 10 BACKSPACE ( 11 )
567    READ ( 11, '(A)' ) line
568    CALL parin_fail_message( 'wind_turbine_parameters', line )
[3246]569
[4497]570 12 CONTINUE  ! TBD Change from continue, mit ierrn machen
[1839]571
[4497]572 END SUBROUTINE wtm_parin
[1839]573
[2563]574
[4497]575!--------------------------------------------------------------------------------------------------!
[2563]576! Description:
577! ------------
[2894]578!> This routine writes the respective restart data.
[4497]579!--------------------------------------------------------------------------------------------------!
580 SUBROUTINE wtm_wrd_global
[2576]581
582
[4497]583    IMPLICIT NONE
[2776]584
[2894]585
[4497]586   IF ( TRIM( restart_data_format_output ) == 'fortran_binary' )  THEN
[2894]587
[4497]588       CALL wrd_write_string( 'generator_speed' )
589       WRITE ( 14 )  generator_speed
[2894]590
[4497]591       CALL wrd_write_string( 'generator_speed_f' )
592       WRITE ( 14 )  generator_speed_f
[2894]593
[4497]594       CALL wrd_write_string( 'generator_speed_f_old' )
595       WRITE ( 14 )  generator_speed_f_old
[2894]596
[4497]597       CALL wrd_write_string( 'generator_speed_old' )
598       WRITE ( 14 )  generator_speed_old
[2894]599
[4497]600       CALL wrd_write_string( 'rotor_speed' )
601       WRITE ( 14 )  rotor_speed
[2894]602
[4497]603       CALL wrd_write_string( 'yaw_angle' )
604       WRITE ( 14 )  yaw_angle
[2894]605
[4497]606       CALL wrd_write_string( 'pitch_angle' )
607       WRITE ( 14 )  pitch_angle
[2894]608
[4497]609       CALL wrd_write_string( 'pitch_angle_old' )
610       WRITE ( 14 )  pitch_angle_old
[2894]611
[4497]612       CALL wrd_write_string( 'torque_gen' )
613       WRITE ( 14 )  torque_gen
[4495]614
[4497]615       CALL wrd_write_string( 'torque_gen_old' )
616       WRITE ( 14 )  torque_gen_old
[4495]617
[4535]618    ELSEIF ( restart_data_format_output(1:3) == 'mpi' )  THEN
[4495]619
[4497]620       CALL wrd_mpi_io_global_array( 'generator_speed', generator_speed )
621       CALL wrd_mpi_io_global_array( 'generator_speed_f', generator_speed_f )
622       CALL wrd_mpi_io_global_array( 'generator_speed_f_old', generator_speed_f_old )
623       CALL wrd_mpi_io_global_array( 'generator_speed_old', generator_speed_old )
624       CALL wrd_mpi_io_global_array( 'rotor_speed', rotor_speed )
625       CALL wrd_mpi_io_global_array( 'yaw_angle', yaw_angle )
626       CALL wrd_mpi_io_global_array( 'pitch_angle', pitch_angle )
627       CALL wrd_mpi_io_global_array( 'pitch_angle_old', pitch_angle_old )
628       CALL wrd_mpi_io_global_array( 'torque_gen', torque_gen )
629       CALL wrd_mpi_io_global_array( 'torque_gen_old', torque_gen_old )
[2563]630
[4497]631    ENDIF
[2563]632
[4497]633 END SUBROUTINE wtm_wrd_global
634
635
636!--------------------------------------------------------------------------------------------------!
[2563]637! Description:
638! ------------
[4495]639!> Read module-specific global restart data (Fortran binary format).
[4497]640!--------------------------------------------------------------------------------------------------!
[4495]641 SUBROUTINE wtm_rrd_global_ftn( found )
[2563]642
643
[4497]644    USE control_parameters,                                                                        &
[2894]645        ONLY: length, restart_string
646
647
[2563]648    IMPLICIT NONE
649
[4497]650    LOGICAL, INTENT(OUT) ::  found
[2563]651
652
[2894]653    found = .TRUE.
[2563]654
655
[2894]656    SELECT CASE ( restart_string(1:length) )
[2563]657
[4447]658       CASE ( 'generator_speed' )
659          READ ( 13 )  generator_speed
660       CASE ( 'generator_speed_f' )
661          READ ( 13 )  generator_speed_f
662       CASE ( 'generator_speed_f_old' )
663          READ ( 13 )  generator_speed_f_old
664       CASE ( 'generator_speed_old' )
665          READ ( 13 )  generator_speed_old
666       CASE ( 'rotor_speed' )
667          READ ( 13 )  rotor_speed
668       CASE ( 'yaw_angle' )
669          READ ( 13 )  yaw_angle
670       CASE ( 'pitch_angle' )
671          READ ( 13 )  pitch_angle
672       CASE ( 'pitch_angle_old' )
673          READ ( 13 )  pitch_angle_old
[2894]674       CASE ( 'torque_gen' )
675          READ ( 13 )  torque_gen
676       CASE ( 'torque_gen_old' )
677          READ ( 13 )  torque_gen_old
[2563]678
[2894]679       CASE DEFAULT
[2563]680
[2894]681          found = .FALSE.
[2563]682
[2894]683    END SELECT
[2563]684
[4497]685
[4495]686 END SUBROUTINE wtm_rrd_global_ftn
[2894]687
688
[2563]689!------------------------------------------------------------------------------!
690! Description:
691! ------------
[4495]692!> Read module-specific global restart data (MPI-IO).
693!------------------------------------------------------------------------------!
694 SUBROUTINE wtm_rrd_global_mpi
695
696    CALL rrd_mpi_io_global_array( 'generator_speed', generator_speed )
697    CALL rrd_mpi_io_global_array( 'generator_speed_f', generator_speed_f )
698    CALL rrd_mpi_io_global_array( 'generator_speed_f_old', generator_speed_f_old )
699    CALL rrd_mpi_io_global_array( 'generator_speed_old', generator_speed_old )
700    CALL rrd_mpi_io_global_array( 'rotor_speed', rotor_speed )
701    CALL rrd_mpi_io_global_array( 'yaw_angle', yaw_angle )
702    CALL rrd_mpi_io_global_array( 'pitch_angle', pitch_angle )
703    CALL rrd_mpi_io_global_array( 'pitch_angle_old', pitch_angle_old )
704    CALL rrd_mpi_io_global_array( 'torque_gen', torque_gen )
705    CALL rrd_mpi_io_global_array( 'torque_gen_old', torque_gen_old )
706
707 END SUBROUTINE wtm_rrd_global_mpi
708
709
[4497]710!--------------------------------------------------------------------------------------------------!
[4495]711! Description:
712! ------------
[2563]713!> Check namelist parameter
[4497]714!--------------------------------------------------------------------------------------------------!
715 SUBROUTINE wtm_check_parameters
[1912]716
[4497]717    IMPLICIT NONE
[4436]718
[4497]719    IF ( .NOT. input_pids_wtm )  THEN
720       IF ( ( .NOT.speed_control ) .AND. pitch_control )  THEN
721          message_string = 'pitch_control = .TRUE. requires speed_control = .TRUE.'
722          CALL message( 'wtm_check_parameters', 'PA0461', 1, 2, 0, 6, 0 )
723       ENDIF
[4436]724
[4497]725       IF ( ANY( rotor_speed(1:n_turbines) < 0.0 ) )  THEN
726          message_string = 'rotor_speed < 0.0, Please set rotor_speed to ' //                      &
727                           'a value equal or larger than zero'
728          CALL message( 'wtm_check_parameters', 'PA0462', 1, 2, 0, 6, 0 )
729       ENDIF
[4436]730
[4497]731       IF ( ANY( hub_x(1:n_turbines) == 9999999.9_wp ) .OR.                                        &
732            ANY( hub_y(1:n_turbines) == 9999999.9_wp ) .OR.                                        &
733            ANY( hub_z(1:n_turbines) == 9999999.9_wp ) )  THEN
[4436]734
[4497]735          message_string = 'hub_x, hub_y, hub_z have to be given for each turbine.'
736          CALL message( 'wtm_check_parameters', 'PA0463', 1, 2, 0, 6, 0 )
[1912]737       ENDIF
[4497]738    ENDIF
739
740 END SUBROUTINE wtm_check_parameters
741!
742!--------------------------------------------------------------------------------------------------!
[1839]743! Description:
744! ------------
745!> Allocate wind turbine model arrays
[4497]746!--------------------------------------------------------------------------------------------------!
747 SUBROUTINE wtm_init_arrays
[1839]748
[4497]749    IMPLICIT NONE
[1839]750
[4497]751    REAL(wp) ::  delta_r_factor  !<
752    REAL(wp) ::  delta_r_init    !<
[1864]753
[4436]754#if defined( __netcdf )
[1839]755!
[4497]756! Read wtm input file (netcdf) if it exists:
757    IF ( input_pids_wtm )  THEN
[4434]758
759!
[4497]760!--    Open the wtm  input file:
761       CALL open_read_file( TRIM( input_file_wtm ) //                                              &
762                            TRIM( coupling_char ), pids_id )
[4434]763
[4497]764       CALL inquire_num_variables( pids_id, num_var_pids )
[4434]765
766!
[4497]767!--    Allocate memory to store variable names and read them:
768       ALLOCATE( vars_pids(1:num_var_pids) )
769       CALL inquire_variable_names( pids_id, vars_pids )
[4434]770
771!
[4497]772!--    Input of all wtm parameters:
773       IF ( check_existence( vars_pids, 'tower_diameter' ) )  THEN
774          CALL get_variable( pids_id, 'tower_diameter', tower_diameter(1:n_turbines) )
775       ENDIF
[4434]776
[4497]777       IF ( check_existence( vars_pids, 'rotor_speed' ) )  THEN
778          CALL get_variable( pids_id, 'rotor_speed', rotor_speed(1:n_turbines) )
779       ENDIF
[4434]780
[4497]781       IF ( check_existence( vars_pids, 'pitch_angle' ) )  THEN
782          CALL get_variable( pids_id, 'pitch_angle', pitch_angle(1:n_turbines) )
783       ENDIF
[4434]784
[4497]785       IF ( check_existence( vars_pids, 'yaw_angle' ) )  THEN
786          CALL get_variable( pids_id, 'yaw_angle', yaw_angle(1:n_turbines) )
787       ENDIF
[4434]788
[4497]789       IF ( check_existence( vars_pids, 'hub_x' ) )  THEN
790          CALL get_variable( pids_id, 'hub_x', hub_x(1:n_turbines) )
791       ENDIF
[4434]792
[4497]793       IF ( check_existence( vars_pids, 'hub_y' ) )  THEN
794          CALL get_variable( pids_id, 'hub_y', hub_y(1:n_turbines) )
795       ENDIF
[4434]796
[4497]797       IF ( check_existence( vars_pids, 'hub_z' ) )  THEN
798          CALL get_variable( pids_id, 'hub_z', hub_z(1:n_turbines) )
799       ENDIF
[4434]800
[4497]801       IF ( check_existence( vars_pids, 'nacelle_radius' ) )  THEN
802          CALL get_variable( pids_id, 'nacelle_radius', nacelle_radius(1:n_turbines) )
803       ENDIF
[4434]804
[4497]805       IF ( check_existence( vars_pids, 'rotor_radius' ) )  THEN
806          CALL get_variable( pids_id, 'rotor_radius', rotor_radius(1:n_turbines) )
807       ENDIF
808!
809!        IF ( check_existence( vars_pids, 'nacelle_cd' ) )  THEN
810!           CALL get_variable( pids_id, 'nacelle_cd', nacelle_cd(1:n_turbines) )
811!        ENDIF
[4434]812
[4497]813       IF ( check_existence( vars_pids, 'tower_cd' ) )  THEN
814          CALL get_variable( pids_id, 'tower_cd', tower_cd(1:n_turbines) )
815       ENDIF
[4434]816!
[4497]817!--    Close wtm input file:
818       CALL close_input_file( pids_id )
[4434]819
[4497]820    ENDIF
[4434]821#endif
822
823!
[4497]824!-- To be able to allocate arrays with dimension of rotor rings and segments,
825!-- the maximum possible numbers of rings and segments have to be calculated:
826    ALLOCATE( nrings(1:n_turbines) )
827    ALLOCATE( delta_r(1:n_turbines) )
[1819]828
[4497]829    nrings(:)  = 0
830    delta_r(:) = 0.0_wp
[1819]831
832!
[4497]833!-- Thickness (radial) of each ring and length (tangential) of each segment:
834    delta_r_factor = segment_width_radial
835    delta_t_factor = segment_length_tangential
836    delta_r_init   = delta_r_factor * MIN( dx, dy, dz(1) )
[1819]837
[4497]838    DO  inot = 1, n_turbines
[1819]839!
[4497]840!--    Determine number of rings:
841       nrings(inot) = NINT( rotor_radius(inot) / delta_r_init )
[1819]842
[4497]843       delta_r(inot) = rotor_radius(inot) / nrings(inot)
[1819]844
[4497]845    ENDDO
[1819]846
[4497]847    nrings_max = MAXVAL( nrings )
[1819]848
[4497]849    ALLOCATE( nsegs(1:nrings_max,1:n_turbines) )
850    ALLOCATE( nsegs_total(1:n_turbines) )
[1819]851
[4497]852    nsegs(:,:)     = 0
853    nsegs_total(:) = 0
[1819]854
855
[4497]856    DO  inot = 1, n_turbines
857       DO  ring = 1, nrings(inot)
[1819]858!
[4497]859!--       Determine number of segments for each ring:
860          nsegs(ring,inot) = MAX( 8, CEILING( delta_r_factor * pi * ( 2.0_wp * ring - 1.0_wp ) /   &
861                                              delta_t_factor ) )
862       ENDDO
[1819]863!
[4497]864!--    Total sum of all rotor segments:
865       nsegs_total(inot) = SUM( nsegs(:,inot) )
866    ENDDO
[1819]867
868!
[4497]869!-- Maximum number of segments per ring:
870    nsegs_max = MAXVAL( nsegs )
[1819]871
[1864]872!!
[4497]873!!-- TODO: Folgendes im Header ausgeben!
874!    IF ( myid == 0 )  THEN
875!       PRINT*, 'nrings(1) = ', nrings(1)
876!       PRINT*, '----------------------------------------------------------------------------------'
877!       PRINT*, 'nsegs(:,1) = ', nsegs(:,1)
878!       PRINT*, '----------------------------------------------------------------------------------'
879!       PRINT*, 'nrings_max = ', nrings_max
880!       PRINT*, 'nsegs_max = ', nsegs_max
881!       PRINT*, 'nsegs_total(1) = ', nsegs_total(1)
882!    ENDIF
[1819]883
884
885!
[4497]886!-- Allocate 1D arrays (dimension = number of turbines):
887    ALLOCATE( i_hub(1:n_turbines) )
888    ALLOCATE( i_smear(1:n_turbines) )
889    ALLOCATE( j_hub(1:n_turbines) )
890    ALLOCATE( j_smear(1:n_turbines) )
891    ALLOCATE( k_hub(1:n_turbines) )
892    ALLOCATE( k_smear(1:n_turbines) )
893    ALLOCATE( torque_total(1:n_turbines) )
894    ALLOCATE( thrust_rotor(1:n_turbines) )
[1819]895
896!
[4497]897!-- Allocation of the 1D arrays for yaw control:
898    ALLOCATE( yawdir(1:n_turbines) )
899    ALLOCATE( u_inflow(1:n_turbines) )
900    ALLOCATE( wdir(1:n_turbines) )
901    ALLOCATE( u_inflow_l(1:n_turbines) )
902    ALLOCATE( wdir_l(1:n_turbines) )
903    ALLOCATE( yaw_angle_l(1:n_turbines) )
904
[1819]905!
[4497]906!-- Allocate 1D arrays (dimension = number of rotor segments):
907    ALLOCATE( alpha_attack(1:nsegs_max) )
908    ALLOCATE( chord(1:nsegs_max) )
909    ALLOCATE( phi_rel(1:nsegs_max) )
910    ALLOCATE( thrust_seg(1:nsegs_max) )
911    ALLOCATE( torque_seg_y(1:nsegs_max) )
912    ALLOCATE( torque_seg_z(1:nsegs_max) )
913    ALLOCATE( turb_cd(1:nsegs_max) )
914    ALLOCATE( turb_cl(1:nsegs_max) )
915    ALLOCATE( vrel(1:nsegs_max) )
916    ALLOCATE( vtheta(1:nsegs_max) )
[1819]917
918!
[4497]919!-- Allocate 2D arrays (dimension = number of rotor rings and segments):
920    ALLOCATE( rbx(1:nrings_max,1:nsegs_max) )
921    ALLOCATE( rby(1:nrings_max,1:nsegs_max) )
922    ALLOCATE( rbz(1:nrings_max,1:nsegs_max) )
923    ALLOCATE( thrust_ring(1:nrings_max,1:nsegs_max) )
924    ALLOCATE( torque_ring_y(1:nrings_max,1:nsegs_max) )
925    ALLOCATE( torque_ring_z(1:nrings_max,1:nsegs_max) )
[1819]926
927!
[4497]928!-- Allocate additional 2D arrays:
929    ALLOCATE( rotx(1:n_turbines,1:3) )
930    ALLOCATE( roty(1:n_turbines,1:3) )
931    ALLOCATE( rotz(1:n_turbines,1:3) )
[1819]932
933!
[4497]934!-- Allocate 3D arrays (dimension = number of grid points):
935    ALLOCATE( nac_cd_surf(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
936    ALLOCATE( rot_tend_x(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
937    ALLOCATE( rot_tend_y(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
938    ALLOCATE( rot_tend_z(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
939    ALLOCATE( thrust(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
940    ALLOCATE( torque_y(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
941    ALLOCATE( torque_z(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
942    ALLOCATE( tow_cd_surf(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
[1819]943
944!
[4497]945!-- Allocate additional 3D arrays:
946    ALLOCATE( u_int(1:n_turbines,1:nrings_max,1:nsegs_max) )
947    ALLOCATE( u_int_1_l(1:n_turbines,1:nrings_max,1:nsegs_max) )
948    ALLOCATE( v_int(1:n_turbines,1:nrings_max,1:nsegs_max) )
949    ALLOCATE( v_int_1_l(1:n_turbines,1:nrings_max,1:nsegs_max) )
950    ALLOCATE( w_int(1:n_turbines,1:nrings_max,1:nsegs_max) )
951    ALLOCATE( w_int_1_l(1:n_turbines,1:nrings_max,1:nsegs_max) )
[1819]952
953!
[4497]954!-- All of the arrays are initialized with a value of zero:
955    i_hub(:)                 = 0
956    i_smear(:)               = 0
957    j_hub(:)                 = 0
958    j_smear(:)               = 0
959    k_hub(:)                 = 0
960    k_smear(:)               = 0
[1819]961
[4497]962    torque_total(:)          = 0.0_wp
963    thrust_rotor(:)          = 0.0_wp
[2563]964
[4497]965    IF ( TRIM( initializing_actions ) /= 'read_restart_data' )  THEN
966       generator_speed(:)             = 0.0_wp
967       generator_speed_old(:)         = 0.0_wp
968       generator_speed_f(:)           = 0.0_wp
969       generator_speed_f_old(:)       = 0.0_wp
970       pitch_angle_old(:)             = 0.0_wp
971       torque_gen(:)                  = 0.0_wp
972       torque_gen_old(:)              = 0.0_wp
973    ENDIF
[1819]974
[4497]975    yawdir(:)                = 0.0_wp
976    wdir_l(:)                = 0.0_wp
977    wdir(:)                  = 0.0_wp
978    u_inflow(:)              = 0.0_wp
979    u_inflow_l(:)            = 0.0_wp
980    yaw_angle_l(:)           = 0.0_wp
981
[1819]982!
[4497]983!-- Allocate 1D arrays (dimension = number of rotor segments):
984    alpha_attack(:)          = 0.0_wp
985    chord(:)                 = 0.0_wp
986    phi_rel(:)               = 0.0_wp
987    thrust_seg(:)            = 0.0_wp
988    torque_seg_y(:)          = 0.0_wp
989    torque_seg_z(:)          = 0.0_wp
990    turb_cd(:)               = 0.0_wp
991    turb_cl(:)               = 0.0_wp
992    vrel(:)                  = 0.0_wp
993    vtheta(:)                = 0.0_wp
[1819]994
[4497]995    rbx(:,:)                 = 0.0_wp
996    rby(:,:)                 = 0.0_wp
997    rbz(:,:)                 = 0.0_wp
998    thrust_ring(:,:)         = 0.0_wp
999    torque_ring_y(:,:)       = 0.0_wp
1000    torque_ring_z(:,:)       = 0.0_wp
[1819]1001
[4497]1002    rotx(:,:)                = 0.0_wp
1003    roty(:,:)                = 0.0_wp
1004    rotz(:,:)                = 0.0_wp
[1819]1005
[4497]1006    nac_cd_surf(:,:,:)       = 0.0_wp
1007    rot_tend_x(:,:,:)        = 0.0_wp
1008    rot_tend_y(:,:,:)        = 0.0_wp
1009    rot_tend_z(:,:,:)        = 0.0_wp
1010    thrust(:,:,:)            = 0.0_wp
1011    torque_y(:,:,:)          = 0.0_wp
1012    torque_z(:,:,:)          = 0.0_wp
1013    tow_cd_surf(:,:,:)       = 0.0_wp
[1819]1014
[4497]1015    u_int(:,:,:)             = 0.0_wp
1016    u_int_1_l(:,:,:)         = 0.0_wp
1017    v_int(:,:,:)             = 0.0_wp
1018    v_int_1_l(:,:,:)         = 0.0_wp
1019    w_int(:,:,:)             = 0.0_wp
1020    w_int_1_l(:,:,:)         = 0.0_wp
[1819]1021
1022
[4497]1023 END SUBROUTINE wtm_init_arrays
[1819]1024
1025
[4497]1026!--------------------------------------------------------------------------------------------------!
[1819]1027! Description:
1028! ------------
[1839]1029!> Initialization of the wind turbine model
[4497]1030!--------------------------------------------------------------------------------------------------!
1031 SUBROUTINE wtm_init
[1819]1032
[4457]1033
[4497]1034    USE control_parameters,                                                                        &
1035        ONLY:  dz_stretch_level_start
[1819]1036
[4497]1037    USE exchange_horiz_mod,                                                                        &
1038        ONLY:  exchange_horiz
1039
1040    IMPLICIT NONE
1041
1042
1043
1044    INTEGER(iwp) ::  i  !< running index
1045    INTEGER(iwp) ::  j  !< running index
1046    INTEGER(iwp) ::  k  !< running index
1047
1048
[1819]1049!
[4497]1050!-- Help variables for the smearing function:
1051    REAL(wp) ::  eps_kernel  !<
1052
[1839]1053!
[4497]1054!-- Help variables for calculation of the tower drag:
1055    INTEGER(iwp) ::  tower_n  !<
1056    INTEGER(iwp) ::  tower_s  !<
[1819]1057
[4497]1058    INTEGER(iwp), DIMENSION(:), ALLOCATABLE :: index_nacb  !<
1059    INTEGER(iwp), DIMENSION(:), ALLOCATABLE :: index_nacl  !<
1060    INTEGER(iwp), DIMENSION(:), ALLOCATABLE :: index_nacr  !<
1061    INTEGER(iwp), DIMENSION(:), ALLOCATABLE :: index_nact  !<
1062
1063    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: circle_points  !<
1064
1065
1066    IF ( debug_output )  CALL debug_message( 'wtm_init', 'start' )
1067
1068    ALLOCATE( index_nacb(1:n_turbines) )
1069    ALLOCATE( index_nacl(1:n_turbines) )
1070    ALLOCATE( index_nacr(1:n_turbines) )
1071    ALLOCATE( index_nact(1:n_turbines) )
1072
[1839]1073!
[4497]1074!--------------------------------------------------------------------------------------------------!
1075!-- Calculation of parameters for the regularization kernel (smearing of the forces)
1076!--------------------------------------------------------------------------------------------------!
[1819]1077!
[4497]1078!-- In the following, some of the required parameters for the smearing will be calculated:
[1819]1079
[4497]1080!-- The kernel is set equal to twice the grid spacing which has turned out to be a reasonable
1081!-- value (see e.g. Troldborg et al. (2013), Wind Energy, DOI: 10.1002/we.1608):
[4528]1082    eps_kernel = smearing_kernel_size * dx
[1819]1083!
[4497]1084!-- The zero point (eps_min) of the polynomial function must be the following if the integral of
1085!-- the polynomial function (for values < eps_min) shall be equal to the integral of the Gaussian
1086!-- function used before:
1087    eps_min = ( 105.0_wp / 32.0_wp )**( 1.0_wp / 3.0_wp ) *                                        &
1088              pi**( 1.0_wp / 6.0_wp ) * eps_kernel
[1819]1089!
[4497]1090!-- Stretching (non-uniform grid spacing) is not considered in the wind turbine model.
1091!-- Therefore, vertical stretching has to be applied above the area where the wtm is active.
1092!-- ABS (...) is required because the default value of dz_stretch_level_start is -9999999.9_wp
1093!-- (negative):
1094    IF ( ABS( dz_stretch_level_start(1) ) <= MAXVAL( hub_z(1:n_turbines) ) +                       &
1095                                             MAXVAL( rotor_radius(1:n_turbines) ) +                &
1096                                             eps_min)  THEN
1097       WRITE( message_string, * ) 'The lowest level where vertical stretching is applied has ' //  &
1098                                  'to  be greater than ',MAXVAL( hub_z(1:n_turbines) )             &
1099                                   + MAXVAL( rotor_radius(1:n_turbines) ) + eps_min
1100       CALL message( 'wtm_init', 'PA0484', 1, 2, 0, 6, 0 )
1101    ENDIF
[3065]1102!
[4497]1103!-- Square of eps_min:
1104    eps_min2 = eps_min**2
[1819]1105!
[4497]1106!-- Parameters in the polynomial function:
1107    pol_a = 1.0_wp / eps_min**4
1108    pol_b = 2.0_wp / eps_min**2
[1819]1109!
[4497]1110!-- Normalization factor which is the inverse of the integral of the smearing function:
1111    eps_factor = 105.0_wp / ( 32.0_wp * pi * eps_min**3 )
1112
1113!-- Change tilt angle to rad:
1114    tilt_angle = tilt_angle * pi / 180.0_wp
1115
[1819]1116!
[4497]1117!-- Change yaw angle to rad:
1118    IF ( TRIM( initializing_actions ) /= 'read_restart_data' )  THEN
1119       yaw_angle(:) = yaw_angle(:) * pi / 180.0_wp
1120    ENDIF
[1819]1121
[1864]1122
[4497]1123    DO  inot = 1, n_turbines
[1819]1124!
[4497]1125!--    Rotate the rotor coordinates in case yaw and tilt are defined:
1126       CALL wtm_rotate_rotor( inot )
1127
[1819]1128!
[4497]1129!--    Determine the indices of the hub height:
1130       i_hub(inot) = INT(   hub_x(inot)                    / dx )
1131       j_hub(inot) = INT( ( hub_y(inot) + 0.5_wp * dy )    / dy )
1132       k_hub(inot) = INT( ( hub_z(inot) + 0.5_wp * dz(1) ) / dz(1) )
[1819]1133
1134!
[4497]1135!--    Determining the area to which the smearing of the forces is applied.
1136!--    As smearing now is effectively applied only for distances smaller than eps_min, the
1137!--    smearing area can be further limited and regarded as a function of eps_min:
1138       i_smear(inot) = CEILING( ( rotor_radius(inot) + eps_min ) / dx )
1139       j_smear(inot) = CEILING( ( rotor_radius(inot) + eps_min ) / dy )
1140       k_smear(inot) = CEILING( ( rotor_radius(inot) + eps_min ) / dz(1) )
[1819]1141
[4497]1142    ENDDO
1143
[1819]1144!
[4497]1145!-- Call the wtm_init_speed_control subroutine and calculate the local rotor_speed for the
1146!-- respective processor:
1147    IF ( speed_control)  THEN
[2792]1148
[4497]1149       CALL wtm_init_speed_control
[2792]1150
[4497]1151       IF ( TRIM( initializing_actions ) == 'read_restart_data' )  THEN
[2792]1152
[4497]1153          DO  inot = 1, n_turbines
[2792]1154
[4497]1155             IF ( nxl > i_hub(inot) )  THEN
1156                torque_gen(inot)        = 0.0_wp
1157                generator_speed_f(inot) = 0.0_wp
1158                rotor_speed_l(inot)     = 0.0_wp
1159             ENDIF
[2792]1160
[4497]1161             IF ( nxr < i_hub(inot) )  THEN
1162                torque_gen(inot)        = 0.0_wp
1163                generator_speed_f(inot) = 0.0_wp
1164                rotor_speed_l(inot)     = 0.0_wp
1165             ENDIF
[2792]1166
[4497]1167             IF ( nys > j_hub(inot) )  THEN
1168                torque_gen(inot)        = 0.0_wp
1169                generator_speed_f(inot) = 0.0_wp
1170                rotor_speed_l(inot)     = 0.0_wp
1171             ENDIF
[2792]1172
[4497]1173             IF ( nyn < j_hub(inot) )  THEN
1174                torque_gen(inot)        = 0.0_wp
1175                generator_speed_f(inot) = 0.0_wp
1176                rotor_speed_l(inot)     = 0.0_wp
1177             ENDIF
[2792]1178
[4497]1179             IF ( ( nxl <= i_hub(inot) ) .AND. ( nxr >= i_hub(inot) ) )  THEN
1180                IF ( ( nys <= j_hub(inot) ) .AND. ( nyn >= j_hub(inot) ) )  THEN
[2792]1181
[4497]1182                   rotor_speed_l(inot) = generator_speed(inot) / gear_ratio
1183
[2792]1184                ENDIF
[4497]1185             ENDIF
[2792]1186
[4497]1187          END DO
[2792]1188
1189       ENDIF
1190
[4497]1191    ENDIF
1192
[2792]1193!
[4497]1194!--------------------------------------------------------------------------------------------------!
1195!-- Determine the area within each grid cell that overlaps with the area of the nacelle and the
1196!-- tower (needed for calculation of the forces)
1197!--------------------------------------------------------------------------------------------------!
[1819]1198!
[4497]1199!-- Note: so far this is only a 2D version, in that the mean flow is perpendicular to the rotor
1200!-- area.
[1819]1201
1202!
[4497]1203!-- Allocation of the array containing information on the intersection points between rotor disk
1204!-- and the numerical grid:
1205    upper_end = ( ny + 1 ) * 10000
[1819]1206
[4497]1207    ALLOCATE( circle_points(1:2,1:upper_end) )
[1819]1208
[4497]1209    circle_points(:,:) = 0.0_wp
1210
1211
1212    DO  inot = 1, n_turbines  ! loop over number of turbines
[1819]1213!
[4497]1214!--    Determine the grid index (u-grid) that corresponds to the location of the rotor center
1215!--    (reduces the amount of calculations in the case that the mean flow is perpendicular to the
1216!--    rotor area):
1217       i = i_hub(inot)
[1819]1218
1219!
[4497]1220!--    Determine the left and the right edge of the nacelle (corresponding grid point indices):
1221       index_nacl(inot) = INT( ( hub_y(inot) - nacelle_radius(inot) + 0.5_wp * dy ) / dy )
1222       index_nacr(inot) = INT( ( hub_y(inot) + nacelle_radius(inot) + 0.5_wp * dy ) / dy )
[1819]1223!
[4497]1224!--    Determine the bottom and the top edge of the nacelle (corresponding grid point indices).
1225!--    The grid point index has to be increased by 1, as the first level for the u-component
1226!--    (index 0) is situated below the surface. All points between z=0 and z=dz/s would already
1227!--    be contained in grid box 1:
1228       index_nacb(inot) = INT( ( hub_z(inot) - nacelle_radius(inot) ) / dz(1) ) + 1
1229       index_nact(inot) = INT( ( hub_z(inot) + nacelle_radius(inot) ) / dz(1) ) + 1
[1819]1230
1231!
[4497]1232!--    Determine the indices of the grid boxes containing the left and the right boundaries of
1233!--    the tower:
1234       tower_n = ( hub_y(inot) + 0.5_wp * tower_diameter(inot) - 0.5_wp * dy ) / dy
1235       tower_s = ( hub_y(inot) - 0.5_wp * tower_diameter(inot) - 0.5_wp * dy ) / dy
[1819]1236
1237!
[4497]1238!--    Determine the fraction of the grid box area overlapping with the tower area and multiply
1239!--    it with the drag of the tower:
1240       IF ( ( nxlg <= i )  .AND.  ( nxrg >= i ) )  THEN
[1819]1241
[4497]1242          DO  j = nys, nyn
[1819]1243!
[4497]1244!--          Loop from south to north boundary of tower:
1245             IF ( ( j >= tower_s )  .AND.  ( j <= tower_n ) )  THEN
[1839]1246
[4497]1247                DO  k = nzb, nzt
[1819]1248
[4497]1249                   IF ( k == k_hub(inot) )  THEN
1250                      IF ( tower_n - tower_s >= 1 )  THEN
[1839]1251!
[4497]1252!--                   Leftmost and rightmost grid box:
1253                         IF ( j == tower_s )  THEN
1254                            tow_cd_surf(k,j,i) = ( hub_z(inot) -                                   &
1255                                 ( k_hub(inot) * dz(1) - 0.5_wp * dz(1) ) ) * & ! extension in z-direction
1256                                 ( ( tower_s + 1.0_wp + 0.5_wp ) * dy    -                         &
1257                                 ( hub_y(inot) - 0.5_wp * tower_diameter(inot) ) ) * & ! extension in y-direction
1258                               tower_cd(inot)
1259
1260                         ELSEIF ( j == tower_n )  THEN
1261                            tow_cd_surf(k,j,i) = ( hub_z(inot)            -                        &
1262                                 ( k_hub(inot) * dz(1) - 0.5_wp * dz(1) ) ) * & ! extension in z-direction
1263                               ( ( hub_y(inot) + 0.5_wp * tower_diameter(inot) )   -               &
1264                                 ( tower_n + 0.5_wp ) * dy ) * & ! extension in y-direction
1265                               tower_cd(inot)
[1819]1266!
[4497]1267!--                      Grid boxes inbetween (where tow_cd_surf = grid box area):
[1819]1268                         ELSE
[4497]1269                            tow_cd_surf(k,j,i) = ( hub_z(inot) -                                   &
1270                                                 ( k_hub(inot) * dz(1) - 0.5_wp * dz(1) ) ) * dy * &
1271                                                 tower_cd(inot)
[1819]1272                         ENDIF
[1839]1273!
[4497]1274!--                   Tower lies completely within one grid box:
1275                      ELSE
1276                         tow_cd_surf(k,j,i) = ( hub_z(inot) - ( k_hub(inot) *                      &
1277                                              dz(1) - 0.5_wp * dz(1) ) ) *                         &
1278                                              tower_diameter(inot) * tower_cd(inot)
1279                      ENDIF
[1839]1280!
[4497]1281!--               In case that k is smaller than k_hub the following actions are carried out:
1282                   ELSEIF ( k < k_hub(inot) )  THEN
1283
1284                      IF ( ( tower_n - tower_s ) >= 1 )  THEN
[1839]1285!
[4497]1286!--                      Leftmost and rightmost grid box:
1287                         IF ( j == tower_s )  THEN
1288                            tow_cd_surf(k,j,i) = dz(1) * ( ( tower_s + 1 + 0.5_wp ) * dy -         &
1289                                                ( hub_y(inot) - 0.5_wp * tower_diameter(inot) ) )  &
1290                                                * tower_cd(inot)
1291
1292                         ELSEIF ( j == tower_n )  THEN
1293                            tow_cd_surf(k,j,i) = dz(1) * ( ( hub_y(inot) + 0.5_wp *                &
1294                                                 tower_diameter(inot) ) - ( tower_n + 0.5_wp )     &
1295                                                 * dy ) * tower_cd(inot)
[1839]1296!
[4497]1297!--                      Grid boxes inbetween (where tow_cd_surf = grid box area):
[1819]1298                         ELSE
[4497]1299                            tow_cd_surf(k,j,i) = dz(1) * dy * tower_cd(inot)
1300                         ENDIF
1301!
1302!--                      Tower lies completely within one grid box:
1303                      ELSE
1304                         tow_cd_surf(k,j,i) = dz(1) * tower_diameter(inot) * tower_cd(inot)
1305                      ENDIF ! end if larger than grid box
[1839]1306
[4497]1307                   ENDIF    ! end if k == k_hub
[1839]1308
[4497]1309                ENDDO       ! end loop over k
[1839]1310
[4497]1311             ENDIF          ! end if inside north and south boundary of tower
[1839]1312
[4497]1313          ENDDO             ! end loop over j
[1839]1314
[4497]1315       ENDIF                ! end if hub inside domain + ghostpoints
[1819]1316
[4497]1317
1318       CALL exchange_horiz( tow_cd_surf, nbgp )
1319
[1839]1320!
[4497]1321!--    Calculation of the nacelle area
1322!--    CAUTION: Currently disabled due to segmentation faults on the FLOW HPC cluster (Oldenburg)
[1864]1323!!
[4497]1324!!--    Tabulate the points on the circle that are required in the following for the calculation
1325!!--    of the Riemann integral (node points; they are called circle_points in the following):
[1864]1326!
[4497]1327!       dy_int = dy / 10000.0_wp
[1864]1328!
[4497]1329!       DO  i_ip = 1, upper_end
1330!          yvalue   = dy_int * ( i_ip - 0.5_wp ) + 0.5_wp * dy  !<--- segmentation fault
1331!          sqrt_arg = nacelle_radius(inot)**2 - ( yvalue - hub_y(inot) )**2  !<--- segmentation fault
1332!          IF ( sqrt_arg >= 0.0_wp )  THEN
[1864]1333!!
[4497]1334!!--          bottom intersection point
1335!             circle_points(1,i_ip) = hub_z(inot) - SQRT( sqrt_arg )
[1864]1336!!
[4497]1337!!--          top intersection point
1338!             circle_points(2,i_ip) = hub_z(inot) + SQRT( sqrt_arg )  !<--- segmentation fault
1339!          ELSE
1340!             circle_points(:,i_ip) = -111111  !<--- segmentation fault
1341!          ENDIF
1342!       ENDDO
[1864]1343!
1344!
[4497]1345!       DO  j = nys, nyn
[1864]1346!!
[4497]1347!!--       In case that the grid box is located completely outside the nacelle (y) it can
1348!!--       automatically be stated that there is no overlap between the grid box and the nacelle
1349!!--       and consequently we can set nac_cd_surf(:,j,i) = 0.0:
1350!          IF ( ( j >= index_nacl(inot) )  .AND.  ( j <= index_nacr(inot) ) )  THEN
1351!             DO  k = nzb+1, nzt
[1864]1352!!
[4497]1353!!--             In case that the grid box is located completely outside the nacelle (z) it can
1354!!--             automatically be stated that there is no overlap between the grid box and the
1355!!--             nacelle and consequently we can set nac_cd_surf(k,j,i) = 0.0:
1356!                IF ( ( k >= index_nacb(inot) )  .OR.                           &
1357!                     ( k <= index_nact(inot) ) )  THEN
[1864]1358!!
[4497]1359!!--                For all other cases Riemann integrals are calculated. Here, the points on the
1360!!--                circle that have been determined above are used in order to calculate the
1361!!--                overlap between the gridbox and the nacelle area (area approached by 10000
1362!!--                rectangulars dz_int * dy_int):
1363!                   DO  i_ipg = 1, 10000
1364!                      dz_int = dz
1365!                      i_ip = j * 10000 + i_ipg
[1864]1366!!
[4497]1367!!--                   Determine the vertical extension dz_int of the circle within the current
1368!!--                   grid box:
1369!                      IF ( ( circle_points(2,i_ip) < zw(k) ) .AND.          &  !<--- segmentation fault
1370!                           ( circle_points(2,i_ip) >= zw(k-1) ) ) THEN
1371!                         dz_int = dz_int -                                  &  !<--- segmentation fault
1372!                                  ( zw(k) - circle_points(2,i_ip) )
1373!                      ENDIF
1374!                      IF ( ( circle_points(1,i_ip) <= zw(k) ) .AND.         &  !<--- segmentation fault
1375!                           ( circle_points(1,i_ip) > zw(k-1) ) ) THEN
1376!                         dz_int = dz_int -                                  &
1377!                                  ( circle_points(1,i_ip) - zw(k-1) )
1378!                      ENDIF
1379!                      IF ( zw(k-1) > circle_points(2,i_ip) ) THEN
1380!                         dz_int = 0.0_wp
1381!                      ENDIF
1382!                      IF ( zw(k) < circle_points(1,i_ip) ) THEN
1383!                         dz_int = 0.0_wp
1384!                      ENDIF
1385!                      IF ( ( nxlg <= i ) .AND. ( nxrg >= i ) ) THEN
1386!                         nac_cd_surf(k,j,i) = nac_cd_surf(k,j,i) +        &  !<--- segmentation fault
1387!                                               dy_int * dz_int * nacelle_cd(inot)
1388!                      ENDIF
1389!                   ENDDO
1390!                ENDIF
1391!             ENDDO
1392!          ENDIF
1393!
1394!       ENDDO
1395!
1396!       CALL exchange_horiz( nac_cd_surf, nbgp )  !<---  segmentation fault
[1819]1397
[4497]1398    ENDDO  ! end of loop over turbines
[1819]1399
[4497]1400    tow_cd_surf   = tow_cd_surf   / ( dx * dy * dz(1) )  ! Normalize tower drag
1401    nac_cd_surf = nac_cd_surf / ( dx * dy * dz(1) )      ! Normalize nacelle drag
[1819]1402
[4497]1403    CALL wtm_read_blade_tables
[3685]1404
[4497]1405    IF ( debug_output )  CALL debug_message( 'wtm_init', 'end' )
[1864]1406
[4497]1407 END SUBROUTINE wtm_init
[1864]1408
[4497]1409
1410
[4423]1411SUBROUTINE wtm_init_output
[4497]1412
1413
1414!    INTEGER(iwp) ::  ntimesteps              !< number of timesteps defined in NetCDF output file
1415!    INTEGER(iwp) ::  ntimesteps_max = 80000  !< number of maximum timesteps defined in NetCDF output file
1416    INTEGER(iwp) ::  return_value            !< returned status value of called function
1417
1418    INTEGER(iwp) ::  n  !< running index
1419
1420    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  ndim !< dummy to write dimension
1421
1422
[4411]1423!
[4497]1424!-- Create NetCDF output file:
[4465]1425#if defined( __netcdf4 )
1426    nc_filename = 'DATA_1D_TS_WTM_NETCDF' // TRIM( coupling_char )
[4423]1427    return_value = dom_def_file( nc_filename, 'netcdf4-serial' )
[4465]1428#else
[4497]1429    message_string = 'Wind turbine model output requires NetCDF version 4. ' //                    &
[4465]1430                     'No output file will be created.'
[4497]1431                   CALL message( 'wtm_init_output', 'PA0672', 0, 1, 0, 6, 0 )
[4465]1432#endif
[4423]1433    IF ( myid == 0 )  THEN
[4411]1434!
[4497]1435!--    Define dimensions in output file:
[4447]1436       ALLOCATE( ndim(1:n_turbines) )
1437       DO  n = 1, n_turbines
[4411]1438          ndim(n) = n
1439       ENDDO
[4497]1440       return_value = dom_def_dim( nc_filename,                                                    &
1441                                   dimension_name = 'turbine',                                     &
1442                                   output_type = 'int32',                                          &
1443                                   bounds = (/1_iwp, n_turbines/),                                 &
[4411]1444                                   values_int32 = ndim )
1445       DEALLOCATE( ndim )
1446
[4497]1447       return_value = dom_def_dim( nc_filename,                                                    &
1448                                   dimension_name = 'time',                                        &
1449                                   output_type = 'real32',                                         &
1450                                   bounds = (/1_iwp/),                                             &
[4426]1451                                   values_realwp = (/0.0_wp/) )
[4497]1452
[4411]1453       variable_name = 'x'
[4497]1454       return_value = dom_def_var( nc_filename,                                                    &
1455                                   variable_name = variable_name,                                  &
1456                                   dimension_names = (/'turbine'/),                                &
[4411]1457                                   output_type = 'real32' )
[4465]1458
[4411]1459       variable_name = 'y'
[4497]1460       return_value = dom_def_var( nc_filename,                                                    &
1461                                   variable_name = variable_name,                                  &
1462                                   dimension_names = (/'turbine'/),                                &
[4411]1463                                   output_type = 'real32' )
1464
1465       variable_name = 'z'
[4497]1466       return_value = dom_def_var( nc_filename,                                                    &
1467                                   variable_name = variable_name,                                  &
1468                                   dimension_names = (/'turbine'/),                                &
[4411]1469                                   output_type = 'real32' )
1470
[4465]1471
1472       variable_name = 'rotor_diameter'
[4497]1473       return_value = dom_def_var( nc_filename,                                                    &
1474                                   variable_name = variable_name,                                  &
1475                                   dimension_names = (/'turbine'/),                                &
[4465]1476                                   output_type = 'real32' )
1477
1478       variable_name = 'tower_diameter'
[4497]1479       return_value = dom_def_var( nc_filename,                                                    &
1480                                   variable_name = variable_name,                                  &
1481                                   dimension_names = (/'turbine'/),                                &
[4465]1482                                   output_type = 'real32' )
1483
[4497]1484       return_value = dom_def_att( nc_filename,                                                    &
1485                                   variable_name = 'time',                                         &
1486                                   attribute_name = 'units',                                       &
[4411]1487                                   value = 'seconds since ' // origin_date_time )
[4465]1488
[4497]1489       return_value = dom_def_att( nc_filename,                                                    &
1490                                   variable_name = 'x',                                            &
1491                                   attribute_name = 'units',                                       &
[4411]1492                                   value = 'm' )
1493
[4497]1494       return_value = dom_def_att( nc_filename,                                                    &
1495                                   variable_name = 'y',                                            &
1496                                   attribute_name = 'units',                                       &
1497                                   value = 'm' )
[4411]1498
[4497]1499       return_value = dom_def_att( nc_filename,                                                    &
1500                                   variable_name = 'z',                                            &
1501                                   attribute_name = 'units',                                       &
[4465]1502                                   value = 'm' )
[4411]1503
[4497]1504       return_value = dom_def_att( nc_filename,                                                    &
1505                                   variable_name = 'rotor_diameter',                               &
1506                                   attribute_name = 'units',                                       &
[4465]1507                                   value = 'm' )
1508
[4497]1509       return_value = dom_def_att( nc_filename,                                                    &
1510                                   variable_name = 'tower_diameter',                               &
1511                                   attribute_name = 'units',                                       &
[4465]1512                                   value = 'm' )
1513
[4497]1514       return_value = dom_def_att( nc_filename,                                                    &
1515                                   variable_name = 'x',                                            &
1516                                   attribute_name = 'long_name',                                   &
[4411]1517                                   value = 'x location of rotor center' )
1518
[4497]1519       return_value = dom_def_att( nc_filename,                                                    &
1520                                   variable_name = 'y',                                            &
1521                                   attribute_name = 'long_name',                                   &
1522                                   value = 'y location of rotor center' )
[4411]1523
[4497]1524       return_value = dom_def_att( nc_filename,                                                    &
1525                                   variable_name = 'z',                                            &
1526                                   attribute_name = 'long_name',                                   &
1527                                   value = 'z location of rotor center' )
[4465]1528
[4497]1529       return_value = dom_def_att( nc_filename,                                                    &
1530                                   variable_name = 'turbine_name',                                 &
1531                                   attribute_name = 'long_name',                                   &
[4465]1532                                   value = 'turbine name')
1533
[4497]1534       return_value = dom_def_att( nc_filename,                                                    &
1535                                   variable_name = 'rotor_diameter',                               &
1536                                   attribute_name = 'long_name',                                   &
[4465]1537                                   value = 'rotor diameter')
1538
[4497]1539       return_value = dom_def_att( nc_filename,                                                    &
1540                                   variable_name = 'tower_diameter',                               &
1541                                   attribute_name = 'long_name',                                   &
[4465]1542                                   value = 'tower diameter')
1543
[4497]1544       return_value = dom_def_att( nc_filename,                                                    &
1545                                   variable_name = 'time',                                         &
1546                                   attribute_name = 'standard_name',                               &
[4411]1547                                   value = 'time')
1548
[4497]1549       return_value = dom_def_att( nc_filename,                                                    &
1550                                   variable_name = 'time',                                         &
1551                                   attribute_name = 'axis',                                        &
[4411]1552                                   value = 'T')
1553
[4497]1554       return_value = dom_def_att( nc_filename,                                                    &
1555                                   variable_name = 'x',                                            &
1556                                   attribute_name = 'axis',                                        &
[4411]1557                                   value = 'X' )
1558
[4497]1559       return_value = dom_def_att( nc_filename,                                                    &
1560                                   variable_name = 'y',                                            &
1561                                   attribute_name = 'axis',                                        &
[4465]1562                                   value = 'Y' )
[4411]1563
[4497]1564
[4465]1565       variable_name = 'generator_power'
[4497]1566       return_value = dom_def_var( nc_filename,                                                    &
1567                                   variable_name = variable_name,                                  &
1568                                   dimension_names = (/ 'turbine', 'time   ' /),                   &
[4465]1569                                   output_type = 'real32' )
[4411]1570
[4497]1571       return_value = dom_def_att( nc_filename,                                                    &
1572                                   variable_name = variable_name,                                  &
1573                                   attribute_name = 'units',                                       &
1574                                   value = 'W' )
[4465]1575
[4411]1576       variable_name = 'generator_speed'
[4497]1577       return_value = dom_def_var( nc_filename,                                                    &
1578                                   variable_name = variable_name,                                  &
1579                                   dimension_names = (/ 'turbine', 'time   ' /),                   &
[4411]1580                                   output_type = 'real32' )
[4465]1581
[4497]1582       return_value = dom_def_att( nc_filename,                                                    &
1583                                   variable_name = variable_name,                                  &
1584                                   attribute_name = 'units',                                       &
[4411]1585                                   value = 'rad/s' )
[4465]1586
[4411]1587       variable_name = 'generator_torque'
[4497]1588       return_value = dom_def_var( nc_filename,                                                    &
1589                                   variable_name = variable_name,                                  &
1590                                   dimension_names = (/ 'turbine', 'time   ' /),                   &
[4411]1591                                   output_type = 'real32' )
[4497]1592
1593       return_value = dom_def_att( nc_filename,                                                    &
1594                                   variable_name = variable_name,                                  &
1595                                   attribute_name = 'units',                                       &
[4411]1596                                   value = 'Nm' )
1597
1598       variable_name = 'pitch_angle'
[4497]1599       return_value = dom_def_var( nc_filename,                                                    &
1600                                   variable_name = variable_name,                                  &
1601                                   dimension_names = (/ 'turbine', 'time   ' /),                   &
[4411]1602                                   output_type = 'real32' )
[4465]1603
[4497]1604       return_value = dom_def_att( nc_filename,                                                    &
1605                                   variable_name = variable_name,                                  &
1606                                   attribute_name = 'units',                                       &
[4465]1607                                   value = 'degrees' )
1608
1609       variable_name = 'rotor_power'
[4497]1610       return_value = dom_def_var( nc_filename,                                                    &
1611                                   variable_name = variable_name,                                  &
1612                                   dimension_names = (/ 'turbine', 'time   ' /),                   &
[4411]1613                                   output_type = 'real32' )
[4465]1614
[4497]1615       return_value = dom_def_att( nc_filename,                                                    &
1616                                   variable_name = variable_name,                                  &
1617                                   attribute_name = 'units',                                       &
1618                                   value = 'W' )
1619
[4465]1620       variable_name = 'rotor_speed'
[4497]1621       return_value = dom_def_var( nc_filename,                                                    &
1622                                   variable_name = variable_name,                                  &
1623                                   dimension_names = (/ 'turbine', 'time   ' /),                   &
[4411]1624                                   output_type = 'real32' )
[4497]1625
1626       return_value = dom_def_att( nc_filename,                                                    &
1627                                   variable_name = variable_name,                                  &
1628                                   attribute_name = 'units',                                       &
[4465]1629                                   value = 'rad/s' )
1630
1631       variable_name = 'rotor_thrust'
[4497]1632       return_value = dom_def_var( nc_filename,                                                    &
1633                                   variable_name = variable_name,                                  &
1634                                   dimension_names = (/ 'turbine', 'time   ' /),                   &
[4411]1635                                   output_type = 'real32' )
[4465]1636
[4497]1637       return_value = dom_def_att( nc_filename,                                                    &
1638                                   variable_name = variable_name,                                  &
1639                                   attribute_name = 'units',                                       &
1640                                   value = 'N' )
1641
[4465]1642       variable_name = 'rotor_torque'
[4497]1643       return_value = dom_def_var( nc_filename,                                                    &
1644                                   variable_name = variable_name,                                  &
1645                                   dimension_names = (/ 'turbine', 'time   ' /),                   &
[4465]1646                                   output_type = 'real32' )
[4497]1647
1648       return_value = dom_def_att( nc_filename,                                                    &
1649                                   variable_name = variable_name,                                  &
1650                                   attribute_name = 'units',                                       &
[4465]1651                                   value = 'Nm' )
1652
[4411]1653       variable_name = 'wind_direction'
[4497]1654       return_value = dom_def_var( nc_filename,                                                    &
1655                                   variable_name = variable_name,                                  &
1656                                   dimension_names = (/ 'turbine', 'time   ' /),                   &
[4411]1657                                   output_type = 'real32' )
[4465]1658
[4497]1659       return_value = dom_def_att( nc_filename,                                                    &
1660                                   variable_name = variable_name,                                  &
1661                                   attribute_name = 'units',                                       &
1662                                   value = 'degrees' )
1663
[4411]1664       variable_name = 'yaw_angle'
[4497]1665       return_value = dom_def_var( nc_filename,                                                    &
1666                                   variable_name = variable_name,                                  &
1667                                   dimension_names = (/ 'turbine', 'time   ' /),                   &
[4411]1668                                   output_type = 'real32' )
[4423]1669
[4497]1670       return_value = dom_def_att( nc_filename,                                                    &
1671                                   variable_name = variable_name,                                  &
1672                                   attribute_name = 'units',                                       &
1673                                   value = 'degrees' )
1674
[4465]1675   ENDIF
[4423]1676END SUBROUTINE
[4497]1677
1678!--------------------------------------------------------------------------------------------------!
[1864]1679! Description:
1680! ------------
[4497]1681!> Read in layout of the rotor blade , the lift and drag tables and the distribution of lift and
1682!> drag tables along the blade
1683!--------------------------------------------------------------------------------------------------!
[1912]1684!
[4497]1685 SUBROUTINE wtm_read_blade_tables
[1819]1686
[1839]1687
[4497]1688    IMPLICIT NONE
[1864]1689
[4497]1690    CHARACTER(200) :: chmess  !< Read in string
[1839]1691
[4497]1692    INTEGER(iwp) ::  ii  !< running index
1693    INTEGER(iwp) ::  jj  !< running index
[1839]1694
[4497]1695    INTEGER(iwp) ::  ierrn  !<
[1839]1696
[4497]1697    INTEGER(iwp) ::  dlen        !< no. rows of local table
1698    INTEGER(iwp) ::  dlenbl      !< no. rows of cd, cl table
1699    INTEGER(iwp) ::  dlenbl_int  !< no. rows of interpolated cd, cl tables
1700    INTEGER(iwp) ::  ialpha      !< table position of current alpha value
1701    INTEGER(iwp) ::  iialpha     !<
1702    INTEGER(iwp) ::  iir         !<
1703    INTEGER(iwp) ::  radres      !< radial resolution
1704    INTEGER(iwp) ::  t1          !< no. of airfoil
1705    INTEGER(iwp) ::  t2          !< no. of airfoil
1706    INTEGER(iwp) ::  trow        !<
[1864]1707
1708
[4497]1709    REAL(wp) :: alpha_attack_i  !<
1710    REAL(wp) :: weight_a        !<
1711    REAL(wp) :: weight_b        !<
[1864]1712
[4497]1713    INTEGER(iwp), DIMENSION(:), ALLOCATABLE :: ttoint1  !<
1714    INTEGER(iwp), DIMENSION(:), ALLOCATABLE :: ttoint2  !<
[1864]1715
[4497]1716    REAL(wp), DIMENSION(:), ALLOCATABLE :: turb_cd_sel1  !<
1717    REAL(wp), DIMENSION(:), ALLOCATABLE :: turb_cd_sel2  !<
1718    REAL(wp), DIMENSION(:), ALLOCATABLE :: turb_cl_sel1  !<
1719    REAL(wp), DIMENSION(:), ALLOCATABLE :: turb_cl_sel2  !<
1720    REAL(wp), DIMENSION(:), ALLOCATABLE :: read_cl_cd    !< read in var array
[1864]1721
[4497]1722    REAL(wp), DIMENSION(:),   ALLOCATABLE :: alpha_attack_tab  !<
1723    REAL(wp), DIMENSION(:),   ALLOCATABLE :: trad1             !<
1724    REAL(wp), DIMENSION(:),   ALLOCATABLE :: trad2             !<
1725    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: turb_cd_table     !<
1726    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: turb_cl_table     !<
[1864]1727
[4497]1728    ALLOCATE ( read_cl_cd(1:2 * n_airfoils + 1) )
[1864]1729
[4497]1730!
1731!-- Read in the distribution of lift and drag tables along the blade, the layout of the rotor
1732!-- blade and the lift and drag tables:
1733    OPEN ( 90, FILE='WTM_DATA', STATUS='OLD', FORM='FORMATTED', IOSTAT=ierrn )
[1864]1734
[4497]1735    IF ( ierrn /= 0 )  THEN
1736       message_string = 'file WTM_DATA does not exist'
1737       CALL message( 'wtm_init', 'PA0464', 1, 2, 0, 6, 0 )
1738    ENDIF
[1864]1739!
[4497]1740!-- Read distribution table:
1741    dlen = 0
[1864]1742
[4497]1743    READ ( 90, '(3/)' )
[1864]1744
[4497]1745    rloop3: DO
1746       READ ( 90, *, IOSTAT=ierrn ) chmess
1747       IF ( ierrn < 0  .OR.  chmess == '#'  .OR.  chmess == '')  EXIT rloop3
1748       dlen = dlen + 1
1749    ENDDO rloop3
[1864]1750
[4497]1751    ALLOCATE( trad1(1:dlen), trad2(1:dlen), ttoint1(1:dlen), ttoint2(1:dlen) )
[1864]1752
[4497]1753    DO  jj = 1, dlen+1
1754       BACKSPACE ( 90, IOSTAT=ierrn )
1755    ENDDO
[1819]1756
[4497]1757    DO  jj = 1, dlen
1758       READ ( 90, * ) trad1(jj), trad2(jj), ttoint1(jj), ttoint2(jj)
1759    ENDDO
1760
[1864]1761!
[4497]1762!-- Read layout table:
1763    dlen = 0
[1819]1764
[4497]1765    READ ( 90, '(3/)')
[1864]1766
[4497]1767    rloop1: DO
1768       READ ( 90, *, IOSTAT=ierrn ) chmess
1769       IF ( ierrn < 0  .OR.  chmess == '#'  .OR.  chmess == '')  EXIT rloop1
1770       dlen = dlen + 1
1771    ENDDO rloop1
[1864]1772
[4497]1773    ALLOCATE( lrd(1:dlen), ard(1:dlen), crd(1:dlen) )
1774    DO  jj = 1, dlen + 1
1775       BACKSPACE ( 90, IOSTAT=ierrn )
1776    ENDDO
1777    DO  jj = 1, dlen
1778       READ ( 90, * ) lrd(jj), ard(jj), crd(jj)
1779    ENDDO
[1864]1780
[4497]1781!
1782!-- Read tables (turb_cl(alpha),turb_cd(alpha) for the different profiles:
1783    dlen = 0
[1864]1784
[4497]1785    READ ( 90, '(3/)' )
[1864]1786
[4497]1787    rloop2: DO
1788       READ ( 90, *, IOSTAT=ierrn ) chmess
1789       IF ( ierrn < 0  .OR.  chmess == '#'  .OR.  chmess == '')  EXIT rloop2
1790       dlen = dlen + 1
1791    ENDDO rloop2
[1864]1792
[4497]1793    ALLOCATE( alpha_attack_tab(1:dlen), turb_cl_table(1:dlen,1:n_airfoils), &
1794              turb_cd_table(1:dlen,1:n_airfoils) )
1795
1796    DO  jj = 1, dlen + 1
1797       BACKSPACE ( 90, IOSTAT=ierrn )
1798    ENDDO
1799
1800    DO  jj = 1, dlen
1801       READ ( 90, * ) read_cl_cd
1802       alpha_attack_tab(jj) = read_cl_cd(1)
1803       DO  ii = 1, n_airfoils
1804          turb_cl_table(jj,ii) = read_cl_cd(ii * 2)
1805          turb_cd_table(jj,ii) = read_cl_cd(ii * 2 + 1)
[1839]1806       ENDDO
[1864]1807
[4497]1808    ENDDO
[1864]1809
[4497]1810    dlenbl = dlen
[1819]1811
[4497]1812    CLOSE ( 90 )
1813
[1864]1814!
[4497]1815!-- For each possible radial position (resolution: 0.1 m --> 631 values if rotor_radius(1)=63m)
1816!-- and each possible angle of attack (resolution: 0.1 degrees --> 3601 values!) determine the
1817!-- lift and drag coefficient by interpolating between the tabulated values of each table
1818!-- (interpolate to current angle of attack) and between the tables (interpolate to current
1819!-- radial position):
1820    ALLOCATE( turb_cl_sel1(1:dlenbl) )
1821    ALLOCATE( turb_cl_sel2(1:dlenbl) )
1822    ALLOCATE( turb_cd_sel1(1:dlenbl) )
1823    ALLOCATE( turb_cd_sel2(1:dlenbl) )
[1839]1824
[4497]1825    radres     = INT( rotor_radius(1) * 10.0_wp ) + 1_iwp
1826    dlenbl_int = INT( 360.0_wp / accu_cl_cd_tab ) + 1_iwp
[1819]1827
[4497]1828    ALLOCATE( turb_cl_tab(1:dlenbl_int,1:radres) )
1829    ALLOCATE( turb_cd_tab(1:dlenbl_int,1:radres) )
[1839]1830
[4497]1831    DO  iir = 1, radres ! loop over radius
[1864]1832
[4497]1833       cur_r = ( iir - 1_iwp ) * 0.1_wp
[2836]1834!
[4497]1835!--    Find position in table 1:
1836       lct = MINLOC( ABS( trad1 - cur_r ) )
1837!          lct(1) = lct(1)
[1864]1838
[4497]1839       IF ( ( trad1(lct(1)) - cur_r ) > 0.0 )  THEN
1840          lct(1) = lct(1) - 1
1841       ENDIF
[1864]1842
[4497]1843       trow = lct(1)
[2836]1844!
[4497]1845!--    Calculate weights for radius interpolation:
1846       weight_a = ( trad2(trow) - cur_r ) / ( trad2(trow) - trad1(trow) )
1847       weight_b = ( cur_r - trad1(trow) ) / ( trad2(trow) - trad1(trow) )
1848       t1 = ttoint1(trow)
1849       t2 = ttoint2(trow)
[1864]1850
[4497]1851       IF ( t1 == t2 )  THEN  ! if both are the same, the weights are NaN
1852          weight_a = 0.5_wp   ! then do interpolate in between same twice
1853          weight_b = 0.5_wp   ! using 0.5 as weight
1854       ENDIF
[2836]1855
[4497]1856       IF ( t1 == 0 .AND. t2 == 0 )  THEN
1857          turb_cd_sel1 = 0.0_wp
1858          turb_cd_sel2 = 0.0_wp
1859          turb_cl_sel1 = 0.0_wp
1860          turb_cl_sel2 = 0.0_wp
[2836]1861
[4497]1862          turb_cd_tab(1,iir) = 0.0_wp  ! For -180 degrees (iialpha=1) the values
1863          turb_cl_tab(1,iir) = 0.0_wp  ! for each radius has to be set
1864                                       ! explicitly
1865       ELSE
1866          turb_cd_sel1 = turb_cd_table(:,t1)
1867          turb_cd_sel2 = turb_cd_table(:,t2)
1868          turb_cl_sel1 = turb_cl_table(:,t1)
1869          turb_cl_sel2 = turb_cl_table(:,t2)
[2836]1870!
[4497]1871!--       For -180 degrees (iialpha=1) the values for each radius has to be set explicitly:
1872          turb_cd_tab(1,iir) = ( weight_a * turb_cd_table(1,t1) + weight_b * turb_cd_table(1,t2) )
1873          turb_cl_tab(1,iir) = ( weight_a * turb_cl_table(1,t1) + weight_b * turb_cl_table(1,t2) )
1874       ENDIF
[2836]1875
[4497]1876       DO  iialpha = 2, dlenbl_int  ! loop over angles
[1819]1877
[4497]1878          alpha_attack_i = -180.0_wp + REAL( iialpha-1 ) * accu_cl_cd_tab
1879          ialpha = 1
1880
1881          DO WHILE  ( ( alpha_attack_i > alpha_attack_tab(ialpha) ) .AND. ( ialpha < dlen ) )
1882             ialpha = ialpha + 1
1883          ENDDO
1884
[1864]1885!
[4497]1886!--       Interpolation of lift and drag coefficiencts on fine grid of radius segments and angles
1887!--       of attack:
1888          turb_cl_tab(iialpha,iir) = ( alpha_attack_tab(ialpha) - alpha_attack_i ) /               &
1889                                     ( alpha_attack_tab(ialpha) - alpha_attack_tab(ialpha-1) ) *   &
1890                                     ( weight_a * turb_cl_sel1(ialpha-1) +                         &
1891                                       weight_b * turb_cl_sel2(ialpha-1) ) +                       &
1892                                     ( alpha_attack_i - alpha_attack_tab(ialpha-1) ) /             &
1893                                     ( alpha_attack_tab(ialpha) - alpha_attack_tab(ialpha-1) ) *   &
1894                                     ( weight_a * turb_cl_sel1(ialpha) +                           &
1895                                       weight_b * turb_cl_sel2(ialpha) )
1896          turb_cd_tab(iialpha,iir) = ( alpha_attack_tab(ialpha) - alpha_attack_i ) /               &
1897                                     ( alpha_attack_tab(ialpha) - alpha_attack_tab(ialpha-1) ) *   &
1898                                     ( weight_a * turb_cd_sel1(ialpha-1) +                         &
1899                                       weight_b * turb_cd_sel2(ialpha-1) ) +                       &
1900                                     ( alpha_attack_i - alpha_attack_tab(ialpha-1) ) /             &
1901                                     ( alpha_attack_tab(ialpha) - alpha_attack_tab(ialpha-1) ) *   &
1902                                     ( weight_a * turb_cd_sel1(ialpha) +                           &
1903                                       weight_b * turb_cd_sel2(ialpha) )
[3182]1904
[4497]1905       ENDDO   ! end loop over angles of attack
[1819]1906
[4497]1907    ENDDO   ! end loop over radius
[2836]1908
[1819]1909
[4497]1910 END SUBROUTINE wtm_read_blade_tables
[1819]1911
[4497]1912
1913!--------------------------------------------------------------------------------------------------!
[1864]1914! Description:
1915! ------------
[4497]1916!> The projection matrix for the coordinate system of therotor disc in respect to the yaw and tilt
1917!> angle of the rotor is calculated
1918!--------------------------------------------------------------------------------------------------!
1919 SUBROUTINE wtm_rotate_rotor( inot )
[1819]1920
[1864]1921
[4497]1922    IMPLICIT NONE
[1864]1923
[4497]1924    INTEGER(iwp) :: inot
[1864]1925!
[4497]1926!-- Calculation of the rotation matrix for the application of the tilt to the rotors:
1927    rot_eigen_rad(1) = SIN( yaw_angle(inot) )   ! x-component of the radial eigenvector
1928    rot_eigen_rad(2) = COS( yaw_angle(inot) )   ! y-component of the radial eigenvector
1929    rot_eigen_rad(3) = 0.0_wp                   ! z-component of the radial eigenvector
[1864]1930
[4497]1931    rot_eigen_azi(1) = 0.0_wp                   ! x-component of the azimuth eigenvector
1932    rot_eigen_azi(2) = 0.0_wp                   ! y-component of the azimuth eigenvector
1933    rot_eigen_azi(3) = 1.0_wp                   ! z-component of the azimuth eigenvector
[1864]1934
[4497]1935    rot_eigen_nor(1) =  COS( yaw_angle(inot) )  ! x-component of the normal eigenvector
1936    rot_eigen_nor(2) = -SIN( yaw_angle(inot) )  ! y-component of the normal eigenvector
1937    rot_eigen_nor(3) = 0.0_wp                   ! z-component of the normal eigenvector
1938
[1864]1939!
[4497]1940!-- Calculation of the coordinate transformation matrix to apply a tilt to the rotor.
1941!-- If tilt = 0, rot_coord_trans is a unit matrix.
1942    rot_coord_trans(inot,1,1) = rot_eigen_rad(1)**2                   *                            &
1943                                ( 1.0_wp - COS( tilt_angle ) ) + COS( tilt_angle )
1944    rot_coord_trans(inot,1,2) = rot_eigen_rad(1) * rot_eigen_rad(2)   *                            &
1945                                ( 1.0_wp - COS( tilt_angle ) )              -                      &
1946                                rot_eigen_rad(3) * SIN( tilt_angle )
1947    rot_coord_trans(inot,1,3) = rot_eigen_rad(1) * rot_eigen_rad(3)   *                            &
1948                                ( 1.0_wp - COS( tilt_angle ) )              +                      &
1949                                rot_eigen_rad(2) * SIN( tilt_angle )
1950    rot_coord_trans(inot,2,1) = rot_eigen_rad(2) * rot_eigen_rad(1)   *                            &
1951                                ( 1.0_wp - COS( tilt_angle ) )              +                      &
1952                                rot_eigen_rad(3) * SIN( tilt_angle )
1953    rot_coord_trans(inot,2,2) = rot_eigen_rad(2)**2                   *                            &
1954                                ( 1.0_wp - COS( tilt_angle ) ) + COS( tilt_angle )
1955    rot_coord_trans(inot,2,3) = rot_eigen_rad(2) * rot_eigen_rad(3)   *                            &
1956                                ( 1.0_wp - COS( tilt_angle ) )              -                      &
1957                                rot_eigen_rad(1) * SIN( tilt_angle )
1958    rot_coord_trans(inot,3,1) = rot_eigen_rad(3) * rot_eigen_rad(1)   *                            &
1959                                ( 1.0_wp - COS( tilt_angle ) )              -                      &
1960                                rot_eigen_rad(2) * SIN( tilt_angle )
1961    rot_coord_trans(inot,3,2) = rot_eigen_rad(3) * rot_eigen_rad(2)   *                            &
1962                                ( 1.0_wp - COS( tilt_angle ) )              +                      &
1963                                rot_eigen_rad(1) * SIN( tilt_angle )
1964    rot_coord_trans(inot,3,3) = rot_eigen_rad(3)**2                   *                            &
1965                                ( 1.0_wp - COS( tilt_angle ) ) + COS( tilt_angle )
[1819]1966
[1864]1967!
[4497]1968!-- Vectors for the Transformation of forces from the rotor's spheric coordinate system to the
1969!-- cartesian coordinate system:
1970    rotx(inot,:) = MATMUL( rot_coord_trans(inot,:,:), rot_eigen_nor )
1971    roty(inot,:) = MATMUL( rot_coord_trans(inot,:,:), rot_eigen_rad )
1972    rotz(inot,:) = MATMUL( rot_coord_trans(inot,:,:), rot_eigen_azi )
[1839]1973
[4497]1974 END SUBROUTINE wtm_rotate_rotor
[1839]1975
[4497]1976
1977!--------------------------------------------------------------------------------------------------!
[1819]1978! Description:
1979! ------------
[1839]1980!> Calculation of the forces generated by the wind turbine
[4497]1981!--------------------------------------------------------------------------------------------------!
1982 SUBROUTINE wtm_forces
[1819]1983
[1864]1984
[4497]1985    IMPLICIT NONE
[1819]1986
1987
[4497]1988    INTEGER(iwp) ::  i, j, k       !< loop indices
1989    INTEGER(iwp) ::  ii, jj, kk    !<
1990    INTEGER(iwp) ::  inot          !< turbine loop index (turbine id)
1991    INTEGER(iwp) ::  iialpha, iir  !<
1992    INTEGER(iwp) ::  rseg          !<
1993    INTEGER(iwp) ::  ring          !<
[4467]1994
[4497]1995    REAL(wp)     ::  flag              !< flag to mask topography grid points
1996    REAL(wp)     ::  sin_rot, cos_rot  !<
1997    REAL(wp)     ::  sin_yaw, cos_yaw  !<
[4467]1998
[4497]1999    REAL(wp) ::  aa, bb, cc, dd  !< interpolation distances
2000    REAL(wp) ::  gg              !< interpolation volume var
[4467]2001
[4497]2002    REAL(wp) ::  dist_u_3d, dist_v_3d, dist_w_3d  !< smearing distances
2003
2004
[1839]2005!
[4497]2006!-- Variables for pitch control:
2007    INTEGER(iwp), DIMENSION(1) ::  lct = 0
[1839]2008
[4497]2009    LOGICAL ::  pitch_sw = .FALSE.
[1819]2010
[4497]2011    REAL(wp), DIMENSION(1)     ::  rad_d = 0.0_wp
[1819]2012
[4497]2013    REAL(wp) :: tl_factor  !< factor for tip loss correction
[1819]2014
2015
[4497]2016    CALL cpu_log( log_point_s(61), 'wtm_forces', 'start' )
[1819]2017
[4497]2018
2019    IF ( time_since_reference_point >= time_turbine_on )   THEN
2020
[1864]2021!
[4497]2022!--    Set forces to zero for each new time step:
2023       thrust(:,:,:)         = 0.0_wp
2024       torque_y(:,:,:)       = 0.0_wp
2025       torque_z(:,:,:)       = 0.0_wp
2026       torque_total(:)       = 0.0_wp
2027       rot_tend_x(:,:,:)     = 0.0_wp
2028       rot_tend_y(:,:,:)     = 0.0_wp
2029       rot_tend_z(:,:,:)     = 0.0_wp
2030       thrust_rotor(:)       = 0.0_wp
[1819]2031!
[4497]2032!--    Loop over number of turbines:
2033       DO  inot = 1, n_turbines
[1819]2034
[4497]2035          cos_yaw = COS(yaw_angle(inot))
2036          sin_yaw = SIN(yaw_angle(inot))
[1819]2037!
[4497]2038!--       Loop over rings of each turbine:
2039          !$OMP PARALLEL PRIVATE (ring, rseg, thrust_seg, torque_seg_y, torque_seg_z, sin_rot,  &
2040          !$OMP&                  cos_rot, re, rbx, rby, rbz, ii, jj, kk, aa, bb, cc, dd, gg)
2041          !$OMP DO
2042          DO  ring = 1, nrings(inot)
[3832]2043
[4497]2044             thrust_seg(:)   = 0.0_wp
2045             torque_seg_y(:) = 0.0_wp
2046             torque_seg_z(:) = 0.0_wp
[1819]2047!
[4497]2048!--          Determine distance between each ring (center) and the hub:
2049             cur_r = (ring - 0.5_wp) * delta_r(inot)
[1819]2050
2051!
[4497]2052!--          Loop over segments of each ring of each turbine:
2053             DO  rseg = 1, nsegs(ring,inot)
[1819]2054!
[4497]2055!--             !----------------------------------------------------------------------------------!
2056!--             !-- Determine coordinates of the ring segments                                   --!
2057!--             !----------------------------------------------------------------------------------!
[1819]2058!
[4497]2059!--             Determine angle of ring segment towards zero degree angle of rotor system
2060!--             (at zero degree rotor direction vectors aligned with y-axis):
2061                phi_rotor = rseg * 2.0_wp * pi / nsegs(ring,inot)
2062                cos_rot   = COS( phi_rotor )
2063                sin_rot   = SIN( phi_rotor )
[1819]2064
[4497]2065!--             Now the direction vectors can be determined with respect to the yaw and tilt angle:
2066                re(1) = cos_rot * sin_yaw
2067                re(2) = cos_rot * cos_yaw
2068                re(3) = sin_rot
[1819]2069
[4497]2070                rote = MATMUL( rot_coord_trans(inot,:,:), re )
[1819]2071!
[4497]2072!--             Coordinates of the single segments (center points):
2073                rbx(ring,rseg) = hub_x(inot) + cur_r * rote(1)
2074                rby(ring,rseg) = hub_y(inot) + cur_r * rote(2)
2075                rbz(ring,rseg) = hub_z(inot) + cur_r * rote(3)
[1819]2076
[4497]2077!--             !----------------------------------------------------------------------------------!
2078!--             !-- Interpolation of the velocity components from the cartesian grid point to    --!
2079!--             !-- the coordinates of each ring segment (follows a method used in the           --!
2080!--             !-- particle model)                                                              --!
2081!--             !----------------------------------------------------------------------------------!
[1819]2082
[4497]2083                u_int(inot,ring,rseg)     = 0.0_wp
2084                u_int_1_l(inot,ring,rseg) = 0.0_wp
[1819]2085
[4497]2086                v_int(inot,ring,rseg)     = 0.0_wp
2087                v_int_1_l(inot,ring,rseg) = 0.0_wp
[1819]2088
[4497]2089                w_int(inot,ring,rseg)     = 0.0_wp
2090                w_int_1_l(inot,ring,rseg) = 0.0_wp
[1819]2091
2092!
[4497]2093!--             Interpolation of the u-component:
2094                ii =   rbx(ring,rseg) * ddx
2095                jj = ( rby(ring,rseg) - 0.5_wp * dy ) * ddy
2096                kk = ( rbz(ring,rseg) + 0.5_wp * dz(1) ) / dz(1)
[1819]2097!
[4497]2098!--             Interpolate only if all required information is available on the current PE:
2099                IF ( ( ii >= nxl )  .AND.  ( ii <= nxr ) )  THEN
2100                   IF ( ( jj >= nys )  .AND.  ( jj <= nyn ) )  THEN
[1819]2101
[4497]2102                      aa = ( ( ii + 1          ) * dx - rbx(ring,rseg) ) *                         &
2103                           ( ( jj + 1 + 0.5_wp ) * dy - rby(ring,rseg) )
2104                      bb = ( rbx(ring,rseg) - ii * dx )                  *                         &
2105                           ( ( jj + 1 + 0.5_wp ) * dy - rby(ring,rseg) )
2106                      cc = ( ( ii+1            ) * dx - rbx(ring,rseg) ) *                         &
2107                           ( rby(ring,rseg) - ( jj + 0.5_wp ) * dy )
2108                      dd = ( rbx(ring,rseg) -              ii * dx )     *                         &
2109                           ( rby(ring,rseg) - ( jj + 0.5_wp ) * dy )
2110                      gg = dx * dy
[1819]2111
[4497]2112                      u_int_l = ( aa * u(kk,jj,ii) + bb * u(kk,jj,ii+1)   + cc * u(kk,jj+1,ii)     &
2113                                +  dd * u(kk,jj+1,ii+1) ) / gg
[1819]2114
[4497]2115                      u_int_u = ( aa * u(kk+1,jj,ii) + bb * u(kk+1,jj,ii+1) + cc * u(kk+1,jj+1,ii) &
2116                                + dd * u(kk+1,jj+1,ii+1) ) / gg
[1819]2117
[4497]2118                      u_int_1_l(inot,ring,rseg) = u_int_l + ( rbz(ring,rseg) - zu(kk) ) / dz(1) *  &
2119                                                ( u_int_u - u_int_l )
[1819]2120
2121                   ELSE
2122                      u_int_1_l(inot,ring,rseg) = 0.0_wp
2123                   ENDIF
2124
[4497]2125                ELSE
2126                   u_int_1_l(inot,ring,rseg) = 0.0_wp
2127                ENDIF
[1819]2128
[4497]2129
[1819]2130!
[4497]2131!--             Interpolation of the v-component:
2132                ii = ( rbx(ring,rseg) - 0.5_wp * dx ) * ddx
2133                jj =   rby(ring,rseg)                 * ddy
2134                kk = ( rbz(ring,rseg) + 0.5_wp * dz(1) ) / dz(1)
[1819]2135!
[4497]2136!--             Interpolate only if all required information is available on the current PE:
2137                IF ( ( ii >= nxl )  .AND.  ( ii <= nxr ) )  THEN
2138                   IF ( ( jj >= nys )  .AND.  ( jj <= nyn ) )  THEN
[1819]2139
[4497]2140                      aa = ( ( ii + 1 + 0.5_wp ) * dx - rbx(ring,rseg) ) *                         &
2141                           ( ( jj + 1 )          * dy - rby(ring,rseg) )
2142                      bb = ( rbx(ring,rseg)     - ( ii + 0.5_wp ) * dx ) *                         &
2143                           ( ( jj + 1 ) * dy          - rby(ring,rseg) )
2144                      cc = ( ( ii + 1 + 0.5_wp ) * dx - rbx(ring,rseg) ) *                         &
2145                           ( rby(ring,rseg)           -        jj * dy )
2146                      dd = ( rbx(ring,rseg)     - ( ii + 0.5_wp ) * dx ) *                         &
2147                           ( rby(ring,rseg)           -        jj * dy )
2148                      gg = dx * dy
[1819]2149
[4497]2150                      v_int_l = ( aa * v(kk,jj,ii) + bb * v(kk,jj,ii+1) + cc * v(kk,jj+1,ii)       &
2151                                + dd * v(kk,jj+1,ii+1) ) / gg
[1819]2152
[4497]2153                      v_int_u = ( aa * v(kk+1,jj,ii) + bb * v(kk+1,jj,ii+1) + cc * v(kk+1,jj+1,ii) &
2154                                + dd * v(kk+1,jj+1,ii+1) ) / gg
[1819]2155
[4497]2156                      v_int_1_l(inot,ring,rseg) = v_int_l + ( rbz(ring,rseg) - zu(kk) ) / dz(1) *  &
2157                                                ( v_int_u - v_int_l )
[1819]2158
2159                   ELSE
2160                      v_int_1_l(inot,ring,rseg) = 0.0_wp
2161                   ENDIF
2162
[4497]2163                ELSE
2164                   v_int_1_l(inot,ring,rseg) = 0.0_wp
2165                ENDIF
[1819]2166
[4497]2167
[1819]2168!
[4497]2169!--             Interpolation of the w-component:
2170                ii = ( rbx(ring,rseg) - 0.5_wp * dx ) * ddx
2171                jj = ( rby(ring,rseg) - 0.5_wp * dy ) * ddy
2172                kk =   rbz(ring,rseg)                 / dz(1)
[1819]2173!
[4497]2174!--             Interpolate only if all required information is available on the current PE:
2175                IF ( ( ii >= nxl )  .AND.  ( ii <= nxr ) )  THEN
2176                   IF ( ( jj >= nys )  .AND.  ( jj <= nyn ) )  THEN
[1819]2177
[4497]2178                      aa = ( ( ii + 1 + 0.5_wp ) * dx - rbx(ring,rseg) ) *                         &
2179                           ( ( jj + 1 + 0.5_wp ) * dy - rby(ring,rseg) )
2180                      bb = ( rbx(ring,rseg)     - ( ii + 0.5_wp ) * dx ) *                         &
2181                           ( ( jj + 1 + 0.5_wp ) * dy - rby(ring,rseg) )
2182                      cc = ( ( ii + 1 + 0.5_wp ) * dx - rbx(ring,rseg) ) *                         &
2183                           ( rby(ring,rseg)     - ( jj + 0.5_wp ) * dy )
2184                      dd = ( rbx(ring,rseg)     - ( ii + 0.5_wp ) * dx ) *                         &
2185                           ( rby(ring,rseg)     - ( jj + 0.5_wp ) * dy )
2186                      gg = dx * dy
[1819]2187
[4497]2188                      w_int_l = ( aa * w(kk,jj,ii) + bb * w(kk,jj,ii+1) + cc * w(kk,jj+1,ii)       &
2189                                + dd * w(kk,jj+1,ii+1) ) / gg
[1819]2190
[4497]2191                      w_int_u = ( aa * w(kk+1,jj,ii) + bb * w(kk+1,jj,ii+1) + cc * w(kk+1,jj+1,ii) &
2192                                + dd * w(kk+1,jj+1,ii+1) ) / gg
[1819]2193
[4497]2194                      w_int_1_l(inot,ring,rseg) = w_int_l + ( rbz(ring,rseg) - zw(kk) ) / dz(1) *  &
2195                                                ( w_int_u - w_int_l )
[1819]2196                   ELSE
2197                      w_int_1_l(inot,ring,rseg) = 0.0_wp
2198                   ENDIF
2199
[4497]2200                ELSE
2201                   w_int_1_l(inot,ring,rseg) = 0.0_wp
2202                ENDIF
2203
[1819]2204             ENDDO
2205
2206          ENDDO
[4497]2207          !$OMP END PARALLEL
[1819]2208
[4497]2209       ENDDO
2210
[1819]2211!
[4497]2212!--    Exchange between PEs (information required on each PE):
[1819]2213#if defined( __parallel )
[4497]2214       CALL MPI_ALLREDUCE( u_int_1_l, u_int, n_turbines * MAXVAL(nrings) *                         &
2215                           MAXVAL(nsegs), MPI_REAL, MPI_SUM, comm2d, ierr )
2216       CALL MPI_ALLREDUCE( v_int_1_l, v_int, n_turbines * MAXVAL(nrings) *                         &
2217                           MAXVAL(nsegs), MPI_REAL, MPI_SUM, comm2d, ierr )
2218       CALL MPI_ALLREDUCE( w_int_1_l, w_int, n_turbines * MAXVAL(nrings) *                         &
2219                           MAXVAL(nsegs), MPI_REAL, MPI_SUM, comm2d, ierr )
[1819]2220#else
[4497]2221       u_int = u_int_1_l
2222       v_int = v_int_1_l
2223       w_int = w_int_1_l
[1819]2224#endif
2225
2226
2227!
[4497]2228!--    Loop over number of turbines:
2229       DO  inot = 1, n_turbines
[1912]2230pit_loop: DO
[1819]2231
[4497]2232          IF ( pitch_sw )  THEN
2233             torque_total(inot) = 0.0_wp
2234             thrust_rotor(inot) = 0.0_wp
2235             pitch_angle(inot)    = pitch_angle(inot) + 0.25_wp
2236!              IF ( myid == 0 ) PRINT*, 'Pitch', inot, pitch_angle(inot)
2237          ELSE
2238             cos_yaw = COS( yaw_angle(inot) )
2239             sin_yaw = SIN( yaw_angle(inot) )
2240             IF ( pitch_control )  THEN
2241                pitch_angle(inot) = MAX( pitch_angle_old(inot) - pitch_rate * dt_3d , 0.0_wp )
[1819]2242             ENDIF
[4497]2243          ENDIF
[1819]2244
[1839]2245!
[4497]2246!--       Loop over rings of each turbine:
2247          !$OMP PARALLEL PRIVATE (ring, rseg, sin_rot, cos_rot, re, rea, ren, rote, rota, rotn, &
2248          !$OMP&                  vtheta, phi_rel, lct, rad_d, alpha_attack, vrel,              &
2249          !$OMP&                  chord, iialpha, iir, turb_cl, tl_factor, thrust_seg,          &
2250          !$OMP&                  torque_seg_y, turb_cd, torque_seg_z, thrust_ring,             &
2251          !$OMP&                  torque_ring_y, torque_ring_z)
2252          !$OMP DO
2253          DO  ring = 1, nrings(inot)
[1819]2254!
[4497]2255!--          Determine distance between each ring (center) and the hub:
2256             cur_r = ( ring - 0.5_wp ) * delta_r(inot)
[1839]2257!
[4497]2258!--          Loop over segments of each ring of each turbine:
2259             DO  rseg = 1, nsegs(ring,inot)
[1819]2260!
[4497]2261!--             Determine angle of ring segment towards zero degree angle of rotor system
2262!--             (at zero degree rotor direction vectors aligned with y-axis):
2263                phi_rotor = rseg * 2.0_wp * pi / nsegs(ring,inot)
2264                cos_rot   = COS( phi_rotor )
2265                sin_rot   = SIN( phi_rotor )
[1819]2266!
[4497]2267!--             Now the direction vectors can be determined with respect to the yaw and tilt angle:
2268                re(1) = cos_rot * sin_yaw
2269                re(2) = cos_rot * cos_yaw
2270                re(3) = sin_rot
[1819]2271
[4497]2272!               The current unit vector in azimuthal direction:
2273                rea(1) = - sin_rot * sin_yaw
2274                rea(2) = - sin_rot * cos_yaw
2275                rea(3) =   cos_rot
[1819]2276
2277!
[4497]2278!--             To respect the yawing angle for the calculations of velocities and forces the
2279!--             unit vectors perpendicular to the rotor area in direction of the positive yaw
2280!--             angle are defined:
2281                ren(1) =   cos_yaw
2282                ren(2) = - sin_yaw
2283                ren(3) = 0.0_wp
[1819]2284!
[4497]2285!--             Multiplication with the coordinate transformation matrix gives the final unit
2286!--             vector with consideration of the rotor tilt:
2287                rote = MATMUL( rot_coord_trans(inot,:,:), re )
2288                rota = MATMUL( rot_coord_trans(inot,:,:), rea )
2289                rotn = MATMUL( rot_coord_trans(inot,:,:), ren )
[1819]2290!
[4497]2291!--             Coordinates of the single segments (center points):
2292                rbx(ring,rseg) = hub_x(inot) + cur_r * rote(1)
[1819]2293
[4497]2294                rby(ring,rseg) = hub_y(inot) + cur_r * rote(2)
[1819]2295
[4497]2296                rbz(ring,rseg) = hub_z(inot) + cur_r * rote(3)
[1819]2297
2298!
[4497]2299!--             !----------------------------------------------------------------------------------!
2300!--             !-- Calculation of various angles and relative velocities                        --!
2301!--             !----------------------------------------------------------------------------------!
[1819]2302!
[4497]2303!--             In the following the 3D-velocity field is projected its components perpendicular
2304!--             and parallel to the rotor area.
2305!--             The calculation of forces will be done in the rotor-coordinates y' and z.
2306!--             The yaw angle will be reintroduced when the force is applied on the hydrodynamic
2307!--             equations.
[1864]2308!
[4497]2309!--             Projection of the xy-velocities relative to the rotor area:
[1864]2310!
[4497]2311!--             Velocity perpendicular to the rotor area:
2312                u_rot = u_int(inot,ring,rseg) * rotn(1) + v_int(inot,ring,rseg)*rotn(2) +          &
2313                        w_int(inot,ring,rseg)*rotn(3)
[1819]2314!
[4497]2315
2316!--             Projection of the 3D-velocity vector in the azimuthal direction:
2317                vtheta(rseg) = rota(1) * u_int(inot,ring,rseg) + rota(2) * v_int(inot,ring,rseg) + &
2318                               rota(3) * w_int(inot,ring,rseg)
[1819]2319!
2320
[4497]2321!--             Determination of the angle phi_rel between the rotor plane and the direction of the
2322!--             flow relative to the rotor:
2323                phi_rel(rseg) = ATAN2( u_rot , ( rotor_speed(inot) * cur_r - vtheta(rseg) ) )
[1819]2324
2325!
[4497]2326!--             Interpolation of the local pitch angle from tabulated values to the current
2327!--             radial position:
2328                lct = minloc( ABS( cur_r-lrd ) )
2329                rad_d = cur_r-lrd(lct)
[1819]2330
[4497]2331                IF ( cur_r == 0.0_wp )  THEN
2332                   alpha_attack(rseg) = 0.0_wp
[1819]2333
[4497]2334                ELSE IF ( cur_r >= lrd(size(ard)) )  THEN
2335                   alpha_attack(rseg) = ( ard(size(ard) ) + ard(size(ard) -1 ) ) / 2.0_wp
2336
2337                ELSE
2338                   alpha_attack(rseg) = ( ard( lct(1) ) * ( ( lrd( lct(1) + 1 ) - cur_r ) /        &
2339                                        ( lrd( lct(1) + 1 ) - lrd( lct(1) ) ) ) ) +                &
2340                                        ( ard( lct(1) + 1 ) * ( ( cur_r - lrd( lct(1) ) ) /        &
2341                                        ( lrd( lct(1) + 1 ) - lrd( lct(1) ) ) ) )
2342                ENDIF
2343
[1819]2344!
[4497]2345!--             In Fortran radian instead of degree is used as unit for all angles.
2346!--             Therefore, a transformation from angles given in degree to angles given in radian
2347!--             is necessary here:
2348                alpha_attack(rseg) = alpha_attack(rseg) * ( ( 2.0_wp * pi ) / 360.0_wp )
[1819]2349!
[4497]2350!--             Substraction of the local pitch angle to obtain the local angle of attack:
2351                alpha_attack(rseg) = phi_rel(rseg) - alpha_attack(rseg)
[1819]2352!
[4497]2353!--             Preliminary transformation back from angles given in radian to angles given in
2354!--             degree:
2355                alpha_attack(rseg) = alpha_attack(rseg) * ( 360.0_wp / ( 2.0_wp * pi ) )
[1819]2356!
[4497]2357!--             Correct with collective pitch angle:
2358                alpha_attack(rseg) = alpha_attack(rseg) - pitch_angle(inot)
[1819]2359
2360!
[4497]2361!--             Determination of the magnitude of the flow velocity relative to the rotor:
2362                vrel(rseg) = SQRT( u_rot**2 + ( rotor_speed(inot) * cur_r - vtheta(rseg) )**2 )
[1819]2363
2364!
[4497]2365!--             !----------------------------------------------------------------------------------!
2366!--             !-- Interpolation of chord as well as lift and drag                              --!
2367!--             !-- coefficients from tabulated values                                           --!
2368!--             !----------------------------------------------------------------------------------!
[1819]2369
2370!
[4497]2371!--             Interpolation of the chord_length from tabulated values to the current radial
2372!--             position:
2373                IF ( cur_r == 0.0_wp )  THEN
2374                   chord(rseg) = 0.0_wp
[1819]2375
[4497]2376                ELSE IF ( cur_r >= lrd( size(crd) ) )  THEN
2377                   chord(rseg) = ( crd( size(crd) ) + ard( size(crd) - 1 ) ) / 2.0_wp
[1819]2378
[4497]2379                ELSE
2380                   chord(rseg) = ( crd( lct(1) ) * ( ( lrd( lct(1) + 1 ) - cur_r ) /               &
2381                                 ( lrd( lct(1) + 1 ) - lrd( lct(1) ) ) ) ) + ( crd( lct(1) + 1 )   &
2382                                 * ( ( cur_r - lrd( lct(1) ) ) / ( lrd( lct(1) + 1 ) -             &
2383                                 lrd( lct(1) ) ) ) )
2384                ENDIF
2385
[1819]2386!
[4497]2387!--             Determine index of current angle of attack, needed for finding the appropriate
2388!--             interpolated values of the lift and drag coefficients
2389!--             (-180.0 degrees = 1, +180.0 degrees = 3601, so one index every 0.1 degrees):
2390                iialpha = CEILING( ( alpha_attack(rseg) + 180.0_wp )                               &
2391                        * ( 1.0_wp / accu_cl_cd_tab ) ) + 1.0_wp
[1819]2392!
[4497]2393!--             Determine index of current radial position, needed for finding the appropriate
2394!--             interpolated values of the lift and drag coefficients (one index every 0.1 m):
2395                iir = CEILING( cur_r * 10.0_wp )
[1819]2396!
[4497]2397!--             Read in interpolated values of the lift and drag coefficients for the current
2398!--             radial position and angle of attack:
2399                turb_cl(rseg) = turb_cl_tab(iialpha,iir)
2400                turb_cd(rseg) = turb_cd_tab(iialpha,iir)
[1819]2401
2402!
[4497]2403!--             Final transformation back from angles given in degree to angles given in radian:
2404                alpha_attack(rseg) = alpha_attack(rseg) * ( ( 2.0_wp * pi ) / 360.0_wp )
[1819]2405
[4497]2406                IF ( tip_loss_correction )  THEN
[4465]2407!
[4497]2408!--               Tip loss correction following Schito.
2409!--               Schito applies the tip loss correction only to the lift force.
2410!--               Therefore, the tip loss correction is only applied to the lift coefficient and
2411!--               not to the drag coefficient in our case.
2412                  IF ( phi_rel(rseg) == 0.0_wp )  THEN
2413                     tl_factor = 1.0_wp
[4465]2414
[4497]2415                  ELSE
2416                     tl_factor = ( 2.0 / pi ) *                                                    &
2417                          ACOS( EXP( -1.0 * ( 3.0 * ( rotor_radius(inot) - cur_r ) /               &
2418                          ( 2.0 * cur_r * ABS( SIN( phi_rel(rseg) ) ) ) ) ) )
2419                  ENDIF
[4465]2420
[4497]2421                  turb_cl(rseg)  = tl_factor * turb_cl(rseg)
2422
2423                ENDIF
[1819]2424!
[4497]2425!--             !----------------------------------------------------------------------------------!
2426!--             !-- Calculation of the forces                                                    --!
2427!--             !----------------------------------------------------------------------------------!
[1819]2428
2429!
[4497]2430!--             Calculate the pre_factor for the thrust and torque forces:
2431                pre_factor = 0.5_wp * ( vrel(rseg)**2 ) * 3.0_wp * chord(rseg) * delta_r(inot)     &
2432                           / nsegs(ring,inot)
[1819]2433
2434!
[4497]2435!--             Calculate the thrust force (x-component of the total force) for each ring segment:
2436                thrust_seg(rseg) = pre_factor * ( turb_cl(rseg) * COS (phi_rel(rseg) ) +           &
2437                                   turb_cd(rseg) * SIN( phi_rel(rseg) ) )
[1819]2438
2439!
[4497]2440!--             Determination of the second of the additional forces acting on the flow in the
2441!--             azimuthal direction: force vector as basis for torque (torque itself would be the
2442!--             vector product of the radius vector and the force vector):
2443                torque_seg = pre_factor * ( turb_cl(rseg) * SIN (phi_rel(rseg) ) -                 &
2444                             turb_cd(rseg) * COS( phi_rel(rseg) ) )
[1819]2445!
[4497]2446!--             Decomposition of the force vector into two parts: One acting along the
2447!--             y-direction and one acting along the z-direction of the rotor coordinate system:
2448                torque_seg_y(rseg) = -torque_seg * sin_rot
2449                torque_seg_z(rseg) =  torque_seg * cos_rot
[1819]2450
[1912]2451!
[4497]2452!--             Add the segment thrust to the thrust of the whole rotor:
2453                !$OMP CRITICAL
2454                thrust_rotor(inot) = thrust_rotor(inot) + thrust_seg(rseg)
[1912]2455
[4465]2456
[4497]2457                torque_total(inot) = torque_total(inot) + (torque_seg * cur_r)
2458                !$OMP END CRITICAL
[1819]2459
[4497]2460             ENDDO   !-- end of loop over ring segments
[1819]2461
2462!
[4497]2463!--          Restore the forces into arrays containing all the segments of each ring:
2464             thrust_ring(ring,:)   = thrust_seg(:)
2465             torque_ring_y(ring,:) = torque_seg_y(:)
2466             torque_ring_z(ring,:) = torque_seg_z(:)
[1819]2467
2468
[4497]2469          ENDDO   !-- end of loop over rings
2470          !$OMP END PARALLEL
[1819]2471
2472
[4497]2473          CALL cpu_log( log_point_s(62), 'wtm_controller', 'start' )
[1819]2474
[4465]2475
[4497]2476          IF ( speed_control )  THEN
[1912]2477!
[4497]2478!--          Calculation of the current generator speed for rotor speed control:
[4465]2479
[4497]2480!
2481!--          The acceleration of the rotor speed is calculated from the force balance of the
2482!--          accelerating torque and the torque of the rotating rotor and generator:
2483             om_rate = ( torque_total(inot) * air_density * gear_efficiency -                      &
2484                         gear_ratio * torque_gen_old(inot) ) / ( rotor_inertia +                   &
2485                         gear_ratio * gear_ratio * generator_inertia ) * dt_3d
[1819]2486
[1912]2487!
[4497]2488!--          The generator speed is given by the product of gear gear_ratio and rotor speed:
2489             generator_speed(inot) = gear_ratio * ( rotor_speed(inot) + om_rate )
[4465]2490
[4497]2491          ENDIF
[4465]2492
[4497]2493          IF ( pitch_control )  THEN
[1819]2494
[1912]2495!
[4497]2496!--          If the current generator speed is above rated, the pitch is not saturated and the
2497!--          change from the last time step is within the maximum pitch rate, then the pitch loop
2498!--          is repeated with a pitch gain:
2499             IF ( ( generator_speed(inot)  > generator_speed_rated )  .AND.                        &
2500                  ( pitch_angle(inot) < 25.0_wp )  .AND.                                           &
2501                  ( pitch_angle(inot) < pitch_angle_old(inot) + pitch_rate * dt_3d ) )  THEN
2502                pitch_sw = .TRUE.
[1912]2503!
[4497]2504!--             Go back to beginning of pit_loop:
2505                CYCLE pit_loop
2506             ENDIF
[4465]2507
[1912]2508!
[4497]2509!--          The current pitch is saved for the next time step:
2510             pitch_angle_old(inot) = pitch_angle(inot)
2511             pitch_sw = .FALSE.
2512          ENDIF
2513          EXIT pit_loop
2514       ENDDO pit_loop ! Recursive pitch control loop
[1819]2515
[1864]2516
[1819]2517!
[4497]2518!--       Call the rotor speed controller:
2519          IF ( speed_control )  THEN
[1819]2520!
[4497]2521!--          Find processor at i_hub, j_hub:
2522             IF ( ( nxl <= i_hub(inot) )  .AND.  ( nxr >= i_hub(inot) ) )  THEN
2523                IF ( ( nys <= j_hub(inot) )  .AND.  ( nyn >= j_hub(inot) ) )  THEN
2524                   CALL wtm_speed_control( inot )
[1912]2525                ENDIF
[1819]2526             ENDIF
2527
[4497]2528          ENDIF
[1819]2529
2530
[4497]2531          CALL cpu_log( log_point_s(62), 'wtm_controller', 'stop' )
[1819]2532
[4497]2533          CALL cpu_log( log_point_s(63), 'wtm_smearing', 'start' )
[1819]2534
[4497]2535
2536!--       !----------------------------------------------------------------------------------------!
2537!--       !--                  Regularization kernel                                             --!
2538!--       !-- Smearing of the forces and interpolation to cartesian grid                         --!
2539!--       !----------------------------------------------------------------------------------------!
[1819]2540!
[4497]2541!--       The aerodynamic blade forces need to be distributed smoothly on several mesh points in
2542!--       order to avoid singular behaviour.
[1819]2543!
[4497]2544!--       Summation over sum of weighted forces. The weighting factor (calculated in user_init)
2545!--       includes information on the distance between the center of the grid cell and the rotor
2546!--       segment under consideration.
[1819]2547!
[4497]2548!--       To save computing time, apply smearing only for the relevant part of the model domain:
[1819]2549!
2550!--
[4497]2551!--       Calculation of the boundaries:
2552          i_smear(inot) = CEILING( ( rotor_radius(inot) * ABS( roty(inot,1) ) + eps_min ) / dx )
2553          j_smear(inot) = CEILING( ( rotor_radius(inot) * ABS( roty(inot,2) ) + eps_min ) / dy )
[1819]2554
[4497]2555          !$OMP PARALLEL PRIVATE (i, j, k, ring, rseg, flag, dist_u_3d, dist_v_3d, dist_w_3d)
2556          !$OMP DO
2557          DO  i = MAX( nxl, i_hub(inot) - i_smear(inot) ), MIN( nxr, i_hub(inot) + i_smear(inot) )
2558             DO  j = MAX( nys, j_hub(inot) - j_smear(inot) ), MIN( nyn, j_hub(inot) + j_smear(inot) )
2559!                 DO  k = MAX( nzb_u_inner(j,i)+1, k_hub(inot) - k_smear(inot) ),                   &
2560!                              k_hub(inot) + k_smear(inot)
2561                DO  k = nzb + 1, k_hub(inot) + k_smear(inot)
2562                   DO  ring = 1, nrings(inot)
2563                      DO  rseg = 1, nsegs(ring,inot)
[1819]2564!
[4497]2565!--                      Predetermine flag to mask topography:
2566                         flag = MERGE( 1.0_wp, 0.0_wp, BTEST( wall_flags_total_0(k,j,i), 1 ) )
[4465]2567
[2232]2568!
[4497]2569!--                      Determine the square of the distance between the current grid point and
2570!--                      each rotor area segment:
2571                         dist_u_3d = ( i * dx               - rbx(ring,rseg) )**2 +                &
2572                                     ( j * dy + 0.5_wp * dy - rby(ring,rseg) )**2 +                &
2573                                     ( k * dz(1) - 0.5_wp * dz(1) - rbz(ring,rseg) )**2
[1819]2574
[4497]2575                         dist_v_3d = ( i * dx + 0.5_wp * dx - rbx(ring,rseg) )**2 +                &
2576                                     ( j * dy               - rby(ring,rseg) )**2 +                &
2577                                     ( k * dz(1) - 0.5_wp * dz(1) - rbz(ring,rseg) )**2
2578
2579                         dist_w_3d = ( i * dx + 0.5_wp * dx - rbx(ring,rseg) )**2 +                &
2580                                     ( j * dy + 0.5_wp * dy - rby(ring,rseg) )**2 +                &
2581                                     ( k * dz(1)               - rbz(ring,rseg) )**2
2582
[1819]2583!
[4497]2584!--                      3D-smearing of the forces with a polynomial function (much faster than
2585!--                      the old Gaussian function), using some parameters that have been
2586!--                      calculated in user_init. The function is only similar to Gaussian
2587!--                      function for squared distances <= eps_min2:
2588                         IF ( dist_u_3d <= eps_min2 )  THEN
2589                            thrust(k,j,i) = thrust(k,j,i) + thrust_ring(ring,rseg) *               &
2590                                            ( ( pol_a * dist_u_3d - pol_b ) *                      &
2591                                             dist_u_3d + 1.0_wp ) * eps_factor * flag
2592                         ENDIF
[1819]2593
[4497]2594                         IF ( dist_v_3d <= eps_min2 )  THEN
2595                            torque_y(k,j,i) = torque_y(k,j,i) + torque_ring_y(ring,rseg) *         &
2596                                              ( ( pol_a * dist_v_3d - pol_b ) *                    &
2597                                               dist_v_3d + 1.0_wp ) * eps_factor * flag
2598                         ENDIF
[4465]2599
[4497]2600                         IF ( dist_w_3d <= eps_min2 )  THEN
2601                            torque_z(k,j,i) = torque_z(k,j,i) + torque_ring_z(ring,rseg) *         &
2602                                              ( ( pol_a * dist_w_3d - pol_b ) *                    &
2603                                               dist_w_3d + 1.0_wp ) * eps_factor * flag
2604                         ENDIF
2605
2606                      ENDDO  ! End of loop over rseg
2607                   ENDDO     ! End of loop over ring
2608
[1819]2609!
[4497]2610!--                Rotation of force components:
2611                   rot_tend_x(k,j,i) = rot_tend_x(k,j,i) + ( thrust(k,j,i) * rotx(inot,1) +        &
2612                                       torque_y(k,j,i) * roty(inot,1) + torque_z(k,j,i) *          &
2613                                       rotz(inot,1) ) * flag
[4465]2614
[4497]2615                   rot_tend_y(k,j,i) = rot_tend_y(k,j,i) + ( thrust(k,j,i) * rotx(inot,2) +        &
2616                                       torque_y(k,j,i) * roty(inot,2) + torque_z(k,j,i) *          &
2617                                       rotz(inot,2) ) * flag
[4465]2618
[4497]2619                   rot_tend_z(k,j,i) = rot_tend_z(k,j,i) + ( thrust(k,j,i) * rotx(inot,3) +        &
2620                                       torque_y(k,j,i) * roty(inot,3) +  torque_z(k,j,i) *         &
2621                                       rotz(inot,3) ) * flag
[1819]2622
[4497]2623                ENDDO  ! End of loop over k
2624             ENDDO     ! End of loop over j
2625          ENDDO        ! End of loop over i
2626          !$OMP END PARALLEL
[1819]2627
[4497]2628          CALL cpu_log( log_point_s(63), 'wtm_smearing', 'stop' )
[4465]2629
[4497]2630       ENDDO                  !-- end of loop over turbines
[1819]2631
[4465]2632
[4497]2633       IF ( yaw_control )  THEN
[1819]2634!
[4497]2635!--       Allocate arrays for yaw control at first call. Can't be allocated before dt_3d is set.
2636          IF ( start_up )  THEN
2637             wdlon= MAX( 1 , NINT( 30.0_wp / dt_3d ) )  ! 30s running mean array
2638             ALLOCATE( wd30(1:n_turbines,1:WDLON) )
2639             wd30 = 999.0_wp                             ! Set to dummy value
2640             ALLOCATE( wd30_l(1:WDLON) )
[4465]2641
[4497]2642             wdsho = MAX( 1 , NINT( 2.0_wp / dt_3d ) )   ! 2s running mean array
2643             ALLOCATE( wd2(1:n_turbines,1:wdsho) )
2644             wd2 = 999.0_wp                              ! Set to dummy value
2645             ALLOCATE( wd2_l(1:wdsho) )
2646             start_up = .FALSE.
2647          ENDIF
[1819]2648
2649!
[4497]2650!--       Calculate the inflow wind speed:
[1819]2651!--
[4497]2652!--       Loop over number of turbines:
2653          DO  inot = 1, n_turbines
[1819]2654!
[4497]2655!--          Find processor at i_hub, j_hub:
2656             IF ( ( nxl <= i_hub(inot) )  .AND.  ( nxr >= i_hub(inot) ) )  THEN
2657                IF ( ( nys <= j_hub(inot) )  .AND.  ( nyn >= j_hub(inot) ) )  THEN
2658                   u_inflow_l(inot) = u(k_hub(inot),j_hub(inot),i_hub(inot))
2659                   wdir_l(inot)     = -1.0_wp * ATAN2( 0.5_wp *                                    &
2660                                    ( v(k_hub(inot), j_hub(inot), i_hub(inot) + 1) +               &
2661                                      v(k_hub(inot), j_hub(inot), i_hub(inot)) ) , 0.5_wp *        &
2662                                    ( u(k_hub(inot), j_hub(inot) + 1, i_hub(inot)) +               &
2663                                      u(k_hub(inot), j_hub(inot), i_hub(inot)) ) )
[1864]2664
[4497]2665                   CALL wtm_yawcontrol( inot )
[1864]2666
[4497]2667                   yaw_angle_l(inot) = yaw_angle(inot)
[1864]2668
[1819]2669                ENDIF
[4497]2670             ENDIF
[4465]2671
[4497]2672          ENDDO  ! end of loop over turbines
[1864]2673
2674!
[4497]2675!--       Transfer of information to the other cpus:
2676#if defined( __parallel )
2677          CALL MPI_ALLREDUCE( u_inflow_l, u_inflow, n_turbines, MPI_REAL,                          &
2678                              MPI_SUM, comm2d, ierr )
2679          CALL MPI_ALLREDUCE( wdir_l, wdir, n_turbines, MPI_REAL, MPI_SUM,                         &
2680                              comm2d, ierr )
2681          CALL MPI_ALLREDUCE( yaw_angle_l, yaw_angle, n_turbines, MPI_REAL,                        &
2682                              MPI_SUM, comm2d, ierr )
[1929]2683#else
[4497]2684          u_inflow   = u_inflow_l
2685          wdir       = wdir_l
2686          yaw_angle  = yaw_angle_l
[4465]2687
[1929]2688#endif
[4497]2689          DO  inot = 1, n_turbines
[4465]2690!
[4497]2691!--          Update rotor orientation:
2692             CALL wtm_rotate_rotor( inot )
[1819]2693
[4497]2694          ENDDO ! End of loop over turbines
[4465]2695
[4497]2696       ENDIF  ! end of yaw control
[4465]2697
[4497]2698       IF ( speed_control )  THEN
[1864]2699!
[4497]2700!--       Transfer of information to the other cpus:
2701!           CALL MPI_ALLREDUCE( generator_speed, generator_speed_old, n_turbines,                   &
2702!                               MPI_REAL,MPI_SUM, comm2d, ierr )
2703#if defined( __parallel )
2704          CALL MPI_ALLREDUCE( torque_gen, torque_gen_old, n_turbines,                              &
2705                              MPI_REAL, MPI_SUM, comm2d, ierr )
2706          CALL MPI_ALLREDUCE( rotor_speed_l, rotor_speed, n_turbines,                              &
2707                              MPI_REAL, MPI_SUM, comm2d, ierr )
2708          CALL MPI_ALLREDUCE( generator_speed_f, generator_speed_f_old, n_turbines,                &
2709                              MPI_REAL, MPI_SUM, comm2d, ierr )
[1929]2710#else
[4497]2711          torque_gen_old        = torque_gen
2712          rotor_speed           = rotor_speed_l
2713          generator_speed_f_old = generator_speed_f
[1929]2714#endif
[4465]2715
2716       ENDIF
[1819]2717
[4497]2718    ENDIF
[1819]2719
[4497]2720    CALL cpu_log( log_point_s(61), 'wtm_forces', 'stop' )
[1819]2721
2722
[4497]2723 END SUBROUTINE wtm_forces
[4465]2724
[4497]2725
2726!--------------------------------------------------------------------------------------------------!
[1839]2727! Description:
2728! ------------
2729!> Yaw controller for the wind turbine model
[4497]2730!--------------------------------------------------------------------------------------------------!
2731 SUBROUTINE wtm_yawcontrol( inot )
[4465]2732
[4497]2733    USE kinds
[4465]2734
[4497]2735    IMPLICIT NONE
[4465]2736
[4497]2737    INTEGER(iwp)             :: inot
2738    INTEGER(iwp)             :: i_wd_30
[1819]2739
[4497]2740    REAL(wp)                 :: missal
[1819]2741
[4497]2742    i_wd_30 = 0_iwp
2743
[1864]2744!
[4497]2745!-- The yaw controller computes a 30s running mean of the wind direction. If the difference
2746!-- between turbine alignment and wind direction exceeds 5 degrees, the turbine is yawed. The
2747!-- mechanism stops as soon as the 2s-running mean of the missalignment is smaller than 0.5
2748!-- degrees. Attention: If the timestep during the simulation changes significantly the lengths
2749!-- of the running means change and it does not correspond to 30s/2s anymore.
2750!-- ! Needs to be modified for these situations !
2751!-- For wind from the east, the averaging of the wind direction could cause problems and the yaw
2752!-- controller is probably flawed. -> Routine for averaging needs to be improved!
[1843]2753!
[4497]2754!-- Check if turbine is not yawing:
2755    IF ( .NOT. doyaw(inot) )  THEN
[1843]2756!
[4497]2757!--    Write current wind direction into array:
2758       wd30_l    = wd30(inot,:)
2759       wd30_l    = CSHIFT( wd30_l, SHIFT = -1 )
2760       wd30_l(1) = wdir(inot)
2761!
2762!--    Check if array is full ( no more dummies ):
2763       IF ( .NOT. ANY( wd30_l == 999.) )  THEN
[1819]2764
[4497]2765          missal = SUM( wd30_l ) / SIZE( wd30_l ) - yaw_angle(inot)
[1819]2766!
[4497]2767!--       Check if turbine is missaligned by more than yaw_misalignment_max:
2768          IF ( ABS( missal ) > yaw_misalignment_max )  THEN
[1843]2769!
[4497]2770!--          Check in which direction to yaw:
2771             yawdir(inot) = SIGN( 1.0_wp, missal )
[1819]2772!
[4497]2773!--          Start yawing of turbine:
2774             yaw_angle(inot) = yaw_angle(inot) + yawdir(inot) * yaw_speed * dt_3d
2775             doyaw(inot)     = .TRUE.
2776             wd30_l          = 999.  ! fill with dummies again
[1819]2777          ENDIF
[4497]2778       ENDIF
[4465]2779
[4497]2780       wd30(inot,:) = wd30_l
[1819]2781
[4465]2782!
[4497]2783!-- If turbine is already yawing:
2784!-- Initialize 2 s running mean and yaw until the missalignment is smaller than
2785!-- yaw_misalignment_min
[1819]2786
[4497]2787    ELSE
[1819]2788!
[4497]2789!--    Initialize 2 s running mean:
2790
2791       wd2_l = wd2(inot,:)
2792       wd2_l = CSHIFT( wd2_l, SHIFT = -1 )
2793       wd2_l(1) = wdir(inot)
[4465]2794!
[4497]2795!--    Check if array is full ( no more dummies ):
2796       IF ( .NOT. ANY( wd2_l == 999.0_wp ) ) THEN
[1864]2797!
[4497]2798!--       Calculate missalignment of turbine:
2799          missal = SUM( wd2_l - yaw_angle(inot) ) / SIZE( wd2_l )
[1864]2800!
[4497]2801!--       Check if missalignment is still larger than 0.5 degree and if the yaw direction is
2802!--       still right:
2803          IF ( ( ABS( missal ) > yaw_misalignment_min )  .AND.                                     &
2804               ( yawdir(inot) == SIGN( 1.0_wp, missal ) ) )  THEN
[1864]2805!
[4497]2806!--          Continue yawing:
2807             yaw_angle(inot) = yaw_angle(inot) + yawdir(inot) * yaw_speed * dt_3d
2808
[1819]2809          ELSE
[1864]2810!
[4497]2811!--          Stop yawing:
2812             doyaw(inot) = .FALSE.
2813             wd2_l       = 999.0_wp  ! fill with dummies again
[1819]2814          ENDIF
[4497]2815       ELSE
2816!
2817!--       Continue yawing:
2818          yaw_angle(inot) = yaw_angle(inot) + yawdir(inot) * yaw_speed * dt_3d
2819       ENDIF
[4465]2820
[4497]2821       wd2(inot,:) = wd2_l
[4465]2822
[4497]2823    ENDIF
[4465]2824
[4497]2825 END SUBROUTINE wtm_yawcontrol
[1819]2826
[1864]2827
[4497]2828!--------------------------------------------------------------------------------------------------!
[1819]2829! Description:
2830! ------------
[1864]2831!> Initialization of the speed control
[4497]2832!--------------------------------------------------------------------------------------------------!
2833 SUBROUTINE wtm_init_speed_control
[1864]2834
2835
[4497]2836    IMPLICIT NONE
[1864]2837
2838!
[4497]2839!-- If speed control is set, remaining variables and control_parameters for the control algorithm
2840!-- are calculated:
[1864]2841!
[4497]2842!-- Calculate slope constant for region 15:
2843    slope15         = ( region_2_slope * region_2_min * region_2_min ) /                           &
2844                      ( region_2_min - region_15_min )
[1864]2845!
[4497]2846!-- Calculate upper limit of slipage region:
2847    vs_sysp         = generator_speed_rated / 1.1_wp
[1864]2848!
[4497]2849!-- Calculate slope of slipage region:
2850    region_25_slope = ( generator_power_rated / generator_speed_rated ) /                          &
2851                    ( generator_speed_rated - vs_sysp )
[1864]2852!
[4497]2853!-- Calculate lower limit of slipage region:
2854    region_25_min   = ( region_25_slope - SQRT( region_25_slope *                                  &
2855                      ( region_25_slope - 4.0_wp * region_2_slope * vs_sysp ) ) ) /                &
2856                      ( 2.0_wp * region_2_slope )
[1864]2857!
[4497]2858!-- Frequency for the simple low pass filter:
2859    fcorner      = 0.25_wp
2860!
2861!-- At the first timestep the torque is set to its maximum to prevent an overspeeding of the rotor:
2862    IF ( TRIM( initializing_actions ) /= 'read_restart_data' ) THEN
2863       torque_gen_old(:) = generator_torque_max
2864    ENDIF
[1864]2865
[4497]2866 END SUBROUTINE wtm_init_speed_control
[1864]2867
[4497]2868
2869!--------------------------------------------------------------------------------------------------!
[1864]2870! Description:
2871! ------------
2872!> Simple controller for the regulation of the rotor speed
[4497]2873!--------------------------------------------------------------------------------------------------!
2874 SUBROUTINE wtm_speed_control( inot )
[1864]2875
2876
[4497]2877    IMPLICIT NONE
[1864]2878
[4497]2879    INTEGER(iwp)::  inot
[1864]2880
[4465]2881
[1864]2882!
[4497]2883!-- The controller is based on the fortran script from Jonkman et al. 2009 "Definition of a 5 MW
2884!-- Reference Wind Turbine for offshore system developement"
[1864]2885
2886!
[4497]2887!-- The generator speed is filtered by a low pass filter  for the control of the generator torque:
2888    lp_coeff = EXP( -2.0_wp * 3.14_wp * dt_3d * fcorner)
2889    generator_speed_f(inot) = ( 1.0_wp - lp_coeff ) * generator_speed(inot) + lp_coeff *           &
2890                               generator_speed_f_old(inot)
[1864]2891
[4497]2892    IF ( generator_speed_f(inot) <= region_15_min )  THEN
[4465]2893!
[4497]2894!--    Region 1: Generator torque is set to zero to accelerate the rotor:
2895       torque_gen(inot) = 0
[4465]2896
[4497]2897    ELSEIF ( generator_speed_f(inot) <= region_2_min )  THEN
[4465]2898!
[4497]2899!--    Region 1.5: Generator torque is increasing linearly with rotor speed:
2900       torque_gen(inot) = slope15 * ( generator_speed_f(inot) - region_15_min )
[4465]2901
[4497]2902    ELSEIF ( generator_speed_f(inot) <= region_25_min )  THEN
[1864]2903!
[4497]2904!--    Region 2: Generator torque is increased by the square of the generator speed to keep the
2905!--              TSR optimal:
2906       torque_gen(inot) = region_2_slope * generator_speed_f(inot) * generator_speed_f(inot)
[4465]2907
[4497]2908    ELSEIF ( generator_speed_f(inot) < generator_speed_rated )  THEN
[4465]2909!
[4497]2910!--    Region 2.5: Slipage region between 2 and 3:
2911       torque_gen(inot) = region_25_slope * ( generator_speed_f(inot) - vs_sysp )
[4465]2912
[4497]2913    ELSE
[4465]2914!
[4497]2915!--    Region 3: Generator torque is antiproportional to the rotor speed to keep the power
2916!--              constant:
2917       torque_gen(inot) = generator_power_rated / generator_speed_f(inot)
[4465]2918
[4497]2919    ENDIF
[4465]2920!
[4497]2921!-- Calculate torque rate and confine with a max:
2922    trq_rate = ( torque_gen(inot) - torque_gen_old(inot) ) / dt_3d
2923    trq_rate = MIN( MAX( trq_rate, -1.0_wp * generator_torque_rate_max ), generator_torque_rate_max )
[4465]2924!
[4497]2925!-- Calculate new gen torque and confine with max torque:
2926    torque_gen(inot) = torque_gen_old(inot) + trq_rate * dt_3d
2927    torque_gen(inot) = MIN( torque_gen(inot), generator_torque_max )
[1864]2928!
[4497]2929!-- Overwrite values for next timestep:
2930    rotor_speed_l(inot) = generator_speed(inot) / gear_ratio
[1864]2931
[4465]2932
[4497]2933 END SUBROUTINE wtm_speed_control
[1864]2934
2935
[4497]2936!--------------------------------------------------------------------------------------------------!
[1864]2937! Description:
2938! ------------
[4497]2939!> Application of the additional forces generated by the wind turbine on the flow components
2940!> (tendency terms)
[1839]2941!> Call for all grid points
[4497]2942!--------------------------------------------------------------------------------------------------!
2943 SUBROUTINE wtm_actions( location )
[1819]2944
2945
[4497]2946    CHARACTER(LEN=*) ::  location  !<
[3875]2947
[4497]2948    INTEGER(iwp) ::  i  !< running index
2949    INTEGER(iwp) ::  j  !< running index
2950    INTEGER(iwp) ::  k  !< running index
[1819]2951
2952
[4497]2953    SELECT CASE ( location )
[1819]2954
[4497]2955    CASE ( 'before_timestep' )
[3875]2956
[4497]2957       CALL wtm_forces
[3875]2958
[4497]2959    CASE ( 'u-tendency' )
[1819]2960!
[4497]2961
2962!--    Apply the x-component of the force to the u-component of the flow:
2963       IF ( time_since_reference_point >= time_turbine_on )  THEN
2964          DO  i = nxlg, nxrg
2965             DO  j = nysg, nyng
2966                DO  k = nzb + 1, MAXVAL( k_hub ) + MAXVAL( k_smear )
[1819]2967!
[4497]2968!--                Calculate the thrust generated by the nacelle and the tower:
2969                   tend_nac_x  = 0.5_wp * nac_cd_surf(k,j,i) * SIGN( u(k,j,i)**2 , u(k,j,i) )
2970                   tend_tow_x  = 0.5_wp * tow_cd_surf(k,j,i) * SIGN( u(k,j,i)**2 , u(k,j,i) )
2971                   tend(k,j,i) = tend(k,j,i) + ( - rot_tend_x(k,j,i) - tend_nac_x - tend_tow_x ) * &
2972                                 MERGE( 1.0_wp, 0.0_wp, BTEST( wall_flags_total_0(k,j,i), 1 ) )
[1819]2973                ENDDO
2974             ENDDO
[4497]2975          ENDDO
2976       ENDIF
[1819]2977
[4497]2978    CASE ( 'v-tendency' )
[1819]2979!
[4497]2980!--    Apply the y-component of the force to the v-component of the flow:
2981       IF ( time_since_reference_point >= time_turbine_on )  THEN
2982          DO  i = nxlg, nxrg
2983             DO  j = nysg, nyng
2984                DO  k = nzb+1, MAXVAL(k_hub) + MAXVAL(k_smear)
2985                   tend_nac_y  = 0.5_wp * nac_cd_surf(k,j,i) * SIGN( v(k,j,i)**2 , v(k,j,i) )
2986                   tend_tow_y  = 0.5_wp * tow_cd_surf(k,j,i) * SIGN( v(k,j,i)**2 , v(k,j,i) )
2987                   tend(k,j,i) = tend(k,j,i) + ( - rot_tend_y(k,j,i) - tend_nac_y - tend_tow_y ) * &
2988                                 MERGE( 1.0_wp, 0.0_wp, BTEST( wall_flags_total_0(k,j,i), 2 ) )
[1819]2989                ENDDO
2990             ENDDO
[4497]2991          ENDDO
2992       ENDIF
[1819]2993
[4497]2994    CASE ( 'w-tendency' )
[1819]2995!
[4497]2996!--    Apply the z-component of the force to the w-component of the flow:
2997       IF ( time_since_reference_point >= time_turbine_on )  THEN
2998          DO  i = nxlg, nxrg
2999             DO  j = nysg, nyng
3000                DO  k = nzb+1,  MAXVAL(k_hub) + MAXVAL(k_smear)
3001                   tend(k,j,i) = tend(k,j,i) - rot_tend_z(k,j,i) *                                 &
3002                                 MERGE( 1.0_wp, 0.0_wp, BTEST( wall_flags_total_0(k,j,i), 3 ) )
[1819]3003                ENDDO
3004             ENDDO
[4497]3005          ENDDO
3006       ENDIF
[1819]3007
3008
[4497]3009    CASE DEFAULT
3010       CONTINUE
[1819]3011
[4497]3012    END SELECT
[1819]3013
3014
[4497]3015 END SUBROUTINE wtm_actions
[1819]3016
3017
[4497]3018!--------------------------------------------------------------------------------------------------!
[1819]3019! Description:
3020! ------------
[4497]3021!> Application of the additional forces generated by the wind turbine on the flow components
3022!> (tendency terms)
[1839]3023!> Call for grid point i,j
[4497]3024!--------------------------------------------------------------------------------------------------!
3025 SUBROUTINE wtm_actions_ij( i, j, location )
[1819]3026
3027
[4497]3028    CHARACTER (LEN=*) ::  location  !<
[1819]3029
[4497]3030    INTEGER(iwp) ::  i  !< running index
3031    INTEGER(iwp) ::  j  !< running index
3032    INTEGER(iwp) ::  k  !< running index
[1819]3033
[4497]3034    SELECT CASE ( location )
[3875]3035
[4497]3036    CASE ( 'before_timestep' )
[3875]3037
[4497]3038       CALL wtm_forces
3039
3040    CASE ( 'u-tendency' )
[1819]3041!
[4497]3042!--    Apply the x-component of the force to the u-component of the flow:
3043       IF ( time_since_reference_point >= time_turbine_on )  THEN
3044          DO  k = nzb+1,  MAXVAL(k_hub) + MAXVAL(k_smear)
[1819]3045!
[4497]3046!--          Calculate the thrust generated by the nacelle and the tower:
3047             tend_nac_x  = 0.5_wp * nac_cd_surf(k,j,i) * SIGN( u(k,j,i)**2 , u(k,j,i) )
3048             tend_tow_x  = 0.5_wp * tow_cd_surf(k,j,i) * SIGN( u(k,j,i)**2 , u(k,j,i) )
3049             tend(k,j,i) = tend(k,j,i) + ( - rot_tend_x(k,j,i) - tend_nac_x - tend_tow_x ) *       &
3050                           MERGE( 1.0_wp, 0.0_wp, BTEST( wall_flags_total_0(k,j,i), 1 ) )
3051          ENDDO
3052       ENDIF
[1819]3053
[4497]3054    CASE ( 'v-tendency' )
[1819]3055!
[4497]3056!--    Apply the y-component of the force to the v-component of the flow:
3057       IF ( time_since_reference_point >= time_turbine_on )  THEN
3058          DO  k = nzb+1,  MAXVAL(k_hub) + MAXVAL(k_smear)
3059             tend_nac_y  = 0.5_wp * nac_cd_surf(k,j,i) * SIGN( v(k,j,i)**2 , v(k,j,i) )
3060             tend_tow_y  = 0.5_wp * tow_cd_surf(k,j,i) * SIGN( v(k,j,i)**2 , v(k,j,i) )
3061             tend(k,j,i) = tend(k,j,i) + ( - rot_tend_y(k,j,i) - tend_nac_y - tend_tow_y )  *      &
3062                           MERGE( 1.0_wp, 0.0_wp, BTEST( wall_flags_total_0(k,j,i), 2 ) )
3063             ENDDO
3064       ENDIF
[1819]3065
[4497]3066    CASE ( 'w-tendency' )
[1819]3067!
[4497]3068!--    Apply the z-component of the force to the w-component of the flow:
3069       IF ( time_since_reference_point >= time_turbine_on )  THEN
3070          DO  k = nzb+1,  MAXVAL(k_hub) + MAXVAL(k_smear)
3071             tend(k,j,i) = tend(k,j,i) - rot_tend_z(k,j,i) *                                       &
3072                           MERGE( 1.0_wp, 0.0_wp, BTEST( wall_flags_total_0(k,j,i), 3 ) )
3073          ENDDO
3074       ENDIF
[1819]3075
3076
[4497]3077    CASE DEFAULT
3078       CONTINUE
[1819]3079
[4497]3080    END SELECT
[1819]3081
3082
[4497]3083 END SUBROUTINE wtm_actions_ij
[1819]3084
[4411]3085
[4497]3086 SUBROUTINE wtm_data_output
[4411]3087
[4465]3088
[4497]3089    INTEGER(iwp) ::  return_value  !< returned status value of called function
3090    INTEGER(iwp) ::  t_ind = 0     !< time index
[4465]3091
[4497]3092    IF ( myid == 0 )  THEN
[4465]3093
[4497]3094!
3095!--    At the first call of this routine write the spatial coordinates:
3096       IF ( .NOT. initial_write_coordinates )  THEN
[4447]3097          ALLOCATE ( output_values_1d_target(1:n_turbines) )
[4497]3098          output_values_1d_target = hub_x(1:n_turbines)
[4423]3099          output_values_1d_pointer => output_values_1d_target
[4497]3100          return_value = dom_write_var( nc_filename,                                               &
3101                                     'x',                                                          &
3102                                     values_realwp_1d = output_values_1d_pointer,                  &
3103                                     bounds_start     = (/1/),                                     &
3104                                     bounds_end       = (/n_turbines/) )
[4411]3105
[4497]3106          output_values_1d_target = hub_y(1:n_turbines)
3107          output_values_1d_pointer => output_values_1d_target
3108          return_value = dom_write_var( nc_filename,                                               &
3109                                     'y',                                                          &
3110                                     values_realwp_1d = output_values_1d_pointer,                  &
3111                                     bounds_start     = (/1/),                                     &
3112                                     bounds_end       = (/n_turbines/) )
[4411]3113
[4497]3114          output_values_1d_target = hub_z(1:n_turbines)
3115          output_values_1d_pointer => output_values_1d_target
3116          return_value = dom_write_var( nc_filename,                                               &
3117                                     'z',                                                          &
3118                                     values_realwp_1d = output_values_1d_pointer,                  &
3119                                     bounds_start     = (/1/),                                     &
3120                                     bounds_end       = (/n_turbines/) )
[4411]3121
[4497]3122          output_values_1d_target = rotor_radius(1:n_turbines) * 2.0_wp
3123          output_values_1d_pointer => output_values_1d_target
3124          return_value = dom_write_var( nc_filename,                                               &
3125                                     'rotor_diameter',                                             &
3126                                     values_realwp_1d = output_values_1d_pointer,                  &
3127                                     bounds_start     = (/1/),                                     &
3128                                     bounds_end       = (/n_turbines/) )
[4411]3129
[4497]3130          output_values_1d_target = tower_diameter(1:n_turbines)
3131          output_values_1d_pointer => output_values_1d_target
3132          return_value = dom_write_var( nc_filename,                                               &
3133                                     'tower_diameter',                                             &
3134                                     values_realwp_1d = output_values_1d_pointer,                  &
3135                                     bounds_start     = (/1/),                                     &
3136                                     bounds_end       = (/n_turbines/) )
[4411]3137
[4497]3138          initial_write_coordinates = .TRUE.
3139          DEALLOCATE ( output_values_1d_target )
3140       ENDIF
[4411]3141
[4497]3142       t_ind = t_ind + 1
[4411]3143
[4497]3144       ALLOCATE ( output_values_1d_target(1:n_turbines) )
3145       output_values_1d_target = rotor_speed(:)
3146       output_values_1d_pointer => output_values_1d_target
[4411]3147
[4497]3148       return_value = dom_write_var( nc_filename,                                                  &
3149                                     'rotor_speed',                                                &
3150                                     values_realwp_1d = output_values_1d_pointer,                  &
3151                                     bounds_start     = (/1, t_ind/),                              &
3152                                     bounds_end       = (/n_turbines, t_ind /) )
[4411]3153
[4497]3154       output_values_1d_target = generator_speed(:)
3155       output_values_1d_pointer => output_values_1d_target
3156       return_value = dom_write_var( nc_filename,                                                  &
3157                                     'generator_speed',                                            &
3158                                     values_realwp_1d = output_values_1d_pointer,                  &
3159                                     bounds_start     = (/1, t_ind/),                              &
3160                                     bounds_end       = (/n_turbines, t_ind /) )
[4411]3161
[4497]3162       output_values_1d_target = torque_gen_old(:)
3163       output_values_1d_pointer => output_values_1d_target
[4411]3164
[4497]3165       return_value = dom_write_var( nc_filename,                                                  &
3166                                     'generator_torque',                                           &
3167                                     values_realwp_1d = output_values_1d_pointer,                  &
3168                                     bounds_start     = (/1, t_ind/),                              &
3169                                     bounds_end       = (/n_turbines, t_ind /) )
[4411]3170
[4497]3171       output_values_1d_target = torque_total(:)
3172       output_values_1d_pointer => output_values_1d_target
[4411]3173
[4497]3174       return_value = dom_write_var( nc_filename,                                                  &
3175                                     'rotor_torque',                                               &
3176                                     values_realwp_1d = output_values_1d_pointer,                  &
3177                                     bounds_start     = (/1, t_ind/),                              &
3178                                     bounds_end       = (/n_turbines, t_ind /) )
3179
3180       output_values_1d_target = pitch_angle(:)
3181       output_values_1d_pointer => output_values_1d_target
3182
3183       return_value = dom_write_var( nc_filename,                                                  &
3184                                     'pitch_angle',                                                &
3185                                     values_realwp_1d = output_values_1d_pointer,                  &
3186                                     bounds_start     = (/1, t_ind/),                              &
3187                                     bounds_end       = (/n_turbines, t_ind /) )
3188
3189       output_values_1d_target = torque_gen_old(:) * generator_speed(:) * generator_efficiency
3190       output_values_1d_pointer => output_values_1d_target
3191
3192       return_value = dom_write_var( nc_filename,                                                  &
3193                                     'generator_power',                                            &
3194                                     values_realwp_1d = output_values_1d_pointer,                  &
3195                                     bounds_start     = (/1, t_ind/),                              &
3196                                     bounds_end       = (/n_turbines, t_ind /) )
3197
3198       DO  inot = 1, n_turbines
3199          output_values_1d_target(inot) = torque_total(inot) * rotor_speed(inot) * air_density
3200       ENDDO
3201       output_values_1d_pointer => output_values_1d_target
3202
3203       return_value = dom_write_var( nc_filename,                                                  &
3204                                     'rotor_power',                                                &
3205                                     values_realwp_1d = output_values_1d_pointer,                  &
3206                                     bounds_start     = (/1, t_ind/),                              &
3207                                     bounds_end       = (/n_turbines, t_ind /) )
3208
3209       output_values_1d_target = thrust_rotor(:)
3210       output_values_1d_pointer => output_values_1d_target
3211
3212       return_value = dom_write_var( nc_filename,                                                  &
3213                                     'rotor_thrust',                                               &
3214                                     values_realwp_1d = output_values_1d_pointer,                  &
3215                                     bounds_start     = (/1, t_ind/),                              &
3216                                     bounds_end       = (/n_turbines, t_ind /) )
3217
3218       output_values_1d_target = wdir(:)*180.0_wp/pi
3219       output_values_1d_pointer => output_values_1d_target
3220
3221       return_value = dom_write_var( nc_filename,                                                  &
3222                                     'wind_direction',                                             &
3223                                     values_realwp_1d = output_values_1d_pointer,                  &
3224                                     bounds_start     = (/1, t_ind/),                              &
3225                                     bounds_end       = (/n_turbines, t_ind /) )
3226
3227       output_values_1d_target = (yaw_angle(:)) * 180.0_wp / pi
3228       output_values_1d_pointer => output_values_1d_target
3229
3230       return_value = dom_write_var( nc_filename,                                                  &
3231                                     'yaw_angle',                                                  &
3232                                     values_realwp_1d = output_values_1d_pointer,                  &
3233                                     bounds_start     = (/1, t_ind/),                              &
3234                                     bounds_end       = (/n_turbines, t_ind /) )
3235
3236       output_values_0d_target = time_since_reference_point
3237       output_values_0d_pointer => output_values_0d_target
3238
3239       return_value = dom_write_var( nc_filename,                                                  &
3240                                     'time',                                                       &
3241                                     values_realwp_0d = output_values_0d_pointer,                  &
3242                                     bounds_start     = (/t_ind/),                                 &
3243                                     bounds_end       = (/t_ind/) )
3244
3245       DEALLOCATE ( output_values_1d_target )
3246
3247    ENDIF
3248
3249 END SUBROUTINE wtm_data_output
3250
[1819]3251 END MODULE wind_turbine_model_mod
Note: See TracBrowser for help on using the repository browser.