PageRenderTime 52ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/wrfv2_fire/main/tc_em.F

http://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 2511 lines | 1520 code | 536 blank | 455 comment | 14 complexity | 5d3ed3c30a17c3508bb29322dec4b194 MD5 | raw file
Possible License(s): AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. ! Create an initial data set for the WRF model based on real data. This
  2. ! program is specifically set up for the Eulerian, mass-based coordinate.
  3. PROGRAM tc_data
  4. USE module_machine
  5. USE module_domain, ONLY : domain, alloc_and_configure_domain, &
  6. domain_clock_set, head_grid, program_name, domain_clockprint, &
  7. set_current_grid_ptr
  8. USE module_io_domain
  9. USE module_initialize_real, ONLY : wrfu_initialize
  10. USE module_driver_constants
  11. USE module_configure, ONLY : grid_config_rec_type, model_config_rec, &
  12. initial_config, get_config_as_buffer, set_config_as_buffer
  13. USE module_timing
  14. USE module_state_description, ONLY: tconly
  15. #ifdef DM_PARALLEL
  16. USE module_dm, ONLY: wrf_dm_initialize
  17. #endif
  18. #ifdef NO_LEAP_CALENDAR
  19. USE module_symbols_util, ONLY: wrfu_cal_noleap
  20. #else
  21. USE module_symbols_util, ONLY: wrfu_cal_gregorian
  22. #endif
  23. USE module_utility, ONLY : WRFU_finalize
  24. IMPLICIT NONE
  25. REAL :: time , bdyfrq
  26. INTEGER :: loop , levels_to_process , debug_level
  27. TYPE(domain) , POINTER :: null_domain
  28. TYPE(domain) , POINTER :: grid , another_grid
  29. TYPE(domain) , POINTER :: grid_ptr , grid_ptr2
  30. TYPE (grid_config_rec_type) :: config_flags
  31. INTEGER :: number_at_same_level
  32. INTEGER :: max_dom, domain_id , grid_id , parent_id , parent_id1 , id
  33. INTEGER :: e_we , e_sn , i_parent_start , j_parent_start
  34. INTEGER :: idum1, idum2
  35. #ifdef DM_PARALLEL
  36. INTEGER :: nbytes
  37. INTEGER, PARAMETER :: configbuflen = 4* CONFIG_BUF_LEN
  38. INTEGER :: configbuf( configbuflen )
  39. LOGICAL , EXTERNAL :: wrf_dm_on_monitor
  40. #endif
  41. LOGICAL found_the_id
  42. INTEGER :: ids , ide , jds , jde , kds , kde
  43. INTEGER :: ims , ime , jms , jme , kms , kme
  44. INTEGER :: ips , ipe , jps , jpe , kps , kpe
  45. INTEGER :: ijds , ijde , spec_bdy_width
  46. INTEGER :: i , j , k , idts, rc
  47. INTEGER :: sibling_count , parent_id_hold , dom_loop
  48. CHARACTER (LEN=80) :: message
  49. INTEGER :: start_year , start_month , start_day , start_hour , start_minute , start_second
  50. INTEGER :: end_year , end_month , end_day , end_hour , end_minute , end_second
  51. INTEGER :: interval_seconds , real_data_init_type
  52. INTEGER :: time_loop_max , time_loop, bogus_id, storm
  53. real::t1,t2
  54. real :: latc_loc(max_bogus),lonc_loc(max_bogus),vmax(max_bogus),rmax(max_bogus)
  55. real :: rankine_lid
  56. INTERFACE
  57. SUBROUTINE Setup_Timekeeping( grid )
  58. USE module_domain, ONLY : domain
  59. TYPE(domain), POINTER :: grid
  60. END SUBROUTINE Setup_Timekeeping
  61. END INTERFACE
  62. #include "version_decl"
  63. ! Define the name of this program (program_name defined in module_domain)
  64. program_name = "TC_EM " // TRIM(release_version) // " PREPROCESSOR"
  65. ! The TC bogus algorithm assumes that the user defines a central point, and then
  66. ! allows the program to remove a typhoon based on a distance in km. This is
  67. ! implemented on a single processor only.
  68. #ifdef DM_PARALLEL
  69. IF ( .NOT. wrf_dm_on_monitor() ) THEN
  70. CALL wrf_error_fatal( 'TC bogus must run with a single processor only, re-run with num procs set to 1' )
  71. END IF
  72. #endif
  73. #ifdef DM_PARALLEL
  74. CALL disable_quilting
  75. #endif
  76. ! Initialize the modules used by the WRF system. Many of the CALLs made from the
  77. ! init_modules routine are NO-OPs. Typical initializations are: the size of a
  78. ! REAL, setting the file handles to a pre-use value, defining moisture and
  79. ! chemistry indices, etc.
  80. CALL wrf_debug ( 100 , 'real_em: calling init_modules ' )
  81. CALL init_modules(1) ! Phase 1 returns after MPI_INIT() (if it is called)
  82. #ifdef NO_LEAP_CALENDAR
  83. CALL WRFU_Initialize( defaultCalKind=WRFU_CAL_NOLEAP, rc=rc )
  84. #else
  85. CALL WRFU_Initialize( defaultCalKind=WRFU_CAL_GREGORIAN, rc=rc )
  86. #endif
  87. CALL init_modules(2) ! Phase 2 resumes after MPI_INIT() (if it is called)
  88. ! The configuration switches mostly come from the NAMELIST input.
  89. #ifdef DM_PARALLEL
  90. IF ( wrf_dm_on_monitor() ) THEN
  91. CALL initial_config
  92. END IF
  93. CALL get_config_as_buffer( configbuf, configbuflen, nbytes )
  94. CALL wrf_dm_bcast_bytes( configbuf, nbytes )
  95. CALL set_config_as_buffer( configbuf, configbuflen )
  96. CALL wrf_dm_initialize
  97. #else
  98. CALL initial_config
  99. #endif
  100. CALL nl_get_debug_level ( 1, debug_level )
  101. CALL set_wrf_debug_level ( debug_level )
  102. CALL wrf_message ( program_name )
  103. ! There are variables in the Registry that are only required for the real
  104. ! program, fields that come from the WPS package. We define the run-time
  105. ! flag that says to allocate space for these input-from-WPS-only arrays.
  106. CALL nl_set_use_wps_input ( 1 , TCONLY )
  107. ! Allocate the space for the mother of all domains.
  108. NULLIFY( null_domain )
  109. CALL wrf_debug ( 100 , 'real_em: calling alloc_and_configure_domain ' )
  110. CALL alloc_and_configure_domain ( domain_id = 1 , &
  111. grid = head_grid , &
  112. parent = null_domain , &
  113. kid = -1 )
  114. grid => head_grid
  115. CALL nl_get_max_dom ( 1 , max_dom )
  116. IF ( model_config_rec%interval_seconds .LE. 0 ) THEN
  117. CALL wrf_error_fatal( 'namelist value for interval_seconds must be > 0')
  118. END IF
  119. all_domains : DO domain_id = 1 , max_dom
  120. IF ( ( model_config_rec%input_from_file(domain_id) ) .OR. &
  121. ( domain_id .EQ. 1 ) ) THEN
  122. CALL Setup_Timekeeping ( grid )
  123. CALL set_current_grid_ptr( grid )
  124. CALL domain_clockprint ( 150, grid, &
  125. 'DEBUG real: clock after Setup_Timekeeping,' )
  126. CALL domain_clock_set( grid, &
  127. time_step_seconds=model_config_rec%interval_seconds )
  128. CALL domain_clockprint ( 150, grid, &
  129. 'DEBUG real: clock after timeStep set,' )
  130. CALL wrf_debug ( 100 , 'tc_em: calling set_scalar_indices_from_config ' )
  131. CALL set_scalar_indices_from_config ( grid%id , idum1, idum2 )
  132. !This is goofy but we need to loop through the number of storms to get
  133. !the namelist variables for the tc_bogus. But then we need to
  134. !call model_to_grid_config_rec with the grid%id = to 1 in order to
  135. !reset to the correct information.
  136. CALL wrf_debug ( 100 , 'tc_em: calling model_to_grid_config_rec ' )
  137. lonc_loc(:) = -999.
  138. latc_loc(:) = -999.
  139. vmax(:) = -999.
  140. rmax(:) = -999.
  141. CALL model_to_grid_config_rec ( grid%id , model_config_rec , config_flags )
  142. lonc_loc(1) = config_flags%lonc_loc
  143. latc_loc(1) = config_flags%latc_loc
  144. vmax(1) = config_flags%vmax_meters_per_second
  145. rmax(1) = config_flags%rmax
  146. rankine_lid = config_flags%rankine_lid
  147. do storm = 2,config_flags%num_storm
  148. bogus_id = storm
  149. CALL model_to_grid_config_rec ( bogus_id , model_config_rec , config_flags )
  150. lonc_loc(storm) = config_flags%lonc_loc
  151. latc_loc(storm) = config_flags%latc_loc
  152. vmax(storm) = config_flags%vmax_meters_per_second
  153. rmax(storm) = config_flags%rmax
  154. ! print *,"in loop ",storm,lonc_loc(storm),latc_loc(storm),vmax(storm),rmax(storm)
  155. end do
  156. CALL model_to_grid_config_rec ( grid%id , model_config_rec , config_flags )
  157. ! Initialize the WRF IO: open files, init file handles, etc.
  158. CALL wrf_debug ( 100 , 'tc_em: calling init_wrfio' )
  159. CALL init_wrfio
  160. ! Some of the configuration values may have been modified from the initial READ
  161. ! of the NAMELIST, so we re-broadcast the configuration records.
  162. #ifdef DM_PARALLEL
  163. CALL wrf_debug ( 100 , 'tc_em: re-broadcast the configuration records' )
  164. CALL get_config_as_buffer( configbuf, configbuflen, nbytes )
  165. CALL wrf_dm_bcast_bytes( configbuf, nbytes )
  166. CALL set_config_as_buffer( configbuf, configbuflen )
  167. #endif
  168. ! No looping in this layer.
  169. CALL wrf_debug ( 100 , 'calling tc_med_sidata_input' )
  170. CALL tc_med_sidata_input ( grid , config_flags, latc_loc, lonc_loc, &
  171. vmax,rmax,rankine_lid)
  172. CALL wrf_debug ( 100 , 'backfrom tc_med_sidata_input' )
  173. ELSE
  174. CYCLE all_domains
  175. END IF
  176. END DO all_domains
  177. CALL set_current_grid_ptr( head_grid )
  178. ! We are done.
  179. CALL wrf_debug ( 0 , 'tc_em: SUCCESS COMPLETE TC BOGUS' )
  180. CALL wrf_shutdown
  181. CALL WRFU_Finalize( rc=rc )
  182. END PROGRAM tc_data
  183. !-----------------------------------------------------------------
  184. SUBROUTINE tc_med_sidata_input ( grid , config_flags, latc_loc, lonc_loc, &
  185. vmax, rmax,rankine_lid)
  186. ! Driver layer
  187. USE module_domain
  188. USE module_io_domain
  189. ! Model layer
  190. USE module_configure
  191. USE module_bc_time_utilities
  192. USE module_optional_input
  193. USE module_date_time
  194. USE module_utility
  195. IMPLICIT NONE
  196. ! Interface
  197. INTERFACE
  198. SUBROUTINE start_domain ( grid , allowed_to_read ) ! comes from module_start in appropriate dyn_ directory
  199. USE module_domain
  200. TYPE (domain) grid
  201. LOGICAL, INTENT(IN) :: allowed_to_read
  202. END SUBROUTINE start_domain
  203. END INTERFACE
  204. ! Arguments
  205. TYPE(domain) :: grid
  206. TYPE (grid_config_rec_type) :: config_flags
  207. ! Local
  208. INTEGER :: time_step_begin_restart
  209. INTEGER :: idsi , ierr , myproc, internal_time_loop,iflag
  210. ! Declarations for the netcdf routines.
  211. INTEGER ::nf_inq
  212. !
  213. CHARACTER (LEN=80) :: si_inpname
  214. CHARACTER (LEN=80) :: message
  215. CHARACTER(LEN=19) :: start_date_char , end_date_char , current_date_char , next_date_char
  216. CHARACTER(LEN=8) :: flag_name
  217. INTEGER :: time_loop_max , loop, rc,icnt,itmp
  218. INTEGER :: julyr , julday ,metndims, metnvars, metngatts, nunlimdimid,rcode
  219. REAL :: gmt
  220. real :: t1,t2,t3,t4
  221. real :: latc_loc(max_bogus), lonc_loc(max_bogus)
  222. real :: vmax(max_bogus),rmax(max_bogus),rankine_lid
  223. grid%input_from_file = .true.
  224. grid%input_from_file = .false.
  225. CALL tc_compute_si_start ( model_config_rec%start_year (grid%id) , &
  226. model_config_rec%start_month (grid%id) , &
  227. model_config_rec%start_day (grid%id) , &
  228. model_config_rec%start_hour (grid%id) , &
  229. model_config_rec%start_minute(grid%id) , &
  230. model_config_rec%start_second(grid%id) , &
  231. model_config_rec%interval_seconds , &
  232. model_config_rec%real_data_init_type , &
  233. start_date_char)
  234. end_date_char = start_date_char
  235. IF ( end_date_char .LT. start_date_char ) THEN
  236. CALL wrf_error_fatal( 'Ending date in namelist ' // end_date_char // ' prior to beginning date ' // start_date_char )
  237. END IF
  238. print *,"the start date char ",start_date_char
  239. print *,"the end date char ",end_date_char
  240. time_loop_max = 1
  241. ! Override stop time with value computed above.
  242. CALL domain_clock_set( grid, stop_timestr=end_date_char )
  243. ! TBH: for now, turn off stop time and let it run data-driven
  244. CALL WRFU_ClockStopTimeDisable( grid%domain_clock, rc=rc )
  245. CALL wrf_check_error( WRFU_SUCCESS, rc, &
  246. 'WRFU_ClockStopTimeDisable(grid%domain_clock) FAILED', &
  247. __FILE__ , &
  248. __LINE__ )
  249. CALL domain_clockprint ( 150, grid, &
  250. 'DEBUG med_sidata_input: clock after stopTime set,' )
  251. ! Here we define the initial time to process, for later use by the code.
  252. current_date_char = start_date_char
  253. start_date = start_date_char // '.0000'
  254. current_date = start_date
  255. CALL nl_set_bdyfrq ( grid%id , REAL(model_config_rec%interval_seconds) )
  256. CALL cpu_time ( t1 )
  257. DO loop = 1 , time_loop_max
  258. internal_time_loop = loop
  259. IF ( ( grid%id .GT. 1 ) .AND. ( loop .GT. 1 ) .AND. &
  260. ( model_config_rec%grid_fdda(grid%id) .EQ. 0 ) .AND. &
  261. ( model_config_rec%sst_update .EQ. 0 ) ) EXIT
  262. print *,' '
  263. print *,'-----------------------------------------------------------------------------'
  264. print *,' '
  265. print '(A,I2,A,A,A,I4,A,I4)' , &
  266. ' Domain ',grid%id,': Current date being processed: ',current_date, ', which is loop #',loop,' out of ',time_loop_max
  267. ! After current_date has been set, fill in the julgmt stuff.
  268. CALL geth_julgmt ( config_flags%julyr , config_flags%julday , config_flags%gmt )
  269. print *,'configflags%julyr, %julday, %gmt:',config_flags%julyr, config_flags%julday, config_flags%gmt
  270. ! Now that the specific Julian info is available, save these in the model config record.
  271. CALL nl_set_gmt (grid%id, config_flags%gmt)
  272. CALL nl_set_julyr (grid%id, config_flags%julyr)
  273. CALL nl_set_julday (grid%id, config_flags%julday)
  274. ! Open the input file for tc stuff. Either the "new" one or the "old" one. The "new" one could have
  275. ! a suffix for the type of the data format. Check to see if either is around.
  276. CALL cpu_time ( t3 )
  277. WRITE ( wrf_err_message , FMT='(A,A)' )'med_sidata_input: calling open_r_dataset for ', &
  278. TRIM(config_flags%auxinput1_inname)
  279. CALL wrf_debug ( 100 , wrf_err_message )
  280. IF ( config_flags%auxinput1_inname(1:8) .NE. 'wrf_real' ) THEN
  281. CALL construct_filename4a( si_inpname , config_flags%auxinput1_inname , grid%id , 2 , &
  282. current_date_char , config_flags%io_form_auxinput1 )
  283. ELSE
  284. CALL construct_filename2a( si_inpname , config_flags%auxinput1_inname , grid%id , 2 , &
  285. current_date_char )
  286. END IF
  287. CALL open_r_dataset ( idsi, TRIM(si_inpname) , grid , config_flags , "DATASET=AUXINPUT1", ierr )
  288. IF ( ierr .NE. 0 ) THEN
  289. CALL wrf_error_fatal( 'error opening ' // TRIM(si_inpname) // &
  290. ' for input; bad date in namelist or file not in directory' )
  291. END IF
  292. ! Input data.
  293. CALL wrf_debug ( 100 , 'med_sidata_input: calling input_auxinput1' )
  294. CALL input_auxinput1 ( idsi , grid , config_flags , ierr )
  295. WRITE ( wrf_err_message , FMT='(A,I10,A)' ) 'Timing for input ',NINT(t4-t3) ,' s.'
  296. CALL wrf_debug( 0, wrf_err_message )
  297. ! Possible optional SI input. This sets flags used by init_domain.
  298. CALL cpu_time ( t3 )
  299. CALL wrf_debug ( 100 , 'med_sidata_input: calling init_module_optional_input' )
  300. CALL init_module_optional_input ( grid , config_flags )
  301. CALL wrf_debug ( 100 , 'med_sidata_input: calling optional_input' )
  302. CALL optional_input ( grid , idsi , config_flags )
  303. !Here we check the flags yet again. The flags are checked in optional_input but
  304. !the grid% flags are not set.
  305. flag_name(1:8) = 'SM000010'
  306. CALL wrf_get_dom_ti_integer ( idsi, 'FLAG_' // flag_name, itmp, 1, icnt, ierr )
  307. IF ( ierr .EQ. 0 ) THEN
  308. grid%flag_sm000010 = 1
  309. end if
  310. flag_name(1:8) = 'SM010040'
  311. CALL wrf_get_dom_ti_integer ( idsi, 'FLAG_' // flag_name, itmp, 1, icnt, ierr )
  312. IF ( ierr .EQ. 0 ) THEN
  313. grid%flag_sm010040 = 1
  314. end if
  315. flag_name(1:8) = 'SM040100'
  316. CALL wrf_get_dom_ti_integer ( idsi, 'FLAG_' // flag_name, itmp, 1, icnt, ierr )
  317. IF ( ierr .EQ. 0 ) THEN
  318. grid%flag_sm040100 = itmp
  319. end if
  320. flag_name(1:8) = 'SM100200'
  321. CALL wrf_get_dom_ti_integer ( idsi, 'FLAG_' // flag_name, itmp, 1, icnt, ierr )
  322. IF ( ierr .EQ. 0 ) THEN
  323. grid%flag_sm100200 = itmp
  324. end if
  325. ! flag_name(1:8) = 'SM010200'
  326. ! CALL wrf_get_dom_ti_integer ( idsi, 'FLAG_' // flag_name, itmp, 1, icnt, ierr )
  327. ! IF ( ierr .EQ. 0 ) THEN
  328. ! config_flags%flag_sm010200 = itmp
  329. ! print *,"found the flag_sm010200 "
  330. ! end if
  331. !Now the soil temperature flags
  332. flag_name(1:8) = 'ST000010'
  333. CALL wrf_get_dom_ti_integer ( idsi, 'FLAG_' // flag_name, itmp, 1, icnt, ierr )
  334. IF ( ierr .EQ. 0 ) THEN
  335. grid%flag_st000010 = 1
  336. END IF
  337. flag_name(1:8) = 'ST010040'
  338. CALL wrf_get_dom_ti_integer ( idsi, 'FLAG_' // flag_name, itmp, 1, icnt, ierr )
  339. IF ( ierr .EQ. 0 ) THEN
  340. grid%flag_st010040 = 1
  341. END IF
  342. flag_name(1:8) = 'ST040100'
  343. CALL wrf_get_dom_ti_integer ( idsi, 'FLAG_' // flag_name, itmp, 1, icnt, ierr )
  344. IF ( ierr .EQ. 0 ) THEN
  345. grid%flag_st040100 = 1
  346. END IF
  347. flag_name(1:8) = 'ST100200'
  348. CALL wrf_get_dom_ti_integer ( idsi, 'FLAG_' // flag_name, itmp, 1, icnt, ierr )
  349. IF ( ierr .EQ. 0 ) THEN
  350. grid%flag_st100200 = 1
  351. END IF
  352. CALL wrf_get_dom_ti_integer ( idsi, 'FLAG_SOIL_LAYERS', itmp, 1, icnt, ierr )
  353. IF ( ierr .EQ. 0 ) THEN
  354. grid%flag_soil_layers = 1
  355. END IF
  356. CALL close_dataset ( idsi , config_flags , "DATASET=AUXINPUT1" )
  357. CALL cpu_time ( t4 )
  358. ! Possible optional SI input. This sets flags used by init_domain.
  359. ! We need to call the optional input routines to get the flags that
  360. ! are in the metgrid output file so they can be put in the tc bogus
  361. ! output file for real to read.
  362. CALL cpu_time ( t3 )
  363. already_been_here = .FALSE.
  364. CALL model_to_grid_config_rec ( grid%id , model_config_rec , config_flags )
  365. CALL cpu_time ( t3 )
  366. CALL assemble_output ( grid , config_flags , loop , time_loop_max, current_date_char, &
  367. latc_loc, lonc_loc, vmax, rmax, rankine_lid,si_inpname)
  368. CALL cpu_time ( t4 )
  369. WRITE ( wrf_err_message , FMT='(A,I10,A)' ) 'Timing for output ',NINT(t4-t3) ,' s.'
  370. CALL wrf_debug( 0, wrf_err_message )
  371. CALL cpu_time ( t2 )
  372. WRITE ( wrf_err_message , FMT='(A,I4,A,I10,A)' ) 'Timing for loop # ',loop,' = ',NINT(t2-t1) ,' s.'
  373. CALL wrf_debug( 0, wrf_err_message )
  374. CALL cpu_time ( t1 )
  375. END DO
  376. END SUBROUTINE tc_med_sidata_input
  377. !-------------------------------------------------------------------------------------
  378. SUBROUTINE tc_compute_si_start( &
  379. start_year , start_month , start_day , start_hour , start_minute , start_second , &
  380. interval_seconds , real_data_init_type , &
  381. start_date_char)
  382. USE module_date_time
  383. IMPLICIT NONE
  384. INTEGER :: start_year , start_month , start_day , start_hour , start_minute , start_second
  385. INTEGER :: end_year , end_month , end_day , end_hour , end_minute , end_second
  386. INTEGER :: interval_seconds , real_data_init_type
  387. INTEGER :: time_loop_max , time_loop
  388. CHARACTER(LEN=19) :: current_date_char , start_date_char , end_date_char , next_date_char
  389. #ifdef PLANET
  390. WRITE ( start_date_char , FMT = '(I4.4,"-",I5.5,"_",I2.2,":",I2.2,":",I2.2)' ) &
  391. start_year,start_day,start_hour,start_minute,start_second
  392. #else
  393. WRITE ( start_date_char , FMT = '(I4.4,"-",I2.2,"-",I2.2,"_",I2.2,":",I2.2,":",I2.2)' ) &
  394. start_year,start_month,start_day,start_hour,start_minute,start_second
  395. #endif
  396. END SUBROUTINE tc_compute_si_start
  397. !-----------------------------------------------------------------------
  398. SUBROUTINE assemble_output ( grid , config_flags , loop , time_loop_max,current_date_char, &
  399. latc_loc, lonc_loc,vmax,rmax,rankine_lid,si_inpname)
  400. USE module_big_step_utilities_em
  401. USE module_domain
  402. USE module_io_domain
  403. USE module_configure
  404. USE module_date_time
  405. USE module_bc
  406. IMPLICIT NONE
  407. TYPE(domain) :: grid
  408. TYPE (grid_config_rec_type) :: config_flags
  409. INTEGER , INTENT(IN) :: loop , time_loop_max
  410. !These values are in the name list and are avaiable from
  411. !from the config_flags.
  412. real :: vmax(max_bogus),vmax_ratio,rankine_lid
  413. real :: rmax(max_bogus),stand_lon,cen_lat,ptop_in_pa
  414. real :: latc_loc(max_bogus),lonc_loc(max_bogus)
  415. INTEGER :: ijds , ijde , spec_bdy_width
  416. INTEGER :: i , j , k , idts,map_proj,remove_only,storms
  417. INTEGER :: id1 , interval_seconds , ierr, rc, sst_update, grid_fdda
  418. INTEGER , SAVE :: id, id2, id4
  419. CHARACTER (LEN=80) :: tcoutname , bdyname,si_inpname
  420. CHARACTER(LEN= 4) :: loop_char
  421. CHARACTER(LEN=19) :: current_date_char
  422. character *19 :: temp19
  423. character *24 :: temp24 , temp24b
  424. real::t1,t2,truelat1,truelat2
  425. ! Boundary width, scalar value.
  426. spec_bdy_width = model_config_rec%spec_bdy_width
  427. interval_seconds = model_config_rec%interval_seconds
  428. sst_update = model_config_rec%sst_update
  429. grid_fdda = model_config_rec%grid_fdda(grid%id)
  430. truelat1 = config_flags%truelat1
  431. truelat2 = config_flags%truelat2
  432. stand_lon = config_flags%stand_lon
  433. cen_lat = config_flags%cen_lat
  434. map_proj = config_flags%map_proj
  435. vmax_ratio = config_flags%vmax_ratio
  436. ptop_in_pa = config_flags%p_top_requested
  437. remove_only = 0
  438. if(config_flags%remove_storm) then
  439. remove_only = 1
  440. end if
  441. storms = config_flags%num_storm
  442. print *,"number of storms ",config_flags%num_storm
  443. call tc_bogus(cen_lat,stand_lon,map_proj,truelat1,truelat2, &
  444. grid%dx,grid%e_we,grid%e_sn,grid%num_metgrid_levels,ptop_in_pa, &
  445. rankine_lid,latc_loc,lonc_loc,vmax,vmax_ratio,rmax,remove_only, &
  446. storms,grid)
  447. ! Open the tc bogused output file. cd
  448. CALL construct_filename4a( tcoutname , config_flags%auxinput1_outname , grid%id , 2 , &
  449. current_date_char , config_flags%io_form_auxinput1 )
  450. print *,"outfile name from construct filename ",tcoutname
  451. CALL open_w_dataset ( id1, TRIM(tcoutname) , grid , config_flags ,output_auxinput1,"DATASET=AUXINPUT1",ierr )
  452. IF ( ierr .NE. 0 ) THEN
  453. CALL wrf_error_fatal( 'tc_em: error opening tc bogus file for writing' )
  454. END IF
  455. CALL output_auxinput1( id1, grid , config_flags , ierr )
  456. CALL close_dataset ( id1 , config_flags , "DATASET=AUXINPUT1" )
  457. END SUBROUTINE assemble_output
  458. !----------------------------------------------------------------------------------------------
  459. SUBROUTINE tc_bogus(centerlat,stdlon,nproj,truelat1,truelat2,dsm,ew,ns,nz,ptop_in_pa, &
  460. rankine_lid,latc_loc,lonc_loc,vmax,vmax_ratio,rmax,remove_only, &
  461. storms,grid)
  462. !!Original Author Dave Gill. Modified by Sherrie Fredrick
  463. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  464. !These are read in from the netcdf file.
  465. !centerlat The center latitude from the global attributes in the netcdf file.
  466. !stdlon The center longitude from the global attributes in the netcdf file.
  467. !nproj The map projection from the global attributes in the netcdf file.
  468. !dsm The spacing in meters from the global attributes in the netcdf file.
  469. !ew The west_east_stag from the dimensions in the netcdf file..
  470. !ns The south_north_stag from the dimensions in the netcdf file. .
  471. !nz The number of metgrid levels from the dimensions in the netcdf file.
  472. !ptop_in_pa This is part of the namelist.input file under the &domains section.
  473. !These values are part of the namelist.input file under the &tc section specifically
  474. !for the tc bogus code.
  475. !NOTES: There can be up to five bogus storms. The variable max_bogus is set in
  476. !the WRF subroutine called module_driver_constants.F in the ./WRFV3/frame directory.
  477. !latc_loc The center latitude of the bogus strorm. This is an array dimensioned max_bogus.
  478. !lonc_loc The center longitude of the bogus strorm. This is an array dimensioned max_bogus.
  479. !vmax The max vortex in meters/second it comes from the namelist entry.
  480. ! This is an array dimensioned max_bogus.
  481. !vmax_ratio This comes from the namelist entry.
  482. !rmax The maximum radius this comes from the namelist entry.
  483. ! This is an array dimensioned max_bogus
  484. !remove_only If this is set to true in the namelist.input file a value of 0.1
  485. ! is automatically assigned to vmax.
  486. !rankine_lid This comes from the namelist entry. It can be used to determine
  487. ! what model levels the bogus storm affects.
  488. !storms The number of bogus storms.
  489. !grid This is a Fortran structure which holds all of the field data values
  490. ! for the netcdf that was read in.
  491. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  492. !module_llxy resides in the share directory.
  493. USE module_llxy
  494. !This is for the large structure (grid)
  495. USE module_domain
  496. IMPLICIT NONE
  497. TYPE(domain) :: grid
  498. integer ew,ns,nz
  499. integer nproj
  500. integer storms,nstrm
  501. real :: centerlat,stdlon,conef,truelat1,truelat2,dsm,dx,rankine_lid
  502. real :: latc_loc(max_bogus),lonc_loc(max_bogus),vmax(max_bogus),vmax_ratio,rmax(max_bogus)
  503. real :: press(ew-1,nz,ns-1),rhmx(nz), vwgt(nz),old_slp(ew-1,ns-1)
  504. real, dimension(:,:,:) , allocatable :: u11,v11,t11,rh11,phi11
  505. real, dimension(:,:,:) , allocatable :: u1 , v1 , t1 , rh1 , phi1
  506. real, dimension(ew-1,ns-1) :: lond,terrain,cor,pslx
  507. !The map scale factors.
  508. real, dimension(ew,ns-1) :: msfu !The mapscale factor for the ew wind staggered grid
  509. real, dimension(ew-1,ns) :: msfv !The mapscale factor for the ns wind staggered grid
  510. real, dimension(ew-1,ns-1) :: msfm !The mapscale factor for the unstaggered grid.
  511. CHARACTER*2 jproj
  512. LOGICAL :: l_tcbogus
  513. real :: r_search,r_vor,beta,devps,humidity_max
  514. real :: devpc,const,r_vor2,cnst,alphar,epsilon,vormx , rad , sum_q
  515. real :: avg_q ,q_old,ror,q_new,dph,dphx0
  516. real :: rh_max,min_RH_value,ps
  517. integer :: vert_variation
  518. integer :: i,k,j,kx,remove_only
  519. integer :: k00,kfrm ,kto ,k85,n_iter,ew_mvc,ns_mvc,nct,itr
  520. integer :: strmci(nz), strmcj(nz)
  521. real :: disx,disy,alpha,degran,pie,rovcp,cp
  522. REAL :: rho,pprm,phip0,x0,y0,vmx,xico,xjco,xicn,xjcn,p85,xlo,rconst,ew_gcntr,ns_gcntr
  523. real :: ptop_in_pa,themax,themin
  524. real :: latinc,loninc
  525. real :: rtemp,colat0,colat
  526. REAL :: q1(ew-1,nz,ns-1), psi1(ew-1,nz,ns-1)
  527. ! This is the entire map projection enchilada.
  528. TYPE(proj_info) :: proj
  529. REAL :: lat1 , lon1
  530. ! These values are read in from the data set.
  531. real :: knowni,knownj
  532. ! TC bogus
  533. REAL utcr(ew,nz,ns-1), vtcr(ew-1,nz,ns)
  534. REAL utcp(ew,nz,ns-1), vtcp(ew-1,nz,ns)
  535. REAL psitc(ew-1,nz,ns-1), psiv(nz)
  536. REAL vortc(ew-1,nz,ns-1), vorv(nz)
  537. REAL tptc(ew-1,nz,ns-1)
  538. REAL phiptc(ew-1,nz,ns-1)
  539. ! Work arrays
  540. REAL uuwork(nz), vvwork(nz), temp2(ew,ns)
  541. REAL vort(ew-1,nz,ns-1), div(ew-1,nz,ns-1)
  542. REAL vortsv(ew-1,nz,ns-1)
  543. REAL theta(ew-1,nz,ns-1), t_reduce(ew-1,nz,ns-1)
  544. REAL ug(ew,nz,ns-1), vg(ew-1,nz,ns), vorg(ew-1,nz,ns-1)
  545. REAL delpx(ew-1,ns-1)
  546. !subroutines for relaxation
  547. REAL outold(ew-1,ns-1)
  548. REAL rd(ew-1,ns-1), ff(ew-1,ns-1)
  549. REAL tmp1(ew-1,ns-1), tmp2(ew-1,ns-1)
  550. ! Background fields.
  551. REAL , DIMENSION (ew-1,nz,ns-1) :: t0, t00, rh0, q0, phi0, psi0, chi
  552. ! Perturbations
  553. REAL , DIMENSION (ew-1,nz,ns-1) :: psipos, tpos, psi ,phipos, phip
  554. ! Final fields.
  555. REAL u2(ew,nz,ns-1), v2(ew-1,nz,ns)
  556. REAL t2(ew-1,nz,ns-1),z2(ew-1,nz,ns-1)
  557. REAL phi2(ew-1,nz,ns-1),rh2(ew-1,nz,ns-1)
  558. print *,"the dimensions: north-south = ",ns," east-west =",ew
  559. IF (nproj .EQ. 1) THEN
  560. jproj = 'LC'
  561. print *,"Lambert Conformal projection"
  562. ELSE IF (nproj .EQ. 2) THEN
  563. jproj = 'ST'
  564. ELSE IF (nproj .EQ. 3) THEN
  565. jproj = 'ME'
  566. print *,"A mercator projection"
  567. END IF
  568. knowni = 1.
  569. knownj = 1.
  570. pie = 3.141592653589793
  571. degran = pie/180.
  572. rconst = 287.04
  573. min_RH_value = 5.0
  574. cp = 1004.0
  575. rovcp = rconst/cp
  576. r_search = 400000.0
  577. r_vor = 300000.0
  578. r_vor2 = r_vor * 4
  579. beta = 0.5
  580. devpc= 40.0
  581. vert_variation = 1
  582. humidity_max = 95.0
  583. alphar = 1.8
  584. latinc = -999.
  585. loninc = -999.
  586. if(remove_only .eq. 1) then
  587. do nstrm=1,storms
  588. vmax(nstrm) = 0.1
  589. end do
  590. end if
  591. ! Set up initializations for map projection so that the lat/lon
  592. ! of the tropical storm can be put into model (i,j) space. This needs to be done once per
  593. ! map projection definition. Since this is the domain that we are "GOING TO", it is a once
  594. ! per regridder requirement. If the user somehow ends up calling this routine for several
  595. ! time periods, there is no problemos, just a bit of overhead with redundant calls.
  596. dx = dsm
  597. lat1 = grid%xlat_gc(1,1)
  598. lon1 = grid%xlong_gc(1,1)
  599. IF( jproj .EQ. 'ME' )THEN
  600. IF ( lon1 .LT. -180. ) lon1 = lon1 + 360.
  601. IF ( lon1 .GT. 180. ) lon1 = lon1 - 360.
  602. IF ( stdlon .LT. -180. ) stdlon = stdlon + 360.
  603. IF ( stdlon .GT. 180. ) stdlon = stdlon - 360.
  604. CALL map_set ( proj_merc, proj, lat1, lon1, lat1, lon1, knowni, knownj, dx, &
  605. latinc,loninc,stdlon , truelat1 , truelat2)
  606. conef = 0.
  607. ELSE IF ( jproj .EQ. 'LC' ) THEN
  608. if((truelat1 .eq. 0.0) .and. (truelat2 .eq. 0.0)) then
  609. print *,"Truelat1 and Truelat2 are both 0"
  610. stop
  611. end if
  612. CALL map_set (proj_lc,proj, lat1, lon1, lat1, lon1, knowni, knownj, dx, &
  613. latinc,loninc,stdlon , truelat1 , truelat2)
  614. conef = proj%cone
  615. ELSE IF ( jproj .EQ. 'ST' ) THEN
  616. conef = 1.
  617. CALL map_set ( proj_ps,proj,lat1, lon1, lat1, lon1, knowni, knownj, dx, &
  618. latinc,loninc,stdlon , truelat1 , truelat2)
  619. END IF
  620. ! Load the pressure array.
  621. kx = nz
  622. do j = 1,ns-1
  623. do k = 1,nz
  624. do i = 1,ew-1
  625. press(i,k,j) = grid%p_gc(i,k,j)*0.01
  626. end do
  627. end do
  628. end do
  629. ! Initialize the vertical profiles for humidity and weighting.
  630. !The ptop variable will be read in from the namelist
  631. IF ( ( ptop_in_pa .EQ. 40000. ) .OR. ( ptop_in_pa .EQ. 60000. ) ) THEN
  632. PRINT '(A)','Hold on pardner, your value for PTOP is gonna cause problems for the TC bogus option.'
  633. PRINT '(A)','Make it higher up than 400 mb.'
  634. STOP 'ptop_woes_for_tc_bogus'
  635. END IF
  636. IF ( vert_variation .EQ. 1 ) THEN
  637. DO k=1,kx
  638. IF ( press(1,k,1) .GT. 400. ) THEN
  639. rhmx(k) = humidity_max
  640. ELSE
  641. rhmx(k) = humidity_max * MAX( 0.1 , (press(1,k,1) - ptop_in_pa/100.)/(400.-ptop_in_pa/100.) )
  642. END IF
  643. IF ( press(1,k,1) .GT. 600. ) THEN
  644. vwgt(k) = 1.0
  645. ELSE IF ( press(1,k,1) .LE. 100. ) THEN
  646. vwgt(k) = 0.0001
  647. ELSE
  648. vwgt(k) = MAX ( 0.0001 , (press(1,k,1)-ptop_in_pa/100.)/(600.-ptop_in_pa/100.) )
  649. END IF
  650. END DO
  651. ELSE IF ( vert_variation .EQ. 2 ) THEN
  652. IF ( kx .eq. 24 ) THEN
  653. rhmx = (/ 95., 95., 95., 95., 95., 95., 95., 95., &
  654. 95., 95., 95., 95., 95., 90., 85., 80., 75., &
  655. 70., 66., 60., 39., 10., 10., 10./)
  656. vwgt = (/ 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 0.9850, &
  657. 0.9680, 0.9500, 0.9290, 0.9060, 0.8810, 0.8500, 0.7580, 0.6500, 0.5100, &
  658. 0.3500, 0.2120, 0.0500, 0.0270, 0.0001, 0.0001, 0.0001/)
  659. ELSE
  660. PRINT '(A)','Number of vertical levels assumed to be 24 for AFWA TC bogus option'
  661. STOP 'AFWA_TC_BOGUS_LEVEL_ERROR'
  662. END IF
  663. END IF
  664. !Remember that ns = the north south staggered. This is one more than the ns mass point grid.
  665. ! ew = the east west staggered. This is one more than the ew mass point grid.
  666. !Put the U and V into the new arrays.
  667. !Remember that the WRF ordering is ew,vert level,ns
  668. !Vorticity and Divergence calculatins are done on
  669. !the staggered grids so the winds are not destaggered
  670. allocate(u11 (1:ew, 1:nz, 1:ns-1))
  671. allocate(u1 (1:ew, 1:nz, 1:ns-1))
  672. allocate(v11 (1:ew-1, 1:nz, 1:ns))
  673. allocate(v1 (1:ew-1, 1:nz, 1:ns))
  674. do j = 1,ns-1
  675. do k = 1,nz
  676. do i = 1,ew
  677. u11(i,k,j) = grid%u_gc(i,k,j)
  678. u1(i,k,j) = grid%u_gc(i,k,j)
  679. msfu(i,j) = grid%msfu(i,j) !map scale factor on the U staggered grid
  680. end do
  681. end do
  682. end do
  683. do j = 1,ns
  684. do k = 1,nz
  685. do i = 1,ew-1
  686. v11(i,k,j) = grid%v_gc(i,k,j)
  687. v1(i,k,j) = grid%v_gc(i,k,j)
  688. msfv(i,j) = grid%msfv(i,j) !map scale factor on the V staggered grid
  689. end do
  690. end do
  691. end do
  692. !Put the temperature, relative humidity and height fields
  693. !into arrays. Save the initial fields also.
  694. !These arrays are on the WRF mass points
  695. allocate(t11 (1:ew-1, 1:nz, 1:ns-1))
  696. allocate(t1 (1:ew-1, 1:nz, 1:ns-1))
  697. allocate(rh11 (1:ew-1, 1:nz, 1:ns-1))
  698. allocate(rh1 (1:ew-1, 1:nz, 1:ns-1))
  699. allocate(phi11(1:ew-1, 1:nz, 1:ns-1))
  700. allocate(phi1 (1:ew-1, 1:nz, 1:ns-1))
  701. do j = 1,ns-1
  702. do k = 1,nz
  703. do i = 1,ew-1
  704. t11(i,k,j) = grid%t_gc(i,k,j)
  705. t1(i,k,j) = grid%t_gc(i,k,j)
  706. rh11(i,k,j) = grid%rh_gc(i,k,j)
  707. rh1(i,k,j) = grid%rh_gc(i,k,j)
  708. msfm(i,j) = grid%msft(i,j)
  709. if(k .eq. 1)then
  710. phi11(i,k,j) = grid%ht_gc(i,j)
  711. phi1(i,k,j) = grid%ht_gc(i,j) * 9.81
  712. else
  713. phi11(i,k,j) = grid%ght_gc(i,k,j)
  714. phi1(i,k,j) = grid%ght_gc(i,k,j) * 9.81
  715. end if
  716. end do
  717. end do
  718. end do
  719. !The two D fields
  720. !The terrain soil height is from ght at level 1
  721. do j = 1,ns-1
  722. do i = 1,ew-1
  723. pslx(i,j) = grid%pslv_gc(i,j) * 0.01
  724. cor(i,j) = grid%f(i,j) !coreolous
  725. lond(i,j) = grid%xlong_gc(i,j)
  726. terrain(i,j) = grid%ht_gc(i,j)
  727. old_slp(i,j) = grid%pslv_gc(i,j)
  728. end do
  729. end do
  730. ! Loop over the number of storms to process.
  731. l_tcbogus = .FALSE.
  732. all_storms : DO nstrm=1,storms
  733. !Make sure the user has defined the rmax variable
  734. if(rmax(nstrm) .eq. -999.) then
  735. print *,"Please enter a value for rmax in the namelist"
  736. stop
  737. end if
  738. k00 = 2
  739. kfrm = k00
  740. p85 = 850.
  741. kto = kfrm
  742. DO k=kfrm+1,kx
  743. IF ( press(1,k,1) .GE. p85 ) THEN
  744. kto = kto + 1
  745. END IF
  746. END DO
  747. k85 = kto
  748. ! Parameters for max wind
  749. rho = 1.2
  750. pprm = devpc*100.
  751. phip0= pprm/rho
  752. !latc_loc and lonc_loc come in from the namelist.
  753. !These x0 and y0 points are relative to the mass points.
  754. CALL latlon_to_ij ( proj , latc_loc(nstrm) , lonc_loc(nstrm) , x0 , y0 )
  755. IF ( ( x0 .LT. 1. ) .OR. ( x0 .GT. REAL(ew-1) ) .OR. &
  756. ( y0 .LT. 1. ) .OR. ( y0 .GT. REAL(ns-1) ) ) THEN
  757. PRINT '(A,I3,A,A,A)',' Storm position is outside the computational domain.'
  758. PRINT '(A,2F6.2,A)' ,' Storm postion: (x,y) = ',x0,y0,'.'
  759. stop
  760. END IF
  761. l_tcbogus = .TRUE.
  762. ! Bogus vortex specifications, vmax (m/s); rmax (m);
  763. vmx = vmax(nstrm) * vmax_ratio
  764. IF ( latc_loc(nstrm) .LT. 0. ) THEN
  765. vmx = -vmx
  766. END IF
  767. IF ( vmax(nstrm) .LE. 0. ) THEN
  768. vmx = SQRT( 2.*(1-beta)*ABS(phip0) )
  769. END IF
  770. ew_gcntr = x0 !ew center grid location
  771. ns_gcntr = y0 !ns center grid location
  772. !For right now we are adding 0.5 to the grid location this
  773. !makes the output of the wrf tc_bogus scheme analogous to the
  774. !ouput of the MM5 tc_bogus scheme.
  775. ew_gcntr = x0 + 0.5
  776. ns_gcntr = y0 + 0.5
  777. n_iter = 1
  778. ! Start computing.
  779. PRINT '(/,A,I3,A,A,A)' ,'---> TC: Processing storm number= ',nstrm
  780. PRINT '(A,F6.2,A,F7.2,A)' ,' Storm center lat= ',latc_loc(nstrm),' lon= ',lonc_loc(nstrm),'.'
  781. PRINT '(A,2F6.2,A)' ,' Storm center grid position (x,y)= ',ew_gcntr,ns_gcntr,'.'
  782. PRINT '(A,F5.2,F9.2,A)' ,' Storm max wind (m/s) and max radius (m)= ',vmx,rmax(nstrm),'.'
  783. PRINT '(A,F5.2,A)' ,' Estimated central press dev (mb)= ',devpc,'.'
  784. ! Initialize storm center to (1,1)
  785. DO k=1,kx
  786. strmci(k) = 1
  787. strmcj(k) = 1
  788. END DO
  789. ! Define complete field of bogus storm
  790. !Note dx is spacing in meters.
  791. !The output arrays from the rankine subroutine vvwork,uuwork,psiv and vorv
  792. !are defined on the WRF mass points.
  793. utcp(:,:,:) = 0.0
  794. vtcp(:,:,:) = 0.0
  795. print *,"nstrm ",rmax(nstrm),ew_gcntr,ns_gcntr
  796. DO j=1,ns-1
  797. DO i=1,ew-1
  798. disx = REAL(i) - ew_gcntr
  799. disy = REAL(j) - ns_gcntr
  800. CALL rankine(disx,disy,dx,kx,vwgt,rmax(nstrm),vmx,uuwork,vvwork,psiv,vorv)
  801. DO k=1,kx
  802. utcp(i,k,j) = uuwork(k)
  803. vtcp(i,k,j) = vvwork(k)
  804. psitc(i,k,j) = psiv(k)
  805. vortc(i,k,j) = vorv(k)
  806. END DO
  807. END DO
  808. END DO
  809. call stagger_rankine_winds(utcp,vtcp,ew,ns,nz)
  810. utcr(:,:,:) = 0.0
  811. vtcr(:,:,:) = 0.0
  812. ! dave Rotate wind to map proj, on the correct staggering
  813. DO j=1,ns-1
  814. DO i=2,ew-1
  815. xlo = stdlon-grid%xlong_u(i,j)
  816. IF ( xlo .GT. 180.)xlo = xlo-360.
  817. IF ( xlo .LT.-180.)xlo = xlo+360.
  818. alpha = xlo*conef*degran*SIGN(1.,centerlat)
  819. DO k=1,kx
  820. utcr(i,k,j) = (vtcp(i-1,k,j)+vtcp(i,k,j)+vtcp(i,k,j+1)+vtcp(i-1,k,j+1))/4 *SIN(alpha)+utcp(i,k,j)*COS(alpha)
  821. if(utcr(i,k,j) .gt. 300.) then
  822. print *,i,k,j,"a very bad value of utcr"
  823. stop
  824. end if
  825. END DO
  826. END DO
  827. END DO
  828. DO j=2,ns-1
  829. DO i=1,ew-1
  830. xlo = stdlon-grid%xlong_v(i,j)
  831. IF ( xlo .GT. 180.)xlo = xlo-360.
  832. IF ( xlo .LT.-180.)xlo = xlo+360.
  833. alpha = xlo*conef*degran*SIGN(1.,centerlat)
  834. DO k=1,kx
  835. vtcr(i,k,j) = vtcp(i,k,j)*COS(alpha)-(utcp(i,k,j-1)+utcp(i+1,k,j-1)+utcp(i+1,k,j)+utcp(i,k,j))/4*SIN(alpha)
  836. if(vtcr(i,k,j) .gt. 300.) then
  837. print *,i,k,j,"a very bad value of vtcr"
  838. stop
  839. end if
  840. END DO
  841. END DO
  842. END DO
  843. !Fill in UTCR's along the left and right side.
  844. do j = 1,ns-1
  845. utcr(1,:,j) = utcr(2,:,j)
  846. utcr(ew,:,j) = utcr(ew-1,:,j)
  847. end do
  848. !Fill in V's along the bottom and top.
  849. do i = 1,ew-1
  850. vtcr(i,:,1) = vtcr(i,:,2)
  851. vtcr(i,:,ns) = vtcr(i,:,ns-1)
  852. end do
  853. ! Compute vorticity of FG. This is the vorticity of the original winds
  854. ! on the staggered grid. The vorticity and divergence are defined at
  855. ! the mass points when done.
  856. CALL vor(u1,v1,msfu,msfv,msfm,ew,ns,kx,dx,vort)
  857. ! Compute divergence of FG
  858. CALL diverg(u1,v1,msfu,msfv,msfm,ew,ns,kx,dx,div)
  859. ! Compute mixing ratio of FG
  860. CALL mxratprs(rh1,t1,press*100.,ew,ns,kx,q1,min_RH_value)
  861. q1(:,1,:) = q1(:,2,:)
  862. ! Compute initial streamfunction - PSI1
  863. vortsv = vort
  864. q0 = q1
  865. ! Solve for streamfunction.
  866. DO k=1,kx
  867. DO j=1,ns-1
  868. DO i=1,ew-1
  869. ff(i,j) = vort(i,k,j)
  870. tmp1(i,j)= 0.0
  871. END DO
  872. END DO
  873. epsilon = 1.E-2
  874. CALL relax(tmp1,ff,rd,ew,ns,dx,epsilon,alphar)
  875. DO j=1,ns-1
  876. DO i=1,ew-1
  877. psi1(i,k,j) = tmp1(i,j)
  878. END DO
  879. END DO
  880. END DO
  881. DO k=1,kx !start of the k loop
  882. IF ( latc_loc(nstrm) .GE. 0. ) THEN
  883. vormx = -1.e10
  884. ELSE
  885. vormx = 1.e10
  886. END IF
  887. ew_mvc = 1
  888. ns_mvc = 1
  889. DO j=1,ns-1
  890. DO i=1,ew-1
  891. rad = SQRT((REAL(i)-ew_gcntr)**2.+(REAL(j)-ns_gcntr)**2.)*dx
  892. IF ( rad .LE. r_search ) THEN
  893. IF ( latc_loc(nstrm) .GE. 0. ) THEN
  894. IF ( vortsv(i,k,j) .GT. vormx ) THEN
  895. vormx = vortsv(i,k,j)
  896. ew_mvc = i
  897. ns_mvc = j
  898. END IF
  899. ELSE IF (latc_loc(nstrm) .LT. 0. ) THEN
  900. IF ( vortsv(i,k,j) .LT. vormx ) THEN
  901. vormx = vortsv(i,k,j)
  902. ew_mvc = i
  903. ns_mvc = j
  904. END IF
  905. END IF
  906. END IF
  907. END DO
  908. END DO
  909. strmci(k) = ew_mvc
  910. strmcj(k) = ns_mvc
  911. DO j=1,ns-1
  912. DO i=1,ew-1
  913. rad = SQRT(REAL((i-ew_mvc)**2.+(j-ns_mvc)**2.))*dx
  914. IF ( rad .GT. r_vor ) THEN
  915. vort(i,k,j) = 0.
  916. div(i,k,j) = 0.
  917. END IF
  918. END DO
  919. END DO
  920. DO itr=1,n_iter
  921. sum_q = 0.
  922. nct = 0
  923. DO j=1,ns-1
  924. DO i=1,ew-1
  925. rad = SQRT(REAL(i-ew_mvc)**2.+REAL(j-ns_mvc)**2.)*dx
  926. IF ( (rad .LT. r_vor2).AND.(rad .GE. 0.8*r_vor2) ) THEN
  927. sum_q = sum_q + q0(i,k,j)
  928. nct = nct + 1
  929. END IF
  930. END DO
  931. END DO
  932. avg_q = sum_q/MAX(REAL(nct),1.)
  933. DO j=1,ns-1
  934. DO i=1,ew-1
  935. q_old = q0(i,k,j)
  936. rad = SQRT(REAL(i-ew_mvc)**2.+REAL(j-ns_mvc)**2.)*dx
  937. IF ( rad .LT. r_vor2 ) THEN
  938. ror = rad/r_vor2
  939. q_new = ((1.-ror)*avg_q) + (ror*q_old)
  940. q0(i,k,j) = q_new
  941. END IF
  942. END DO
  943. END DO
  944. END DO !end of itr loop
  945. END DO !of the k loop
  946. ! Compute divergent wind (chi) at the mass points
  947. DO k=1,kx
  948. DO j=1,ns-1
  949. DO i=1,ew-1
  950. ff(i,j) = div(i,k,j)
  951. tmp1(i,j)= 0.0
  952. END DO
  953. END DO
  954. epsilon = 1.e-2
  955. CALL relax(tmp1,ff,rd,ew,ns,dx,epsilon,alphar)
  956. DO j=1,ns-1
  957. DO i=1,ew-1
  958. chi(i,k,j) = tmp1(i,j)
  959. END DO
  960. END DO
  961. END DO !of the k loop for divergent winds
  962. ! Compute background streamfunction (PSI0) and perturbation field (PSI)
  963. ! print *,"perturbation field (PSI) relax three"
  964. DO k=1,kx
  965. DO j=1,ns-1
  966. DO i=1,ew-1
  967. ff(i,j)=vort(i,k,j)
  968. tmp1(i,j)=0.0
  969. END DO
  970. END DO
  971. epsilon = 1.e-2
  972. CALL relax(tmp1,ff,rd,ew,ns,dx,epsilon,alphar)
  973. DO j=1,ns-1
  974. DO i=1,ew-1
  975. psi(i,k,j)=tmp1(i,j)
  976. END DO
  977. END DO
  978. END DO
  979. !We can now calculate the final wind fields.
  980. call final_ew_velocity(u2,u1,chi,psi,utcr,dx,ew,ns,nz)
  981. call final_ns_velocity(v2,v1,chi,psi,vtcr,dx,ew,ns,nz)
  982. DO k=1,kx
  983. DO j=1,ns-1
  984. DO i=1,ew-1
  985. psi0(i,k,j) = psi1(i,k,j)-psi(i,k,j)
  986. END DO
  987. END DO
  988. END DO
  989. DO k=k00,kx
  990. DO j=1,ns-1
  991. DO i=1,ew-1
  992. psipos(i,k,j)=psi(i,k,j)
  993. END DO
  994. END DO
  995. END DO
  996. ! Geostrophic vorticity.
  997. !We calculate the ug and vg on the wrf U and V staggered grids
  998. !since this is where the vorticity subroutine expects them.
  999. CALL geowind(phi1,ew,ns,kx,dx,ug,vg)
  1000. CALL vor(ug,vg,msfu,msfv,msfm,ew,ns,kx,dx,vorg)
  1001. DO k=1,kx
  1002. ew_mvc = strmci(k)
  1003. ns_mvc = strmcj(k)
  1004. DO j=1,ns-1
  1005. DO i=1,ew-1
  1006. rad = SQRT(REAL(i-ew_mvc)**2.+REAL(j-ns_mvc)**2.)*dx
  1007. IF ( rad .GT. r_vor ) THEN
  1008. vorg(i,k,j) = 0.
  1009. END IF
  1010. END DO
  1011. END DO
  1012. END DO
  1013. DO k=k00,kx
  1014. DO j=1,ns-1
  1015. DO i=1,ew-1
  1016. ff(i,j) = vorg(i,k,j)
  1017. tmp1(i,j)= 0.0
  1018. END DO
  1019. END DO
  1020. epsilon = 1.e-3
  1021. CALL relax(tmp1,ff,rd,ew,ns,dx,epsilon,alphar)
  1022. DO j=1,ns-1
  1023. DO i=1,ew-1
  1024. phip(i,k,j) = tmp1(i,j)
  1025. END DO
  1026. END DO
  1027. END DO
  1028. ! Background geopotential.
  1029. DO k=k00,kx
  1030. DO j=1,ns-1
  1031. DO i=1,ew-1
  1032. phi0(i,k,j) = phi1(i,k,j) - phip(i,k,j)
  1033. END DO
  1034. END DO
  1035. END DO
  1036. ! Background temperature
  1037. DO k=k00,kx
  1038. DO j=1,ns-1
  1039. DO i=1,ew-1
  1040. IF( k .EQ. 2 ) THEN
  1041. tpos(i,k,j) = (-1./rconst)*(phip(i,k+1,j)-phip(i,k,j ))/LOG(press(i,k+1,j)/press(i,k,j))
  1042. ELSE IF ( k .EQ. kx ) THEN
  1043. tpos(i,k,j) = (-1./rconst)*(phip(i,k ,j)-phip(i,k-1,j))/LOG(press(i,k,j )/press(i,k-1,j))
  1044. ELSE
  1045. tpos(i,k,j) = (-1./rconst)*(phip(i,k+1,j)-phip(i,k-1,j))/LOG(press(i,k+1,j)/press(i,k-1,j))
  1046. END IF
  1047. t0(i,k,j) = t1(i,k,j)-tpos(i,k,j)
  1048. t00(i,k,j) = t0(i,k,j)
  1049. if(t0(i,k,j) .gt. 400) then
  1050. print *,"interesting temperature ",t0(i,k,j)," at ",i,j,k
  1051. stop
  1052. end if
  1053. END DO
  1054. END DO
  1055. END DO
  1056. ! New RH.
  1057. CALL qvtorh (q0,t0,press*100.,k00,ew,ns,kx,rh0,min_RH_value)
  1058. call final_RH(rh2,rh0,rhmx,strmci,strmcj,rmax(nstrm),ew,ns,nz,k00,dx,ew_gcntr,ns_gcntr,r_vor2)
  1059. ! adjust T0
  1060. DO k=k00,kx
  1061. DO j=1,ns-1
  1062. DO i=1,ew-1
  1063. theta(i,k,j) = t1(i,k,j)*(1000./press(i,k,j))**rovcp
  1064. END DO
  1065. END DO
  1066. END DO
  1067. ew_mvc = strmci(k00)
  1068. ns_mvc = strmcj(k00)
  1069. DO k=kfrm,kto
  1070. DO j=1,ns-1
  1071. DO i=1,ew-1
  1072. rad = SQRT(REAL(i-ew_mvc)**2.+REAL(j-ns_mvc)**2.)*dx
  1073. IF ( rad .LT. r_vor2 ) THEN
  1074. t_reduce(i,k,j) = theta(i,k85,j)-0.03*(press(i,k,j)-press(i,k85,j))
  1075. t0(i,k,j) = t00(i,k,j)*(rad/r_vor2) + (((press(i,k,j)/1000.)**rovcp)*t_reduce(i,k,j))*(1.-(rad/r_vor2))
  1076. END IF
  1077. END DO
  1078. END DO
  1079. END DO
  1080. ! Geopotential perturbation
  1081. DO k=1,kx
  1082. DO j=1,ns-1
  1083. DO i=1,ew-1
  1084. tmp1(i,j)=psitc(i,k,j)
  1085. END DO
  1086. END DO
  1087. CALL balance(cor,tmp1,ew,ns,dx,outold)
  1088. DO j=1,ns-1
  1089. DO i=1,ew-1
  1090. ff(i,j)=outold(i,j)
  1091. tmp1(i,j)=0.0
  1092. END DO
  1093. END DO
  1094. epsilon = 1.e-3
  1095. CALL relax (tmp1,ff,rd,ew,ns,dx,epsilon,alphar)
  1096. DO j=1,ns-1
  1097. DO i=1,ew-1
  1098. phiptc(i,k,j) = tmp1(i,j)
  1099. END DO
  1100. END DO
  1101. END DO
  1102. ! New geopotential field.
  1103. DO j=1,ns-1
  1104. DO k=1,kx
  1105. DO i=1,ew-1
  1106. phi2(i,k,j) = phi0(i,k,j) + phiptc(i,k,j)
  1107. END DO
  1108. END DO
  1109. END DO
  1110. ! New temperature field.
  1111. DO j=1,ns-1
  1112. DO k=k00,kx
  1113. DO i=1,ew-1
  1114. IF( k .EQ. 2 ) THEN
  1115. tptc(i,k,j)=(-1./rconst)*(phiptc(i,k+1,j)-phiptc(i,k,j ))/LOG(press(i,k+1,j)/press(i,k,j))
  1116. ELSE IF ( k .EQ. kx ) THEN
  1117. tptc(i,k,j)=(-1./rconst)*(phiptc(i,k,j )-phiptc(i,k-1,j))/LOG(press(i,k,j)/press(i,k-1,j))
  1118. ELSE
  1119. tptc(i,k,j)=(-1./rconst)*(phiptc(i,k+1,j)-phiptc(i,k-1,j))/LOG(press(i,k+1,j)/press(i,k-1,j))
  1120. END IF
  1121. t2(i,k,j) = t0(i,k,j) + tptc(i,k,j)
  1122. if(t2(i,k,j) .gt. 400) then
  1123. print *,"interesting temperature "
  1124. print *,t2(i,k,j),i,k,j,tptc(i,k,j)
  1125. stop
  1126. end if
  1127. END DO
  1128. END DO
  1129. END DO
  1130. ! Sea level pressure change.
  1131. DO j=1,ns-1
  1132. DO i=1,ew-1
  1133. dph = phi2(i,k00,j)-phi1(i,k00,j)
  1134. delpx(i,j) = rho*dph*0.01
  1135. END DO
  1136. END DO
  1137. ! New SLP.
  1138. ! print *,"new slp",nstrm
  1139. DO j=1,ns-1
  1140. DO i=1,ew-1
  1141. pslx(i,j) = pslx(i,j)+delpx(i,j)
  1142. grid%pslv_gc(i,j) = pslx(i,j) * 100.
  1143. ! print *,pslx(i,j)
  1144. END DO
  1145. END DO
  1146. ! Set new geopotential at surface to terrain elevation.
  1147. DO j=1,ns-1
  1148. DO i=1,ew-1
  1149. z2(i,1,j) = terrain(i,j)
  1150. END DO
  1151. END DO
  1152. ! Geopotential back to height.
  1153. DO j=1,ns-1
  1154. DO k=k00,kx
  1155. DO i=1,ew-1
  1156. z2(i,k,j) = phi2(i,k,j)/9.81
  1157. END DO
  1158. END DO
  1159. END DO
  1160. ! New surface temperature, assuming same theta as from 1000 mb.
  1161. ! print *,"new surface temperature"
  1162. DO j=1,ns-1
  1163. DO i=1,ew-1
  1164. ps = pslx(i,j)
  1165. t2(i,1,j) = t2(i,k00,j)*((ps/1000.)**rovcp)
  1166. if(t2(i,1,j) .gt. 400) then
  1167. print *,"Interesting surface temperature"
  1168. print *,t2(i,1,j),t2(i,k00,j),ps,i,j
  1169. stop
  1170. end if
  1171. END DO
  1172. END DO
  1173. ! Set surface RH to the value from 1000 mb.
  1174. DO j=1,ns-1
  1175. DO i=1,ew-1
  1176. rh2(i,1,j) = rh2(i,k00,j)
  1177. END DO
  1178. END DO
  1179. ! Modification of tropical storm complete.
  1180. PRINT '(A,I3,A)' ,' Bogus storm number ',nstrm,' completed.'
  1181. do j = 1,ns-1
  1182. do k = 1,nz
  1183. do i = 1,ew
  1184. u1(i,k,j) = u2(i,k,j)
  1185. grid%u_gc(i,k,j) = u2(i,k,j)
  1186. end do
  1187. end do
  1188. end do
  1189. do j = 1,ns
  1190. do k = 1,nz
  1191. do i = 1,ew-1
  1192. v1(i,k,j) = v2(i,k,j)
  1193. grid%v_gc(i,k,j) = v2(i,k,j)
  1194. end do
  1195. end do
  1196. end do
  1197. do j = 1,ns-1
  1198. do k = 1,nz
  1199. do i = 1,ew-1
  1200. t1(i,k,j) = t2(i,k,j)
  1201. grid%t_gc(i,k,j) = t2(i,k,j)
  1202. rh1(i,k,j) = rh2(i,k,j)
  1203. grid%rh_gc(i,k,j) = rh2(i,k,j)
  1204. phi1(i,k,j) = phi2(i,k,j)
  1205. grid%ght_gc(i,k,j) = z2(i,k,j)
  1206. END DO
  1207. END DO
  1208. END DO
  1209. END DO all_storms
  1210. deallocate(u11)
  1211. deallocate(v11)
  1212. deallocate(t11)
  1213. deallocate(rh11)
  1214. deallocate(phi11)
  1215. deallocate(u1)
  1216. deallocate(v1)
  1217. deallocate(t1)
  1218. deallocate(rh1)
  1219. deallocate(phi1)
  1220. do j = 1,ns-1
  1221. do i = 1,ew-1
  1222. if(grid%ht_gc(i,j) .gt. 1) then
  1223. grid%p_gc(i,1,j) = grid%p_gc(i,1,j) + (pslx(i,j) * 100. - old_slp(i,j))
  1224. grid%psfc(i,j) = grid%psfc(i,j) + (pslx(i,j) * 100. - old_slp(i,j))
  1225. else
  1226. grid%p_gc(i,1,j) = pslx(i,j) * 100.
  1227. grid%psfc(i,j) = pslx(i,j) * 100.
  1228. end if
  1229. end do
  1230. end do
  1231. E

Large files files are truncated, but you can click here to view the full file