Changeset 12377 for NEMO/trunk/src/OCE/SBC
- Timestamp:
- 2020-02-12T15:39:06+01:00 (4 years ago)
- Location:
- NEMO/trunk
- Files:
-
- 8 deleted
- 21 edited
- 8 copied
Legend:
- Unmodified
- Added
- Removed
-
NEMO/trunk
- Property svn:externals
-
old new 3 3 ^/utils/build/mk@HEAD mk 4 4 ^/utils/tools@HEAD tools 5 ^/vendors/AGRIF/dev @HEAD ext/AGRIF5 ^/vendors/AGRIF/dev_r11615_ENHANCE-04_namelists_as_internalfiles_agrif@HEAD ext/AGRIF 6 6 ^/vendors/FCM@HEAD ext/FCM 7 7 ^/vendors/IOIPSL@HEAD ext/IOIPSL
-
- Property svn:externals
-
NEMO/trunk/src/OCE/SBC/cpl_oasis3.F90
r12132 r12377 114 114 !------------------------------------------------------------------ 115 115 CALL oasis_init_comp ( ncomp_id, TRIM(cd_modname), nerror ) 116 IF 116 IF( nerror /= OASIS_Ok ) & 117 117 CALL oasis_abort (ncomp_id, 'cpl_init', 'Failure in oasis_init_comp') 118 118 … … 122 122 123 123 CALL oasis_get_localcomm ( kl_comm, nerror ) 124 IF 124 IF( nerror /= OASIS_Ok ) & 125 125 CALL oasis_abort (ncomp_id, 'cpl_init','Failure in oasis_get_localcomm' ) 126 126 ! … … 149 149 150 150 ! patch to restore wraparound rows in cpl_send, cpl_rcv, cpl_define 151 IF 151 IF( ltmp_wapatch ) THEN 152 152 nldi_save = nldi ; nlei_save = nlei 153 153 nldj_save = nldj ; nlej_save = nlej … … 203 203 paral(5) = jpiglo ! global extent in x 204 204 205 IF( ln_ctl) THEN205 IF( sn_cfctl%l_oasout ) THEN 206 206 WRITE(numout,*) ' multiexchg: paral (1:5)', paral 207 207 WRITE(numout,*) ' multiexchg: jpi, jpj =', jpi, jpj … … 217 217 ! 218 218 DO ji = 1, ksnd 219 IF 219 IF( ssnd(ji)%laction ) THEN 220 220 221 221 IF( ssnd(ji)%nct > nmaxcat ) THEN … … 228 228 DO jm = 1, kcplmodel 229 229 230 IF 230 IF( ssnd(ji)%nct .GT. 1 ) THEN 231 231 WRITE(cli2,'(i2.2)') jc 232 232 zclname = TRIM(ssnd(ji)%clname)//'_cat'//cli2 … … 234 234 zclname = ssnd(ji)%clname 235 235 ENDIF 236 IF 236 IF( kcplmodel > 1 ) THEN 237 237 WRITE(cli2,'(i2.2)') jm 238 238 zclname = 'model'//cli2//'_'//TRIM(zclname) … … 241 241 IF( agrif_fixed() /= 0 ) THEN 242 242 zclname=TRIM(Agrif_CFixed())//'_'//TRIM(zclname) 243 END 244 #endif 245 IF( ln_ctl) WRITE(numout,*) "Define", ji, jc, jm, " "//TRIM(zclname), " for ", OASIS_Out243 ENDIF 244 #endif 245 IF( sn_cfctl%l_oasout ) WRITE(numout,*) "Define", ji, jc, jm, " "//TRIM(zclname), " for ", OASIS_Out 246 246 CALL oasis_def_var (ssnd(ji)%nid(jc,jm), zclname, id_part , (/ 2, 1 /), & 247 247 & OASIS_Out , ishape , OASIS_REAL, nerror ) 248 IF 248 IF( nerror /= OASIS_Ok ) THEN 249 249 WRITE(numout,*) 'Failed to define transient ', ji, jc, jm, " "//TRIM(zclname) 250 250 CALL oasis_abort ( ssnd(ji)%nid(jc,jm), 'cpl_define', 'Failure in oasis_def_var' ) 251 251 ENDIF 252 IF( ln_ctl.AND. ssnd(ji)%nid(jc,jm) /= -1 ) WRITE(numout,*) "variable defined in the namcouple"253 IF( ln_ctl.AND. ssnd(ji)%nid(jc,jm) == -1 ) WRITE(numout,*) "variable NOT defined in the namcouple"252 IF( sn_cfctl%l_oasout .AND. ssnd(ji)%nid(jc,jm) /= -1 ) WRITE(numout,*) "variable defined in the namcouple" 253 IF( sn_cfctl%l_oasout .AND. ssnd(ji)%nid(jc,jm) == -1 ) WRITE(numout,*) "variable NOT defined in the namcouple" 254 254 END DO 255 255 END DO … … 262 262 ! 263 263 DO ji = 1, krcv 264 IF 264 IF( srcv(ji)%laction ) THEN 265 265 266 266 IF( srcv(ji)%nct > nmaxcat ) THEN … … 273 273 DO jm = 1, kcplmodel 274 274 275 IF 275 IF( srcv(ji)%nct .GT. 1 ) THEN 276 276 WRITE(cli2,'(i2.2)') jc 277 277 zclname = TRIM(srcv(ji)%clname)//'_cat'//cli2 … … 279 279 zclname = srcv(ji)%clname 280 280 ENDIF 281 IF 281 IF( kcplmodel > 1 ) THEN 282 282 WRITE(cli2,'(i2.2)') jm 283 283 zclname = 'model'//cli2//'_'//TRIM(zclname) … … 286 286 IF( agrif_fixed() /= 0 ) THEN 287 287 zclname=TRIM(Agrif_CFixed())//'_'//TRIM(zclname) 288 END 289 #endif 290 IF( ln_ctl) WRITE(numout,*) "Define", ji, jc, jm, " "//TRIM(zclname), " for ", OASIS_In288 ENDIF 289 #endif 290 IF( sn_cfctl%l_oasout ) WRITE(numout,*) "Define", ji, jc, jm, " "//TRIM(zclname), " for ", OASIS_In 291 291 CALL oasis_def_var (srcv(ji)%nid(jc,jm), zclname, id_part , (/ 2, 1 /), & 292 292 & OASIS_In , ishape , OASIS_REAL, nerror ) 293 IF 293 IF( nerror /= OASIS_Ok ) THEN 294 294 WRITE(numout,*) 'Failed to define transient ', ji, jc, jm, " "//TRIM(zclname) 295 295 CALL oasis_abort ( srcv(ji)%nid(jc,jm), 'cpl_define', 'Failure in oasis_def_var' ) 296 296 ENDIF 297 IF( ln_ctl.AND. srcv(ji)%nid(jc,jm) /= -1 ) WRITE(numout,*) "variable defined in the namcouple"298 IF( ln_ctl.AND. srcv(ji)%nid(jc,jm) == -1 ) WRITE(numout,*) "variable NOT defined in the namcouple"297 IF( sn_cfctl%l_oasout .AND. srcv(ji)%nid(jc,jm) /= -1 ) WRITE(numout,*) "variable defined in the namcouple" 298 IF( sn_cfctl%l_oasout .AND. srcv(ji)%nid(jc,jm) == -1 ) WRITE(numout,*) "variable NOT defined in the namcouple" 299 299 300 300 END DO … … 316 316 #endif 317 317 ! 318 IF 318 IF( ltmp_wapatch ) THEN 319 319 nldi = nldi_save ; nlei = nlei_save 320 320 nldj = nldj_save ; nlej = nlej_save … … 338 338 !!-------------------------------------------------------------------- 339 339 ! patch to restore wraparound rows in cpl_send, cpl_rcv, cpl_define 340 IF 340 IF( ltmp_wapatch ) THEN 341 341 nldi_save = nldi ; nlei_save = nlei 342 342 nldj_save = nldj ; nlej_save = nlej … … 355 355 CALL oasis_put ( ssnd(kid)%nid(jc,jm), kstep, pdata(nldi:nlei, nldj:nlej,jc), kinfo ) 356 356 357 IF ( ln_ctl) THEN357 IF ( sn_cfctl%l_oasout ) THEN 358 358 IF ( kinfo == OASIS_Sent .OR. kinfo == OASIS_ToRest .OR. & 359 359 & kinfo == OASIS_SentOut .OR. kinfo == OASIS_ToRestOut ) THEN … … 374 374 ENDDO 375 375 ENDDO 376 IF 376 IF( ltmp_wapatch ) THEN 377 377 nldi = nldi_save ; nlei = nlei_save 378 378 nldj = nldj_save ; nlej = nlej_save … … 399 399 !!-------------------------------------------------------------------- 400 400 ! patch to restore wraparound rows in cpl_send, cpl_rcv, cpl_define 401 IF 401 IF( ltmp_wapatch ) THEN 402 402 nldi_save = nldi ; nlei_save = nlei 403 403 nldj_save = nldj ; nlej_save = nlej … … 409 409 ! 410 410 DO jc = 1, srcv(kid)%nct 411 IF 411 IF( ltmp_wapatch ) THEN 412 412 IF( nimpp == 1 ) nldi = 1 413 413 IF( nimpp + jpi - 1 == jpiglo ) nlei = jpi … … 426 426 & kinfo == OASIS_RecvOut .OR. kinfo == OASIS_FromRestOut 427 427 428 IF ( ln_ctl) WRITE(numout,*) "llaction, kinfo, kstep, ivarid: " , llaction, kinfo, kstep, srcv(kid)%nid(jc,jm)428 IF ( sn_cfctl%l_oasout ) WRITE(numout,*) "llaction, kinfo, kstep, ivarid: " , llaction, kinfo, kstep, srcv(kid)%nid(jc,jm) 429 429 430 IF 430 IF( llaction ) THEN 431 431 432 432 kinfo = OASIS_Rcv … … 438 438 ENDIF 439 439 440 IF ( ln_ctl) THEN440 IF ( sn_cfctl%l_oasout ) THEN 441 441 WRITE(numout,*) '****************' 442 442 WRITE(numout,*) 'oasis_get: Incoming ', srcv(kid)%clname … … 456 456 ENDDO 457 457 458 IF 458 IF( ltmp_wapatch ) THEN 459 459 nldi = nldi_save ; nlei = nlei_save 460 460 nldj = nldj_save ; nlej = nlej_save … … 489 489 ! 490 490 DO ji = 1, nsnd 491 IF 491 IF(ssnd(ji)%laction ) THEN 492 492 DO jm = 1, ncplmodel 493 493 IF( ssnd(ji)%nid(1,jm) /= -1 ) THEN … … 501 501 ENDDO 502 502 DO ji = 1, nrcv 503 IF 503 IF(srcv(ji)%laction ) THEN 504 504 DO jm = 1, ncplmodel 505 505 IF( srcv(ji)%nid(1,jm) /= -1 ) THEN … … 535 535 ! 536 536 DEALLOCATE( exfld ) 537 IF 537 IF(nstop == 0) THEN 538 538 CALL oasis_terminate( nerror ) 539 539 ELSE -
NEMO/trunk/src/OCE/SBC/cyclone.F90
r10068 r12377 37 37 38 38 !! * Substitutions 39 # include " vectopt_loop_substitute.h90"39 # include "do_loop_substitute.h90" 40 40 !!---------------------------------------------------------------------- 41 41 !! NEMO/OCE 4.0 , NEMO Consortium (2018) … … 137 137 zhemi = SIGN( 1. , zrlat ) 138 138 zinfl = 15.* rad ! clim inflow angle in Tropical Cyclones 139 IF 139 IF( vortex == 0 ) THEN 140 140 141 141 ! Vortex Holland reconstruct wind at each lon-lat position … … 147 147 zb = 2. 148 148 149 DO jj = 1, jpj 150 DO ji = 1, jpi 151 152 ! calc distance between TC center and any point following great circle 153 ! source : http://www.movable-type.co.uk/scripts/latlong.html 154 zzrglam = rad * glamt(ji,jj) - zrlon 155 zzrgphi = rad * gphit(ji,jj) 156 zdist = ra * ACOS( SIN( zrlat ) * SIN( zzrgphi ) & 157 & + COS( zrlat ) * COS( zzrgphi ) * COS( zzrglam ) ) 158 159 IF (zdist < zrout2) THEN ! calculation of wind only to a given max radius 160 ! shape of the wind profile 161 zztmp = ( zrmw / ( zdist + 1.e-12 ) )**zb 162 zztmp = zvmax * SQRT( zztmp * EXP(1. - zztmp) ) 163 164 IF (zdist > zrout1) THEN ! bring to zero between r_out1 and r_out2 165 zztmp = zztmp * ( (zrout2-zdist)*1.e-6 ) 166 ENDIF 167 168 ! !!! KILL EQ WINDS 169 ! IF (SIGN( 1. , zrlat ) /= zhemi) THEN 170 ! zztmp = 0. ! winds in other hemisphere 171 ! IF (ABS(gphit(ji,jj)) <= 5.) zztmp=0. ! kill between 5N-5S 172 ! ENDIF 173 ! IF (ABS(gphit(ji,jj)) <= 10. .and. ABS(gphit(ji,jj)) > 5.) THEN 174 ! zztmp = zztmp * ( 1./5. * (ABS(gphit(ji,jj)) - 5.) ) 175 ! !linear to zero between 10 and 5 176 ! ENDIF 177 ! !!! / KILL EQ 178 179 IF (ABS(gphit(ji,jj)) >= 55.) zztmp = 0. ! kill weak spurious winds at high latitude 180 181 zwnd_t = COS( zinfl ) * zztmp 182 zwnd_r = - SIN( zinfl ) * zztmp 183 184 ! Project radial-tangential components on zonal-meridional components 185 ! ------------------------------------------------------------------- 186 187 ! ztheta = azimuthal angle of the great circle between two points 188 zztmp = COS( zrlat ) * SIN( zzrgphi ) & 189 & - SIN( zrlat ) * COS( zzrgphi ) * COS( zzrglam ) 190 ztheta = ATAN2( COS( zzrgphi ) * SIN( zzrglam ) , zztmp ) 191 192 zwnd_x(ji,jj) = zwnd_x(ji,jj) - zhemi * COS(ztheta)*zwnd_t + SIN(ztheta)*zwnd_r 193 zwnd_y(ji,jj) = zwnd_y(ji,jj) + zhemi * SIN(ztheta)*zwnd_t + COS(ztheta)*zwnd_r 194 ENDIF 195 END DO 196 END DO 149 DO_2D_11_11 150 151 ! calc distance between TC center and any point following great circle 152 ! source : http://www.movable-type.co.uk/scripts/latlong.html 153 zzrglam = rad * glamt(ji,jj) - zrlon 154 zzrgphi = rad * gphit(ji,jj) 155 zdist = ra * ACOS( SIN( zrlat ) * SIN( zzrgphi ) & 156 & + COS( zrlat ) * COS( zzrgphi ) * COS( zzrglam ) ) 157 158 IF(zdist < zrout2) THEN ! calculation of wind only to a given max radius 159 ! shape of the wind profile 160 zztmp = ( zrmw / ( zdist + 1.e-12 ) )**zb 161 zztmp = zvmax * SQRT( zztmp * EXP(1. - zztmp) ) 162 163 IF(zdist > zrout1) THEN ! bring to zero between r_out1 and r_out2 164 zztmp = zztmp * ( (zrout2-zdist)*1.e-6 ) 165 ENDIF 166 167 ! !!! KILL EQ WINDS 168 ! IF(SIGN( 1. , zrlat ) /= zhemi) THEN 169 ! zztmp = 0. ! winds in other hemisphere 170 ! IF(ABS(gphit(ji,jj)) <= 5.) zztmp=0. ! kill between 5N-5S 171 ! ENDIF 172 ! IF(ABS(gphit(ji,jj)) <= 10. .and. ABS(gphit(ji,jj)) > 5.) THEN 173 ! zztmp = zztmp * ( 1./5. * (ABS(gphit(ji,jj)) - 5.) ) 174 ! !linear to zero between 10 and 5 175 ! ENDIF 176 ! !!! / KILL EQ 177 178 IF(ABS(gphit(ji,jj)) >= 55.) zztmp = 0. ! kill weak spurious winds at high latitude 179 180 zwnd_t = COS( zinfl ) * zztmp 181 zwnd_r = - SIN( zinfl ) * zztmp 182 183 ! Project radial-tangential components on zonal-meridional components 184 ! ------------------------------------------------------------------- 185 186 ! ztheta = azimuthal angle of the great circle between two points 187 zztmp = COS( zrlat ) * SIN( zzrgphi ) & 188 & - SIN( zrlat ) * COS( zzrgphi ) * COS( zzrglam ) 189 ztheta = ATAN2( COS( zzrgphi ) * SIN( zzrglam ) , zztmp ) 190 191 zwnd_x(ji,jj) = zwnd_x(ji,jj) - zhemi * COS(ztheta)*zwnd_t + SIN(ztheta)*zwnd_r 192 zwnd_y(ji,jj) = zwnd_y(ji,jj) + zhemi * SIN(ztheta)*zwnd_t + COS(ztheta)*zwnd_r 193 ENDIF 194 END_2D 197 195 198 ELSE IF 196 ELSE IF( vortex == 1 ) THEN 199 197 200 198 ! Vortex Willoughby reconstruct wind at each lon-lat position … … 206 204 zn = 2.1340 + 0.0077*zvmax - 0.4522*LOG(zrmw/1000.) - 0.0038*ABS( ztct(jtc,jp_lat) ) 207 205 zA = 0.5913 + 0.0029*zvmax - 0.1361*LOG(zrmw/1000.) - 0.0042*ABS( ztct(jtc,jp_lat) ) 208 IF 206 IF(zA < 0) THEN 209 207 zA=0 210 208 ENDIF 211 209 212 DO jj = 1, jpj 213 DO ji = 1, jpi 214 215 zzrglam = rad * glamt(ji,jj) - zrlon 216 zzrgphi = rad * gphit(ji,jj) 217 zdist = ra * ACOS( SIN( zrlat ) * SIN( zzrgphi ) & 218 & + COS( zrlat ) * COS( zzrgphi ) * COS( zzrglam ) ) 219 220 IF (zdist < zrout2) THEN ! calculation of wind only to a given max radius 210 DO_2D_11_11 211 212 zzrglam = rad * glamt(ji,jj) - zrlon 213 zzrgphi = rad * gphit(ji,jj) 214 zdist = ra * ACOS( SIN( zrlat ) * SIN( zzrgphi ) & 215 & + COS( zrlat ) * COS( zzrgphi ) * COS( zzrglam ) ) 216 217 IF(zdist < zrout2) THEN ! calculation of wind only to a given max radius 218 219 ! shape of the wind profile 220 IF(zdist <= zrmw) THEN ! inside the Radius of Maximum Wind 221 zztmp = zvmax * (zdist/zrmw)**zn 222 ELSE 223 zztmp = zvmax * ( (1-zA) * EXP(- (zdist-zrmw)/zXX1 ) + zA * EXP(- (zdist-zrmw)/zXX2 ) ) 224 ENDIF 225 226 IF(zdist > zrout1) THEN ! bring to zero between r_out1 and r_out2 227 zztmp = zztmp * ( (zrout2-zdist)*1.e-6 ) 228 ENDIF 229 230 ! !!! KILL EQ WINDS 231 ! IF(SIGN( 1. , zrlat ) /= zhemi) THEN 232 ! zztmp = 0. ! winds in other hemisphere 233 ! IF(ABS(gphit(ji,jj)) <= 5.) zztmp=0. ! kill between 5N-5S 234 ! ENDIF 235 ! IF(ABS(gphit(ji,jj)) <= 10. .and. ABS(gphit(ji,jj)) > 5.) THEN 236 ! zztmp = zztmp * ( 1./5. * (ABS(gphit(ji,jj)) - 5.) ) 237 ! !linear to zero between 10 and 5 238 ! ENDIF 239 ! !!! / KILL EQ 240 241 IF(ABS(gphit(ji,jj)) >= 55.) zztmp = 0. ! kill weak spurious winds at high latitude 242 243 zwnd_t = COS( zinfl ) * zztmp 244 zwnd_r = - SIN( zinfl ) * zztmp 245 246 ! Project radial-tangential components on zonal-meridional components 247 ! ------------------------------------------------------------------- 221 248 222 ! shape of the wind profile 223 IF (zdist <= zrmw) THEN ! inside the Radius of Maximum Wind 224 zztmp = zvmax * (zdist/zrmw)**zn 225 ELSE 226 zztmp = zvmax * ( (1-zA) * EXP(- (zdist-zrmw)/zXX1 ) + zA * EXP(- (zdist-zrmw)/zXX2 ) ) 227 ENDIF 228 229 IF (zdist > zrout1) THEN ! bring to zero between r_out1 and r_out2 230 zztmp = zztmp * ( (zrout2-zdist)*1.e-6 ) 231 ENDIF 232 233 ! !!! KILL EQ WINDS 234 ! IF (SIGN( 1. , zrlat ) /= zhemi) THEN 235 ! zztmp = 0. ! winds in other hemisphere 236 ! IF (ABS(gphit(ji,jj)) <= 5.) zztmp=0. ! kill between 5N-5S 237 ! ENDIF 238 ! IF (ABS(gphit(ji,jj)) <= 10. .and. ABS(gphit(ji,jj)) > 5.) THEN 239 ! zztmp = zztmp * ( 1./5. * (ABS(gphit(ji,jj)) - 5.) ) 240 ! !linear to zero between 10 and 5 241 ! ENDIF 242 ! !!! / KILL EQ 243 244 IF (ABS(gphit(ji,jj)) >= 55.) zztmp = 0. ! kill weak spurious winds at high latitude 245 246 zwnd_t = COS( zinfl ) * zztmp 247 zwnd_r = - SIN( zinfl ) * zztmp 248 249 ! Project radial-tangential components on zonal-meridional components 250 ! ------------------------------------------------------------------- 251 252 ! ztheta = azimuthal angle of the great circle between two points 253 zztmp = COS( zrlat ) * SIN( zzrgphi ) & 254 & - SIN( zrlat ) * COS( zzrgphi ) * COS( zzrglam ) 255 ztheta = ATAN2( COS( zzrgphi ) * SIN( zzrglam ) , zztmp ) 256 257 zwnd_x(ji,jj) = zwnd_x(ji,jj) - zhemi * COS(ztheta)*zwnd_t + SIN(ztheta)*zwnd_r 258 zwnd_y(ji,jj) = zwnd_y(ji,jj) + zhemi * SIN(ztheta)*zwnd_t + COS(ztheta)*zwnd_r 259 260 ENDIF 261 END DO 262 END DO 249 ! ztheta = azimuthal angle of the great circle between two points 250 zztmp = COS( zrlat ) * SIN( zzrgphi ) & 251 & - SIN( zrlat ) * COS( zzrgphi ) * COS( zzrglam ) 252 ztheta = ATAN2( COS( zzrgphi ) * SIN( zzrglam ) , zztmp ) 253 254 zwnd_x(ji,jj) = zwnd_x(ji,jj) - zhemi * COS(ztheta)*zwnd_t + SIN(ztheta)*zwnd_r 255 zwnd_y(ji,jj) = zwnd_y(ji,jj) + zhemi * SIN(ztheta)*zwnd_t + COS(ztheta)*zwnd_r 256 257 ENDIF 258 END_2D 263 259 ENDIF ! / vortex Holland or Wiloughby 264 260 ENDIF ! / cyclone is defined in this slot ? yes--> begin -
NEMO/trunk/src/OCE/SBC/fldread.F90
r12367 r12377 13 13 !! fld_read : read input fields used for the computation of the surface boundary condition 14 14 !! fld_init : initialization of field read 15 !! fld_ rec : determined the record(s) to be read15 !! fld_def : define the record(s) of the file and its name 16 16 !! fld_get : read the data 17 17 !! fld_map : read global data from file and map onto local data using a general mapping (use for open boundaries) 18 18 !! fld_rot : rotate the vector fields onto the local grid direction 19 !! fld_clopn : update the data file name andclose/open the files19 !! fld_clopn : close/open the files 20 20 !! fld_fill : fill the data structure with the associated information read in namelist 21 21 !! wgt_list : manage the weights used for interpolation … … 25 25 !! seaoverland : create shifted matrices for seaoverland application 26 26 !! fld_interp : apply weights to input gridded data to create data on model grid 27 !! ksec_week : function returning the first 3 letters of the first day of the weekly file 27 !! fld_filename : define the filename according to a given date 28 !! ksec_week : function returning seconds between 00h of the beginning of the week and half of the current time step 28 29 !!---------------------------------------------------------------------- 29 30 USE oce ! ocean dynamics and tracers … … 44 45 PUBLIC fld_map ! routine called by tides_init 45 46 PUBLIC fld_read, fld_fill ! called by sbc... modules 46 PUBLIC fld_ clopn47 PUBLIC fld_def 47 48 48 49 TYPE, PUBLIC :: FLD_N !: Namelist field informations … … 72 73 INTEGER , DIMENSION(2) :: nrec_b ! before record (1: index, 2: second since Jan. 1st 00h of nit000 year) 73 74 INTEGER , DIMENSION(2) :: nrec_a ! after record (1: index, 2: second since Jan. 1st 00h of nit000 year) 74 REAL(wp) , ALLOCATABLE, DIMENSION(:,:,: ) :: fnow ! input fields interpolated to now time step 75 REAL(wp) , ALLOCATABLE, DIMENSION(:,:,:,:) :: fdta ! 2 consecutive record of input fields 75 INTEGER , ALLOCATABLE, DIMENSION(: ) :: nrecsec ! 76 REAL(wp), ALLOCATABLE, DIMENSION(:,:,: ) :: fnow ! input fields interpolated to now time step 77 REAL(wp), ALLOCATABLE, DIMENSION(:,:,:,:) :: fdta ! 2 consecutive record of input fields 76 78 CHARACTER(len = 256) :: wgtname ! current name of the NetCDF weight file acting as a key 77 79 ! ! into the WGTLIST structure … … 118 120 TYPE( WGT ), DIMENSION(tot_wgts) :: ref_wgts ! array of wgts 119 121 INTEGER :: nxt_wgt = 1 ! point to next available space in ref_wgts array 122 INTEGER :: nflag = 0 120 123 REAL(wp), PARAMETER :: undeff_lsm = -999.00_wp 121 124 122 125 !$AGRIF_END_DO_NOT_TREAT 123 126 127 !! * Substitutions 128 # include "do_loop_substitute.h90" 124 129 !!---------------------------------------------------------------------- 125 130 !! NEMO/OCE 4.0 , NEMO Consortium (2018) … … 129 134 CONTAINS 130 135 131 SUBROUTINE fld_read( kt, kn_fsbc, sd, kit, kt_offset)136 SUBROUTINE fld_read( kt, kn_fsbc, sd, kit, pt_offset, Kmm ) 132 137 !!--------------------------------------------------------------------- 133 138 !! *** ROUTINE fld_read *** … … 145 150 TYPE(FLD), INTENT(inout), DIMENSION(:) :: sd ! input field related variables 146 151 INTEGER , INTENT(in ), OPTIONAL :: kit ! subcycle timestep for timesplitting option 147 INTEGER , INTENT(in ), OPTIONAL :: kt_offset ! provide fields at time other than "now" 148 ! ! kt_offset = -1 => fields at "before" time level 149 ! ! kt_offset = +1 => fields at "after" time level 150 ! ! etc. 151 !! 152 INTEGER :: itmp ! local variable 152 REAL(wp) , INTENT(in ), OPTIONAL :: pt_offset ! provide fields at time other than "now" 153 INTEGER , INTENT(in ), OPTIONAL :: Kmm ! ocean time level index 154 !! 153 155 INTEGER :: imf ! size of the structure sd 154 156 INTEGER :: jf ! dummy indices 155 INTEGER :: isecend ! number of second since Jan. 1st 00h of nit000 year at nitend156 157 INTEGER :: isecsbc ! number of seconds between Jan. 1st 00h of nit000 year and the middle of sbc time step 157 INTEGER :: it_offset ! local time offset variable158 LOGICAL :: llnxtyr ! open next year file?159 LOGICAL :: llnxtmth ! open next month file?160 LOGICAL :: llstop ! stop is the file does not exist161 158 LOGICAL :: ll_firstcall ! true if this is the first call to fld_read for this set of fields 159 REAL(wp) :: zt_offset ! local time offset variable 162 160 REAL(wp) :: ztinta ! ratio applied to after records when doing time interpolation 163 161 REAL(wp) :: ztintb ! ratio applied to before records when doing time interpolation … … 167 165 IF( PRESENT(kit) ) ll_firstcall = ll_firstcall .and. kit == 1 168 166 169 IF ( nn_components == jp_iam_sas ) THEN ; it_offset = nn_fsbc170 ELSE ; it_offset = 0171 ENDIF 172 IF( PRESENT( kt_offset) ) it_offset = kt_offset173 174 ! Note that shifting time to be centrered in the middle of sbc time step impacts only nsec_* variables of the calendar175 IF( present(kit) ) THEN ! ignore kn_fsbc in this case176 isecsbc = nsec_year + nsec1jan000 + (kit+it_offset)*NINT( rdt/REAL(nn_baro,wp) )167 IF( nn_components == jp_iam_sas ) THEN ; zt_offset = REAL( nn_fsbc, wp ) 168 ELSE ; zt_offset = 0. 169 ENDIF 170 IF( PRESENT(pt_offset) ) zt_offset = pt_offset 171 172 ! Note that all varibles starting by nsec_* are shifted time by +1/2 time step to be centrered 173 IF( PRESENT(kit) ) THEN ! ignore kn_fsbc in this case 174 isecsbc = nsec_year + nsec1jan000 + NINT( ( REAL( kit,wp) + zt_offset ) * rdt / REAL(nn_baro,wp) ) 177 175 ELSE ! middle of sbc time step 178 isecsbc = nsec_year + nsec1jan000 + NINT(0.5 * REAL(kn_fsbc - 1,wp) * rdt) + it_offset * NINT(rdt) 176 ! note: we use kn_fsbc-1 because nsec_year is defined at the middle of the current time step 177 isecsbc = nsec_year + nsec1jan000 + NINT( ( 0.5*REAL(kn_fsbc-1,wp) + zt_offset ) * rdt ) 179 178 ENDIF 180 179 imf = SIZE( sd ) … … 183 182 DO jf = 1, imf 184 183 IF( TRIM(sd(jf)%clrootname) == 'NOT USED' ) CYCLE 185 CALL fld_init( kn_fsbc, sd(jf) ) ! read each before field (put them in after as they will be swapped)184 CALL fld_init( isecsbc, sd(jf) ) ! read each before field (put them in after as they will be swapped) 186 185 END DO 187 186 IF( lwp ) CALL wgt_print() ! control print … … 192 191 ! 193 192 DO jf = 1, imf ! --- loop over field --- ! 194 193 ! 195 194 IF( TRIM(sd(jf)%clrootname) == 'NOT USED' ) CYCLE 196 197 IF( isecsbc > sd(jf)%nrec_a(2) .OR. ll_firstcall ) THEN ! read/update the after data? 198 199 sd(jf)%nrec_b(:) = sd(jf)%nrec_a(:) ! swap before record informations 200 sd(jf)%rotn(1) = sd(jf)%rotn(2) ! swap before rotate informations 201 IF( sd(jf)%ln_tint ) sd(jf)%fdta(:,:,:,1) = sd(jf)%fdta(:,:,:,2) ! swap before record field 202 203 CALL fld_rec( kn_fsbc, sd(jf), kt_offset = it_offset, kit = kit ) ! update after record informations 204 205 ! if kn_fsbc*rdt is larger than freqh (which is kind of odd), 206 ! it is possible that the before value is no more the good one... we have to re-read it 207 ! if before is not the last record of the file currently opened and after is the first record to be read 208 ! in a new file which means after = 1 (the file to be opened corresponds to the current time) 209 ! or after = nreclast + 1 (the file to be opened corresponds to a future time step) 210 IF( .NOT. ll_firstcall .AND. sd(jf)%ln_tint .AND. sd(jf)%nrec_b(1) /= sd(jf)%nreclast & 211 & .AND. MOD( sd(jf)%nrec_a(1), sd(jf)%nreclast ) == 1 ) THEN 212 itmp = sd(jf)%nrec_a(1) ! temporary storage 213 sd(jf)%nrec_a(1) = sd(jf)%nreclast ! read the last record of the file currently opened 214 CALL fld_get( sd(jf) ) ! read after data 215 sd(jf)%fdta(:,:,:,1) = sd(jf)%fdta(:,:,:,2) ! re-swap before record field 216 sd(jf)%nrec_b(1) = sd(jf)%nrec_a(1) ! update before record informations 217 sd(jf)%nrec_b(2) = sd(jf)%nrec_a(2) - NINT( sd(jf)%freqh * 3600. ) ! assume freq to be in hours in this case 218 sd(jf)%rotn(1) = sd(jf)%rotn(2) ! update before rotate informations 219 sd(jf)%nrec_a(1) = itmp ! move back to after record 220 ENDIF 221 222 CALL fld_clopn( sd(jf) ) ! Do we need to open a new year/month/week/day file? 223 224 IF( sd(jf)%ln_tint ) THEN 225 226 ! if kn_fsbc*rdt is larger than freqh (which is kind of odd), 227 ! it is possible that the before value is no more the good one... we have to re-read it 228 ! if before record is not just just before the after record... 229 IF( .NOT. ll_firstcall .AND. MOD( sd(jf)%nrec_a(1), sd(jf)%nreclast ) /= 1 & 230 & .AND. sd(jf)%nrec_b(1) /= sd(jf)%nrec_a(1) - 1 ) THEN 231 sd(jf)%nrec_a(1) = sd(jf)%nrec_a(1) - 1 ! move back to before record 232 CALL fld_get( sd(jf) ) ! read after data 233 sd(jf)%fdta(:,:,:,1) = sd(jf)%fdta(:,:,:,2) ! re-swap before record field 234 sd(jf)%nrec_b(1) = sd(jf)%nrec_a(1) ! update before record informations 235 sd(jf)%nrec_b(2) = sd(jf)%nrec_a(2) - NINT( sd(jf)%freqh * 3600. ) ! assume freq to be in hours in this case 236 sd(jf)%rotn(1) = sd(jf)%rotn(2) ! update before rotate informations 237 sd(jf)%nrec_a(1) = sd(jf)%nrec_a(1) + 1 ! move back to after record 238 ENDIF 239 ENDIF ! temporal interpolation? 240 241 ! do we have to change the year/month/week/day of the forcing field?? 242 ! if we do time interpolation we will need to open next year/month/week/day file before the end of the current 243 ! one. If so, we are still before the end of the year/month/week/day when calling fld_rec so sd(jf)%nrec_a(1) 244 ! will be larger than the record number that should be read for current year/month/week/day 245 ! do we need next file data? 246 ! This applies to both cases with or without time interpolation 247 IF( sd(jf)%nrec_a(1) > sd(jf)%nreclast ) THEN 248 249 sd(jf)%nrec_a(1) = sd(jf)%nrec_a(1) - sd(jf)%nreclast ! 250 251 IF( .NOT. ( sd(jf)%ln_clim .AND. sd(jf)%cltype == 'yearly' ) ) THEN ! close/open the current/new file 252 253 llnxtmth = sd(jf)%cltype == 'monthly' .OR. nday == nmonth_len(nmonth) ! open next month file? 254 llnxtyr = sd(jf)%cltype == 'yearly' .OR. (nmonth == 12 .AND. llnxtmth) ! open next year file? 255 256 ! if the run finishes at the end of the current year/month/week/day, we will allow next 257 ! year/month/week/day file to be not present. If the run continue further than the current 258 ! year/month/week/day, next year/month/week/day file must exist 259 isecend = nsec_year + nsec1jan000 + (nitend - kt) * NINT(rdt) ! second at the end of the run 260 llstop = isecend > sd(jf)%nrec_a(2) ! read more than 1 record of next year 261 ! we suppose that the date of next file is next day (should be ok even for weekly files...) 262 CALL fld_clopn( sd(jf), nyear + COUNT((/llnxtyr /)) , & 263 & nmonth + COUNT((/llnxtmth/)) - 12 * COUNT((/llnxtyr /)), & 264 & nday + 1 - nmonth_len(nmonth) * COUNT((/llnxtmth/)), llstop ) 265 266 IF( sd(jf)%num <= 0 .AND. .NOT. llstop ) THEN ! next year file does not exist 267 CALL ctl_warn('next year/month/week/day file: '//TRIM(sd(jf)%clname)// & 268 & ' not present -> back to current year/month/day') 269 CALL fld_clopn( sd(jf) ) ! back to the current year/month/day 270 sd(jf)%nrec_a(1) = sd(jf)%nreclast ! force to read the last record in the current year file 271 ENDIF 272 273 ENDIF 274 ENDIF ! open need next file? 275 276 ! read after data 277 CALL fld_get( sd(jf) ) 278 279 ENDIF ! read new data? 195 CALL fld_update( isecsbc, sd(jf), Kmm ) 196 ! 280 197 END DO ! --- end loop over field --- ! 281 198 … … 292 209 WRITE(numout, clfmt) TRIM( sd(jf)%clvar ), kt, REAL(isecsbc,wp)/rday, nyear, nmonth, nday, & 293 210 & sd(jf)%nrec_b(1), sd(jf)%nrec_a(1), REAL(sd(jf)%nrec_b(2),wp)/rday, REAL(sd(jf)%nrec_a(2),wp)/rday 294 WRITE(numout, *) ' it_offset is : ',it_offset211 WRITE(numout, *) ' zt_offset is : ',zt_offset 295 212 ENDIF 296 213 ! temporal interpolation weights … … 316 233 317 234 318 SUBROUTINE fld_init( k n_fsbc, sdjf )235 SUBROUTINE fld_init( ksecsbc, sdjf ) 319 236 !!--------------------------------------------------------------------- 320 237 !! *** ROUTINE fld_init *** 321 238 !! 322 !! ** Purpose : - first call to fld_recto define before values323 !! - if time interpolation, read before data324 !!---------------------------------------------------------------------- 325 INTEGER , INTENT(in ) :: k n_fsbc ! sbc computation period (in time step)239 !! ** Purpose : - first call(s) to fld_def to define before values 240 !! - open file 241 !!---------------------------------------------------------------------- 242 INTEGER , INTENT(in ) :: ksecsbc ! 326 243 TYPE(FLD), INTENT(inout) :: sdjf ! input field related variables 327 !! 328 LOGICAL :: llprevyr ! are we reading previous year file? 329 LOGICAL :: llprevmth ! are we reading previous month file? 330 LOGICAL :: llprevweek ! are we reading previous week file? 331 LOGICAL :: llprevday ! are we reading previous day file? 332 LOGICAL :: llprev ! llprevyr .OR. llprevmth .OR. llprevweek .OR. llprevday 333 INTEGER :: idvar ! variable id 334 INTEGER :: inrec ! number of record existing for this variable 335 INTEGER :: iyear, imonth, iday ! first day of the current file in yyyy mm dd 336 INTEGER :: isec_week ! number of seconds since start of the weekly file 337 CHARACTER(LEN=1000) :: clfmt ! write format 338 !!--------------------------------------------------------------------- 339 ! 340 llprevyr = .FALSE. 341 llprevmth = .FALSE. 342 llprevweek = .FALSE. 343 llprevday = .FALSE. 344 isec_week = 0 345 ! 346 ! define record informations 347 CALL fld_rec( kn_fsbc, sdjf, ldbefore = .TRUE. ) ! return before values in sdjf%nrec_a (as we will swap it later) 348 ! 349 ! Note that shifting time to be centrered in the middle of sbc time step impacts only nsec_* variables of the calendar 350 ! 351 IF( sdjf%ln_tint ) THEN ! we need to read the previous record and we will put it in the current record structure 352 ! 353 IF( sdjf%nrec_a(1) == 0 ) THEN ! we redefine record sdjf%nrec_a(1) with the last record of previous year file 354 IF ( NINT(sdjf%freqh) == -12 ) THEN ! yearly mean 355 IF( sdjf%cltype == 'yearly' ) THEN ! yearly file 356 sdjf%nrec_a(1) = 1 ! force to read the unique record 357 llprevyr = .NOT. sdjf%ln_clim ! use previous year file? 358 ELSE 359 CALL ctl_stop( "fld_init: yearly mean file must be in a yearly type of file: "//TRIM(sdjf%clrootname) ) 360 ENDIF 361 ELSEIF( NINT(sdjf%freqh) == -1 ) THEN ! monthly mean 362 IF( sdjf%cltype == 'monthly' ) THEN ! monthly file 363 sdjf%nrec_a(1) = 1 ! force to read the unique record 364 llprevmth = .TRUE. ! use previous month file? 365 llprevyr = llprevmth .AND. nmonth == 1 ! use previous year file? 366 ELSE ! yearly file 367 sdjf%nrec_a(1) = 12 ! force to read december mean 368 llprevyr = .NOT. sdjf%ln_clim ! use previous year file? 369 ENDIF 370 ELSE ! higher frequency mean (in hours) 371 IF ( sdjf%cltype == 'monthly' ) THEN ! monthly file 372 sdjf%nrec_a(1) = NINT( 24. * REAL(nmonth_len(nmonth-1),wp) / sdjf%freqh )! last record of previous month 373 llprevmth = .TRUE. ! use previous month file? 374 llprevyr = llprevmth .AND. nmonth == 1 ! use previous year file? 375 ELSEIF( sdjf%cltype(1:4) == 'week' ) THEN ! weekly file 376 llprevweek = .TRUE. ! use previous week file? 377 sdjf%nrec_a(1) = NINT( 24. * 7. / sdjf%freqh ) ! last record of previous week 378 isec_week = NINT(rday) * 7 ! add a shift toward previous week 379 ELSEIF( sdjf%cltype == 'daily' ) THEN ! daily file 380 sdjf%nrec_a(1) = NINT( 24. / sdjf%freqh ) ! last record of previous day 381 llprevday = .TRUE. ! use previous day file? 382 llprevmth = llprevday .AND. nday == 1 ! use previous month file? 383 llprevyr = llprevmth .AND. nmonth == 1 ! use previous year file? 384 ELSE ! yearly file 385 sdjf%nrec_a(1) = NINT( 24. * REAL(nyear_len(0),wp) / sdjf%freqh ) ! last record of previous year 386 llprevyr = .NOT. sdjf%ln_clim ! use previous year file? 387 ENDIF 388 ENDIF 389 ENDIF 390 ! 391 IF ( sdjf%cltype(1:4) == 'week' ) THEN 392 isec_week = isec_week + ksec_week( sdjf%cltype(6:8) ) ! second since the beginning of the week 393 llprevmth = isec_week > nsec_month ! longer time since the beginning of the week than the month 394 llprevyr = llprevmth .AND. nmonth == 1 395 ENDIF 396 llprev = llprevyr .OR. llprevmth .OR. llprevweek .OR. llprevday 397 ! 398 iyear = nyear - COUNT((/llprevyr /)) 399 imonth = nmonth - COUNT((/llprevmth/)) + 12 * COUNT((/llprevyr /)) 400 iday = nday - COUNT((/llprevday/)) + nmonth_len(nmonth-1) * COUNT((/llprevmth/)) - isec_week / NINT(rday) 401 ! 402 CALL fld_clopn( sdjf, iyear, imonth, iday, .NOT. llprev ) 403 ! 404 ! if previous year/month/day file does not exist, we switch to the current year/month/day 405 IF( llprev .AND. sdjf%num <= 0 ) THEN 406 CALL ctl_warn( 'previous year/month/week/day file: '//TRIM(sdjf%clrootname)// & 407 & ' not present -> back to current year/month/week/day' ) 408 ! we force to read the first record of the current year/month/day instead of last record of previous year/month/day 409 llprev = .FALSE. 410 sdjf%nrec_a(1) = 1 411 CALL fld_clopn( sdjf ) 412 ENDIF 413 ! 414 IF( llprev ) THEN ! check if the record sdjf%nrec_a(1) exists in the file 415 idvar = iom_varid( sdjf%num, sdjf%clvar ) ! id of the variable sdjf%clvar 416 IF( idvar <= 0 ) RETURN 417 inrec = iom_file( sdjf%num )%dimsz( iom_file( sdjf%num )%ndims(idvar), idvar ) ! size of the last dim of idvar 418 sdjf%nrec_a(1) = MIN( sdjf%nrec_a(1), inrec ) ! make sure we select an existing record 419 ENDIF 420 ! 421 ! read before data in after arrays(as we will swap it later) 422 CALL fld_get( sdjf ) 423 ! 424 clfmt = "(' fld_init : time-interpolation for ', a, ' read previous record = ', i6, ' at time = ', f7.2, ' days')" 425 IF(lwp) WRITE(numout, clfmt) TRIM(sdjf%clvar), sdjf%nrec_a(1), REAL(sdjf%nrec_a(2),wp)/rday 426 ! 427 ENDIF 244 !!--------------------------------------------------------------------- 245 ! 246 IF( nflag == 0 ) nflag = -( HUGE(0) - 10 ) 247 ! 248 CALL fld_def( sdjf ) 249 IF( sdjf%ln_tint .AND. ksecsbc < sdjf%nrecsec(1) ) CALL fld_def( sdjf, ldprev = .TRUE. ) 250 ! 251 CALL fld_clopn( sdjf ) 252 sdjf%nrec_a(:) = (/ 1, nflag /) ! default definition to force flp_update to read the file. 428 253 ! 429 254 END SUBROUTINE fld_init 430 255 431 256 432 SUBROUTINE fld_ rec( kn_fsbc, sdjf, ldbefore, kit, kt_offset)433 !!--------------------------------------------------------------------- 434 !! *** ROUTINE fld_ rec***257 SUBROUTINE fld_update( ksecsbc, sdjf, Kmm ) 258 !!--------------------------------------------------------------------- 259 !! *** ROUTINE fld_update *** 435 260 !! 436 261 !! ** Purpose : Compute … … 441 266 !! nrec_b(2) and nrec_a(2): time of the beginning and end of the record 442 267 !!---------------------------------------------------------------------- 443 INTEGER , INTENT(in ) :: kn_fsbc ! sbc computation period (in time step) 444 TYPE(FLD), INTENT(inout) :: sdjf ! input field related variables 445 LOGICAL , INTENT(in ), OPTIONAL :: ldbefore ! sent back before record values (default = .FALSE.) 446 INTEGER , INTENT(in ), OPTIONAL :: kit ! index of barotropic subcycle 447 ! ! used only if sdjf%ln_tint = .TRUE. 448 INTEGER , INTENT(in ), OPTIONAL :: kt_offset ! Offset of required time level compared to "now" 449 ! ! time level in units of time steps. 450 ! 451 LOGICAL :: llbefore ! local definition of ldbefore 452 INTEGER :: iendrec ! end of this record (in seconds) 453 INTEGER :: imth ! month number 454 INTEGER :: ifreq_sec ! frequency mean (in seconds) 455 INTEGER :: isec_week ! number of seconds since the start of the weekly file 456 INTEGER :: it_offset ! local time offset variable 457 REAL(wp) :: ztmp ! temporary variable 458 !!---------------------------------------------------------------------- 459 ! 460 ! Note that shifting time to be centrered in the middle of sbc time step impacts only nsec_* variables of the calendar 461 ! 462 IF( PRESENT(ldbefore) ) THEN ; llbefore = ldbefore .AND. sdjf%ln_tint ! needed only if sdjf%ln_tint = .TRUE. 463 ELSE ; llbefore = .FALSE. 464 ENDIF 465 ! 466 IF ( nn_components == jp_iam_sas ) THEN ; it_offset = nn_fsbc 467 ELSE ; it_offset = 0 468 ENDIF 469 IF( PRESENT(kt_offset) ) it_offset = kt_offset 470 IF( PRESENT(kit) ) THEN ; it_offset = ( kit + it_offset ) * NINT( rdt/REAL(nn_baro,wp) ) 471 ELSE ; it_offset = it_offset * NINT( rdt ) 472 ENDIF 473 ! 474 ! ! =========== ! 475 IF ( NINT(sdjf%freqh) == -12 ) THEN ! yearly mean 476 ! ! =========== ! 477 ! 478 IF( sdjf%ln_tint ) THEN ! time interpolation, shift by 1/2 record 479 ! 480 ! INT( ztmp ) 481 ! /|\ 482 ! 1 | *---- 483 ! 0 |----( 484 ! |----+----|--> time 485 ! 0 /|\ 1 (nday/nyear_len(1)) 486 ! | 487 ! | 488 ! forcing record : 1 489 ! 490 ztmp = REAL( nsec_year, wp ) / ( REAL( nyear_len(1), wp ) * rday ) + 0.5 & 491 & + REAL( it_offset, wp ) / ( REAL( nyear_len(1), wp ) * rday ) 492 sdjf%nrec_a(1) = 1 + INT( ztmp ) - COUNT((/llbefore/)) 493 ! swap at the middle of the year 494 IF( llbefore ) THEN ; sdjf%nrec_a(2) = nsec1jan000 - (1 - INT(ztmp)) * NINT(0.5 * rday) * nyear_len(0) + & 495 & INT(ztmp) * NINT( 0.5 * rday) * nyear_len(1) 496 ELSE ; sdjf%nrec_a(2) = nsec1jan000 + (1 - INT(ztmp)) * NINT(0.5 * rday) * nyear_len(1) + & 497 & INT(ztmp) * INT(rday) * nyear_len(1) + INT(ztmp) * NINT( 0.5 * rday) * nyear_len(2) 268 INTEGER , INTENT(in ) :: ksecsbc ! 269 TYPE(FLD), INTENT(inout) :: sdjf ! input field related variables 270 INTEGER , OPTIONAL, INTENT(in ) :: Kmm ! ocean time level index 271 ! 272 INTEGER :: ja ! end of this record (in seconds) 273 !!---------------------------------------------------------------------- 274 ! 275 IF( ksecsbc > sdjf%nrec_a(2) ) THEN ! --> we need to update after data 276 277 ! find where is the new after record... (it is not necessary sdjf%nrec_a(1)+1 ) 278 ja = sdjf%nrec_a(1) 279 DO WHILE ( ksecsbc >= sdjf%nrecsec(ja) .AND. ja < sdjf%nreclast ) ! Warning: make sure ja <= sdjf%nreclast in this test 280 ja = ja + 1 281 END DO 282 IF( ksecsbc > sdjf%nrecsec(ja) ) ja = ja + 1 ! in case ksecsbc > sdjf%nrecsec(sdjf%nreclast) 283 284 ! if ln_tint and if the new after is not ja+1, we need also to update after data before the swap 285 ! so, after the swap, sdjf%nrec_b(2) will still be the closest value located just before ksecsbc 286 IF( sdjf%ln_tint .AND. ( ja > sdjf%nrec_a(1) + 1 .OR. sdjf%nrec_a(2) == nflag ) ) THEN 287 sdjf%nrec_a(:) = (/ ja-1, sdjf%nrecsec(ja-1) /) ! update nrec_a with before information 288 CALL fld_get( sdjf, Kmm ) ! read after data that will be used as before data 289 ENDIF 290 291 ! if after is in the next file... 292 IF( ja > sdjf%nreclast ) THEN 293 294 CALL fld_def( sdjf ) 295 IF( ksecsbc > sdjf%nrecsec(sdjf%nreclast) ) CALL fld_def( sdjf, ldnext = .TRUE. ) 296 CALL fld_clopn( sdjf ) ! open next file 297 298 ! find where is after in this new file 299 ja = 1 300 DO WHILE ( ksecsbc > sdjf%nrecsec(ja) .AND. ja < sdjf%nreclast ) 301 ja = ja + 1 302 END DO 303 IF( ksecsbc > sdjf%nrecsec(ja) ) ja = ja + 1 ! in case ksecsbc > sdjf%nrecsec(sdjf%nreclast) 304 305 IF( ja > sdjf%nreclast ) THEN 306 CALL ctl_stop( "STOP", "fld_def: need next-next file? we should not be there... file: "//TRIM(sdjf%clrootname) ) 498 307 ENDIF 499 ELSE ! no time interpolation 500 sdjf%nrec_a(1) = 1 501 sdjf%nrec_a(2) = NINT(rday) * nyear_len(1) + nsec1jan000 ! swap at the end of the year 502 sdjf%nrec_b(2) = nsec1jan000 ! beginning of the year (only for print) 503 ENDIF 504 ! 505 ! ! ============ ! 506 ELSEIF( NINT(sdjf%freqh) == -1 ) THEN ! monthly mean ! 507 ! ! ============ ! 508 ! 509 IF( sdjf%ln_tint ) THEN ! time interpolation, shift by 1/2 record 510 ! 511 ! INT( ztmp ) 512 ! /|\ 513 ! 1 | *---- 514 ! 0 |----( 515 ! |----+----|--> time 516 ! 0 /|\ 1 (nday/nmonth_len(nmonth)) 517 ! | 518 ! | 519 ! forcing record : nmonth 520 ! 521 ztmp = REAL( nsec_month, wp ) / ( REAL( nmonth_len(nmonth), wp ) * rday ) + 0.5 & 522 & + REAL( it_offset, wp ) / ( REAL( nmonth_len(nmonth), wp ) * rday ) 523 imth = nmonth + INT( ztmp ) - COUNT((/llbefore/)) 524 IF( sdjf%cltype == 'monthly' ) THEN ; sdjf%nrec_a(1) = 1 + INT( ztmp ) - COUNT((/llbefore/)) 525 ELSE ; sdjf%nrec_a(1) = imth 308 309 ! if ln_tint and if after is not the first record, we must (potentially again) update after data before the swap 310 IF( sdjf%ln_tint .AND. ja > 1 ) THEN 311 IF( sdjf%nrecsec(0) /= nflag ) THEN ! no trick used: after file is not the current file 312 sdjf%nrec_a(:) = (/ ja-1, sdjf%nrecsec(ja-1) /) ! update nrec_a with before information 313 CALL fld_get( sdjf, Kmm ) ! read after data that will be used as before data 314 ENDIF 526 315 ENDIF 527 sdjf%nrec_a(2) = nmonth_half( imth ) + nsec1jan000 ! swap at the middle of the month 528 ELSE ! no time interpolation 529 IF( sdjf%cltype == 'monthly' ) THEN ; sdjf%nrec_a(1) = 1 530 ELSE ; sdjf%nrec_a(1) = nmonth 531 ENDIF 532 sdjf%nrec_a(2) = nmonth_end(nmonth ) + nsec1jan000 ! swap at the end of the month 533 sdjf%nrec_b(2) = nmonth_end(nmonth-1) + nsec1jan000 ! beginning of the month (only for print) 534 ENDIF 535 ! 536 ! ! ================================ ! 537 ELSE ! higher frequency mean (in hours) 538 ! ! ================================ ! 539 ! 540 ifreq_sec = NINT( sdjf%freqh * 3600. ) ! frequency mean (in seconds) 541 IF( sdjf%cltype(1:4) == 'week' ) isec_week = ksec_week( sdjf%cltype(6:8) ) ! since the first day of the current week 542 ! number of second since the beginning of the file 543 IF( sdjf%cltype == 'monthly' ) THEN ; ztmp = REAL(nsec_month,wp) ! since the first day of the current month 544 ELSEIF( sdjf%cltype(1:4) == 'week' ) THEN ; ztmp = REAL(isec_week ,wp) ! since the first day of the current week 545 ELSEIF( sdjf%cltype == 'daily' ) THEN ; ztmp = REAL(nsec_day ,wp) ! since 00h of the current day 546 ELSE ; ztmp = REAL(nsec_year ,wp) ! since 00h on Jan 1 of the current year 547 ENDIF 548 ztmp = ztmp + 0.5 * REAL(kn_fsbc - 1, wp) * rdt + REAL( it_offset, wp ) ! centrered in the middle of sbc time step 549 ztmp = ztmp + 0.01 * rdt ! avoid truncation error 550 IF( sdjf%ln_tint ) THEN ! time interpolation, shift by 1/2 record 551 ! 552 ! INT( ztmp/ifreq_sec + 0.5 ) 553 ! /|\ 554 ! 2 | *-----( 555 ! 1 | *-----( 556 ! 0 |--( 557 ! |--+--|--+--|--+--|--> time 558 ! 0 /|\ 1 /|\ 2 /|\ 3 (ztmp/ifreq_sec) 559 ! | | | 560 ! | | | 561 ! forcing record : 1 2 3 562 ! 563 ztmp= ztmp / REAL(ifreq_sec, wp) + 0.5 564 ELSE ! no time interpolation 565 ! 566 ! INT( ztmp/ifreq_sec ) 567 ! /|\ 568 ! 2 | *-----( 569 ! 1 | *-----( 570 ! 0 |-----( 571 ! |--+--|--+--|--+--|--> time 572 ! 0 /|\ 1 /|\ 2 /|\ 3 (ztmp/ifreq_sec) 573 ! | | | 574 ! | | | 575 ! forcing record : 1 2 3 576 ! 577 ztmp= ztmp / REAL(ifreq_sec, wp) 578 ENDIF 579 sdjf%nrec_a(1) = 1 + INT( ztmp ) - COUNT((/llbefore/)) ! record number to be read 580 581 iendrec = ifreq_sec * sdjf%nrec_a(1) + nsec1jan000 ! end of this record (in second) 582 ! add the number of seconds between 00h Jan 1 and the end of previous month/week/day (ok if nmonth=1) 583 IF( sdjf%cltype == 'monthly' ) iendrec = iendrec + NINT(rday) * SUM(nmonth_len(1:nmonth -1)) 584 IF( sdjf%cltype(1:4) == 'week' ) iendrec = iendrec + ( nsec_year - isec_week ) 585 IF( sdjf%cltype == 'daily' ) iendrec = iendrec + NINT(rday) * ( nday_year - 1 ) 586 IF( sdjf%ln_tint ) THEN 587 sdjf%nrec_a(2) = iendrec - ifreq_sec / 2 ! swap at the middle of the record 316 317 ENDIF 318 319 IF( sdjf%ln_tint ) THEN 320 ! Swap data 321 sdjf%nrec_b(:) = sdjf%nrec_a(:) ! swap before record informations 322 sdjf%rotn(1) = sdjf%rotn(2) ! swap before rotate informations 323 sdjf%fdta(:,:,:,1) = sdjf%fdta(:,:,:,2) ! swap before record field 588 324 ELSE 589 sdjf%nrec_a(2) = iendrec ! swap at the end of the record 590 sdjf%nrec_b(2) = iendrec - ifreq_sec ! beginning of the record (only for print) 591 ENDIF 592 ! 593 ENDIF 594 ! 595 IF( .NOT. sdjf%ln_tint ) sdjf%nrec_a(2) = sdjf%nrec_a(2) - 1 ! last second belongs to bext record : *----( 596 ! 597 END SUBROUTINE fld_rec 598 599 600 SUBROUTINE fld_get( sdjf ) 325 sdjf%nrec_b(:) = (/ ja-1, sdjf%nrecsec(ja-1) /) ! only for print 326 ENDIF 327 328 ! read new after data 329 sdjf%nrec_a(:) = (/ ja, sdjf%nrecsec(ja) /) ! update nrec_a as it is used by fld_get 330 CALL fld_get( sdjf, Kmm ) ! read after data (with nrec_a informations) 331 332 ENDIF 333 ! 334 END SUBROUTINE fld_update 335 336 337 SUBROUTINE fld_get( sdjf, Kmm ) 601 338 !!--------------------------------------------------------------------- 602 339 !! *** ROUTINE fld_get *** … … 604 341 !! ** Purpose : read the data 605 342 !!---------------------------------------------------------------------- 606 TYPE(FLD) , INTENT(inout) :: sdjf ! input field related variables 343 TYPE(FLD), INTENT(inout) :: sdjf ! input field related variables 344 INTEGER , OPTIONAL, INTENT(in ) :: Kmm ! ocean time level index 607 345 ! 608 346 INTEGER :: ipk ! number of vertical levels of sdjf%fdta ( 2D: ipk=1 ; 3D: ipk=jpk ) … … 618 356 IF( ASSOCIATED(sdjf%imap) ) THEN 619 357 IF( sdjf%ln_tint ) THEN ; CALL fld_map( sdjf%num, sdjf%clvar, sdjf%fdta(:,:,:,2), sdjf%nrec_a(1), & 620 & sdjf%imap, sdjf%igrd, sdjf%ibdy, sdjf%ltotvel, sdjf%lzint )358 & sdjf%imap, sdjf%igrd, sdjf%ibdy, sdjf%ltotvel, sdjf%lzint, Kmm ) 621 359 ELSE ; CALL fld_map( sdjf%num, sdjf%clvar, sdjf%fnow(:,:,: ), sdjf%nrec_a(1), & 622 & sdjf%imap, sdjf%igrd, sdjf%ibdy, sdjf%ltotvel, sdjf%lzint )360 & sdjf%imap, sdjf%igrd, sdjf%ibdy, sdjf%ltotvel, sdjf%lzint, Kmm ) 623 361 ENDIF 624 362 ELSE IF( LEN(TRIM(sdjf%wgtname)) > 0 ) THEN … … 656 394 ENDIF 657 395 CASE DEFAULT 658 IF 396 IF(lk_c1d .AND. lmoor ) THEN 659 397 IF( sdjf%ln_tint ) THEN 660 398 CALL iom_get( sdjf%num, jpdom_unknown, sdjf%clvar, sdjf%fdta(2,2,:,2), sdjf%nrec_a(1) ) … … 677 415 678 416 679 SUBROUTINE fld_map( knum, cdvar, pdta, krec, kmap, kgrd, kbdy, ldtotvel, ldzint )417 SUBROUTINE fld_map( knum, cdvar, pdta, krec, kmap, kgrd, kbdy, ldtotvel, ldzint, Kmm ) 680 418 !!--------------------------------------------------------------------- 681 419 !! *** ROUTINE fld_map *** … … 694 432 LOGICAL, OPTIONAL , INTENT(in ) :: ldtotvel ! true if total ( = barotrop + barocline) velocity 695 433 LOGICAL, OPTIONAL , INTENT(in ) :: ldzint ! true if 3D variable requires a vertical interpolation 434 INTEGER, OPTIONAL , INTENT(in ) :: Kmm ! ocean time level index 696 435 !! 697 436 INTEGER :: ipi ! length of boundary data on local process … … 758 497 759 498 CALL iom_getatt(knum, '_FillValue', zfv, cdvar=cdvar ) 760 CALL fld_bdy_interp(zdta_read, zdta_read_z, zdta_read_dz, pdta, kgrd, kbdy, zfv, ldtotvel )499 CALL fld_bdy_interp(zdta_read, zdta_read_z, zdta_read_dz, pdta, kgrd, kbdy, zfv, ldtotvel, Kmm) 761 500 DEALLOCATE( zdta_read, zdta_read_z, zdta_read_dz ) 762 501 … … 822 561 END SUBROUTINE fld_map_core 823 562 824 825 SUBROUTINE fld_bdy_interp(pdta_read, pdta_read_z, pdta_read_dz, pdta, kgrd, kbdy, pfv, ldtotvel) 563 SUBROUTINE fld_bdy_interp(pdta_read, pdta_read_z, pdta_read_dz, pdta, kgrd, kbdy, pfv, ldtotvel, Kmm ) 826 564 !!--------------------------------------------------------------------- 827 565 !! *** ROUTINE fld_bdy_interp *** … … 840 578 INTEGER , INTENT(in ) :: kgrd ! grid type (t, u, v) 841 579 INTEGER , INTENT(in ) :: kbdy ! bdy number 580 INTEGER, OPTIONAL , INTENT(in ) :: Kmm ! ocean time level index 842 581 !! 843 582 INTEGER :: ipi ! length of boundary data on local process … … 866 605 SELECT CASE( kgrd ) 867 606 CASE(1) ! depth of T points: 868 zdepth(:) = gdept _n(ji,jj,:)607 zdepth(:) = gdept(ji,jj,:,Kmm) 869 608 CASE(2) ! depth of U points: we must not use gdept_n as we don't want to do a communication 870 609 ! --> copy what is done for gdept_n in domvvl... 871 610 zdhalf(1) = 0.0_wp 872 zdepth(1) = 0.5_wp * e3uw _n(ji,jj,1)611 zdepth(1) = 0.5_wp * e3uw(ji,jj,1,Kmm) 873 612 DO jk = 2, jpk ! vertical sum 874 613 ! zcoef = umask - wumask ! 0 everywhere tmask = wmask, ie everywhere expect at jk = mikt … … 877 616 !!gm ??????? BUG ? gdept_n as well as gde3w_n does not include the thickness of ISF ?? 878 617 zcoef = ( umask(ji,jj,jk) - wumask(ji,jj,jk) ) 879 zdhalf(jk) = zdhalf(jk-1) + e3u _n(ji,jj,jk-1)880 zdepth(jk) = zcoef * ( zdhalf(jk ) + 0.5 * e3uw_n(ji,jj,jk)) &881 & + (1. -zcoef) * ( zdepth(jk-1) + e3uw_n(ji,jj,jk))618 zdhalf(jk) = zdhalf(jk-1) + e3u(ji,jj,jk-1,Kmm) 619 zdepth(jk) = zcoef * ( zdhalf(jk ) + 0.5_wp * e3uw(ji,jj,jk,Kmm)) & 620 & + (1._wp-zcoef) * ( zdepth(jk-1) + e3uw(ji,jj,jk,Kmm)) 882 621 END DO 883 622 CASE(3) ! depth of V points: we must not use gdept_n as we don't want to do a communication 884 623 ! --> copy what is done for gdept_n in domvvl... 885 624 zdhalf(1) = 0.0_wp 886 zdepth(1) = 0.5_wp * e3vw _n(ji,jj,1)625 zdepth(1) = 0.5_wp * e3vw(ji,jj,1,Kmm) 887 626 DO jk = 2, jpk ! vertical sum 888 627 ! zcoef = vmask - wvmask ! 0 everywhere tmask = wmask, ie everywhere expect at jk = mikt … … 891 630 !!gm ??????? BUG ? gdept_n as well as gde3w_n does not include the thickness of ISF ?? 892 631 zcoef = ( vmask(ji,jj,jk) - wvmask(ji,jj,jk) ) 893 zdhalf(jk) = zdhalf(jk-1) + e3v _n(ji,jj,jk-1)894 zdepth(jk) = zcoef * ( zdhalf(jk ) + 0.5 * e3vw_n(ji,jj,jk)) &895 & + (1. -zcoef) * ( zdepth(jk-1) + e3vw_n(ji,jj,jk))632 zdhalf(jk) = zdhalf(jk-1) + e3v(ji,jj,jk-1,Kmm) 633 zdepth(jk) = zcoef * ( zdhalf(jk ) + 0.5_wp * e3vw(ji,jj,jk,Kmm)) & 634 & + (1._wp-zcoef) * ( zdepth(jk-1) + e3vw(ji,jj,jk,Kmm)) 896 635 END DO 897 636 END SELECT … … 911 650 END DO 912 651 ENDIF 913 END DO 652 END DO ! jpk 914 653 ! 915 654 END DO ! ipi … … 937 676 ztrans_new = 0._wp 938 677 DO jk = 1, jpk ! calculate transport on model grid 939 ztrans_new = ztrans_new + pdta(jb,1,jk ) * e3u_n(ji,jj,jk) * umask(ji,jj,jk)678 ztrans_new = ztrans_new + pdta(jb,1,jk ) * e3u(ji,jj,jk,Kmm ) * umask(ji,jj,jk) 940 679 ENDDO 941 680 DO jk = 1, jpk ! make transport correction 942 681 IF(ldtotvel) THEN ! bdy data are total velocity so adjust bt transport term to match input data 943 pdta(jb,1,jk) = ( pdta(jb,1,jk) + ( ztrans - ztrans_new ) * r1_hu _n(ji,jj) ) * umask(ji,jj,jk)682 pdta(jb,1,jk) = ( pdta(jb,1,jk) + ( ztrans - ztrans_new ) * r1_hu(ji,jj,Kmm) ) * umask(ji,jj,jk) 944 683 ELSE ! we're just dealing with bc velocity so bt transport term should sum to zero 945 pdta(jb,1,jk) = ( pdta(jb,1,jk) + ( 0._wp - ztrans_new ) * r1_hu_n(ji,jj) )* umask(ji,jj,jk)684 pdta(jb,1,jk) = pdta(jb,1,jk) + ( 0._wp - ztrans_new ) * r1_hu(ji,jj,Kmm) * umask(ji,jj,jk) 946 685 ENDIF 947 686 ENDDO … … 958 697 ztrans_new = 0._wp 959 698 DO jk = 1, jpk ! calculate transport on model grid 960 ztrans_new = ztrans_new + pdta(jb,1,jk ) * e3v_n(ji,jj,jk) * vmask(ji,jj,jk)699 ztrans_new = ztrans_new + pdta(jb,1,jk ) * e3v(ji,jj,jk,Kmm ) * vmask(ji,jj,jk) 961 700 ENDDO 962 701 DO jk = 1, jpk ! make transport correction 963 702 IF(ldtotvel) THEN ! bdy data are total velocity so adjust bt transport term to match input data 964 pdta(jb,1,jk) = ( pdta(jb,1,jk) + ( ztrans - ztrans_new ) * r1_hv _n(ji,jj) ) * vmask(ji,jj,jk)703 pdta(jb,1,jk) = ( pdta(jb,1,jk) + ( ztrans - ztrans_new ) * r1_hv(ji,jj,Kmm) ) * vmask(ji,jj,jk) 965 704 ELSE ! we're just dealing with bc velocity so bt transport term should sum to zero 966 pdta(jb,1,jk) = ( pdta(jb,1,jk) + ( 0._wp - ztrans_new ) * r1_hv_n(ji,jj) )* vmask(ji,jj,jk)705 pdta(jb,1,jk) = pdta(jb,1,jk) + ( 0._wp - ztrans_new ) * r1_hv(ji,jj,Kmm) * vmask(ji,jj,jk) 967 706 ENDIF 968 707 ENDDO 969 708 ENDDO 970 709 END SELECT 971 710 972 711 END SUBROUTINE fld_bdy_interp 973 712 974 713 975 714 SUBROUTINE fld_rot( kt, sd ) 976 715 !!--------------------------------------------------------------------- … … 1013 752 sd(ju)%fdta(:,:,jk,jn) = utmp(:,:) ; sd(iv)%fdta(:,:,jk,jn) = vtmp(:,:) 1014 753 ELSE 1015 CALL rot_rep( sd(ju)%fnow(:,:,jk ), sd(iv)%fnow(:,:,jk), 'T', 'en->i', utmp(:,:) )1016 CALL rot_rep( sd(ju)%fnow(:,:,jk ), sd(iv)%fnow(:,:,jk), 'T', 'en->j', vtmp(:,:) )754 CALL rot_rep( sd(ju)%fnow(:,:,jk ), sd(iv)%fnow(:,:,jk ), 'T', 'en->i', utmp(:,:) ) 755 CALL rot_rep( sd(ju)%fnow(:,:,jk ), sd(iv)%fnow(:,:,jk ), 'T', 'en->j', vtmp(:,:) ) 1017 756 sd(ju)%fnow(:,:,jk ) = utmp(:,:) ; sd(iv)%fnow(:,:,jk ) = vtmp(:,:) 1018 757 ENDIF … … 1030 769 1031 770 1032 SUBROUTINE fld_clopn( sdjf, kyear, kmonth, kday, ldstop ) 771 SUBROUTINE fld_def( sdjf, ldprev, ldnext ) 772 !!--------------------------------------------------------------------- 773 !! *** ROUTINE fld_def *** 774 !! 775 !! ** Purpose : define the record(s) of the file and its name 776 !!---------------------------------------------------------------------- 777 TYPE(FLD) , INTENT(inout) :: sdjf ! input field related variables 778 LOGICAL, OPTIONAL, INTENT(in ) :: ldprev ! 779 LOGICAL, OPTIONAL, INTENT(in ) :: ldnext ! 780 ! 781 INTEGER :: jt 782 INTEGER :: idaysec ! number of seconds in 1 day = NINT(rday) 783 INTEGER :: iyr, imt, idy, isecwk 784 INTEGER :: indexyr, indexmt 785 INTEGER :: ireclast 786 INTEGER :: ishift, istart 787 INTEGER, DIMENSION(2) :: isave 788 REAL(wp) :: zfreqs 789 LOGICAL :: llprev, llnext, llstop 790 LOGICAL :: llprevmt, llprevyr 791 LOGICAL :: llnextmt, llnextyr 792 !!---------------------------------------------------------------------- 793 idaysec = NINT(rday) 794 ! 795 IF( PRESENT(ldprev) ) THEN ; llprev = ldprev 796 ELSE ; llprev = .FALSE. 797 ENDIF 798 IF( PRESENT(ldnext) ) THEN ; llnext = ldnext 799 ELSE ; llnext = .FALSE. 800 ENDIF 801 802 ! current file parameters 803 IF( sdjf%cltype(1:4) == 'week' ) THEN ! find the day of the beginning of the current week 804 isecwk = ksec_week( sdjf%cltype(6:8) ) ! seconds between the beginning of the week and half of current time step 805 llprevmt = isecwk > nsec_month ! longer time since beginning of the current week than the current month 806 llprevyr = llprevmt .AND. nmonth == 1 807 iyr = nyear - COUNT((/llprevyr/)) 808 imt = nmonth - COUNT((/llprevmt/)) + 12 * COUNT((/llprevyr/)) 809 idy = nday + nmonth_len(nmonth-1) * COUNT((/llprevmt/)) - isecwk / idaysec 810 isecwk = nsec_year - isecwk ! seconds between 00h jan 1st of current year and current week beginning 811 ELSE 812 iyr = nyear 813 imt = nmonth 814 idy = nday 815 isecwk = 0 816 ENDIF 817 818 ! previous file parameters 819 IF( llprev ) THEN 820 IF( sdjf%cltype(1:4) == 'week' ) THEN ! find the day of the beginning of previous week 821 isecwk = isecwk + 7 * idaysec ! seconds between the beginning of previous week and half of the time step 822 llprevmt = isecwk > nsec_month ! longer time since beginning of the previous week than the current month 823 llprevyr = llprevmt .AND. nmonth == 1 824 iyr = nyear - COUNT((/llprevyr/)) 825 imt = nmonth - COUNT((/llprevmt/)) + 12 * COUNT((/llprevyr/)) 826 idy = nday + nmonth_len(nmonth-1) * COUNT((/llprevmt/)) - isecwk / idaysec 827 isecwk = nsec_year - isecwk ! seconds between 00h jan 1st of current year and previous week beginning 828 ELSE 829 idy = nday - COUNT((/ sdjf%cltype == 'daily' /)) 830 imt = nmonth - COUNT((/ sdjf%cltype == 'monthly' .OR. idy == 0 /)) 831 iyr = nyear - COUNT((/ sdjf%cltype == 'yearly' .OR. imt == 0 /)) 832 IF( idy == 0 ) idy = nmonth_len(imt) 833 IF( imt == 0 ) imt = 12 834 isecwk = 0 835 ENDIF 836 ENDIF 837 838 ! next file parameters 839 IF( llnext ) THEN 840 IF( sdjf%cltype(1:4) == 'week' ) THEN ! find the day of the beginning of next week 841 isecwk = 7 * idaysec - isecwk ! seconds between half of the time step and the beginning of next week 842 llnextmt = isecwk > ( nmonth_len(nmonth)*idaysec - nsec_month ) ! larger than the seconds to the end of the month 843 llnextyr = llnextmt .AND. nmonth == 12 844 iyr = nyear + COUNT((/llnextyr/)) 845 imt = nmonth + COUNT((/llnextmt/)) - 12 * COUNT((/llnextyr/)) 846 idy = nday - nmonth_len(nmonth) * COUNT((/llnextmt/)) + isecwk / idaysec + 1 847 isecwk = nsec_year + isecwk ! seconds between 00h jan 1st of current year and next week beginning 848 ELSE 849 idy = nday + COUNT((/ sdjf%cltype == 'daily' /)) 850 imt = nmonth + COUNT((/ sdjf%cltype == 'monthly' .OR. idy > nmonth_len(nmonth) /)) 851 iyr = nyear + COUNT((/ sdjf%cltype == 'yearly' .OR. imt == 13 /)) 852 IF( idy > nmonth_len(nmonth) ) idy = 1 853 IF( imt == 13 ) imt = 1 854 isecwk = 0 855 ENDIF 856 ENDIF 857 ! 858 ! find the last record to be read -> update sdjf%nreclast 859 indexyr = iyr - nyear + 1 ! which year are we looking for? previous(0), current(1) or next(2)? 860 indexmt = imt + 12 * ( indexyr - 1 ) ! which month are we looking for (relatively to current year)? 861 ! 862 ! Last record to be read in the current file 863 ! Predefine the number of record in the file according of its type. 864 ! We could compare this number with the number of records in the file and make a stop if the 2 numbers do not match... 865 ! However this would be much less fexible (e.g. for tests) and will force to rewite input files according to nleapy... 866 IF ( NINT(sdjf%freqh) == -12 ) THEN ; ireclast = 1 ! yearly mean: consider only 1 record 867 ELSEIF( NINT(sdjf%freqh) == -1 ) THEN ! monthly mean: 868 IF( sdjf%cltype == 'monthly' ) THEN ; ireclast = 1 ! consider that the file has 1 record 869 ELSE ; ireclast = 12 ! consider that the file has 12 record 870 ENDIF 871 ELSE ! higher frequency mean (in hours) 872 IF( sdjf%cltype == 'monthly' ) THEN ; ireclast = NINT( 24. * REAL(nmonth_len(indexmt), wp) / sdjf%freqh ) 873 ELSEIF( sdjf%cltype(1:4) == 'week' ) THEN ; ireclast = NINT( 24. * 7. / sdjf%freqh ) 874 ELSEIF( sdjf%cltype == 'daily' ) THEN ; ireclast = NINT( 24. / sdjf%freqh ) 875 ELSE ; ireclast = NINT( 24. * REAL( nyear_len(indexyr), wp) / sdjf%freqh ) 876 ENDIF 877 ENDIF 878 879 sdjf%nreclast = ireclast 880 ! Allocate arrays for beginning/middle/end of each record (seconds since Jan. 1st 00h of nit000 year) 881 IF( ALLOCATED(sdjf%nrecsec) ) DEALLOCATE( sdjf%nrecsec ) 882 ALLOCATE( sdjf%nrecsec( 0:ireclast ) ) 883 ! 884 IF ( NINT(sdjf%freqh) == -12 ) THEN ! yearly mean and yearly file 885 SELECT CASE( indexyr ) 886 CASE(0) ; sdjf%nrecsec(0) = nsec1jan000 - nyear_len( 0 ) * idaysec 887 CASE(1) ; sdjf%nrecsec(0) = nsec1jan000 888 CASE(2) ; sdjf%nrecsec(0) = nsec1jan000 + nyear_len( 1 ) * idaysec 889 ENDSELECT 890 sdjf%nrecsec(1) = sdjf%nrecsec(0) + nyear_len( indexyr ) * idaysec 891 ELSEIF( NINT(sdjf%freqh) == -1 ) THEN ! monthly mean: 892 IF( sdjf%cltype == 'monthly' ) THEN ! monthly file 893 sdjf%nrecsec(0 ) = nsec1jan000 + nmonth_beg(indexmt ) 894 sdjf%nrecsec(1 ) = nsec1jan000 + nmonth_beg(indexmt+1) 895 ELSE ! yearly file 896 ishift = 12 * ( indexyr - 1 ) 897 sdjf%nrecsec(0:12) = nsec1jan000 + nmonth_beg(1+ishift:13+ishift) 898 ENDIF 899 ELSE ! higher frequency mean (in hours) 900 IF( sdjf%cltype == 'monthly' ) THEN ; istart = nsec1jan000 + nmonth_beg(indexmt) 901 ELSEIF( sdjf%cltype(1:4) == 'week' ) THEN ; istart = nsec1jan000 + isecwk 902 ELSEIF( sdjf%cltype == 'daily' ) THEN ; istart = nsec1jan000 + nmonth_beg(indexmt) + ( idy - 1 ) * idaysec 903 ELSEIF( indexyr == 0 ) THEN ; istart = nsec1jan000 - nyear_len( 0 ) * idaysec 904 ELSEIF( indexyr == 2 ) THEN ; istart = nsec1jan000 + nyear_len( 1 ) * idaysec 905 ELSE ; istart = nsec1jan000 906 ENDIF 907 zfreqs = sdjf%freqh * rhhmm * rmmss 908 DO jt = 0, sdjf%nreclast 909 sdjf%nrecsec(jt) = istart + NINT( zfreqs * REAL(jt,wp) ) 910 END DO 911 ENDIF 912 ! 913 IF( sdjf%ln_tint ) THEN ! record time defined in the middle of the record, computed using an implementation 914 ! of the rounded average that is valid over the full integer range 915 sdjf%nrecsec(1:sdjf%nreclast) = sdjf%nrecsec(0:sdjf%nreclast-1) / 2 + sdjf%nrecsec(1:sdjf%nreclast) / 2 + & 916 & MAX( MOD( sdjf%nrecsec(0:sdjf%nreclast-1), 2 ), MOD( sdjf%nrecsec(1:sdjf%nreclast), 2 ) ) 917 END IF 918 ! 919 sdjf%clname = fld_filename( sdjf, idy, imt, iyr ) 920 ! 921 END SUBROUTINE fld_def 922 923 924 SUBROUTINE fld_clopn( sdjf ) 1033 925 !!--------------------------------------------------------------------- 1034 926 !! *** ROUTINE fld_clopn *** 1035 927 !! 1036 !! ** Purpose : update the file name and close/open the files 1037 !!---------------------------------------------------------------------- 1038 TYPE(FLD) , INTENT(inout) :: sdjf ! input field related variables 1039 INTEGER, OPTIONAL, INTENT(in ) :: kyear ! year value 1040 INTEGER, OPTIONAL, INTENT(in ) :: kmonth ! month value 1041 INTEGER, OPTIONAL, INTENT(in ) :: kday ! day value 1042 LOGICAL, OPTIONAL, INTENT(in ) :: ldstop ! stop if open to read a non-existing file (default = .TRUE.) 1043 ! 1044 LOGICAL :: llprevyr ! are we reading previous year file? 1045 LOGICAL :: llprevmth ! are we reading previous month file? 1046 INTEGER :: iyear, imonth, iday ! first day of the current file in yyyy mm dd 1047 INTEGER :: isec_week ! number of seconds since start of the weekly file 1048 INTEGER :: indexyr ! year undex (O/1/2: previous/current/next) 1049 REAL(wp) :: zyear_len, zmonth_len ! length (days) of iyear and imonth ! 1050 CHARACTER(len = 256) :: clname ! temporary file name 1051 !!---------------------------------------------------------------------- 1052 IF( PRESENT(kyear) ) THEN ! use given values 1053 iyear = kyear 1054 imonth = kmonth 1055 iday = kday 1056 IF ( sdjf%cltype(1:4) == 'week' ) THEN ! find the day of the beginning of the week 1057 isec_week = ksec_week( sdjf%cltype(6:8) )- (86400 * 8 ) 1058 llprevmth = isec_week > nsec_month ! longer time since beginning of the week than the month 1059 llprevyr = llprevmth .AND. nmonth == 1 1060 iyear = nyear - COUNT((/llprevyr /)) 1061 imonth = nmonth - COUNT((/llprevmth/)) + 12 * COUNT((/llprevyr /)) 1062 iday = nday + nmonth_len(nmonth-1) * COUNT((/llprevmth/)) - isec_week / NINT(rday) 1063 ENDIF 1064 ELSE ! use current day values 1065 IF ( sdjf%cltype(1:4) == 'week' ) THEN ! find the day of the beginning of the week 1066 isec_week = ksec_week( sdjf%cltype(6:8) ) ! second since the beginning of the week 1067 llprevmth = isec_week > nsec_month ! longer time since beginning of the week than the month 1068 llprevyr = llprevmth .AND. nmonth == 1 1069 ELSE 1070 isec_week = 0 1071 llprevmth = .FALSE. 1072 llprevyr = .FALSE. 1073 ENDIF 1074 iyear = nyear - COUNT((/llprevyr /)) 1075 imonth = nmonth - COUNT((/llprevmth/)) + 12 * COUNT((/llprevyr /)) 1076 iday = nday + nmonth_len(nmonth-1) * COUNT((/llprevmth/)) - isec_week / NINT(rday) 1077 ENDIF 1078 1079 ! build the new filename if not climatological data 1080 clname=TRIM(sdjf%clrootname) 1081 ! 1082 ! note that sdjf%ln_clim is is only acting on the presence of the year in the file name 1083 IF( .NOT. sdjf%ln_clim ) THEN 1084 WRITE(clname, '(a,"_y",i4.4)' ) TRIM( sdjf%clrootname ), iyear ! add year 1085 IF( sdjf%cltype /= 'yearly' ) WRITE(clname, '(a,"m" ,i2.2)' ) TRIM( clname ), imonth ! add month 1086 ELSE 1087 ! build the new filename if climatological data 1088 IF( sdjf%cltype /= 'yearly' ) WRITE(clname, '(a,"_m",i2.2)' ) TRIM( sdjf%clrootname ), imonth ! add month 1089 ENDIF 1090 IF( sdjf%cltype == 'daily' .OR. sdjf%cltype(1:4) == 'week' ) & 1091 & WRITE(clname, '(a,"d" ,i2.2)' ) TRIM( clname ), iday ! add day 1092 ! 1093 IF( TRIM(clname) /= TRIM(sdjf%clname) .OR. sdjf%num == 0 ) THEN ! new file to be open 1094 ! 1095 sdjf%clname = TRIM(clname) 1096 IF( sdjf%num /= 0 ) CALL iom_close( sdjf%num ) ! close file if already open 1097 CALL iom_open( sdjf%clname, sdjf%num, ldstop = ldstop, ldiof = LEN(TRIM(sdjf%wgtname)) > 0 ) 1098 ! 1099 ! find the last record to be read -> update sdjf%nreclast 1100 indexyr = iyear - nyear + 1 1101 zyear_len = REAL(nyear_len( indexyr ), wp) 1102 SELECT CASE ( indexyr ) 1103 CASE ( 0 ) ; zmonth_len = 31. ! previous year -> imonth = 12 1104 CASE ( 1 ) ; zmonth_len = REAL(nmonth_len(imonth), wp) 1105 CASE ( 2 ) ; zmonth_len = 31. ! next year -> imonth = 1 1106 END SELECT 1107 ! 1108 ! last record to be read in the current file 1109 IF ( sdjf%freqh == -12. ) THEN ; sdjf%nreclast = 1 ! yearly mean 1110 ELSEIF( sdjf%freqh == -1. ) THEN ! monthly mean 1111 IF( sdjf%cltype == 'monthly' ) THEN ; sdjf%nreclast = 1 1112 ELSE ; sdjf%nreclast = 12 1113 ENDIF 1114 ELSE ! higher frequency mean (in hours) 1115 IF( sdjf%cltype == 'monthly' ) THEN ; sdjf%nreclast = NINT( 24. * zmonth_len / sdjf%freqh ) 1116 ELSEIF( sdjf%cltype(1:4) == 'week' ) THEN ; sdjf%nreclast = NINT( 24. * 7. / sdjf%freqh ) 1117 ELSEIF( sdjf%cltype == 'daily' ) THEN ; sdjf%nreclast = NINT( 24. / sdjf%freqh ) 1118 ELSE ; sdjf%nreclast = NINT( 24. * zyear_len / sdjf%freqh ) 1119 ENDIF 1120 ENDIF 928 !! ** Purpose : close/open the files 929 !!---------------------------------------------------------------------- 930 TYPE(FLD) , INTENT(inout) :: sdjf ! input field related variables 931 ! 932 INTEGER, DIMENSION(2) :: isave 933 LOGICAL :: llprev, llnext, llstop 934 !!---------------------------------------------------------------------- 935 ! 936 llprev = sdjf%nrecsec(sdjf%nreclast) < nsec000_1jan000 ! file ends before the beginning of the job -> file may not exist 937 llnext = sdjf%nrecsec( 0 ) > nsecend_1jan000 ! file begins after the end of the job -> file may not exist 938 939 llstop = sdjf%ln_clim .OR. .NOT. ( llprev .OR. llnext ) 940 941 IF( sdjf%num <= 0 .OR. .NOT. sdjf%ln_clim ) THEN 942 IF( sdjf%num > 0 ) CALL iom_close( sdjf%num ) ! close file if already open 943 CALL iom_open( sdjf%clname, sdjf%num, ldstop = llstop, ldiof = LEN(TRIM(sdjf%wgtname)) > 0 ) 944 ENDIF 945 ! 946 IF( sdjf%num <= 0 .AND. .NOT. llstop ) THEN ! file not found but we do accept this... 947 ! 948 IF( llprev ) THEN ! previous file does not exist : go back to current and accept to read only the first record 949 CALL ctl_warn('previous file: '//TRIM(sdjf%clname)//' not found -> go back to current year/month/week/day file') 950 isave(1:2) = sdjf%nrecsec(sdjf%nreclast-1:sdjf%nreclast) ! save previous file info 951 CALL fld_def( sdjf ) ! go back to current file 952 sdjf%nreclast = 1 ! force to use only the first record (do as if other were not existing...) 953 sdjf%nrecsec(0:1) = isave(1:2) 954 ENDIF 955 ! 956 IF( llnext ) THEN ! next file does not exist : go back to current and accept to read only the last record 957 CALL ctl_warn('next file: '//TRIM(sdjf%clname)//' not found -> go back to current year/month/week/day file') 958 isave(1:2) = sdjf%nrecsec(0:1) ! save next file info 959 CALL fld_def( sdjf ) ! go back to current file 960 ! -> read last record but keep record info from the first record of next file 961 sdjf%nrecsec(sdjf%nreclast-1:sdjf%nreclast) = isave(1:2) 962 sdjf%nrecsec(0:sdjf%nreclast-2) = nflag 963 ENDIF 964 ! 965 CALL iom_open( sdjf%clname, sdjf%num, ldiof = LEN(TRIM(sdjf%wgtname)) > 0 ) 1121 966 ! 1122 967 ENDIF … … 1300 1145 CALL iom_open( sd%clname, inum, ldiof = LEN(TRIM(sd%wgtname)) > 0 ) 1301 1146 1302 !! get dimensions 1303 IF ( SIZE(sd%fnow, 3) > 1) THEN1147 !! get dimensions: we consider 2D data as 3D data with vertical dim size = 1 1148 IF( SIZE(sd%fnow, 3) > 0 ) THEN 1304 1149 ALLOCATE( ddims(4) ) 1305 1150 ELSE … … 1314 1159 1315 1160 CALL iom_open ( sd%wgtname, inum ) ! interpolation weights 1316 IF 1161 IF( inum > 0 ) THEN 1317 1162 1318 1163 !! determine whether we have an east-west cyclic grid … … 1623 1468 1624 1469 ref_wgts(kw)%fly_dta(:,:,:) = 0.0 1625 SELECT CASE( SIZE(ref_wgts(kw)%fly_dta(jpi1:jpi2,jpj1:jpj2,:),3) ) 1626 CASE(1) 1627 CALL iom_get( num, jpdom_unknown, clvar, ref_wgts(kw)%fly_dta(jpi1:jpi2,jpj1:jpj2,1), nrec, rec1, recn) 1628 CASE DEFAULT 1629 CALL iom_get( num, jpdom_unknown, clvar, ref_wgts(kw)%fly_dta(jpi1:jpi2,jpj1:jpj2,:), nrec, rec1, recn) 1630 END SELECT 1470 CALL iom_get( num, jpdom_unknown, clvar, ref_wgts(kw)%fly_dta(jpi1:jpi2,jpj1:jpj2,:), nrec, rec1, recn) 1631 1471 ENDIF 1632 1472 … … 1646 1486 END DO 1647 1487 1648 IF 1488 IF(ref_wgts(kw)%numwgt .EQ. 16) THEN 1649 1489 1650 1490 !! fix up halo points that we couldnt read from file … … 1672 1512 IF( jpi1 == 2 ) THEN 1673 1513 rec1(1) = ref_wgts(kw)%ddims(1) - ref_wgts(kw)%overlap 1674 SELECT CASE( SIZE( ref_wgts(kw)%col(:,jpj1:jpj2,:),3) ) 1675 CASE(1) 1676 CALL iom_get( num, jpdom_unknown, clvar, ref_wgts(kw)%col(:,jpj1:jpj2,1), nrec, rec1, recn) 1677 CASE DEFAULT 1678 CALL iom_get( num, jpdom_unknown, clvar, ref_wgts(kw)%col(:,jpj1:jpj2,:), nrec, rec1, recn) 1679 END SELECT 1514 CALL iom_get( num, jpdom_unknown, clvar, ref_wgts(kw)%col(:,jpj1:jpj2,:), nrec, rec1, recn) 1680 1515 ref_wgts(kw)%fly_dta(jpi1-1,jpj1:jpj2,:) = ref_wgts(kw)%col(1,jpj1:jpj2,:) 1681 1516 ENDIF 1682 1517 IF( jpi2 + jpimin - 1 == ref_wgts(kw)%ddims(1)+1 ) THEN 1683 1518 rec1(1) = 1 + ref_wgts(kw)%overlap 1684 SELECT CASE( SIZE( ref_wgts(kw)%col(:,jpj1:jpj2,:),3) ) 1685 CASE(1) 1686 CALL iom_get( num, jpdom_unknown, clvar, ref_wgts(kw)%col(:,jpj1:jpj2,1), nrec, rec1, recn) 1687 CASE DEFAULT 1688 CALL iom_get( num, jpdom_unknown, clvar, ref_wgts(kw)%col(:,jpj1:jpj2,:), nrec, rec1, recn) 1689 END SELECT 1519 CALL iom_get( num, jpdom_unknown, clvar, ref_wgts(kw)%col(:,jpj1:jpj2,:), nrec, rec1, recn) 1690 1520 ref_wgts(kw)%fly_dta(jpi2+1,jpj1:jpj2,:) = ref_wgts(kw)%col(1,jpj1:jpj2,:) 1691 1521 ENDIF … … 1729 1559 END DO 1730 1560 ! 1731 END 1561 ENDIF 1732 1562 ! 1733 1563 END SUBROUTINE fld_interp 1734 1564 1735 1565 1566 FUNCTION fld_filename( sdjf, kday, kmonth, kyear ) 1567 !!--------------------------------------------------------------------- 1568 !! *** FUNCTION fld_filename *** 1569 !! 1570 !! ** Purpose : define the filename according to a given date 1571 !!--------------------------------------------------------------------- 1572 TYPE(FLD), INTENT(in) :: sdjf ! input field related variables 1573 INTEGER , INTENT(in) :: kday, kmonth, kyear 1574 ! 1575 CHARACTER(len = 256) :: clname, fld_filename 1576 !!--------------------------------------------------------------------- 1577 1578 1579 ! build the new filename if not climatological data 1580 clname=TRIM(sdjf%clrootname) 1581 ! 1582 ! note that sdjf%ln_clim is is only acting on the presence of the year in the file name 1583 IF( .NOT. sdjf%ln_clim ) THEN 1584 WRITE(clname, '(a,"_y",i4.4)' ) TRIM( sdjf%clrootname ), kyear ! add year 1585 IF( sdjf%cltype /= 'yearly' ) WRITE(clname, '(a, "m",i2.2)' ) TRIM( clname ), kmonth ! add month 1586 ELSE 1587 ! build the new filename if climatological data 1588 IF( sdjf%cltype /= 'yearly' ) WRITE(clname, '(a,"_m",i2.2)' ) TRIM( sdjf%clrootname ), kmonth ! add month 1589 ENDIF 1590 IF( sdjf%cltype == 'daily' .OR. sdjf%cltype(1:4) == 'week' ) & 1591 & WRITE(clname, '(a,"d" ,i2.2)' ) TRIM( clname ), kday ! add day 1592 1593 fld_filename = clname 1594 1595 END FUNCTION fld_filename 1596 1597 1736 1598 FUNCTION ksec_week( cdday ) 1737 1599 !!--------------------------------------------------------------------- 1738 !! *** FUNCTION ks hift_week ***1739 !! 1740 !! ** Purpose : return the first 3 letters of the first day of the weekly file1600 !! *** FUNCTION ksec_week *** 1601 !! 1602 !! ** Purpose : seconds between 00h of the beginning of the week and half of the current time step 1741 1603 !!--------------------------------------------------------------------- 1742 1604 CHARACTER(len=*), INTENT(in) :: cdday ! first 3 letters of the first day of the weekly file … … 1754 1616 ishift = ijul * NINT(rday) 1755 1617 ! 1756 ksec_week = nsec_ week+ ishift1618 ksec_week = nsec_monday + ishift 1757 1619 ksec_week = MOD( ksec_week, 7*NINT(rday) ) 1758 1620 ! -
NEMO/trunk/src/OCE/SBC/geo2ocean.F90
r10425 r12377 43 43 44 44 !! * Substitutions 45 # include " vectopt_loop_substitute.h90"45 # include "do_loop_substitute.h90" 46 46 !!---------------------------------------------------------------------- 47 47 !! NEMO/OCE 4.0 , NEMO Consortium (2018) … … 160 160 ! (computation done on the north stereographic polar plane) 161 161 ! 162 DO jj = 2, jpjm1 163 DO ji = fs_2, jpi ! vector opt. 164 ! 165 zlam = plamt(ji,jj) ! north pole direction & modulous (at t-point) 166 zphi = pphit(ji,jj) 167 zxnpt = 0. - 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) 168 zynpt = 0. - 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) 169 znnpt = zxnpt*zxnpt + zynpt*zynpt 170 ! 171 zlam = plamu(ji,jj) ! north pole direction & modulous (at u-point) 172 zphi = pphiu(ji,jj) 173 zxnpu = 0. - 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) 174 zynpu = 0. - 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) 175 znnpu = zxnpu*zxnpu + zynpu*zynpu 176 ! 177 zlam = plamv(ji,jj) ! north pole direction & modulous (at v-point) 178 zphi = pphiv(ji,jj) 179 zxnpv = 0. - 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) 180 zynpv = 0. - 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) 181 znnpv = zxnpv*zxnpv + zynpv*zynpv 182 ! 183 zlam = plamf(ji,jj) ! north pole direction & modulous (at f-point) 184 zphi = pphif(ji,jj) 185 zxnpf = 0. - 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) 186 zynpf = 0. - 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) 187 znnpf = zxnpf*zxnpf + zynpf*zynpf 188 ! 189 zlam = plamv(ji,jj ) ! j-direction: v-point segment direction (around t-point) 190 zphi = pphiv(ji,jj ) 191 zlan = plamv(ji,jj-1) 192 zphh = pphiv(ji,jj-1) 193 zxvvt = 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) & 194 & - 2. * COS( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. ) 195 zyvvt = 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) & 196 & - 2. * SIN( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. ) 197 znvvt = SQRT( znnpt * ( zxvvt*zxvvt + zyvvt*zyvvt ) ) 198 znvvt = MAX( znvvt, 1.e-14 ) 199 ! 200 zlam = plamf(ji,jj ) ! j-direction: f-point segment direction (around u-point) 201 zphi = pphif(ji,jj ) 202 zlan = plamf(ji,jj-1) 203 zphh = pphif(ji,jj-1) 204 zxffu = 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) & 205 & - 2. * COS( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. ) 206 zyffu = 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) & 207 & - 2. * SIN( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. ) 208 znffu = SQRT( znnpu * ( zxffu*zxffu + zyffu*zyffu ) ) 209 znffu = MAX( znffu, 1.e-14 ) 210 ! 211 zlam = plamf(ji ,jj) ! i-direction: f-point segment direction (around v-point) 212 zphi = pphif(ji ,jj) 213 zlan = plamf(ji-1,jj) 214 zphh = pphif(ji-1,jj) 215 zxffv = 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) & 216 & - 2. * COS( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. ) 217 zyffv = 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) & 218 & - 2. * SIN( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. ) 219 znffv = SQRT( znnpv * ( zxffv*zxffv + zyffv*zyffv ) ) 220 znffv = MAX( znffv, 1.e-14 ) 221 ! 222 zlam = plamu(ji,jj+1) ! j-direction: u-point segment direction (around f-point) 223 zphi = pphiu(ji,jj+1) 224 zlan = plamu(ji,jj ) 225 zphh = pphiu(ji,jj ) 226 zxuuf = 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) & 227 & - 2. * COS( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. ) 228 zyuuf = 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) & 229 & - 2. * SIN( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. ) 230 znuuf = SQRT( znnpf * ( zxuuf*zxuuf + zyuuf*zyuuf ) ) 231 znuuf = MAX( znuuf, 1.e-14 ) 232 ! 233 ! ! cosinus and sinus using dot and cross products 234 gsint(ji,jj) = ( zxnpt*zyvvt - zynpt*zxvvt ) / znvvt 235 gcost(ji,jj) = ( zxnpt*zxvvt + zynpt*zyvvt ) / znvvt 236 ! 237 gsinu(ji,jj) = ( zxnpu*zyffu - zynpu*zxffu ) / znffu 238 gcosu(ji,jj) = ( zxnpu*zxffu + zynpu*zyffu ) / znffu 239 ! 240 gsinf(ji,jj) = ( zxnpf*zyuuf - zynpf*zxuuf ) / znuuf 241 gcosf(ji,jj) = ( zxnpf*zxuuf + zynpf*zyuuf ) / znuuf 242 ! 243 gsinv(ji,jj) = ( zxnpv*zxffv + zynpv*zyffv ) / znffv 244 gcosv(ji,jj) =-( zxnpv*zyffv - zynpv*zxffv ) / znffv ! (caution, rotation of 90 degres) 245 ! 246 END DO 247 END DO 162 DO_2D_00_01 163 ! 164 zlam = plamt(ji,jj) ! north pole direction & modulous (at t-point) 165 zphi = pphit(ji,jj) 166 zxnpt = 0. - 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) 167 zynpt = 0. - 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) 168 znnpt = zxnpt*zxnpt + zynpt*zynpt 169 ! 170 zlam = plamu(ji,jj) ! north pole direction & modulous (at u-point) 171 zphi = pphiu(ji,jj) 172 zxnpu = 0. - 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) 173 zynpu = 0. - 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) 174 znnpu = zxnpu*zxnpu + zynpu*zynpu 175 ! 176 zlam = plamv(ji,jj) ! north pole direction & modulous (at v-point) 177 zphi = pphiv(ji,jj) 178 zxnpv = 0. - 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) 179 zynpv = 0. - 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) 180 znnpv = zxnpv*zxnpv + zynpv*zynpv 181 ! 182 zlam = plamf(ji,jj) ! north pole direction & modulous (at f-point) 183 zphi = pphif(ji,jj) 184 zxnpf = 0. - 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) 185 zynpf = 0. - 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) 186 znnpf = zxnpf*zxnpf + zynpf*zynpf 187 ! 188 zlam = plamv(ji,jj ) ! j-direction: v-point segment direction (around t-point) 189 zphi = pphiv(ji,jj ) 190 zlan = plamv(ji,jj-1) 191 zphh = pphiv(ji,jj-1) 192 zxvvt = 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) & 193 & - 2. * COS( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. ) 194 zyvvt = 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) & 195 & - 2. * SIN( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. ) 196 znvvt = SQRT( znnpt * ( zxvvt*zxvvt + zyvvt*zyvvt ) ) 197 znvvt = MAX( znvvt, 1.e-14 ) 198 ! 199 zlam = plamf(ji,jj ) ! j-direction: f-point segment direction (around u-point) 200 zphi = pphif(ji,jj ) 201 zlan = plamf(ji,jj-1) 202 zphh = pphif(ji,jj-1) 203 zxffu = 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) & 204 & - 2. * COS( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. ) 205 zyffu = 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) & 206 & - 2. * SIN( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. ) 207 znffu = SQRT( znnpu * ( zxffu*zxffu + zyffu*zyffu ) ) 208 znffu = MAX( znffu, 1.e-14 ) 209 ! 210 zlam = plamf(ji ,jj) ! i-direction: f-point segment direction (around v-point) 211 zphi = pphif(ji ,jj) 212 zlan = plamf(ji-1,jj) 213 zphh = pphif(ji-1,jj) 214 zxffv = 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) & 215 & - 2. * COS( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. ) 216 zyffv = 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) & 217 & - 2. * SIN( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. ) 218 znffv = SQRT( znnpv * ( zxffv*zxffv + zyffv*zyffv ) ) 219 znffv = MAX( znffv, 1.e-14 ) 220 ! 221 zlam = plamu(ji,jj+1) ! j-direction: u-point segment direction (around f-point) 222 zphi = pphiu(ji,jj+1) 223 zlan = plamu(ji,jj ) 224 zphh = pphiu(ji,jj ) 225 zxuuf = 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) & 226 & - 2. * COS( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. ) 227 zyuuf = 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) & 228 & - 2. * SIN( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. ) 229 znuuf = SQRT( znnpf * ( zxuuf*zxuuf + zyuuf*zyuuf ) ) 230 znuuf = MAX( znuuf, 1.e-14 ) 231 ! 232 ! ! cosinus and sinus using dot and cross products 233 gsint(ji,jj) = ( zxnpt*zyvvt - zynpt*zxvvt ) / znvvt 234 gcost(ji,jj) = ( zxnpt*zxvvt + zynpt*zyvvt ) / znvvt 235 ! 236 gsinu(ji,jj) = ( zxnpu*zyffu - zynpu*zxffu ) / znffu 237 gcosu(ji,jj) = ( zxnpu*zxffu + zynpu*zyffu ) / znffu 238 ! 239 gsinf(ji,jj) = ( zxnpf*zyuuf - zynpf*zxuuf ) / znuuf 240 gcosf(ji,jj) = ( zxnpf*zxuuf + zynpf*zyuuf ) / znuuf 241 ! 242 gsinv(ji,jj) = ( zxnpv*zxffv + zynpv*zyffv ) / znffv 243 gcosv(ji,jj) =-( zxnpv*zyffv - zynpv*zxffv ) / znffv ! (caution, rotation of 90 degres) 244 ! 245 END_2D 248 246 249 247 ! =============== ! … … 251 249 ! =============== ! 252 250 253 DO jj = 2, jpjm1 254 DO ji = fs_2, jpi ! vector opt. 255 IF( MOD( ABS( plamv(ji,jj) - plamv(ji,jj-1) ), 360. ) < 1.e-8 ) THEN 256 gsint(ji,jj) = 0. 257 gcost(ji,jj) = 1. 258 ENDIF 259 IF( MOD( ABS( plamf(ji,jj) - plamf(ji,jj-1) ), 360. ) < 1.e-8 ) THEN 260 gsinu(ji,jj) = 0. 261 gcosu(ji,jj) = 1. 262 ENDIF 263 IF( ABS( pphif(ji,jj) - pphif(ji-1,jj) ) < 1.e-8 ) THEN 264 gsinv(ji,jj) = 0. 265 gcosv(ji,jj) = 1. 266 ENDIF 267 IF( MOD( ABS( plamu(ji,jj) - plamu(ji,jj+1) ), 360. ) < 1.e-8 ) THEN 268 gsinf(ji,jj) = 0. 269 gcosf(ji,jj) = 1. 270 ENDIF 271 END DO 272 END DO 251 DO_2D_00_01 252 IF( MOD( ABS( plamv(ji,jj) - plamv(ji,jj-1) ), 360. ) < 1.e-8 ) THEN 253 gsint(ji,jj) = 0. 254 gcost(ji,jj) = 1. 255 ENDIF 256 IF( MOD( ABS( plamf(ji,jj) - plamf(ji,jj-1) ), 360. ) < 1.e-8 ) THEN 257 gsinu(ji,jj) = 0. 258 gcosu(ji,jj) = 1. 259 ENDIF 260 IF( ABS( pphif(ji,jj) - pphif(ji-1,jj) ) < 1.e-8 ) THEN 261 gsinv(ji,jj) = 0. 262 gcosv(ji,jj) = 1. 263 ENDIF 264 IF( MOD( ABS( plamu(ji,jj) - plamu(ji,jj+1) ), 360. ) < 1.e-8 ) THEN 265 gsinf(ji,jj) = 0. 266 gcosf(ji,jj) = 1. 267 ENDIF 268 END_2D 273 269 274 270 ! =========================== ! -
NEMO/trunk/src/OCE/SBC/sbc_oce.F90
r12132 r12377 2 2 !!====================================================================== 3 3 !! *** MODULE sbc_oce *** 4 !! Surface module : variables defined in core memory 4 !! Surface module : variables defined in core memory 5 5 !!====================================================================== 6 6 !! History : 3.0 ! 2006-06 (G. Madec) Original code … … 9 9 !! - ! 2010-11 (G. Madec) ice-ocean stress always computed at each ocean time-step 10 10 !! 3.3 ! 2010-10 (J. Chanut, C. Bricaud) add the surface pressure forcing 11 !! 4.0 ! 2012-05 (C. Rousset) add attenuation coef for use in ice model 11 !! 4.0 ! 2012-05 (C. Rousset) add attenuation coef for use in ice model 12 12 !! 4.0 ! 2016-06 (L. Brodeau) new unified bulk routine (based on AeroBulk) 13 !! 4.0 ! 2019-03 (F. Lemarié, G. Samson) add compatibility with ABL mode 13 14 !!---------------------------------------------------------------------- 14 15 … … 26 27 PUBLIC sbc_oce_alloc ! routine called in sbcmod.F90 27 28 PUBLIC sbc_tau2wnd ! routine called in several sbc modules 28 29 29 30 !!---------------------------------------------------------------------- 30 31 !! Namelist for the Ocean Surface Boundary Condition … … 34 35 LOGICAL , PUBLIC :: ln_flx !: flux formulation 35 36 LOGICAL , PUBLIC :: ln_blk !: bulk formulation 37 LOGICAL , PUBLIC :: ln_abl !: Atmospheric boundary layer model 36 38 #if defined key_oasis3 37 39 LOGICAL , PUBLIC :: lk_oasis = .TRUE. !: OASIS used … … 43 45 LOGICAL , PUBLIC :: ln_dm2dc !: Daily mean to Diurnal Cycle short wave (qsr) 44 46 LOGICAL , PUBLIC :: ln_rnf !: runoffs / runoff mouths 45 LOGICAL , PUBLIC :: ln_isf !: ice shelf melting 46 LOGICAL , PUBLIC :: ln_ssr !: Sea Surface restoring on SST and/or SSS 47 LOGICAL , PUBLIC :: ln_ssr !: Sea Surface restoring on SST and/or SSS 47 48 LOGICAL , PUBLIC :: ln_apr_dyn !: Atmospheric pressure forcing used on dynamics (ocean & ice) 48 49 INTEGER , PUBLIC :: nn_ice !: flag for ice in the surface boundary condition (=0/1/2/3) … … 50 51 ! !: =F levitating ice (no presure effect) with mass and salt exchanges 51 52 ! !: =T embedded sea-ice (pressure effect + mass and salt exchanges) 52 INTEGER , PUBLIC :: nn_components !: flag for sbc module (including sea-ice) coupling mode (see component definition below) 53 INTEGER , PUBLIC :: nn_fwb !: FreshWater Budget: 54 ! !: = 0 unchecked 53 INTEGER , PUBLIC :: nn_components !: flag for sbc module (including sea-ice) coupling mode (see component definition below) 54 INTEGER , PUBLIC :: nn_fwb !: FreshWater Budget: 55 ! !: = 0 unchecked 55 56 ! !: = 1 global mean of e-p-r set to zero at each nn_fsbc time step 56 57 ! !: = 2 annual global mean of e-p-r set to zero … … 77 78 INTEGER , PUBLIC, PARAMETER :: jp_flx = 2 !: flux formulation 78 79 INTEGER , PUBLIC, PARAMETER :: jp_blk = 3 !: bulk formulation 79 INTEGER , PUBLIC, PARAMETER :: jp_purecpl = 4 !: Pure ocean-atmosphere Coupled formulation 80 INTEGER , PUBLIC, PARAMETER :: jp_none = 5 !: for OPA when doing coupling via SAS module 81 82 !!---------------------------------------------------------------------- 83 !! Stokes drift parametrization definition 80 INTEGER , PUBLIC, PARAMETER :: jp_abl = 4 !: Atmospheric boundary layer formulation 81 INTEGER , PUBLIC, PARAMETER :: jp_purecpl = 5 !: Pure ocean-atmosphere Coupled formulation 82 INTEGER , PUBLIC, PARAMETER :: jp_none = 6 !: for OPA when doing coupling via SAS module 83 84 !!---------------------------------------------------------------------- 85 !! Stokes drift parametrization definition 84 86 !!---------------------------------------------------------------------- 85 87 INTEGER , PUBLIC, PARAMETER :: jp_breivik_2014 = 0 !: Breivik 2014: v_z=v_0*[exp(2*k*z)/(1-8*k*z)] 86 INTEGER , PUBLIC, PARAMETER :: jp_li_2017 = 1 !: Li et al 2017: Stokes drift based on Phillips spectrum (Breivik 2016) 87 88 INTEGER , PUBLIC, PARAMETER :: jp_peakfr = 2 !: Li et al 2017: using the peak wave number read from wave model instead 89 88 INTEGER , PUBLIC, PARAMETER :: jp_li_2017 = 1 !: Li et al 2017: Stokes drift based on Phillips spectrum (Breivik 2016) 89 ! with depth averaged profile 90 INTEGER , PUBLIC, PARAMETER :: jp_peakfr = 2 !: Li et al 2017: using the peak wave number read from wave model instead 91 ! of the inverse depth scale 90 92 LOGICAL , PUBLIC :: ll_st_bv2014 = .FALSE. ! logical indicator, .true. if Breivik 2014 parameterisation is active. 91 93 LOGICAL , PUBLIC :: ll_st_li2017 = .FALSE. ! logical indicator, .true. if Li 2017 parameterisation is active. … … 96 98 !! component definition 97 99 !!---------------------------------------------------------------------- 98 INTEGER , PUBLIC, PARAMETER :: jp_iam_nemo = 0 !: Initial single executable configuration 99 100 INTEGER , PUBLIC, PARAMETER :: jp_iam_nemo = 0 !: Initial single executable configuration 101 ! (no internal OASIS coupling) 100 102 INTEGER , PUBLIC, PARAMETER :: jp_iam_opa = 1 !: Multi executable configuration - OPA component 101 103 ! (internal OASIS coupling) 102 104 INTEGER , PUBLIC, PARAMETER :: jp_iam_sas = 2 !: Multi executable configuration - SAS component 103 105 ! (internal OASIS coupling) 104 106 !!---------------------------------------------------------------------- 105 107 !! Ocean Surface Boundary Condition fields … … 107 109 INTEGER , PUBLIC :: ncpl_qsr_freq = 0 !: qsr coupling frequency per days from atmosphere (used by top) 108 110 ! 109 LOGICAL , PUBLIC :: lhftau = .FALSE. !: HF tau used in TKE: mean(stress module) - module(mean stress)110 111 !! !! now ! before !! 111 112 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: utau , utau_b !: sea surface i-stress (ocean referential) [N/m2] 112 113 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: vtau , vtau_b !: sea surface j-stress (ocean referential) [N/m2] 113 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: taum !: module of sea surface stress (at T-point) [N/m2] 114 !! wndm is used onmpute surface gases exchanges in ice-free ocean or leads114 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: taum !: module of sea surface stress (at T-point) [N/m2] 115 !! wndm is used compute surface gases exchanges in ice-free ocean or leads 115 116 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: wndm !: wind speed module at T-point (=|U10m-Uoce|) [m/s] 117 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: rhoa !: air density at "rn_zu" m above the sea [kg/m3] 116 118 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: qsr !: sea heat flux: solar [W/m2] 117 119 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: qns , qns_b !: sea heat flux: non solar [W/m2] … … 122 124 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: emp_tot !: total E-P over ocean and ice [Kg/m2/s] 123 125 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: fmmflx !: freshwater budget: freezing/melting [Kg/m2/s] 124 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: rnf , rnf_b !: river runoff [Kg/m2/s] 125 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: fwfisf , fwfisf_b !: ice shelf melting [Kg/m2/s] 126 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: fwficb , fwficb_b !: iceberg melting [Kg/m2/s] 127 126 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: rnf , rnf_b !: river runoff [Kg/m2/s] 127 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: fwficb , fwficb_b !: iceberg melting [Kg/m2/s] 128 128 !! 129 129 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:,:) :: sbc_tsc, sbc_tsc_b !: sbc content trend [K.m/s] jpi,jpj,jpts … … 137 137 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:,:) :: xcplmask !: coupling mask for ln_mixcpl (warning: allocated in sbccpl) 138 138 139 !!--------------------------------------------------------------------- 140 !! ABL Vertical Domain size 141 !!--------------------------------------------------------------------- 142 INTEGER , PUBLIC :: jpka = 2 !: ABL number of vertical levels (default definition) 143 INTEGER , PUBLIC :: jpkam1 = 1 !: jpka-1 144 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: ght_abl, ghw_abl !: ABL geopotential height (needed for iom) 145 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: e3t_abl, e3w_abl !: ABL vertical scale factors (needed for iom) 146 139 147 !!---------------------------------------------------------------------- 140 148 !! Sea Surface Mean fields … … 146 154 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: sss_m !: mean (nn_fsbc time-step) surface sea salinity [psu] 147 155 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: ssh_m !: mean (nn_fsbc time-step) sea surface height [m] 156 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: tsk_m !: mean (nn_fsbc time-step) SKIN surface sea temp. [Celsius] 148 157 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: e3t_m !: mean (nn_fsbc time-step) sea surface layer thickness [m] 149 158 REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: frq_m !: mean (nn_fsbc time-step) fraction of solar net radiation absorbed in the 1st T level [-] 150 159 151 160 !! * Substitutions 152 # include " vectopt_loop_substitute.h90"161 # include "do_loop_substitute.h90" 153 162 !!---------------------------------------------------------------------- 154 163 !! NEMO/OCE 4.0 , NEMO Consortium (2018) … … 167 176 ! 168 177 ALLOCATE( utau(jpi,jpj) , utau_b(jpi,jpj) , taum(jpi,jpj) , & 169 & vtau(jpi,jpj) , vtau_b(jpi,jpj) , wndm(jpi,jpj) , STAT=ierr(1) )170 178 & vtau(jpi,jpj) , vtau_b(jpi,jpj) , wndm(jpi,jpj) , rhoa(jpi,jpj) , STAT=ierr(1) ) 179 ! 171 180 ALLOCATE( qns_tot(jpi,jpj) , qns (jpi,jpj) , qns_b(jpi,jpj), & 172 181 & qsr_tot(jpi,jpj) , qsr (jpi,jpj) , & 173 182 & emp (jpi,jpj) , emp_b(jpi,jpj) , & 174 183 & sfx (jpi,jpj) , sfx_b(jpi,jpj) , emp_tot(jpi,jpj), fmmflx(jpi,jpj), STAT=ierr(2) ) 175 176 ALLOCATE( fwfisf (jpi,jpj),rnf (jpi,jpj) , sbc_tsc (jpi,jpj,jpts) , qsr_hc (jpi,jpj,jpk) , &177 & fwfisf_b(jpi,jpj),rnf_b(jpi,jpj) , sbc_tsc_b(jpi,jpj,jpts) , qsr_hc_b(jpi,jpj,jpk) , &184 ! 185 ALLOCATE( rnf (jpi,jpj) , sbc_tsc (jpi,jpj,jpts) , qsr_hc (jpi,jpj,jpk) , & 186 & rnf_b(jpi,jpj) , sbc_tsc_b(jpi,jpj,jpts) , qsr_hc_b(jpi,jpj,jpk) , & 178 187 & fwficb (jpi,jpj), fwficb_b(jpi,jpj), STAT=ierr(3) ) 179 188 ! 180 189 ALLOCATE( tprecip(jpi,jpj) , sprecip(jpi,jpj) , fr_i(jpi,jpj) , & 181 & atm_co2(jpi,jpj) , 190 & atm_co2(jpi,jpj) , tsk_m(jpi,jpj) , & 182 191 & ssu_m (jpi,jpj) , sst_m(jpi,jpj) , frq_m(jpi,jpj) , & 183 192 & ssv_m (jpi,jpj) , sss_m(jpi,jpj) , ssh_m(jpi,jpj) , STAT=ierr(4) ) 184 193 ! 185 194 ALLOCATE( e3t_m(jpi,jpj) , STAT=ierr(5) ) 186 195 ! 187 196 sbc_oce_alloc = MAXVAL( ierr ) 188 197 CALL mpp_sum ( 'sbc_oce', sbc_oce_alloc ) … … 195 204 !!--------------------------------------------------------------------- 196 205 !! *** ROUTINE sbc_tau2wnd *** 197 !! 198 !! ** Purpose : Estimation of wind speed as a function of wind stress 206 !! 207 !! ** Purpose : Estimation of wind speed as a function of wind stress 199 208 !! 200 209 !! ** Method : |tau|=rhoa*Cd*|U|^2 … … 207 216 INTEGER :: ji, jj ! dummy indices 208 217 !!--------------------------------------------------------------------- 209 zcoef = 0.5 / ( zrhoa * zcdrag ) 210 DO jj = 2, jpjm1 211 DO ji = fs_2, fs_jpim1 ! vect. opt. 212 ztx = utau(ji-1,jj ) + utau(ji,jj) 213 zty = vtau(ji ,jj-1) + vtau(ji,jj) 214 ztau = SQRT( ztx * ztx + zty * zty ) 215 wndm(ji,jj) = SQRT ( ztau * zcoef ) * tmask(ji,jj,1) 216 END DO 217 END DO 218 zcoef = 0.5 / ( zrhoa * zcdrag ) 219 DO_2D_00_00 220 ztx = utau(ji-1,jj ) + utau(ji,jj) 221 zty = vtau(ji ,jj-1) + vtau(ji,jj) 222 ztau = SQRT( ztx * ztx + zty * zty ) 223 wndm(ji,jj) = SQRT ( ztau * zcoef ) * tmask(ji,jj,1) 224 END_2D 218 225 CALL lbc_lnk( 'sbc_oce', wndm(:,:) , 'T', 1. ) 219 226 ! -
NEMO/trunk/src/OCE/SBC/sbcapr.F90
r11536 r12377 69 69 NAMELIST/namsbc_apr/ cn_dir, sn_apr, ln_ref_apr, rn_pref, ln_apr_obc 70 70 !!---------------------------------------------------------------------- 71 REWIND( numnam_ref ) ! Namelist namsbc_apr in reference namelist : File for atmospheric pressure forcing72 71 READ ( numnam_ref, namsbc_apr, IOSTAT = ios, ERR = 901) 73 72 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namsbc_apr in reference namelist' ) 74 73 75 REWIND( numnam_cfg ) ! Namelist namsbc_apr in configuration namelist : File for atmospheric pressure forcing76 74 READ ( numnam_cfg, namsbc_apr, IOSTAT = ios, ERR = 902 ) 77 75 902 IF( ios > 0 ) CALL ctl_nam ( ios , 'namsbc_apr in configuration namelist' ) … … 103 101 ! 104 102 ! !* control check 105 IF 103 IF( ln_apr_obc ) THEN 106 104 IF(lwp) WRITE(numout,*) ' Inverse barometer added to OBC ssh data' 107 105 ENDIF -
NEMO/trunk/src/OCE/SBC/sbcblk.F90
r12276 r12377 15 15 !! 3.7 ! 2014-06 (L. Brodeau) simplification and optimization of CORE bulk 16 16 !! 4.0 ! 2016-06 (L. Brodeau) sbcblk_core becomes sbcblk and is not restricted to the CORE algorithm anymore 17 !! ! ==> based on AeroBulk (http ://aerobulk.sourceforge.net/)17 !! ! ==> based on AeroBulk (https://github.com/brodeau/aerobulk/) 18 18 !! 4.0 ! 2016-10 (G. Madec) introduce a sbc_blk_init routine 19 !! 4.0 ! 2016-10 (M. Vancoppenolle) Introduce conduction flux emulator (M. Vancoppenolle) 19 !! 4.0 ! 2016-10 (M. Vancoppenolle) Introduce conduction flux emulator (M. Vancoppenolle) 20 !! 4.0 ! 2019-03 (F. Lemarié & G. Samson) add ABL compatibility (ln_abl=TRUE) 20 21 !!---------------------------------------------------------------------- 21 22 … … 23 24 !! sbc_blk_init : initialisation of the chosen bulk formulation as ocean surface boundary condition 24 25 !! sbc_blk : bulk formulation as ocean surface boundary condition 25 !! blk_oce : computes momentum, heat and freshwater fluxes over ocean 26 !! rho_air : density of (moist) air (depends on T_air, q_air and SLP 27 !! cp_air : specific heat of (moist) air (depends spec. hum. q_air) 28 !! q_sat : saturation humidity as a function of SLP and temperature 29 !! L_vap : latent heat of vaporization of water as a function of temperature 30 !! sea-ice case only : 31 !! blk_ice_tau : provide the air-ice stress 32 !! blk_ice_flx : provide the heat and mass fluxes at air-ice interface 26 !! blk_oce_1 : computes pieces of momentum, heat and freshwater fluxes over ocean for ABL model (ln_abl=TRUE) 27 !! blk_oce_2 : finalizes momentum, heat and freshwater fluxes computation over ocean after the ABL step (ln_abl=TRUE) 28 !! sea-ice case only : 29 !! blk_ice_1 : provide the air-ice stress 30 !! blk_ice_2 : provide the heat and mass fluxes at air-ice interface 33 31 !! blk_ice_qcn : provide ice surface temperature and snow/ice conduction flux (emulating conduction flux) 34 32 !! Cdn10_Lupkes2012 : Lupkes et al. (2012) air-ice drag 35 !! Cdn10_Lupkes2015 : Lupkes et al. (2015) air-ice drag 33 !! Cdn10_Lupkes2015 : Lupkes et al. (2015) air-ice drag 36 34 !!---------------------------------------------------------------------- 37 35 USE oce ! ocean dynamics and tracers … … 46 44 USE lib_fortran ! to use key_nosignedzero 47 45 #if defined key_si3 48 USE ice , ONLY : u_ice, v_ice, jpl, a_i_b, at_i_b, t_su, rn_cnd_s, hfx_err_dif46 USE ice , ONLY : jpl, a_i_b, at_i_b, rn_cnd_s, hfx_err_dif 49 47 USE icethd_dh ! for CALL ice_thd_snwblow 50 48 #endif 51 USE sbcblk_algo_ncar ! => turb_ncar : NCAR - CORE (Large & Yeager, 2009) 52 USE sbcblk_algo_coare ! => turb_coare : COAREv3.0 (Fairall et al. 2003)53 USE sbcblk_algo_coare3p 5 ! => turb_coare3p5 : COAREv3.5 (Edson et al. 2013)54 USE sbcblk_algo_ecmwf ! => turb_ecmwf : ECMWF (IFS cycle 31)49 USE sbcblk_algo_ncar ! => turb_ncar : NCAR - CORE (Large & Yeager, 2009) 50 USE sbcblk_algo_coare3p0 ! => turb_coare3p0 : COAREv3.0 (Fairall et al. 2003) 51 USE sbcblk_algo_coare3p6 ! => turb_coare3p6 : COAREv3.6 (Fairall et al. 2018 + Edson et al. 2013) 52 USE sbcblk_algo_ecmwf ! => turb_ecmwf : ECMWF (IFS cycle 45r1) 55 53 ! 56 54 USE iom ! I/O manager library … … 60 58 USE prtctl ! Print control 61 59 60 USE sbcblk_phy ! a catalog of functions for physical/meteorological parameters in the marine boundary layer, rho_air, q_sat, etc... 61 62 62 63 IMPLICIT NONE 63 64 PRIVATE … … 65 66 PUBLIC sbc_blk_init ! called in sbcmod 66 67 PUBLIC sbc_blk ! called in sbcmod 68 PUBLIC blk_oce_1 ! called in sbcabl 69 PUBLIC blk_oce_2 ! called in sbcabl 67 70 #if defined key_si3 68 PUBLIC blk_ice_ tau! routine called in icesbc69 PUBLIC blk_ice_ flx! routine called in icesbc71 PUBLIC blk_ice_1 ! routine called in icesbc 72 PUBLIC blk_ice_2 ! routine called in icesbc 70 73 PUBLIC blk_ice_qcn ! routine called in icesbc 71 #endif 72 73 !!Lolo: should ultimately be moved in the module with all physical constants ? 74 !!gm : In principle, yes. 75 REAL(wp), PARAMETER :: Cp_dry = 1005.0 !: Specic heat of dry air, constant pressure [J/K/kg] 76 REAL(wp), PARAMETER :: Cp_vap = 1860.0 !: Specic heat of water vapor, constant pressure [J/K/kg] 77 REAL(wp), PARAMETER :: R_dry = 287.05_wp !: Specific gas constant for dry air [J/K/kg] 78 REAL(wp), PARAMETER :: R_vap = 461.495_wp !: Specific gas constant for water vapor [J/K/kg] 79 REAL(wp), PARAMETER :: reps0 = R_dry/R_vap !: ratio of gas constant for dry air and water vapor => ~ 0.622 80 REAL(wp), PARAMETER :: rctv0 = R_vap/R_dry !: for virtual temperature (== (1-eps)/eps) => ~ 0.608 81 82 INTEGER , PARAMETER :: jpfld =10 ! maximum number of files to read 83 INTEGER , PARAMETER :: jp_wndi = 1 ! index of 10m wind velocity (i-component) (m/s) at T-point 84 INTEGER , PARAMETER :: jp_wndj = 2 ! index of 10m wind velocity (j-component) (m/s) at T-point 85 INTEGER , PARAMETER :: jp_tair = 3 ! index of 10m air temperature (Kelvin) 86 INTEGER , PARAMETER :: jp_humi = 4 ! index of specific humidity ( % ) 87 INTEGER , PARAMETER :: jp_qsr = 5 ! index of solar heat (W/m2) 88 INTEGER , PARAMETER :: jp_qlw = 6 ! index of Long wave (W/m2) 89 INTEGER , PARAMETER :: jp_prec = 7 ! index of total precipitation (rain+snow) (Kg/m2/s) 90 INTEGER , PARAMETER :: jp_snow = 8 ! index of snow (solid prcipitation) (kg/m2/s) 91 INTEGER , PARAMETER :: jp_slp = 9 ! index of sea level pressure (Pa) 92 INTEGER , PARAMETER :: jp_tdif =10 ! index of tau diff associated to HF tau (N/m2) at T-point 93 94 TYPE(FLD), ALLOCATABLE, DIMENSION(:) :: sf ! structure of input fields (file informations, fields read) 95 96 ! !!! Bulk parameters 97 REAL(wp), PARAMETER :: cpa = 1000.5 ! specific heat of air (only used for ice fluxes now...) 98 REAL(wp), PARAMETER :: Ls = 2.839e6 ! latent heat of sublimation 99 REAL(wp), PARAMETER :: Stef = 5.67e-8 ! Stefan Boltzmann constant 100 REAL(wp), PARAMETER :: Cd_ice = 1.4e-3 ! transfer coefficient over ice 101 REAL(wp), PARAMETER :: albo = 0.066 ! ocean albedo assumed to be constant 102 ! 74 #endif 75 76 INTEGER , PUBLIC :: jpfld ! maximum number of files to read 77 INTEGER , PUBLIC, PARAMETER :: jp_wndi = 1 ! index of 10m wind velocity (i-component) (m/s) at T-point 78 INTEGER , PUBLIC, PARAMETER :: jp_wndj = 2 ! index of 10m wind velocity (j-component) (m/s) at T-point 79 INTEGER , PUBLIC, PARAMETER :: jp_tair = 3 ! index of 10m air temperature (Kelvin) 80 INTEGER , PUBLIC, PARAMETER :: jp_humi = 4 ! index of specific humidity ( % ) 81 INTEGER , PUBLIC, PARAMETER :: jp_qsr = 5 ! index of solar heat (W/m2) 82 INTEGER , PUBLIC, PARAMETER :: jp_qlw = 6 ! index of Long wave (W/m2) 83 INTEGER , PUBLIC, PARAMETER :: jp_prec = 7 ! index of total precipitation (rain+snow) (Kg/m2/s) 84 INTEGER , PUBLIC, PARAMETER :: jp_snow = 8 ! index of snow (solid prcipitation) (kg/m2/s) 85 INTEGER , PUBLIC, PARAMETER :: jp_slp = 9 ! index of sea level pressure (Pa) 86 INTEGER , PUBLIC, PARAMETER :: jp_hpgi =10 ! index of ABL geostrophic wind or hpg (i-component) (m/s) at T-point 87 INTEGER , PUBLIC, PARAMETER :: jp_hpgj =11 ! index of ABL geostrophic wind or hpg (j-component) (m/s) at T-point 88 89 TYPE(FLD), PUBLIC, ALLOCATABLE, DIMENSION(:) :: sf ! structure of input atmospheric fields (file informations, fields read) 90 103 91 ! !!* Namelist namsbc_blk : bulk parameters 104 92 LOGICAL :: ln_NCAR ! "NCAR" algorithm (Large and Yeager 2008) 105 93 LOGICAL :: ln_COARE_3p0 ! "COARE 3.0" algorithm (Fairall et al. 2003) 106 LOGICAL :: ln_COARE_3p 5 ! "COARE 3.5" algorithm (Edson et al. 2013)107 LOGICAL :: ln_ECMWF ! "ECMWF" algorithm (IFS cycle 31)94 LOGICAL :: ln_COARE_3p6 ! "COARE 3.6" algorithm (Edson et al. 2013) 95 LOGICAL :: ln_ECMWF ! "ECMWF" algorithm (IFS cycle 45r1) 108 96 ! 109 LOGICAL :: ln_taudif ! logical flag to use the "mean of stress module - module of mean stress" data 110 REAL(wp) :: rn_pfac ! multiplication factor for precipitation 111 REAL(wp) :: rn_efac ! multiplication factor for evaporation 112 REAL(wp) :: rn_vfac ! multiplication factor for ice/ocean velocity in the calculation of wind stress 113 REAL(wp) :: rn_zqt ! z(q,t) : height of humidity and temperature measurements 114 REAL(wp) :: rn_zu ! z(u) : height of wind measurements 115 !!gm ref namelist initialize it so remove the setting to false below 116 LOGICAL :: ln_Cd_L12 = .FALSE. ! Modify the drag ice-atm depending on ice concentration (from Lupkes et al. JGR2012) 117 LOGICAL :: ln_Cd_L15 = .FALSE. ! Modify the drag ice-atm depending on ice concentration (from Lupkes et al. JGR2015) 97 LOGICAL :: ln_Cd_L12 ! ice-atm drag = F( ice concentration ) (Lupkes et al. JGR2012) 98 LOGICAL :: ln_Cd_L15 ! ice-atm drag = F( ice concentration, atmospheric stability ) (Lupkes et al. JGR2015) 118 99 ! 119 REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: Cd_atm ! transfer coefficient for momentum (tau) 120 REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: Ch_atm ! transfer coefficient for sensible heat (Q_sens) 121 REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: Ce_atm ! tansfert coefficient for evaporation (Q_lat) 122 REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: t_zu ! air temperature at wind speed height (needed by Lupkes 2015 bulk scheme) 123 REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: q_zu ! air spec. hum. at wind speed height (needed by Lupkes 2015 bulk scheme) 124 REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: cdn_oce, chn_oce, cen_oce ! needed by Lupkes 2015 bulk scheme 100 REAL(wp) :: rn_pfac ! multiplication factor for precipitation 101 REAL(wp), PUBLIC :: rn_efac ! multiplication factor for evaporation 102 REAL(wp), PUBLIC :: rn_vfac ! multiplication factor for ice/ocean velocity in the calculation of wind stress 103 REAL(wp) :: rn_zqt ! z(q,t) : height of humidity and temperature measurements 104 REAL(wp) :: rn_zu ! z(u) : height of wind measurements 105 ! 106 REAL(wp), ALLOCATABLE, DIMENSION(:,:) :: Cd_ice , Ch_ice , Ce_ice ! transfert coefficients over ice 107 REAL(wp), ALLOCATABLE, DIMENSION(:,:) :: Cdn_oce, Chn_oce, Cen_oce ! neutral coeffs over ocean (L15 bulk scheme) 108 REAL(wp), ALLOCATABLE, DIMENSION(:,:) :: t_zu, q_zu ! air temp. and spec. hum. at wind speed height (L15 bulk scheme) 109 110 LOGICAL :: ln_skin_cs ! use the cool-skin (only available in ECMWF and COARE algorithms) !LB 111 LOGICAL :: ln_skin_wl ! use the warm-layer parameterization (only available in ECMWF and COARE algorithms) !LB 112 LOGICAL :: ln_humi_sph ! humidity read in files ("sn_humi") is specific humidity [kg/kg] if .true. !LB 113 LOGICAL :: ln_humi_dpt ! humidity read in files ("sn_humi") is dew-point temperature [K] if .true. !LB 114 LOGICAL :: ln_humi_rlh ! humidity read in files ("sn_humi") is relative humidity [%] if .true. !LB 115 ! 116 INTEGER :: nhumi ! choice of the bulk algorithm 117 ! ! associated indices: 118 INTEGER, PARAMETER :: np_humi_sph = 1 119 INTEGER, PARAMETER :: np_humi_dpt = 2 120 INTEGER, PARAMETER :: np_humi_rlh = 3 125 121 126 122 INTEGER :: nblk ! choice of the bulk algorithm … … 128 124 INTEGER, PARAMETER :: np_NCAR = 1 ! "NCAR" algorithm (Large and Yeager 2008) 129 125 INTEGER, PARAMETER :: np_COARE_3p0 = 2 ! "COARE 3.0" algorithm (Fairall et al. 2003) 130 INTEGER, PARAMETER :: np_COARE_3p 5 = 3 ! "COARE 3.5" algorithm (Edson et al. 2013)131 INTEGER, PARAMETER :: np_ECMWF = 4 ! "ECMWF" algorithm (IFS cycle 31)126 INTEGER, PARAMETER :: np_COARE_3p6 = 3 ! "COARE 3.6" algorithm (Edson et al. 2013) 127 INTEGER, PARAMETER :: np_ECMWF = 4 ! "ECMWF" algorithm (IFS cycle 45r1) 132 128 133 129 !! * Substitutions 134 # include " vectopt_loop_substitute.h90"130 # include "do_loop_substitute.h90" 135 131 !!---------------------------------------------------------------------- 136 132 !! NEMO/OCE 4.0 , NEMO Consortium (2018) … … 144 140 !! *** ROUTINE sbc_blk_alloc *** 145 141 !!------------------------------------------------------------------- 146 ALLOCATE( Cd_atm (jpi,jpj), Ch_atm (jpi,jpj), Ce_atm (jpi,jpj), t_zu(jpi,jpj), q_zu(jpi,jpj), & 147 & cdn_oce(jpi,jpj), chn_oce(jpi,jpj), cen_oce(jpi,jpj), STAT=sbc_blk_alloc ) 142 ALLOCATE( t_zu(jpi,jpj) , q_zu(jpi,jpj) , & 143 & Cdn_oce(jpi,jpj), Chn_oce(jpi,jpj), Cen_oce(jpi,jpj), & 144 & Cd_ice (jpi,jpj), Ch_ice (jpi,jpj), Ce_ice (jpi,jpj), STAT=sbc_blk_alloc ) 148 145 ! 149 146 CALL mpp_sum ( 'sbcblk', sbc_blk_alloc ) … … 158 155 !! ** Purpose : choose and initialize a bulk formulae formulation 159 156 !! 160 !! ** Method : 157 !! ** Method : 161 158 !! 162 159 !!---------------------------------------------------------------------- 163 INTEGER :: ifpr, jfld! dummy loop indice and argument160 INTEGER :: jfpr ! dummy loop indice and argument 164 161 INTEGER :: ios, ierror, ioptio ! Local integer 165 162 !! 166 163 CHARACTER(len=100) :: cn_dir ! Root directory for location of atmospheric forcing files 167 TYPE(FLD_N), DIMENSION(jpfld) :: slf_i! array of namelist informations on the fields to read164 TYPE(FLD_N), ALLOCATABLE, DIMENSION(:) :: slf_i ! array of namelist informations on the fields to read 168 165 TYPE(FLD_N) :: sn_wndi, sn_wndj, sn_humi, sn_qsr ! informations about the fields to be read 169 166 TYPE(FLD_N) :: sn_qlw , sn_tair, sn_prec, sn_snow ! " " 170 TYPE(FLD_N) :: sn_slp , sn_ tdif! " "167 TYPE(FLD_N) :: sn_slp , sn_hpgi, sn_hpgj ! " " 171 168 NAMELIST/namsbc_blk/ sn_wndi, sn_wndj, sn_humi, sn_qsr, sn_qlw , & ! input fields 172 & sn_tair, sn_prec, sn_snow, sn_slp, sn_tdif, & 173 & ln_NCAR, ln_COARE_3p0, ln_COARE_3p5, ln_ECMWF, & ! bulk algorithm 174 & cn_dir , ln_taudif, rn_zqt, rn_zu, & 175 & rn_pfac, rn_efac, rn_vfac, ln_Cd_L12, ln_Cd_L15 169 & sn_tair, sn_prec, sn_snow, sn_slp, sn_hpgi, sn_hpgj, & 170 & ln_NCAR, ln_COARE_3p0, ln_COARE_3p6, ln_ECMWF, & ! bulk algorithm 171 & cn_dir , rn_zqt, rn_zu, & 172 & rn_pfac, rn_efac, rn_vfac, ln_Cd_L12, ln_Cd_L15, & 173 & ln_skin_cs, ln_skin_wl, ln_humi_sph, ln_humi_dpt, ln_humi_rlh ! cool-skin / warm-layer !LB 176 174 !!--------------------------------------------------------------------- 177 175 ! … … 179 177 IF( sbc_blk_alloc() /= 0 ) CALL ctl_stop( 'STOP', 'sbc_blk : unable to allocate standard arrays' ) 180 178 ! 181 ! !** read bulk namelist 182 REWIND( numnam_ref ) !* Namelist namsbc_blk in reference namelist : bulk parameters 179 ! !** read bulk namelist 183 180 READ ( numnam_ref, namsbc_blk, IOSTAT = ios, ERR = 901) 184 181 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namsbc_blk in reference namelist' ) 185 182 ! 186 REWIND( numnam_cfg ) !* Namelist namsbc_blk in configuration namelist : bulk parameters187 183 READ ( numnam_cfg, namsbc_blk, IOSTAT = ios, ERR = 902 ) 188 184 902 IF( ios > 0 ) CALL ctl_nam ( ios , 'namsbc_blk in configuration namelist' ) … … 192 188 ! !** initialization of the chosen bulk formulae (+ check) 193 189 ! !* select the bulk chosen in the namelist and check the choice 194 ioptio = 0 195 IF( ln_NCAR ) THEN ; nblk = np_NCAR ; ioptio = ioptio + 1 ; ENDIF 196 IF( ln_COARE_3p0 ) THEN ; nblk = np_COARE_3p0 ; ioptio = ioptio + 1 ; ENDIF 197 IF( ln_COARE_3p5 ) THEN ; nblk = np_COARE_3p5 ; ioptio = ioptio + 1 ; ENDIF 198 IF( ln_ECMWF ) THEN ; nblk = np_ECMWF ; ioptio = ioptio + 1 ; ENDIF 199 ! 190 ioptio = 0 191 IF( ln_NCAR ) THEN 192 nblk = np_NCAR ; ioptio = ioptio + 1 193 ENDIF 194 IF( ln_COARE_3p0 ) THEN 195 nblk = np_COARE_3p0 ; ioptio = ioptio + 1 196 ENDIF 197 IF( ln_COARE_3p6 ) THEN 198 nblk = np_COARE_3p6 ; ioptio = ioptio + 1 199 ENDIF 200 IF( ln_ECMWF ) THEN 201 nblk = np_ECMWF ; ioptio = ioptio + 1 202 ENDIF 200 203 IF( ioptio /= 1 ) CALL ctl_stop( 'sbc_blk_init: Choose one and only one bulk algorithm' ) 204 205 ! !** initialization of the cool-skin / warm-layer parametrization 206 IF( ln_skin_cs .OR. ln_skin_wl ) THEN 207 !! Some namelist sanity tests: 208 IF( ln_NCAR ) & 209 & CALL ctl_stop( 'sbc_blk_init: Cool-skin/warm-layer param. not compatible with NCAR algorithm' ) 210 IF( nn_fsbc /= 1 ) & 211 & CALL ctl_stop( 'sbc_blk_init: Please set "nn_fsbc" to 1 when using cool-skin/warm-layer param.') 212 END IF 213 214 IF( ln_skin_wl ) THEN 215 !! Check if the frequency of downwelling solar flux input makes sense and if ln_dm2dc=T if it is daily! 216 IF( (sn_qsr%freqh < 0.).OR.(sn_qsr%freqh > 24.) ) & 217 & CALL ctl_stop( 'sbc_blk_init: Warm-layer param. (ln_skin_wl) not compatible with freq. of solar flux > daily' ) 218 IF( (sn_qsr%freqh == 24.).AND.(.NOT. ln_dm2dc) ) & 219 & CALL ctl_stop( 'sbc_blk_init: Please set ln_dm2dc=T for warm-layer param. (ln_skin_wl) to work properly' ) 220 END IF 221 222 ioptio = 0 223 IF( ln_humi_sph ) THEN 224 nhumi = np_humi_sph ; ioptio = ioptio + 1 225 ENDIF 226 IF( ln_humi_dpt ) THEN 227 nhumi = np_humi_dpt ; ioptio = ioptio + 1 228 ENDIF 229 IF( ln_humi_rlh ) THEN 230 nhumi = np_humi_rlh ; ioptio = ioptio + 1 231 ENDIF 232 IF( ioptio /= 1 ) CALL ctl_stop( 'sbc_blk_init: Choose one and only one type of air humidity' ) 201 233 ! 202 234 IF( ln_dm2dc ) THEN !* check: diurnal cycle on Qsr 203 235 IF( sn_qsr%freqh /= 24. ) CALL ctl_stop( 'sbc_blk_init: ln_dm2dc=T only with daily short-wave input' ) 204 IF( sn_qsr%ln_tint ) THEN 236 IF( sn_qsr%ln_tint ) THEN 205 237 CALL ctl_warn( 'sbc_blk_init: ln_dm2dc=T daily qsr time interpolation done by sbcdcy module', & 206 238 & ' ==> We force time interpolation = .false. for qsr' ) … … 210 242 ! !* set the bulk structure 211 243 ! !- store namelist information in an array 244 IF( ln_blk ) jpfld = 9 245 IF( ln_abl ) jpfld = 11 246 ALLOCATE( slf_i(jpfld) ) 247 ! 212 248 slf_i(jp_wndi) = sn_wndi ; slf_i(jp_wndj) = sn_wndj 213 249 slf_i(jp_qsr ) = sn_qsr ; slf_i(jp_qlw ) = sn_qlw 214 250 slf_i(jp_tair) = sn_tair ; slf_i(jp_humi) = sn_humi 215 251 slf_i(jp_prec) = sn_prec ; slf_i(jp_snow) = sn_snow 216 slf_i(jp_slp ) = sn_slp ; slf_i(jp_tdif) = sn_tdif217 !218 lhftau = ln_taudif !- add an extra field if HF stress is used219 jfld = jpfld - COUNT( (/.NOT.lhftau/) )252 slf_i(jp_slp ) = sn_slp 253 IF( ln_abl ) THEN 254 slf_i(jp_hpgi) = sn_hpgi ; slf_i(jp_hpgj) = sn_hpgj 255 END IF 220 256 ! 221 257 ! !- allocate the bulk structure 222 ALLOCATE( sf(j fld), STAT=ierror )258 ALLOCATE( sf(jpfld), STAT=ierror ) 223 259 IF( ierror > 0 ) CALL ctl_stop( 'STOP', 'sbc_blk_init: unable to allocate sf structure' ) 224 DO ifpr= 1, jfld 225 ALLOCATE( sf(ifpr)%fnow(jpi,jpj,1) ) 226 IF( slf_i(ifpr)%ln_tint ) ALLOCATE( sf(ifpr)%fdta(jpi,jpj,1,2) ) 227 IF( slf_i(ifpr)%freqh > 0. .AND. MOD( NINT(3600. * slf_i(ifpr)%freqh), nn_fsbc * NINT(rdt) ) /= 0 ) & 228 & CALL ctl_warn( 'sbc_blk_init: sbcmod timestep rdt*nn_fsbc is NOT a submultiple of atmospheric forcing frequency.', & 229 & ' This is not ideal. You should consider changing either rdt or nn_fsbc value...' ) 230 260 ! 261 DO jfpr= 1, jpfld 262 ! 263 IF( TRIM(sf(jfpr)%clrootname) == 'NOT USED' ) THEN !-- not used field --! (only now allocated and set to zero) 264 ALLOCATE( sf(jfpr)%fnow(jpi,jpj,1) ) 265 sf(jfpr)%fnow(:,:,1) = 0._wp 266 ELSE !-- used field --! 267 IF( ln_abl .AND. & 268 & ( jfpr == jp_wndi .OR. jfpr == jp_wndj .OR. jfpr == jp_humi .OR. & 269 & jfpr == jp_hpgi .OR. jfpr == jp_hpgj .OR. jfpr == jp_tair ) ) THEN ! ABL: some fields are 3D input 270 ALLOCATE( sf(jfpr)%fnow(jpi,jpj,jpka) ) 271 IF( slf_i(jfpr)%ln_tint ) ALLOCATE( sf(jfpr)%fdta(jpi,jpj,jpka,2) ) 272 ELSE ! others or Bulk fields are 2D fiels 273 ALLOCATE( sf(jfpr)%fnow(jpi,jpj,1) ) 274 IF( slf_i(jfpr)%ln_tint ) ALLOCATE( sf(jfpr)%fdta(jpi,jpj,1,2) ) 275 ENDIF 276 ! 277 IF( slf_i(jfpr)%freqh > 0. .AND. MOD( NINT(3600. * slf_i(jfpr)%freqh), nn_fsbc * NINT(rdt) ) /= 0 ) & 278 & CALL ctl_warn( 'sbc_blk_init: sbcmod timestep rdt*nn_fsbc is NOT a submultiple of atmospheric forcing frequency.', & 279 & ' This is not ideal. You should consider changing either rdt or nn_fsbc value...' ) 280 ENDIF 231 281 END DO 232 282 ! !- fill the bulk structure with namelist informations 233 283 CALL fld_fill( sf, slf_i, cn_dir, 'sbc_blk_init', 'surface boundary condition -- bulk formulae', 'namsbc_blk' ) 234 284 ! 235 IF 236 !Activated wave module but neither drag nor stokes drift activated237 IF 285 IF( ln_wave ) THEN 286 !Activated wave module but neither drag nor stokes drift activated 287 IF( .NOT.(ln_cdgw .OR. ln_sdw .OR. ln_tauwoc .OR. ln_stcor ) ) THEN 238 288 CALL ctl_stop( 'STOP', 'Ask for wave coupling but ln_cdgw=F, ln_sdw=F, ln_tauwoc=F, ln_stcor=F' ) 239 !drag coefficient read from wave model definable only with mfs bulk formulae and core240 ELSEIF (ln_cdgw .AND. .NOT. ln_NCAR ) THEN241 242 ELSEIF 243 289 !drag coefficient read from wave model definable only with mfs bulk formulae and core 290 ELSEIF(ln_cdgw .AND. .NOT. ln_NCAR ) THEN 291 CALL ctl_stop( 'drag coefficient read from wave model definable only with NCAR and CORE bulk formulae') 292 ELSEIF(ln_stcor .AND. .NOT. ln_sdw) THEN 293 CALL ctl_stop( 'Stokes-Coriolis term calculated only if activated Stokes Drift ln_sdw=T') 244 294 ENDIF 245 295 ELSE 246 IF ( ln_cdgw .OR. ln_sdw .OR. ln_tauwoc .OR. ln_stcor ) & 247 & CALL ctl_stop( 'Not Activated Wave Module (ln_wave=F) but asked coupling ', & 248 & 'with drag coefficient (ln_cdgw =T) ' , & 249 & 'or Stokes Drift (ln_sdw=T) ' , & 250 & 'or ocean stress modification due to waves (ln_tauwoc=T) ', & 251 & 'or Stokes-Coriolis term (ln_stcori=T)' ) 252 ENDIF 253 ! 254 ! 296 IF( ln_cdgw .OR. ln_sdw .OR. ln_tauwoc .OR. ln_stcor ) & 297 & CALL ctl_stop( 'Not Activated Wave Module (ln_wave=F) but asked coupling ', & 298 & 'with drag coefficient (ln_cdgw =T) ' , & 299 & 'or Stokes Drift (ln_sdw=T) ' , & 300 & 'or ocean stress modification due to waves (ln_tauwoc=T) ', & 301 & 'or Stokes-Coriolis term (ln_stcori=T)' ) 302 ENDIF 303 ! 304 IF( ln_abl ) THEN ! ABL: read 3D fields for wind, temperature, humidity and pressure gradient 305 rn_zqt = ght_abl(2) ! set the bulk altitude to ABL first level 306 rn_zu = ght_abl(2) 307 IF(lwp) WRITE(numout,*) 308 IF(lwp) WRITE(numout,*) ' ABL formulation: overwrite rn_zqt & rn_zu with ABL first level altitude' 309 ENDIF 310 ! 311 ! set transfer coefficients to default sea-ice values 312 Cd_ice(:,:) = rCd_ice 313 Ch_ice(:,:) = rCd_ice 314 Ce_ice(:,:) = rCd_ice 315 ! 255 316 IF(lwp) THEN !** Control print 256 317 ! 257 WRITE(numout,*) !* namelist 318 WRITE(numout,*) !* namelist 258 319 WRITE(numout,*) ' Namelist namsbc_blk (other than data information):' 259 320 WRITE(numout,*) ' "NCAR" algorithm (Large and Yeager 2008) ln_NCAR = ', ln_NCAR 260 321 WRITE(numout,*) ' "COARE 3.0" algorithm (Fairall et al. 2003) ln_COARE_3p0 = ', ln_COARE_3p0 261 WRITE(numout,*) ' "COARE 3.5" algorithm (Edson et al. 2013) ln_COARE_3p5 = ', ln_COARE_3p0 262 WRITE(numout,*) ' "ECMWF" algorithm (IFS cycle 31) ln_ECMWF = ', ln_ECMWF 263 WRITE(numout,*) ' add High freq.contribution to the stress module ln_taudif = ', ln_taudif 322 WRITE(numout,*) ' "COARE 3.6" algorithm (Fairall 2018 + Edson al 2013)ln_COARE_3p6 = ', ln_COARE_3p6 323 WRITE(numout,*) ' "ECMWF" algorithm (IFS cycle 45r1) ln_ECMWF = ', ln_ECMWF 264 324 WRITE(numout,*) ' Air temperature and humidity reference height (m) rn_zqt = ', rn_zqt 265 325 WRITE(numout,*) ' Wind vector reference height (m) rn_zu = ', rn_zu … … 275 335 CASE( np_NCAR ) ; WRITE(numout,*) ' ==>>> "NCAR" algorithm (Large and Yeager 2008)' 276 336 CASE( np_COARE_3p0 ) ; WRITE(numout,*) ' ==>>> "COARE 3.0" algorithm (Fairall et al. 2003)' 277 CASE( np_COARE_3p 5 ) ; WRITE(numout,*) ' ==>>> "COARE 3.5" algorithm (Edson et al. 2013)'278 CASE( np_ECMWF ) ; WRITE(numout,*) ' ==>>> "ECMWF" algorithm (IFS cycle 31)'337 CASE( np_COARE_3p6 ) ; WRITE(numout,*) ' ==>>> "COARE 3.6" algorithm (Fairall 2018+Edson et al. 2013)' 338 CASE( np_ECMWF ) ; WRITE(numout,*) ' ==>>> "ECMWF" algorithm (IFS cycle 45r1)' 279 339 END SELECT 280 340 ! 341 WRITE(numout,*) 342 WRITE(numout,*) ' use cool-skin parameterization (SSST) ln_skin_cs = ', ln_skin_cs 343 WRITE(numout,*) ' use warm-layer parameterization (SSST) ln_skin_wl = ', ln_skin_wl 344 ! 345 WRITE(numout,*) 346 SELECT CASE( nhumi ) !* Print the choice of air humidity 347 CASE( np_humi_sph ) ; WRITE(numout,*) ' ==>>> air humidity is SPECIFIC HUMIDITY [kg/kg]' 348 CASE( np_humi_dpt ) ; WRITE(numout,*) ' ==>>> air humidity is DEW-POINT TEMPERATURE [K]' 349 CASE( np_humi_rlh ) ; WRITE(numout,*) ' ==>>> air humidity is RELATIVE HUMIDITY [%]' 350 END SELECT 351 ! 281 352 ENDIF 282 353 ! … … 291 362 !! (momentum, heat, freshwater and runoff) 292 363 !! 293 !! ** Method : (1) READ each fluxes in NetCDF files: 294 !! the 10m wind velocity (i-component) (m/s) at T-point 295 !! the 10m wind velocity (j-component) (m/s) at T-point 296 !! the 10m or 2m specific humidity ( % ) 297 !! the solar heat (W/m2) 298 !! the Long wave (W/m2) 299 !! the 10m or 2m air temperature (Kelvin) 300 !! the total precipitation (rain+snow) (Kg/m2/s) 301 !! the snow (solid prcipitation) (kg/m2/s) 302 !! the tau diff associated to HF tau (N/m2) at T-point (ln_taudif=T) 303 !! (2) CALL blk_oce 364 !! ** Method : 365 !! (1) READ each fluxes in NetCDF files: 366 !! the wind velocity (i-component) at z=rn_zu (m/s) at T-point 367 !! the wind velocity (j-component) at z=rn_zu (m/s) at T-point 368 !! the specific humidity at z=rn_zqt (kg/kg) 369 !! the air temperature at z=rn_zqt (Kelvin) 370 !! the solar heat (W/m2) 371 !! the Long wave (W/m2) 372 !! the total precipitation (rain+snow) (Kg/m2/s) 373 !! the snow (solid precipitation) (kg/m2/s) 374 !! ABL dynamical forcing (i/j-components of either hpg or geostrophic winds) 375 !! (2) CALL blk_oce_1 and blk_oce_2 304 376 !! 305 377 !! C A U T I O N : never mask the surface stress fields … … 318 390 !!---------------------------------------------------------------------- 319 391 INTEGER, INTENT(in) :: kt ! ocean time step 320 !!--------------------------------------------------------------------- 392 !!---------------------------------------------------------------------- 393 REAL(wp), DIMENSION(jpi,jpj) :: zssq, zcd_du, zsen, zevp 394 REAL(wp) :: ztmp 395 !!---------------------------------------------------------------------- 321 396 ! 322 397 CALL fld_read( kt, nn_fsbc, sf ) ! input fields provided at the current time-step 323 ! 398 399 ! Sanity/consistence test on humidity at first time step to detect potential screw-up: 400 IF( kt == nit000 ) THEN 401 IF(lwp) WRITE(numout,*) '' 402 #if defined key_agrif 403 IF(lwp) WRITE(numout,*) ' === AGRIF => Sanity/consistence test on air humidity SKIPPED! :( ===' 404 #else 405 ztmp = SUM(tmask(:,:,1)) ! number of ocean points on local proc domain 406 IF( ztmp > 8._wp ) THEN ! test only on proc domains with at least 8 ocean points! 407 ztmp = SUM(sf(jp_humi)%fnow(:,:,1)*tmask(:,:,1))/ztmp ! mean humidity over ocean on proc 408 SELECT CASE( nhumi ) 409 CASE( np_humi_sph ) ! specific humidity => expect: 0. <= something < 0.065 [kg/kg] (0.061 is saturation at 45degC !!!) 410 IF( (ztmp < 0._wp) .OR. (ztmp > 0.065) ) ztmp = -1._wp 411 CASE( np_humi_dpt ) ! dew-point temperature => expect: 110. <= something < 320. [K] 412 IF( (ztmp < 110._wp).OR.(ztmp > 320._wp) ) ztmp = -1._wp 413 CASE( np_humi_rlh ) ! relative humidity => expect: 0. <= something < 100. [%] 414 IF( (ztmp < 0._wp) .OR.(ztmp > 100._wp) ) ztmp = -1._wp 415 END SELECT 416 IF(ztmp < 0._wp) THEN 417 IF (lwp) WRITE(numout,'(" Mean humidity value found on proc #",i6.6," is: ",f10.5)') narea, ztmp 418 CALL ctl_stop( 'STOP', 'Something is wrong with air humidity!!!', & 419 & ' ==> check the unit in your input files' , & 420 & ' ==> check consistence of namelist choice: specific? relative? dew-point?', & 421 & ' ==> ln_humi_sph -> [kg/kg] | ln_humi_rlh -> [%] | ln_humi_dpt -> [K] !!!' ) 422 END IF 423 END IF 424 IF(lwp) WRITE(numout,*) ' === Sanity/consistence test on air humidity sucessfuly passed! ===' 425 #endif 426 IF(lwp) WRITE(numout,*) '' 427 END IF !IF( kt == nit000 ) 324 428 ! ! compute the surface ocean fluxes using bulk formulea 325 IF( MOD( kt - 1, nn_fsbc ) == 0 ) CALL blk_oce( kt, sf, sst_m, ssu_m, ssv_m ) 326 429 IF( MOD( kt - 1, nn_fsbc ) == 0 ) THEN 430 CALL blk_oce_1( kt, sf(jp_wndi)%fnow(:,:,1), sf(jp_wndj)%fnow(:,:,1), & ! <<= in 431 & sf(jp_tair)%fnow(:,:,1), sf(jp_humi)%fnow(:,:,1), & ! <<= in 432 & sf(jp_slp )%fnow(:,:,1), sst_m, ssu_m, ssv_m, & ! <<= in 433 & sf(jp_qsr )%fnow(:,:,1), sf(jp_qlw )%fnow(:,:,1), & ! <<= in (wl/cs) 434 & tsk_m, zssq, zcd_du, zsen, zevp ) ! =>> out 435 436 CALL blk_oce_2( sf(jp_tair)%fnow(:,:,1), sf(jp_qsr )%fnow(:,:,1), & ! <<= in 437 & sf(jp_qlw )%fnow(:,:,1), sf(jp_prec)%fnow(:,:,1), & ! <<= in 438 & sf(jp_snow)%fnow(:,:,1), tsk_m, & ! <<= in 439 & zsen, zevp ) ! <=> in out 440 ENDIF 441 ! 327 442 #if defined key_cice 328 443 IF( MOD( kt - 1, nn_fsbc ) == 0 ) THEN 329 444 qlw_ice(:,:,1) = sf(jp_qlw )%fnow(:,:,1) 330 IF( ln_dm2dc ) THEN ; qsr_ice(:,:,1) = sbc_dcy( sf(jp_qsr)%fnow(:,:,1) ) 331 ELSE ; qsr_ice(:,:,1) = sf(jp_qsr)%fnow(:,:,1) 332 ENDIF 445 IF( ln_dm2dc ) THEN 446 qsr_ice(:,:,1) = sbc_dcy( sf(jp_qsr)%fnow(:,:,1) ) 447 ELSE 448 qsr_ice(:,:,1) = sf(jp_qsr)%fnow(:,:,1) 449 ENDIF 333 450 tatm_ice(:,:) = sf(jp_tair)%fnow(:,:,1) 334 qatm_ice(:,:) = sf(jp_humi)%fnow(:,:,1) 451 452 SELECT CASE( nhumi ) 453 CASE( np_humi_sph ) 454 qatm_ice(:,:) = sf(jp_humi)%fnow(:,:,1) 455 CASE( np_humi_dpt ) 456 qatm_ice(:,:) = q_sat( sf(jp_humi)%fnow(:,:,1), sf(jp_slp)%fnow(:,:,1) ) 457 CASE( np_humi_rlh ) 458 qatm_ice(:,:) = q_air_rh( 0.01_wp*sf(jp_humi)%fnow(:,:,1), sf(jp_tair)%fnow(:,:,1), sf(jp_slp)%fnow(:,:,1)) !LB: 0.01 => RH is % percent in file 459 END SELECT 460 335 461 tprecip(:,:) = sf(jp_prec)%fnow(:,:,1) * rn_pfac 336 462 sprecip(:,:) = sf(jp_snow)%fnow(:,:,1) * rn_pfac … … 343 469 344 470 345 SUBROUTINE blk_oce( kt, sf, pst, pu, pv ) 346 !!--------------------------------------------------------------------- 347 !! *** ROUTINE blk_oce *** 348 !! 349 !! ** Purpose : provide the momentum, heat and freshwater fluxes at 350 !! the ocean surface at each time step 351 !! 352 !! ** Method : bulk formulea for the ocean using atmospheric 353 !! fields read in sbc_read 471 SUBROUTINE blk_oce_1( kt, pwndi, pwndj , ptair, phumi, & ! inp 472 & pslp , pst , pu , pv, & ! inp 473 & pqsr , pqlw , & ! inp 474 & ptsk, pssq , pcd_du, psen , pevp ) ! out 475 !!--------------------------------------------------------------------- 476 !! *** ROUTINE blk_oce_1 *** 477 !! 478 !! ** Purpose : if ln_blk=T, computes surface momentum, heat and freshwater fluxes 479 !! if ln_abl=T, computes Cd x |U|, Ch x |U|, Ce x |U| for ABL integration 480 !! 481 !! ** Method : bulk formulae using atmospheric fields from : 482 !! if ln_blk=T, atmospheric fields read in sbc_read 483 !! if ln_abl=T, the ABL model at previous time-step 484 !! 485 !! ** Outputs : - pssq : surface humidity used to compute latent heat flux (kg/kg) 486 !! - pcd_du : Cd x |dU| at T-points (m/s) 487 !! - psen : Ch x |dU| at T-points (m/s) 488 !! - pevp : Ce x |dU| at T-points (m/s) 489 !!--------------------------------------------------------------------- 490 INTEGER , INTENT(in ) :: kt ! time step index 491 REAL(wp), INTENT(in ), DIMENSION(:,:) :: pwndi ! atmospheric wind at U-point [m/s] 492 REAL(wp), INTENT(in ), DIMENSION(:,:) :: pwndj ! atmospheric wind at V-point [m/s] 493 REAL(wp), INTENT(in ), DIMENSION(:,:) :: phumi ! specific humidity at T-points [kg/kg] 494 REAL(wp), INTENT(in ), DIMENSION(:,:) :: ptair ! potential temperature at T-points [Kelvin] 495 REAL(wp), INTENT(in ), DIMENSION(:,:) :: pslp ! sea-level pressure [Pa] 496 REAL(wp), INTENT(in ), DIMENSION(:,:) :: pst ! surface temperature [Celsius] 497 REAL(wp), INTENT(in ), DIMENSION(:,:) :: pu ! surface current at U-point (i-component) [m/s] 498 REAL(wp), INTENT(in ), DIMENSION(:,:) :: pv ! surface current at V-point (j-component) [m/s] 499 REAL(wp), INTENT(in ), DIMENSION(:,:) :: pqsr ! 500 REAL(wp), INTENT(in ), DIMENSION(:,:) :: pqlw ! 501 REAL(wp), INTENT( out), DIMENSION(:,:) :: ptsk ! skin temp. (or SST if CS & WL not used) [Celsius] 502 REAL(wp), INTENT( out), DIMENSION(:,:) :: pssq ! specific humidity at pst [kg/kg] 503 REAL(wp), INTENT( out), DIMENSION(:,:) :: pcd_du ! Cd x |dU| at T-points [m/s] 504 REAL(wp), INTENT( out), DIMENSION(:,:) :: psen ! Ch x |dU| at T-points [m/s] 505 REAL(wp), INTENT( out), DIMENSION(:,:) :: pevp ! Ce x |dU| at T-points [m/s] 506 ! 507 INTEGER :: ji, jj ! dummy loop indices 508 REAL(wp) :: zztmp ! local variable 509 REAL(wp), DIMENSION(jpi,jpj) :: zwnd_i, zwnd_j ! wind speed components at T-point 510 REAL(wp), DIMENSION(jpi,jpj) :: zU_zu ! bulk wind speed at height zu [m/s] 511 REAL(wp), DIMENSION(jpi,jpj) :: ztpot ! potential temperature of air at z=rn_zqt [K] 512 REAL(wp), DIMENSION(jpi,jpj) :: zqair ! specific humidity of air at z=rn_zqt [kg/kg] 513 REAL(wp), DIMENSION(jpi,jpj) :: zcd_oce ! momentum transfert coefficient over ocean 514 REAL(wp), DIMENSION(jpi,jpj) :: zch_oce ! sensible heat transfert coefficient over ocean 515 REAL(wp), DIMENSION(jpi,jpj) :: zce_oce ! latent heat transfert coefficient over ocean 516 REAL(wp), DIMENSION(jpi,jpj) :: zqla ! latent heat flux 517 REAL(wp), DIMENSION(jpi,jpj) :: zztmp1, zztmp2 518 !!--------------------------------------------------------------------- 519 ! 520 ! local scalars ( place there for vector optimisation purposes) 521 ! ! Temporary conversion from Celcius to Kelvin (and set minimum value far above 0 K) 522 ptsk(:,:) = pst(:,:) + rt0 ! by default: skin temperature = "bulk SST" (will remain this way if NCAR algorithm used!) 523 524 ! ----------------------------------------------------------------------------- ! 525 ! 0 Wind components and module at T-point relative to the moving ocean ! 526 ! ----------------------------------------------------------------------------- ! 527 528 ! ... components ( U10m - U_oce ) at T-point (unmasked) 529 #if defined key_cyclone 530 zwnd_i(:,:) = 0._wp 531 zwnd_j(:,:) = 0._wp 532 CALL wnd_cyc( kt, zwnd_i, zwnd_j ) ! add analytical tropical cyclone (Vincent et al. JGR 2012) 533 DO_2D_00_00 534 pwndi(ji,jj) = pwndi(ji,jj) + zwnd_i(ji,jj) 535 pwndj(ji,jj) = pwndj(ji,jj) + zwnd_j(ji,jj) 536 END_2D 537 #endif 538 DO_2D_00_00 539 zwnd_i(ji,jj) = ( pwndi(ji,jj) - rn_vfac * 0.5 * ( pu(ji-1,jj ) + pu(ji,jj) ) ) 540 zwnd_j(ji,jj) = ( pwndj(ji,jj) - rn_vfac * 0.5 * ( pv(ji ,jj-1) + pv(ji,jj) ) ) 541 END_2D 542 CALL lbc_lnk_multi( 'sbcblk', zwnd_i, 'T', -1., zwnd_j, 'T', -1. ) 543 ! ... scalar wind ( = | U10m - U_oce | ) at T-point (masked) 544 wndm(:,:) = SQRT( zwnd_i(:,:) * zwnd_i(:,:) & 545 & + zwnd_j(:,:) * zwnd_j(:,:) ) * tmask(:,:,1) 546 547 ! ----------------------------------------------------------------------------- ! 548 ! I Solar FLUX ! 549 ! ----------------------------------------------------------------------------- ! 550 551 ! ocean albedo assumed to be constant + modify now Qsr to include the diurnal cycle ! Short Wave 552 zztmp = 1. - albo 553 IF( ln_dm2dc ) THEN 554 qsr(:,:) = zztmp * sbc_dcy( sf(jp_qsr)%fnow(:,:,1) ) * tmask(:,:,1) 555 ELSE 556 qsr(:,:) = zztmp * sf(jp_qsr)%fnow(:,:,1) * tmask(:,:,1) 557 ENDIF 558 559 560 ! ----------------------------------------------------------------------------- ! 561 ! II Turbulent FLUXES ! 562 ! ----------------------------------------------------------------------------- ! 563 564 ! specific humidity at SST 565 pssq(:,:) = rdct_qsat_salt * q_sat( ptsk(:,:), pslp(:,:) ) 566 567 IF( ln_skin_cs .OR. ln_skin_wl ) THEN 568 !! Backup "bulk SST" and associated spec. hum. 569 zztmp1(:,:) = ptsk(:,:) 570 zztmp2(:,:) = pssq(:,:) 571 ENDIF 572 573 ! specific humidity of air at "rn_zqt" m above the sea 574 SELECT CASE( nhumi ) 575 CASE( np_humi_sph ) 576 zqair(:,:) = phumi(:,:) ! what we read in file is already a spec. humidity! 577 CASE( np_humi_dpt ) 578 !IF(lwp) WRITE(numout,*) ' *** blk_oce => computing q_air out of d_air and slp !' !LBrm 579 zqair(:,:) = q_sat( phumi(:,:), pslp(:,:) ) 580 CASE( np_humi_rlh ) 581 !IF(lwp) WRITE(numout,*) ' *** blk_oce => computing q_air out of RH, t_air and slp !' !LBrm 582 zqair(:,:) = q_air_rh( 0.01_wp*phumi(:,:), ptair(:,:), pslp(:,:) ) !LB: 0.01 => RH is % percent in file 583 END SELECT 584 ! 585 ! potential temperature of air at "rn_zqt" m above the sea 586 IF( ln_abl ) THEN 587 ztpot = ptair(:,:) 588 ELSE 589 ! Estimate of potential temperature at z=rn_zqt, based on adiabatic lapse-rate 590 ! (see Josey, Gulev & Yu, 2013) / doi=10.1016/B978-0-12-391851-2.00005-2 591 ! (since reanalysis products provide T at z, not theta !) 592 !#LB: because AGRIF hates functions that return something else than a scalar, need to 593 ! use scalar version of gamma_moist() ... 594 DO_2D_11_11 595 ztpot(ji,jj) = ptair(ji,jj) + gamma_moist( ptair(ji,jj), zqair(ji,jj) ) * rn_zqt 596 END_2D 597 ENDIF 598 599 600 601 !! Time to call the user-selected bulk parameterization for 602 !! == transfer coefficients ==! Cd, Ch, Ce at T-point, and more... 603 SELECT CASE( nblk ) 604 605 CASE( np_NCAR ) 606 CALL turb_ncar ( rn_zqt, rn_zu, ptsk, ztpot, pssq, zqair, wndm, & 607 & zcd_oce, zch_oce, zce_oce, t_zu, q_zu, zU_zu, cdn_oce, chn_oce, cen_oce ) 608 609 CASE( np_COARE_3p0 ) 610 CALL turb_coare3p0 ( kt, rn_zqt, rn_zu, ptsk, ztpot, pssq, zqair, wndm, ln_skin_cs, ln_skin_wl, & 611 & zcd_oce, zch_oce, zce_oce, t_zu, q_zu, zU_zu, cdn_oce, chn_oce, cen_oce, & 612 & Qsw=qsr(:,:), rad_lw=pqlw(:,:), slp=pslp(:,:) ) 613 614 CASE( np_COARE_3p6 ) 615 CALL turb_coare3p6 ( kt, rn_zqt, rn_zu, ptsk, ztpot, pssq, zqair, wndm, ln_skin_cs, ln_skin_wl, & 616 & zcd_oce, zch_oce, zce_oce, t_zu, q_zu, zU_zu, cdn_oce, chn_oce, cen_oce, & 617 & Qsw=qsr(:,:), rad_lw=pqlw(:,:), slp=pslp(:,:) ) 618 619 CASE( np_ECMWF ) 620 CALL turb_ecmwf ( kt, rn_zqt, rn_zu, ptsk, ztpot, pssq, zqair, wndm, ln_skin_cs, ln_skin_wl, & 621 & zcd_oce, zch_oce, zce_oce, t_zu, q_zu, zU_zu, cdn_oce, chn_oce, cen_oce, & 622 & Qsw=qsr(:,:), rad_lw=pqlw(:,:), slp=pslp(:,:) ) 623 624 CASE DEFAULT 625 CALL ctl_stop( 'STOP', 'sbc_oce: non-existing bulk formula selected' ) 626 627 END SELECT 628 629 IF( ln_skin_cs .OR. ln_skin_wl ) THEN 630 !! ptsk and pssq have been updated!!! 631 !! 632 !! In the presence of sea-ice we forget about the cool-skin/warm-layer update of ptsk and pssq: 633 WHERE ( fr_i(:,:) > 0.001_wp ) 634 ! sea-ice present, we forget about the update, using what we backed up before call to turb_*() 635 ptsk(:,:) = zztmp1(:,:) 636 pssq(:,:) = zztmp2(:,:) 637 END WHERE 638 END IF 639 640 !! CALL iom_put( "Cd_oce", zcd_oce) ! output value of pure ocean-atm. transfer coef. 641 !! CALL iom_put( "Ch_oce", zch_oce) ! output value of pure ocean-atm. transfer coef. 642 643 IF( ABS(rn_zu - rn_zqt) < 0.1_wp ) THEN 644 !! If zu == zt, then ensuring once for all that: 645 t_zu(:,:) = ztpot(:,:) 646 q_zu(:,:) = zqair(:,:) 647 ENDIF 648 649 650 ! Turbulent fluxes over ocean => BULK_FORMULA @ sbcblk_phy.F90 651 ! ------------------------------------------------------------- 652 653 IF( ln_abl ) THEN !== ABL formulation ==! multiplication by rho_air and turbulent fluxes computation done in ablstp 654 !! FL do we need this multiplication by tmask ... ??? 655 DO_2D_11_11 656 zztmp = zU_zu(ji,jj) !* tmask(ji,jj,1) 657 wndm(ji,jj) = zztmp ! Store zU_zu in wndm to compute ustar2 in ablmod 658 pcd_du(ji,jj) = zztmp * zcd_oce(ji,jj) 659 psen(ji,jj) = zztmp * zch_oce(ji,jj) 660 pevp(ji,jj) = zztmp * zce_oce(ji,jj) 661 END_2D 662 ELSE !== BLK formulation ==! turbulent fluxes computation 663 CALL BULK_FORMULA( rn_zu, ptsk(:,:), pssq(:,:), t_zu(:,:), q_zu(:,:), & 664 & zcd_oce(:,:), zch_oce(:,:), zce_oce(:,:), & 665 & wndm(:,:), zU_zu(:,:), pslp(:,:), & 666 & taum(:,:), psen(:,:), zqla(:,:), & 667 & pEvap=pevp(:,:), prhoa=rhoa(:,:) ) 668 669 zqla(:,:) = zqla(:,:) * tmask(:,:,1) 670 psen(:,:) = psen(:,:) * tmask(:,:,1) 671 taum(:,:) = taum(:,:) * tmask(:,:,1) 672 pevp(:,:) = pevp(:,:) * tmask(:,:,1) 673 674 ! Tau i and j component on T-grid points, using array "zcd_oce" as a temporary array... 675 zcd_oce = 0._wp 676 WHERE ( wndm > 0._wp ) zcd_oce = taum / wndm 677 zwnd_i = zcd_oce * zwnd_i 678 zwnd_j = zcd_oce * zwnd_j 679 680 CALL iom_put( "taum_oce", taum ) ! output wind stress module 681 682 ! ... utau, vtau at U- and V_points, resp. 683 ! Note the use of 0.5*(2-umask) in order to unmask the stress along coastlines 684 ! Note the use of MAX(tmask(i,j),tmask(i+1,j) is to mask tau over ice shelves 685 DO_2D_10_10 686 utau(ji,jj) = 0.5 * ( 2. - umask(ji,jj,1) ) * ( zwnd_i(ji,jj) + zwnd_i(ji+1,jj ) ) & 687 & * MAX(tmask(ji,jj,1),tmask(ji+1,jj,1)) 688 vtau(ji,jj) = 0.5 * ( 2. - vmask(ji,jj,1) ) * ( zwnd_j(ji,jj) + zwnd_j(ji ,jj+1) ) & 689 & * MAX(tmask(ji,jj,1),tmask(ji,jj+1,1)) 690 END_2D 691 CALL lbc_lnk_multi( 'sbcblk', utau, 'U', -1., vtau, 'V', -1. ) 692 693 IF(sn_cfctl%l_prtctl) THEN 694 CALL prt_ctl( tab2d_1=wndm , clinfo1=' blk_oce_1: wndm : ') 695 CALL prt_ctl( tab2d_1=utau , clinfo1=' blk_oce_1: utau : ', mask1=umask, & 696 & tab2d_2=vtau , clinfo2=' vtau : ', mask2=vmask ) 697 ENDIF 698 ! 699 ENDIF !IF( ln_abl ) 700 701 ptsk(:,:) = ( ptsk(:,:) - rt0 ) * tmask(:,:,1) ! Back to Celsius 702 703 IF( ln_skin_cs .OR. ln_skin_wl ) THEN 704 CALL iom_put( "t_skin" , ptsk ) ! T_skin in Celsius 705 CALL iom_put( "dt_skin" , ptsk - pst ) ! T_skin - SST temperature difference... 706 ENDIF 707 708 IF(sn_cfctl%l_prtctl) THEN 709 CALL prt_ctl( tab2d_1=pevp , clinfo1=' blk_oce_1: pevp : ' ) 710 CALL prt_ctl( tab2d_1=psen , clinfo1=' blk_oce_1: psen : ' ) 711 CALL prt_ctl( tab2d_1=pssq , clinfo1=' blk_oce_1: pssq : ' ) 712 ENDIF 713 ! 714 END SUBROUTINE blk_oce_1 715 716 717 SUBROUTINE blk_oce_2( ptair, pqsr, pqlw, pprec, & ! <<= in 718 & psnow, ptsk, psen, pevp ) ! <<= in 719 !!--------------------------------------------------------------------- 720 !! *** ROUTINE blk_oce_2 *** 721 !! 722 !! ** Purpose : finalize the momentum, heat and freshwater fluxes computation 723 !! at the ocean surface at each time step knowing Cd, Ch, Ce and 724 !! atmospheric variables (from ABL or external data) 354 725 !! 355 726 !! ** Outputs : - utau : i-component of the stress at U-point (N/m2) … … 360 731 !! - qns : Non Solar heat flux over the ocean (W/m2) 361 732 !! - emp : evaporation minus precipitation (kg/m2/s) 362 !! 363 !! ** Nota : sf has to be a dummy argument for AGRIF on NEC 364 !!--------------------------------------------------------------------- 365 INTEGER , INTENT(in ) :: kt ! time step index 366 TYPE(fld), INTENT(inout), DIMENSION(:) :: sf ! input data 367 REAL(wp) , INTENT(in) , DIMENSION(:,:) :: pst ! surface temperature [Celcius] 368 REAL(wp) , INTENT(in) , DIMENSION(:,:) :: pu ! surface current at U-point (i-component) [m/s] 369 REAL(wp) , INTENT(in) , DIMENSION(:,:) :: pv ! surface current at V-point (j-component) [m/s] 733 !!--------------------------------------------------------------------- 734 REAL(wp), INTENT(in), DIMENSION(:,:) :: ptair 735 REAL(wp), INTENT(in), DIMENSION(:,:) :: pqsr 736 REAL(wp), INTENT(in), DIMENSION(:,:) :: pqlw 737 REAL(wp), INTENT(in), DIMENSION(:,:) :: pprec 738 REAL(wp), INTENT(in), DIMENSION(:,:) :: psnow 739 REAL(wp), INTENT(in), DIMENSION(:,:) :: ptsk ! SKIN surface temperature [Celsius] 740 REAL(wp), INTENT(in), DIMENSION(:,:) :: psen 741 REAL(wp), INTENT(in), DIMENSION(:,:) :: pevp 370 742 ! 371 743 INTEGER :: ji, jj ! dummy loop indices 372 REAL(wp) :: zztmp ! local variable 373 REAL(wp), DIMENSION(jpi,jpj) :: zwnd_i, zwnd_j ! wind speed components at T-point 374 REAL(wp), DIMENSION(jpi,jpj) :: zsq ! specific humidity at pst 375 REAL(wp), DIMENSION(jpi,jpj) :: zqlw, zqsb ! long wave and sensible heat fluxes 376 REAL(wp), DIMENSION(jpi,jpj) :: zqla, zevap ! latent heat fluxes and evaporation 377 REAL(wp), DIMENSION(jpi,jpj) :: zst ! surface temperature in Kelvin 378 REAL(wp), DIMENSION(jpi,jpj) :: zU_zu ! bulk wind speed at height zu [m/s] 379 REAL(wp), DIMENSION(jpi,jpj) :: ztpot ! potential temperature of air at z=rn_zqt [K] 380 REAL(wp), DIMENSION(jpi,jpj) :: zrhoa ! density of air [kg/m^3] 744 REAL(wp) :: zztmp,zz1,zz2,zz3 ! local variable 745 REAL(wp), DIMENSION(jpi,jpj) :: ztskk ! skin temp. in Kelvin 746 REAL(wp), DIMENSION(jpi,jpj) :: zqlw ! long wave and sensible heat fluxes 747 REAL(wp), DIMENSION(jpi,jpj) :: zqla ! latent heat fluxes and evaporation 381 748 !!--------------------------------------------------------------------- 382 749 ! 383 750 ! local scalars ( place there for vector optimisation purposes) 384 zst(:,:) = pst(:,:) + rt0 ! convert SST from Celcius to Kelvin (and set minimum value far above 0 K) 385 751 752 753 ztskk(:,:) = ptsk(:,:) + rt0 ! => ptsk in Kelvin rather than Celsius 754 386 755 ! ----------------------------------------------------------------------------- ! 387 ! 0 Wind components and module at T-point relative to the moving ocean!756 ! III Net longwave radiative FLUX ! 388 757 ! ----------------------------------------------------------------------------- ! 389 758 390 ! ... components ( U10m - U_oce ) at T-point (unmasked) 391 !!gm move zwnd_i (_j) set to zero inside the key_cyclone ??? 392 zwnd_i(:,:) = 0._wp 393 zwnd_j(:,:) = 0._wp 394 #if defined key_cyclone 395 CALL wnd_cyc( kt, zwnd_i, zwnd_j ) ! add analytical tropical cyclone (Vincent et al. JGR 2012) 396 DO jj = 2, jpjm1 397 DO ji = fs_2, fs_jpim1 ! vect. opt. 398 sf(jp_wndi)%fnow(ji,jj,1) = sf(jp_wndi)%fnow(ji,jj,1) + zwnd_i(ji,jj) 399 sf(jp_wndj)%fnow(ji,jj,1) = sf(jp_wndj)%fnow(ji,jj,1) + zwnd_j(ji,jj) 400 END DO 401 END DO 402 #endif 403 DO jj = 2, jpjm1 404 DO ji = fs_2, fs_jpim1 ! vect. opt. 405 zwnd_i(ji,jj) = ( sf(jp_wndi)%fnow(ji,jj,1) - rn_vfac * 0.5 * ( pu(ji-1,jj ) + pu(ji,jj) ) ) 406 zwnd_j(ji,jj) = ( sf(jp_wndj)%fnow(ji,jj,1) - rn_vfac * 0.5 * ( pv(ji ,jj-1) + pv(ji,jj) ) ) 407 END DO 408 END DO 409 CALL lbc_lnk_multi( 'sbcblk', zwnd_i, 'T', -1., zwnd_j, 'T', -1. ) 410 ! ... scalar wind ( = | U10m - U_oce | ) at T-point (masked) 411 wndm(:,:) = SQRT( zwnd_i(:,:) * zwnd_i(:,:) & 412 & + zwnd_j(:,:) * zwnd_j(:,:) ) * tmask(:,:,1) 759 !! LB: now moved after Turbulent fluxes because must use the skin temperature rather that the SST 760 !! (ztskk is skin temperature if ln_skin_cs==.TRUE. .OR. ln_skin_wl==.TRUE.) 761 zqlw(:,:) = emiss_w * ( pqlw(:,:) - stefan*ztskk(:,:)*ztskk(:,:)*ztskk(:,:)*ztskk(:,:) ) * tmask(:,:,1) ! Net radiative longwave flux 762 763 ! Latent flux over ocean 764 ! ----------------------- 765 766 ! use scalar version of L_vap() for AGRIF compatibility 767 DO_2D_11_11 768 zqla(ji,jj) = - L_vap( ztskk(ji,jj) ) * pevp(ji,jj) ! Latent Heat flux !!GS: possibility to add a global qla to avoid recomputation after abl update 769 END_2D 770 771 IF(sn_cfctl%l_prtctl) THEN 772 CALL prt_ctl( tab2d_1=zqla , clinfo1=' blk_oce_2: zqla : ' ) 773 CALL prt_ctl( tab2d_1=zqlw , clinfo1=' blk_oce_2: zqlw : ', tab2d_2=qsr, clinfo2=' qsr : ' ) 774 775 ENDIF 413 776 414 777 ! ----------------------------------------------------------------------------- ! 415 ! I Radiative FLUXES!778 ! IV Total FLUXES ! 416 779 ! ----------------------------------------------------------------------------- ! 417 418 ! ocean albedo assumed to be constant + modify now Qsr to include the diurnal cycle ! Short Wave 419 zztmp = 1. - albo 420 IF( ln_dm2dc ) THEN ; qsr(:,:) = zztmp * sbc_dcy( sf(jp_qsr)%fnow(:,:,1) ) * tmask(:,:,1) 421 ELSE ; qsr(:,:) = zztmp * sf(jp_qsr)%fnow(:,:,1) * tmask(:,:,1) 422 ENDIF 423 424 zqlw(:,:) = ( sf(jp_qlw)%fnow(:,:,1) - Stef * zst(:,:)*zst(:,:)*zst(:,:)*zst(:,:) ) * tmask(:,:,1) ! Long Wave 425 426 ! ----------------------------------------------------------------------------- ! 427 ! II Turbulent FLUXES ! 428 ! ----------------------------------------------------------------------------- ! 429 430 ! ... specific humidity at SST and IST tmask( 431 zsq(:,:) = 0.98 * q_sat( zst(:,:), sf(jp_slp)%fnow(:,:,1) ) 432 !! 433 !! Estimate of potential temperature at z=rn_zqt, based on adiabatic lapse-rate 434 !! (see Josey, Gulev & Yu, 2013) / doi=10.1016/B978-0-12-391851-2.00005-2 435 !! (since reanalysis products provide T at z, not theta !) 436 ztpot = sf(jp_tair)%fnow(:,:,1) + gamma_moist( sf(jp_tair)%fnow(:,:,1), sf(jp_humi)%fnow(:,:,1) ) * rn_zqt 437 438 SELECT CASE( nblk ) !== transfer coefficients ==! Cd, Ch, Ce at T-point 439 ! 440 CASE( np_NCAR ) ; CALL turb_ncar ( rn_zqt, rn_zu, zst, ztpot, zsq, sf(jp_humi)%fnow, wndm, & ! NCAR-COREv2 441 & Cd_atm, Ch_atm, Ce_atm, t_zu, q_zu, zU_zu, cdn_oce, chn_oce, cen_oce ) 442 CASE( np_COARE_3p0 ) ; CALL turb_coare ( rn_zqt, rn_zu, zst, ztpot, zsq, sf(jp_humi)%fnow, wndm, & ! COARE v3.0 443 & Cd_atm, Ch_atm, Ce_atm, t_zu, q_zu, zU_zu, cdn_oce, chn_oce, cen_oce ) 444 CASE( np_COARE_3p5 ) ; CALL turb_coare3p5( rn_zqt, rn_zu, zst, ztpot, zsq, sf(jp_humi)%fnow, wndm, & ! COARE v3.5 445 & Cd_atm, Ch_atm, Ce_atm, t_zu, q_zu, zU_zu, cdn_oce, chn_oce, cen_oce ) 446 CASE( np_ECMWF ) ; CALL turb_ecmwf ( rn_zqt, rn_zu, zst, ztpot, zsq, sf(jp_humi)%fnow, wndm, & ! ECMWF 447 & Cd_atm, Ch_atm, Ce_atm, t_zu, q_zu, zU_zu, cdn_oce, chn_oce, cen_oce ) 448 CASE DEFAULT 449 CALL ctl_stop( 'STOP', 'sbc_oce: non-existing bulk formula selected' ) 450 END SELECT 451 452 ! ! Compute true air density : 453 IF( ABS(rn_zu - rn_zqt) > 0.01 ) THEN ! At zu: (probably useless to remove zrho*grav*rn_zu from SLP...) 454 zrhoa(:,:) = rho_air( t_zu(:,:) , q_zu(:,:) , sf(jp_slp)%fnow(:,:,1) ) 455 ELSE ! At zt: 456 zrhoa(:,:) = rho_air( sf(jp_tair)%fnow(:,:,1), sf(jp_humi)%fnow(:,:,1), sf(jp_slp)%fnow(:,:,1) ) 457 END IF 458 459 !! CALL iom_put( "Cd_oce", Cd_atm) ! output value of pure ocean-atm. transfer coef. 460 !! CALL iom_put( "Ch_oce", Ch_atm) ! output value of pure ocean-atm. transfer coef. 461 462 DO jj = 1, jpj ! tau module, i and j component 463 DO ji = 1, jpi 464 zztmp = zrhoa(ji,jj) * zU_zu(ji,jj) * Cd_atm(ji,jj) ! using bulk wind speed 465 taum (ji,jj) = zztmp * wndm (ji,jj) 466 zwnd_i(ji,jj) = zztmp * zwnd_i(ji,jj) 467 zwnd_j(ji,jj) = zztmp * zwnd_j(ji,jj) 468 END DO 469 END DO 470 471 ! ! add the HF tau contribution to the wind stress module 472 IF( lhftau ) taum(:,:) = taum(:,:) + sf(jp_tdif)%fnow(:,:,1) 473 474 CALL iom_put( "taum_oce", taum ) ! output wind stress module 475 476 ! ... utau, vtau at U- and V_points, resp. 477 ! Note the use of 0.5*(2-umask) in order to unmask the stress along coastlines 478 ! Note the use of MAX(tmask(i,j),tmask(i+1,j) is to mask tau over ice shelves 479 DO jj = 1, jpjm1 480 DO ji = 1, fs_jpim1 481 utau(ji,jj) = 0.5 * ( 2. - umask(ji,jj,1) ) * ( zwnd_i(ji,jj) + zwnd_i(ji+1,jj ) ) & 482 & * MAX(tmask(ji,jj,1),tmask(ji+1,jj,1)) 483 vtau(ji,jj) = 0.5 * ( 2. - vmask(ji,jj,1) ) * ( zwnd_j(ji,jj) + zwnd_j(ji ,jj+1) ) & 484 & * MAX(tmask(ji,jj,1),tmask(ji,jj+1,1)) 485 END DO 486 END DO 487 CALL lbc_lnk_multi( 'sbcblk', utau, 'U', -1., vtau, 'V', -1. ) 488 489 ! Turbulent fluxes over ocean 490 ! ----------------------------- 491 492 ! zqla used as temporary array, for rho*U (common term of bulk formulae): 493 zqla(:,:) = zrhoa(:,:) * zU_zu(:,:) * tmask(:,:,1) 494 495 IF( ABS( rn_zu - rn_zqt) < 0.01_wp ) THEN 496 !! q_air and t_air are given at 10m (wind reference height) 497 zevap(:,:) = rn_efac*MAX( 0._wp, zqla(:,:)*Ce_atm(:,:)*(zsq(:,:) - sf(jp_humi)%fnow(:,:,1)) ) ! Evaporation, using bulk wind speed 498 zqsb (:,:) = cp_air(sf(jp_humi)%fnow(:,:,1))*zqla(:,:)*Ch_atm(:,:)*(zst(:,:) - ztpot(:,:) ) ! Sensible Heat, using bulk wind speed 499 ELSE 500 !! q_air and t_air are not given at 10m (wind reference height) 501 ! Values of temp. and hum. adjusted to height of wind during bulk algorithm iteration must be used!!! 502 zevap(:,:) = rn_efac*MAX( 0._wp, zqla(:,:)*Ce_atm(:,:)*(zsq(:,:) - q_zu(:,:) ) ) ! Evaporation, using bulk wind speed 503 zqsb (:,:) = cp_air(sf(jp_humi)%fnow(:,:,1))*zqla(:,:)*Ch_atm(:,:)*(zst(:,:) - t_zu(:,:) ) ! Sensible Heat, using bulk wind speed 504 ENDIF 505 506 zqla(:,:) = L_vap(zst(:,:)) * zevap(:,:) ! Latent Heat flux 507 508 509 IF(ln_ctl) THEN 510 CALL prt_ctl( tab2d_1=zqla , clinfo1=' blk_oce: zqla : ', tab2d_2=Ce_atm , clinfo2=' Ce_oce : ' ) 511 CALL prt_ctl( tab2d_1=zqsb , clinfo1=' blk_oce: zqsb : ', tab2d_2=Ch_atm , clinfo2=' Ch_oce : ' ) 512 CALL prt_ctl( tab2d_1=zqlw , clinfo1=' blk_oce: zqlw : ', tab2d_2=qsr, clinfo2=' qsr : ' ) 513 CALL prt_ctl( tab2d_1=zsq , clinfo1=' blk_oce: zsq : ', tab2d_2=zst, clinfo2=' zst : ' ) 514 CALL prt_ctl( tab2d_1=utau , clinfo1=' blk_oce: utau : ', mask1=umask, & 515 & tab2d_2=vtau , clinfo2= ' vtau : ', mask2=vmask ) 516 CALL prt_ctl( tab2d_1=wndm , clinfo1=' blk_oce: wndm : ') 517 CALL prt_ctl( tab2d_1=zst , clinfo1=' blk_oce: zst : ') 518 ENDIF 519 520 ! ----------------------------------------------------------------------------- ! 521 ! III Total FLUXES ! 522 ! ----------------------------------------------------------------------------- ! 523 ! 524 emp (:,:) = ( zevap(:,:) & ! mass flux (evap. - precip.) 525 & - sf(jp_prec)%fnow(:,:,1) * rn_pfac ) * tmask(:,:,1) 526 ! 527 qns(:,:) = zqlw(:,:) - zqsb(:,:) - zqla(:,:) & ! Downward Non Solar 528 & - sf(jp_snow)%fnow(:,:,1) * rn_pfac * rLfus & ! remove latent melting heat for solid precip 529 & - zevap(:,:) * pst(:,:) * rcp & ! remove evap heat content at SST 530 & + ( sf(jp_prec)%fnow(:,:,1) - sf(jp_snow)%fnow(:,:,1) ) * rn_pfac & ! add liquid precip heat content at Tair 531 & * ( sf(jp_tair)%fnow(:,:,1) - rt0 ) * rcp & 532 & + sf(jp_snow)%fnow(:,:,1) * rn_pfac & ! add solid precip heat content at min(Tair,Tsnow) 533 & * ( MIN( sf(jp_tair)%fnow(:,:,1), rt0 ) - rt0 ) * rcpi 780 ! 781 emp (:,:) = ( pevp(:,:) & ! mass flux (evap. - precip.) 782 & - pprec(:,:) * rn_pfac ) * tmask(:,:,1) 783 ! 784 qns(:,:) = zqlw(:,:) + psen(:,:) + zqla(:,:) & ! Downward Non Solar 785 & - psnow(:,:) * rn_pfac * rLfus & ! remove latent melting heat for solid precip 786 & - pevp(:,:) * ptsk(:,:) * rcp & ! remove evap heat content at SST 787 & + ( pprec(:,:) - psnow(:,:) ) * rn_pfac & ! add liquid precip heat content at Tair 788 & * ( ptair(:,:) - rt0 ) * rcp & 789 & + psnow(:,:) * rn_pfac & ! add solid precip heat content at min(Tair,Tsnow) 790 & * ( MIN( ptair(:,:), rt0 ) - rt0 ) * rcpi 534 791 qns(:,:) = qns(:,:) * tmask(:,:,1) 535 792 ! 536 793 #if defined key_si3 537 qns_oce(:,:) = zqlw(:,:) - zqsb(:,:) - zqla(:,:)! non solar without emp (only needed by SI3)794 qns_oce(:,:) = zqlw(:,:) + psen(:,:) + zqla(:,:) ! non solar without emp (only needed by SI3) 538 795 qsr_oce(:,:) = qsr(:,:) 539 796 #endif 540 797 ! 798 CALL iom_put( "rho_air" , rhoa*tmask(:,:,1) ) ! output air density [kg/m^3] 799 CALL iom_put( "evap_oce" , pevp ) ! evaporation 800 CALL iom_put( "qlw_oce" , zqlw ) ! output downward longwave heat over the ocean 801 CALL iom_put( "qsb_oce" , psen ) ! output downward sensible heat over the ocean 802 CALL iom_put( "qla_oce" , zqla ) ! output downward latent heat over the ocean 803 tprecip(:,:) = pprec(:,:) * rn_pfac * tmask(:,:,1) ! output total precipitation [kg/m2/s] 804 sprecip(:,:) = psnow(:,:) * rn_pfac * tmask(:,:,1) ! output solid precipitation [kg/m2/s] 805 CALL iom_put( 'snowpre', sprecip ) ! Snow 806 CALL iom_put( 'precip' , tprecip ) ! Total precipitation 807 ! 541 808 IF ( nn_ice == 0 ) THEN 542 CALL iom_put( "qlw_oce" , zqlw ) ! output downward longwave heat over the ocean 543 CALL iom_put( "qsb_oce" , - zqsb ) ! output downward sensible heat over the ocean 544 CALL iom_put( "qla_oce" , - zqla ) ! output downward latent heat over the ocean 545 CALL iom_put( "qemp_oce", qns-zqlw+zqsb+zqla ) ! output downward heat content of E-P over the ocean 546 CALL iom_put( "qns_oce" , qns ) ! output downward non solar heat over the ocean 547 CALL iom_put( "qsr_oce" , qsr ) ! output downward solar heat over the ocean 548 CALL iom_put( "qt_oce" , qns+qsr ) ! output total downward heat over the ocean 549 tprecip(:,:) = sf(jp_prec)%fnow(:,:,1) * rn_pfac * tmask(:,:,1) ! output total precipitation [kg/m2/s] 550 sprecip(:,:) = sf(jp_snow)%fnow(:,:,1) * rn_pfac * tmask(:,:,1) ! output solid precipitation [kg/m2/s] 551 CALL iom_put( 'snowpre', sprecip ) ! Snow 552 CALL iom_put( 'precip' , tprecip ) ! Total precipitation 553 ENDIF 554 ! 555 IF(ln_ctl) THEN 556 CALL prt_ctl(tab2d_1=zqsb , clinfo1=' blk_oce: zqsb : ', tab2d_2=zqlw , clinfo2=' zqlw : ') 557 CALL prt_ctl(tab2d_1=zqla , clinfo1=' blk_oce: zqla : ', tab2d_2=qsr , clinfo2=' qsr : ') 558 CALL prt_ctl(tab2d_1=pst , clinfo1=' blk_oce: pst : ', tab2d_2=emp , clinfo2=' emp : ') 559 CALL prt_ctl(tab2d_1=utau , clinfo1=' blk_oce: utau : ', mask1=umask, & 560 & tab2d_2=vtau , clinfo2= ' vtau : ' , mask2=vmask ) 561 ENDIF 562 ! 563 END SUBROUTINE blk_oce 564 565 566 567 FUNCTION rho_air( ptak, pqa, pslp ) 568 !!------------------------------------------------------------------------------- 569 !! *** FUNCTION rho_air *** 570 !! 571 !! ** Purpose : compute density of (moist) air using the eq. of state of the atmosphere 572 !! 573 !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk) 574 !!------------------------------------------------------------------------------- 575 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: ptak ! air temperature [K] 576 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pqa ! air specific humidity [kg/kg] 577 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pslp ! pressure in [Pa] 578 REAL(wp), DIMENSION(jpi,jpj) :: rho_air ! density of moist air [kg/m^3] 579 !!------------------------------------------------------------------------------- 580 ! 581 rho_air = pslp / ( R_dry*ptak * ( 1._wp + rctv0*pqa ) ) 582 ! 583 END FUNCTION rho_air 584 585 586 FUNCTION cp_air( pqa ) 587 !!------------------------------------------------------------------------------- 588 !! *** FUNCTION cp_air *** 589 !! 590 !! ** Purpose : Compute specific heat (Cp) of moist air 591 !! 592 !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk) 593 !!------------------------------------------------------------------------------- 594 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pqa ! air specific humidity [kg/kg] 595 REAL(wp), DIMENSION(jpi,jpj) :: cp_air ! specific heat of moist air [J/K/kg] 596 !!------------------------------------------------------------------------------- 597 ! 598 Cp_air = Cp_dry + Cp_vap * pqa 599 ! 600 END FUNCTION cp_air 601 602 603 FUNCTION q_sat( ptak, pslp ) 604 !!---------------------------------------------------------------------------------- 605 !! *** FUNCTION q_sat *** 606 !! 607 !! ** Purpose : Specific humidity at saturation in [kg/kg] 608 !! Based on accurate estimate of "e_sat" 609 !! aka saturation water vapor (Goff, 1957) 610 !! 611 !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk) 612 !!---------------------------------------------------------------------------------- 613 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: ptak ! air temperature [K] 614 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pslp ! sea level atmospheric pressure [Pa] 615 REAL(wp), DIMENSION(jpi,jpj) :: q_sat ! Specific humidity at saturation [kg/kg] 616 ! 617 INTEGER :: ji, jj ! dummy loop indices 618 REAL(wp) :: ze_sat, ztmp ! local scalar 619 !!---------------------------------------------------------------------------------- 620 ! 621 DO jj = 1, jpj 622 DO ji = 1, jpi 623 ! 624 ztmp = rt0 / ptak(ji,jj) 625 ! 626 ! Vapour pressure at saturation [hPa] : WMO, (Goff, 1957) 627 ze_sat = 10.**( 10.79574*(1. - ztmp) - 5.028*LOG10(ptak(ji,jj)/rt0) & 628 & + 1.50475*10.**(-4)*(1. - 10.**(-8.2969*(ptak(ji,jj)/rt0 - 1.)) ) & 629 & + 0.42873*10.**(-3)*(10.**(4.76955*(1. - ztmp)) - 1.) + 0.78614 ) 630 ! 631 q_sat(ji,jj) = reps0 * ze_sat/( 0.01_wp*pslp(ji,jj) - (1._wp - reps0)*ze_sat ) ! 0.01 because SLP is in [Pa] 632 ! 633 END DO 634 END DO 635 ! 636 END FUNCTION q_sat 637 638 639 FUNCTION gamma_moist( ptak, pqa ) 640 !!---------------------------------------------------------------------------------- 641 !! *** FUNCTION gamma_moist *** 642 !! 643 !! ** Purpose : Compute the moist adiabatic lapse-rate. 644 !! => http://glossary.ametsoc.org/wiki/Moist-adiabatic_lapse_rate 645 !! => http://www.geog.ucsb.edu/~joel/g266_s10/lecture_notes/chapt03/oh10_3_01/oh10_3_01.html 646 !! 647 !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk) 648 !!---------------------------------------------------------------------------------- 649 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: ptak ! air temperature [K] 650 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pqa ! specific humidity [kg/kg] 651 REAL(wp), DIMENSION(jpi,jpj) :: gamma_moist ! moist adiabatic lapse-rate 652 ! 653 INTEGER :: ji, jj ! dummy loop indices 654 REAL(wp) :: zrv, ziRT ! local scalar 655 !!---------------------------------------------------------------------------------- 656 ! 657 DO jj = 1, jpj 658 DO ji = 1, jpi 659 zrv = pqa(ji,jj) / (1. - pqa(ji,jj)) 660 ziRT = 1. / (R_dry*ptak(ji,jj)) ! 1/RT 661 gamma_moist(ji,jj) = grav * ( 1. + rLevap*zrv*ziRT ) / ( Cp_dry + rLevap*rLevap*zrv*reps0*ziRT/ptak(ji,jj) ) 662 END DO 663 END DO 664 ! 665 END FUNCTION gamma_moist 666 667 668 FUNCTION L_vap( psst ) 669 !!--------------------------------------------------------------------------------- 670 !! *** FUNCTION L_vap *** 671 !! 672 !! ** Purpose : Compute the latent heat of vaporization of water from temperature 673 !! 674 !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk) 675 !!---------------------------------------------------------------------------------- 676 REAL(wp), DIMENSION(jpi,jpj) :: L_vap ! latent heat of vaporization [J/kg] 677 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: psst ! water temperature [K] 678 !!---------------------------------------------------------------------------------- 679 ! 680 L_vap = ( 2.501 - 0.00237 * ( psst(:,:) - rt0) ) * 1.e6 681 ! 682 END FUNCTION L_vap 809 CALL iom_put( "qemp_oce" , qns-zqlw-psen-zqla ) ! output downward heat content of E-P over the ocean 810 CALL iom_put( "qns_oce" , qns ) ! output downward non solar heat over the ocean 811 CALL iom_put( "qsr_oce" , qsr ) ! output downward solar heat over the ocean 812 CALL iom_put( "qt_oce" , qns+qsr ) ! output total downward heat over the ocean 813 ENDIF 814 ! 815 IF(sn_cfctl%l_prtctl) THEN 816 CALL prt_ctl(tab2d_1=zqlw , clinfo1=' blk_oce_2: zqlw : ') 817 CALL prt_ctl(tab2d_1=zqla , clinfo1=' blk_oce_2: zqla : ', tab2d_2=qsr , clinfo2=' qsr : ') 818 CALL prt_ctl(tab2d_1=emp , clinfo1=' blk_oce_2: emp : ') 819 ENDIF 820 ! 821 END SUBROUTINE blk_oce_2 822 683 823 684 824 #if defined key_si3 … … 686 826 !! 'key_si3' SI3 sea-ice model 687 827 !!---------------------------------------------------------------------- 688 !! blk_ice_ tau: provide the air-ice stress689 !! blk_ice_ flx: provide the heat and mass fluxes at air-ice interface828 !! blk_ice_1 : provide the air-ice stress 829 !! blk_ice_2 : provide the heat and mass fluxes at air-ice interface 690 830 !! blk_ice_qcn : provide ice surface temperature and snow/ice conduction flux (emulating conduction flux) 691 831 !! Cdn10_Lupkes2012 : Lupkes et al. (2012) air-ice drag 692 !! Cdn10_Lupkes2015 : Lupkes et al. (2015) air-ice drag 832 !! Cdn10_Lupkes2015 : Lupkes et al. (2015) air-ice drag 693 833 !!---------------------------------------------------------------------- 694 834 695 SUBROUTINE blk_ice_tau 696 !!--------------------------------------------------------------------- 697 !! *** ROUTINE blk_ice_tau *** 835 SUBROUTINE blk_ice_1( pwndi, pwndj, ptair, phumi, pslp , puice, pvice, ptsui, & ! inputs 836 & putaui, pvtaui, pseni, pevpi, pssqi, pcd_dui ) ! optional outputs 837 !!--------------------------------------------------------------------- 838 !! *** ROUTINE blk_ice_1 *** 698 839 !! 699 840 !! ** Purpose : provide the surface boundary condition over sea-ice … … 703 844 !! NB: ice drag coefficient is assumed to be a constant 704 845 !!--------------------------------------------------------------------- 846 REAL(wp) , INTENT(in ), DIMENSION(:,: ) :: pslp ! sea-level pressure [Pa] 847 REAL(wp) , INTENT(in ), DIMENSION(:,: ) :: pwndi ! atmospheric wind at T-point [m/s] 848 REAL(wp) , INTENT(in ), DIMENSION(:,: ) :: pwndj ! atmospheric wind at T-point [m/s] 849 REAL(wp) , INTENT(in ), DIMENSION(:,: ) :: ptair ! atmospheric wind at T-point [m/s] 850 REAL(wp) , INTENT(in ), DIMENSION(:,: ) :: phumi ! atmospheric wind at T-point [m/s] 851 REAL(wp) , INTENT(in ), DIMENSION(:,: ) :: puice ! sea-ice velocity on I or C grid [m/s] 852 REAL(wp) , INTENT(in ), DIMENSION(:,: ) :: pvice ! " 853 REAL(wp) , INTENT(in ), DIMENSION(:,: ) :: ptsui ! sea-ice surface temperature [K] 854 REAL(wp) , INTENT( out), DIMENSION(:,: ), OPTIONAL :: putaui ! if ln_blk 855 REAL(wp) , INTENT( out), DIMENSION(:,: ), OPTIONAL :: pvtaui ! if ln_blk 856 REAL(wp) , INTENT( out), DIMENSION(:,: ), OPTIONAL :: pseni ! if ln_abl 857 REAL(wp) , INTENT( out), DIMENSION(:,: ), OPTIONAL :: pevpi ! if ln_abl 858 REAL(wp) , INTENT( out), DIMENSION(:,: ), OPTIONAL :: pssqi ! if ln_abl 859 REAL(wp) , INTENT( out), DIMENSION(:,: ), OPTIONAL :: pcd_dui ! if ln_abl 860 ! 705 861 INTEGER :: ji, jj ! dummy loop indices 706 REAL(wp) :: zwndi_f , zwndj_f, zwnorm_f ! relative wind module and components at F-point707 862 REAL(wp) :: zwndi_t , zwndj_t ! relative wind components at T-point 708 REAL(wp), DIMENSION(jpi,jpj) :: zrhoa ! transfer coefficient for momentum (tau) 709 !!--------------------------------------------------------------------- 710 ! 711 ! set transfer coefficients to default sea-ice values 712 Cd_atm(:,:) = Cd_ice 713 Ch_atm(:,:) = Cd_ice 714 Ce_atm(:,:) = Cd_ice 715 716 wndm_ice(:,:) = 0._wp !!gm brutal.... 863 REAL(wp) :: zootm_su ! sea-ice surface mean temperature 864 REAL(wp) :: zztmp1, zztmp2 ! temporary arrays 865 REAL(wp), DIMENSION(jpi,jpj) :: zcd_dui ! transfer coefficient for momentum (tau) 866 !!--------------------------------------------------------------------- 867 ! 717 868 718 869 ! ------------------------------------------------------------ ! … … 720 871 ! ------------------------------------------------------------ ! 721 872 ! C-grid ice dynamics : U & V-points (same as ocean) 722 DO jj = 2, jpjm1 723 DO ji = fs_2, fs_jpim1 ! vect. opt. 724 zwndi_t = ( sf(jp_wndi)%fnow(ji,jj,1) - rn_vfac * 0.5 * ( u_ice(ji-1,jj ) + u_ice(ji,jj) ) ) 725 zwndj_t = ( sf(jp_wndj)%fnow(ji,jj,1) - rn_vfac * 0.5 * ( v_ice(ji ,jj-1) + v_ice(ji,jj) ) ) 726 wndm_ice(ji,jj) = SQRT( zwndi_t * zwndi_t + zwndj_t * zwndj_t ) * tmask(ji,jj,1) 727 END DO 728 END DO 873 DO_2D_00_00 874 zwndi_t = ( pwndi(ji,jj) - rn_vfac * 0.5_wp * ( puice(ji-1,jj ) + puice(ji,jj) ) ) 875 zwndj_t = ( pwndj(ji,jj) - rn_vfac * 0.5_wp * ( pvice(ji ,jj-1) + pvice(ji,jj) ) ) 876 wndm_ice(ji,jj) = SQRT( zwndi_t * zwndi_t + zwndj_t * zwndj_t ) * tmask(ji,jj,1) 877 END_2D 729 878 CALL lbc_lnk( 'sbcblk', wndm_ice, 'T', 1. ) 730 879 ! 731 880 ! Make ice-atm. drag dependent on ice concentration 732 881 IF ( ln_Cd_L12 ) THEN ! calculate new drag from Lupkes(2012) equations 733 CALL Cdn10_Lupkes2012( Cd_atm ) 734 Ch_atm(:,:) = Cd_atm(:,:) ! momentum and heat transfer coef. are considered identical 882 CALL Cdn10_Lupkes2012( Cd_ice ) 883 Ch_ice(:,:) = Cd_ice(:,:) ! momentum and heat transfer coef. are considered identical 884 Ce_ice(:,:) = Cd_ice(:,:) 735 885 ELSEIF( ln_Cd_L15 ) THEN ! calculate new drag from Lupkes(2015) equations 736 CALL Cdn10_Lupkes2015( Cd_atm, Ch_atm ) 737 ENDIF 738 739 !! CALL iom_put( "Cd_ice", Cd_atm) ! output value of pure ice-atm. transfer coef. 740 !! CALL iom_put( "Ch_ice", Ch_atm) ! output value of pure ice-atm. transfer coef. 886 CALL Cdn10_Lupkes2015( ptsui, pslp, Cd_ice, Ch_ice ) 887 Ce_ice(:,:) = Ch_ice(:,:) ! sensible and latent heat transfer coef. are considered identical 888 ENDIF 889 890 !! IF ( iom_use("Cd_ice") ) CALL iom_put("Cd_ice", Cd_ice) ! output value of pure ice-atm. transfer coef. 891 !! IF ( iom_use("Ch_ice") ) CALL iom_put("Ch_ice", Ch_ice) ! output value of pure ice-atm. transfer coef. 741 892 742 893 ! local scalars ( place there for vector optimisation purposes) 743 ! Computing density of air! Way denser that 1.2 over sea-ice !!! 744 zrhoa (:,:) = rho_air(sf(jp_tair)%fnow(:,:,1), sf(jp_humi)%fnow(:,:,1), sf(jp_slp)%fnow(:,:,1)) 745 746 !!gm brutal.... 747 utau_ice (:,:) = 0._wp 748 vtau_ice (:,:) = 0._wp 749 !!gm end 750 751 ! ------------------------------------------------------------ ! 752 ! Wind stress relative to the moving ice ( U10m - U_ice ) ! 753 ! ------------------------------------------------------------ ! 754 ! C-grid ice dynamics : U & V-points (same as ocean) 755 DO jj = 2, jpjm1 756 DO ji = fs_2, fs_jpim1 ! vect. opt. 757 utau_ice(ji,jj) = 0.5 * zrhoa(ji,jj) * Cd_atm(ji,jj) * ( wndm_ice(ji+1,jj ) + wndm_ice(ji,jj) ) & 758 & * ( 0.5 * (sf(jp_wndi)%fnow(ji+1,jj,1) + sf(jp_wndi)%fnow(ji,jj,1) ) - rn_vfac * u_ice(ji,jj) ) 759 vtau_ice(ji,jj) = 0.5 * zrhoa(ji,jj) * Cd_atm(ji,jj) * ( wndm_ice(ji,jj+1 ) + wndm_ice(ji,jj) ) & 760 & * ( 0.5 * (sf(jp_wndj)%fnow(ji,jj+1,1) + sf(jp_wndj)%fnow(ji,jj,1) ) - rn_vfac * v_ice(ji,jj) ) 761 END DO 762 END DO 763 CALL lbc_lnk_multi( 'sbcblk', utau_ice, 'U', -1., vtau_ice, 'V', -1. ) 764 ! 765 ! 766 IF(ln_ctl) THEN 767 CALL prt_ctl(tab2d_1=utau_ice , clinfo1=' blk_ice: utau_ice : ', tab2d_2=vtau_ice , clinfo2=' vtau_ice : ') 768 CALL prt_ctl(tab2d_1=wndm_ice , clinfo1=' blk_ice: wndm_ice : ') 769 ENDIF 770 ! 771 END SUBROUTINE blk_ice_tau 772 773 774 SUBROUTINE blk_ice_flx( ptsu, phs, phi, palb ) 775 !!--------------------------------------------------------------------- 776 !! *** ROUTINE blk_ice_flx *** 894 !IF (ln_abl) rhoa (:,:) = rho_air( ptair(:,:), phumi(:,:), pslp(:,:) ) !!GS: rhoa must be (re)computed here with ABL to avoid division by zero after (TBI) 895 zcd_dui(:,:) = wndm_ice(:,:) * Cd_ice(:,:) 896 897 IF( ln_blk ) THEN 898 ! ------------------------------------------------------------ ! 899 ! Wind stress relative to the moving ice ( U10m - U_ice ) ! 900 ! ------------------------------------------------------------ ! 901 ! C-grid ice dynamics : U & V-points (same as ocean) 902 DO_2D_00_00 903 putaui(ji,jj) = 0.5_wp * ( rhoa(ji+1,jj) * zcd_dui(ji+1,jj) & 904 & + rhoa(ji ,jj) * zcd_dui(ji ,jj) ) & 905 & * ( 0.5_wp * ( pwndi(ji+1,jj) + pwndi(ji,jj) ) - rn_vfac * puice(ji,jj) ) 906 pvtaui(ji,jj) = 0.5_wp * ( rhoa(ji,jj+1) * zcd_dui(ji,jj+1) & 907 & + rhoa(ji,jj ) * zcd_dui(ji,jj ) ) & 908 & * ( 0.5_wp * ( pwndj(ji,jj+1) + pwndj(ji,jj) ) - rn_vfac * pvice(ji,jj) ) 909 END_2D 910 CALL lbc_lnk_multi( 'sbcblk', putaui, 'U', -1., pvtaui, 'V', -1. ) 911 ! 912 IF(sn_cfctl%l_prtctl) CALL prt_ctl( tab2d_1=putaui , clinfo1=' blk_ice: putaui : ' & 913 & , tab2d_2=pvtaui , clinfo2=' pvtaui : ' ) 914 ELSE 915 zztmp1 = 11637800.0_wp 916 zztmp2 = -5897.8_wp 917 DO_2D_11_11 918 pcd_dui(ji,jj) = zcd_dui (ji,jj) 919 pseni (ji,jj) = wndm_ice(ji,jj) * Ch_ice(ji,jj) 920 pevpi (ji,jj) = wndm_ice(ji,jj) * Ce_ice(ji,jj) 921 zootm_su = zztmp2 / ptsui(ji,jj) ! ptsui is in K (it can't be zero ??) 922 pssqi (ji,jj) = zztmp1 * EXP( zootm_su ) / rhoa(ji,jj) 923 END_2D 924 ENDIF 925 ! 926 IF(sn_cfctl%l_prtctl) CALL prt_ctl(tab2d_1=wndm_ice , clinfo1=' blk_ice: wndm_ice : ') 927 ! 928 END SUBROUTINE blk_ice_1 929 930 931 SUBROUTINE blk_ice_2( ptsu, phs, phi, palb, ptair, phumi, pslp, pqlw, pprec, psnow ) 932 !!--------------------------------------------------------------------- 933 !! *** ROUTINE blk_ice_2 *** 777 934 !! 778 935 !! ** Purpose : provide the heat and mass fluxes at air-ice interface … … 784 941 !! caution : the net upward water flux has with mm/day unit 785 942 !!--------------------------------------------------------------------- 786 REAL(wp), DIMENSION(:,:,:), INTENT(in) :: ptsu ! sea ice surface temperature 943 REAL(wp), DIMENSION(:,:,:), INTENT(in) :: ptsu ! sea ice surface temperature [K] 787 944 REAL(wp), DIMENSION(:,:,:), INTENT(in) :: phs ! snow thickness 788 945 REAL(wp), DIMENSION(:,:,:), INTENT(in) :: phi ! ice thickness 789 946 REAL(wp), DIMENSION(:,:,:), INTENT(in) :: palb ! ice albedo (all skies) 947 REAL(wp), DIMENSION(:,: ), INTENT(in) :: ptair 948 REAL(wp), DIMENSION(:,: ), INTENT(in) :: phumi 949 REAL(wp), DIMENSION(:,: ), INTENT(in) :: pslp 950 REAL(wp), DIMENSION(:,: ), INTENT(in) :: pqlw 951 REAL(wp), DIMENSION(:,: ), INTENT(in) :: pprec 952 REAL(wp), DIMENSION(:,: ), INTENT(in) :: psnow 790 953 !! 791 954 INTEGER :: ji, jj, jl ! dummy loop indices 792 955 REAL(wp) :: zst3 ! local variable 793 956 REAL(wp) :: zcoef_dqlw, zcoef_dqla ! - - 794 REAL(wp) :: zztmp, z 1_rLsub! - -957 REAL(wp) :: zztmp, zztmp2, z1_rLsub ! - - 795 958 REAL(wp) :: zfr1, zfr2 ! local variables 796 959 REAL(wp), DIMENSION(jpi,jpj,jpl) :: z1_st ! inverse of surface temperature … … 800 963 REAL(wp), DIMENSION(jpi,jpj,jpl) :: z_dqsb ! sensible heat sensitivity over ice 801 964 REAL(wp), DIMENSION(jpi,jpj) :: zevap, zsnw ! evaporation and snw distribution after wind blowing (SI3) 802 REAL(wp), DIMENSION(jpi,jpj) :: z rhoa965 REAL(wp), DIMENSION(jpi,jpj) :: zqair ! specific humidity of air at z=rn_zqt [kg/kg] !LB 803 966 REAL(wp), DIMENSION(jpi,jpj) :: ztmp, ztmp2 804 967 !!--------------------------------------------------------------------- 805 968 ! 806 zcoef_dqlw = 4.0 * 0.95 * Stef ! local scalars 807 zcoef_dqla = -Ls * 11637800. * (-5897.8) 808 ! 809 zrhoa(:,:) = rho_air( sf(jp_tair)%fnow(:,:,1), sf(jp_humi)%fnow(:,:,1), sf(jp_slp)%fnow(:,:,1) ) 969 zcoef_dqlw = 4._wp * 0.95_wp * stefan ! local scalars 970 zcoef_dqla = -rLsub * 11637800._wp * (-5897.8_wp) !LB: BAD! 971 ! 972 SELECT CASE( nhumi ) 973 CASE( np_humi_sph ) 974 zqair(:,:) = phumi(:,:) ! what we read in file is already a spec. humidity! 975 CASE( np_humi_dpt ) 976 zqair(:,:) = q_sat( phumi(:,:), pslp ) 977 CASE( np_humi_rlh ) 978 zqair(:,:) = q_air_rh( 0.01_wp*phumi(:,:), ptair(:,:), pslp(:,:) ) !LB: 0.01 => RH is % percent in file 979 END SELECT 810 980 ! 811 981 zztmp = 1. / ( 1. - albo ) 812 WHERE( ptsu(:,:,:) /= 0._wp ) ; z1_st(:,:,:) = 1._wp / ptsu(:,:,:) 813 ELSEWHERE ; z1_st(:,:,:) = 0._wp 982 WHERE( ptsu(:,:,:) /= 0._wp ) 983 z1_st(:,:,:) = 1._wp / ptsu(:,:,:) 984 ELSEWHERE 985 z1_st(:,:,:) = 0._wp 814 986 END WHERE 815 987 ! ! ========================== ! … … 825 997 qsr_ice(ji,jj,jl) = zztmp * ( 1. - palb(ji,jj,jl) ) * qsr(ji,jj) 826 998 ! Long Wave (lw) 827 z_qlw(ji,jj,jl) = 0.95 * ( sf(jp_qlw)%fnow(ji,jj,1) - Stef* ptsu(ji,jj,jl) * zst3 ) * tmask(ji,jj,1)999 z_qlw(ji,jj,jl) = 0.95 * ( pqlw(ji,jj) - stefan * ptsu(ji,jj,jl) * zst3 ) * tmask(ji,jj,1) 828 1000 ! lw sensitivity 829 1001 z_dqlw(ji,jj,jl) = zcoef_dqlw * zst3 … … 833 1005 ! ----------------------------! 834 1006 835 ! ... turbulent heat fluxes with Ch_ atm recalculated in blk_ice_tau1007 ! ... turbulent heat fluxes with Ch_ice recalculated in blk_ice_1 836 1008 ! Sensible Heat 837 z_qsb(ji,jj,jl) = zrhoa(ji,jj) * cpa * Ch_atm(ji,jj) * wndm_ice(ji,jj) * (ptsu(ji,jj,jl) - sf(jp_tair)%fnow(ji,jj,1))1009 z_qsb(ji,jj,jl) = rhoa(ji,jj) * rCp_air * Ch_ice(ji,jj) * wndm_ice(ji,jj) * (ptsu(ji,jj,jl) - ptair(ji,jj)) 838 1010 ! Latent Heat 839 qla_ice(ji,jj,jl) = rn_efac * MAX( 0.e0, zrhoa(ji,jj) * Ls * Ch_atm(ji,jj) * wndm_ice(ji,jj) * & 840 & ( 11637800. * EXP( -5897.8 * z1_st(ji,jj,jl) ) / zrhoa(ji,jj) - sf(jp_humi)%fnow(ji,jj,1) ) ) 1011 zztmp2 = EXP( -5897.8 * z1_st(ji,jj,jl) ) 1012 qla_ice(ji,jj,jl) = rn_efac * MAX( 0.e0, rhoa(ji,jj) * rLsub * Ce_ice(ji,jj) * wndm_ice(ji,jj) * & 1013 & ( 11637800. * zztmp2 / rhoa(ji,jj) - zqair(ji,jj) ) ) 841 1014 ! Latent heat sensitivity for ice (Dqla/Dt) 842 1015 IF( qla_ice(ji,jj,jl) > 0._wp ) THEN 843 dqla_ice(ji,jj,jl) = rn_efac * zcoef_dqla * C h_atm(ji,jj) * wndm_ice(ji,jj) * &844 & z1_st(ji,jj,jl) *z1_st(ji,jj,jl) * EXP(-5897.8 * z1_st(ji,jj,jl))1016 dqla_ice(ji,jj,jl) = rn_efac * zcoef_dqla * Ce_ice(ji,jj) * wndm_ice(ji,jj) * & 1017 & z1_st(ji,jj,jl) * z1_st(ji,jj,jl) * zztmp2 845 1018 ELSE 846 1019 dqla_ice(ji,jj,jl) = 0._wp … … 848 1021 849 1022 ! Sensible heat sensitivity (Dqsb_ice/Dtn_ice) 850 z_dqsb(ji,jj,jl) = zrhoa(ji,jj) * cpa * Ch_atm(ji,jj) * wndm_ice(ji,jj)1023 z_dqsb(ji,jj,jl) = rhoa(ji,jj) * rCp_air * Ch_ice(ji,jj) * wndm_ice(ji,jj) 851 1024 852 1025 ! ----------------------------! … … 863 1036 END DO 864 1037 ! 865 tprecip(:,:) = sf(jp_prec)%fnow(:,:,1) * rn_pfac * tmask(:,:,1) ! total precipitation [kg/m2/s]866 sprecip(:,:) = sf(jp_snow)%fnow(:,:,1) * rn_pfac * tmask(:,:,1) ! solid precipitation [kg/m2/s]867 CALL iom_put( 'snowpre', sprecip ) 868 CALL iom_put( 'precip' , tprecip ) 1038 tprecip(:,:) = pprec(:,:) * rn_pfac * tmask(:,:,1) ! total precipitation [kg/m2/s] 1039 sprecip(:,:) = psnow(:,:) * rn_pfac * tmask(:,:,1) ! solid precipitation [kg/m2/s] 1040 CALL iom_put( 'snowpre', sprecip ) ! Snow precipitation 1041 CALL iom_put( 'precip' , tprecip ) ! Total precipitation 869 1042 870 1043 ! --- evaporation --- ! … … 883 1056 ! --- heat flux associated with emp --- ! 884 1057 qemp_oce(:,:) = - ( 1._wp - at_i_b(:,:) ) * zevap(:,:) * sst_m(:,:) * rcp & ! evap at sst 885 & + ( tprecip(:,:) - sprecip(:,:) ) * ( sf(jp_tair)%fnow(:,:,1) - rt0 ) * rcp& ! liquid precip at Tair1058 & + ( tprecip(:,:) - sprecip(:,:) ) * ( ptair(:,:) - rt0 ) * rcp & ! liquid precip at Tair 886 1059 & + sprecip(:,:) * ( 1._wp - zsnw ) * & ! solid precip at min(Tair,Tsnow) 887 & ( ( MIN( sf(jp_tair)%fnow(:,:,1), rt0 ) - rt0 ) * rcpi * tmask(:,:,1) - rLfus )1060 & ( ( MIN( ptair(:,:), rt0 ) - rt0 ) * rcpi * tmask(:,:,1) - rLfus ) 888 1061 qemp_ice(:,:) = sprecip(:,:) * zsnw * & ! solid precip (only) 889 & ( ( MIN( sf(jp_tair)%fnow(:,:,1), rt0 ) - rt0 ) * rcpi * tmask(:,:,1) - rLfus )1062 & ( ( MIN( ptair(:,:), rt0 ) - rt0 ) * rcpi * tmask(:,:,1) - rLfus ) 890 1063 891 1064 ! --- total solar and non solar fluxes --- ! … … 895 1068 896 1069 ! --- heat content of precip over ice in J/m3 (to be used in 1D-thermo) --- ! 897 qprec_ice(:,:) = rhos * ( ( MIN( sf(jp_tair)%fnow(:,:,1), rt0 ) - rt0 ) * rcpi * tmask(:,:,1) - rLfus )1070 qprec_ice(:,:) = rhos * ( ( MIN( ptair(:,:), rt0 ) - rt0 ) * rcpi * tmask(:,:,1) - rLfus ) 898 1071 899 1072 ! --- heat content of evap over ice in W/m2 (to be used in 1D-thermo) --- 900 1073 DO jl = 1, jpl 901 1074 qevap_ice(:,:,jl) = 0._wp ! should be -evap_ice(:,:,jl)*( ( Tice - rt0 ) * rcpi * tmask(:,:,1) ) 902 ! ! But we do not have Tice => consider it at 0degC => evap=0 1075 ! ! But we do not have Tice => consider it at 0degC => evap=0 903 1076 END DO 904 1077 … … 907 1080 zfr2 = ( 0.82 * ( 1.0 - cldf_ice ) + 0.65 * cldf_ice ) ! zfr2 such that zfr1 + zfr2 to equal 1 908 1081 ! 909 WHERE ( phs(:,:,:) <= 0._wp .AND. phi(:,:,:) < 0.1_wp ) ! linear decrease from hi=0 to 10cm 1082 WHERE ( phs(:,:,:) <= 0._wp .AND. phi(:,:,:) < 0.1_wp ) ! linear decrease from hi=0 to 10cm 910 1083 qtr_ice_top(:,:,:) = qsr_ice(:,:,:) * ( zfr1 + zfr2 * ( 1._wp - phi(:,:,:) * 10._wp ) ) 911 1084 ELSEWHERE( phs(:,:,:) <= 0._wp .AND. phi(:,:,:) >= 0.1_wp ) ! constant (zfr1) when hi>10cm 912 1085 qtr_ice_top(:,:,:) = qsr_ice(:,:,:) * zfr1 913 1086 ELSEWHERE ! zero when hs>0 914 qtr_ice_top(:,:,:) = 0._wp 1087 qtr_ice_top(:,:,:) = 0._wp 915 1088 END WHERE 916 1089 ! 917 1090 918 1091 IF( iom_use('evap_ao_cea') .OR. iom_use('hflx_evap_cea') ) THEN 919 ztmp(:,:) = zevap(:,:) * ( 1._wp - at_i_b(:,:) ) 920 CALL iom_put( 'evap_ao_cea' , ztmp(:,:) * tmask(:,:,1) ) ! ice-free oce evap (cell average)921 CALL iom_put( 'hflx_evap_cea', ztmp(:,:) * sst_m(:,:) * rcp * tmask(:,:,1) ) ! heat flux from evap (cell average)1092 ztmp(:,:) = zevap(:,:) * ( 1._wp - at_i_b(:,:) ) 1093 IF( iom_use('evap_ao_cea' ) ) CALL iom_put( 'evap_ao_cea' , ztmp(:,:) * tmask(:,:,1) ) ! ice-free oce evap (cell average) 1094 IF( iom_use('hflx_evap_cea') ) CALL iom_put( 'hflx_evap_cea', ztmp(:,:) * sst_m(:,:) * rcp * tmask(:,:,1) ) ! heat flux from evap (cell average) 922 1095 ENDIF 923 1096 IF( iom_use('hflx_rain_cea') ) THEN 924 1097 ztmp(:,:) = rcp * ( SUM( (ptsu-rt0) * a_i_b, dim=3 ) + sst_m(:,:) * ( 1._wp - at_i_b(:,:) ) ) 925 CALL iom_put( 'hflx_rain_cea', ( tprecip(:,:) - sprecip(:,:) ) * ztmp(:,:) ) ! heat flux from rain (cell average)1098 IF( iom_use('hflx_rain_cea') ) CALL iom_put( 'hflx_rain_cea', ( tprecip(:,:) - sprecip(:,:) ) * ztmp(:,:) ) ! heat flux from rain (cell average) 926 1099 ENDIF 927 1100 IF( iom_use('hflx_snow_cea') .OR. iom_use('hflx_snow_ao_cea') .OR. iom_use('hflx_snow_ai_cea') ) THEN 928 WHERE( SUM( a_i_b, dim=3 ) > 1.e-10 ) ; ztmp(:,:) = rcpi * SUM( (ptsu-rt0) * a_i_b, dim=3 ) / SUM( a_i_b, dim=3 ) 929 ELSEWHERE ; ztmp(:,:) = rcp * sst_m(:,:) 930 ENDWHERE 931 ztmp2(:,:) = sprecip(:,:) * ( ztmp(:,:) - rLfus ) 932 CALL iom_put('hflx_snow_cea' , ztmp2(:,:) ) ! heat flux from snow (cell average) 933 CALL iom_put('hflx_snow_ao_cea', ztmp2(:,:) * ( 1._wp - zsnw(:,:) ) ) ! heat flux from snow (over ocean) 934 CALL iom_put('hflx_snow_ai_cea', ztmp2(:,:) * zsnw(:,:) ) ! heat flux from snow (over ice) 935 ENDIF 936 ! 937 IF(ln_ctl) THEN 1101 WHERE( SUM( a_i_b, dim=3 ) > 1.e-10 ) 1102 ztmp(:,:) = rcpi * SUM( (ptsu-rt0) * a_i_b, dim=3 ) / SUM( a_i_b, dim=3 ) 1103 ELSEWHERE 1104 ztmp(:,:) = rcp * sst_m(:,:) 1105 ENDWHERE 1106 ztmp2(:,:) = sprecip(:,:) * ( ztmp(:,:) - rLfus ) 1107 IF( iom_use('hflx_snow_cea') ) CALL iom_put('hflx_snow_cea' , ztmp2(:,:) ) ! heat flux from snow (cell average) 1108 IF( iom_use('hflx_snow_ao_cea') ) CALL iom_put('hflx_snow_ao_cea', ztmp2(:,:) * ( 1._wp - zsnw(:,:) ) ) ! heat flux from snow (over ocean) 1109 IF( iom_use('hflx_snow_ai_cea') ) CALL iom_put('hflx_snow_ai_cea', ztmp2(:,:) * zsnw(:,:) ) ! heat flux from snow (over ice) 1110 ENDIF 1111 ! 1112 IF(sn_cfctl%l_prtctl) THEN 938 1113 CALL prt_ctl(tab3d_1=qla_ice , clinfo1=' blk_ice: qla_ice : ', tab3d_2=z_qsb , clinfo2=' z_qsb : ', kdim=jpl) 939 1114 CALL prt_ctl(tab3d_1=z_qlw , clinfo1=' blk_ice: z_qlw : ', tab3d_2=dqla_ice, clinfo2=' dqla_ice : ', kdim=jpl) … … 944 1119 ENDIF 945 1120 ! 946 END SUBROUTINE blk_ice_ flx947 1121 END SUBROUTINE blk_ice_2 1122 948 1123 949 1124 SUBROUTINE blk_ice_qcn( ld_virtual_itd, ptsu, ptb, phs, phi ) … … 954 1129 !! to force sea ice / snow thermodynamics 955 1130 !! in the case conduction flux is emulated 956 !! 1131 !! 957 1132 !! ** Method : compute surface energy balance assuming neglecting heat storage 958 1133 !! following the 0-layer Semtner (1976) approach … … 979 1154 REAL(wp), DIMENSION(jpi,jpj,jpl) :: zgfac ! enhanced conduction factor 980 1155 !!--------------------------------------------------------------------- 981 1156 982 1157 ! -------------------------------------! 983 1158 ! I Enhanced conduction factor ! … … 987 1162 ! 988 1163 zgfac(:,:,:) = 1._wp 989 1164 990 1165 IF( ld_virtual_itd ) THEN 991 1166 ! … … 993 1168 zfac2 = EXP(1._wp) * 0.5_wp * zepsilon 994 1169 zfac3 = 2._wp / zepsilon 995 ! 996 DO jl = 1, jpl 997 DO jj = 1 , jpj 998 DO ji = 1, jpi 999 zhe = ( rn_cnd_s * phi(ji,jj,jl) + rcnd_i * phs(ji,jj,jl) ) * zfac ! Effective thickness 1000 IF( zhe >= zfac2 ) zgfac(ji,jj,jl) = MIN( 2._wp, 0.5_wp * ( 1._wp + LOG( zhe * zfac3 ) ) ) ! Enhanced conduction factor 1001 END DO 1002 END DO 1170 ! 1171 DO jl = 1, jpl 1172 DO_2D_11_11 1173 zhe = ( rn_cnd_s * phi(ji,jj,jl) + rcnd_i * phs(ji,jj,jl) ) * zfac ! Effective thickness 1174 IF( zhe >= zfac2 ) zgfac(ji,jj,jl) = MIN( 2._wp, 0.5_wp * ( 1._wp + LOG( zhe * zfac3 ) ) ) ! Enhanced conduction factor 1175 END_2D 1003 1176 END DO 1004 ! 1005 ENDIF 1006 1177 ! 1178 ENDIF 1179 1007 1180 ! -------------------------------------------------------------! 1008 1181 ! II Surface temperature and conduction flux ! … … 1012 1185 ! 1013 1186 DO jl = 1, jpl 1014 DO jj = 1 , jpj 1015 DO ji = 1, jpi 1016 ! 1017 zkeff_h = zfac * zgfac(ji,jj,jl) / & ! Effective conductivity of the snow-ice system divided by thickness 1018 & ( rcnd_i * phs(ji,jj,jl) + rn_cnd_s * MAX( 0.01, phi(ji,jj,jl) ) ) 1019 ztsu = ptsu(ji,jj,jl) ! Store current iteration temperature 1020 ztsu0 = ptsu(ji,jj,jl) ! Store initial surface temperature 1021 zqa0 = qsr_ice(ji,jj,jl) - qtr_ice_top(ji,jj,jl) + qns_ice(ji,jj,jl) ! Net initial atmospheric heat flux 1022 ! 1023 DO iter = 1, nit ! --- Iterative loop 1024 zqc = zkeff_h * ( ztsu - ptb(ji,jj) ) ! Conduction heat flux through snow-ice system (>0 downwards) 1025 zqnet = zqa0 + dqns_ice(ji,jj,jl) * ( ztsu - ptsu(ji,jj,jl) ) - zqc ! Surface energy budget 1026 ztsu = ztsu - zqnet / ( dqns_ice(ji,jj,jl) - zkeff_h ) ! Temperature update 1027 END DO 1028 ! 1029 ptsu (ji,jj,jl) = MIN( rt0, ztsu ) 1030 qcn_ice(ji,jj,jl) = zkeff_h * ( ptsu(ji,jj,jl) - ptb(ji,jj) ) 1031 qns_ice(ji,jj,jl) = qns_ice(ji,jj,jl) + dqns_ice(ji,jj,jl) * ( ptsu(ji,jj,jl) - ztsu0 ) 1032 qml_ice(ji,jj,jl) = ( qsr_ice(ji,jj,jl) - qtr_ice_top(ji,jj,jl) + qns_ice(ji,jj,jl) - qcn_ice(ji,jj,jl) ) & 1033 & * MAX( 0._wp , SIGN( 1._wp, ptsu(ji,jj,jl) - rt0 ) ) 1034 1035 ! --- Diagnose the heat loss due to changing non-solar flux (as in icethd_zdf_bl99) --- ! 1036 hfx_err_dif(ji,jj) = hfx_err_dif(ji,jj) - ( dqns_ice(ji,jj,jl) * ( ptsu(ji,jj,jl) - ztsu0 ) ) * a_i_b(ji,jj,jl) 1037 1187 DO_2D_11_11 1188 ! 1189 zkeff_h = zfac * zgfac(ji,jj,jl) / & ! Effective conductivity of the snow-ice system divided by thickness 1190 & ( rcnd_i * phs(ji,jj,jl) + rn_cnd_s * MAX( 0.01, phi(ji,jj,jl) ) ) 1191 ztsu = ptsu(ji,jj,jl) ! Store current iteration temperature 1192 ztsu0 = ptsu(ji,jj,jl) ! Store initial surface temperature 1193 zqa0 = qsr_ice(ji,jj,jl) - qtr_ice_top(ji,jj,jl) + qns_ice(ji,jj,jl) ! Net initial atmospheric heat flux 1194 ! 1195 DO iter = 1, nit ! --- Iterative loop 1196 zqc = zkeff_h * ( ztsu - ptb(ji,jj) ) ! Conduction heat flux through snow-ice system (>0 downwards) 1197 zqnet = zqa0 + dqns_ice(ji,jj,jl) * ( ztsu - ptsu(ji,jj,jl) ) - zqc ! Surface energy budget 1198 ztsu = ztsu - zqnet / ( dqns_ice(ji,jj,jl) - zkeff_h ) ! Temperature update 1038 1199 END DO 1039 END DO 1200 ! 1201 ptsu (ji,jj,jl) = MIN( rt0, ztsu ) 1202 qcn_ice(ji,jj,jl) = zkeff_h * ( ptsu(ji,jj,jl) - ptb(ji,jj) ) 1203 qns_ice(ji,jj,jl) = qns_ice(ji,jj,jl) + dqns_ice(ji,jj,jl) * ( ptsu(ji,jj,jl) - ztsu0 ) 1204 qml_ice(ji,jj,jl) = ( qsr_ice(ji,jj,jl) - qtr_ice_top(ji,jj,jl) + qns_ice(ji,jj,jl) - qcn_ice(ji,jj,jl) ) & 1205 & * MAX( 0._wp , SIGN( 1._wp, ptsu(ji,jj,jl) - rt0 ) ) 1206 1207 ! --- Diagnose the heat loss due to changing non-solar flux (as in icethd_zdf_bl99) --- ! 1208 hfx_err_dif(ji,jj) = hfx_err_dif(ji,jj) - ( dqns_ice(ji,jj,jl) * ( ptsu(ji,jj,jl) - ztsu0 ) ) * a_i_b(ji,jj,jl) 1209 1210 END_2D 1040 1211 ! 1041 END DO 1042 ! 1212 END DO 1213 ! 1043 1214 END SUBROUTINE blk_ice_qcn 1044 1045 1046 SUBROUTINE Cdn10_Lupkes2012( Cd )1215 1216 1217 SUBROUTINE Cdn10_Lupkes2012( pcd ) 1047 1218 !!---------------------------------------------------------------------- 1048 1219 !! *** ROUTINE Cdn10_Lupkes2012 *** 1049 1220 !! 1050 !! ** Purpose : Recompute the neutral air-ice drag referenced at 10m 1221 !! ** Purpose : Recompute the neutral air-ice drag referenced at 10m 1051 1222 !! to make it dependent on edges at leads, melt ponds and flows. 1052 1223 !! After some approximations, this can be resumed to a dependency 1053 1224 !! on ice concentration. 1054 !! 1225 !! 1055 1226 !! ** Method : The parameterization is taken from Lupkes et al. (2012) eq.(50) 1056 1227 !! with the highest level of approximation: level4, eq.(59) … … 1064 1235 !! 1065 1236 !! This new drag has a parabolic shape (as a function of A) starting at 1066 !! Cdw(say 1.5e-3) for A=0, reaching 1.97e-3 for A~0.5 1237 !! Cdw(say 1.5e-3) for A=0, reaching 1.97e-3 for A~0.5 1067 1238 !! and going down to Cdi(say 1.4e-3) for A=1 1068 1239 !! … … 1074 1245 !! 1075 1246 !!---------------------------------------------------------------------- 1076 REAL(wp), DIMENSION(:,:), INTENT(inout) :: Cd1247 REAL(wp), DIMENSION(:,:), INTENT(inout) :: pcd 1077 1248 REAL(wp), PARAMETER :: zCe = 2.23e-03_wp 1078 1249 REAL(wp), PARAMETER :: znu = 1._wp … … 1089 1260 1090 1261 ! ice-atm drag 1091 Cd(:,:) =Cd_ice + & ! pure ice drag1092 & zCe * ( 1._wp - at_i_b(:,:) )**zcoef * at_i_b(:,:)**(zmu-1._wp) ! change due to sea-ice morphology1093 1262 pcd(:,:) = rCd_ice + & ! pure ice drag 1263 & zCe * ( 1._wp - at_i_b(:,:) )**zcoef * at_i_b(:,:)**(zmu-1._wp) ! change due to sea-ice morphology 1264 1094 1265 END SUBROUTINE Cdn10_Lupkes2012 1095 1266 1096 1267 1097 SUBROUTINE Cdn10_Lupkes2015( Cd, Ch )1268 SUBROUTINE Cdn10_Lupkes2015( ptm_su, pslp, pcd, pch ) 1098 1269 !!---------------------------------------------------------------------- 1099 1270 !! *** ROUTINE Cdn10_Lupkes2015 *** 1100 1271 !! 1101 1272 !! ** pUrpose : Alternative turbulent transfert coefficients formulation 1102 !! between sea-ice and atmosphere with distinct momentum 1103 !! and heat coefficients depending on sea-ice concentration 1273 !! between sea-ice and atmosphere with distinct momentum 1274 !! and heat coefficients depending on sea-ice concentration 1104 1275 !! and atmospheric stability (no meltponds effect for now). 1105 !! 1276 !! 1106 1277 !! ** Method : The parameterization is adapted from Lupkes et al. (2015) 1107 1278 !! and ECHAM6 atmospheric model. Compared to Lupkes2012 scheme, 1108 1279 !! it considers specific skin and form drags (Andreas et al. 2010) 1109 !! to compute neutral transfert coefficients for both heat and 1280 !! to compute neutral transfert coefficients for both heat and 1110 1281 !! momemtum fluxes. Atmospheric stability effect on transfert 1111 1282 !! coefficient is also taken into account following Louis (1979). … … 1116 1287 !!---------------------------------------------------------------------- 1117 1288 ! 1118 REAL(wp), DIMENSION(:,:), INTENT(inout) :: Cd 1119 REAL(wp), DIMENSION(:,:), INTENT(inout) :: Ch 1120 REAL(wp), DIMENSION(jpi,jpj) :: ztm_su, zst, zqo_sat, zqi_sat 1289 REAL(wp), DIMENSION(:,:), INTENT(in ) :: ptm_su ! sea-ice surface temperature [K] 1290 REAL(wp), DIMENSION(:,:), INTENT(in ) :: pslp ! sea-level pressure [Pa] 1291 REAL(wp), DIMENSION(:,:), INTENT(inout) :: pcd ! momentum transfert coefficient 1292 REAL(wp), DIMENSION(:,:), INTENT(inout) :: pch ! heat transfert coefficient 1293 REAL(wp), DIMENSION(jpi,jpj) :: zst, zqo_sat, zqi_sat 1121 1294 ! 1122 1295 ! ECHAM6 constants … … 1146 1319 !!---------------------------------------------------------------------- 1147 1320 1148 ! mean temperature1149 WHERE( at_i_b(:,:) > 1.e-20 ) ; ztm_su(:,:) = SUM( t_su(:,:,:) * a_i_b(:,:,:) , dim=3 ) / at_i_b(:,:)1150 ELSEWHERE ; ztm_su(:,:) = rt01151 ENDWHERE1152 1153 1321 ! Momentum Neutral Transfert Coefficients (should be a constant) 1154 1322 zCdn_form_tmp = zce10 * ( LOG( 10._wp / z0_form_ice + 1._wp ) / LOG( rn_zu / z0_form_ice + 1._wp ) )**2 ! Eq. 40 1155 1323 zCdn_skin_ice = ( vkarmn / LOG( rn_zu / z0_skin_ice + 1._wp ) )**2 ! Eq. 7 1156 zCdn_ice = zCdn_skin_ice ! Eq. 7 (cf Lupkes email for details)1324 zCdn_ice = zCdn_skin_ice ! Eq. 7 1157 1325 !zCdn_ice = 1.89e-3 ! old ECHAM5 value (cf Eq. 32) 1158 1326 1159 1327 ! Heat Neutral Transfert Coefficients 1160 zChn_skin_ice = vkarmn**2 / ( LOG( rn_zu / z0_ice + 1._wp ) * LOG( rn_zu * z1_alpha / z0_skin_ice + 1._wp ) ) ! Eq. 50 + Eq. 52 (cf Lupkes email for details)1161 1328 zChn_skin_ice = vkarmn**2 / ( LOG( rn_zu / z0_ice + 1._wp ) * LOG( rn_zu * z1_alpha / z0_skin_ice + 1._wp ) ) ! Eq. 50 + Eq. 52 1329 1162 1330 ! Atmospheric and Surface Variables 1163 1331 zst(:,:) = sst_m(:,:) + rt0 ! convert SST from Celcius to Kelvin 1164 zqo_sat(:,:) = 0.98_wp * q_sat( zst(:,:) , sf(jp_slp)%fnow(:,:,1) ) ! saturation humidity over ocean [kg/kg] 1165 zqi_sat(:,:) = 0.98_wp * q_sat( ztm_su(:,:), sf(jp_slp)%fnow(:,:,1) ) ! saturation humidity over ice [kg/kg] 1166 ! 1167 DO jj = 2, jpjm1 ! reduced loop is necessary for reproducibility 1168 DO ji = fs_2, fs_jpim1 1169 ! Virtual potential temperature [K] 1170 zthetav_os = zst(ji,jj) * ( 1._wp + rctv0 * zqo_sat(ji,jj) ) ! over ocean 1171 zthetav_is = ztm_su(ji,jj) * ( 1._wp + rctv0 * zqi_sat(ji,jj) ) ! ocean ice 1172 zthetav_zu = t_zu (ji,jj) * ( 1._wp + rctv0 * q_zu(ji,jj) ) ! at zu 1173 1174 ! Bulk Richardson Number (could use Ri_bulk function from aerobulk instead) 1175 zrib_o = grav / zthetav_os * ( zthetav_zu - zthetav_os ) * rn_zu / MAX( 0.5, wndm(ji,jj) )**2 ! over ocean 1176 zrib_i = grav / zthetav_is * ( zthetav_zu - zthetav_is ) * rn_zu / MAX( 0.5, wndm_ice(ji,jj) )**2 ! over ice 1177 1178 ! Momentum and Heat Neutral Transfert Coefficients 1179 zCdn_form_ice = zCdn_form_tmp * at_i_b(ji,jj) * ( 1._wp - at_i_b(ji,jj) )**zbeta ! Eq. 40 1180 zChn_form_ice = zCdn_form_ice / ( 1._wp + ( LOG( z1_alphaf ) / vkarmn ) * SQRT( zCdn_form_ice ) ) ! Eq. 53 1181 1182 ! Momentum and Heat Stability functions (possibility to use psi_m_ecmwf instead) 1183 z0w = rn_zu * EXP( -1._wp * vkarmn / SQRT( Cdn_oce(ji,jj) ) ) ! over water 1184 z0i = z0_skin_ice ! over ice (cf Lupkes email for details) 1185 IF( zrib_o <= 0._wp ) THEN 1186 zfmw = 1._wp - zam * zrib_o / ( 1._wp + 3._wp * zc2 * Cdn_oce(ji,jj) * SQRT( -zrib_o * ( rn_zu / z0w + 1._wp ) ) ) ! Eq. 10 1187 zfhw = ( 1._wp + ( zbetah * ( zthetav_os - zthetav_zu )**r1_3 / ( Chn_oce(ji,jj) * MAX(0.01, wndm(ji,jj)) ) & ! Eq. 26 1188 & )**zgamma )**z1_gamma 1189 ELSE 1190 zfmw = 1._wp / ( 1._wp + zam * zrib_o / SQRT( 1._wp + zrib_o ) ) ! Eq. 12 1191 zfhw = 1._wp / ( 1._wp + zah * zrib_o / SQRT( 1._wp + zrib_o ) ) ! Eq. 28 1192 ENDIF 1193 1194 IF( zrib_i <= 0._wp ) THEN 1195 zfmi = 1._wp - zam * zrib_i / (1._wp + 3._wp * zc2 * zCdn_ice * SQRT( -zrib_i * ( rn_zu / z0i + 1._wp))) ! Eq. 9 1196 zfhi = 1._wp - zah * zrib_i / (1._wp + 3._wp * zc2 * zCdn_ice * SQRT( -zrib_i * ( rn_zu / z0i + 1._wp))) ! Eq. 25 1197 ELSE 1198 zfmi = 1._wp / ( 1._wp + zam * zrib_i / SQRT( 1._wp + zrib_i ) ) ! Eq. 11 1199 zfhi = 1._wp / ( 1._wp + zah * zrib_i / SQRT( 1._wp + zrib_i ) ) ! Eq. 27 1200 ENDIF 1201 1202 ! Momentum Transfert Coefficients (Eq. 38) 1203 Cd(ji,jj) = zCdn_skin_ice * zfmi + & 1204 & zCdn_form_ice * ( zfmi * at_i_b(ji,jj) + zfmw * ( 1._wp - at_i_b(ji,jj) ) ) / MAX( 1.e-06, at_i_b(ji,jj) ) 1205 1206 ! Heat Transfert Coefficients (Eq. 49) 1207 Ch(ji,jj) = zChn_skin_ice * zfhi + & 1208 & zChn_form_ice * ( zfhi * at_i_b(ji,jj) + zfhw * ( 1._wp - at_i_b(ji,jj) ) ) / MAX( 1.e-06, at_i_b(ji,jj) ) 1209 ! 1210 END DO 1211 END DO 1212 CALL lbc_lnk_multi( 'sbcblk', Cd, 'T', 1., Ch, 'T', 1. ) 1332 zqo_sat(:,:) = rdct_qsat_salt * q_sat( zst(:,:) , pslp(:,:) ) ! saturation humidity over ocean [kg/kg] 1333 zqi_sat(:,:) = q_sat( ptm_su(:,:), pslp(:,:) ) ! saturation humidity over ice [kg/kg] 1334 ! 1335 DO_2D_00_00 1336 ! Virtual potential temperature [K] 1337 zthetav_os = zst(ji,jj) * ( 1._wp + rctv0 * zqo_sat(ji,jj) ) ! over ocean 1338 zthetav_is = ptm_su(ji,jj) * ( 1._wp + rctv0 * zqi_sat(ji,jj) ) ! ocean ice 1339 zthetav_zu = t_zu (ji,jj) * ( 1._wp + rctv0 * q_zu(ji,jj) ) ! at zu 1340 1341 ! Bulk Richardson Number (could use Ri_bulk function from aerobulk instead) 1342 zrib_o = grav / zthetav_os * ( zthetav_zu - zthetav_os ) * rn_zu / MAX( 0.5, wndm(ji,jj) )**2 ! over ocean 1343 zrib_i = grav / zthetav_is * ( zthetav_zu - zthetav_is ) * rn_zu / MAX( 0.5, wndm_ice(ji,jj) )**2 ! over ice 1344 1345 ! Momentum and Heat Neutral Transfert Coefficients 1346 zCdn_form_ice = zCdn_form_tmp * at_i_b(ji,jj) * ( 1._wp - at_i_b(ji,jj) )**zbeta ! Eq. 40 1347 zChn_form_ice = zCdn_form_ice / ( 1._wp + ( LOG( z1_alphaf ) / vkarmn ) * SQRT( zCdn_form_ice ) ) ! Eq. 53 1348 1349 ! Momentum and Heat Stability functions (possibility to use psi_m_ecmwf instead ?) 1350 z0w = rn_zu * EXP( -1._wp * vkarmn / SQRT( Cdn_oce(ji,jj) ) ) ! over water 1351 z0i = z0_skin_ice ! over ice 1352 IF( zrib_o <= 0._wp ) THEN 1353 zfmw = 1._wp - zam * zrib_o / ( 1._wp + 3._wp * zc2 * Cdn_oce(ji,jj) * SQRT( -zrib_o * ( rn_zu / z0w + 1._wp ) ) ) ! Eq. 10 1354 zfhw = ( 1._wp + ( zbetah * ( zthetav_os - zthetav_zu )**r1_3 / ( Chn_oce(ji,jj) * MAX(0.01, wndm(ji,jj)) ) & ! Eq. 26 1355 & )**zgamma )**z1_gamma 1356 ELSE 1357 zfmw = 1._wp / ( 1._wp + zam * zrib_o / SQRT( 1._wp + zrib_o ) ) ! Eq. 12 1358 zfhw = 1._wp / ( 1._wp + zah * zrib_o / SQRT( 1._wp + zrib_o ) ) ! Eq. 28 1359 ENDIF 1360 1361 IF( zrib_i <= 0._wp ) THEN 1362 zfmi = 1._wp - zam * zrib_i / (1._wp + 3._wp * zc2 * zCdn_ice * SQRT( -zrib_i * ( rn_zu / z0i + 1._wp))) ! Eq. 9 1363 zfhi = 1._wp - zah * zrib_i / (1._wp + 3._wp * zc2 * zCdn_ice * SQRT( -zrib_i * ( rn_zu / z0i + 1._wp))) ! Eq. 25 1364 ELSE 1365 zfmi = 1._wp / ( 1._wp + zam * zrib_i / SQRT( 1._wp + zrib_i ) ) ! Eq. 11 1366 zfhi = 1._wp / ( 1._wp + zah * zrib_i / SQRT( 1._wp + zrib_i ) ) ! Eq. 27 1367 ENDIF 1368 1369 ! Momentum Transfert Coefficients (Eq. 38) 1370 pcd(ji,jj) = zCdn_skin_ice * zfmi + & 1371 & zCdn_form_ice * ( zfmi * at_i_b(ji,jj) + zfmw * ( 1._wp - at_i_b(ji,jj) ) ) / MAX( 1.e-06, at_i_b(ji,jj) ) 1372 1373 ! Heat Transfert Coefficients (Eq. 49) 1374 pch(ji,jj) = zChn_skin_ice * zfhi + & 1375 & zChn_form_ice * ( zfhi * at_i_b(ji,jj) + zfhw * ( 1._wp - at_i_b(ji,jj) ) ) / MAX( 1.e-06, at_i_b(ji,jj) ) 1376 ! 1377 END_2D 1378 CALL lbc_lnk_multi( 'sbcblk', pcd, 'T', 1., pch, 'T', 1. ) 1213 1379 ! 1214 1380 END SUBROUTINE Cdn10_Lupkes2015 -
NEMO/trunk/src/OCE/SBC/sbcblk_algo_ecmwf.F90
r10069 r12377 1 1 MODULE sbcblk_algo_ecmwf 2 2 !!====================================================================== 3 !! *** MODULE sbcblk_algo_ecmwf *** 4 !! Computes turbulent components of surface fluxes 5 !! according to the method in IFS of the ECMWF model 6 !! 3 !! *** MODULE sbcblk_algo_ecmwf *** 4 !! Computes: 7 5 !! * bulk transfer coefficients C_D, C_E and C_H 8 6 !! * air temp. and spec. hum. adjusted from zt (2m) to zu (10m) if needed … … 10 8 !! => all these are used in bulk formulas in sbcblk.F90 11 9 !! 12 !! Using the bulk formulation/param. of IFS of ECMWF (cycle 31r2)10 !! Using the bulk formulation/param. of IFS of ECMWF (cycle 40r1) 13 11 !! based on IFS doc (avaible online on the ECMWF's website) 14 12 !! 13 !! Routine turb_ecmwf maintained and developed in AeroBulk 14 !! (https://github.com/brodeau/aerobulk) 15 15 !! 16 !! Routine turb_ecmwf maintained and developed in AeroBulk 17 !! (http://aerobulk.sourceforge.net/) 18 !! 19 !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk) 16 !! ** Author: L. Brodeau, June 2019 / AeroBulk (https://github.com/brodeau/aerobulk) 20 17 !!---------------------------------------------------------------------- 21 18 !! History : 4.0 ! 2016-02 (L.Brodeau) Original code … … 41 38 42 39 USE sbc_oce ! Surface boundary condition: ocean fields 40 USE sbcblk_phy ! all thermodynamics functions, rho_air, q_sat, etc... !LB 41 USE sbcblk_skin_ecmwf ! cool-skin/warm layer scheme !LB 43 42 44 43 IMPLICIT NONE 45 44 PRIVATE 46 45 47 PUBLIC :: TURB_ECMWF ! called by sbcblk.F90 48 49 ! !! ECMWF own values for given constants, taken form IFS documentation... 46 PUBLIC :: SBCBLK_ALGO_ECMWF_INIT, TURB_ECMWF 47 !! * Substitutions 48 # include "do_loop_substitute.h90" 49 50 !! ECMWF own values for given constants, taken form IFS documentation... 50 51 REAL(wp), PARAMETER :: charn0 = 0.018 ! Charnock constant (pretty high value here !!! 51 52 ! ! => Usually 0.011 for moderate winds) 52 53 REAL(wp), PARAMETER :: zi0 = 1000. ! scale height of the atmospheric boundary layer...1 53 54 REAL(wp), PARAMETER :: Beta0 = 1. ! gustiness parameter ( = 1.25 in COAREv3) 54 REAL(wp), PARAMETER :: rctv0 = 0.608 ! constant to obtain virtual temperature...55 REAL(wp), PARAMETER :: Cp_dry = 1005.0 ! Specic heat of dry air, constant pressure [J/K/kg]56 REAL(wp), PARAMETER :: Cp_vap = 1860.0 ! Specic heat of water vapor, constant pressure [J/K/kg]57 55 REAL(wp), PARAMETER :: alpha_M = 0.11 ! For roughness length (smooth surface term) 58 56 REAL(wp), PARAMETER :: alpha_H = 0.40 ! (Chapter 3, p.34, IFS doc Cy31r1) 59 57 REAL(wp), PARAMETER :: alpha_Q = 0.62 ! 58 59 INTEGER , PARAMETER :: nb_itt = 10 ! number of itterations 60 60 61 !!---------------------------------------------------------------------- 61 62 CONTAINS 62 63 63 SUBROUTINE TURB_ECMWF( zt, zu, sst, t_zt, ssq , q_zt , U_zu, & 64 & Cd, Ch, Ce , t_zu, q_zu, U_blk, & 65 & Cdn, Chn, Cen ) 66 !!---------------------------------------------------------------------------------- 67 !! *** ROUTINE turb_ecmwf *** 68 !! 69 !! 2015: L. Brodeau (brodeau@gmail.com) 70 !! 71 !! ** Purpose : Computes turbulent transfert coefficients of surface 72 !! fluxes according to IFS doc. (cycle 31) 73 !! If relevant (zt /= zu), adjust temperature and humidity from height zt to zu 74 !! 75 !! ** Method : Monin Obukhov Similarity Theory 64 65 SUBROUTINE sbcblk_algo_ecmwf_init(l_use_cs, l_use_wl) 66 !!--------------------------------------------------------------------- 67 !! *** FUNCTION sbcblk_algo_ecmwf_init *** 76 68 !! 77 69 !! INPUT : 78 70 !! ------- 71 !! * l_use_cs : use the cool-skin parameterization 72 !! * l_use_wl : use the warm-layer parameterization 73 !!--------------------------------------------------------------------- 74 LOGICAL , INTENT(in) :: l_use_cs ! use the cool-skin parameterization 75 LOGICAL , INTENT(in) :: l_use_wl ! use the warm-layer parameterization 76 INTEGER :: ierr 77 !!--------------------------------------------------------------------- 78 IF( l_use_wl ) THEN 79 ierr = 0 80 ALLOCATE ( dT_wl(jpi,jpj), Hz_wl(jpi,jpj), STAT=ierr ) 81 IF( ierr > 0 ) CALL ctl_stop( ' SBCBLK_ALGO_ECMWF_INIT => allocation of dT_wl & Hz_wl failed!' ) 82 dT_wl(:,:) = 0._wp 83 Hz_wl(:,:) = rd0 ! (rd0, constant, = 3m is default for Zeng & Beljaars) 84 ENDIF 85 IF( l_use_cs ) THEN 86 ierr = 0 87 ALLOCATE ( dT_cs(jpi,jpj), STAT=ierr ) 88 IF( ierr > 0 ) CALL ctl_stop( ' SBCBLK_ALGO_ECMWF_INIT => allocation of dT_cs failed!' ) 89 dT_cs(:,:) = -0.25_wp ! First guess of skin correction 90 ENDIF 91 END SUBROUTINE sbcblk_algo_ecmwf_init 92 93 94 95 SUBROUTINE turb_ecmwf( kt, zt, zu, T_s, t_zt, q_s, q_zt, U_zu, l_use_cs, l_use_wl, & 96 & Cd, Ch, Ce, t_zu, q_zu, U_blk, & 97 & Cdn, Chn, Cen, & 98 & Qsw, rad_lw, slp, pdT_cs, & ! optionals for cool-skin (and warm-layer) 99 & pdT_wl, pHz_wl ) ! optionals for warm-layer only 100 !!---------------------------------------------------------------------- 101 !! *** ROUTINE turb_ecmwf *** 102 !! 103 !! ** Purpose : Computes turbulent transfert coefficients of surface 104 !! fluxes according to IFS doc. (cycle 45r1) 105 !! If relevant (zt /= zu), adjust temperature and humidity from height zt to zu 106 !! Returns the effective bulk wind speed at zu to be used in the bulk formulas 107 !! 108 !! Applies the cool-skin warm-layer correction of the SST to T_s 109 !! if the net shortwave flux at the surface (Qsw), the downwelling longwave 110 !! radiative fluxes at the surface (rad_lw), and the sea-leve pressure (slp) 111 !! are provided as (optional) arguments! 112 !! 113 !! INPUT : 114 !! ------- 115 !! * kt : current time step (starts at 1) 79 116 !! * zt : height for temperature and spec. hum. of air [m] 80 !! * zu : height for wind speed (generally 10m) [m] 81 !! * U_zu : scalar wind speed at 10m [m/s] 82 !! * sst : SST [K] 117 !! * zu : height for wind speed (usually 10m) [m] 83 118 !! * t_zt : potential air temperature at zt [K] 84 !! * ssq : specific humidity at saturation at SST [kg/kg]85 119 !! * q_zt : specific humidity of air at zt [kg/kg] 86 !! 120 !! * U_zu : scalar wind speed at zu [m/s] 121 !! * l_use_cs : use the cool-skin parameterization 122 !! * l_use_wl : use the warm-layer parameterization 123 !! 124 !! INPUT/OUTPUT: 125 !! ------------- 126 !! * T_s : always "bulk SST" as input [K] 127 !! -> unchanged "bulk SST" as output if CSWL not used [K] 128 !! -> skin temperature as output if CSWL used [K] 129 !! 130 !! * q_s : SSQ aka saturation specific humidity at temp. T_s [kg/kg] 131 !! -> doesn't need to be given a value if skin temp computed (in case l_use_cs=True or l_use_wl=True) 132 !! -> MUST be given the correct value if not computing skint temp. (in case l_use_cs=False or l_use_wl=False) 133 !! 134 !! OPTIONAL INPUT: 135 !! --------------- 136 !! * Qsw : net solar flux (after albedo) at the surface (>0) [W/m^2] 137 !! * rad_lw : downwelling longwave radiation at the surface (>0) [W/m^2] 138 !! * slp : sea-level pressure [Pa] 139 !! 140 !! OPTIONAL OUTPUT: 141 !! ---------------- 142 !! * pdT_cs : SST increment "dT" for cool-skin correction [K] 143 !! * pdT_wl : SST increment "dT" for warm-layer correction [K] 144 !! * pHz_wl : thickness of warm-layer [m] 87 145 !! 88 146 !! OUTPUT : … … 93 151 !! * t_zu : pot. air temperature adjusted at wind height zu [K] 94 152 !! * q_zu : specific humidity of air // [kg/kg] 95 !! * U_blk : bulk wind at 10m [m/s] 96 !! 97 !! 98 !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk) 99 !!---------------------------------------------------------------------------------- 153 !! * U_blk : bulk wind speed at zu [m/s] 154 !! 155 !! 156 !! ** Author: L. Brodeau, June 2019 / AeroBulk (https://github.com/brodeau/aerobulk/) 157 !!---------------------------------------------------------------------------------- 158 INTEGER, INTENT(in ) :: kt ! current time step 100 159 REAL(wp), INTENT(in ) :: zt ! height for t_zt and q_zt [m] 101 160 REAL(wp), INTENT(in ) :: zu ! height for U_zu [m] 102 REAL(wp), INTENT(in ), DIMENSION(jpi,jpj) :: sst! sea surface temperature [Kelvin]161 REAL(wp), INTENT(inout), DIMENSION(jpi,jpj) :: T_s ! sea surface temperature [Kelvin] 103 162 REAL(wp), INTENT(in ), DIMENSION(jpi,jpj) :: t_zt ! potential air temperature [Kelvin] 104 REAL(wp), INTENT(in ), DIMENSION(jpi,jpj) :: ssq! sea surface specific humidity [kg/kg]105 REAL(wp), INTENT(in ), DIMENSION(jpi,jpj) :: q_zt ! specific air humidity 163 REAL(wp), INTENT(inout), DIMENSION(jpi,jpj) :: q_s ! sea surface specific humidity [kg/kg] 164 REAL(wp), INTENT(in ), DIMENSION(jpi,jpj) :: q_zt ! specific air humidity at zt [kg/kg] 106 165 REAL(wp), INTENT(in ), DIMENSION(jpi,jpj) :: U_zu ! relative wind module at zu [m/s] 166 LOGICAL , INTENT(in ) :: l_use_cs ! use the cool-skin parameterization 167 LOGICAL , INTENT(in ) :: l_use_wl ! use the warm-layer parameterization 107 168 REAL(wp), INTENT( out), DIMENSION(jpi,jpj) :: Cd ! transfer coefficient for momentum (tau) 108 169 REAL(wp), INTENT( out), DIMENSION(jpi,jpj) :: Ch ! transfer coefficient for sensible heat (Q_sens) … … 110 171 REAL(wp), INTENT( out), DIMENSION(jpi,jpj) :: t_zu ! pot. air temp. adjusted at zu [K] 111 172 REAL(wp), INTENT( out), DIMENSION(jpi,jpj) :: q_zu ! spec. humidity adjusted at zu [kg/kg] 112 REAL(wp), INTENT( out), DIMENSION(jpi,jpj) :: U_blk ! bulk wind at 10m[m/s]173 REAL(wp), INTENT( out), DIMENSION(jpi,jpj) :: U_blk ! bulk wind speed at zu [m/s] 113 174 REAL(wp), INTENT( out), DIMENSION(jpi,jpj) :: Cdn, Chn, Cen ! neutral transfer coefficients 114 175 ! 176 REAL(wp), INTENT(in ), OPTIONAL, DIMENSION(jpi,jpj) :: Qsw ! [W/m^2] 177 REAL(wp), INTENT(in ), OPTIONAL, DIMENSION(jpi,jpj) :: rad_lw ! [W/m^2] 178 REAL(wp), INTENT(in ), OPTIONAL, DIMENSION(jpi,jpj) :: slp ! [Pa] 179 REAL(wp), INTENT( out), OPTIONAL, DIMENSION(jpi,jpj) :: pdT_cs 180 REAL(wp), INTENT( out), OPTIONAL, DIMENSION(jpi,jpj) :: pdT_wl ! [K] 181 REAL(wp), INTENT( out), OPTIONAL, DIMENSION(jpi,jpj) :: pHz_wl ! [m] 182 ! 115 183 INTEGER :: j_itt 116 LOGICAL :: l_zt_equal_zu = .FALSE. ! if q and t are given at same height as U 117 INTEGER , PARAMETER :: nb_itt = 4 ! number of itterations 118 ! 119 REAL(wp), DIMENSION(jpi,jpj) :: u_star, t_star, q_star, & 120 & dt_zu, dq_zu, & 121 & znu_a, & !: Nu_air, Viscosity of air 122 & Linv, & !: 1/L (inverse of Monin Obukhov length... 123 & z0, z0t, z0q 124 REAL(wp), DIMENSION(jpi,jpj) :: func_m, func_h 125 REAL(wp), DIMENSION(jpi,jpj) :: ztmp0, ztmp1, ztmp2 126 !!---------------------------------------------------------------------------------- 127 ! 128 ! Identical first gess as in COARE, with IFS parameter values though 129 ! 184 LOGICAL :: l_zt_equal_zu = .FALSE. ! if q and t are given at same height as U 185 ! 186 REAL(wp), DIMENSION(jpi,jpj) :: u_star, t_star, q_star 187 REAL(wp), DIMENSION(jpi,jpj) :: dt_zu, dq_zu 188 REAL(wp), DIMENSION(jpi,jpj) :: znu_a !: Nu_air, Viscosity of air 189 REAL(wp), DIMENSION(jpi,jpj) :: Linv !: 1/L (inverse of Monin Obukhov length... 190 REAL(wp), DIMENSION(jpi,jpj) :: z0, z0t, z0q 191 ! 192 REAL(wp), DIMENSION(:,:), ALLOCATABLE :: zsst ! to back up the initial bulk SST 193 ! 194 REAL(wp), DIMENSION(jpi,jpj) :: func_m, func_h 195 REAL(wp), DIMENSION(jpi,jpj) :: ztmp0, ztmp1, ztmp2 196 CHARACTER(len=40), PARAMETER :: crtnm = 'turb_ecmwf@sbcblk_algo_ecmwf.F90' 197 !!---------------------------------------------------------------------------------- 198 199 IF( kt == nit000 ) CALL SBCBLK_ALGO_ECMWF_INIT(l_use_cs, l_use_wl) 200 130 201 l_zt_equal_zu = .FALSE. 131 IF( ABS(zu - zt) < 0.01 ) l_zt_equal_zu = .TRUE. ! testing "zu == zt" is risky with double precision 132 133 202 IF( ABS(zu - zt) < 0.01_wp ) l_zt_equal_zu = .TRUE. ! testing "zu == zt" is risky with double precision 203 204 !! Initializations for cool skin and warm layer: 205 IF( l_use_cs .AND. (.NOT.(PRESENT(Qsw) .AND. PRESENT(rad_lw) .AND. PRESENT(slp))) ) & 206 & CALL ctl_stop( '['//TRIM(crtnm)//'] => ' , 'you need to provide Qsw, rad_lw & slp to use cool-skin param!' ) 207 208 IF( l_use_wl .AND. (.NOT.(PRESENT(Qsw) .AND. PRESENT(rad_lw) .AND. PRESENT(slp))) ) & 209 & CALL ctl_stop( '['//TRIM(crtnm)//'] => ' , 'you need to provide Qsw, rad_lw & slp to use warm-layer param!' ) 210 211 IF( l_use_cs .OR. l_use_wl ) THEN 212 ALLOCATE ( zsst(jpi,jpj) ) 213 zsst = T_s ! backing up the bulk SST 214 IF( l_use_cs ) T_s = T_s - 0.25_wp ! First guess of correction 215 q_s = rdct_qsat_salt*q_sat(MAX(T_s, 200._wp), slp) ! First guess of q_s 216 ENDIF 217 218 219 ! Identical first gess as in COARE, with IFS parameter values though... 220 ! 134 221 !! First guess of temperature and humidity at height zu: 135 t_zu = MAX( t_zt , 0.0) ! who knows what's given on masked-continental regions...136 q_zu = MAX( q_zt , 1.e-6 ) ! "222 t_zu = MAX( t_zt , 180._wp ) ! who knows what's given on masked-continental regions... 223 q_zu = MAX( q_zt , 1.e-6_wp ) ! " 137 224 138 225 !! Pot. temp. difference (and we don't want it to be 0!) 139 dt_zu = t_zu - sst ; dt_zu = SIGN( MAX(ABS(dt_zu),1.e-6), dt_zu )140 dq_zu = q_zu - ssq ; dq_zu = SIGN( MAX(ABS(dq_zu),1.e-9), dq_zu )141 142 znu_a = visc_air(t_z t) ! Air viscosity (m^2/s) at zt given from temperature in (K)143 144 ztmp2 = 0.5 * 0.5! initial guess for wind gustiness contribution145 U_blk = SQRT(U_zu*U_zu + ztmp2) 146 147 ! z0 = 0.0001148 ztmp2 = 10000. ! optimization: ztmp2 == 1/z0149 ztmp0 = LOG(zu*ztmp2) 150 z tmp1 = LOG(10.*ztmp2)151 u_star = 0.035*U_blk*ztmp1/ztmp0 ! (u* = 0.035*Un10)152 153 z0 = charn0*u_star*u_star/grav + 0.11*znu_a/u_star154 z0t = 0.1*EXP(vkarmn/(0.00115/(vkarmn/ztmp1))) ! WARNING: 1/z0t !226 dt_zu = t_zu - T_s ; dt_zu = SIGN( MAX(ABS(dt_zu),1.E-6_wp), dt_zu ) 227 dq_zu = q_zu - q_s ; dq_zu = SIGN( MAX(ABS(dq_zu),1.E-9_wp), dq_zu ) 228 229 znu_a = visc_air(t_zu) ! Air viscosity (m^2/s) at zt given from temperature in (K) 230 231 U_blk = SQRT(U_zu*U_zu + 0.5_wp*0.5_wp) ! initial guess for wind gustiness contribution 232 233 ztmp0 = LOG( zu*10000._wp) ! optimization: 10000. == 1/z0 (with z0 first guess == 0.0001) 234 ztmp1 = LOG(10._wp*10000._wp) ! " " " 235 u_star = 0.035_wp*U_blk*ztmp1/ztmp0 ! (u* = 0.035*Un10) 236 237 z0 = charn0*u_star*u_star/grav + 0.11_wp*znu_a/u_star 238 z0 = MIN( MAX(ABS(z0), 1.E-9) , 1._wp ) ! (prevents FPE from stupid values from masked region later on) 239 240 z0t = 1._wp / ( 0.1_wp*EXP(vkarmn/(0.00115/(vkarmn/ztmp1))) ) 241 z0t = MIN( MAX(ABS(z0t), 1.E-9) , 1._wp ) ! (prevents FPE from stupid values from masked region later on) 155 242 156 243 Cd = (vkarmn/ztmp0)**2 ! first guess of Cd 157 244 158 ztmp0 = vkarmn*vkarmn/LOG(zt *z0t)/Cd159 160 ztmp2 = Ri_bulk( zu, t_zu, dt_zu, q_zu, dq_zu, U_blk ) ! Ribu = Bulk Richardson number161 162 !! First estimate of zeta_u, depending on the stability, ie sign of Ribu(ztmp2):163 ztmp1 = 0.5 + SIGN( 0.5 , ztmp2 )245 ztmp0 = vkarmn*vkarmn/LOG(zt/z0t)/Cd 246 247 ztmp2 = Ri_bulk( zu, T_s, t_zu, q_s, q_zu, U_blk ) ! Bulk Richardson Number (BRN) 248 249 !! First estimate of zeta_u, depending on the stability, ie sign of BRN (ztmp2): 250 ztmp1 = 0.5 + SIGN( 0.5_wp , ztmp2 ) 164 251 func_m = ztmp0*ztmp2 ! temporary array !! 165 !! Ribu < 0 Ribu > 0 Beta = 1.25166 func_h = (1.-ztmp1)*(func_m/(1.+ztmp2/(-zu/(zi0*0.004*Beta0**3)))) & ! temporary array !!! func_h == zeta_u167 & + ztmp1*(func_m*(1. + 27./9.*ztmp2/ztmp0))252 func_h = (1._wp-ztmp1) * (func_m/(1._wp+ztmp2/(-zu/(zi0*0.004_wp*Beta0**3)))) & ! BRN < 0 ! temporary array !!! func_h == zeta_u 253 & + ztmp1 * (func_m*(1._wp + 27._wp/9._wp*ztmp2/func_m)) ! BRN > 0 254 !#LB: should make sure that the "func_m" of "27./9.*ztmp2/func_m" is "ztmp0*ztmp2" and not "ztmp0==vkarmn*vkarmn/LOG(zt/z0t)/Cd" ! 168 255 169 256 !! First guess M-O stability dependent scaling params.(u*,t*,q*) to estimate z0 and z/L 170 ztmp0 = vkarmn/(LOG(zu*z0t) - psi_h_ecmwf(func_h))171 172 u_star = U_blk*vkarmn/(LOG(zu) - LOG(z0) - psi_m_ecmwf(func_h))257 ztmp0 = vkarmn/(LOG(zu/z0t) - psi_h_ecmwf(func_h)) 258 259 u_star = MAX ( U_blk*vkarmn/(LOG(zu) - LOG(z0) - psi_m_ecmwf(func_h)) , 1.E-9 ) ! (MAX => prevents FPE from stupid values from masked region later on) 173 260 t_star = dt_zu*ztmp0 174 261 q_star = dq_zu*ztmp0 175 262 176 ! What 's needto be done if zt /= zu:263 ! What needs to be done if zt /= zu: 177 264 IF( .NOT. l_zt_equal_zu ) THEN 178 !179 265 !! First update of values at zu (or zt for wind) 180 266 ztmp0 = psi_h_ecmwf(func_h) - psi_h_ecmwf(zt*func_h/zu) ! zt*func_h/zu == zeta_t 181 ztmp1 = log(zt/zu) + ztmp0267 ztmp1 = LOG(zt/zu) + ztmp0 182 268 t_zu = t_zt - t_star/vkarmn*ztmp1 183 269 q_zu = q_zt - q_star/vkarmn*ztmp1 184 q_zu = (0.5 + sign(0.5,q_zu))*q_zu !Makes it impossible to have negative humidity : 185 186 dt_zu = t_zu - sst ; dt_zu = SIGN( MAX(ABS(dt_zu),1.E-6), dt_zu ) 187 dq_zu = q_zu - ssq ; dq_zu = SIGN( MAX(ABS(dq_zu),1.E-9), dq_zu ) 188 ! 270 q_zu = (0.5_wp + SIGN(0.5_wp,q_zu))*q_zu !Makes it impossible to have negative humidity : 271 ! 272 dt_zu = t_zu - T_s ; dt_zu = SIGN( MAX(ABS(dt_zu),1.E-6_wp), dt_zu ) 273 dq_zu = q_zu - q_s ; dq_zu = SIGN( MAX(ABS(dq_zu),1.E-9_wp), dq_zu ) 189 274 ENDIF 190 275 … … 194 279 195 280 !! First guess of inverse of Monin-Obukov length (1/L) : 196 ztmp0 = (1. + rctv0*q_zu) ! the factor to apply to temp. to get virt. temp... 197 Linv = grav*vkarmn*(t_star*ztmp0 + rctv0*t_zu*q_star) / ( u_star*u_star * t_zu*ztmp0 ) 281 Linv = One_on_L( t_zu, q_zu, u_star, t_star, q_star ) 198 282 199 283 !! Functions such as u* = U_blk*vkarmn/func_m 200 ztmp1 = zu + z0 201 ztmp0 = ztmp1*Linv 202 func_m = LOG(ztmp1) -LOG(z0) - psi_m_ecmwf(ztmp0) + psi_m_ecmwf(z0*Linv) 203 func_h = LOG(ztmp1*z0t) - psi_h_ecmwf(ztmp0) + psi_h_ecmwf(1./z0t*Linv) 204 284 ztmp0 = zu*Linv 285 func_m = LOG(zu) - LOG(z0) - psi_m_ecmwf(ztmp0) + psi_m_ecmwf( z0*Linv) 286 func_h = LOG(zu) - LOG(z0t) - psi_h_ecmwf(ztmp0) + psi_h_ecmwf(z0t*Linv) 205 287 206 288 !! ITERATION BLOCK 207 !! ***************208 209 289 DO j_itt = 1, nb_itt 210 290 211 291 !! Bulk Richardson Number at z=zu (Eq. 3.25) 212 ztmp0 = Ri_bulk( zu, t_zu, dt_zu, q_zu, dq_zu, U_blk)292 ztmp0 = Ri_bulk( zu, T_s, t_zu, q_s, q_zu, U_blk ) ! Bulk Richardson Number (BRN) 213 293 214 294 !! New estimate of the inverse of the Monin-Obukhon length (Linv == zeta/zu) : 215 Linv = ztmp0*func_m*func_m/func_h / zu ! From Eq. 3.23, Chap.3, p.33, IFS doc - Cy31r1 295 Linv = ztmp0*func_m*func_m/func_h / zu ! From Eq. 3.23, Chap.3.2.3, IFS doc - Cy40r1 296 !! Note: it is slightly different that the L we would get with the usual 297 Linv = SIGN( MIN(ABS(Linv),200._wp), Linv ) ! (prevent FPE from stupid values from masked region later on...) 216 298 217 299 !! Update func_m with new Linv: 218 ztmp1 = zu + z0 219 func_m = LOG(ztmp1) -LOG(z0) - psi_m_ecmwf(ztmp1*Linv) + psi_m_ecmwf(z0*Linv) 300 func_m = LOG(zu) -LOG(z0) - psi_m_ecmwf(zu*Linv) + psi_m_ecmwf(z0*Linv) ! LB: should be "zu+z0" rather than "zu" alone, but z0 is tiny wrt zu! 220 301 221 302 !! Need to update roughness lengthes: … … 223 304 ztmp2 = u_star*u_star 224 305 ztmp1 = znu_a/u_star 225 z0 = alpha_M*ztmp1 + charn0*ztmp2/grav 226 z0t = alpha_H*ztmp1 ! eq.3.26, Chap.3, p.34, IFS doc - Cy31r1 227 z0q = alpha_Q*ztmp1 228 229 !! Update wind at 10m taking into acount convection-related wind gustiness: 230 ! Only true when unstable (L<0) => when ztmp0 < 0 => - !!! 231 ztmp2 = ztmp2 * (MAX(-zi0*Linv/vkarmn,0.))**(2./3.) ! => w*^2 (combining Eq. 3.8 and 3.18, hap.3, IFS doc - Cy31r1) 232 !! => equivalent using Beta=1 (gustiness parameter, 1.25 for COARE, also zi0=600 in COARE..) 233 U_blk = MAX(sqrt(U_zu*U_zu + ztmp2), 0.2) ! eq.3.17, Chap.3, p.32, IFS doc - Cy31r1 306 z0 = MIN( ABS( alpha_M*ztmp1 + charn0*ztmp2/grav ) , 0.001_wp) 307 z0t = MIN( ABS( alpha_H*ztmp1 ) , 0.001_wp) ! eq.3.26, Chap.3, p.34, IFS doc - Cy31r1 308 z0q = MIN( ABS( alpha_Q*ztmp1 ) , 0.001_wp) 309 310 !! Update wind at zu with convection-related wind gustiness in unstable conditions (Chap. 3.2, IFS doc - Cy40r1, Eq.3.17 and Eq.3.18 + Eq.3.8) 311 ztmp2 = Beta0*Beta0*ztmp2*(MAX(-zi0*Linv/vkarmn,0._wp))**(2._wp/3._wp) ! square of wind gustiness contribution (combining Eq. 3.8 and 3.18, hap.3, IFS doc - Cy31r1) 312 !! ! Only true when unstable (L<0) => when ztmp0 < 0 => explains "-" before zi0 313 U_blk = MAX(SQRT(U_zu*U_zu + ztmp2), 0.2_wp) ! include gustiness in bulk wind speed 234 314 ! => 0.2 prevents U_blk to be 0 in stable case when U_zu=0. 235 315 … … 238 318 !! as well the air-sea differences: 239 319 IF( .NOT. l_zt_equal_zu ) THEN 240 241 320 !! Arrays func_m and func_h are free for a while so using them as temporary arrays... 242 func_h = psi_h_ecmwf( (zu+z0)*Linv) ! temporary array !!!243 func_m = psi_h_ecmwf( (zt+z0)*Linv) ! temporary array !!!321 func_h = psi_h_ecmwf(zu*Linv) ! temporary array !!! 322 func_m = psi_h_ecmwf(zt*Linv) ! temporary array !!! 244 323 245 324 ztmp2 = psi_h_ecmwf(z0t*Linv) 246 325 ztmp0 = func_h - ztmp2 247 ztmp1 = vkarmn/(LOG(zu +z0) - LOG(z0t) - ztmp0)326 ztmp1 = vkarmn/(LOG(zu) - LOG(z0t) - ztmp0) 248 327 t_star = dt_zu*ztmp1 249 328 ztmp2 = ztmp0 - func_m + ztmp2 … … 253 332 ztmp2 = psi_h_ecmwf(z0q*Linv) 254 333 ztmp0 = func_h - ztmp2 255 ztmp1 = vkarmn/(LOG(zu +z0) - LOG(z0q) - ztmp0)334 ztmp1 = vkarmn/(LOG(zu) - LOG(z0q) - ztmp0) 256 335 q_star = dq_zu*ztmp1 257 336 ztmp2 = ztmp0 - func_m + ztmp2 258 ztmp1 = log(zt/zu) + ztmp2337 ztmp1 = LOG(zt/zu) + ztmp2 259 338 q_zu = q_zt - q_star/vkarmn*ztmp1 260 261 dt_zu = t_zu - sst ; dt_zu = SIGN( MAX(ABS(dt_zu),1.E-6), dt_zu ) 262 dq_zu = q_zu - ssq ; dq_zu = SIGN( MAX(ABS(dq_zu),1.E-9), dq_zu ) 263 264 END IF 339 ENDIF 265 340 266 341 !! Updating because of updated z0 and z0t and new Linv... 267 ztmp1 = zu + z0 268 ztmp0 = ztmp1*Linv 269 func_m = log(ztmp1) - LOG(z0 ) - psi_m_ecmwf(ztmp0) + psi_m_ecmwf(z0 *Linv) 270 func_h = log(ztmp1) - LOG(z0t) - psi_h_ecmwf(ztmp0) + psi_h_ecmwf(z0t*Linv) 271 272 END DO 342 ztmp0 = zu*Linv 343 func_m = log(zu) - LOG(z0 ) - psi_m_ecmwf(ztmp0) + psi_m_ecmwf(z0 *Linv) 344 func_h = log(zu) - LOG(z0t) - psi_h_ecmwf(ztmp0) + psi_h_ecmwf(z0t*Linv) 345 346 347 IF( l_use_cs ) THEN 348 !! Cool-skin contribution 349 350 CALL UPDATE_QNSOL_TAU( zu, T_s, q_s, t_zu, q_zu, u_star, t_star, q_star, U_zu, U_blk, slp, rad_lw, & 351 & ztmp1, ztmp0, Qlat=ztmp2) ! Qnsol -> ztmp1 / Tau -> ztmp0 352 353 CALL CS_ECMWF( Qsw, ztmp1, u_star, zsst ) ! Qnsol -> ztmp1 354 355 T_s(:,:) = zsst(:,:) + dT_cs(:,:)*tmask(:,:,1) 356 IF( l_use_wl ) T_s(:,:) = T_s(:,:) + dT_wl(:,:)*tmask(:,:,1) 357 q_s(:,:) = rdct_qsat_salt*q_sat(MAX(T_s(:,:), 200._wp), slp(:,:)) 358 359 ENDIF 360 361 IF( l_use_wl ) THEN 362 !! Warm-layer contribution 363 CALL UPDATE_QNSOL_TAU( zu, T_s, q_s, t_zu, q_zu, u_star, t_star, q_star, U_zu, U_blk, slp, rad_lw, & 364 & ztmp1, ztmp2) ! Qnsol -> ztmp1 / Tau -> ztmp2 365 CALL WL_ECMWF( Qsw, ztmp1, u_star, zsst ) 366 !! Updating T_s and q_s !!! 367 T_s(:,:) = zsst(:,:) + dT_wl(:,:)*tmask(:,:,1) ! 368 IF( l_use_cs ) T_s(:,:) = T_s(:,:) + dT_cs(:,:)*tmask(:,:,1) 369 q_s(:,:) = rdct_qsat_salt*q_sat(MAX(T_s(:,:), 200._wp), slp(:,:)) 370 ENDIF 371 372 IF( l_use_cs .OR. l_use_wl .OR. (.NOT. l_zt_equal_zu) ) THEN 373 dt_zu = t_zu - T_s ; dt_zu = SIGN( MAX(ABS(dt_zu),1.E-6_wp), dt_zu ) 374 dq_zu = q_zu - q_s ; dq_zu = SIGN( MAX(ABS(dq_zu),1.E-9_wp), dq_zu ) 375 ENDIF 376 377 END DO !DO j_itt = 1, nb_itt 273 378 274 379 Cd = vkarmn*vkarmn/(func_m*func_m) 275 380 Ch = vkarmn*vkarmn/(func_m*func_h) 276 ztmp1 = log((zu + z0)/z0q) - psi_h_ecmwf((zu + z0)*Linv) + psi_h_ecmwf(z0q*Linv) ! func_q 277 Ce = vkarmn*vkarmn/(func_m*ztmp1) 278 279 ztmp1 = zu + z0 280 Cdn = vkarmn*vkarmn / (log(ztmp1/z0 )*log(ztmp1/z0 )) 281 Chn = vkarmn*vkarmn / (log(ztmp1/z0t)*log(ztmp1/z0t)) 282 Cen = vkarmn*vkarmn / (log(ztmp1/z0q)*log(ztmp1/z0q)) 283 284 END SUBROUTINE TURB_ECMWF 381 ztmp2 = log(zu/z0q) - psi_h_ecmwf(zu*Linv) + psi_h_ecmwf(z0q*Linv) ! func_q 382 Ce = vkarmn*vkarmn/(func_m*ztmp2) 383 384 Cdn = vkarmn*vkarmn / (log(zu/z0 )*log(zu/z0 )) 385 Chn = vkarmn*vkarmn / (log(zu/z0t)*log(zu/z0t)) 386 Cen = vkarmn*vkarmn / (log(zu/z0q)*log(zu/z0q)) 387 388 IF( l_use_cs .AND. PRESENT(pdT_cs) ) pdT_cs = dT_cs 389 IF( l_use_wl .AND. PRESENT(pdT_wl) ) pdT_wl = dT_wl 390 IF( l_use_wl .AND. PRESENT(pHz_wl) ) pHz_wl = Hz_wl 391 392 IF( l_use_cs .OR. l_use_wl ) DEALLOCATE ( zsst ) 393 394 END SUBROUTINE turb_ecmwf 285 395 286 396 … … 294 404 !! and L is M-O length 295 405 !! 296 !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk)406 !! ** Author: L. Brodeau, June 2016 / AeroBulk (https://github.com/brodeau/aerobulk/) 297 407 !!---------------------------------------------------------------------------------- 298 408 REAL(wp), DIMENSION(jpi,jpj) :: psi_m_ecmwf … … 302 412 REAL(wp) :: zzeta, zx, ztmp, psi_unst, psi_stab, stab 303 413 !!---------------------------------------------------------------------------------- 304 ! 305 DO jj = 1, jpj 306 DO ji = 1, jpi 307 ! 308 zzeta = MIN( pzeta(ji,jj) , 5. ) !! Very stable conditions (L positif and big!): 309 ! 310 ! Unstable (Paulson 1970): 311 ! eq.3.20, Chap.3, p.33, IFS doc - Cy31r1 312 zx = SQRT(ABS(1. - 16.*zzeta)) 313 ztmp = 1. + SQRT(zx) 314 ztmp = ztmp*ztmp 315 psi_unst = LOG( 0.125*ztmp*(1. + zx) ) & 316 & -2.*ATAN( SQRT(zx) ) + 0.5*rpi 317 ! 318 ! Unstable: 319 ! eq.3.22, Chap.3, p.33, IFS doc - Cy31r1 320 psi_stab = -2./3.*(zzeta - 5./0.35)*EXP(-0.35*zzeta) & 321 & - zzeta - 2./3.*5./0.35 322 ! 323 ! Combining: 324 stab = 0.5 + SIGN(0.5, zzeta) ! zzeta > 0 => stab = 1 325 ! 326 psi_m_ecmwf(ji,jj) = (1. - stab) * psi_unst & ! (zzeta < 0) Unstable 327 & + stab * psi_stab ! (zzeta > 0) Stable 328 ! 329 END DO 330 END DO 331 ! 414 DO_2D_11_11 415 ! 416 zzeta = MIN( pzeta(ji,jj) , 5._wp ) !! Very stable conditions (L positif and big!): 417 ! 418 ! Unstable (Paulson 1970): 419 ! eq.3.20, Chap.3, p.33, IFS doc - Cy31r1 420 zx = SQRT(ABS(1._wp - 16._wp*zzeta)) 421 ztmp = 1._wp + SQRT(zx) 422 ztmp = ztmp*ztmp 423 psi_unst = LOG( 0.125_wp*ztmp*(1._wp + zx) ) & 424 & -2._wp*ATAN( SQRT(zx) ) + 0.5_wp*rpi 425 ! 426 ! Unstable: 427 ! eq.3.22, Chap.3, p.33, IFS doc - Cy31r1 428 psi_stab = -2._wp/3._wp*(zzeta - 5._wp/0.35_wp)*EXP(-0.35_wp*zzeta) & 429 & - zzeta - 2._wp/3._wp*5._wp/0.35_wp 430 ! 431 ! Combining: 432 stab = 0.5_wp + SIGN(0.5_wp, zzeta) ! zzeta > 0 => stab = 1 433 ! 434 psi_m_ecmwf(ji,jj) = (1._wp - stab) * psi_unst & ! (zzeta < 0) Unstable 435 & + stab * psi_stab ! (zzeta > 0) Stable 436 ! 437 END_2D 332 438 END FUNCTION psi_m_ecmwf 333 439 334 440 335 441 FUNCTION psi_h_ecmwf( pzeta ) 336 442 !!---------------------------------------------------------------------------------- … … 342 448 !! and L is M-O length 343 449 !! 344 !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk)450 !! ** Author: L. Brodeau, June 2016 / AeroBulk (https://github.com/brodeau/aerobulk/) 345 451 !!---------------------------------------------------------------------------------- 346 452 REAL(wp), DIMENSION(jpi,jpj) :: psi_h_ecmwf … … 351 457 !!---------------------------------------------------------------------------------- 352 458 ! 353 DO jj = 1, jpj 354 DO ji = 1, jpi 355 ! 356 zzeta = MIN(pzeta(ji,jj) , 5.) ! Very stable conditions (L positif and big!): 357 ! 358 zx = ABS(1. - 16.*zzeta)**.25 ! this is actually (1/phi_m)**2 !!! 359 ! ! eq.3.19, Chap.3, p.33, IFS doc - Cy31r1 360 ! Unstable (Paulson 1970) : 361 psi_unst = 2.*LOG(0.5*(1. + zx*zx)) ! eq.3.20, Chap.3, p.33, IFS doc - Cy31r1 362 ! 363 ! Stable: 364 psi_stab = -2./3.*(zzeta - 5./0.35)*EXP(-0.35*zzeta) & ! eq.3.22, Chap.3, p.33, IFS doc - Cy31r1 365 & - ABS(1. + 2./3.*zzeta)**1.5 - 2./3.*5./0.35 + 1. 366 ! LB: added ABS() to avoid NaN values when unstable, which contaminates the unstable solution... 367 ! 368 stab = 0.5 + SIGN(0.5, zzeta) ! zzeta > 0 => stab = 1 369 ! 370 ! 371 psi_h_ecmwf(ji,jj) = (1. - stab) * psi_unst & ! (zzeta < 0) Unstable 372 & + stab * psi_stab ! (zzeta > 0) Stable 373 ! 374 END DO 375 END DO 376 ! 459 DO_2D_11_11 460 ! 461 zzeta = MIN(pzeta(ji,jj) , 5._wp) ! Very stable conditions (L positif and big!): 462 ! 463 zx = ABS(1._wp - 16._wp*zzeta)**.25 ! this is actually (1/phi_m)**2 !!! 464 ! ! eq.3.19, Chap.3, p.33, IFS doc - Cy31r1 465 ! Unstable (Paulson 1970) : 466 psi_unst = 2._wp*LOG(0.5_wp*(1._wp + zx*zx)) ! eq.3.20, Chap.3, p.33, IFS doc - Cy31r1 467 ! 468 ! Stable: 469 psi_stab = -2._wp/3._wp*(zzeta - 5._wp/0.35_wp)*EXP(-0.35_wp*zzeta) & ! eq.3.22, Chap.3, p.33, IFS doc - Cy31r1 470 & - ABS(1._wp + 2._wp/3._wp*zzeta)**1.5_wp - 2._wp/3._wp*5._wp/0.35_wp + 1._wp 471 ! LB: added ABS() to avoid NaN values when unstable, which contaminates the unstable solution... 472 ! 473 stab = 0.5_wp + SIGN(0.5_wp, zzeta) ! zzeta > 0 => stab = 1 474 ! 475 ! 476 psi_h_ecmwf(ji,jj) = (1._wp - stab) * psi_unst & ! (zzeta < 0) Unstable 477 & + stab * psi_stab ! (zzeta > 0) Stable 478 ! 479 END_2D 377 480 END FUNCTION psi_h_ecmwf 378 481 379 380 FUNCTION Ri_bulk( pz, ptz, pdt, pqz, pdq, pub )381 !!----------------------------------------------------------------------------------382 !! Bulk Richardson number (Eq. 3.25 IFS doc)383 !!384 !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk)385 !!----------------------------------------------------------------------------------386 REAL(wp), DIMENSION(jpi,jpj) :: Ri_bulk !387 !388 REAL(wp) , INTENT(in) :: pz ! height above the sea [m]389 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: ptz ! air temperature at pz m [K]390 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pdt ! ptz - sst [K]391 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pqz ! air temperature at pz m [kg/kg]392 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pdq ! pqz - ssq [kg/kg]393 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pub ! bulk wind speed [m/s]394 !!----------------------------------------------------------------------------------395 !396 Ri_bulk = grav*pz/(pub*pub) &397 & * ( pdt/(ptz - 0.5_wp*(pdt + grav*pz/(Cp_dry+Cp_vap*pqz))) &398 & + rctv0*pdq )399 !400 END FUNCTION Ri_bulk401 402 403 FUNCTION visc_air(ptak)404 !!----------------------------------------------------------------------------------405 !! Air kinetic viscosity (m^2/s) given from temperature in degrees...406 !!407 !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk)408 !!----------------------------------------------------------------------------------409 REAL(wp), DIMENSION(jpi,jpj) :: visc_air !410 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: ptak ! air temperature in (K)411 !412 INTEGER :: ji, jj ! dummy loop indices413 REAL(wp) :: ztc, ztc2 ! local scalar414 !!----------------------------------------------------------------------------------415 !416 DO jj = 1, jpj417 DO ji = 1, jpi418 ztc = ptak(ji,jj) - rt0 ! air temp, in deg. C419 ztc2 = ztc*ztc420 visc_air(ji,jj) = 1.326e-5*(1. + 6.542E-3*ztc + 8.301e-6*ztc2 - 4.84e-9*ztc2*ztc)421 END DO422 END DO423 !424 END FUNCTION visc_air425 482 426 483 !!====================================================================== -
NEMO/trunk/src/OCE/SBC/sbcblk_algo_ncar.F90
r10190 r12377 11 11 !! 12 12 !! Routine turb_ncar maintained and developed in AeroBulk 13 !! (http ://aerobulk.sourceforge.net/)13 !! (https://github.com/brodeau/aerobulk/) 14 14 !! 15 15 !! L. Brodeau, 2015 … … 38 38 USE lib_fortran ! to use key_nosignedzero 39 39 40 USE sbcblk_phy ! all thermodynamics functions, rho_air, q_sat, etc... !LB 40 41 41 42 IMPLICIT NONE 42 43 PRIVATE 43 44 44 PUBLIC :: TURB_NCAR ! called by sbcblk.F90 45 46 ! ! NCAR own values for given constants: 47 REAL(wp), PARAMETER :: rctv0 = 0.608 ! constant to obtain virtual temperature... 48 45 PUBLIC :: TURB_NCAR ! called by sbcblk.F90 46 47 INTEGER , PARAMETER :: nb_itt = 5 ! number of itterations 48 !! * Substitutions 49 # include "do_loop_substitute.h90" 50 49 51 !!---------------------------------------------------------------------- 50 52 CONTAINS … … 61 63 !! Returns the effective bulk wind speed at 10m to be used in the bulk formulas 62 64 !! 63 !! ** Method : Monin Obukhov Similarity Theory64 !! + Large & Yeager (2004,2008) closure: CD_n10 = f(U_n10)65 !!66 !! ** References : Large & Yeager, 2004 / Large & Yeager, 200867 !!68 !! ** Last update: Laurent Brodeau, June 2014:69 !! - handles both cases zt=zu and zt/=zu70 !! - optimized: less 2D arrays allocated and less operations71 !! - better first guess of stability by checking air-sea difference of virtual temperature72 !! rather than temperature difference only...73 !! - added function "cd_neutral_10m" that uses the improved parametrization of74 !! Large & Yeager 2008. Drag-coefficient reduction for Cyclone conditions!75 !! - using code-wide physical constants defined into "phycst.mod" rather than redifining them76 !! => 'vkarmn' and 'grav'77 !!78 !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk)79 65 !! 80 66 !! INPUT : 81 67 !! ------- 82 68 !! * zt : height for temperature and spec. hum. of air [m] 83 !! * zu : height for wind speed (generally 10m) [m] 84 !! * U_zu : scalar wind speed at 10m [m/s] 85 !! * sst : SST [K] 69 !! * zu : height for wind speed (usually 10m) [m] 70 !! * sst : bulk SST [K] 86 71 !! * t_zt : potential air temperature at zt [K] 87 72 !! * ssq : specific humidity at saturation at SST [kg/kg] 88 73 !! * q_zt : specific humidity of air at zt [kg/kg] 74 !! * U_zu : scalar wind speed at zu [m/s] 89 75 !! 90 76 !! … … 96 82 !! * t_zu : pot. air temperature adjusted at wind height zu [K] 97 83 !! * q_zu : specific humidity of air // [kg/kg] 98 !! * U_blk : bulk wind at 10m [m/s] 84 !! * U_blk : bulk wind speed at zu [m/s] 85 !! 86 !! 87 !! ** Author: L. Brodeau, June 2019 / AeroBulk (https://github.com/brodeau/aerobulk/) 99 88 !!---------------------------------------------------------------------------------- 100 89 REAL(wp), INTENT(in ) :: zt ! height for t_zt and q_zt [m] … … 103 92 REAL(wp), INTENT(in ), DIMENSION(jpi,jpj) :: t_zt ! potential air temperature [Kelvin] 104 93 REAL(wp), INTENT(in ), DIMENSION(jpi,jpj) :: ssq ! sea surface specific humidity [kg/kg] 105 REAL(wp), INTENT(in ), DIMENSION(jpi,jpj) :: q_zt ! specific air humidity 94 REAL(wp), INTENT(in ), DIMENSION(jpi,jpj) :: q_zt ! specific air humidity at zt [kg/kg] 106 95 REAL(wp), INTENT(in ), DIMENSION(jpi,jpj) :: U_zu ! relative wind module at zu [m/s] 107 96 REAL(wp), INTENT( out), DIMENSION(jpi,jpj) :: Cd ! transfer coefficient for momentum (tau) … … 110 99 REAL(wp), INTENT( out), DIMENSION(jpi,jpj) :: t_zu ! pot. air temp. adjusted at zu [K] 111 100 REAL(wp), INTENT( out), DIMENSION(jpi,jpj) :: q_zu ! spec. humidity adjusted at zu [kg/kg] 112 REAL(wp), INTENT( out), DIMENSION(jpi,jpj) :: U_blk ! bulk wind at 10m[m/s]101 REAL(wp), INTENT( out), DIMENSION(jpi,jpj) :: U_blk ! bulk wind speed at zu [m/s] 113 102 REAL(wp), INTENT( out), DIMENSION(jpi,jpj) :: Cdn, Chn, Cen ! neutral transfer coefficients 114 103 ! 115 INTEGER :: j_itt 116 LOGICAL :: l_zt_equal_zu = .FALSE. ! if q and t are given at same height as U 117 INTEGER , PARAMETER :: nb_itt = 4 ! number of itterations 104 INTEGER :: j_itt 105 LOGICAL :: l_zt_equal_zu = .FALSE. ! if q and t are given at same height as U 118 106 ! 119 107 REAL(wp), DIMENSION(jpi,jpj) :: Cx_n10 ! 10m neutral latent/sensible coefficient … … 126 114 ! 127 115 l_zt_equal_zu = .FALSE. 128 IF( ABS(zu - zt) < 0.01 )l_zt_equal_zu = .TRUE. ! testing "zu == zt" is risky with double precision129 130 U_blk = MAX( 0.5 , U_zu ) ! relative wind speed at zu (normally 10m), we don't want to fall under 0.5 m/s116 IF( ABS(zu - zt) < 0.01_wp ) l_zt_equal_zu = .TRUE. ! testing "zu == zt" is risky with double precision 117 118 U_blk = MAX( 0.5_wp , U_zu ) ! relative wind speed at zu (normally 10m), we don't want to fall under 0.5 m/s 131 119 132 120 !! First guess of stability: 133 ztmp0 = t_zt*(1. + rctv0*q_zt) - sst*(1. + rctv0*ssq) ! air-sea difference of virtual pot. temp. at zt134 stab = 0.5 + sign(0.5,ztmp0) ! stab = 1 if dTv > 0 => STABLE, 0 if unstable121 ztmp0 = virt_temp(t_zt, q_zt) - virt_temp(sst, ssq) ! air-sea difference of virtual pot. temp. at zt 122 stab = 0.5_wp + sign(0.5_wp,ztmp0) ! stab = 1 if dTv > 0 => STABLE, 0 if unstable 135 123 136 124 !! Neutral coefficients at 10m: … … 139 127 ztmp0 (:,:) = cdn_wave(:,:) 140 128 ELSE 141 129 ztmp0 = cd_neutral_10m( U_blk ) 142 130 ENDIF 143 131 … … 146 134 !! Initializing transf. coeff. with their first guess neutral equivalents : 147 135 Cd = ztmp0 148 Ce = 1.e-3 *( 34.6* sqrt_Cd_n10 )149 Ch = 1.e-3 *sqrt_Cd_n10*(18.*stab + 32.7*(1.- stab))136 Ce = 1.e-3_wp*( 34.6_wp * sqrt_Cd_n10 ) 137 Ch = 1.e-3_wp*sqrt_Cd_n10*(18._wp*stab + 32.7_wp*(1._wp - stab)) 150 138 stab = sqrt_Cd_n10 ! Temporaty array !!! stab == SQRT(Cd) 151 139 152 IF( ln_cdgw ) Cen = Ce ; Chn = Ch 140 IF( ln_cdgw ) THEN 141 Cen = Ce 142 Chn = Ch 143 ENDIF 153 144 154 145 !! Initializing values at z_u with z_t values: 155 146 t_zu = t_zt ; q_zu = q_zt 156 147 157 !! * Now starting iteration loop158 DO j_itt =1, nb_itt148 !! ITERATION BLOCK 149 DO j_itt = 1, nb_itt 159 150 ! 160 151 ztmp1 = t_zu - sst ! Updating air/sea differences … … 162 153 163 154 ! Updating turbulent scales : (L&Y 2004 eq. (7)) 164 ztmp1 = Ch/stab*ztmp1 ! theta* (stab == SQRT(Cd)) 165 ztmp2 = Ce/stab*ztmp2 ! q* (stab == SQRT(Cd)) 166 167 ztmp0 = 1. + rctv0*q_zu ! multiply this with t and you have the virtual temperature 155 ztmp0 = stab*U_blk ! u* (stab == SQRT(Cd)) 156 ztmp1 = Ch/stab*ztmp1 ! theta* (stab == SQRT(Cd)) 157 ztmp2 = Ce/stab*ztmp2 ! q* (stab == SQRT(Cd)) 168 158 169 159 ! Estimate the inverse of Monin-Obukov length (1/L) at height zu: 170 ztmp0 = (grav*vkarmn/(t_zu*ztmp0)*(ztmp1*ztmp0 + rctv0*t_zu*ztmp2)) / (Cd*U_blk*U_blk) 171 ! ( Cd*U_blk*U_blk is U*^2 at zu ) 172 160 ztmp0 = One_on_L( t_zu, q_zu, ztmp0, ztmp1, ztmp2 ) 161 173 162 !! Stability parameters : 174 zeta_u = zu*ztmp0 ; zeta_u = sign( min(abs(zeta_u),10.0), zeta_u ) 163 zeta_u = zu*ztmp0 164 zeta_u = sign( min(abs(zeta_u),10._wp), zeta_u ) 175 165 zpsi_h_u = psi_h( zeta_u ) 176 166 … … 178 168 IF( .NOT. l_zt_equal_zu ) THEN 179 169 !! Array 'stab' is free for the moment so using it to store 'zeta_t' 180 stab = zt*ztmp0 ; stab = SIGN( MIN(ABS(stab),10.0), stab ) ! Temporaty array stab == zeta_t !!! 170 stab = zt*ztmp0 171 stab = SIGN( MIN(ABS(stab),10._wp), stab ) ! Temporaty array stab == zeta_t !!! 181 172 stab = LOG(zt/zu) + zpsi_h_u - psi_h(stab) ! stab just used as temp array again! 182 173 t_zu = t_zt - ztmp1/vkarmn*stab ! ztmp1 is still theta* L&Y 2004 eq.(9b) 183 174 q_zu = q_zt - ztmp2/vkarmn*stab ! ztmp2 is still q* L&Y 2004 eq.(9c) 184 q_zu = max(0., q_zu) 185 END IF 186 175 q_zu = max(0._wp, q_zu) 176 ENDIF 177 178 ! Update neutral wind speed at 10m and neutral Cd at 10m (L&Y 2004 eq. 9a)... 179 ! In very rare low-wind conditions, the old way of estimating the 180 ! neutral wind speed at 10m leads to a negative value that causes the code 181 ! to crash. To prevent this a threshold of 0.25m/s is imposed. 187 182 ztmp2 = psi_m(zeta_u) 188 183 IF( ln_cdgw ) THEN ! surface wave case 189 184 stab = vkarmn / ( vkarmn / sqrt_Cd_n10 - ztmp2 ) ! (stab == SQRT(Cd)) 190 185 Cd = stab * stab 191 ztmp0 = (LOG(zu/10. ) - zpsi_h_u) / vkarmn / sqrt_Cd_n10186 ztmp0 = (LOG(zu/10._wp) - zpsi_h_u) / vkarmn / sqrt_Cd_n10 192 187 ztmp2 = stab / sqrt_Cd_n10 ! (stab == SQRT(Cd)) 193 ztmp1 = 1. + Chn * ztmp0188 ztmp1 = 1._wp + Chn * ztmp0 194 189 Ch = Chn * ztmp2 / ztmp1 ! L&Y 2004 eq. (10b) 195 ztmp1 = 1. + Cen * ztmp0190 ztmp1 = 1._wp + Cen * ztmp0 196 191 Ce = Cen * ztmp2 / ztmp1 ! L&Y 2004 eq. (10c) 197 192 198 193 ELSE 199 200 201 202 203 ztmp0 = MAX( 0.25 , U_blk/(1. + sqrt_Cd_n10/vkarmn*(LOG(zu/10.) - ztmp2)) ) ! U_n10 (ztmp2 == psi_m(zeta_u))204 205 206 207 208 stab = 0.5 + sign(0.5,zeta_u)! update stability209 Cx_n10 = 1.e-3*sqrt_Cd_n10*(18.*stab + 32.7*(1.- stab)) ! L&Y 2004 eq. (6c-6d) (Cx_n10 == Ch_n10)210 211 212 213 ztmp1 = 1. + sqrt_Cd_n10/vkarmn*(LOG(zu/10.) - ztmp2) ! L&Y 2004 eq. (10a) (ztmp2 == psi_m(zeta_u))214 215 216 217 ztmp0 = (LOG(zu/10.) - zpsi_h_u) / vkarmn / sqrt_Cd_n10218 219 ztmp1 = 1.+ Cx_n10*ztmp0 ! (Cx_n10 == Ch_n10)220 221 222 Cx_n10 = 1.e-3 * (34.6* sqrt_Cd_n10) ! L&Y 2004 eq. (6b) ! Cx_n10 == Ce_n10223 224 ztmp1 = 1.+ Cx_n10*ztmp0225 226 227 ! 228 END DO 229 ! 194 ! Update neutral wind speed at 10m and neutral Cd at 10m (L&Y 2004 eq. 9a)... 195 ! In very rare low-wind conditions, the old way of estimating the 196 ! neutral wind speed at 10m leads to a negative value that causes the code 197 ! to crash. To prevent this a threshold of 0.25m/s is imposed. 198 ztmp0 = MAX( 0.25_wp , U_blk/(1._wp + sqrt_Cd_n10/vkarmn*(LOG(zu/10._wp) - ztmp2)) ) ! U_n10 (ztmp2 == psi_m(zeta_u)) 199 ztmp0 = cd_neutral_10m(ztmp0) ! Cd_n10 200 Cdn(:,:) = ztmp0 201 sqrt_Cd_n10 = sqrt(ztmp0) 202 203 stab = 0.5_wp + sign(0.5_wp,zeta_u) ! update stability 204 Cx_n10 = 1.e-3_wp*sqrt_Cd_n10*(18._wp*stab + 32.7_wp*(1._wp - stab)) ! L&Y 2004 eq. (6c-6d) (Cx_n10 == Ch_n10) 205 Chn(:,:) = Cx_n10 206 207 !! Update of transfer coefficients: 208 ztmp1 = 1._wp + sqrt_Cd_n10/vkarmn*(LOG(zu/10._wp) - ztmp2) ! L&Y 2004 eq. (10a) (ztmp2 == psi_m(zeta_u)) 209 Cd = ztmp0 / ( ztmp1*ztmp1 ) 210 stab = SQRT( Cd ) ! Temporary array !!! (stab == SQRT(Cd)) 211 212 ztmp0 = (LOG(zu/10._wp) - zpsi_h_u) / vkarmn / sqrt_Cd_n10 213 ztmp2 = stab / sqrt_Cd_n10 ! (stab == SQRT(Cd)) 214 ztmp1 = 1._wp + Cx_n10*ztmp0 ! (Cx_n10 == Ch_n10) 215 Ch = Cx_n10*ztmp2 / ztmp1 ! L&Y 2004 eq. (10b) 216 217 Cx_n10 = 1.e-3_wp * (34.6_wp * sqrt_Cd_n10) ! L&Y 2004 eq. (6b) ! Cx_n10 == Ce_n10 218 Cen(:,:) = Cx_n10 219 ztmp1 = 1._wp + Cx_n10*ztmp0 220 Ce = Cx_n10*ztmp2 / ztmp1 ! L&Y 2004 eq. (10c) 221 ENDIF 222 223 END DO !DO j_itt = 1, nb_itt 224 230 225 END SUBROUTINE turb_ncar 231 226 … … 238 233 !! Origin: Large & Yeager 2008 eq.(11a) and eq.(11b) 239 234 !! 240 !! ** Author: L. Brodeau, june 2016 / AeroBulk (https:// sourceforge.net/p/aerobulk)235 !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://github.com/brodeau/aerobulk/) 241 236 !!---------------------------------------------------------------------------------- 242 237 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pw10 ! scalar wind speed at 10m (m/s) … … 247 242 !!---------------------------------------------------------------------------------- 248 243 ! 249 DO jj = 1, jpj 250 DO ji = 1, jpi 251 ! 252 zw = pw10(ji,jj) 253 zw6 = zw*zw*zw 254 zw6 = zw6*zw6 255 ! 256 ! When wind speed > 33 m/s => Cyclone conditions => special treatment 257 zgt33 = 0.5 + SIGN( 0.5, (zw - 33.) ) ! If pw10 < 33. => 0, else => 1 258 ! 259 cd_neutral_10m(ji,jj) = 1.e-3 * ( & 260 & (1. - zgt33)*( 2.7/zw + 0.142 + zw/13.09 - 3.14807E-10*zw6) & ! wind < 33 m/s 261 & + zgt33 * 2.34 ) ! wind >= 33 m/s 262 ! 263 cd_neutral_10m(ji,jj) = MAX(cd_neutral_10m(ji,jj), 1.E-6) 264 ! 265 END DO 266 END DO 244 DO_2D_11_11 245 ! 246 zw = pw10(ji,jj) 247 zw6 = zw*zw*zw 248 zw6 = zw6*zw6 249 ! 250 ! When wind speed > 33 m/s => Cyclone conditions => special treatment 251 zgt33 = 0.5_wp + SIGN( 0.5_wp, (zw - 33._wp) ) ! If pw10 < 33. => 0, else => 1 252 ! 253 cd_neutral_10m(ji,jj) = 1.e-3_wp * ( & 254 & (1._wp - zgt33)*( 2.7_wp/zw + 0.142_wp + zw/13.09_wp - 3.14807E-10_wp*zw6) & ! wind < 33 m/s 255 & + zgt33 * 2.34_wp ) ! wind >= 33 m/s 256 ! 257 cd_neutral_10m(ji,jj) = MAX(cd_neutral_10m(ji,jj), 1.E-6_wp) 258 ! 259 END_2D 267 260 ! 268 261 END FUNCTION cd_neutral_10m … … 273 266 !! Universal profile stability function for momentum 274 267 !! !! Psis, L&Y 2004 eq. (8c), (8d), (8e) 275 !! 276 !! pzet 0 : stability paramenter, z/L where z is altitude measurement268 !! 269 !! pzeta : stability paramenter, z/L where z is altitude measurement 277 270 !! and L is M-O length 278 271 !! 279 !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk)280 !!---------------------------------------------------------------------------------- 281 REAL(wp), DIMENSION(jpi,jpj) , INTENT(in) :: pzeta282 REAL(wp), DIMENSION(jpi,jpj) :: psi_m283 ! 284 INTEGER :: ji, jj 272 !! ** Author: L. Brodeau, June 2016 / AeroBulk (https://github.com/brodeau/aerobulk/) 273 !!---------------------------------------------------------------------------------- 274 REAL(wp), DIMENSION(jpi,jpj) :: psi_m 275 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pzeta 276 ! 277 INTEGER :: ji, jj ! dummy loop indices 285 278 REAL(wp) :: zx2, zx, zstab ! local scalars 286 279 !!---------------------------------------------------------------------------------- 287 ! 288 DO jj = 1, jpj 289 DO ji = 1, jpi 290 zx2 = SQRT( ABS( 1. - 16.*pzeta(ji,jj) ) ) 291 zx2 = MAX ( zx2 , 1. ) 292 zx = SQRT( zx2 ) 293 zstab = 0.5 + SIGN( 0.5 , pzeta(ji,jj) ) 294 ! 295 psi_m(ji,jj) = zstab * (-5.*pzeta(ji,jj)) & ! Stable 296 & + (1. - zstab) * (2.*LOG((1. + zx)*0.5) & ! Unstable 297 & + LOG((1. + zx2)*0.5) - 2.*ATAN(zx) + rpi*0.5) ! " 298 ! 299 END DO 300 END DO 301 ! 280 DO_2D_11_11 281 zx2 = SQRT( ABS( 1._wp - 16._wp*pzeta(ji,jj) ) ) 282 zx2 = MAX( zx2 , 1._wp ) 283 zx = SQRT( zx2 ) 284 zstab = 0.5_wp + SIGN( 0.5_wp , pzeta(ji,jj) ) 285 ! 286 psi_m(ji,jj) = zstab * (-5._wp*pzeta(ji,jj)) & ! Stable 287 & + (1._wp - zstab) * (2._wp*LOG((1._wp + zx)*0.5_wp) & ! Unstable 288 & + LOG((1._wp + zx2)*0.5_wp) - 2._wp*ATAN(zx) + rpi*0.5_wp) ! " 289 ! 290 END_2D 302 291 END FUNCTION psi_m 303 292 … … 308 297 !! !! Psis, L&Y 2004 eq. (8c), (8d), (8e) 309 298 !! 310 !! pzet 0 : stability paramenter, z/L where z is altitude measurement299 !! pzeta : stability paramenter, z/L where z is altitude measurement 311 300 !! and L is M-O length 312 301 !! 313 !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk) 314 !!---------------------------------------------------------------------------------- 302 !! ** Author: L. Brodeau, June 2016 / AeroBulk (https://github.com/brodeau/aerobulk/) 303 !!---------------------------------------------------------------------------------- 304 REAL(wp), DIMENSION(jpi,jpj) :: psi_h 315 305 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pzeta 316 REAL(wp), DIMENSION(jpi,jpj) :: psi_h 317 ! 318 INTEGER :: ji, jj ! dummy loop indices 306 ! 307 INTEGER :: ji, jj ! dummy loop indices 319 308 REAL(wp) :: zx2, zstab ! local scalars 320 309 !!---------------------------------------------------------------------------------- 321 310 ! 322 DO jj = 1, jpj 323 DO ji = 1, jpi 324 zx2 = SQRT( ABS( 1. - 16.*pzeta(ji,jj) ) ) 325 zx2 = MAX ( zx2 , 1. ) 326 zstab = 0.5 + SIGN( 0.5 , pzeta(ji,jj) ) 327 ! 328 psi_h(ji,jj) = zstab * (-5.*pzeta(ji,jj)) & ! Stable 329 & + (1. - zstab) * (2.*LOG( (1. + zx2)*0.5 )) ! Unstable 330 ! 331 END DO 332 END DO 333 ! 311 DO_2D_11_11 312 zx2 = SQRT( ABS( 1._wp - 16._wp*pzeta(ji,jj) ) ) 313 zx2 = MAX( zx2 , 1._wp ) 314 zstab = 0.5_wp + SIGN( 0.5_wp , pzeta(ji,jj) ) 315 ! 316 psi_h(ji,jj) = zstab * (-5._wp*pzeta(ji,jj)) & ! Stable 317 & + (1._wp - zstab) * (2._wp*LOG( (1._wp + zx2)*0.5_wp )) ! Unstable 318 ! 319 END_2D 334 320 END FUNCTION psi_h 335 321 -
NEMO/trunk/src/OCE/SBC/sbccpl.F90
r12288 r12377 27 27 USE sbcwave ! surface boundary condition: waves 28 28 USE phycst ! physical constants 29 USE isf_oce , ONLY : l_isfoasis, fwfisf_oasis ! ice shelf boundary condition 29 30 #if defined key_si3 30 31 USE ice ! ice variables … … 32 33 USE cpl_oasis3 ! OASIS3 coupling 33 34 USE geo2ocean ! 34 USE oce , ONLY : ts n, un, vn, sshn, ub, vb, sshb, fraqsr_1lev35 USE oce , ONLY : ts, uu, vv, ssh, fraqsr_1lev 35 36 USE ocealb ! 36 37 USE eosbn2 ! 37 38 USE sbcrnf , ONLY : l_rnfcpl 38 USE sbcisf , ONLY : l_isfcpl39 39 #if defined key_cice 40 40 USE ice_domain_size, only: ncat … … 198 198 199 199 !! Substitution 200 # include " vectopt_loop_substitute.h90"200 # include "do_loop_substitute.h90" 201 201 !!---------------------------------------------------------------------- 202 202 !! NEMO/OCE 4.0 , NEMO Consortium (2018) … … 264 264 ! ================================ ! 265 265 ! 266 REWIND( numnam_ref ) ! Namelist namsbc_cpl in reference namelist : Variables for OASIS coupling267 266 READ ( numnam_ref, namsbc_cpl, IOSTAT = ios, ERR = 901) 268 267 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namsbc_cpl in reference namelist' ) 269 268 ! 270 REWIND( numnam_cfg ) ! Namelist namsbc_cpl in configuration namelist : Variables for OASIS coupling271 269 READ ( numnam_cfg, namsbc_cpl, IOSTAT = ios, ERR = 902 ) 272 270 902 IF( ios > 0 ) CALL ctl_nam ( ios , 'namsbc_cpl in configuration namelist' ) … … 453 451 CASE( 'conservative' ) 454 452 srcv( (/jpr_rain, jpr_snow, jpr_ievp, jpr_tevp/) )%laction = .TRUE. 455 IF 453 IF( k_ice <= 1 ) srcv(jpr_ievp)%laction = .FALSE. 456 454 CASE( 'oce and ice' ) ; srcv( (/jpr_ievp, jpr_sbpr, jpr_semp, jpr_oemp/) )%laction = .TRUE. 457 455 CASE default ; CALL ctl_stop( 'sbc_cpl_init: wrong definition of sn_rcv_emp%cldes' ) … … 474 472 srcv(jpr_icb)%clname = 'OIceberg' ; IF( TRIM( sn_rcv_icb%cldes) == 'coupled' ) srcv(jpr_icb)%laction = .TRUE. 475 473 476 IF( srcv(jpr_isf)%laction .AND. ln_isf) THEN477 l_isf cpl = .TRUE. ! -> no need to read isf in sbcisf474 IF( srcv(jpr_isf)%laction ) THEN 475 l_isfoasis = .TRUE. ! -> isf fwf comes from oasis 478 476 IF(lwp) WRITE(numout,*) 479 477 IF(lwp) WRITE(numout,*) ' iceshelf received from oasis ' 478 CALL ctl_stop('STOP','not coded') 480 479 ENDIF 481 480 ! … … 533 532 ! ! ------------------------- ! 534 533 srcv(jpr_taum)%clname = 'O_TauMod' ; IF( TRIM(sn_rcv_taumod%cldes) == 'coupled' ) srcv(jpr_taum)%laction = .TRUE. 535 lhftau = srcv(jpr_taum)%laction536 534 ! 537 535 ! ! ------------------------- ! … … 558 556 srcv(jpr_botm )%clname = 'OBotMlt' 559 557 IF( TRIM(sn_rcv_iceflx%cldes) == 'coupled' ) THEN 560 IF 558 IF( TRIM( sn_rcv_iceflx%clcat ) == 'yes' ) THEN 561 559 srcv(jpr_topm:jpr_botm)%nct = nn_cats_cpl 562 560 ELSE … … 569 567 ! ! ------------------------- ! 570 568 srcv(jpr_ts_ice)%clname = 'OTsfIce' ! needed by Met Office 571 IF 572 IF 573 IF 569 IF( TRIM( sn_rcv_ts_ice%cldes ) == 'ice' ) srcv(jpr_ts_ice)%laction = .TRUE. 570 IF( TRIM( sn_rcv_ts_ice%clcat ) == 'yes' ) srcv(jpr_ts_ice)%nct = nn_cats_cpl 571 IF( TRIM( sn_rcv_emp%clcat ) == 'yes' ) srcv(jpr_ievp)%nct = nn_cats_cpl 574 572 575 573 #if defined key_si3 … … 699 697 ! for example O_Runoff received by OPA from SAS and therefore O_Runoff received by SAS from the Atmosphere 700 698 DO jn = 1, jprcv 701 IF 699 IF( srcv(jn)%clname(1:1) == "O" ) srcv(jn)%clname = "S"//srcv(jn)%clname(2:LEN(srcv(jn)%clname)) 702 700 END DO 703 701 ! … … 726 724 ! =================================================== ! 727 725 DO jn = 1, jprcv 728 IF 726 IF( srcv(jn)%laction ) ALLOCATE( frcv(jn)%z3(jpi,jpj,srcv(jn)%nct) ) 729 727 END DO 730 728 ! Allocate taum part of frcv which is used even when not received as coupling field 731 IF 729 IF( .NOT. srcv(jpr_taum)%laction ) ALLOCATE( frcv(jpr_taum)%z3(jpi,jpj,srcv(jpr_taum)%nct) ) 732 730 ! Allocate w10m part of frcv which is used even when not received as coupling field 733 IF 731 IF( .NOT. srcv(jpr_w10m)%laction ) ALLOCATE( frcv(jpr_w10m)%z3(jpi,jpj,srcv(jpr_w10m)%nct) ) 734 732 ! Allocate jpr_otx1 part of frcv which is used even when not received as coupling field 735 IF 736 IF 733 IF( .NOT. srcv(jpr_otx1)%laction ) ALLOCATE( frcv(jpr_otx1)%z3(jpi,jpj,srcv(jpr_otx1)%nct) ) 734 IF( .NOT. srcv(jpr_oty1)%laction ) ALLOCATE( frcv(jpr_oty1)%z3(jpi,jpj,srcv(jpr_oty1)%nct) ) 737 735 ! Allocate itx1 and ity1 as they are used in sbc_cpl_ice_tau even if srcv(jpr_itx1)%laction = .FALSE. 738 736 IF( k_ice /= 0 ) THEN 739 IF 740 IF 741 END 737 IF( .NOT. srcv(jpr_itx1)%laction ) ALLOCATE( frcv(jpr_itx1)%z3(jpi,jpj,srcv(jpr_itx1)%nct) ) 738 IF( .NOT. srcv(jpr_ity1)%laction ) ALLOCATE( frcv(jpr_ity1)%z3(jpi,jpj,srcv(jpr_ity1)%nct) ) 739 ENDIF 742 740 743 741 ! ================================ ! … … 763 761 CASE( 'oce and ice' , 'weighted oce and ice' , 'oce and weighted ice' ) 764 762 ssnd( (/jps_toce, jps_tice/) )%laction = .TRUE. 765 IF 763 IF( TRIM( sn_snd_temp%clcat ) == 'yes' ) ssnd(jps_tice)%nct = nn_cats_cpl 766 764 CASE( 'mixed oce-ice' ) ; ssnd( jps_tmix )%laction = .TRUE. 767 765 CASE default ; CALL ctl_stop( 'sbc_cpl_init: wrong definition of sn_snd_temp%cldes' ) … … 783 781 ! 1. sending mixed oce-ice albedo or 784 782 ! 2. receiving mixed oce-ice solar radiation 785 IF 783 IF( TRIM ( sn_snd_alb%cldes ) == 'mixed oce-ice' .OR. TRIM ( sn_rcv_qsr%cldes ) == 'mixed oce-ice' ) THEN 786 784 CALL oce_alb( zaos, zacs ) 787 785 ! Due to lack of information on nebulosity : mean clear/overcast sky … … 802 800 ssnd(jps_fice1)%laction = .TRUE. ! First-order regridded ice concentration, to be used producing atmos-to-ice fluxes (Met Office requirement) 803 801 ! Currently no namelist entry to determine sending of multi-category ice fraction so use the thickness entry for now 804 IF 805 IF 802 IF( TRIM( sn_snd_thick%clcat ) == 'yes' ) ssnd(jps_fice)%nct = nn_cats_cpl 803 IF( TRIM( sn_snd_thick1%clcat ) == 'yes' ) ssnd(jps_fice1)%nct = nn_cats_cpl 806 804 ENDIF 807 805 808 IF 806 IF(TRIM( sn_snd_ifrac%cldes ) == 'coupled') ssnd(jps_ficet)%laction = .TRUE. 809 807 810 808 SELECT CASE ( TRIM( sn_snd_thick%cldes ) ) … … 812 810 CASE( 'ice and snow' ) 813 811 ssnd(jps_hice:jps_hsnw)%laction = .TRUE. 814 IF 812 IF( TRIM( sn_snd_thick%clcat ) == 'yes' ) THEN 815 813 ssnd(jps_hice:jps_hsnw)%nct = nn_cats_cpl 816 814 ENDIF 817 815 CASE ( 'weighted ice and snow' ) 818 816 ssnd(jps_hice:jps_hsnw)%laction = .TRUE. 819 IF 817 IF( TRIM( sn_snd_thick%clcat ) == 'yes' ) ssnd(jps_hice:jps_hsnw)%nct = nn_cats_cpl 820 818 CASE default ; CALL ctl_stop( 'sbc_cpl_init: wrong definition of sn_snd_thick%cldes' ) 821 819 END SELECT … … 834 832 ssnd(jps_a_p)%laction = .TRUE. 835 833 ssnd(jps_ht_p)%laction = .TRUE. 836 IF 834 IF( TRIM( sn_snd_mpnd%clcat ) == 'yes' ) THEN 837 835 ssnd(jps_a_p)%nct = nn_cats_cpl 838 836 ssnd(jps_ht_p)%nct = nn_cats_cpl 839 837 ELSE 840 IF 838 IF( nn_cats_cpl > 1 ) THEN 841 839 CALL ctl_stop( 'sbc_cpl_init: use weighted ice option for sn_snd_mpnd%cldes if not exchanging category fields' ) 842 840 ENDIF … … 845 843 ssnd(jps_a_p)%laction = .TRUE. 846 844 ssnd(jps_ht_p)%laction = .TRUE. 847 IF 845 IF( TRIM( sn_snd_mpnd%clcat ) == 'yes' ) THEN 848 846 ssnd(jps_a_p)%nct = nn_cats_cpl 849 847 ssnd(jps_ht_p)%nct = nn_cats_cpl … … 919 917 CASE ( 'ice only' ) 920 918 ssnd(jps_ttilyr)%laction = .TRUE. 921 IF 919 IF( TRIM( sn_snd_ttilyr%clcat ) == 'yes' ) THEN 922 920 ssnd(jps_ttilyr)%nct = nn_cats_cpl 923 921 ELSE 924 IF 922 IF( nn_cats_cpl > 1 ) THEN 925 923 CALL ctl_stop( 'sbc_cpl_init: use weighted ice option for sn_snd_ttilyr%cldes if not exchanging category fields' ) 926 924 ENDIF … … 928 926 CASE ( 'weighted ice' ) 929 927 ssnd(jps_ttilyr)%laction = .TRUE. 930 IF 928 IF( TRIM( sn_snd_ttilyr%clcat ) == 'yes' ) ssnd(jps_ttilyr)%nct = nn_cats_cpl 931 929 CASE default ; CALL ctl_stop( 'sbc_cpl_init: wrong definition of sn_snd_ttilyr%cldes;'//sn_snd_ttilyr%cldes ) 932 930 END SELECT … … 938 936 CASE ( 'ice only' ) 939 937 ssnd(jps_kice)%laction = .TRUE. 940 IF 938 IF( TRIM( sn_snd_cond%clcat ) == 'yes' ) THEN 941 939 ssnd(jps_kice)%nct = nn_cats_cpl 942 940 ELSE 943 IF 941 IF( nn_cats_cpl > 1 ) THEN 944 942 CALL ctl_stop( 'sbc_cpl_init: use weighted ice option for sn_snd_cond%cldes if not exchanging category fields' ) 945 943 ENDIF … … 947 945 CASE ( 'weighted ice' ) 948 946 ssnd(jps_kice)%laction = .TRUE. 949 IF 947 IF( TRIM( sn_snd_cond%clcat ) == 'yes' ) ssnd(jps_kice)%nct = nn_cats_cpl 950 948 CASE default ; CALL ctl_stop( 'sbc_cpl_init: wrong definition of sn_snd_cond%cldes;'//sn_snd_cond%cldes ) 951 949 END SELECT … … 1008 1006 ! for example O_SSTSST sent by OPA to SAS and therefore S_SSTSST sent by SAS to the Atmosphere 1009 1007 DO jn = 1, jpsnd 1010 IF 1008 IF( ssnd(jn)%clname(1:1) == "O" ) ssnd(jn)%clname = "S"//ssnd(jn)%clname(2:LEN(ssnd(jn)%clname)) 1011 1009 END DO 1012 1010 ! … … 1035 1033 CALL cpl_define(jprcv, jpsnd, nn_cplmodel) 1036 1034 1037 IF 1035 IF(ln_usecplmask) THEN 1038 1036 xcplmask(:,:,:) = 0. 1039 1037 CALL iom_open( 'cplmask', inum ) … … 1049 1047 1050 1048 1051 SUBROUTINE sbc_cpl_rcv( kt, k_fsbc, k_ice )1049 SUBROUTINE sbc_cpl_rcv( kt, k_fsbc, k_ice, Kbb, Kmm ) 1052 1050 !!---------------------------------------------------------------------- 1053 1051 !! *** ROUTINE sbc_cpl_rcv *** … … 1099 1097 INTEGER, INTENT(in) :: k_fsbc ! frequency of sbc (-> ice model) computation 1100 1098 INTEGER, INTENT(in) :: k_ice ! ice management in the sbc (=0/1/2/3) 1099 INTEGER, INTENT(in) :: Kbb, Kmm ! ocean model time level indices 1101 1100 !! 1102 1101 LOGICAL :: llnewtx, llnewtau ! update wind stress components and module?? … … 1166 1165 ! 1167 1166 IF( srcv(jpr_otx1)%clgrid == 'T' ) THEN 1168 DO jj = 2, jpjm1 ! T ==> (U,V) 1169 DO ji = fs_2, fs_jpim1 ! vector opt. 1170 frcv(jpr_otx1)%z3(ji,jj,1) = 0.5 * ( frcv(jpr_otx1)%z3(ji+1,jj ,1) + frcv(jpr_otx1)%z3(ji,jj,1) ) 1171 frcv(jpr_oty1)%z3(ji,jj,1) = 0.5 * ( frcv(jpr_oty1)%z3(ji ,jj+1,1) + frcv(jpr_oty1)%z3(ji,jj,1) ) 1172 END DO 1173 END DO 1167 DO_2D_00_00 1168 frcv(jpr_otx1)%z3(ji,jj,1) = 0.5 * ( frcv(jpr_otx1)%z3(ji+1,jj ,1) + frcv(jpr_otx1)%z3(ji,jj,1) ) 1169 frcv(jpr_oty1)%z3(ji,jj,1) = 0.5 * ( frcv(jpr_oty1)%z3(ji ,jj+1,1) + frcv(jpr_oty1)%z3(ji,jj,1) ) 1170 END_2D 1174 1171 CALL lbc_lnk_multi( 'sbccpl', frcv(jpr_otx1)%z3(:,:,1), 'U', -1., frcv(jpr_oty1)%z3(:,:,1), 'V', -1. ) 1175 1172 ENDIF … … 1192 1189 ! => need to be done only when otx1 was changed 1193 1190 IF( llnewtx ) THEN 1194 DO jj = 2, jpjm1 1195 DO ji = fs_2, fs_jpim1 ! vect. opt. 1196 zzx = frcv(jpr_otx1)%z3(ji-1,jj ,1) + frcv(jpr_otx1)%z3(ji,jj,1) 1197 zzy = frcv(jpr_oty1)%z3(ji ,jj-1,1) + frcv(jpr_oty1)%z3(ji,jj,1) 1198 frcv(jpr_taum)%z3(ji,jj,1) = 0.5 * SQRT( zzx * zzx + zzy * zzy ) 1199 END DO 1200 END DO 1191 DO_2D_00_00 1192 zzx = frcv(jpr_otx1)%z3(ji-1,jj ,1) + frcv(jpr_otx1)%z3(ji,jj,1) 1193 zzy = frcv(jpr_oty1)%z3(ji ,jj-1,1) + frcv(jpr_oty1)%z3(ji,jj,1) 1194 frcv(jpr_taum)%z3(ji,jj,1) = 0.5 * SQRT( zzx * zzx + zzy * zzy ) 1195 END_2D 1201 1196 CALL lbc_lnk( 'sbccpl', frcv(jpr_taum)%z3(:,:,1), 'T', 1. ) 1202 1197 llnewtau = .TRUE. … … 1219 1214 IF( llnewtau ) THEN 1220 1215 zcoef = 1. / ( zrhoa * zcdrag ) 1221 DO jj = 1, jpj 1222 DO ji = 1, jpi 1223 frcv(jpr_w10m)%z3(ji,jj,1) = SQRT( frcv(jpr_taum)%z3(ji,jj,1) * zcoef ) 1224 END DO 1225 END DO 1216 DO_2D_11_11 1217 frcv(jpr_w10m)%z3(ji,jj,1) = SQRT( frcv(jpr_taum)%z3(ji,jj,1) * zcoef ) 1218 END_2D 1226 1219 ENDIF 1227 1220 ENDIF … … 1262 1255 1263 1256 IF( kt == nit000 ) ssh_ibb(:,:) = ssh_ib(:,:) ! correct this later (read from restart if possible) 1264 END 1257 ENDIF 1265 1258 ! 1266 1259 IF( ln_sdw ) THEN ! Stokes Drift correction activated … … 1298 1291 IF( srcv(jpr_sdrftx)%laction .OR. srcv(jpr_sdrfty)%laction .OR. srcv(jpr_wper)%laction & 1299 1292 .OR. srcv(jpr_hsig)%laction .OR. srcv(jpr_wfreq)%laction) THEN 1300 CALL sbc_stokes( )1293 CALL sbc_stokes( Kmm ) 1301 1294 ENDIF 1302 1295 ENDIF … … 1350 1343 IF( srcv(jpr_ocx1)%laction ) THEN ! received by sas in case of opa <-> sas coupling 1351 1344 ssu_m(:,:) = frcv(jpr_ocx1)%z3(:,:,1) 1352 u b (:,:,1) = ssu_m(:,:)! will be used in icestp in the call of ice_forcing_tau1353 u n (:,:,1) = ssu_m(:,:)! will be used in sbc_cpl_snd if atmosphere coupling1345 uu(:,:,1,Kbb) = ssu_m(:,:) ! will be used in icestp in the call of ice_forcing_tau 1346 uu(:,:,1,Kmm) = ssu_m(:,:) ! will be used in sbc_cpl_snd if atmosphere coupling 1354 1347 CALL iom_put( 'ssu_m', ssu_m ) 1355 1348 ENDIF 1356 1349 IF( srcv(jpr_ocy1)%laction ) THEN 1357 1350 ssv_m(:,:) = frcv(jpr_ocy1)%z3(:,:,1) 1358 v b (:,:,1) = ssv_m(:,:)! will be used in icestp in the call of ice_forcing_tau1359 v n (:,:,1) = ssv_m(:,:)! will be used in sbc_cpl_snd if atmosphere coupling1351 vv(:,:,1,Kbb) = ssv_m(:,:) ! will be used in icestp in the call of ice_forcing_tau 1352 vv(:,:,1,Kmm) = ssv_m(:,:) ! will be used in sbc_cpl_snd if atmosphere coupling 1360 1353 CALL iom_put( 'ssv_m', ssv_m ) 1361 1354 ENDIF … … 1401 1394 rnf(:,:) = rnf(:,:) + fwficb(:,:) ! iceberg added to runfofs 1402 1395 ENDIF 1403 IF( srcv(jpr_isf)%laction ) fwfisf(:,:) = - frcv(jpr_isf)%z3(:,:,1) ! fresh water flux from the isf (fwfisf <0 mean melting) 1396 ! 1397 ! ice shelf fwf 1398 IF( srcv(jpr_isf)%laction ) THEN 1399 fwfisf_oasis(:,:) = - frcv(jpr_isf)%z3(:,:,1) ! fresh water flux from the isf (fwfisf <0 mean melting) 1400 END IF 1404 1401 1405 1402 IF( ln_mixcpl ) THEN ; emp(:,:) = emp(:,:) * xcplmask(:,:,0) + zemp(:,:) * zmsk(:,:) … … 1411 1408 ELSE IF( srcv(jpr_qnsmix)%laction ) THEN ; zqns(:,:) = frcv(jpr_qnsmix)%z3(:,:,1) 1412 1409 ELSE ; zqns(:,:) = 0._wp 1413 END 1410 ENDIF 1414 1411 ! update qns over the free ocean with: 1415 1412 IF( nn_components /= jp_iam_opa ) THEN … … 1546 1543 p_tauj(:,:) = frcv(jpr_ity1)%z3(:,:,1) 1547 1544 CASE( 'F' ) 1548 DO jj = 2, jpjm1 ! F ==> (U,V) 1549 DO ji = fs_2, fs_jpim1 ! vector opt. 1550 p_taui(ji,jj) = 0.5 * ( frcv(jpr_itx1)%z3(ji,jj,1) + frcv(jpr_itx1)%z3(ji ,jj-1,1) ) 1551 p_tauj(ji,jj) = 0.5 * ( frcv(jpr_ity1)%z3(ji,jj,1) + frcv(jpr_ity1)%z3(ji-1,jj ,1) ) 1552 END DO 1553 END DO 1545 DO_2D_00_00 1546 p_taui(ji,jj) = 0.5 * ( frcv(jpr_itx1)%z3(ji,jj,1) + frcv(jpr_itx1)%z3(ji ,jj-1,1) ) 1547 p_tauj(ji,jj) = 0.5 * ( frcv(jpr_ity1)%z3(ji,jj,1) + frcv(jpr_ity1)%z3(ji-1,jj ,1) ) 1548 END_2D 1554 1549 CASE( 'T' ) 1555 DO jj = 2, jpjm1 ! T ==> (U,V) 1556 DO ji = fs_2, fs_jpim1 ! vector opt. 1557 p_taui(ji,jj) = 0.5 * ( frcv(jpr_itx1)%z3(ji+1,jj ,1) + frcv(jpr_itx1)%z3(ji,jj,1) ) 1558 p_tauj(ji,jj) = 0.5 * ( frcv(jpr_ity1)%z3(ji ,jj+1,1) + frcv(jpr_ity1)%z3(ji,jj,1) ) 1559 END DO 1560 END DO 1550 DO_2D_00_00 1551 p_taui(ji,jj) = 0.5 * ( frcv(jpr_itx1)%z3(ji+1,jj ,1) + frcv(jpr_itx1)%z3(ji,jj,1) ) 1552 p_tauj(ji,jj) = 0.5 * ( frcv(jpr_ity1)%z3(ji ,jj+1,1) + frcv(jpr_ity1)%z3(ji,jj,1) ) 1553 END_2D 1561 1554 CASE( 'I' ) 1562 DO jj = 2, jpjm1 ! I ==> (U,V) 1563 DO ji = 2, jpim1 ! NO vector opt. 1564 p_taui(ji,jj) = 0.5 * ( frcv(jpr_itx1)%z3(ji+1,jj+1,1) + frcv(jpr_itx1)%z3(ji+1,jj ,1) ) 1565 p_tauj(ji,jj) = 0.5 * ( frcv(jpr_ity1)%z3(ji+1,jj+1,1) + frcv(jpr_ity1)%z3(ji ,jj+1,1) ) 1566 END DO 1567 END DO 1555 DO_2D_00_00 1556 p_taui(ji,jj) = 0.5 * ( frcv(jpr_itx1)%z3(ji+1,jj+1,1) + frcv(jpr_itx1)%z3(ji+1,jj ,1) ) 1557 p_tauj(ji,jj) = 0.5 * ( frcv(jpr_ity1)%z3(ji+1,jj+1,1) + frcv(jpr_ity1)%z3(ji ,jj+1,1) ) 1558 END_2D 1568 1559 END SELECT 1569 1560 IF( srcv(jpr_itx1)%clgrid /= 'U' ) THEN … … 1683 1674 ! --- evaporation over ice (kg/m2/s) --- ! 1684 1675 DO jl=1,jpl 1685 IF 1676 IF(sn_rcv_emp%clcat == 'yes') THEN ; zevap_ice(:,:,jl) = frcv(jpr_ievp)%z3(:,:,jl) 1686 1677 ELSE ; zevap_ice(:,:,jl) = frcv(jpr_ievp)%z3(:,:,1 ) ; ENDIF 1687 1678 ENDDO … … 1704 1695 ENDIF 1705 1696 IF( srcv(jpr_isf)%laction ) THEN ! iceshelf (fwfisf <0 mean melting) 1706 fwfisf (:,:) = - frcv(jpr_isf)%z3(:,:,1)1697 fwfisf_oasis(:,:) = - frcv(jpr_isf)%z3(:,:,1) 1707 1698 ENDIF 1708 1699 … … 1743 1734 ENDIF 1744 1735 IF( srcv(jpr_isf)%laction ) THEN ! iceshelf (fwfisf <0 mean melting) 1745 fwfisf (:,:) = - frcv(jpr_isf)%z3(:,:,1)1736 fwfisf_oasis(:,:) = - frcv(jpr_isf)%z3(:,:,1) 1746 1737 ENDIF 1747 1738 ! … … 1765 1756 IF( srcv(jpr_cal)%laction ) CALL iom_put( 'calving_cea' , frcv(jpr_cal)%z3(:,:,1) * tmask(:,:,1) ) ! calving 1766 1757 IF( srcv(jpr_icb)%laction ) CALL iom_put( 'iceberg_cea' , frcv(jpr_icb)%z3(:,:,1) * tmask(:,:,1) ) ! icebergs 1767 CALL iom_put( 'snowpre' , sprecip(:,:) ) ! Snow1768 CALL iom_put( 'precip' , tprecip(:,:) ) ! total precipitation1769 IF ( iom_use('rain') )CALL iom_put( 'rain' , tprecip(:,:) - sprecip(:,:) ) ! liquid precipitation1770 IF ( iom_use('snow_ao_cea') )CALL iom_put( 'snow_ao_cea' , sprecip(:,:) * ( 1._wp - zsnw(:,:) ) ) ! Snow over ice-free ocean (cell average)1771 IF ( iom_use('snow_ai_cea') )CALL iom_put( 'snow_ai_cea' , sprecip(:,:) * zsnw(:,:) ) ! Snow over sea-ice (cell average)1772 IF ( iom_use('rain_ao_cea') )CALL iom_put( 'rain_ao_cea' , ( tprecip(:,:) - sprecip(:,:) ) * picefr(:,:) ) ! liquid precipitation over ocean (cell average)1773 IF ( iom_use('subl_ai_cea') )CALL iom_put( 'subl_ai_cea' , frcv(jpr_ievp)%z3(:,:,1) * picefr(:,:) * tmask(:,:,1) ) ! Sublimation over sea-ice (cell average)1774 IF ( iom_use('evap_ao_cea') )CALL iom_put( 'evap_ao_cea' , ( frcv(jpr_tevp)%z3(:,:,1) &1758 IF( iom_use('snowpre') ) CALL iom_put( 'snowpre' , sprecip(:,:) ) ! Snow 1759 IF( iom_use('precip') ) CALL iom_put( 'precip' , tprecip(:,:) ) ! total precipitation 1760 IF( iom_use('rain') ) CALL iom_put( 'rain' , tprecip(:,:) - sprecip(:,:) ) ! liquid precipitation 1761 IF( iom_use('snow_ao_cea') ) CALL iom_put( 'snow_ao_cea' , sprecip(:,:) * ( 1._wp - zsnw(:,:) ) ) ! Snow over ice-free ocean (cell average) 1762 IF( iom_use('snow_ai_cea') ) CALL iom_put( 'snow_ai_cea' , sprecip(:,:) * zsnw(:,:) ) ! Snow over sea-ice (cell average) 1763 IF( iom_use('rain_ao_cea') ) CALL iom_put( 'rain_ao_cea' , ( tprecip(:,:) - sprecip(:,:) ) * picefr(:,:) ) ! liquid precipitation over ocean (cell average) 1764 IF( iom_use('subl_ai_cea') ) CALL iom_put( 'subl_ai_cea' , frcv(jpr_ievp)%z3(:,:,1) * picefr(:,:) * tmask(:,:,1) ) ! Sublimation over sea-ice (cell average) 1765 IF( iom_use('evap_ao_cea') ) CALL iom_put( 'evap_ao_cea' , ( frcv(jpr_tevp)%z3(:,:,1) & 1775 1766 & - frcv(jpr_ievp)%z3(:,:,1) * picefr(:,:) ) * tmask(:,:,1) ) ! ice-free oce evap (cell average) 1776 1767 ! note: runoff output is done in sbcrnf (which includes icebergs too) and iceshelf output is done in sbcisf … … 1783 1774 CASE( 'conservative' ) ! the required fields are directly provided 1784 1775 zqns_tot(:,:) = frcv(jpr_qnsmix)%z3(:,:,1) 1785 IF 1776 IF( TRIM(sn_rcv_qns%clcat) == 'yes' ) THEN 1786 1777 zqns_ice(:,:,1:jpl) = frcv(jpr_qnsice)%z3(:,:,1:jpl) 1787 1778 ELSE … … 1792 1783 CASE( 'oce and ice' ) ! the total flux is computed from ocean and ice fluxes 1793 1784 zqns_tot(:,:) = ziceld(:,:) * frcv(jpr_qnsoce)%z3(:,:,1) 1794 IF 1785 IF( TRIM(sn_rcv_qns%clcat) == 'yes' ) THEN 1795 1786 DO jl=1,jpl 1796 1787 zqns_tot(:,: ) = zqns_tot(:,:) + a_i(:,:,jl) * frcv(jpr_qnsice)%z3(:,:,jl) … … 1904 1895 #endif 1905 1896 ! outputs 1906 IF ( srcv(jpr_cal)%laction ) CALL iom_put('hflx_cal_cea' , - frcv(jpr_cal)%z3(:,:,1) * rLfus ) ! latent heat from calving 1907 IF ( srcv(jpr_icb)%laction ) CALL iom_put('hflx_icb_cea' , - frcv(jpr_icb)%z3(:,:,1) * rLfus ) ! latent heat from icebergs melting 1908 IF ( iom_use( 'hflx_rain_cea') ) CALL iom_put('hflx_rain_cea' , ( tprecip(:,:) - sprecip(:,:) ) * zcptrain(:,:) ) ! heat flux from rain (cell average) 1909 IF ( iom_use( 'hflx_evap_cea') ) CALL iom_put('hflx_evap_cea' , ( frcv(jpr_tevp)%z3(:,:,1) - frcv(jpr_ievp)%z3(:,:,1) * picefr(:,:) ) & 1910 & * zcptn(:,:) * tmask(:,:,1) ) ! heat flux from evap (cell average) 1911 IF ( iom_use( 'hflx_prec_cea') ) CALL iom_put('hflx_prec_cea' , sprecip(:,:) * ( zcptsnw(:,:) - rLfus ) & ! heat flux from all precip (cell avg) 1912 & + ( tprecip(:,:) - sprecip(:,:) ) * zcptrain(:,:) ) 1913 IF ( iom_use( 'hflx_snow_cea') ) CALL iom_put('hflx_snow_cea' , sprecip(:,:) * ( zcptsnw(:,:) - rLfus ) ) ! heat flux from snow (cell average) 1914 IF ( iom_use('hflx_snow_ao_cea') ) CALL iom_put('hflx_snow_ao_cea', sprecip(:,:) * ( zcptsnw(:,:) - rLfus ) * ( 1._wp - zsnw(:,:) ) ) ! heat flux from snow (over ocean) 1915 IF ( iom_use('hflx_snow_ai_cea') ) CALL iom_put('hflx_snow_ai_cea', sprecip(:,:) * ( zcptsnw(:,:) - rLfus ) * zsnw(:,:) ) ! heat flux from snow (over ice) 1897 IF( srcv(jpr_cal)%laction ) CALL iom_put('hflx_cal_cea' , - frcv(jpr_cal)%z3(:,:,1) * rLfus ) ! latent heat from calving 1898 IF( srcv(jpr_icb)%laction ) CALL iom_put('hflx_icb_cea' , - frcv(jpr_icb)%z3(:,:,1) * rLfus ) ! latent heat from icebergs melting 1899 IF( iom_use('hflx_rain_cea') ) CALL iom_put('hflx_rain_cea' , ( tprecip(:,:) - sprecip(:,:) ) * zcptrain(:,:) ) ! heat flux from rain (cell average) 1900 IF( iom_use('hflx_evap_cea') ) CALL iom_put('hflx_evap_cea' , ( frcv(jpr_tevp)%z3(:,:,1) - frcv(jpr_ievp)%z3(:,:,1) & 1901 & * picefr(:,:) ) * zcptn(:,:) * tmask(:,:,1) ) ! heat flux from evap (cell average) 1902 IF( iom_use('hflx_prec_cea') ) CALL iom_put('hflx_prec_cea' , sprecip(:,:) * ( zcptsnw(:,:) - rLfus ) + & ! heat flux from all precip (cell avg) 1903 & ( tprecip(:,:) - sprecip(:,:) ) * zcptrain(:,:) ) 1904 IF( iom_use('hflx_snow_cea') ) CALL iom_put('hflx_snow_cea' , sprecip(:,:) * ( zcptsnw(:,:) - rLfus ) ) ! heat flux from snow (cell average) 1905 IF( iom_use('hflx_snow_ao_cea') ) CALL iom_put('hflx_snow_ao_cea', sprecip(:,:) * ( zcptsnw(:,:) - rLfus ) & 1906 & * ( 1._wp - zsnw(:,:) ) ) ! heat flux from snow (over ocean) 1907 IF( iom_use('hflx_snow_ai_cea') ) CALL iom_put('hflx_snow_ai_cea', sprecip(:,:) * ( zcptsnw(:,:) - rLfus ) & 1908 & * zsnw(:,:) ) ! heat flux from snow (over ice) 1916 1909 ! note: hflx for runoff and iceshelf are done in sbcrnf and sbcisf resp. 1917 1910 ! … … 1923 1916 CASE( 'conservative' ) 1924 1917 zqsr_tot(:,: ) = frcv(jpr_qsrmix)%z3(:,:,1) 1925 IF 1918 IF( TRIM(sn_rcv_qsr%clcat) == 'yes' ) THEN 1926 1919 zqsr_ice(:,:,1:jpl) = frcv(jpr_qsrice)%z3(:,:,1:jpl) 1927 1920 ELSE … … 1933 1926 CASE( 'oce and ice' ) 1934 1927 zqsr_tot(:,: ) = ziceld(:,:) * frcv(jpr_qsroce)%z3(:,:,1) 1935 IF 1928 IF( TRIM(sn_rcv_qsr%clcat) == 'yes' ) THEN 1936 1929 DO jl = 1, jpl 1937 1930 zqsr_tot(:,: ) = zqsr_tot(:,:) + a_i(:,:,jl) * frcv(jpr_qsrice)%z3(:,:,jl) … … 1999 1992 ! ! ========================= ! 2000 1993 CASE ('coupled') 2001 IF 1994 IF( TRIM(sn_rcv_dqnsdt%clcat) == 'yes' ) THEN 2002 1995 zdqns_ice(:,:,1:jpl) = frcv(jpr_dqnsdt)%z3(:,:,1:jpl) 2003 1996 ELSE … … 2088 2081 2089 2082 2090 SUBROUTINE sbc_cpl_snd( kt )2083 SUBROUTINE sbc_cpl_snd( kt, Kbb, Kmm ) 2091 2084 !!---------------------------------------------------------------------- 2092 2085 !! *** ROUTINE sbc_cpl_snd *** … … 2098 2091 !!---------------------------------------------------------------------- 2099 2092 INTEGER, INTENT(in) :: kt 2093 INTEGER, INTENT(in) :: Kbb, Kmm ! ocean model time level index 2100 2094 ! 2101 2095 INTEGER :: ji, jj, jl ! dummy loop indices … … 2114 2108 IF( ssnd(jps_toce)%laction .OR. ssnd(jps_tice)%laction .OR. ssnd(jps_tmix)%laction ) THEN 2115 2109 2116 IF 2117 ztmp1(:,:) = ts n(:,:,1,jp_tem) ! send temperature as it is (potential or conservative) -> use of l_useCT on the received part2110 IF( nn_components == jp_iam_opa ) THEN 2111 ztmp1(:,:) = ts(:,:,1,jp_tem,Kmm) ! send temperature as it is (potential or conservative) -> use of l_useCT on the received part 2118 2112 ELSE 2119 2113 ! we must send the surface potential temperature 2120 IF( l_useCT ) THEN ; ztmp1(:,:) = eos_pt_from_ct( ts n(:,:,1,jp_tem), tsn(:,:,1,jp_sal) )2121 ELSE ; ztmp1(:,:) = ts n(:,:,1,jp_tem)2114 IF( l_useCT ) THEN ; ztmp1(:,:) = eos_pt_from_ct( ts(:,:,1,jp_tem,Kmm), ts(:,:,1,jp_sal,Kmm) ) 2115 ELSE ; ztmp1(:,:) = ts(:,:,1,jp_tem,Kmm) 2122 2116 ENDIF 2123 2117 ! … … 2147 2141 CASE default ; CALL ctl_stop( 'sbc_cpl_snd: wrong definition of sn_snd_temp%clcat' ) 2148 2142 END SELECT 2149 CASE( 'oce and weighted ice') ; ztmp1(:,:) = ts n(:,:,1,jp_tem) + rt02143 CASE( 'oce and weighted ice') ; ztmp1(:,:) = ts(:,:,1,jp_tem,Kmm) + rt0 2150 2144 SELECT CASE( sn_snd_temp%clcat ) 2151 2145 CASE( 'yes' ) … … 2353 2347 ! ! CO2 flux from PISCES ! 2354 2348 ! ! ------------------------- ! 2355 IF( ssnd(jps_co2)%laction .AND. l_co2cpl ) THEN 2356 ztmp1(:,:) = oce_co2(:,:) * 1000. ! conversion in molC/m2/s 2357 CALL cpl_snd( jps_co2, isec, RESHAPE ( ztmp1, (/jpi,jpj,1/) ) , info ) 2358 ENDIF 2349 IF( ssnd(jps_co2)%laction .AND. l_co2cpl ) THEN 2350 ztmp1(:,:) = oce_co2(:,:) * 1000. ! conversion in molC/m2/s 2351 CALL cpl_snd( jps_co2, isec, RESHAPE ( ztmp1, (/jpi,jpj,1/) ) , info ) 2352 ENDIF 2359 2353 ! 2360 2354 ! ! ------------------------- ! … … 2371 2365 ! i i+1 (for I) 2372 2366 IF( nn_components == jp_iam_opa ) THEN 2373 zotx1(:,:) = u n(:,:,1)2374 zoty1(:,:) = v n(:,:,1)2367 zotx1(:,:) = uu(:,:,1,Kmm) 2368 zoty1(:,:) = vv(:,:,1,Kmm) 2375 2369 ELSE 2376 2370 SELECT CASE( TRIM( sn_snd_crt%cldes ) ) 2377 2371 CASE( 'oce only' ) ! C-grid ==> T 2378 DO jj = 2, jpjm1 2379 DO ji = fs_2, fs_jpim1 ! vector opt. 2380 zotx1(ji,jj) = 0.5 * ( un(ji,jj,1) + un(ji-1,jj ,1) ) 2381 zoty1(ji,jj) = 0.5 * ( vn(ji,jj,1) + vn(ji ,jj-1,1) ) 2382 END DO 2383 END DO 2372 DO_2D_00_00 2373 zotx1(ji,jj) = 0.5 * ( uu(ji,jj,1,Kmm) + uu(ji-1,jj ,1,Kmm) ) 2374 zoty1(ji,jj) = 0.5 * ( vv(ji,jj,1,Kmm) + vv(ji ,jj-1,1,Kmm) ) 2375 END_2D 2384 2376 CASE( 'weighted oce and ice' ) ! Ocean and Ice on C-grid ==> T 2385 DO jj = 2, jpjm1 2386 DO ji = fs_2, fs_jpim1 ! vector opt. 2387 zotx1(ji,jj) = 0.5 * ( un (ji,jj,1) + un (ji-1,jj ,1) ) * zfr_l(ji,jj) 2388 zoty1(ji,jj) = 0.5 * ( vn (ji,jj,1) + vn (ji ,jj-1,1) ) * zfr_l(ji,jj) 2389 zitx1(ji,jj) = 0.5 * ( u_ice(ji,jj ) + u_ice(ji-1,jj ) ) * fr_i(ji,jj) 2390 zity1(ji,jj) = 0.5 * ( v_ice(ji,jj ) + v_ice(ji ,jj-1 ) ) * fr_i(ji,jj) 2391 END DO 2392 END DO 2377 DO_2D_00_00 2378 zotx1(ji,jj) = 0.5 * ( uu (ji,jj,1,Kmm) + uu (ji-1,jj ,1,Kmm) ) * zfr_l(ji,jj) 2379 zoty1(ji,jj) = 0.5 * ( vv (ji,jj,1,Kmm) + vv (ji ,jj-1,1,Kmm) ) * zfr_l(ji,jj) 2380 zitx1(ji,jj) = 0.5 * ( u_ice(ji,jj ) + u_ice(ji-1,jj ) ) * fr_i(ji,jj) 2381 zity1(ji,jj) = 0.5 * ( v_ice(ji,jj ) + v_ice(ji ,jj-1 ) ) * fr_i(ji,jj) 2382 END_2D 2393 2383 CALL lbc_lnk_multi( 'sbccpl', zitx1, 'T', -1., zity1, 'T', -1. ) 2394 2384 CASE( 'mixed oce-ice' ) ! Ocean and Ice on C-grid ==> T 2395 DO jj = 2, jpjm1 2396 DO ji = fs_2, fs_jpim1 ! vector opt. 2397 zotx1(ji,jj) = 0.5 * ( un (ji,jj,1) + un (ji-1,jj ,1) ) * zfr_l(ji,jj) & 2398 & + 0.5 * ( u_ice(ji,jj ) + u_ice(ji-1,jj ) ) * fr_i(ji,jj) 2399 zoty1(ji,jj) = 0.5 * ( vn (ji,jj,1) + vn (ji ,jj-1,1) ) * zfr_l(ji,jj) & 2400 & + 0.5 * ( v_ice(ji,jj ) + v_ice(ji ,jj-1 ) ) * fr_i(ji,jj) 2401 END DO 2402 END DO 2385 DO_2D_00_00 2386 zotx1(ji,jj) = 0.5 * ( uu (ji,jj,1,Kmm) + uu (ji-1,jj ,1,Kmm) ) * zfr_l(ji,jj) & 2387 & + 0.5 * ( u_ice(ji,jj ) + u_ice(ji-1,jj ) ) * fr_i(ji,jj) 2388 zoty1(ji,jj) = 0.5 * ( vv (ji,jj,1,Kmm) + vv (ji ,jj-1,1,Kmm) ) * zfr_l(ji,jj) & 2389 & + 0.5 * ( v_ice(ji,jj ) + v_ice(ji ,jj-1 ) ) * fr_i(ji,jj) 2390 END_2D 2403 2391 END SELECT 2404 2392 CALL lbc_lnk_multi( 'sbccpl', zotx1, ssnd(jps_ocx1)%clgrid, -1., zoty1, ssnd(jps_ocy1)%clgrid, -1. ) … … 2459 2447 SELECT CASE( TRIM( sn_snd_crtw%cldes ) ) 2460 2448 CASE( 'oce only' ) ! C-grid ==> T 2461 DO jj = 2, jpjm1 2462 DO ji = fs_2, fs_jpim1 ! vector opt. 2463 zotx1(ji,jj) = 0.5 * ( un(ji,jj,1) + un(ji-1,jj ,1) ) 2464 zoty1(ji,jj) = 0.5 * ( vn(ji,jj,1) + vn(ji , jj-1,1) ) 2465 END DO 2466 END DO 2449 DO_2D_00_00 2450 zotx1(ji,jj) = 0.5 * ( uu(ji,jj,1,Kmm) + uu(ji-1,jj ,1,Kmm) ) 2451 zoty1(ji,jj) = 0.5 * ( vv(ji,jj,1,Kmm) + vv(ji , jj-1,1,Kmm) ) 2452 END_2D 2467 2453 CASE( 'weighted oce and ice' ) ! Ocean and Ice on C-grid ==> T 2468 DO jj = 2, jpjm1 2469 DO ji = fs_2, fs_jpim1 ! vector opt. 2470 zotx1(ji,jj) = 0.5 * ( un (ji,jj,1) + un (ji-1,jj ,1) ) * zfr_l(ji,jj) 2471 zoty1(ji,jj) = 0.5 * ( vn (ji,jj,1) + vn (ji ,jj-1,1) ) * zfr_l(ji,jj) 2472 zitx1(ji,jj) = 0.5 * ( u_ice(ji,jj ) + u_ice(ji-1,jj ) ) * fr_i(ji,jj) 2473 zity1(ji,jj) = 0.5 * ( v_ice(ji,jj ) + v_ice(ji ,jj-1 ) ) * fr_i(ji,jj) 2474 END DO 2475 END DO 2454 DO_2D_00_00 2455 zotx1(ji,jj) = 0.5 * ( uu (ji,jj,1,Kmm) + uu (ji-1,jj ,1,Kmm) ) * zfr_l(ji,jj) 2456 zoty1(ji,jj) = 0.5 * ( vv (ji,jj,1,Kmm) + vv (ji ,jj-1,1,Kmm) ) * zfr_l(ji,jj) 2457 zitx1(ji,jj) = 0.5 * ( u_ice(ji,jj ) + u_ice(ji-1,jj ) ) * fr_i(ji,jj) 2458 zity1(ji,jj) = 0.5 * ( v_ice(ji,jj ) + v_ice(ji ,jj-1 ) ) * fr_i(ji,jj) 2459 END_2D 2476 2460 CALL lbc_lnk_multi( 'sbccpl', zitx1, 'T', -1., zity1, 'T', -1. ) 2477 2461 CASE( 'mixed oce-ice' ) ! Ocean and Ice on C-grid ==> T 2478 DO jj = 2, jpjm1 2479 DO ji = fs_2, fs_jpim1 ! vector opt. 2480 zotx1(ji,jj) = 0.5 * ( un (ji,jj,1) + un (ji-1,jj ,1) ) * zfr_l(ji,jj) & 2481 & + 0.5 * ( u_ice(ji,jj ) + u_ice(ji-1,jj ) ) * fr_i(ji,jj) 2482 zoty1(ji,jj) = 0.5 * ( vn (ji,jj,1) + vn (ji ,jj-1,1) ) * zfr_l(ji,jj) & 2483 & + 0.5 * ( v_ice(ji,jj ) + v_ice(ji ,jj-1 ) ) * fr_i(ji,jj) 2484 END DO 2485 END DO 2462 DO_2D_00_00 2463 zotx1(ji,jj) = 0.5 * ( uu (ji,jj,1,Kmm) + uu (ji-1,jj ,1,Kmm) ) * zfr_l(ji,jj) & 2464 & + 0.5 * ( u_ice(ji,jj ) + u_ice(ji-1,jj ) ) * fr_i(ji,jj) 2465 zoty1(ji,jj) = 0.5 * ( vv (ji,jj,1,Kmm) + vv (ji ,jj-1,1,Kmm) ) * zfr_l(ji,jj) & 2466 & + 0.5 * ( v_ice(ji,jj ) + v_ice(ji ,jj-1 ) ) * fr_i(ji,jj) 2467 END_2D 2486 2468 END SELECT 2487 2469 CALL lbc_lnk_multi( 'sbccpl', zotx1, ssnd(jps_ocxw)%clgrid, -1., zoty1, ssnd(jps_ocyw)%clgrid, -1. ) … … 2522 2504 IF( ssnd(jps_ficet)%laction ) THEN 2523 2505 CALL cpl_snd( jps_ficet, isec, RESHAPE ( fr_i, (/jpi,jpj,1/) ), info ) 2524 END 2506 ENDIF 2525 2507 ! ! ------------------------- ! 2526 2508 ! ! Water levels to waves ! … … 2529 2511 IF( ln_apr_dyn ) THEN 2530 2512 IF( kt /= nit000 ) THEN 2531 ztmp1(:,:) = ssh b(:,:) - 0.5 * ( ssh_ib(:,:) + ssh_ibb(:,:) )2513 ztmp1(:,:) = ssh(:,:,Kbb) - 0.5 * ( ssh_ib(:,:) + ssh_ibb(:,:) ) 2532 2514 ELSE 2533 ztmp1(:,:) = ssh b(:,:)2515 ztmp1(:,:) = ssh(:,:,Kbb) 2534 2516 ENDIF 2535 2517 ELSE 2536 ztmp1(:,:) = ssh n(:,:)2518 ztmp1(:,:) = ssh(:,:,Kmm) 2537 2519 ENDIF 2538 2520 CALL cpl_snd( jps_wlev , isec, RESHAPE ( ztmp1, (/jpi,jpj,1/) ), info ) 2539 END 2521 ENDIF 2540 2522 ! 2541 2523 ! Fields sent by OPA to SAS when doing OPA<->SAS coupling … … 2544 2526 ! ! removed inverse barometer ssh when Patm 2545 2527 ! forcing is used (for sea-ice dynamics) 2546 IF( ln_apr_dyn ) THEN ; ztmp1(:,:) = ssh b(:,:) - 0.5 * ( ssh_ib(:,:) + ssh_ibb(:,:) )2547 ELSE ; ztmp1(:,:) = ssh n(:,:)2528 IF( ln_apr_dyn ) THEN ; ztmp1(:,:) = ssh(:,:,Kbb) - 0.5 * ( ssh_ib(:,:) + ssh_ibb(:,:) ) 2529 ELSE ; ztmp1(:,:) = ssh(:,:,Kmm) 2548 2530 ENDIF 2549 2531 CALL cpl_snd( jps_ssh , isec, RESHAPE ( ztmp1 , (/jpi,jpj,1/) ), info ) … … 2552 2534 ! ! SSS 2553 2535 IF( ssnd(jps_soce )%laction ) THEN 2554 CALL cpl_snd( jps_soce , isec, RESHAPE ( ts n(:,:,1,jp_sal), (/jpi,jpj,1/) ), info )2536 CALL cpl_snd( jps_soce , isec, RESHAPE ( ts(:,:,1,jp_sal,Kmm), (/jpi,jpj,1/) ), info ) 2555 2537 ENDIF 2556 2538 ! ! first T level thickness 2557 2539 IF( ssnd(jps_e3t1st )%laction ) THEN 2558 CALL cpl_snd( jps_e3t1st, isec, RESHAPE ( e3t _n(:,:,1) , (/jpi,jpj,1/) ), info )2540 CALL cpl_snd( jps_e3t1st, isec, RESHAPE ( e3t(:,:,1,Kmm) , (/jpi,jpj,1/) ), info ) 2559 2541 ENDIF 2560 2542 ! ! Qsr fraction … … 2579 2561 ! ! ------------------------- ! 2580 2562 ! needed by Met Office 2581 CALL eos_fzp(ts n(:,:,1,jp_sal), sstfrz)2563 CALL eos_fzp(ts(:,:,1,jp_sal,Kmm), sstfrz) 2582 2564 ztmp1(:,:) = sstfrz(:,:) + rt0 2583 2565 IF( ssnd(jps_sstfrz)%laction ) CALL cpl_snd( jps_sstfrz, isec, RESHAPE ( ztmp1, (/jpi,jpj,1/) ), info) -
NEMO/trunk/src/OCE/SBC/sbcdcy.F90
r10425 r12377 7 7 !! NEMO 2.0 ! 2006-02 (S. Masson, G. Madec) adaptation to NEMO 8 8 !! 3.1 ! 2009-07 (J.M. Molines) adaptation to v3.1 9 !! 4.* ! 2019-10 (L. Brodeau) nothing really new, but the routine 10 !! ! "sbc_dcy_param" has been extracted from old function "sbc_dcy" 11 !! ! => this allows the warm-layer param of COARE3* to know the time 12 !! ! of dawn and dusk even if "ln_dm2dc=.false." (rdawn_dcy & rdusk_dcy 13 !! ! are now public) 9 14 !!---------------------------------------------------------------------- 10 15 … … 22 27 IMPLICIT NONE 23 28 PRIVATE 24 29 25 30 INTEGER, PUBLIC :: nday_qsr !: day when parameters were computed 26 31 27 32 REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: raa , rbb , rcc , rab ! diurnal cycle parameters 28 REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: rtmd, rdawn, rdusk, rscal ! - - - 29 33 REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: rtmd, rscal ! - - - 34 REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:), PUBLIC :: rdawn_dcy, rdusk_dcy ! - - - 35 30 36 PUBLIC sbc_dcy ! routine called by sbc 31 37 PUBLIC sbc_dcy_param ! routine used here and called by warm-layer parameterization (sbcblk_skin_coare*) 38 39 !! * Substitutions 40 # include "do_loop_substitute.h90" 32 41 !!---------------------------------------------------------------------- 33 42 !! NEMO/OCE 4.0 , NEMO Consortium (2018) 34 !! $Id$ 43 !! $Id$ 35 44 !! Software governed by the CeCILL license (see ./LICENSE) 36 45 !!---------------------------------------------------------------------- 37 46 CONTAINS 38 47 39 40 41 42 43 44 & rtmd(jpi,jpj) , rdawn(jpi,jpj) , rdusk(jpi,jpj) , rscal(jpi,jpj) , STAT=sbc_dcy_alloc )45 46 47 48 48 INTEGER FUNCTION sbc_dcy_alloc() 49 !!---------------------------------------------------------------------- 50 !! *** FUNCTION sbc_dcy_alloc *** 51 !!---------------------------------------------------------------------- 52 ALLOCATE( raa (jpi,jpj) , rbb (jpi,jpj) , rcc (jpi,jpj) , rab (jpi,jpj) , & 53 & rtmd(jpi,jpj) , rdawn_dcy(jpi,jpj) , rdusk_dcy(jpi,jpj) , rscal(jpi,jpj) , STAT=sbc_dcy_alloc ) 54 ! 55 CALL mpp_sum ( 'sbcdcy', sbc_dcy_alloc ) 56 IF( sbc_dcy_alloc /= 0 ) CALL ctl_stop( 'STOP', 'sbc_dcy_alloc: failed to allocate arrays' ) 57 END FUNCTION sbc_dcy_alloc 49 58 50 59 … … 60 69 !! 61 70 !! reference : Bernie, DJ, E Guilyardi, G Madec, JM Slingo, and SJ Woolnough, 2007 62 !! Impact of resolving the diurnal cycle in an ocean--atmosphere GCM. 71 !! Impact of resolving the diurnal cycle in an ocean--atmosphere GCM. 63 72 !! Part 1: a diurnally forced OGCM. Climate Dynamics 29:6, 575-590. 64 73 !!---------------------------------------------------------------------- 65 74 LOGICAL , OPTIONAL , INTENT(in) :: l_mask ! use the routine for night mask computation 66 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pqsrin ! input daily QSR flux 75 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pqsrin ! input daily QSR flux 67 76 REAL(wp), DIMENSION(jpi,jpj) :: zqsrout ! output QSR flux with diurnal cycle 68 77 !! 69 78 INTEGER :: ji, jj ! dummy loop indices 70 79 INTEGER, DIMENSION(jpi,jpj) :: imask_night ! night mask 71 REAL(wp) :: ztwopi, zinvtwopi, zconvrad72 80 REAL(wp) :: zlo, zup, zlousd, zupusd 73 REAL(wp) :: zdsws, zdecrad, ztx, zsin, zcos 74 REAL(wp) :: ztmp, ztmp1, ztmp2, ztest 81 REAL(wp) :: ztmp, ztmp1, ztmp2 75 82 REAL(wp) :: ztmpm, ztmpm1, ztmpm2 76 !---------------------------statement functions------------------------77 REAL(wp) :: fintegral, pt1, pt2, paaa, pbbb, pccc ! dummy statement function arguments78 fintegral( pt1, pt2, paaa, pbbb, pccc ) = &79 & paaa * pt2 + zinvtwopi * pbbb * SIN(pccc + ztwopi * pt2) &80 & - paaa * pt1 - zinvtwopi * pbbb * SIN(pccc + ztwopi * pt1)81 83 !!--------------------------------------------------------------------- 82 84 ! 83 85 ! Initialization 84 86 ! -------------- 85 ztwopi = 2._wp * rpi86 zinvtwopi = 1._wp / ztwopi87 zconvrad = ztwopi / 360._wp88 89 87 ! When are we during the day (from 0 to 1) 90 88 zlo = ( REAL(nsec_day, wp) - 0.5_wp * rdt ) / rday 91 89 zup = zlo + ( REAL(nn_fsbc, wp) * rdt ) / rday 92 ! 93 IF( nday_qsr == -1 ) THEN ! first time step only 90 ! 91 IF( nday_qsr == -1 ) THEN ! first time step only 94 92 IF(lwp) THEN 95 93 WRITE(numout,*) … … 98 96 WRITE(numout,*) 99 97 ENDIF 98 ENDIF 99 100 ! Setting parameters for each new day: 101 CALL sbc_dcy_param() 102 103 !CALL iom_put( "rdusk_dcy", rdusk_dcy(:,:)*tmask(:,:,1) ) !LB 104 !CALL iom_put( "rdawn_dcy", rdawn_dcy(:,:)*tmask(:,:,1) ) !LB 105 !CALL iom_put( "rscal_dcy", rscal(:,:)*tmask(:,:,1) ) !LB 106 107 108 ! 3. update qsr with the diurnal cycle 109 ! ------------------------------------ 110 111 imask_night(:,:) = 0 112 DO_2D_11_11 113 ztmpm = 0._wp 114 IF( ABS(rab(ji,jj)) < 1. ) THEN ! day duration is less than 24h 115 ! 116 IF( rdawn_dcy(ji,jj) < rdusk_dcy(ji,jj) ) THEN ! day time in one part 117 zlousd = MAX(zlo, rdawn_dcy(ji,jj)) 118 zlousd = MIN(zlousd, zup) 119 zupusd = MIN(zup, rdusk_dcy(ji,jj)) 120 zupusd = MAX(zupusd, zlo) 121 ztmp = fintegral(zlousd, zupusd, raa(ji,jj), rbb(ji,jj), rcc(ji,jj)) 122 zqsrout(ji,jj) = pqsrin(ji,jj) * ztmp * rscal(ji,jj) 123 ztmpm = zupusd - zlousd 124 IF( ztmpm .EQ. 0 ) imask_night(ji,jj) = 1 125 ! 126 ELSE ! day time in two parts 127 zlousd = MIN(zlo, rdusk_dcy(ji,jj)) 128 zupusd = MIN(zup, rdusk_dcy(ji,jj)) 129 ztmp1 = fintegral(zlousd, zupusd, raa(ji,jj), rbb(ji,jj), rcc(ji,jj)) 130 ztmpm1=zupusd-zlousd 131 zlousd = MAX(zlo, rdawn_dcy(ji,jj)) 132 zupusd = MAX(zup, rdawn_dcy(ji,jj)) 133 ztmp2 = fintegral(zlousd, zupusd, raa(ji,jj), rbb(ji,jj), rcc(ji,jj)) 134 ztmpm2 =zupusd-zlousd 135 ztmp = ztmp1 + ztmp2 136 ztmpm = ztmpm1 + ztmpm2 137 zqsrout(ji,jj) = pqsrin(ji,jj) * ztmp * rscal(ji,jj) 138 IF(ztmpm .EQ. 0.) imask_night(ji,jj) = 1 139 ENDIF 140 ELSE ! 24h light or 24h night 141 ! 142 IF( raa(ji,jj) > rbb(ji,jj) ) THEN ! 24h day 143 ztmp = fintegral(zlo, zup, raa(ji,jj), rbb(ji,jj), rcc(ji,jj)) 144 zqsrout(ji,jj) = pqsrin(ji,jj) * ztmp * rscal(ji,jj) 145 imask_night(ji,jj) = 0 146 ! 147 ELSE ! No day 148 zqsrout(ji,jj) = 0.0_wp 149 imask_night(ji,jj) = 1 150 ENDIF 151 ENDIF 152 END_2D 153 ! 154 IF( PRESENT(l_mask) .AND. l_mask ) THEN 155 zqsrout(:,:) = float(imask_night(:,:)) 156 ENDIF 157 ! 158 END FUNCTION sbc_dcy 159 160 161 SUBROUTINE sbc_dcy_param( ) 162 !! 163 INTEGER :: ji, jj ! dummy loop indices 164 !INTEGER, DIMENSION(jpi,jpj) :: imask_night ! night mask 165 REAL(wp) :: zdsws, zdecrad, ztx, zsin, zcos 166 REAL(wp) :: ztmp, ztest 167 !---------------------------statement functions------------------------ 168 ! 169 IF( nday_qsr == -1 ) THEN ! first time step only 100 170 ! allocate sbcdcy arrays 101 171 IF( sbc_dcy_alloc() /= 0 ) CALL ctl_stop( 'STOP', 'sbc_dcy_alloc : unable to allocate arrays' ) 102 172 ! Compute rcc needed to compute the time integral of the diurnal cycle 103 rcc(:,:) = zconvrad * glamt(:,:) - rpi173 rcc(:,:) = rad * glamt(:,:) - rpi 104 174 ! time of midday 105 175 rtmd(:,:) = 0.5_wp - glamt(:,:) / 360._wp … … 107 177 ENDIF 108 178 109 ! If this is a new day, we have to update the dawn, dusk and scaling function 179 ! If this is a new day, we have to update the dawn, dusk and scaling function 110 180 !---------------------- 111 112 ! 2.1 dawn and dusk 113 114 ! nday is the number of days since the beginning of the current month 115 IF( nday_qsr /= nday ) THEN 181 182 ! 2.1 dawn and dusk 183 184 ! nday is the number of days since the beginning of the current month 185 IF( nday_qsr /= nday ) THEN 116 186 ! save the day of the year and the daily mean of qsr 117 nday_qsr = nday 118 ! number of days since the previous winter solstice (supposed to be always 21 December) 187 nday_qsr = nday 188 ! number of days since the previous winter solstice (supposed to be always 21 December) 119 189 zdsws = REAL(11 + nday_year, wp) 120 190 ! declination of the earths orbit 121 zdecrad = (-23.5_wp * zconvrad) * COS( zdsws * ztwopi / REAL(nyear_len(1),wp) )191 zdecrad = (-23.5_wp * rad) * COS( zdsws * 2._wp*rpi / REAL(nyear_len(1),wp) ) 122 192 ! Compute A and B needed to compute the time integral of the diurnal cycle 123 193 124 194 zsin = SIN( zdecrad ) ; zcos = COS( zdecrad ) 125 DO jj = 1, jpj 126 DO ji = 1, jpi 127 ztmp = zconvrad * gphit(ji,jj) 128 raa(ji,jj) = SIN( ztmp ) * zsin 129 rbb(ji,jj) = COS( ztmp ) * zcos 130 END DO 131 END DO 195 DO_2D_11_11 196 ztmp = rad * gphit(ji,jj) 197 raa(ji,jj) = SIN( ztmp ) * zsin 198 rbb(ji,jj) = COS( ztmp ) * zcos 199 END_2D 132 200 ! Compute the time of dawn and dusk 133 201 134 ! rab to test if the day time is equal to 0, less than 24h of full day 202 ! rab to test if the day time is equal to 0, less than 24h of full day 135 203 rab(:,:) = -raa(:,:) / rbb(:,:) 136 DO jj = 1, jpj 137 DO ji = 1, jpi 138 IF ( ABS(rab(ji,jj)) < 1._wp ) THEN ! day duration is less than 24h 139 ! When is it night? 140 ztx = zinvtwopi * (ACOS(rab(ji,jj)) - rcc(ji,jj)) 141 ztest = -rbb(ji,jj) * SIN( rcc(ji,jj) + ztwopi * ztx ) 142 ! is it dawn or dusk? 143 IF ( ztest > 0._wp ) THEN 144 rdawn(ji,jj) = ztx 145 rdusk(ji,jj) = rtmd(ji,jj) + ( rtmd(ji,jj) - rdawn(ji,jj) ) 146 ELSE 147 rdusk(ji,jj) = ztx 148 rdawn(ji,jj) = rtmd(ji,jj) - ( rdusk(ji,jj) - rtmd(ji,jj) ) 149 ENDIF 204 DO_2D_11_11 205 IF( ABS(rab(ji,jj)) < 1._wp ) THEN ! day duration is less than 24h 206 ! When is it night? 207 ztx = 1._wp/(2._wp*rpi) * (ACOS(rab(ji,jj)) - rcc(ji,jj)) 208 ztest = -rbb(ji,jj) * SIN( rcc(ji,jj) + 2._wp*rpi * ztx ) 209 ! is it dawn or dusk? 210 IF( ztest > 0._wp ) THEN 211 rdawn_dcy(ji,jj) = ztx 212 rdusk_dcy(ji,jj) = rtmd(ji,jj) + ( rtmd(ji,jj) - rdawn_dcy(ji,jj) ) 150 213 ELSE 151 rd awn(ji,jj) = rtmd(ji,jj) + 0.5_wp152 rd usk(ji,jj) = rdawn(ji,jj)214 rdusk_dcy(ji,jj) = ztx 215 rdawn_dcy(ji,jj) = rtmd(ji,jj) - ( rdusk_dcy(ji,jj) - rtmd(ji,jj) ) 153 216 ENDIF 154 END DO 155 END DO 156 rdawn(:,:) = MOD( (rdawn(:,:) + 1._wp), 1._wp ) 157 rdusk(:,:) = MOD( (rdusk(:,:) + 1._wp), 1._wp ) 217 ELSE 218 rdawn_dcy(ji,jj) = rtmd(ji,jj) + 0.5_wp 219 rdusk_dcy(ji,jj) = rdawn_dcy(ji,jj) 220 ENDIF 221 END_2D 222 rdawn_dcy(:,:) = MOD( (rdawn_dcy(:,:) + 1._wp), 1._wp ) 223 rdusk_dcy(:,:) = MOD( (rdusk_dcy(:,:) + 1._wp), 1._wp ) 158 224 ! 2.2 Compute the scaling function: 159 225 ! S* = the inverse of the time integral of the diurnal cycle from dawn to dusk 160 226 ! Avoid possible infinite scaling factor, associated with very short daylight 161 227 ! periods, by ignoring periods less than 1/1000th of a day (ticket #1040) 162 DO jj = 1, jpj 163 DO ji = 1, jpi 164 IF ( ABS(rab(ji,jj)) < 1._wp ) THEN ! day duration is less than 24h 165 rscal(ji,jj) = 0.0_wp 166 IF ( rdawn(ji,jj) < rdusk(ji,jj) ) THEN ! day time in one part 167 IF( (rdusk(ji,jj) - rdawn(ji,jj) ) .ge. 0.001_wp ) THEN 168 rscal(ji,jj) = fintegral(rdawn(ji,jj), rdusk(ji,jj), raa(ji,jj), rbb(ji,jj), rcc(ji,jj)) 169 rscal(ji,jj) = 1._wp / rscal(ji,jj) 170 ENDIF 171 ELSE ! day time in two parts 172 IF( (rdusk(ji,jj) + (1._wp - rdawn(ji,jj)) ) .ge. 0.001_wp ) THEN 173 rscal(ji,jj) = fintegral(0._wp, rdusk(ji,jj), raa(ji,jj), rbb(ji,jj), rcc(ji,jj)) & 174 & + fintegral(rdawn(ji,jj), 1._wp, raa(ji,jj), rbb(ji,jj), rcc(ji,jj)) 175 rscal(ji,jj) = 1. / rscal(ji,jj) 176 ENDIF 228 DO_2D_11_11 229 IF( ABS(rab(ji,jj)) < 1._wp ) THEN ! day duration is less than 24h 230 rscal(ji,jj) = 0.0_wp 231 IF( rdawn_dcy(ji,jj) < rdusk_dcy(ji,jj) ) THEN ! day time in one part 232 IF( (rdusk_dcy(ji,jj) - rdawn_dcy(ji,jj) ) .ge. 0.001_wp ) THEN 233 rscal(ji,jj) = fintegral(rdawn_dcy(ji,jj), rdusk_dcy(ji,jj), raa(ji,jj), rbb(ji,jj), rcc(ji,jj)) 234 rscal(ji,jj) = 1._wp / rscal(ji,jj) 177 235 ENDIF 178 ELSE 179 IF ( raa(ji,jj) > rbb(ji,jj) ) THEN ! 24h day 180 rscal(ji,jj) = fintegral(0._wp, 1._wp, raa(ji,jj), rbb(ji,jj), rcc(ji,jj)) 181 rscal(ji,jj) = 1._wp / rscal(ji,jj) 182 ELSE ! No day 183 rscal(ji,jj) = 0.0_wp 236 ELSE ! day time in two parts 237 IF( (rdusk_dcy(ji,jj) + (1._wp - rdawn_dcy(ji,jj)) ) .ge. 0.001_wp ) THEN 238 rscal(ji,jj) = fintegral(0._wp, rdusk_dcy(ji,jj), raa(ji,jj), rbb(ji,jj), rcc(ji,jj)) & 239 & + fintegral(rdawn_dcy(ji,jj), 1._wp, raa(ji,jj), rbb(ji,jj), rcc(ji,jj)) 240 rscal(ji,jj) = 1. / rscal(ji,jj) 184 241 ENDIF 185 242 ENDIF 186 END DO 187 END DO 243 ELSE 244 IF( raa(ji,jj) > rbb(ji,jj) ) THEN ! 24h day 245 rscal(ji,jj) = fintegral(0._wp, 1._wp, raa(ji,jj), rbb(ji,jj), rcc(ji,jj)) 246 rscal(ji,jj) = 1._wp / rscal(ji,jj) 247 ELSE ! No day 248 rscal(ji,jj) = 0.0_wp 249 ENDIF 250 ENDIF 251 END_2D 188 252 ! 189 253 ztmp = rday / ( rdt * REAL(nn_fsbc, wp) ) 190 254 rscal(:,:) = rscal(:,:) * ztmp 191 255 ! 192 ENDIF 193 ! 3. update qsr with the diurnal cycle 194 ! ------------------------------------ 195 196 imask_night(:,:) = 0 197 DO jj = 1, jpj 198 DO ji = 1, jpi 199 ztmpm = 0._wp 200 IF( ABS(rab(ji,jj)) < 1. ) THEN ! day duration is less than 24h 201 ! 202 IF( rdawn(ji,jj) < rdusk(ji,jj) ) THEN ! day time in one part 203 zlousd = MAX(zlo, rdawn(ji,jj)) 204 zlousd = MIN(zlousd, zup) 205 zupusd = MIN(zup, rdusk(ji,jj)) 206 zupusd = MAX(zupusd, zlo) 207 ztmp = fintegral(zlousd, zupusd, raa(ji,jj), rbb(ji,jj), rcc(ji,jj)) 208 zqsrout(ji,jj) = pqsrin(ji,jj) * ztmp * rscal(ji,jj) 209 ztmpm = zupusd - zlousd 210 IF ( ztmpm .EQ. 0 ) imask_night(ji,jj) = 1 211 ! 212 ELSE ! day time in two parts 213 zlousd = MIN(zlo, rdusk(ji,jj)) 214 zupusd = MIN(zup, rdusk(ji,jj)) 215 ztmp1 = fintegral(zlousd, zupusd, raa(ji,jj), rbb(ji,jj), rcc(ji,jj)) 216 ztmpm1=zupusd-zlousd 217 zlousd = MAX(zlo, rdawn(ji,jj)) 218 zupusd = MAX(zup, rdawn(ji,jj)) 219 ztmp2 = fintegral(zlousd, zupusd, raa(ji,jj), rbb(ji,jj), rcc(ji,jj)) 220 ztmpm2 =zupusd-zlousd 221 ztmp = ztmp1 + ztmp2 222 ztmpm = ztmpm1 + ztmpm2 223 zqsrout(ji,jj) = pqsrin(ji,jj) * ztmp * rscal(ji,jj) 224 IF (ztmpm .EQ. 0.) imask_night(ji,jj) = 1 225 ENDIF 226 ELSE ! 24h light or 24h night 227 ! 228 IF( raa(ji,jj) > rbb(ji,jj) ) THEN ! 24h day 229 ztmp = fintegral(zlo, zup, raa(ji,jj), rbb(ji,jj), rcc(ji,jj)) 230 zqsrout(ji,jj) = pqsrin(ji,jj) * ztmp * rscal(ji,jj) 231 imask_night(ji,jj) = 0 232 ! 233 ELSE ! No day 234 zqsrout(ji,jj) = 0.0_wp 235 imask_night(ji,jj) = 1 236 ENDIF 237 ENDIF 238 END DO 239 END DO 240 ! 241 IF( PRESENT(l_mask) .AND. l_mask ) THEN 242 zqsrout(:,:) = float(imask_night(:,:)) 243 ENDIF 244 ! 245 END FUNCTION sbc_dcy 256 ENDIF !IF( nday_qsr /= nday ) 257 ! 258 END SUBROUTINE sbc_dcy_param 259 260 261 FUNCTION fintegral( pt1, pt2, paaa, pbbb, pccc ) 262 REAL(wp), INTENT(in) :: pt1, pt2, paaa, pbbb, pccc 263 REAL(wp) :: fintegral 264 fintegral = paaa * pt2 + 1._wp/(2._wp*rpi) * pbbb * SIN(pccc + 2._wp*rpi*pt2) & 265 & - paaa * pt1 - 1._wp/(2._wp*rpi) * pbbb * SIN(pccc + 2._wp*rpi*pt1) 266 END FUNCTION fintegral 246 267 247 268 !!====================================================================== -
NEMO/trunk/src/OCE/SBC/sbcflx.F90
r11536 r12377 38 38 39 39 !! * Substitutions 40 # include " vectopt_loop_substitute.h90"40 # include "do_loop_substitute.h90" 41 41 !!---------------------------------------------------------------------- 42 42 !! NEMO/OCE 4.0 , NEMO Consortium (2018) … … 91 91 IF( kt == nit000 ) THEN ! First call kt=nit000 92 92 ! set file information 93 REWIND( numnam_ref ) ! Namelist namsbc_flx in reference namelist : Files for fluxes94 93 READ ( numnam_ref, namsbc_flx, IOSTAT = ios, ERR = 901) 95 94 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namsbc_flx in reference namelist' ) 96 95 97 REWIND( numnam_cfg ) ! Namelist namsbc_flx in configuration namelist : Files for fluxes98 96 READ ( numnam_cfg, namsbc_flx, IOSTAT = ios, ERR = 902 ) 99 97 902 IF( ios > 0 ) CALL ctl_nam ( ios , 'namsbc_flx in configuration namelist' ) … … 131 129 ELSE ; qsr(:,:) = sf(jp_qsr)%fnow(:,:,1) 132 130 ENDIF 133 DO jj = 1, jpj ! set the ocean fluxes from read fields 134 DO ji = 1, jpi 135 utau(ji,jj) = sf(jp_utau)%fnow(ji,jj,1) 136 vtau(ji,jj) = sf(jp_vtau)%fnow(ji,jj,1) 137 qns (ji,jj) = sf(jp_qtot)%fnow(ji,jj,1) - sf(jp_qsr)%fnow(ji,jj,1) 138 emp (ji,jj) = sf(jp_emp )%fnow(ji,jj,1) 139 END DO 140 END DO 131 DO_2D_11_11 132 utau(ji,jj) = sf(jp_utau)%fnow(ji,jj,1) 133 vtau(ji,jj) = sf(jp_vtau)%fnow(ji,jj,1) 134 qns (ji,jj) = sf(jp_qtot)%fnow(ji,jj,1) - sf(jp_qsr)%fnow(ji,jj,1) 135 emp (ji,jj) = sf(jp_emp )%fnow(ji,jj,1) 136 END_2D 141 137 ! ! add to qns the heat due to e-p 142 138 qns(:,:) = qns(:,:) - emp(:,:) * sst_m(:,:) * rcp ! mass flux is at SST … … 147 143 ! ! module of wind stress and wind speed at T-point 148 144 zcoef = 1. / ( zrhoa * zcdrag ) 149 DO jj = 2, jpjm1 150 DO ji = fs_2, fs_jpim1 ! vect. opt. 151 ztx = utau(ji-1,jj ) + utau(ji,jj) 152 zty = vtau(ji ,jj-1) + vtau(ji,jj) 153 zmod = 0.5 * SQRT( ztx * ztx + zty * zty ) 154 taum(ji,jj) = zmod 155 wndm(ji,jj) = SQRT( zmod * zcoef ) 156 END DO 157 END DO 145 DO_2D_00_00 146 ztx = utau(ji-1,jj ) + utau(ji,jj) 147 zty = vtau(ji ,jj-1) + vtau(ji,jj) 148 zmod = 0.5 * SQRT( ztx * ztx + zty * zty ) 149 taum(ji,jj) = zmod 150 wndm(ji,jj) = SQRT( zmod * zcoef ) 151 END_2D 158 152 taum(:,:) = taum(:,:) * tmask(:,:,1) ; wndm(:,:) = wndm(:,:) * tmask(:,:,1) 159 153 CALL lbc_lnk( 'sbcflx', taum(:,:), 'T', 1. ) ; CALL lbc_lnk( 'sbcflx', wndm(:,:), 'T', 1. ) -
NEMO/trunk/src/OCE/SBC/sbcfwb.F90
r10570 r12377 17 17 USE dom_oce ! ocean space and time domain 18 18 USE sbc_oce ! surface ocean boundary condition 19 USE isf_oce , ONLY : fwfisf_cav, fwfisf_par ! ice shelf melting contribution 19 20 USE sbc_ice , ONLY : snwice_mass, snwice_mass_b, snwice_fmass 20 21 USE phycst ! physical constants 21 22 USE sbcrnf ! ocean runoffs 22 USE sbcisf ! ice shelf melting contribution23 23 USE sbcssr ! Sea-Surface damping terms 24 24 ! … … 39 39 REAL(wp) :: area ! global mean ocean surface (interior domain) 40 40 41 !! * Substitutions42 # include "vectopt_loop_substitute.h90"43 41 !!---------------------------------------------------------------------- 44 42 !! NEMO/OCE 4.0 , NEMO Consortium (2018) … … 48 46 CONTAINS 49 47 50 SUBROUTINE sbc_fwb( kt, kn_fwb, kn_fsbc )48 SUBROUTINE sbc_fwb( kt, kn_fwb, kn_fsbc, Kmm ) 51 49 !!--------------------------------------------------------------------- 52 50 !! *** ROUTINE sbc_fwb *** … … 65 63 INTEGER, INTENT( in ) :: kn_fsbc ! 66 64 INTEGER, INTENT( in ) :: kn_fwb ! ocean time-step index 65 INTEGER, INTENT( in ) :: Kmm ! ocean time level index 67 66 ! 68 67 INTEGER :: inum, ikty, iyear ! local integers … … 104 103 ! 105 104 IF( MOD( kt-1, kn_fsbc ) == 0 ) THEN 106 y_fwfnow(1) = local_sum( e1e2t(:,:) * ( emp(:,:) - rnf(:,:) + fwfisf (:,:) - snwice_fmass(:,:) ) )105 y_fwfnow(1) = local_sum( e1e2t(:,:) * ( emp(:,:) - rnf(:,:) + fwfisf_cav(:,:) + fwfisf_par(:,:) - snwice_fmass(:,:) ) ) 107 106 CALL mpp_delay_sum( 'sbcfwb', 'fwb', y_fwfnow(:), z_fwfprv(:), kt == nitend - nn_fsbc + 1 ) 108 107 z_fwfprv(1) = z_fwfprv(1) / area … … 131 130 a_fwb_b = a_fwb ! mean sea level taking into account the ice+snow 132 131 ! sum over the global domain 133 a_fwb = glob_sum( 'sbcfwb', e1e2t(:,:) * ( ssh n(:,:) + snwice_mass(:,:) * r1_rau0 ) )132 a_fwb = glob_sum( 'sbcfwb', e1e2t(:,:) * ( ssh(:,:,Kmm) + snwice_mass(:,:) * r1_rau0 ) ) 134 133 a_fwb = a_fwb * 1.e+3 / ( area * rday * 365. ) ! convert in Kg/m3/s = mm/s 135 134 !!gm ! !!bug 365d year … … 159 158 ztmsk_neg(:,:) = tmask_i(:,:) - ztmsk_pos(:,:) 160 159 ! ! fwf global mean (excluding ocean to ice/snow exchanges) 161 z_fwf = glob_sum( 'sbcfwb', e1e2t(:,:) * ( emp(:,:) - rnf(:,:) + fwfisf (:,:) - snwice_fmass(:,:) ) ) / area160 z_fwf = glob_sum( 'sbcfwb', e1e2t(:,:) * ( emp(:,:) - rnf(:,:) + fwfisf_cav(:,:) + fwfisf_par(:,:) - snwice_fmass(:,:) ) ) / area 162 161 ! 163 162 IF( z_fwf < 0._wp ) THEN ! spread out over >0 erp area to increase evaporation -
NEMO/trunk/src/OCE/SBC/sbcice_cice.F90
r11536 r12377 88 88 REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:), PRIVATE :: png ! local array used in sbc_cice_ice 89 89 90 !! * Substitutions 91 # include "do_loop_substitute.h90" 90 92 !!---------------------------------------------------------------------- 91 93 !! NEMO/OCE 4.0 , NEMO Consortium (2018) … … 132 134 IF ( ksbc == jp_flx ) THEN 133 135 CALL cice_sbc_force(kt) 134 ELSE IF 136 ELSE IF( ksbc == jp_purecpl ) THEN 135 137 CALL sbc_cpl_ice_flx( fr_i ) 136 138 ENDIF … … 140 142 CALL cice_sbc_out ( kt, ksbc ) 141 143 142 IF 144 IF( ksbc == jp_purecpl ) CALL cice_sbc_hadgam(kt+1) 143 145 144 146 ENDIF ! End sea-ice time step only … … 147 149 148 150 149 SUBROUTINE cice_sbc_init( ksbc )151 SUBROUTINE cice_sbc_init( ksbc, Kbb, Kmm ) 150 152 !!--------------------------------------------------------------------- 151 153 !! *** ROUTINE cice_sbc_init *** … … 154 156 !!--------------------------------------------------------------------- 155 157 INTEGER, INTENT( in ) :: ksbc ! surface forcing type 158 INTEGER, INTENT( in ) :: Kbb, Kmm ! time level indices 156 159 REAL(wp), DIMENSION(jpi,jpj) :: ztmp1, ztmp2 157 160 REAL(wp) :: zcoefu, zcoefv, zcoeff ! local scalar … … 168 171 ! there is no restart file. 169 172 ! Values from a CICE restart file would overwrite this 170 IF 171 CALL nemo2cice( ts n(:,:,1,jp_tem) , sst , 'T' , 1.)173 IF( .NOT. ln_rstart ) THEN 174 CALL nemo2cice( ts(:,:,1,jp_tem,Kmm) , sst , 'T' , 1.) 172 175 ENDIF 173 176 #endif … … 177 180 178 181 ! Do some CICE consistency checks 179 IF 180 IF 182 IF( (ksbc == jp_flx) .OR. (ksbc == jp_purecpl) ) THEN 183 IF( calc_strair .OR. calc_Tsfc ) THEN 181 184 CALL ctl_stop( 'STOP', 'cice_sbc_init : Forcing option requires calc_strair=F and calc_Tsfc=F in ice_in' ) 182 185 ENDIF 183 ELSEIF 184 IF 186 ELSEIF(ksbc == jp_blk) THEN 187 IF( .NOT. (calc_strair .AND. calc_Tsfc) ) THEN 185 188 CALL ctl_stop( 'STOP', 'cice_sbc_init : Forcing option requires calc_strair=T and calc_Tsfc=T in ice_in' ) 186 189 ENDIF … … 194 197 ! Ensure ocean temperatures are nowhere below freezing if not a NEMO restart 195 198 IF( .NOT. ln_rstart ) THEN 196 ts n(:,:,:,jp_tem) = MAX (tsn(:,:,:,jp_tem),Tocnfrz)197 ts b(:,:,:,jp_tem) = tsn(:,:,:,jp_tem)199 ts(:,:,:,jp_tem,Kmm) = MAX (ts(:,:,:,jp_tem,Kmm),Tocnfrz) 200 ts(:,:,:,jp_tem,Kbb) = ts(:,:,:,jp_tem,Kmm) 198 201 ENDIF 199 202 … … 202 205 203 206 CALL cice2nemo(aice,fr_i, 'T', 1. ) 204 IF 207 IF( (ksbc == jp_flx) .OR. (ksbc == jp_purecpl) ) THEN 205 208 DO jl=1,ncat 206 209 CALL cice2nemo(aicen(:,:,jl,:),a_i(:,:,jl), 'T', 1. ) … … 210 213 ! T point to U point 211 214 ! T point to V point 212 DO jj=1,jpjm1 213 DO ji=1,jpim1 214 fr_iu(ji,jj)=0.5*(fr_i(ji,jj)+fr_i(ji+1,jj))*umask(ji,jj,1) 215 fr_iv(ji,jj)=0.5*(fr_i(ji,jj)+fr_i(ji,jj+1))*vmask(ji,jj,1) 216 ENDDO 217 ENDDO 215 DO_2D_10_10 216 fr_iu(ji,jj)=0.5*(fr_i(ji,jj)+fr_i(ji+1,jj))*umask(ji,jj,1) 217 fr_iv(ji,jj)=0.5*(fr_i(ji,jj)+fr_i(ji,jj+1))*vmask(ji,jj,1) 218 END_2D 218 219 219 220 CALL lbc_lnk_multi( 'sbcice_cice', fr_iu , 'U', 1., fr_iv , 'V', 1. ) … … 227 228 IF( .NOT.ln_rstart ) THEN 228 229 IF( ln_ice_embd ) THEN ! embedded sea-ice: deplete the initial ssh below sea-ice area 229 ssh n(:,:) = sshn(:,:) - snwice_mass(:,:) * r1_rau0230 ssh b(:,:) = sshb(:,:) - snwice_mass(:,:) * r1_rau0230 ssh(:,:,Kmm) = ssh(:,:,Kmm) - snwice_mass(:,:) * r1_rau0 231 ssh(:,:,Kbb) = ssh(:,:,Kbb) - snwice_mass(:,:) * r1_rau0 231 232 232 233 !!gm This should be put elsewhere.... (same remark for limsbc) … … 235 236 ! 236 237 DO jk = 1,jpkm1 ! adjust initial vertical scale factors 237 e3t _n(:,:,jk) = e3t_0(:,:,jk)*( 1._wp + sshn(:,:)*tmask(:,:,1)/(ht_0(:,:) + 1.0 - tmask(:,:,1)) )238 e3t _b(:,:,jk) = e3t_0(:,:,jk)*( 1._wp + sshb(:,:)*tmask(:,:,1)/(ht_0(:,:) + 1.0 - tmask(:,:,1)) )238 e3t(:,:,jk,Kmm) = e3t_0(:,:,jk)*( 1._wp + ssh(:,:,Kmm)*tmask(:,:,1)/(ht_0(:,:) + 1.0 - tmask(:,:,1)) ) 239 e3t(:,:,jk,Kbb) = e3t_0(:,:,jk)*( 1._wp + ssh(:,:,Kbb)*tmask(:,:,1)/(ht_0(:,:) + 1.0 - tmask(:,:,1)) ) 239 240 ENDDO 240 e3t _a(:,:,:) = e3t_b(:,:,:)241 e3t(:,:,:,Krhs) = e3t(:,:,:,Kbb) 241 242 ! Reconstruction of all vertical scale factors at now and before time-steps 242 243 ! ============================================================================= 243 244 ! Horizontal scale factor interpolations 244 245 ! -------------------------------------- 245 CALL dom_vvl_interpol( e3t _b(:,:,:), e3u_b(:,:,:), 'U' )246 CALL dom_vvl_interpol( e3t _b(:,:,:), e3v_b(:,:,:), 'V' )247 CALL dom_vvl_interpol( e3t _n(:,:,:), e3u_n(:,:,:), 'U' )248 CALL dom_vvl_interpol( e3t _n(:,:,:), e3v_n(:,:,:), 'V' )249 CALL dom_vvl_interpol( e3u _n(:,:,:), e3f_n(:,:,:), 'F' )246 CALL dom_vvl_interpol( e3t(:,:,:,Kbb), e3u(:,:,:,Kbb), 'U' ) 247 CALL dom_vvl_interpol( e3t(:,:,:,Kbb), e3v(:,:,:,Kbb), 'V' ) 248 CALL dom_vvl_interpol( e3t(:,:,:,Kmm), e3u(:,:,:,Kmm), 'U' ) 249 CALL dom_vvl_interpol( e3t(:,:,:,Kmm), e3v(:,:,:,Kmm), 'V' ) 250 CALL dom_vvl_interpol( e3u(:,:,:,Kmm), e3f(:,:,:), 'F' ) 250 251 ! Vertical scale factor interpolations 251 252 ! ------------------------------------ 252 CALL dom_vvl_interpol( e3t _n(:,:,:), e3w_n (:,:,:), 'W' )253 CALL dom_vvl_interpol( e3u _n(:,:,:), e3uw_n(:,:,:), 'UW' )254 CALL dom_vvl_interpol( e3v _n(:,:,:), e3vw_n(:,:,:), 'VW' )255 CALL dom_vvl_interpol( e3u _b(:,:,:), e3uw_b(:,:,:), 'UW' )256 CALL dom_vvl_interpol( e3v _b(:,:,:), e3vw_b(:,:,:), 'VW' )253 CALL dom_vvl_interpol( e3t(:,:,:,Kmm), e3w (:,:,:,Kmm), 'W' ) 254 CALL dom_vvl_interpol( e3u(:,:,:,Kmm), e3uw(:,:,:,Kmm), 'UW' ) 255 CALL dom_vvl_interpol( e3v(:,:,:,Kmm), e3vw(:,:,:,Kmm), 'VW' ) 256 CALL dom_vvl_interpol( e3u(:,:,:,Kbb), e3uw(:,:,:,Kbb), 'UW' ) 257 CALL dom_vvl_interpol( e3v(:,:,:,Kbb), e3vw(:,:,:,Kbb), 'VW' ) 257 258 ! t- and w- points depth 258 259 ! ---------------------- 259 gdept _n(:,:,1) = 0.5_wp * e3w_n(:,:,1)260 gdepw _n(:,:,1) = 0.0_wp261 gde3w _n(:,:,1) = gdept_n(:,:,1) - sshn(:,:)260 gdept(:,:,1,Kmm) = 0.5_wp * e3w(:,:,1,Kmm) 261 gdepw(:,:,1,Kmm) = 0.0_wp 262 gde3w(:,:,1) = gdept(:,:,1,Kmm) - ssh(:,:,Kmm) 262 263 DO jk = 2, jpk 263 gdept _n(:,:,jk) = gdept_n(:,:,jk-1) + e3w_n(:,:,jk)264 gdepw _n(:,:,jk) = gdepw_n(:,:,jk-1) + e3t_n(:,:,jk-1)265 gde3w _n(:,:,jk) = gdept_n(:,:,jk) - sshn (:,:)264 gdept(:,:,jk,Kmm) = gdept(:,:,jk-1,Kmm) + e3w(:,:,jk,Kmm) 265 gdepw(:,:,jk,Kmm) = gdepw(:,:,jk-1,Kmm) + e3t(:,:,jk-1,Kmm) 266 gde3w(:,:,jk) = gdept(:,:,jk ,Kmm) - sshn (:,:) 266 267 END DO 267 268 ENDIF … … 297 298 ! forced and coupled case 298 299 299 IF 300 IF( (ksbc == jp_flx).OR.(ksbc == jp_purecpl) ) THEN 300 301 301 302 ztmpn(:,:,:)=0.0 … … 303 304 ! x comp of wind stress (CI_1) 304 305 ! U point to F point 305 DO jj=1,jpjm1 306 DO ji=1,jpi 307 ztmp(ji,jj) = 0.5 * ( fr_iu(ji,jj) * utau(ji,jj) & 308 + fr_iu(ji,jj+1) * utau(ji,jj+1) ) * fmask(ji,jj,1) 309 ENDDO 310 ENDDO 306 DO_2D_10_11 307 ztmp(ji,jj) = 0.5 * ( fr_iu(ji,jj) * utau(ji,jj) & 308 + fr_iu(ji,jj+1) * utau(ji,jj+1) ) * fmask(ji,jj,1) 309 END_2D 311 310 CALL nemo2cice(ztmp,strax,'F', -1. ) 312 311 313 312 ! y comp of wind stress (CI_2) 314 313 ! V point to F point 315 DO jj=1,jpj 316 DO ji=1,jpim1 317 ztmp(ji,jj) = 0.5 * ( fr_iv(ji,jj) * vtau(ji,jj) & 318 + fr_iv(ji+1,jj) * vtau(ji+1,jj) ) * fmask(ji,jj,1) 319 ENDDO 320 ENDDO 314 DO_2D_11_10 315 ztmp(ji,jj) = 0.5 * ( fr_iv(ji,jj) * vtau(ji,jj) & 316 + fr_iv(ji+1,jj) * vtau(ji+1,jj) ) * fmask(ji,jj,1) 317 END_2D 321 318 CALL nemo2cice(ztmp,stray,'F', -1. ) 322 319 323 320 ! Surface downward latent heat flux (CI_5) 324 IF 321 IF(ksbc == jp_flx) THEN 325 322 DO jl=1,ncat 326 323 ztmpn(:,:,jl)=qla_ice(:,:,1)*a_i(:,:,jl) … … 330 327 qla_ice(:,:,1)= - ( emp_ice(:,:)+sprecip(:,:) ) * rLsub 331 328 ! End of temporary code 332 DO jj=1,jpj 333 DO ji=1,jpi 334 IF (fr_i(ji,jj).eq.0.0) THEN 335 DO jl=1,ncat 336 ztmpn(ji,jj,jl)=0.0 337 ENDDO 338 ! This will then be conserved in CICE 339 ztmpn(ji,jj,1)=qla_ice(ji,jj,1) 340 ELSE 341 DO jl=1,ncat 342 ztmpn(ji,jj,jl)=qla_ice(ji,jj,1)*a_i(ji,jj,jl)/fr_i(ji,jj) 343 ENDDO 344 ENDIF 345 ENDDO 346 ENDDO 329 DO_2D_11_11 330 IF(fr_i(ji,jj).eq.0.0) THEN 331 DO jl=1,ncat 332 ztmpn(ji,jj,jl)=0.0 333 ENDDO 334 ! This will then be conserved in CICE 335 ztmpn(ji,jj,1)=qla_ice(ji,jj,1) 336 ELSE 337 DO jl=1,ncat 338 ztmpn(ji,jj,jl)=qla_ice(ji,jj,1)*a_i(ji,jj,jl)/fr_i(ji,jj) 339 ENDDO 340 ENDIF 341 END_2D 347 342 ENDIF 348 343 DO jl=1,ncat … … 351 346 ! GBM conductive flux through ice (CI_6) 352 347 ! Convert to GBM 353 IF 348 IF(ksbc == jp_flx) THEN 354 349 ztmp(:,:) = botmelt(:,:,jl)*a_i(:,:,jl) 355 350 ELSE … … 360 355 ! GBM surface heat flux (CI_7) 361 356 ! Convert to GBM 362 IF 357 IF(ksbc == jp_flx) THEN 363 358 ztmp(:,:) = (topmelt(:,:,jl)+botmelt(:,:,jl))*a_i(:,:,jl) 364 359 ELSE … … 368 363 ENDDO 369 364 370 ELSE IF 365 ELSE IF(ksbc == jp_blk) THEN 371 366 372 367 ! Pass bulk forcing fields to CICE (which will calculate heat fluxes etc itself) … … 434 429 ! x comp and y comp of surface ocean current 435 430 ! U point to F point 436 DO jj=1,jpjm1 437 DO ji=1,jpi 438 ztmp(ji,jj)=0.5*(ssu_m(ji,jj)+ssu_m(ji,jj+1))*fmask(ji,jj,1) 439 ENDDO 440 ENDDO 431 DO_2D_10_11 432 ztmp(ji,jj)=0.5*(ssu_m(ji,jj)+ssu_m(ji,jj+1))*fmask(ji,jj,1) 433 END_2D 441 434 CALL nemo2cice(ztmp,uocn,'F', -1. ) 442 435 443 436 ! V point to F point 444 DO jj=1,jpj 445 DO ji=1,jpim1 446 ztmp(ji,jj)=0.5*(ssv_m(ji,jj)+ssv_m(ji+1,jj))*fmask(ji,jj,1) 447 ENDDO 448 ENDDO 437 DO_2D_11_10 438 ztmp(ji,jj)=0.5*(ssv_m(ji,jj)+ssv_m(ji+1,jj))*fmask(ji,jj,1) 439 END_2D 449 440 CALL nemo2cice(ztmp,vocn,'F', -1. ) 450 441 … … 468 459 ! x comp and y comp of sea surface slope (on F points) 469 460 ! T point to F point 470 DO jj = 1, jpjm1 471 DO ji = 1, jpim1 472 ztmp(ji,jj)=0.5 * ( (zpice(ji+1,jj )-zpice(ji,jj )) * r1_e1u(ji,jj ) & 473 & + (zpice(ji+1,jj+1)-zpice(ji,jj+1)) * r1_e1u(ji,jj+1) ) * fmask(ji,jj,1) 474 END DO 475 END DO 461 DO_2D_10_10 462 ztmp(ji,jj)=0.5 * ( (zpice(ji+1,jj )-zpice(ji,jj )) * r1_e1u(ji,jj ) & 463 & + (zpice(ji+1,jj+1)-zpice(ji,jj+1)) * r1_e1u(ji,jj+1) ) * fmask(ji,jj,1) 464 END_2D 476 465 CALL nemo2cice( ztmp,ss_tltx,'F', -1. ) 477 466 478 467 ! T point to F point 479 DO jj = 1, jpjm1 480 DO ji = 1, jpim1 481 ztmp(ji,jj)=0.5 * ( (zpice(ji ,jj+1)-zpice(ji ,jj)) * r1_e2v(ji ,jj) & 482 & + (zpice(ji+1,jj+1)-zpice(ji+1,jj)) * r1_e2v(ji+1,jj) ) * fmask(ji,jj,1) 483 END DO 484 END DO 468 DO_2D_10_10 469 ztmp(ji,jj)=0.5 * ( (zpice(ji ,jj+1)-zpice(ji ,jj)) * r1_e2v(ji ,jj) & 470 & + (zpice(ji+1,jj+1)-zpice(ji+1,jj)) * r1_e2v(ji+1,jj) ) * fmask(ji,jj,1) 471 END_2D 485 472 CALL nemo2cice(ztmp,ss_tlty,'F', -1. ) 486 473 ! … … 508 495 ss_iou(:,:)=0.0 509 496 ! F point to U point 510 DO jj=2,jpjm1 511 DO ji=2,jpim1 512 ss_iou(ji,jj) = 0.5 * ( ztmp1(ji,jj-1) + ztmp1(ji,jj) ) * umask(ji,jj,1) 513 ENDDO 514 ENDDO 497 DO_2D_00_00 498 ss_iou(ji,jj) = 0.5 * ( ztmp1(ji,jj-1) + ztmp1(ji,jj) ) * umask(ji,jj,1) 499 END_2D 515 500 CALL lbc_lnk( 'sbcice_cice', ss_iou , 'U', -1. ) 516 501 … … 520 505 ! F point to V point 521 506 522 DO jj=1,jpjm1 523 DO ji=2,jpim1 524 ss_iov(ji,jj) = 0.5 * ( ztmp1(ji-1,jj) + ztmp1(ji,jj) ) * vmask(ji,jj,1) 525 ENDDO 526 ENDDO 507 DO_2D_10_00 508 ss_iov(ji,jj) = 0.5 * ( ztmp1(ji-1,jj) + ztmp1(ji,jj) ) * vmask(ji,jj,1) 509 END_2D 527 510 CALL lbc_lnk( 'sbcice_cice', ss_iov , 'V', -1. ) 528 511 … … 546 529 ! Freshwater fluxes 547 530 548 IF 531 IF(ksbc == jp_flx) THEN 549 532 ! Note that emp from the forcing files is evap*(1-aice)-(tprecip-aice*sprecip) 550 533 ! What we want here is evap*(1-aice)-tprecip*(1-aice) hence manipulation below … … 552 535 ! Better to use evap and tprecip? (but for now don't read in evap in this case) 553 536 emp(:,:) = emp(:,:)+fr_i(:,:)*(tprecip(:,:)-sprecip(:,:)) 554 ELSE IF 537 ELSE IF(ksbc == jp_blk) THEN 555 538 emp(:,:) = (1.0-fr_i(:,:))*emp(:,:) 556 ELSE IF 539 ELSE IF(ksbc == jp_purecpl) THEN 557 540 ! emp_tot is set in sbc_cpl_ice_flx (called from cice_sbc_in above) 558 541 ! This is currently as required with the coupling fields from the UM atmosphere … … 584 567 ! Scale qsr and qns according to ice fraction (bulk formulae only) 585 568 586 IF 569 IF(ksbc == jp_blk) THEN 587 570 qsr(:,:)=qsr(:,:)*(1.0-fr_i(:,:)) 588 571 qns(:,:)=qns(:,:)*(1.0-fr_i(:,:)) 589 572 ENDIF 590 573 ! Take into account snow melting except for fully coupled when already in qns_tot 591 IF 574 IF(ksbc == jp_purecpl) THEN 592 575 qsr(:,:)= qsr_tot(:,:) 593 576 qns(:,:)= qns_tot(:,:) … … 606 589 CALL lbc_lnk( 'sbcice_cice', qsr , 'T', 1. ) 607 590 608 DO jj=1,jpj 609 DO ji=1,jpi 610 nfrzmlt(ji,jj)=MAX(nfrzmlt(ji,jj),0.0) 611 ENDDO 612 ENDDO 591 DO_2D_11_11 592 nfrzmlt(ji,jj)=MAX(nfrzmlt(ji,jj),0.0) 593 END_2D 613 594 614 595 #if defined key_cice4 … … 624 605 625 606 CALL cice2nemo(aice,fr_i,'T', 1. ) 626 IF 607 IF( (ksbc == jp_flx).OR.(ksbc == jp_purecpl) ) THEN 627 608 DO jl=1,ncat 628 609 CALL cice2nemo(aicen(:,:,jl,:),a_i(:,:,jl), 'T', 1. ) … … 632 613 ! T point to U point 633 614 ! T point to V point 634 DO jj=1,jpjm1 635 DO ji=1,jpim1 636 fr_iu(ji,jj)=0.5*(fr_i(ji,jj)+fr_i(ji+1,jj))*umask(ji,jj,1) 637 fr_iv(ji,jj)=0.5*(fr_i(ji,jj)+fr_i(ji,jj+1))*vmask(ji,jj,1) 638 ENDDO 639 ENDDO 615 DO_2D_10_10 616 fr_iu(ji,jj)=0.5*(fr_i(ji,jj)+fr_i(ji+1,jj))*umask(ji,jj,1) 617 fr_iv(ji,jj)=0.5*(fr_i(ji,jj)+fr_i(ji,jj+1))*vmask(ji,jj,1) 618 END_2D 640 619 641 620 CALL lbc_lnk_multi( 'sbcice_cice', fr_iu , 'U', 1., fr_iv , 'V', 1. ) … … 762 741 sn_bot5 = FLD_N( 'botmeltn5_1m' , -1. , 'botmeltn5' , .true. , .true. , ' yearly' , '' , '' , '' ) 763 742 764 REWIND( numnam_ref ) ! Namelist namsbc_cice in reference namelist :765 743 READ ( numnam_ref, namsbc_cice, IOSTAT = ios, ERR = 901) 766 744 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namsbc_cice in reference namelist' ) 767 745 768 REWIND( numnam_cfg ) ! Namelist namsbc_cice in configuration namelist : Parameters of the run769 746 READ ( numnam_cfg, namsbc_cice, IOSTAT = ios, ERR = 902 ) 770 747 902 IF( ios > 0 ) CALL ctl_nam ( ios , 'namsbc_cice in configuration namelist' ) … … 879 856 ! B. Gather pn into global array (png) 880 857 881 IF 858 IF( jpnij > 1) THEN 882 859 CALL mppsync 883 860 CALL mppgather (pn,0,png) … … 892 869 ! (may be OK but not 100% sure) 893 870 894 IF 871 IF(nproc==0) THEN 895 872 ! pcg(:,:)=0.0 896 873 DO jn=1,jpnij … … 996 973 997 974 pn(:,:)=0.0 998 DO jj=1,jpjm1 999 DO ji=1,jpim1 1000 pn(ji,jj)=pc(ji+1-ji_off,jj+1-jj_off,1) 1001 ENDDO 1002 ENDDO 975 DO_2D_10_10 976 pn(ji,jj)=pc(ji+1-ji_off,jj+1-jj_off,1) 977 END_2D 1003 978 1004 979 #else … … 1015 990 ! the lbclnk call on pn will replace these with sensible values 1016 991 1017 IF 992 IF(nproc==0) THEN 1018 993 png(:,:,:)=0.0 1019 994 DO jn=1,jpnij … … 1028 1003 ! C. Scatter png into NEMO field (pn) for each processor 1029 1004 1030 IF 1005 IF( jpnij > 1) THEN 1031 1006 CALL mppsync 1032 1007 CALL mppscatter (png,0,pn) … … 1056 1031 END SUBROUTINE sbc_ice_cice 1057 1032 1058 SUBROUTINE cice_sbc_init (ksbc ) ! Dummy routine1033 SUBROUTINE cice_sbc_init (ksbc, Kbb, Kmm) ! Dummy routine 1059 1034 IMPLICIT NONE 1060 1035 INTEGER, INTENT( in ) :: ksbc 1036 INTEGER, INTENT( in ) :: Kbb, Kmm 1061 1037 WRITE(*,*) 'cice_sbc_init: You should not have seen this print! error?', ksbc 1062 1038 END SUBROUTINE cice_sbc_init -
NEMO/trunk/src/OCE/SBC/sbcice_if.F90
r11536 r12377 35 35 TYPE(FLD), ALLOCATABLE, DIMENSION(:) :: sf_ice ! structure of input ice-cover (file informations, fields read) 36 36 37 !! * Substitutions 38 # include "do_loop_substitute.h90" 37 39 !!---------------------------------------------------------------------- 38 40 !! NEMO/OCE 4.0 , NEMO Consortium (2018) … … 42 44 CONTAINS 43 45 44 SUBROUTINE sbc_ice_if( kt )46 SUBROUTINE sbc_ice_if( kt, Kbb, Kmm ) 45 47 !!--------------------------------------------------------------------- 46 48 !! *** ROUTINE sbc_ice_if *** … … 59 61 !!--------------------------------------------------------------------- 60 62 INTEGER, INTENT(in) :: kt ! ocean time step 63 INTEGER, INTENT(in) :: Kbb, Kmm ! ocean time level indices 61 64 ! 62 65 INTEGER :: ji, jj ! dummy loop indices … … 74 77 ! ! ====================== ! 75 78 ! set file information 76 REWIND( numnam_ref ) ! Namelist namsbc_iif in reference namelist : Ice if file77 79 READ ( numnam_ref, namsbc_iif, IOSTAT = ios, ERR = 901) 78 80 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namsbc_iif in reference namelist' ) 79 81 80 REWIND( numnam_cfg ) ! Namelist Namelist namsbc_iif in configuration namelist : Ice if file81 82 READ ( numnam_cfg, namsbc_iif, IOSTAT = ios, ERR = 902 ) 82 83 902 IF( ios > 0 ) CALL ctl_nam ( ios , 'namsbc_iif in configuration namelist' ) … … 108 109 109 110 ! Flux and ice fraction computation 110 DO jj = 1, jpj 111 DO ji = 1, jpi 112 ! 113 zt_fzp = fr_i(ji,jj) ! freezing point temperature 114 zfr_obs = sf_ice(1)%fnow(ji,jj,1) ! observed ice cover 115 ! ! ocean ice fraction (0/1) from the freezing point temperature 116 IF( sst_m(ji,jj) <= zt_fzp ) THEN ; fr_i(ji,jj) = 1.e0 117 ELSE ; fr_i(ji,jj) = 0.e0 118 ENDIF 111 DO_2D_11_11 112 ! 113 zt_fzp = fr_i(ji,jj) ! freezing point temperature 114 zfr_obs = sf_ice(1)%fnow(ji,jj,1) ! observed ice cover 115 ! ! ocean ice fraction (0/1) from the freezing point temperature 116 IF( sst_m(ji,jj) <= zt_fzp ) THEN ; fr_i(ji,jj) = 1.e0 117 ELSE ; fr_i(ji,jj) = 0.e0 118 ENDIF 119 119 120 tsn(ji,jj,1,jp_tem) = MAX( tsn(ji,jj,1,jp_tem), zt_fzp ) ! avoid over-freezing point temperature120 ts(ji,jj,1,jp_tem,Kmm) = MAX( ts(ji,jj,1,jp_tem,Kmm), zt_fzp ) ! avoid over-freezing point temperature 121 121 122 122 qsr(ji,jj) = ( 1. - zfr_obs ) * qsr(ji,jj) ! solar heat flux : zero below observed ice cover 123 123 124 125 126 127 zqri = ztrp * ( tsb(ji,jj,1,jp_tem) - ( zt_fzp - 1.) )128 zqrj = ztrp * MIN( 0., tsb(ji,jj,1,jp_tem) - zt_fzp )129 130 124 ! ! non solar heat flux : add a damping term 125 ! # ztrp*(t-(tgel-1.)) if observed ice and no opa ice (zfr_obs=1 fr_i=0) 126 ! # ztrp*min(0,t-tgel) if observed ice and opa ice (zfr_obs=1 fr_i=1) 127 zqri = ztrp * ( ts(ji,jj,1,jp_tem,Kbb) - ( zt_fzp - 1.) ) 128 zqrj = ztrp * MIN( 0., ts(ji,jj,1,jp_tem,Kbb) - zt_fzp ) 129 zqrp = ( zfr_obs * ( (1. - fr_i(ji,jj) ) * zqri & 130 & + fr_i(ji,jj) * zqrj ) ) * tmask(ji,jj,1) 131 131 132 ! ! non-solar heat flux 133 ! # qns unchanged if no climatological ice (zfr_obs=0) 134 ! # qns = zqrp if climatological ice and no opa ice (zfr_obs=1, fr_i=0) 135 ! # qns = zqrp -2(-4) watt/m2 if climatological ice and opa ice (zfr_obs=1, fr_i=1) 136 ! (-2=arctic, -4=antarctic) 137 zqi = -3. + SIGN( 1._wp, ff_f(ji,jj) ) 138 qns(ji,jj) = ( ( 1.- zfr_obs ) * qns(ji,jj) & 139 & + zfr_obs * fr_i(ji,jj) * zqi ) * tmask(ji,jj,1) & 140 & + zqrp 141 END DO 142 END DO 132 ! ! non-solar heat flux 133 ! # qns unchanged if no climatological ice (zfr_obs=0) 134 ! # qns = zqrp if climatological ice and no opa ice (zfr_obs=1, fr_i=0) 135 ! # qns = zqrp -2(-4) watt/m2 if climatological ice and opa ice (zfr_obs=1, fr_i=1) 136 ! (-2=arctic, -4=antarctic) 137 zqi = -3. + SIGN( 1._wp, ff_f(ji,jj) ) 138 qns(ji,jj) = ( ( 1.- zfr_obs ) * qns(ji,jj) & 139 & + zfr_obs * fr_i(ji,jj) * zqi ) * tmask(ji,jj,1) & 140 & + zqrp 141 END_2D 143 142 ! 144 143 ENDIF -
NEMO/trunk/src/OCE/SBC/sbcmod.F90
r12276 r12377 15 15 !! 3.6 ! 2014-11 (P. Mathiot, C. Harris) add ice shelves melting 16 16 !! 4.0 ! 2016-06 (L. Brodeau) new general bulk formulation 17 !! 4.0 ! 2019-03 (F. Lemarié & G. Samson) add ABL compatibility (ln_abl=TRUE) 17 18 !!---------------------------------------------------------------------- 18 19 … … 24 25 USE oce ! ocean dynamics and tracers 25 26 USE dom_oce ! ocean space and time domain 27 USE closea ! closed seas 26 28 USE phycst ! physical constants 27 29 USE sbc_oce ! Surface boundary condition: ocean fields … … 32 34 USE sbcflx ! surface boundary condition: flux formulation 33 35 USE sbcblk ! surface boundary condition: bulk formulation 36 USE sbcabl ! atmospheric boundary layer 34 37 USE sbcice_if ! surface boundary condition: ice-if sea-ice model 35 38 #if defined key_si3 … … 37 40 #endif 38 41 USE sbcice_cice ! surface boundary condition: CICE sea-ice model 39 USE sbcisf ! surface boundary condition: ice-shelf40 42 USE sbccpl ! surface boundary condition: coupled formulation 41 43 USE cpl_oasis3 ! OASIS routines for coupling 44 USE sbcclo ! surface boundary condition: closed sea correction 42 45 USE sbcssr ! surface boundary condition: sea surface restoring 43 46 USE sbcrnf ! surface boundary condition: runoffs 44 47 USE sbcapr ! surface boundary condition: atmo pressure 45 USE sbcisf ! surface boundary condition: ice shelf46 48 USE sbcfwb ! surface boundary condition: freshwater budget 47 49 USE icbstp ! Icebergs … … 59 61 USE timing ! Timing 60 62 USE wet_dry 61 USE diu rnal_bulk, ONLY: ln_diurnal_only ! diurnal SST diagnostic63 USE diu_bulk, ONLY: ln_diurnal_only ! diurnal SST diagnostic 62 64 63 65 IMPLICIT NONE … … 76 78 CONTAINS 77 79 78 SUBROUTINE sbc_init 80 SUBROUTINE sbc_init( Kbb, Kmm, Kaa ) 79 81 !!--------------------------------------------------------------------- 80 82 !! *** ROUTINE sbc_init *** … … 88 90 !! - nsbc: type of sbc 89 91 !!---------------------------------------------------------------------- 92 INTEGER, INTENT(in) :: Kbb, Kmm, Kaa ! ocean time level indices 90 93 INTEGER :: ios, icpt ! local integer 91 94 LOGICAL :: ll_purecpl, ll_opa, ll_not_nemo ! local logical 92 95 !! 93 96 NAMELIST/namsbc/ nn_fsbc , & 94 & ln_usr , ln_flx , ln_blk ,&97 & ln_usr , ln_flx , ln_blk , ln_abl, & 95 98 & ln_cpl , ln_mixcpl, nn_components, & 96 99 & nn_ice , ln_ice_embd, & 97 100 & ln_traqsr, ln_dm2dc , & 98 & ln_rnf , nn_fwb , ln_ssr , ln_isf , ln_apr_dyn ,&99 & ln_wave , ln_cdgw , ln_sdw , ln_tauwoc , ln_stcor 101 & ln_rnf , nn_fwb , ln_ssr , ln_apr_dyn, & 102 & ln_wave , ln_cdgw , ln_sdw , ln_tauwoc , ln_stcor , & 100 103 & ln_tauw , nn_lsm, nn_sdrift 101 104 !!---------------------------------------------------------------------- … … 108 111 ! 109 112 ! !** read Surface Module namelist 110 REWIND( numnam_ref ) !* Namelist namsbc in reference namelist : Surface boundary111 113 READ ( numnam_ref, namsbc, IOSTAT = ios, ERR = 901) 112 114 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namsbc in reference namelist' ) 113 REWIND( numnam_cfg ) !* Namelist namsbc in configuration namelist : Parameters of the run114 115 READ ( numnam_cfg, namsbc, IOSTAT = ios, ERR = 902 ) 115 116 902 IF( ios > 0 ) CALL ctl_nam ( ios , 'namsbc in configuration namelist' ) … … 125 126 IF( lk_cice ) nn_ice = 3 126 127 ENDIF 127 #else 128 IF( lk_si3 ) nn_ice = 2 129 IF( lk_cice ) nn_ice = 3 128 !!GS: TBD 129 !#else 130 ! IF( lk_si3 ) nn_ice = 2 131 ! IF( lk_cice ) nn_ice = 3 130 132 #endif 131 133 ! … … 137 139 WRITE(numout,*) ' flux formulation ln_flx = ', ln_flx 138 140 WRITE(numout,*) ' bulk formulation ln_blk = ', ln_blk 141 WRITE(numout,*) ' ABL formulation ln_abl = ', ln_abl 139 142 WRITE(numout,*) ' Type of coupling (Ocean/Ice/Atmosphere) : ' 140 143 WRITE(numout,*) ' ocean-atmosphere coupled formulation ln_cpl = ', ln_cpl … … 153 156 WRITE(numout,*) ' Patm gradient added in ocean & ice Eqs. ln_apr_dyn = ', ln_apr_dyn 154 157 WRITE(numout,*) ' runoff / runoff mouths ln_rnf = ', ln_rnf 155 WRITE(numout,*) ' iceshelf formulation ln_isf = ', ln_isf156 158 WRITE(numout,*) ' nb of iterations if land-sea-mask applied nn_lsm = ', nn_lsm 157 159 WRITE(numout,*) ' surface wave ln_wave = ', ln_wave … … 225 227 CASE( 1 ) !- Ice-cover climatology ("Ice-if" model) 226 228 CASE( 2 ) !- SI3 ice model 229 IF( .NOT.( ln_blk .OR. ln_cpl .OR. ln_abl .OR. ln_usr ) ) & 230 & CALL ctl_stop( 'sbc_init : SI3 sea-ice model requires ln_blk or ln_cpl or ln_abl or ln_usr = T' ) 227 231 CASE( 3 ) !- CICE ice model 228 IF( .NOT.( ln_blk .OR. ln_cpl ) ) CALL ctl_stop( 'sbc_init : CICE sea-ice model requires ln_blk or ln_cpl = T' ) 229 IF( lk_agrif ) CALL ctl_stop( 'sbc_init : CICE sea-ice model not currently available with AGRIF' ) 232 IF( .NOT.( ln_blk .OR. ln_cpl .OR. ln_abl .OR. ln_usr ) ) & 233 & CALL ctl_stop( 'sbc_init : CICE sea-ice model requires ln_blk or ln_cpl or ln_abl or ln_usr = T' ) 234 IF( lk_agrif ) & 235 & CALL ctl_stop( 'sbc_init : CICE sea-ice model not currently available with AGRIF' ) 230 236 CASE DEFAULT !- not supported 231 237 END SELECT 238 IF( ln_diurnal .AND. .NOT. ln_blk ) CALL ctl_stop( "sbc_init: diurnal flux processing only implemented for bulk forcing" ) 232 239 ! 233 240 ! !** allocate and set required variables … … 239 246 #endif 240 247 ! 241 IF( .NOT.ln_isf ) THEN !* No ice-shelf in the domain : allocate and set to zero242 IF( sbc_isf_alloc() /= 0 ) CALL ctl_stop( 'STOP', 'sbc_init : unable to allocate sbc_isf arrays' )243 fwfisf (:,:) = 0._wp ; risf_tsc (:,:,:) = 0._wp244 fwfisf_b(:,:) = 0._wp ; risf_tsc_b(:,:,:) = 0._wp245 END IF246 248 ! 247 249 IF( sbc_ssr_alloc() /= 0 ) CALL ctl_stop( 'STOP', 'sbc_init : unable to allocate sbc_ssr arrays' ) … … 262 264 263 265 ! ! Choice of the Surface Boudary Condition (set nsbc) 266 nday_qsr = -1 ! allow initialization at the 1st call !LB: now warm-layer of COARE* calls "sbc_dcy_param" of sbcdcy.F90! 264 267 IF( ln_dm2dc ) THEN !* daily mean to diurnal cycle 265 nday_qsr = -1 ! allow initialization at the 1st call266 IF( .NOT.( ln_flx .OR. ln_blk ) .AND. nn_components /= jp_iam_opa ) &267 & CALL ctl_stop( 'qsr diurnal cycle from daily values requires a flux or bulkformulation' )268 !LB:nday_qsr = -1 ! allow initialization at the 1st call 269 IF( .NOT.( ln_flx .OR. ln_blk .OR. ln_abl ) .AND. nn_components /= jp_iam_opa ) & 270 & CALL ctl_stop( 'qsr diurnal cycle from daily values requires flux, bulk or abl formulation' ) 268 271 ENDIF 269 272 ! !* Choice of the Surface Boudary Condition … … 278 281 IF( ln_flx ) THEN ; nsbc = jp_flx ; icpt = icpt + 1 ; ENDIF ! flux formulation 279 282 IF( ln_blk ) THEN ; nsbc = jp_blk ; icpt = icpt + 1 ; ENDIF ! bulk formulation 283 IF( ln_abl ) THEN ; nsbc = jp_abl ; icpt = icpt + 1 ; ENDIF ! ABL formulation 280 284 IF( ll_purecpl ) THEN ; nsbc = jp_purecpl ; icpt = icpt + 1 ; ENDIF ! Pure Coupled formulation 281 285 IF( ll_opa ) THEN ; nsbc = jp_none ; icpt = icpt + 1 ; ENDIF ! opa coupling via SAS module … … 289 293 CASE( jp_flx ) ; WRITE(numout,*) ' ==>>> flux formulation' 290 294 CASE( jp_blk ) ; WRITE(numout,*) ' ==>>> bulk formulation' 295 CASE( jp_abl ) ; WRITE(numout,*) ' ==>>> ABL formulation' 291 296 CASE( jp_purecpl ) ; WRITE(numout,*) ' ==>>> pure coupled formulation' 292 297 !!gm abusive use of jp_none ?? ===>>> need to be check and changed by adding a jp_sas parameter … … 335 340 ! !** associated modules : initialization 336 341 ! 337 CALL sbc_ssm_init ! Sea-surface mean fields initialization 342 CALL sbc_ssm_init ( Kbb, Kmm ) ! Sea-surface mean fields initialization 343 ! 344 IF( l_sbc_clo ) CALL sbc_clo_init ! closed sea surface initialisation 338 345 ! 339 346 IF( ln_blk ) CALL sbc_blk_init ! bulk formulae initialization 340 347 348 IF( ln_abl ) CALL sbc_abl_init ! Atmospheric Boundary Layer (ABL) 349 341 350 IF( ln_ssr ) CALL sbc_ssr_init ! Sea-Surface Restoring initialization 342 351 ! 343 IF( ln_isf ) CALL sbc_isf_init ! Compute iceshelves 344 ! 345 CALL sbc_rnf_init ! Runof initialization 346 ! 347 IF( ln_apr_dyn ) CALL sbc_apr_init ! Atmo Pressure Forcing initialization 352 ! 353 CALL sbc_rnf_init( Kmm ) ! Runof initialization 354 ! 355 IF( ln_apr_dyn ) CALL sbc_apr_init ! Atmo Pressure Forcing initialization 348 356 ! 349 357 #if defined key_si3 … … 351 359 IF( sbc_ice_alloc() /= 0 ) CALL ctl_stop('STOP', 'sbc_ice_alloc : unable to allocate arrays' ) 352 360 ELSEIF( nn_ice == 2 ) THEN 353 CALL ice_init 361 CALL ice_init( Kbb, Kmm, Kaa ) ! ICE initialization 354 362 ENDIF 355 363 #endif 356 IF( nn_ice == 3 ) CALL cice_sbc_init( nsbc ) ! CICE initialization357 ! 358 IF( ln_wave ) CALL sbc_wave_init ! surface wave initialisation364 IF( nn_ice == 3 ) CALL cice_sbc_init( nsbc, Kbb, Kmm ) ! CICE initialization 365 ! 366 IF( ln_wave ) CALL sbc_wave_init ! surface wave initialisation 359 367 ! 360 368 IF( lwxios ) THEN … … 371 379 372 380 373 SUBROUTINE sbc( kt )381 SUBROUTINE sbc( kt, Kbb, Kmm ) 374 382 !!--------------------------------------------------------------------- 375 383 !! *** ROUTINE sbc *** … … 388 396 !!---------------------------------------------------------------------- 389 397 INTEGER, INTENT(in) :: kt ! ocean time step 398 INTEGER, INTENT(in) :: Kbb, Kmm ! ocean time level indices 390 399 ! 391 400 LOGICAL :: ll_sas, ll_opa ! local logical … … 406 415 emp_b (:,:) = emp (:,:) 407 416 sfx_b (:,:) = sfx (:,:) 408 IF 417 IF( ln_rnf ) THEN 409 418 rnf_b (:,: ) = rnf (:,: ) 410 419 rnf_tsc_b(:,:,:) = rnf_tsc(:,:,:) 411 420 ENDIF 412 IF( ln_isf ) THEN413 fwfisf_b (:,: ) = fwfisf (:,: )414 risf_tsc_b(:,:,:) = risf_tsc(:,:,:)415 ENDIF416 421 ! 417 422 ENDIF … … 423 428 ll_opa = nn_components == jp_iam_opa 424 429 ! 425 IF( .NOT.ll_sas ) CALL sbc_ssm ( kt )! mean ocean sea surface variables (sst_m, sss_m, ssu_m, ssv_m)426 IF( ln_wave ) CALL sbc_wave( kt )! surface waves430 IF( .NOT.ll_sas ) CALL sbc_ssm ( kt, Kbb, Kmm ) ! mean ocean sea surface variables (sst_m, sss_m, ssu_m, ssv_m) 431 IF( ln_wave ) CALL sbc_wave( kt, Kmm ) ! surface waves 427 432 428 433 ! … … 431 436 SELECT CASE( nsbc ) ! Compute ocean surface boundary condition 432 437 ! ! (i.e. utau,vtau, qns, qsr, emp, sfx) 433 CASE( jp_usr ) ; CALL usrdef_sbc_oce( kt )! user defined formulation434 CASE( jp_flx ) ; CALL sbc_flx ( kt ) ! flux formulation438 CASE( jp_usr ) ; CALL usrdef_sbc_oce( kt, Kbb ) ! user defined formulation 439 CASE( jp_flx ) ; CALL sbc_flx ( kt ) ! flux formulation 435 440 CASE( jp_blk ) 436 IF( ll_sas ) CALL sbc_cpl_rcv ( kt, nn_fsbc, nn_ice ) ! OPA-SAS coupling: SAS receiving fields from OPA441 IF( ll_sas ) CALL sbc_cpl_rcv ( kt, nn_fsbc, nn_ice, Kbb, Kmm ) ! OPA-SAS coupling: SAS receiving fields from OPA 437 442 CALL sbc_blk ( kt ) ! bulk formulation for the ocean 438 443 ! 439 CASE( jp_purecpl ) ; CALL sbc_cpl_rcv ( kt, nn_fsbc, nn_ice ) ! pure coupled formulation 444 CASE( jp_abl ) 445 IF( ll_sas ) CALL sbc_cpl_rcv ( kt, nn_fsbc, nn_ice, Kbb, Kmm ) ! OPA-SAS coupling: SAS receiving fields from OPA 446 CALL sbc_abl ( kt ) ! ABL formulation for the ocean 447 ! 448 CASE( jp_purecpl ) ; CALL sbc_cpl_rcv ( kt, nn_fsbc, nn_ice, Kbb, Kmm ) ! pure coupled formulation 440 449 CASE( jp_none ) 441 IF( ll_opa ) CALL sbc_cpl_rcv ( kt, nn_fsbc, nn_ice )! OPA-SAS coupling: OPA receiving fields from SAS450 IF( ll_opa ) CALL sbc_cpl_rcv ( kt, nn_fsbc, nn_ice, Kbb, Kmm ) ! OPA-SAS coupling: OPA receiving fields from SAS 442 451 END SELECT 443 452 ! 444 IF( ln_mixcpl ) CALL sbc_cpl_rcv ( kt, nn_fsbc, nn_ice )! forced-coupled mixed formulation after forcing445 ! 446 IF ( ln_wave .AND. (ln_tauwoc .OR. ln_tauw) ) CALL sbc_wstress( ) ! Wind stress provided by waves453 IF( ln_mixcpl ) CALL sbc_cpl_rcv ( kt, nn_fsbc, nn_ice, Kbb, Kmm ) ! forced-coupled mixed formulation after forcing 454 ! 455 IF ( ln_wave .AND. (ln_tauwoc .OR. ln_tauw) ) CALL sbc_wstress( ) ! Wind stress provided by waves 447 456 ! 448 457 ! !== Misc. Options ==! 449 458 ! 450 459 SELECT CASE( nn_ice ) ! Update heat and freshwater fluxes over sea-ice areas 451 CASE( 1 ) ; CALL sbc_ice_if ( kt )! Ice-cover climatology ("Ice-if" model)460 CASE( 1 ) ; CALL sbc_ice_if ( kt, Kbb, Kmm ) ! Ice-cover climatology ("Ice-if" model) 452 461 #if defined key_si3 453 CASE( 2 ) ; CALL ice_stp ( kt, nsbc )! SI3 ice model462 CASE( 2 ) ; CALL ice_stp ( kt, Kbb, Kmm, nsbc ) ! SI3 ice model 454 463 #endif 455 464 CASE( 3 ) ; CALL sbc_ice_cice ( kt, nsbc ) ! CICE ice model … … 458 467 IF( ln_icebergs ) THEN 459 468 CALL icb_stp( kt ) ! compute icebergs 460 ! icebergs may advect into haloes during the icb step and alter emp. 461 ! A lbc_lnk is necessary here to ensure restartability (#2113) 469 ! Icebergs do not melt over the haloes. 470 ! So emp values over the haloes are no more consistent with the inner domain values. 471 ! A lbc_lnk is therefore needed to ensure reproducibility and restartability. 472 ! see ticket #2113 for discussion about this lbc_lnk. 462 473 IF( .NOT. ln_passive_mode ) CALL lbc_lnk( 'sbcmod', emp, 'T', 1. ) ! ensure restartability with icebergs 463 474 ENDIF 464 475 465 IF( ln_isf ) CALL sbc_isf( kt ) ! compute iceshelves466 467 476 IF( ln_rnf ) CALL sbc_rnf( kt ) ! add runoffs to fresh water fluxes 468 477 469 IF( ln_ssr ) CALL sbc_ssr( kt ) ! add SST/SSS damping term470 471 IF( nn_fwb /= 0 ) CALL sbc_fwb( kt, nn_fwb, nn_fsbc ) ! control the freshwater budget478 IF( ln_ssr ) CALL sbc_ssr( kt ) ! add SST/SSS damping term 479 480 IF( nn_fwb /= 0 ) CALL sbc_fwb( kt, nn_fwb, nn_fsbc, Kmm ) ! control the freshwater budget 472 481 473 482 ! Special treatment of freshwater fluxes over closed seas in the model domain 474 483 ! Should not be run if ln_diurnal_only 475 IF( l_sbc_clo .AND. (.NOT. ln_diurnal_only)) CALL sbc_clo( kt )484 IF( l_sbc_clo ) CALL sbc_clo( kt ) 476 485 477 486 !!$!RBbug do not understand why see ticket 667 478 487 !!$!clem: it looks like it is necessary for the north fold (in certain circumstances). Don't know why. 479 488 !!$ CALL lbc_lnk( 'sbcmod', emp, 'T', 1. ) 480 IF 489 IF( ll_wd ) THEN ! If near WAD point limit the flux for now 481 490 zthscl = atanh(rn_wd_sbcfra) ! taper frac default is .999 482 zwdht(:,:) = ssh n(:,:) + ht_0(:,:) - rn_wdmin1 ! do this calc of water491 zwdht(:,:) = ssh(:,:,Kmm) + ht_0(:,:) - rn_wdmin1 ! do this calc of water 483 492 ! depth above wd limit once 484 493 WHERE( zwdht(:,:) <= 0.0 ) … … 510 519 CALL iom_get( numror, jpdom_autoglo, 'utau_b', utau_b, ldxios = lrxios ) ! before i-stress (U-point) 511 520 CALL iom_get( numror, jpdom_autoglo, 'vtau_b', vtau_b, ldxios = lrxios ) ! before j-stress (V-point) 512 CALL iom_get( numror, jpdom_autoglo, 'qns_b' , qns_b, ldxios = lrxios) ! before non solar heat flux (T-point)521 CALL iom_get( numror, jpdom_autoglo, 'qns_b', qns_b, ldxios = lrxios ) ! before non solar heat flux (T-point) 513 522 ! The 3D heat content due to qsr forcing is treated in traqsr 514 523 ! CALL iom_get( numror, jpdom_autoglo, 'qsr_b' , qsr_b, ldxios = lrxios ) ! before solar heat flux (T-point) … … 567 576 CALL iom_put( "vtau", vtau ) ! j-wind stress 568 577 ! 569 IF( ln_ctl) THEN! print mean trends (used for debugging)570 CALL prt_ctl(tab2d_1=fr_i , clinfo1=' fr_i- : ', mask1=tmask )571 CALL prt_ctl(tab2d_1=(emp-rnf + fwfisf), clinfo1=' emp-rnf- : ', mask1=tmask )572 CALL prt_ctl(tab2d_1=(sfx-rnf + fwfisf), clinfo1=' sfx-rnf- : ', mask1=tmask )578 IF(sn_cfctl%l_prtctl) THEN ! print mean trends (used for debugging) 579 CALL prt_ctl(tab2d_1=fr_i , clinfo1=' fr_i - : ', mask1=tmask ) 580 CALL prt_ctl(tab2d_1=(emp-rnf) , clinfo1=' emp-rnf - : ', mask1=tmask ) 581 CALL prt_ctl(tab2d_1=(sfx-rnf) , clinfo1=' sfx-rnf - : ', mask1=tmask ) 573 582 CALL prt_ctl(tab2d_1=qns , clinfo1=' qns - : ', mask1=tmask ) 574 583 CALL prt_ctl(tab2d_1=qsr , clinfo1=' qsr - : ', mask1=tmask ) 575 584 CALL prt_ctl(tab3d_1=tmask , clinfo1=' tmask - : ', mask1=tmask, kdim=jpk ) 576 CALL prt_ctl(tab3d_1=ts n(:,:,:,jp_tem), clinfo1=' sst - : ', mask1=tmask, kdim=1 )577 CALL prt_ctl(tab3d_1=ts n(:,:,:,jp_sal), clinfo1=' sss - : ', mask1=tmask, kdim=1 )578 CALL prt_ctl(tab2d_1=utau , clinfo1=' utau - : ', mask1=umask, &579 & tab2d_2=vtau , clinfo2=' vtau - : ', mask2=vmask )585 CALL prt_ctl(tab3d_1=ts(:,:,:,jp_tem,Kmm), clinfo1=' sst - : ', mask1=tmask, kdim=1 ) 586 CALL prt_ctl(tab3d_1=ts(:,:,:,jp_sal,Kmm), clinfo1=' sss - : ', mask1=tmask, kdim=1 ) 587 CALL prt_ctl(tab2d_1=utau , clinfo1=' utau - : ', mask1=umask, & 588 & tab2d_2=vtau , clinfo2=' vtau - : ', mask2=vmask ) 580 589 ENDIF 581 590 -
NEMO/trunk/src/OCE/SBC/sbcrnf.F90
r12277 r12377 70 70 TYPE(FLD), ALLOCATABLE, DIMENSION(:) :: sf_t_rnf ! structure: river runoff temperature (file information, fields read) 71 71 72 !! * Substitutions 73 # include "do_loop_substitute.h90" 72 74 !!---------------------------------------------------------------------- 73 75 !! NEMO/OCE 4.0 , NEMO Consortium (2018) … … 183 185 184 186 185 SUBROUTINE sbc_rnf_div( phdivn )187 SUBROUTINE sbc_rnf_div( phdivn, Kmm ) 186 188 !!---------------------------------------------------------------------- 187 189 !! *** ROUTINE sbc_rnf *** … … 195 197 !! ** Action : phdivn decreased by the runoff inflow 196 198 !!---------------------------------------------------------------------- 199 INTEGER , INTENT(in ) :: Kmm ! ocean time level index 197 200 REAL(wp), DIMENSION(:,:,:), INTENT(inout) :: phdivn ! horizontal divergence 198 201 !! … … 205 208 IF( ln_rnf_depth .OR. ln_rnf_depth_ini ) THEN !== runoff distributed over several levels ==! 206 209 IF( ln_linssh ) THEN !* constant volume case : just apply the runoff input flow 207 DO jj = 1, jpj 208 DO ji = 1, jpi 209 DO jk = 1, nk_rnf(ji,jj) 210 phdivn(ji,jj,jk) = phdivn(ji,jj,jk) - ( rnf(ji,jj) + rnf_b(ji,jj) ) * zfact * r1_rau0 / h_rnf(ji,jj) 211 END DO 210 DO_2D_11_11 211 DO jk = 1, nk_rnf(ji,jj) 212 phdivn(ji,jj,jk) = phdivn(ji,jj,jk) - ( rnf(ji,jj) + rnf_b(ji,jj) ) * zfact * r1_rau0 / h_rnf(ji,jj) 212 213 END DO 213 END DO214 END_2D 214 215 ELSE !* variable volume case 215 DO jj = 1, jpj ! update the depth over which runoffs are distributed 216 DO ji = 1, jpi 217 h_rnf(ji,jj) = 0._wp 218 DO jk = 1, nk_rnf(ji,jj) ! recalculates h_rnf to be the depth in metres 219 h_rnf(ji,jj) = h_rnf(ji,jj) + e3t_n(ji,jj,jk) ! to the bottom of the relevant grid box 220 END DO 221 ! ! apply the runoff input flow 222 DO jk = 1, nk_rnf(ji,jj) 223 phdivn(ji,jj,jk) = phdivn(ji,jj,jk) - ( rnf(ji,jj) + rnf_b(ji,jj) ) * zfact * r1_rau0 / h_rnf(ji,jj) 224 END DO 216 DO_2D_11_11 217 h_rnf(ji,jj) = 0._wp 218 DO jk = 1, nk_rnf(ji,jj) ! recalculates h_rnf to be the depth in metres 219 h_rnf(ji,jj) = h_rnf(ji,jj) + e3t(ji,jj,jk,Kmm) ! to the bottom of the relevant grid box 225 220 END DO 226 END DO 221 ! ! apply the runoff input flow 222 DO jk = 1, nk_rnf(ji,jj) 223 phdivn(ji,jj,jk) = phdivn(ji,jj,jk) - ( rnf(ji,jj) + rnf_b(ji,jj) ) * zfact * r1_rau0 / h_rnf(ji,jj) 224 END DO 225 END_2D 227 226 ENDIF 228 227 ELSE !== runoff put only at the surface ==! 229 h_rnf (:,:) = e3t _n (:,:,1) ! update h_rnf to be depth of top box230 phdivn(:,:,1) = phdivn(:,:,1) - ( rnf(:,:) + rnf_b(:,:) ) * zfact * r1_rau0 / e3t _n(:,:,1)228 h_rnf (:,:) = e3t (:,:,1,Kmm) ! update h_rnf to be depth of top box 229 phdivn(:,:,1) = phdivn(:,:,1) - ( rnf(:,:) + rnf_b(:,:) ) * zfact * r1_rau0 / e3t(:,:,1,Kmm) 231 230 ENDIF 232 231 ! … … 234 233 235 234 236 SUBROUTINE sbc_rnf_init 235 SUBROUTINE sbc_rnf_init( Kmm ) 237 236 !!---------------------------------------------------------------------- 238 237 !! *** ROUTINE sbc_rnf_init *** … … 244 243 !! ** Action : - read parameters 245 244 !!---------------------------------------------------------------------- 245 INTEGER, INTENT(in) :: Kmm ! ocean time level index 246 246 CHARACTER(len=32) :: rn_dep_file ! runoff file name 247 247 INTEGER :: ji, jj, jk, jm ! dummy loop indices … … 275 275 ! ! ============ 276 276 ! 277 REWIND( numnam_ref )278 277 READ ( numnam_ref, namsbc_rnf, IOSTAT = ios, ERR = 901) 279 278 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namsbc_rnf in reference namelist' ) 280 279 281 REWIND( numnam_cfg )282 280 READ ( numnam_cfg, namsbc_rnf, IOSTAT = ios, ERR = 902 ) 283 281 902 IF( ios > 0 ) CALL ctl_nam ( ios , 'namsbc_rnf in configuration namelist' ) … … 362 360 ! 363 361 nk_rnf(:,:) = 0 ! set the number of level over which river runoffs are applied 364 DO jj = 1, jpj 365 DO ji = 1, jpi 366 IF( h_rnf(ji,jj) > 0._wp ) THEN 367 jk = 2 368 DO WHILE ( jk < mbkt(ji,jj) .AND. gdept_0(ji,jj,jk) < h_rnf(ji,jj) ) ; jk = jk + 1 369 END DO 370 nk_rnf(ji,jj) = jk 371 ELSEIF( h_rnf(ji,jj) == -1._wp ) THEN ; nk_rnf(ji,jj) = 1 372 ELSEIF( h_rnf(ji,jj) == -999._wp ) THEN ; nk_rnf(ji,jj) = mbkt(ji,jj) 373 ELSE 374 CALL ctl_stop( 'sbc_rnf_init: runoff depth not positive, and not -999 or -1, rnf value in file fort.999' ) 375 WRITE(999,*) 'ji, jj, h_rnf(ji,jj) :', ji, jj, h_rnf(ji,jj) 376 ENDIF 362 DO_2D_11_11 363 IF( h_rnf(ji,jj) > 0._wp ) THEN 364 jk = 2 365 DO WHILE ( jk < mbkt(ji,jj) .AND. gdept_0(ji,jj,jk) < h_rnf(ji,jj) ) ; jk = jk + 1 366 END DO 367 nk_rnf(ji,jj) = jk 368 ELSEIF( h_rnf(ji,jj) == -1._wp ) THEN ; nk_rnf(ji,jj) = 1 369 ELSEIF( h_rnf(ji,jj) == -999._wp ) THEN ; nk_rnf(ji,jj) = mbkt(ji,jj) 370 ELSE 371 CALL ctl_stop( 'sbc_rnf_init: runoff depth not positive, and not -999 or -1, rnf value in file fort.999' ) 372 WRITE(999,*) 'ji, jj, h_rnf(ji,jj) :', ji, jj, h_rnf(ji,jj) 373 ENDIF 374 END_2D 375 DO_2D_11_11 376 h_rnf(ji,jj) = 0._wp 377 DO jk = 1, nk_rnf(ji,jj) 378 h_rnf(ji,jj) = h_rnf(ji,jj) + e3t(ji,jj,jk,Kmm) 377 379 END DO 378 END DO 379 DO jj = 1, jpj ! set the associated depth 380 DO ji = 1, jpi 381 h_rnf(ji,jj) = 0._wp 382 DO jk = 1, nk_rnf(ji,jj) 383 h_rnf(ji,jj) = h_rnf(ji,jj) + e3t_n(ji,jj,jk) 384 END DO 385 END DO 386 END DO 380 END_2D 387 381 ! 388 382 ELSE IF( ln_rnf_depth_ini ) THEN ! runoffs applied at the surface … … 409 403 WHERE( zrnfcl(:,:,1) > 0._wp ) h_rnf(:,:) = zacoef * zrnfcl(:,:,1) ! compute depth for all runoffs 410 404 ! 411 DO jj = 1, jpj ! take in account min depth of ocean rn_hmin 412 DO ji = 1, jpi 413 IF( zrnfcl(ji,jj,1) > 0._wp ) THEN 414 jk = mbkt(ji,jj) 415 h_rnf(ji,jj) = MIN( h_rnf(ji,jj), gdept_0(ji,jj,jk ) ) 416 ENDIF 405 DO_2D_11_11 406 IF( zrnfcl(ji,jj,1) > 0._wp ) THEN 407 jk = mbkt(ji,jj) 408 h_rnf(ji,jj) = MIN( h_rnf(ji,jj), gdept_0(ji,jj,jk ) ) 409 ENDIF 410 END_2D 411 ! 412 nk_rnf(:,:) = 0 ! number of levels on which runoffs are distributed 413 DO_2D_11_11 414 IF( zrnfcl(ji,jj,1) > 0._wp ) THEN 415 jk = 2 416 DO WHILE ( jk < mbkt(ji,jj) .AND. gdept_0(ji,jj,jk) < h_rnf(ji,jj) ) ; jk = jk + 1 417 END DO 418 nk_rnf(ji,jj) = jk 419 ELSE 420 nk_rnf(ji,jj) = 1 421 ENDIF 422 END_2D 423 ! 424 DO_2D_11_11 425 h_rnf(ji,jj) = 0._wp 426 DO jk = 1, nk_rnf(ji,jj) 427 h_rnf(ji,jj) = h_rnf(ji,jj) + e3t(ji,jj,jk,Kmm) 417 428 END DO 418 END DO 419 ! 420 nk_rnf(:,:) = 0 ! number of levels on which runoffs are distributed 421 DO jj = 1, jpj 422 DO ji = 1, jpi 423 IF( zrnfcl(ji,jj,1) > 0._wp ) THEN 424 jk = 2 425 DO WHILE ( jk < mbkt(ji,jj) .AND. gdept_0(ji,jj,jk) < h_rnf(ji,jj) ) ; jk = jk + 1 426 END DO 427 nk_rnf(ji,jj) = jk 428 ELSE 429 nk_rnf(ji,jj) = 1 430 ENDIF 431 END DO 432 END DO 433 ! 434 DO jj = 1, jpj ! set the associated depth 435 DO ji = 1, jpi 436 h_rnf(ji,jj) = 0._wp 437 DO jk = 1, nk_rnf(ji,jj) 438 h_rnf(ji,jj) = h_rnf(ji,jj) + e3t_n(ji,jj,jk) 439 END DO 440 END DO 441 END DO 429 END_2D 442 430 ! 443 431 IF( nn_rnf_depth_file == 1 ) THEN ! save output nb levels for runoff … … 449 437 ELSE ! runoffs applied at the surface 450 438 nk_rnf(:,:) = 1 451 h_rnf (:,:) = e3t _n(:,:,1)439 h_rnf (:,:) = e3t(:,:,1,Kmm) 452 440 ENDIF 453 441 ! -
NEMO/trunk/src/OCE/SBC/sbcssm.F90
r10425 r12377 39 39 CONTAINS 40 40 41 SUBROUTINE sbc_ssm( kt )41 SUBROUTINE sbc_ssm( kt, Kbb, Kmm ) 42 42 !!--------------------------------------------------------------------- 43 43 !! *** ROUTINE sbc_oce *** … … 53 53 !!--------------------------------------------------------------------- 54 54 INTEGER, INTENT(in) :: kt ! ocean time step 55 INTEGER, INTENT(in) :: Kbb, Kmm ! ocean time level indices 55 56 ! 56 57 INTEGER :: ji, jj ! loop index … … 60 61 ! 61 62 ! !* surface T-, U-, V- ocean level variables (T, S, depth, velocity) 62 DO jj = 1, jpj 63 DO ji = 1, jpi 64 zts(ji,jj,jp_tem) = tsn(ji,jj,mikt(ji,jj),jp_tem) 65 zts(ji,jj,jp_sal) = tsn(ji,jj,mikt(ji,jj),jp_sal) 66 END DO 67 END DO 63 zts(:,:,jp_tem) = ts(:,:,1,jp_tem,Kmm) 64 zts(:,:,jp_sal) = ts(:,:,1,jp_sal,Kmm) 68 65 ! 69 66 IF( nn_fsbc == 1 ) THEN ! Instantaneous surface fields ! 70 67 ! ! ---------------------------------------- ! 71 ssu_m(:,:) = u b(:,:,1)72 ssv_m(:,:) = v b(:,:,1)68 ssu_m(:,:) = uu(:,:,1,Kbb) 69 ssv_m(:,:) = vv(:,:,1,Kbb) 73 70 IF( l_useCT ) THEN ; sst_m(:,:) = eos_pt_from_ct( zts(:,:,jp_tem), zts(:,:,jp_sal) ) 74 ELSE 71 ELSE ; sst_m(:,:) = zts(:,:,jp_tem) 75 72 ENDIF 76 73 sss_m(:,:) = zts(:,:,jp_sal) 77 74 ! ! removed inverse barometer ssh when Patm forcing is used (for sea-ice dynamics) 78 IF( ln_apr_dyn ) THEN ; ssh_m(:,:) = ssh n(:,:) - 0.5 * ( ssh_ib(:,:) + ssh_ibb(:,:) )79 ELSE ; ssh_m(:,:) = ssh n(:,:)80 ENDIF 81 ! 82 e3t_m(:,:) = e3t _n(:,:,1)75 IF( ln_apr_dyn ) THEN ; ssh_m(:,:) = ssh(:,:,Kmm) - 0.5 * ( ssh_ib(:,:) + ssh_ibb(:,:) ) 76 ELSE ; ssh_m(:,:) = ssh(:,:,Kmm) 77 ENDIF 78 ! 79 e3t_m(:,:) = e3t(:,:,1,Kmm) 83 80 ! 84 81 frq_m(:,:) = fraqsr_1lev(:,:) … … 92 89 IF(lwp) WRITE(numout,*) '~~~~~~~ ' 93 90 zcoef = REAL( nn_fsbc - 1, wp ) 94 ssu_m(:,:) = zcoef * u b(:,:,1)95 ssv_m(:,:) = zcoef * v b(:,:,1)91 ssu_m(:,:) = zcoef * uu(:,:,1,Kbb) 92 ssv_m(:,:) = zcoef * vv(:,:,1,Kbb) 96 93 IF( l_useCT ) THEN ; sst_m(:,:) = zcoef * eos_pt_from_ct( zts(:,:,jp_tem), zts(:,:,jp_sal) ) 97 94 ELSE ; sst_m(:,:) = zcoef * zts(:,:,jp_tem) … … 99 96 sss_m(:,:) = zcoef * zts(:,:,jp_sal) 100 97 ! ! removed inverse barometer ssh when Patm forcing is used (for sea-ice dynamics) 101 IF( ln_apr_dyn ) THEN ; ssh_m(:,:) = zcoef * ( ssh n(:,:) - 0.5 * ( ssh_ib(:,:) + ssh_ibb(:,:) ) )102 ELSE ; ssh_m(:,:) = zcoef * sshn(:,:)103 ENDIF 104 ! 105 e3t_m(:,:) = zcoef * e3t _n(:,:,1)98 IF( ln_apr_dyn ) THEN ; ssh_m(:,:) = zcoef * ( ssh(:,:,Kmm) - 0.5 * ( ssh_ib(:,:) + ssh_ibb(:,:) ) ) 99 ELSE ; ssh_m(:,:) = zcoef * ssh(:,:,Kmm) 100 ENDIF 101 ! 102 e3t_m(:,:) = zcoef * e3t(:,:,1,Kmm) 106 103 ! 107 104 frq_m(:,:) = zcoef * fraqsr_1lev(:,:) … … 120 117 ! ! Cumulate at each time step ! 121 118 ! ! ---------------------------------------- ! 122 ssu_m(:,:) = ssu_m(:,:) + u b(:,:,1)123 ssv_m(:,:) = ssv_m(:,:) + v b(:,:,1)119 ssu_m(:,:) = ssu_m(:,:) + uu(:,:,1,Kbb) 120 ssv_m(:,:) = ssv_m(:,:) + vv(:,:,1,Kbb) 124 121 IF( l_useCT ) THEN ; sst_m(:,:) = sst_m(:,:) + eos_pt_from_ct( zts(:,:,jp_tem), zts(:,:,jp_sal) ) 125 122 ELSE ; sst_m(:,:) = sst_m(:,:) + zts(:,:,jp_tem) … … 127 124 sss_m(:,:) = sss_m(:,:) + zts(:,:,jp_sal) 128 125 ! ! removed inverse barometer ssh when Patm forcing is used (for sea-ice dynamics) 129 IF( ln_apr_dyn ) THEN ; ssh_m(:,:) = ssh_m(:,:) + ssh n(:,:) - 0.5 * ( ssh_ib(:,:) + ssh_ibb(:,:) )130 ELSE ; ssh_m(:,:) = ssh_m(:,:) + ssh n(:,:)131 ENDIF 132 ! 133 e3t_m(:,:) = e3t_m(:,:) + e3t _n(:,:,1)126 IF( ln_apr_dyn ) THEN ; ssh_m(:,:) = ssh_m(:,:) + ssh(:,:,Kmm) - 0.5 * ( ssh_ib(:,:) + ssh_ibb(:,:) ) 127 ELSE ; ssh_m(:,:) = ssh_m(:,:) + ssh(:,:,Kmm) 128 ENDIF 129 ! 130 e3t_m(:,:) = e3t_m(:,:) + e3t(:,:,1,Kmm) 134 131 ! 135 132 frq_m(:,:) = frq_m(:,:) + fraqsr_1lev(:,:) … … 184 181 185 182 186 SUBROUTINE sbc_ssm_init 183 SUBROUTINE sbc_ssm_init( Kbb, Kmm ) 187 184 !!---------------------------------------------------------------------- 188 185 !! *** ROUTINE sbc_ssm_init *** … … 192 189 !! ** Action : - read parameters 193 190 !!---------------------------------------------------------------------- 191 INTEGER, INTENT(in) :: Kbb, Kmm ! ocean time level indices 194 192 REAL(wp) :: zcoef, zf_sbc ! local scalar 195 193 !!---------------------------------------------------------------------- … … 242 240 ! 243 241 IF(lwp) WRITE(numout,*) ' default initialisation of ss._m arrays' 244 ssu_m(:,:) = u b(:,:,1)245 ssv_m(:,:) = v b(:,:,1)246 IF( l_useCT ) THEN ; sst_m(:,:) = eos_pt_from_ct( ts n(:,:,1,jp_tem), tsn(:,:,1,jp_sal) )247 ELSE ; sst_m(:,:) = ts n(:,:,1,jp_tem)248 ENDIF 249 sss_m(:,:) = ts n (:,:,1,jp_sal)250 ssh_m(:,:) = ssh n (:,:)251 e3t_m(:,:) = e3t _n(:,:,1)242 ssu_m(:,:) = uu(:,:,1,Kbb) 243 ssv_m(:,:) = vv(:,:,1,Kbb) 244 IF( l_useCT ) THEN ; sst_m(:,:) = eos_pt_from_ct( ts(:,:,1,jp_tem,Kmm), ts(:,:,1,jp_sal,Kmm) ) 245 ELSE ; sst_m(:,:) = ts(:,:,1,jp_tem,Kmm) 246 ENDIF 247 sss_m(:,:) = ts (:,:,1,jp_sal,Kmm) 248 ssh_m(:,:) = ssh(:,:,Kmm) 249 e3t_m(:,:) = e3t (:,:,1,Kmm) 252 250 frq_m(:,:) = 1._wp 253 251 ! -
NEMO/trunk/src/OCE/SBC/sbcssr.F90
r12276 r12377 49 49 TYPE(FLD), ALLOCATABLE, DIMENSION(:) :: sf_sss ! structure of input SSS (file informations, fields read) 50 50 51 !! * Substitutions 52 # include "do_loop_substitute.h90" 51 53 !!---------------------------------------------------------------------- 52 54 !! NEMO/OCE 4.0 , NEMO Consortium (2018) … … 93 95 ! 94 96 IF( nn_sstr == 1 ) THEN !* Temperature restoring term 95 DO jj = 1, jpj 96 DO ji = 1, jpi 97 zqrp = rn_dqdt * ( sst_m(ji,jj) - sf_sst(1)%fnow(ji,jj,1) ) * tmask(ji,jj,1) 98 qns(ji,jj) = qns(ji,jj) + zqrp 99 qrp(ji,jj) = zqrp 100 END DO 101 END DO 97 DO_2D_11_11 98 zqrp = rn_dqdt * ( sst_m(ji,jj) - sf_sst(1)%fnow(ji,jj,1) ) * tmask(ji,jj,1) 99 qns(ji,jj) = qns(ji,jj) + zqrp 100 qrp(ji,jj) = zqrp 101 END_2D 102 102 ENDIF 103 103 ! … … 105 105 ! use fraction of ice ( fr_i ) to adjust relaxation under ice if nn_sssr_ice .ne. 1 106 106 ! n.b. coefice is initialised and fixed to 1._wp if nn_sssr_ice = 1 107 DO jj = 1, jpj 108 DO ji = 1, jpi 109 SELECT CASE ( nn_sssr_ice ) 110 CASE ( 0 ) ; coefice(ji,jj) = 1._wp - fr_i(ji,jj) ! no/reduced damping under ice 111 CASE DEFAULT ; coefice(ji,jj) = 1._wp + ( nn_sssr_ice - 1 ) * fr_i(ji,jj) ! reinforced damping (x nn_sssr_ice) under ice ) 112 END SELECT 113 END DO 114 END DO 107 DO_2D_11_11 108 SELECT CASE ( nn_sssr_ice ) 109 CASE ( 0 ) ; coefice(ji,jj) = 1._wp - fr_i(ji,jj) ! no/reduced damping under ice 110 CASE DEFAULT ; coefice(ji,jj) = 1._wp + ( nn_sssr_ice - 1 ) * fr_i(ji,jj) ! reinforced damping (x nn_sssr_ice) under ice ) 111 END SELECT 112 END_2D 115 113 ENDIF 116 114 ! 117 115 IF( nn_sssr == 1 ) THEN !* Salinity damping term (salt flux only (sfx)) 118 116 zsrp = rn_deds / rday ! from [mm/day] to [kg/m2/s] 119 DO jj = 1, jpj 120 DO ji = 1, jpi 121 zerp = zsrp * ( 1. - 2.*rnfmsk(ji,jj) ) & ! No damping in vicinity of river mouths 122 & * coefice(ji,jj) & ! Optional control of damping under sea-ice 123 & * ( sss_m(ji,jj) - sf_sss(1)%fnow(ji,jj,1) ) * tmask(ji,jj,1) 124 sfx(ji,jj) = sfx(ji,jj) + zerp ! salt flux 125 erp(ji,jj) = zerp / MAX( sss_m(ji,jj), 1.e-20 ) ! converted into an equivalent volume flux (diagnostic only) 126 END DO 127 END DO 117 DO_2D_11_11 118 zerp = zsrp * ( 1. - 2.*rnfmsk(ji,jj) ) & ! No damping in vicinity of river mouths 119 & * coefice(ji,jj) & ! Optional control of damping under sea-ice 120 & * ( sss_m(ji,jj) - sf_sss(1)%fnow(ji,jj,1) ) * tmask(ji,jj,1) 121 sfx(ji,jj) = sfx(ji,jj) + zerp ! salt flux 122 erp(ji,jj) = zerp / MAX( sss_m(ji,jj), 1.e-20 ) ! converted into an equivalent volume flux (diagnostic only) 123 END_2D 128 124 ! 129 125 ELSEIF( nn_sssr == 2 ) THEN !* Salinity damping term (volume flux (emp) and associated heat flux (qns) 130 126 zsrp = rn_deds / rday ! from [mm/day] to [kg/m2/s] 131 127 zerp_bnd = rn_sssr_bnd / rday ! - - 132 DO jj = 1, jpj 133 DO ji = 1, jpi 134 zerp = zsrp * ( 1. - 2.*rnfmsk(ji,jj) ) & ! No damping in vicinity of river mouths 135 & * coefice(ji,jj) & ! Optional control of damping under sea-ice 136 & * ( sss_m(ji,jj) - sf_sss(1)%fnow(ji,jj,1) ) & 137 & / MAX( sss_m(ji,jj), 1.e-20 ) * tmask(ji,jj,1) 138 IF( ln_sssr_bnd ) zerp = SIGN( 1., zerp ) * MIN( zerp_bnd, ABS(zerp) ) 139 emp(ji,jj) = emp (ji,jj) + zerp 140 qns(ji,jj) = qns(ji,jj) - zerp * rcp * sst_m(ji,jj) 141 erp(ji,jj) = zerp 142 END DO 143 END DO 128 DO_2D_11_11 129 zerp = zsrp * ( 1. - 2.*rnfmsk(ji,jj) ) & ! No damping in vicinity of river mouths 130 & * coefice(ji,jj) & ! Optional control of damping under sea-ice 131 & * ( sss_m(ji,jj) - sf_sss(1)%fnow(ji,jj,1) ) & 132 & / MAX( sss_m(ji,jj), 1.e-20 ) * tmask(ji,jj,1) 133 IF( ln_sssr_bnd ) zerp = SIGN( 1., zerp ) * MIN( zerp_bnd, ABS(zerp) ) 134 emp(ji,jj) = emp (ji,jj) + zerp 135 qns(ji,jj) = qns(ji,jj) - zerp * rcp * sst_m(ji,jj) 136 erp(ji,jj) = zerp 137 END_2D 144 138 ENDIF 145 139 ! … … 180 174 ENDIF 181 175 ! 182 REWIND( numnam_ref ) ! Namelist namsbc_ssr in reference namelist :183 176 READ ( numnam_ref, namsbc_ssr, IOSTAT = ios, ERR = 901) 184 177 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namsbc_ssr in reference namelist' ) 185 178 186 REWIND( numnam_cfg ) ! Namelist namsbc_ssr in configuration namelist :187 179 READ ( numnam_cfg, namsbc_ssr, IOSTAT = ios, ERR = 902 ) 188 180 902 IF( ios > 0 ) CALL ctl_nam ( ios , 'namsbc_ssr in configuration namelist' ) -
NEMO/trunk/src/OCE/SBC/sbcwave.F90
r11536 r12377 72 72 73 73 !! * Substitutions 74 # include " vectopt_loop_substitute.h90"74 # include "do_loop_substitute.h90" 75 75 !!---------------------------------------------------------------------- 76 76 !! NEMO/OCE 4.0 , NEMO Consortium (2018) … … 80 80 CONTAINS 81 81 82 SUBROUTINE sbc_stokes( )82 SUBROUTINE sbc_stokes( Kmm ) 83 83 !!--------------------------------------------------------------------- 84 84 !! *** ROUTINE sbc_stokes *** … … 92 92 !! ** action 93 93 !!--------------------------------------------------------------------- 94 INTEGER, INTENT(in) :: Kmm ! ocean time level index 94 95 INTEGER :: jj, ji, jk ! dummy loop argument 95 96 INTEGER :: ik ! local integer … … 111 112 IF( ll_st_bv_li ) THEN ! (Eq. (19) in Breivik et al. (2014) ) 112 113 zfac = 2.0_wp * rpi / 16.0_wp 113 DO jj = 1, jpj 114 DO ji = 1, jpi 115 ! Stokes drift velocity estimated from Hs and Tmean 116 ztransp = zfac * hsw(ji,jj)*hsw(ji,jj) / MAX( wmp(ji,jj), 0.0000001_wp ) 117 ! Stokes surface speed 118 tsd2d(ji,jj) = SQRT( ut0sd(ji,jj)*ut0sd(ji,jj) + vt0sd(ji,jj)*vt0sd(ji,jj)) 119 ! Wavenumber scale 120 zk_t(ji,jj) = ABS( tsd2d(ji,jj) ) / MAX( ABS( 5.97_wp*ztransp ), 0.0000001_wp ) 121 END DO 122 END DO 123 DO jj = 1, jpjm1 ! exp. wave number & Stokes drift velocity at u- & v-points 124 DO ji = 1, jpim1 125 zk_u(ji,jj) = 0.5_wp * ( zk_t(ji,jj) + zk_t(ji+1,jj) ) 126 zk_v(ji,jj) = 0.5_wp * ( zk_t(ji,jj) + zk_t(ji,jj+1) ) 127 ! 128 zu0_sd(ji,jj) = 0.5_wp * ( ut0sd(ji,jj) + ut0sd(ji+1,jj) ) 129 zv0_sd(ji,jj) = 0.5_wp * ( vt0sd(ji,jj) + vt0sd(ji,jj+1) ) 130 END DO 131 END DO 114 DO_2D_11_11 115 ! Stokes drift velocity estimated from Hs and Tmean 116 ztransp = zfac * hsw(ji,jj)*hsw(ji,jj) / MAX( wmp(ji,jj), 0.0000001_wp ) 117 ! Stokes surface speed 118 tsd2d(ji,jj) = SQRT( ut0sd(ji,jj)*ut0sd(ji,jj) + vt0sd(ji,jj)*vt0sd(ji,jj)) 119 ! Wavenumber scale 120 zk_t(ji,jj) = ABS( tsd2d(ji,jj) ) / MAX( ABS( 5.97_wp*ztransp ), 0.0000001_wp ) 121 END_2D 122 DO_2D_10_10 123 zk_u(ji,jj) = 0.5_wp * ( zk_t(ji,jj) + zk_t(ji+1,jj) ) 124 zk_v(ji,jj) = 0.5_wp * ( zk_t(ji,jj) + zk_t(ji,jj+1) ) 125 ! 126 zu0_sd(ji,jj) = 0.5_wp * ( ut0sd(ji,jj) + ut0sd(ji+1,jj) ) 127 zv0_sd(ji,jj) = 0.5_wp * ( vt0sd(ji,jj) + vt0sd(ji,jj+1) ) 128 END_2D 132 129 ELSE IF( ll_st_peakfr ) THEN ! peak wave number calculated from the peak frequency received by the wave model 133 DO jj = 1, jpj 134 DO ji = 1, jpi 135 zk_t(ji,jj) = ( 2.0_wp * rpi * wfreq(ji,jj) ) * ( 2.0_wp * rpi * wfreq(ji,jj) ) / grav 136 END DO 137 END DO 138 DO jj = 1, jpjm1 139 DO ji = 1, jpim1 140 zk_u(ji,jj) = 0.5_wp * ( zk_t(ji,jj) + zk_t(ji+1,jj) ) 141 zk_v(ji,jj) = 0.5_wp * ( zk_t(ji,jj) + zk_t(ji,jj+1) ) 142 ! 143 zu0_sd(ji,jj) = 0.5_wp * ( ut0sd(ji,jj) + ut0sd(ji+1,jj) ) 144 zv0_sd(ji,jj) = 0.5_wp * ( vt0sd(ji,jj) + vt0sd(ji,jj+1) ) 145 END DO 146 END DO 130 DO_2D_11_11 131 zk_t(ji,jj) = ( 2.0_wp * rpi * wfreq(ji,jj) ) * ( 2.0_wp * rpi * wfreq(ji,jj) ) / grav 132 END_2D 133 DO_2D_10_10 134 zk_u(ji,jj) = 0.5_wp * ( zk_t(ji,jj) + zk_t(ji+1,jj) ) 135 zk_v(ji,jj) = 0.5_wp * ( zk_t(ji,jj) + zk_t(ji,jj+1) ) 136 ! 137 zu0_sd(ji,jj) = 0.5_wp * ( ut0sd(ji,jj) + ut0sd(ji+1,jj) ) 138 zv0_sd(ji,jj) = 0.5_wp * ( vt0sd(ji,jj) + vt0sd(ji,jj+1) ) 139 END_2D 147 140 ENDIF 148 141 ! 149 142 ! !== horizontal Stokes Drift 3D velocity ==! 150 143 IF( ll_st_bv2014 ) THEN 151 DO jk = 1, jpkm1 152 DO jj = 2, jpjm1 153 DO ji = 2, jpim1 154 zdep_u = 0.5_wp * ( gdept_n(ji,jj,jk) + gdept_n(ji+1,jj,jk) ) 155 zdep_v = 0.5_wp * ( gdept_n(ji,jj,jk) + gdept_n(ji,jj+1,jk) ) 156 ! 157 zkh_u = zk_u(ji,jj) * zdep_u ! k * depth 158 zkh_v = zk_v(ji,jj) * zdep_v 159 ! ! Depth attenuation 160 zda_u = EXP( -2.0_wp*zkh_u ) / ( 1.0_wp + 8.0_wp*zkh_u ) 161 zda_v = EXP( -2.0_wp*zkh_v ) / ( 1.0_wp + 8.0_wp*zkh_v ) 162 ! 163 usd(ji,jj,jk) = zda_u * zu0_sd(ji,jj) * umask(ji,jj,jk) 164 vsd(ji,jj,jk) = zda_v * zv0_sd(ji,jj) * vmask(ji,jj,jk) 165 END DO 166 END DO 167 END DO 144 DO_3D_00_00( 1, jpkm1 ) 145 zdep_u = 0.5_wp * ( gdept(ji,jj,jk,Kmm) + gdept(ji+1,jj,jk,Kmm) ) 146 zdep_v = 0.5_wp * ( gdept(ji,jj,jk,Kmm) + gdept(ji,jj+1,jk,Kmm) ) 147 ! 148 zkh_u = zk_u(ji,jj) * zdep_u ! k * depth 149 zkh_v = zk_v(ji,jj) * zdep_v 150 ! ! Depth attenuation 151 zda_u = EXP( -2.0_wp*zkh_u ) / ( 1.0_wp + 8.0_wp*zkh_u ) 152 zda_v = EXP( -2.0_wp*zkh_v ) / ( 1.0_wp + 8.0_wp*zkh_v ) 153 ! 154 usd(ji,jj,jk) = zda_u * zu0_sd(ji,jj) * umask(ji,jj,jk) 155 vsd(ji,jj,jk) = zda_v * zv0_sd(ji,jj) * vmask(ji,jj,jk) 156 END_3D 168 157 ELSE IF( ll_st_li2017 .OR. ll_st_peakfr ) THEN 169 158 ALLOCATE( zstokes_psi_u_top(jpi,jpj), zstokes_psi_v_top(jpi,jpj) ) 170 DO jj = 1, jpjm1 ! exp. wave number & Stokes drift velocity at u- & v-points 171 DO ji = 1, jpim1 172 zstokes_psi_u_top(ji,jj) = 0._wp 173 zstokes_psi_v_top(ji,jj) = 0._wp 174 END DO 175 END DO 159 DO_2D_10_10 160 zstokes_psi_u_top(ji,jj) = 0._wp 161 zstokes_psi_v_top(ji,jj) = 0._wp 162 END_2D 176 163 zsqrtpi = SQRT(rpi) 177 164 z_two_thirds = 2.0_wp / 3.0_wp 178 DO jk = 1, jpkm1 179 DO jj = 2, jpjm1 180 DO ji = 2, jpim1 181 zbot_u = ( gdepw_n(ji,jj,jk+1) + gdepw_n(ji+1,jj,jk+1) ) ! 2 * bottom depth 182 zbot_v = ( gdepw_n(ji,jj,jk+1) + gdepw_n(ji,jj+1,jk+1) ) ! 2 * bottom depth 183 zkb_u = zk_u(ji,jj) * zbot_u ! 2 * k * bottom depth 184 zkb_v = zk_v(ji,jj) * zbot_v ! 2 * k * bottom depth 185 ! 186 zke3_u = MAX(1.e-8_wp, 2.0_wp * zk_u(ji,jj) * e3u_n(ji,jj,jk)) ! 2k * thickness 187 zke3_v = MAX(1.e-8_wp, 2.0_wp * zk_v(ji,jj) * e3v_n(ji,jj,jk)) ! 2k * thickness 188 189 ! Depth attenuation .... do u component first.. 190 zdepth = zkb_u 191 zsqrt_depth = SQRT(zdepth) 192 zexp_depth = EXP(-zdepth) 193 zstokes_psi_u_bot = 1.0_wp - zexp_depth & 194 & - z_two_thirds * ( zsqrtpi*zsqrt_depth*zdepth*ERFC(zsqrt_depth) & 195 & + 1.0_wp - (1.0_wp + zdepth)*zexp_depth ) 196 zda_u = ( zstokes_psi_u_bot - zstokes_psi_u_top(ji,jj) ) / zke3_u 197 zstokes_psi_u_top(ji,jj) = zstokes_psi_u_bot 198 199 ! ... and then v component 200 zdepth =zkb_v 201 zsqrt_depth = SQRT(zdepth) 202 zexp_depth = EXP(-zdepth) 203 zstokes_psi_v_bot = 1.0_wp - zexp_depth & 204 & - z_two_thirds * ( zsqrtpi*zsqrt_depth*zdepth*ERFC(zsqrt_depth) & 205 & + 1.0_wp - (1.0_wp + zdepth)*zexp_depth ) 206 zda_v = ( zstokes_psi_v_bot - zstokes_psi_v_top(ji,jj) ) / zke3_v 207 zstokes_psi_v_top(ji,jj) = zstokes_psi_v_bot 208 ! 209 usd(ji,jj,jk) = zda_u * zu0_sd(ji,jj) * umask(ji,jj,jk) 210 vsd(ji,jj,jk) = zda_v * zv0_sd(ji,jj) * vmask(ji,jj,jk) 211 END DO 212 END DO 213 END DO 165 DO_3D_00_00( 1, jpkm1 ) 166 zbot_u = ( gdepw(ji,jj,jk+1,Kmm) + gdepw(ji+1,jj,jk+1,Kmm) ) ! 2 * bottom depth 167 zbot_v = ( gdepw(ji,jj,jk+1,Kmm) + gdepw(ji,jj+1,jk+1,Kmm) ) ! 2 * bottom depth 168 zkb_u = zk_u(ji,jj) * zbot_u ! 2 * k * bottom depth 169 zkb_v = zk_v(ji,jj) * zbot_v ! 2 * k * bottom depth 170 ! 171 zke3_u = MAX(1.e-8_wp, 2.0_wp * zk_u(ji,jj) * e3u(ji,jj,jk,Kmm)) ! 2k * thickness 172 zke3_v = MAX(1.e-8_wp, 2.0_wp * zk_v(ji,jj) * e3v(ji,jj,jk,Kmm)) ! 2k * thickness 173 174 ! Depth attenuation .... do u component first.. 175 zdepth = zkb_u 176 zsqrt_depth = SQRT(zdepth) 177 zexp_depth = EXP(-zdepth) 178 zstokes_psi_u_bot = 1.0_wp - zexp_depth & 179 & - z_two_thirds * ( zsqrtpi*zsqrt_depth*zdepth*ERFC(zsqrt_depth) & 180 & + 1.0_wp - (1.0_wp + zdepth)*zexp_depth ) 181 zda_u = ( zstokes_psi_u_bot - zstokes_psi_u_top(ji,jj) ) / zke3_u 182 zstokes_psi_u_top(ji,jj) = zstokes_psi_u_bot 183 184 ! ... and then v component 185 zdepth =zkb_v 186 zsqrt_depth = SQRT(zdepth) 187 zexp_depth = EXP(-zdepth) 188 zstokes_psi_v_bot = 1.0_wp - zexp_depth & 189 & - z_two_thirds * ( zsqrtpi*zsqrt_depth*zdepth*ERFC(zsqrt_depth) & 190 & + 1.0_wp - (1.0_wp + zdepth)*zexp_depth ) 191 zda_v = ( zstokes_psi_v_bot - zstokes_psi_v_top(ji,jj) ) / zke3_v 192 zstokes_psi_v_top(ji,jj) = zstokes_psi_v_bot 193 ! 194 usd(ji,jj,jk) = zda_u * zu0_sd(ji,jj) * umask(ji,jj,jk) 195 vsd(ji,jj,jk) = zda_v * zv0_sd(ji,jj) * vmask(ji,jj,jk) 196 END_3D 214 197 DEALLOCATE( zstokes_psi_u_top, zstokes_psi_v_top ) 215 198 ENDIF … … 220 203 ! !== vertical Stokes Drift 3D velocity ==! 221 204 ! 222 DO jk = 1, jpkm1 ! Horizontal e3*divergence 223 DO jj = 2, jpj 224 DO ji = fs_2, jpi 225 ze3divh(ji,jj,jk) = ( e2u(ji ,jj) * e3u_n(ji ,jj,jk) * usd(ji ,jj,jk) & 226 & - e2u(ji-1,jj) * e3u_n(ji-1,jj,jk) * usd(ji-1,jj,jk) & 227 & + e1v(ji,jj ) * e3v_n(ji,jj ,jk) * vsd(ji,jj ,jk) & 228 & - e1v(ji,jj-1) * e3v_n(ji,jj-1,jk) * vsd(ji,jj-1,jk) ) * r1_e1e2t(ji,jj) 229 END DO 230 END DO 231 END DO 205 DO_3D_01_01( 1, jpkm1 ) 206 ze3divh(ji,jj,jk) = ( e2u(ji ,jj) * e3u(ji ,jj,jk,Kmm) * usd(ji ,jj,jk) & 207 & - e2u(ji-1,jj) * e3u(ji-1,jj,jk,Kmm) * usd(ji-1,jj,jk) & 208 & + e1v(ji,jj ) * e3v(ji,jj ,jk,Kmm) * vsd(ji,jj ,jk) & 209 & - e1v(ji,jj-1) * e3v(ji,jj-1,jk,Kmm) * vsd(ji,jj-1,jk) ) * r1_e1e2t(ji,jj) 210 END_3D 232 211 ! 233 212 #if defined key_agrif … … 291 270 ! 292 271 IF( ln_tauw ) THEN 293 DO jj = 1, jpjm1 294 DO ji = 1, jpim1 295 ! Stress components at u- & v-points 296 utau(ji,jj) = 0.5_wp * ( tauw_x(ji,jj) + tauw_x(ji+1,jj) ) 297 vtau(ji,jj) = 0.5_wp * ( tauw_y(ji,jj) + tauw_y(ji,jj+1) ) 298 ! 299 ! Stress module at t points 300 taum(ji,jj) = SQRT( tauw_x(ji,jj)*tauw_x(ji,jj) + tauw_y(ji,jj)*tauw_y(ji,jj) ) 301 END DO 302 END DO 272 DO_2D_10_10 273 ! Stress components at u- & v-points 274 utau(ji,jj) = 0.5_wp * ( tauw_x(ji,jj) + tauw_x(ji+1,jj) ) 275 vtau(ji,jj) = 0.5_wp * ( tauw_y(ji,jj) + tauw_y(ji,jj+1) ) 276 ! 277 ! Stress module at t points 278 taum(ji,jj) = SQRT( tauw_x(ji,jj)*tauw_x(ji,jj) + tauw_y(ji,jj)*tauw_y(ji,jj) ) 279 END_2D 303 280 CALL lbc_lnk_multi( 'sbcwave', utau(:,:), 'U', -1. , vtau(:,:), 'V', -1. , taum(:,:) , 'T', -1. ) 304 281 ENDIF … … 307 284 308 285 309 SUBROUTINE sbc_wave( kt )286 SUBROUTINE sbc_wave( kt, Kmm ) 310 287 !!--------------------------------------------------------------------- 311 288 !! *** ROUTINE sbc_wave *** … … 322 299 !!--------------------------------------------------------------------- 323 300 INTEGER, INTENT(in ) :: kt ! ocean time step 301 INTEGER, INTENT(in ) :: Kmm ! ocean time index 324 302 !!--------------------------------------------------------------------- 325 303 ! … … 361 339 ! 362 340 IF( ( ll_st_bv_li .AND. jp_hsw>0 .AND. jp_wmp>0 .AND. jp_usd>0 .AND. jp_vsd>0 ) .OR. & 363 & ( ll_st_peakfr .AND. jp_wfr>0 .AND. jp_usd>0 .AND. jp_vsd>0 ) ) CALL sbc_stokes( )341 & ( ll_st_peakfr .AND. jp_wfr>0 .AND. jp_usd>0 .AND. jp_vsd>0 ) ) CALL sbc_stokes( Kmm ) 364 342 ! 365 343 ENDIF … … 395 373 !!--------------------------------------------------------------------- 396 374 ! 397 REWIND( numnam_ref ) ! Namelist namsbc_wave in reference namelist : File for drag coeff. from wave model398 375 READ ( numnam_ref, namsbc_wave, IOSTAT = ios, ERR = 901) 399 376 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namsbc_wave in reference namelist' ) 400 377 401 REWIND( numnam_cfg ) ! Namelist namsbc_wave in configuration namelist : File for drag coeff. from wave model402 378 READ ( numnam_cfg, namsbc_wave, IOSTAT = ios, ERR = 902 ) 403 379 902 IF( ios > 0 ) CALL ctl_nam ( ios , 'namsbc_wave in configuration namelist' )
Note: See TracChangeset
for help on using the changeset viewer.