1 | !WRF:MODEL_LAYER:PHYSICS |
---|
2 | |
---|
3 | MODULE module_wind_fitch |
---|
4 | |
---|
5 | ! Calculates drag at model levels intersected by turbine blades |
---|
6 | ! using wind speed dependent thrust coeff obtained from manufacturer. |
---|
7 | ! Adds source of TKE from KE not extracted by turbine for power. |
---|
8 | ! Output: |
---|
9 | ! du, dv: horizontal velocity tendencies |
---|
10 | ! qke: TKE |
---|
11 | ! Input: |
---|
12 | ! dz = dz between full levels (m) |
---|
13 | ! phb = geopotential height |
---|
14 | ! theight = hub height in m |
---|
15 | ! tdiameter = turbine diameter in m |
---|
16 | ! stdthrcoef = standing thrust coeff. |
---|
17 | ! tpower = turbine power in MW |
---|
18 | ! cospeed = cut-out speed in m/s |
---|
19 | ! cispeed = cut-in speed in m/s |
---|
20 | ! ewfx = x-extent of rectangular wind farm in grid cells |
---|
21 | ! ewfy = y-extent of rectangular wind farm in grid cells |
---|
22 | ! pwfx = x-coord of grid cell in SW corner of farm |
---|
23 | ! pwfy = y-coord of grid cell in SW corner of farm |
---|
24 | ! turbpercell = no. of turbines per grid cell |
---|
25 | |
---|
26 | USE module_wind_generic |
---|
27 | USE module_driver_constants, ONLY : max_domains |
---|
28 | USE module_model_constants, ONLY : g |
---|
29 | |
---|
30 | IMPLICIT NONE |
---|
31 | |
---|
32 | LOGICAL, DIMENSION(max_domains) :: inited |
---|
33 | |
---|
34 | PUBLIC turbine_drag |
---|
35 | PRIVATE dragcof, turbine_area, inited |
---|
36 | |
---|
37 | CONTAINS |
---|
38 | |
---|
39 | SUBROUTINE turbine_drag( & |
---|
40 | & id & |
---|
41 | &,phb,u,v,xlat_u,xlong_u & |
---|
42 | &,xlat_v,xlong_v & |
---|
43 | &,dx,dz,dt,qke,du,dv & |
---|
44 | &,ids,ide,jds,jde,kds,kde & |
---|
45 | &,ims,ime,jms,jme,kms,kme & |
---|
46 | &,its,ite,jts,jte,kts,kte & |
---|
47 | &) |
---|
48 | |
---|
49 | INTEGER, INTENT(IN) :: id ! grid id |
---|
50 | INTEGER, INTENT(IN) :: its,ite,jts,jte,kts,kte |
---|
51 | INTEGER, INTENT(IN) :: ims,ime,jms,jme,kms,kme |
---|
52 | INTEGER, INTENT(IN) :: ids,ide,jds,jde,kds,kde |
---|
53 | REAL, INTENT(IN) :: dx,dt |
---|
54 | REAL, DIMENSION(ims:ime,kms:kme,jms:jme), INTENT(IN) :: dz,u,v,phb |
---|
55 | REAL, DIMENSION(ims:ime,jms:jme), INTENT(IN) :: xlat_u, xlong_u |
---|
56 | REAL, DIMENSION(ims:ime,jms:jme), INTENT(IN) :: xlat_v, xlong_v |
---|
57 | REAL, DIMENSION(ims:ime,kms:kme,jms:jme), INTENT(INOUT) :: du,dv,qke |
---|
58 | ! Local |
---|
59 | TYPE(windturbine_specs), POINTER :: p |
---|
60 | INTEGER turbgridid |
---|
61 | REAL hubheight,diameter,power,cutinspeed,cutoutspeed,stdthrcoef,turbpercell |
---|
62 | INTEGER ewfx,ewfy,pwfx,pwfy |
---|
63 | REAL blade_l_point,blade_u_point,zheightl,zheightu,z1,z2,tarea |
---|
64 | REAL speed,tkecof,powcof,thrcof,wfdensity |
---|
65 | INTEGER itf,jtf,ktf |
---|
66 | INTEGER i,j,k,swfindx,ewfindx,swfindy,ewfindy,n,n1,n2,iturbine |
---|
67 | INTEGER k_turbine_bot, k_turbine_top |
---|
68 | |
---|
69 | LOGICAL :: kfound |
---|
70 | INTEGER :: allzero |
---|
71 | |
---|
72 | itf=MIN0(ite,ide-1) |
---|
73 | jtf=MIN0(jte,jde-1) |
---|
74 | ktf=MIN0(kte,kde-1) |
---|
75 | |
---|
76 | CALL nl_get_td_turbpercell(1,turbpercell) |
---|
77 | CALL nl_get_td_turbgridid(1,turbgridid) |
---|
78 | IF ( .NOT. inited(id) ) THEN |
---|
79 | IF ( windspec .EQ. WIND_TURBINES_FROMLIST ) THEN |
---|
80 | ! first check and see if xlat and xlong are all zero, if so, then use i,j directly |
---|
81 | ! (just check the u variables) |
---|
82 | allzero=1 |
---|
83 | DO j=jts,jtf |
---|
84 | DO i=its,itf |
---|
85 | IF (xlat_u(i,j).NE.0. .OR. xlong_u(i,j).NE.0)allzero=0 |
---|
86 | ENDDO |
---|
87 | ENDDO |
---|
88 | CALL wrf_dm_bcast_integer(allzero,1) |
---|
89 | IF ( allzero .NE. 1 ) THEN |
---|
90 | ! if there are actual lats and lons available, find i and j based on lat and lon |
---|
91 | ! otherwise, it is an idealized case and the user has specified i and j in the |
---|
92 | ! turbines file read in by read_windturbines_in in module_wind_generic |
---|
93 | DO iturbine = 1,nwindturbines ! nwindturbines defined in module_wind_generic |
---|
94 | p => windturbines(iturbine) |
---|
95 | IF ( id .EQ. p%id ) THEN |
---|
96 | DO j=jts,jtf |
---|
97 | DO i=its,itf |
---|
98 | IF (xlat_v(i,j) .LE. p%lat .AND. p%lat .LT. xlat_v(i+1,j) .AND. & |
---|
99 | xlong_u(i,j).LE. p%lon .AND. p%lon .LT. xlong_u(i,j+1)) THEN |
---|
100 | p%i=i |
---|
101 | p%j=j |
---|
102 | ENDIF |
---|
103 | ENDDO |
---|
104 | ENDDO |
---|
105 | ENDIF |
---|
106 | ENDDO |
---|
107 | ENDIF |
---|
108 | ELSE IF ( windspec .EQ. WIND_TURBINES_IDEAL .AND. id .EQ. turbgridid ) THEN |
---|
109 | CALL nl_get_td_ewfx(1,ewfx) |
---|
110 | CALL nl_get_td_ewfy(1,ewfy) |
---|
111 | CALL nl_get_td_pwfx(1,pwfx) |
---|
112 | CALL nl_get_td_pwfy(1,pwfy) |
---|
113 | CALL nl_get_td_hubheight(1,hubheight) |
---|
114 | CALL nl_get_td_diameter(1,diameter) |
---|
115 | CALL nl_get_td_power(1,power) |
---|
116 | CALL nl_get_td_cutinspeed(1,cutinspeed) |
---|
117 | CALL nl_get_td_cutoutspeed(1,cutoutspeed) |
---|
118 | CALL nl_get_td_stdthrcoef(1,stdthrcoef) |
---|
119 | ! count the turbines |
---|
120 | n = 0 |
---|
121 | DO j = jts,jtf |
---|
122 | IF ( pwfy .LE. j .AND. j .LE. (pwfy+ewfy-1) ) THEN |
---|
123 | DO i = its,itf |
---|
124 | IF ( pwfx .LE. i .AND. i .LE. (pwfx+ewfx-1) ) THEN |
---|
125 | n = n + 1 |
---|
126 | ENDIF |
---|
127 | ENDDO |
---|
128 | ENDIF |
---|
129 | ENDDO |
---|
130 | nwindturbines = n |
---|
131 | ALLOCATE(windturbines(nwindturbines)) |
---|
132 | ! set the turbines |
---|
133 | n = 0 |
---|
134 | DO j = jts,jtf |
---|
135 | IF ( pwfy .LE. j .AND. j .LE. (pwfy+ewfy-1) ) THEN |
---|
136 | DO i = its,itf |
---|
137 | IF ( pwfx .LE. i .AND. i .LE. (pwfx+ewfx-1) ) THEN |
---|
138 | n = n + 1 |
---|
139 | IF ( n .GT. nwindturbines ) THEN |
---|
140 | CALL wrf_error_fatal('would overrun windturbines array') |
---|
141 | ENDIF |
---|
142 | windturbines(n)%id = id |
---|
143 | windturbines(n)%lat = 0.0 |
---|
144 | windturbines(n)%lon = 0.0 |
---|
145 | windturbines(n)%i = i |
---|
146 | windturbines(n)%j = j |
---|
147 | windturbines(n)%hubheight = hubheight |
---|
148 | windturbines(n)%diameter = diameter |
---|
149 | windturbines(n)%stdthrcoef = stdthrcoef |
---|
150 | windturbines(n)%power = power |
---|
151 | windturbines(n)%cutinspeed = cutinspeed |
---|
152 | windturbines(n)%cutoutspeed = cutoutspeed |
---|
153 | ENDIF |
---|
154 | ENDDO |
---|
155 | ENDIF |
---|
156 | ENDDO |
---|
157 | ENDIF |
---|
158 | inited(id) = .TRUE. |
---|
159 | ENDIF |
---|
160 | IF ( windspec .EQ. WIND_TURBINES_FROMLIST ) THEN |
---|
161 | wfdensity = 1.0/(dx*dx) ! per turbine, so numerator is 1 |
---|
162 | ELSE |
---|
163 | wfdensity = turbpercell/(dx*dx) |
---|
164 | ENDIF |
---|
165 | |
---|
166 | IF (inited(id) .AND. & |
---|
167 | ((windspec .EQ. WIND_TURBINES_FROMLIST) .OR. & |
---|
168 | (windspec .EQ. WIND_TURBINES_IDEAL .AND. id .EQ. turbgridid ))) THEN |
---|
169 | DO iturbine = 1,nwindturbines ! nwindturbines defined in module_wind_generic |
---|
170 | p => windturbines(iturbine) |
---|
171 | IF ( id .EQ. p%id ) THEN |
---|
172 | ! vertical layers cut by turbine blades |
---|
173 | k_turbine_bot=0 !bottom level |
---|
174 | k_turbine_top=-1 !top level |
---|
175 | i = p%i |
---|
176 | j = p%j |
---|
177 | |
---|
178 | IF (( its .LE. i .AND. i .LE. itf ) .AND. & |
---|
179 | ( jts .LE. j .AND. j .LE. jtf ) ) THEN |
---|
180 | |
---|
181 | blade_l_point=p%hubheight-p%diameter/2. ! height of lower blade tip above ground (m) (theight=hub height) |
---|
182 | blade_u_point=p%hubheight+p%diameter/2. ! height of upper blade tip above ground (m) |
---|
183 | |
---|
184 | kfound = .false. |
---|
185 | zheightl=0.0 |
---|
186 | ! find vertical levels cut by turbine blades |
---|
187 | DO k=kts,ktf |
---|
188 | IF(.NOT. kfound) THEN |
---|
189 | zheightu = zheightl + dz(i,k,j) ! increment height |
---|
190 | |
---|
191 | IF(blade_l_point .GE. zheightl .AND. blade_l_point .LE. zheightu) THEN |
---|
192 | k_turbine_bot=k ! lower blade tip cuts this level |
---|
193 | ENDIF |
---|
194 | |
---|
195 | IF(blade_u_point .GE. zheightl .AND. blade_u_point .LE. zheightu) THEN |
---|
196 | k_turbine_top=k ! upper blade tip cuts this level |
---|
197 | kfound = .TRUE. |
---|
198 | ENDIF |
---|
199 | |
---|
200 | zheightl = zheightu |
---|
201 | ENDIF |
---|
202 | ENDDO |
---|
203 | IF ( kfound ) THEN |
---|
204 | DO k=k_turbine_bot,k_turbine_top ! loop over turbine blade levels |
---|
205 | |
---|
206 | z1=phb(i,k,j)/g-blade_l_point-phb(i,1,j)/g ! distance between k level and lower blade tip |
---|
207 | z2=phb(i,k+1,j)/g-blade_l_point-phb(i,1,j)/g ! distance between k+1 level and lower blade tip |
---|
208 | |
---|
209 | IF(z1 .LT. 0.) z1=0.0 ! k level lower than lower blade tip |
---|
210 | IF(z2 .GT. p%diameter) z2=p%diameter ! k+1 level higher than turbine upper blade tip |
---|
211 | |
---|
212 | ! magnitude of horizontal velocity |
---|
213 | speed=sqrt(u(i,k,j)*u(i,k,j)+v(i,k,j)*v(i,k,j)) |
---|
214 | |
---|
215 | ! calculate TKE, power and thrust coeffs |
---|
216 | CALL dragcof(tkecof,powcof,thrcof, & |
---|
217 | speed,p%cutinspeed,p%cutoutspeed, & |
---|
218 | p%power,p%diameter,p%stdthrcoef) |
---|
219 | |
---|
220 | CALL turbine_area(z1,z2,p%diameter,wfdensity,tarea) |
---|
221 | |
---|
222 | ! output TKE tendency |
---|
223 | qke(i,k,j) = qke(i,k,j)+speed*speed*speed*tarea*tkecof*dt/dz(i,k,j) |
---|
224 | ! output u tendency |
---|
225 | du(i,k,j) = du(i,k,j)-.5*u(i,k,j)*thrcof*speed*tarea/dz(i,k,j) |
---|
226 | ! output v tendency |
---|
227 | dv(i,k,j) = dv(i,k,j)-.5*v(i,k,j)*thrcof*speed*tarea/dz(i,k,j) |
---|
228 | |
---|
229 | ENDDO |
---|
230 | ENDIF |
---|
231 | ENDIF |
---|
232 | ENDIF |
---|
233 | ENDDO |
---|
234 | ENDIF |
---|
235 | END SUBROUTINE turbine_drag |
---|
236 | |
---|
237 | ! calculates area of turbine between two vertical levels |
---|
238 | ! Input variables : |
---|
239 | ! z1 = distance between k level and lower blade tip |
---|
240 | ! z2 = distance between k+1 level and lower blade tip |
---|
241 | ! wfdensity = wind farm density in m^-2 |
---|
242 | ! tdiameter = turbine diameter |
---|
243 | ! Output variable : |
---|
244 | ! tarea = area of turbine between two levels * wfdensity |
---|
245 | SUBROUTINE turbine_area(z1,z2,tdiameter,wfdensity,tarea) |
---|
246 | |
---|
247 | REAL, INTENT(IN) ::tdiameter,wfdensity |
---|
248 | REAL, INTENT(INOUT) ::z1,z2 |
---|
249 | REAL, INTENT(OUT):: tarea |
---|
250 | REAL r,zc1,zc2 |
---|
251 | |
---|
252 | r=tdiameter/2. !r = turbine radius |
---|
253 | z1=r-z1 !distance of kth level from turbine center |
---|
254 | z2=r-z2 !distance of k+1 th level from turbine center |
---|
255 | zc1=abs(z1) |
---|
256 | zc2=abs(z2) |
---|
257 | !turbine area between z1 and z2 |
---|
258 | IF(z1 .GT. 0. .AND. z2 .GT. 0) THEN |
---|
259 | tarea=zc1*sqrt(r*r-zc1*zc1)+r*r*asin(zc1/r)- & |
---|
260 | (zc2*sqrt(r*r-zc2*zc2)+r*r*asin(zc2/r)) |
---|
261 | ELSE IF(z1 .LT. 0. .AND. z2 .LT. 0) THEN |
---|
262 | tarea=zc2*sqrt(r*r-zc2*zc2)+r*r*asin(zc2/r)- & |
---|
263 | (zc1*sqrt(r*r-zc1*zc1)+r*r*asin(zc1/r)) |
---|
264 | ELSE |
---|
265 | tarea=zc2*sqrt(r*r-zc2*zc2)+r*r*asin(zc2/r)+ & |
---|
266 | zc1*sqrt(r*r-zc1*zc1)+r*r*asin(zc1/r) |
---|
267 | ENDIF |
---|
268 | tarea=tarea*wfdensity !turbine area * wind farm density |
---|
269 | |
---|
270 | END SUBROUTINE turbine_area |
---|
271 | |
---|
272 | ! Caculates tke, power and thrust coefficients as function of horiz wind speed |
---|
273 | ! from fit to turbine power curve - needs to be changed for particular turbine used |
---|
274 | |
---|
275 | ! tkecof = tke coefficient |
---|
276 | ! powcof = power coefficient |
---|
277 | ! thrcof = thrust coefficient |
---|
278 | ! cispeed = cut-in speed in m/s |
---|
279 | ! cospeed = cut-out speed in m/s |
---|
280 | ! tpower = turbine power in MW |
---|
281 | ! speed = horiz wind speed in m/s |
---|
282 | ! tdiameter = turbine diameter in m |
---|
283 | ! stdthrcoef = standing thrust coefficient |
---|
284 | |
---|
285 | SUBROUTINE dragcof(tkecof,powcof,thrcof,speed,cispeed,cospeed, & |
---|
286 | tpower,tdiameter,stdthrcoef) |
---|
287 | |
---|
288 | ! DISCLAIMER: The following power curve, power coefficients, and thrust |
---|
289 | ! coefficients are meant for testing purposes only, and were formulated as |
---|
290 | ! an approximation to a real curve. The user is strongly encouraged to |
---|
291 | ! incorporate their own curves for the particular turbine of interest |
---|
292 | ! to them. |
---|
293 | |
---|
294 | REAL, PARAMETER :: pi=22./7. |
---|
295 | REAL, INTENT(IN):: speed, cispeed, cospeed, tpower,tdiameter,stdthrcoef |
---|
296 | REAL, INTENT(OUT):: tkecof,powcof,thrcof |
---|
297 | REAL :: power,area,mspeed,hspeed |
---|
298 | |
---|
299 | area=pi/4.*tdiameter*tdiameter ! area swept by turbine blades |
---|
300 | |
---|
301 | ! GENERIC POWER CURVE - USE AT YOUR OWN RISK |
---|
302 | mspeed=0.5*(cospeed+cispeed) !average of cispeed & cospeed |
---|
303 | hspeed=0.5*(cospeed-mspeed) !this regulates the transition to full power |
---|
304 | power =tpower*(.5*tanh((speed - (mspeed-hspeed))/(hspeed*0.60)) + .5)*.8 |
---|
305 | |
---|
306 | ! GENERIC power coefficient calculation - USE AT YOUR OWN RISK |
---|
307 | IF(speed .LE. cispeed .OR. speed .GE. cospeed) THEN |
---|
308 | power=0. |
---|
309 | powcof=0. |
---|
310 | ELSE |
---|
311 | powcof = power * 2.e+6 / (speed*speed*speed*area) |
---|
312 | IF (speed .LT. cispeed*2.) THEN ! dampen artificial max near cispeed |
---|
313 | powcof = powcof * exp(-((speed-cispeed*2.)**2./(cispeed*2.))) |
---|
314 | end if |
---|
315 | powcof = MIN(powcof,.55) |
---|
316 | ENDIF |
---|
317 | |
---|
318 | ! GENERIC Thrust coefficient calculation - USE AT YOUR OWN RISK |
---|
319 | IF (speed .LE. cispeed .OR. speed .GE. cospeed) THEN |
---|
320 | thrcof = stdthrcoef |
---|
321 | ELSE |
---|
322 | !thrcof= stdthrcoef+2.3/speed**.8 |
---|
323 | thrcof = powcof + powcof*0.75 |
---|
324 | thrcof = MIN(thrcof,.9) |
---|
325 | thrcof = MAX(thrcof,stdthrcoef) |
---|
326 | ENDIF |
---|
327 | |
---|
328 | ! tke coefficient calculation |
---|
329 | tkecof=thrcof-powcof |
---|
330 | IF(tkecof .LT. 0.) tkecof=0. |
---|
331 | |
---|
332 | END SUBROUTINE dragcof |
---|
333 | |
---|
334 | SUBROUTINE init_module_wind_fitch |
---|
335 | inited = .FALSE. |
---|
336 | END SUBROUTINE init_module_wind_fitch |
---|
337 | |
---|
338 | END MODULE module_wind_fitch |
---|