source: lmdz_wrf/WRFV3/phys/module_wind_fitch.F @ 1

Last change on this file since 1 was 1, checked in by lfita, 10 years ago
  • -- --- Opening of the WRF+LMDZ coupling repository --- -- -

WRF: version v3.3
LMDZ: version v1818

More details in:

File size: 12.0 KB
Line 
1!WRF:MODEL_LAYER:PHYSICS
2
3MODULE 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
37CONTAINS
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 
338END MODULE module_wind_fitch
Note: See TracBrowser for help on using the repository browser.