diff --git a/driver/fire_behavior.F90 b/driver/fire_behavior.F90 index 22b8a9e..78480e0 100644 --- a/driver/fire_behavior.F90 +++ b/driver/fire_behavior.F90 @@ -17,6 +17,7 @@ program fire_behavior type (wrf_t) :: atm_state type (namelist_t) :: config_flags + #ifdef DM_PARALLEL call mpi_init (ierr) if (ierr /= MPI_SUCCESS) then @@ -28,14 +29,25 @@ program fire_behavior ! Read namelist call config_flags%Initialization (file_name = 'namelist.fire') - call Init_atm_state (atm_state, config_flags) - call Init_fire_state (grid, config_flags, atm_state) + select case (config_flags%ideal_opt) + case (0) + call Init_atm_state (atm_state, config_flags) + call Init_fire_state (grid, config_flags, atm_state) + + case (1) + call Init_fire_state (grid, config_flags) + + case default + write (ERROR_UNIT, *) 'ERROR: ideal_opt option not supported: ', config_flags%ideal_opt + stop + + end select call grid%Save_state () do while (grid%datetime_now < grid%datetime_end) call Advance_state (grid, config_flags) call grid%Handle_output (config_flags) - call grid%Handle_wrfdata_update (atm_state, config_flags) + if (config_flags%ideal_opt == 0) call grid%Handle_wrfdata_update (atm_state, config_flags) end do #ifdef DM_PARALLEL diff --git a/driver/initialize_mod.F90 b/driver/initialize_mod.F90 index 94f83a0..d14d270 100644 --- a/driver/initialize_mod.F90 +++ b/driver/initialize_mod.F90 @@ -46,20 +46,25 @@ subroutine Init_fire_state (grid, config_flags, wrf) if (DEBUG_LOCAL) call Print_message (' Entering subroutine Init_state') - ! Fire state initialization - if (DEBUG_LOCAL) call Print_message (' Reading geogrid file') - geogrid = geogrid_t (file_name = 'geo_em.d01.nc') + if (DEBUG_LOCAL) call Print_message (' Initialization...') + if (config_flags%ideal_opt == 0) then + ! Real world + if (DEBUG_LOCAL) call Print_message (' Reading geogrid file') + geogrid = geogrid_t (file_name = 'geo_em.d01.nc') - if (DEBUG_LOCAL) call Print_message (' Initializing state') - call grid%Initialization (config_flags, geogrid) + if (DEBUG_LOCAL) call Print_message (' Initializing fire state') + call grid%Initialization (config_flags, geogrid) - ! Atmosphere to Fire - if (present (wrf)) then - if (DEBUG_LOCAL) call Print_message (' Initializing atmospheric state') - call grid%Handle_wrfdata_update (wrf, config_flags) + if (present (wrf)) then + if (DEBUG_LOCAL) call Print_message (' Initializing atmospheric state') + call grid%Handle_wrfdata_update (wrf, config_flags) + end if + else + ! Ideal + if (DEBUG_LOCAL) call Print_message (' Initializing fire state') + call grid%Initialization (config_flags) end if - ! Fire init call Init_fire_components (grid, config_flags) if (DEBUG_LOCAL) then diff --git a/io/namelist_mod.F90 b/io/namelist_mod.F90 index c90fa52..7137238 100644 --- a/io/namelist_mod.F90 +++ b/io/namelist_mod.F90 @@ -9,6 +9,12 @@ module namelist_mod public :: namelist_t, FIRE_MAX_IGNITIONS_IN_NAMELIST integer, parameter :: FIRE_MAX_IGNITIONS_IN_NAMELIST = 5 + ! Default ideal block + real, parameter :: DX_DEFAULT = 100.0, U_DEFAULT = 5.0, V_DEFAULT = 0.0, LAT_DEFAULT = 40.3636, LON_DEFAULT = -4.4035, & + DZ_DX_DEFAULT = 0.0, ELEVATION_DEFAULT = 0.0 + integer, parameter :: IDEAL_OPT_DEFAULT = 0, NX_DEFAULT = 100, FUEL_CAT_DEFAULT = 1 + ! Default options + integer, parameter :: NO_FMC_MODEL = -1 type :: namelist_t integer :: start_year = -1, start_month = -1, start_day = -1, start_hour = -1, start_minute = -1, start_second = -1, & @@ -51,7 +57,7 @@ module namelist_mod ! Objects integer :: fuel_opt = 1 ! Fuel model integer :: ros_opt = 0 ! ROS parameterization - integer :: fmc_opt = -1 ! FMC model + integer :: fmc_opt = NO_FMC_MODEL ! FMC model integer :: emis_opt = 0 ! Object to be added. 0) WRF-Fire emiss, 1) PM2.5 as a function of FMC ! Ignitions @@ -102,17 +108,50 @@ module namelist_mod real :: fire_ignition_end_time5 = 0.0 real :: fire_ignition_radius5 = 0.0 + ! Ideal block + integer :: ideal_opt = IDEAL_OPT_DEFAULT ! 0) real world, 1) ideal + real :: dx = DX_DEFAULT + real :: dy = DX_DEFAULT + integer :: nx = NX_DEFAULT + integer :: ny = NX_DEFAULT + + real :: zonal_wind = U_DEFAULT + real :: meridional_wind = V_DEFAULT + integer :: fuel_cat = FUEL_CAT_DEFAULT + real :: dz_dx = DZ_DX_DEFAULT + real :: dz_dy = DZ_DX_DEFAULT + real :: elevation = ELEVATION_DEFAULT + + real :: cen_lat = LAT_DEFAULT + real :: cen_lon = LON_DEFAULT + real :: stand_lon = LON_DEFAULT + real :: true_lat_1 = LAT_DEFAULT + real :: true_lat_2 = LAT_DEFAULT + ! Atmosphere integer :: kds = 1, kde = 1 contains + procedure, public :: Check_nml => Check_nml procedure, public :: Initialization => Init_namelist procedure, public :: Init_fire_block => Init_fire_block + procedure, public :: Init_ideal_block => Init_ideal_block procedure, public :: Init_time_block => Init_time_block procedure, public :: Init_atm_block => Init_atm_block_legacy end type namelist_t contains + subroutine Check_nml (this) + + implicit none + + class (namelist_t), intent (in out) :: this + + if (this%ideal_opt /= 0 .and. this%fmoist_run) & + call Stop_simulation ('ideal runs do not support a FMC model') + + end subroutine Check_nml + subroutine Init_atm_block_legacy (this, file_name) implicit none @@ -332,6 +371,76 @@ subroutine Init_fire_block (this, file_name) end subroutine Init_fire_block + subroutine Init_ideal_block (this, file_name) + + implicit none + + class (namelist_t), intent (in out) :: this + character (len = *), intent (in) :: file_name + + real :: dx, dy, zonal_wind, meridional_wind, cen_lat, cen_lon, stand_lon, true_lat_1, true_lat_2, & + dz_dx, dz_dy, elevation + integer :: nx, ny, fuel_cat, ideal_opt + + character (len = :), allocatable :: msg + integer :: unit_nml, io_stat + + namelist /ideal/ ideal_opt, dx, dy, nx, ny, zonal_wind, meridional_wind, fuel_cat, & + dz_dx, dz_dy, elevation, cen_lat, cen_lon, stand_lon, true_lat_1, true_lat_2 + + + ! Set default values + ideal_opt = IDEAL_OPT_DEFAULT + dx = DX_DEFAULT + dy = DX_DEFAULT + nx = NX_DEFAULT + ny = NX_DEFAULT + + zonal_wind = U_DEFAULT + meridional_wind = V_DEFAULT + fuel_cat = FUEL_CAT_DEFAULT + dz_dx = DZ_DX_DEFAULT + dz_dy = DZ_DX_DEFAULT + elevation = ELEVATION_DEFAULT + + cen_lat = LAT_DEFAULT + cen_lon = LON_DEFAULT + stand_lon = LON_DEFAULT + true_lat_1 = LAT_DEFAULT + true_lat_2 = LAT_DEFAULT + + open (newunit = unit_nml, file = trim (file_name), action = 'read', iostat = io_stat) + if (io_stat /= 0) then + msg = 'Problems opening namelist file ' // trim (file_name) + call Stop_simulation (msg) + end if + + read (unit_nml, nml = ideal, iostat = io_stat) + if (io_stat /= 0) call Stop_simulation ('Problems reading namelist ideal block') + close (unit_nml) + + this%ideal_opt = ideal_opt + this%dx = dx + this%dy = dy + + this%nx = nx + this%ny = ny + + this%zonal_wind = zonal_wind + this%meridional_wind = meridional_wind + this%fuel_cat = fuel_cat + this%dz_dx = dz_dx + this%dz_dy = dz_dy + this%elevation = elevation + + this%cen_lat = cen_lat + this%cen_lon = cen_lon + this%stand_lon = stand_lon + this%true_lat_1 = true_lat_1 + this%true_lat_2 = true_lat_2 + + end subroutine Init_ideal_block + subroutine Init_time_block (this, file_name) implicit none @@ -412,6 +521,9 @@ subroutine Init_namelist (this, file_name) call this%Init_time_block (file_name = trim (file_name)) call this%Init_fire_block (file_name = trim (file_name)) call this%Init_atm_block (file_name = trim (file_name)) + call this%Init_ideal_block (file_name = trim (file_name)) + + call this%Check_nml () if (DEBUG_LOCAL) call Print_message (' Leaving subroutine Read_namelist') diff --git a/state/state_mod.F90 b/state/state_mod.F90 index 10f035a..b159760 100644 --- a/state/state_mod.F90 +++ b/state/state_mod.F90 @@ -251,13 +251,14 @@ subroutine Init_domain (this, config_flags, geogrid, & real, intent (in), optional :: cen_lat, cen_lon, truelat1, truelat2, stand_lon, dx, dy real, dimension(:, :), intent (in), optional :: nfuel_cat, zsf, dzdxf, dzdyf - integer, parameter :: INIT_MODE_NONE = 0, INIT_MODE_GEOGRID = 1, INIT_MODE_WRF = 2 + integer, parameter :: INIT_MODE_NONE = 0, INIT_MODE_GEOGRID = 1, INIT_MODE_WRF = 2, INIT_MODE_IDEAL = 3 type (proj_lc_t) :: proj logical, parameter :: DEBUG_LOCAL = .false. - integer :: ids0, ide0, jds0, jde0, init_mode + integer :: ids0, ide0, jds0, jde0, i, j, init_mode init_mode = INIT_MODE_NONE + if (config_flags%ideal_opt == 1) init_mode = INIT_MODE_IDEAL if (present (geogrid)) init_mode = INIT_MODE_GEOGRID if (present (ifds) .and. present (ifde) .and. present (ifms) .and. present (ifme) .and. present (ifps) .and. present (ifpe) .and. & present (jfds) .and. present (jfde) .and. present (jfms) .and. present (jfme) .and. present (jfps) .and. present (jfpe) .and. & @@ -273,11 +274,18 @@ subroutine Init_domain (this, config_flags, geogrid, & ! Set dimensions Set_dims: select case (init_mode) - case (INIT_MODE_GEOGRID) - ids0 = geogrid%ifds - ide0 = geogrid%ifde - jds0 = geogrid%jfds - jde0 = geogrid%jfde + case (INIT_MODE_GEOGRID, INIT_MODE_IDEAL) + if (init_mode == INIT_MODE_GEOGRID) then + ids0 = geogrid%ifds + ide0 = geogrid%ifde + jds0 = geogrid%jfds + jde0 = geogrid%jfde + else if (init_mode == INIT_MODE_IDEAL) then + ids0 = 1 + ide0 = config_flags%nx + jds0 = 1 + jde0 = config_flags%ny + end if this%ifds = ids0 this%ifde = ide0 @@ -364,6 +372,19 @@ subroutine Init_domain (this, config_flags, geogrid, & this%dx = dx / sr_x this%dy = dy / sr_y + case (INIT_MODE_IDEAL) + this%dx = config_flags%dx + this%dy = config_flags%dy + + this%cen_lat = config_flags%cen_lat + this%cen_lon = config_flags%cen_lon + + proj = proj_lc_t (cen_lat = this%cen_lat , cen_lon = this%cen_lon, dx = this%dx, dy = this%dy, & + standard_lon = config_flags%stand_lon, true_lat_1 = config_flags%true_lat_1, & + true_lat_2 = config_flags%true_lat_2, nx = config_flags%nx, ny = config_flags%ny) + + call this%Init_latlons (proj) + case default call Stop_simulation ('Not ready to complete fire state initialization 2') @@ -397,6 +418,21 @@ subroutine Init_domain (this, config_flags, geogrid, & !this%lfn_hist(this%ifms:this%ifme, this%jfms:this%jfme) = lfn_hist call Stop_simulation ('Not ready to initialize from fire perimeter inside WRF') + case (INIT_MODE_IDEAL) + do j = this%jfds, this%jfde + do i = this%ifds, this%ifde + this%zsf(i, j) = config_flags%elevation + & + (i - this%ifds) * config_flags%dz_dx * config_flags%dx + & + (j - this%jfds) * config_flags%dz_dy * config_flags%dy + end do + end do + this%dzdxf(this%ifds:this%ifde, this%jfds:this%jfde) = config_flags%dz_dx + this%dzdyf(this%ifds:this%ifde, this%jfds:this%jfde) = config_flags%dz_dy + this%nfuel_cat(this%ifds:this%ifde, this%jfds:this%jfde) = config_flags%fuel_cat + + if (config_flags%fire_is_real_perim) & + call Stop_simulation ('Not ready to initialize from fire perimeter in idealized mode') + case default call Stop_simulation ('Not ready to complete fire state initialization 3') @@ -778,8 +814,13 @@ subroutine Set_vars_to_default (this, config_flags) type (namelist_t), intent (in) :: config_flags - this%uf = 0.0 - this%vf = 0.0 + if (config_flags%ideal_opt == 1) then + this%uf(this%ifds:this%ifde, this%jfds:this%jfde) = config_flags%zonal_wind + this%vf(this%ifds:this%ifde, this%jfds:this%jfde) = config_flags%meridional_wind + else + this%uf = 0.0 + this%vf = 0.0 + end if this%fmc_g = config_flags%fuelmc_g ! Init lfn more than the largest domain side this%lfn(this%ifds:this%ifde, this%jfds:this%jfde) = 2.0 * & diff --git a/tests/test7/namelist.fire b/tests/test7/namelist.fire index 58ce971..fffaea8 100644 --- a/tests/test7/namelist.fire +++ b/tests/test7/namelist.fire @@ -37,3 +37,5 @@ fire_upwinding = 9, ! 0=none, 1=standard, 2=godunov, 3=eno, 4=sethian / + &ideal + / diff --git a/tests/test8/namelist.fire b/tests/test8/namelist.fire index ba75bdf..68cf0ed 100644 --- a/tests/test8/namelist.fire +++ b/tests/test8/namelist.fire @@ -39,3 +39,5 @@ fmoist_freq = 1, ! Fuel moisture model updated every time step / + &ideal + / diff --git a/tests/testx/namelist.fire b/tests/testx/namelist.fire index 58ce971..fffaea8 100644 --- a/tests/testx/namelist.fire +++ b/tests/testx/namelist.fire @@ -37,3 +37,5 @@ fire_upwinding = 9, ! 0=none, 1=standard, 2=godunov, 3=eno, 4=sethian / + &ideal + /