! +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ! + + ! + glide_setup.f90 - part of the Glimmer-CISM ice model + ! + + ! +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ! ! Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 ! Glimmer-CISM contributors - see AUTHORS file for list of contributors ! ! This file is part of Glimmer-CISM. ! ! Glimmer-CISM is free software: you can redistribute it and/or modify ! it under the terms of the GNU General Public License as published by ! the Free Software Foundation, either version 2 of the License, or (at ! your option) any later version. ! ! Glimmer-CISM is distributed in the hope that it will be useful, ! but WITHOUT ANY WARRANTY; without even the implied warranty of ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! GNU General Public License for more details. ! ! You should have received a copy of the GNU General Public License ! along with Glimmer-CISM. If not, see . ! ! Glimmer-CISM is hosted on BerliOS.de: ! https://developer.berlios.de/projects/glimmer-cism/ ! ! +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #ifdef HAVE_CONFIG_H #include "config.inc" #endif module glide_setup !*FD Contains general routines for initialisation, etc, called !*FD from the top-level glimmer subroutines. private public :: glide_readconfig, glide_printconfig, glide_scale_params, & glide_calclsrf, glide_marinlim, glide_load_sigma, glide_maskthck, & glide_read_sigma, glide_calc_sigma contains subroutine glide_readconfig(model,config) !*FD read GLIDE configuration file use glide_types use glimmer_config implicit none type(glide_global_type) :: model !*FD model instance type(ConfigSection), pointer :: config !*FD structure holding sections of configuration file ! local variables type(ConfigSection), pointer :: section ! read grid size parameters call GetSection(config,section,'grid') if (associated(section)) then call handle_grid(section, model) end if ! read time parameters call GetSection(config,section,'time') if (associated(section)) then call handle_time(section, model) end if ! read options parameters call GetSection(config,section,'options') if (associated(section)) then call handle_options(section, model) end if ! read parameters call GetSection(config,section,'parameters') if (associated(section)) then call handle_parameters(section, model) end if ! read GTHF call GetSection(config,section,'GTHF') if (associated(section)) then model%options%gthf = 1 call handle_gthf(section, model) end if end subroutine glide_readconfig subroutine glide_printconfig(model) !*FD print model configuration to log use glimmer_log use glide_types implicit none type(glide_global_type) :: model !*FD model instance call write_log_div call print_grid(model) call print_time(model) call print_options(model) call print_parameters(model) call print_gthf(model) end subroutine glide_printconfig subroutine glide_scale_params(model) !*FD scale parameters use glide_types use glimmer_physcon, only: scyr, gn use glimmer_paramets, only: thk0,tim0,len0, tau0, vel0, vis0, acc0 implicit none type(glide_global_type) :: model !*FD model instance tau0 = (vel0/(vis0*len0))**(1.0/gn) model%numerics%ntem = model%numerics%ntem * model%numerics%tinc model%numerics%nvel = model%numerics%nvel * model%numerics%tinc model%numerics%dt = model%numerics%tinc * scyr / tim0 model%numerics%dttem = model%numerics%ntem * scyr / tim0 model%numerics%thklim = model%numerics%thklim / thk0 model%numerics%dew = model%numerics%dew / len0 model%numerics%dns = model%numerics%dns / len0 model%numerics%mlimit = model%numerics%mlimit / thk0 model%velowk%trc0 = vel0 * len0 / (thk0**2) model%velowk%btrac_const = model%paramets%btrac_const/model%velowk%trc0/scyr model%velowk%btrac_max = model%paramets%btrac_max/model%velowk%trc0/scyr model%velowk%btrac_slope = model%paramets%btrac_slope*acc0/model%velowk%trc0 end subroutine glide_scale_params subroutine glide_read_sigma(model,config) !*FD read sigma levels from configuration file use glide_types use glimmer_config implicit none type(glide_global_type) :: model !*FD model instance type(ConfigSection), pointer :: config !*FD structure holding sections of configuration file ! local variables type(ConfigSection), pointer :: section ! read grid size parameters call GetSection(config,section,'sigma') if (associated(section)) then call handle_sigma(section, model) end if end subroutine glide_read_sigma !------------------------------------------------------------------------- !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ subroutine glide_maskthck(whichthck,crita,critb,dom,pointno,totpts,empty) !*FD Calculates the contents of the mask array. use glimmer_global, only : dp, sp implicit none !------------------------------------------------------------------------- ! Subroutine arguments !------------------------------------------------------------------------- integer, intent(in) :: whichthck !*FD Option determining !*FD which method to use. real(dp),dimension(:,:),intent(in) :: crita !*FD Ice thickness real(sp),dimension(:,:),intent(in) :: critb !*FD Mass balance integer, dimension(:), intent(out) :: dom integer, dimension(:,:),intent(out) :: pointno !*FD Output mask integer, intent(out) :: totpts !*FD Total number of points logical, intent(out) :: empty !*FD Set if no mask points set. !------------------------------------------------------------------------- ! Internal variables !------------------------------------------------------------------------- integer,dimension(size(crita,2),2) :: band logical,dimension(size(crita,2)) :: full integer :: covtot integer :: ew,ns,ewn,nsn !------------------------------------------------------------------------- ewn=size(crita,1) ; nsn=size(crita,2) pointno = 0 covtot = 0 !------------------------------------------------------------------------- do ns = 1,nsn full(ns) = .false. do ew = 1,ewn if ( thckcrit(crita(max(1,ew-1):min(ewn,ew+1),max(1,ns-1):min(nsn,ns+1)),critb(ew,ns)) ) then covtot = covtot + 1 pointno(ew,ns) = covtot if ( .not. full(ns) ) then band(ns,1) = ew full(ns) = .true. else band(ns,2) = ew end if end if end do end do totpts = covtot dom(1:2) = (/ewn,1/); empty = .true. do ns = 1,nsn if (full(ns)) then if (empty) then empty = .false. dom(3) = ns end if dom(4) = ns dom(1) = min0(dom(1),band(ns,1)) dom(2) = max0(dom(2),band(ns,2)) end if end do contains logical function thckcrit(ca,cb) implicit none real(dp),dimension(:,:),intent(in) :: ca real(sp), intent(in) :: cb select case (whichthck) case(5) ! whichthck=5 is not a 'known case' if ( ca(2,2) > 0.0d0 .or. cb > 0.0) then thckcrit = .true. else thckcrit = .false. end if case default ! If the thickness in the region under consideration ! or the mass balance is positive, thckcrit is .true. if ( any((ca(:,:) > 0.0d0)) .or. cb > 0.0 ) then thckcrit = .true. else thckcrit = .false. end if end select end function thckcrit end subroutine glide_maskthck subroutine glide_calclsrf(thck,topg,eus,lsrf) !*FD Calculates the elevation of the lower surface of the ice, !*FD by considering whether it is floating or not. use glimmer_global, only : dp use glimmer_physcon, only : rhoi, rhoo implicit none real(dp), intent(in), dimension(:,:) :: thck !*FD Ice thickness real(dp), intent(in), dimension(:,:) :: topg !*FD Bedrock topography elevation real, intent(in) :: eus !*FD global sea level real(dp), intent(out), dimension(:,:) :: lsrf !*FD Lower ice surface elevation real(dp), parameter :: con = - rhoi / rhoo where (topg-eus < con * thck) lsrf = con * thck elsewhere lsrf = topg end where end subroutine glide_calclsrf !------------------------------------------------------------------------- subroutine glide_marinlim(which,thck,relx,topg,mask,mlimit,calving_fraction,eus,ablation_field) !*FD Removes non-grounded ice, according to one of two altenative !*FD criteria, and sets upper surface of non-ice-covered points !*FD equal to the topographic height, or sea-level, whichever is higher. use glimmer_global, only : dp, sp use glimmer_physcon, only : rhoi, rhoo use glide_mask implicit none !--------------------------------------------------------------------- ! Subroutine arguments !--------------------------------------------------------------------- integer, intent(in) :: which !*FD Option to choose ice-removal method !*FD \begin{description} !*FD \item[0] Set thickness to zero if !*FD relaxed bedrock is below a given level. !*FD \item[1] Set thickness to zero if !*FD ice is floating. !*FD \end{description} real(dp),dimension(:,:),intent(inout) :: thck !*FD Ice thickness (scaled) real(dp),dimension(:,:),intent(in) :: relx !*FD Relaxed topography (scaled) real(dp),dimension(:,:),intent(in) :: topg !*FD Present bedrock topography (scaled) integer, dimension(:,:),pointer :: mask !*FD grid type mask real(dp) :: mlimit !*FD Lower limit on topography elevation for !*FD ice to be present (scaled). Used with !*FD $\mathtt{which}=0$. real(dp), intent(in) :: calving_fraction !*FD fraction of ice lost when calving Used with !*FD $\mathtt{which}=3$. real, intent(inout) :: eus !*FD eustatic sea level real(sp),dimension(:,:),intent(inout) :: ablation_field integer ew,ns real(dp), parameter :: con = - rhoi / rhoo !--------------------------------------------------------------------- ablation_field=0.0 select case (which) case(1) ! Set thickness to zero if ice is floating where (is_float(mask)) ablation_field=thck thck = 0.0d0 end where case(2) ! Set thickness to zero if relaxed bedrock is below a ! given level where (relx <= mlimit+eus) ablation_field=thck thck = 0.0d0 end where case(3) ! remove fraction of ice when floating do ns = 2,size(thck,2)-1 do ew = 2,size(thck,1)-1 if (is_calving(mask(ew,ns))) then ablation_field(ew,ns)=(1.0-calving_fraction)*thck(ew,ns) thck(ew,ns) = calving_fraction*thck(ew,ns) !mask(ew,ns) = glide_mask_ocean end if end do end do case(4) ! Set thickness to zero at marine edge if present ! bedrock is below a given level where (is_marine_ice_edge(mask).and.topg0', & '~basal water ', & '~basal melt ', & 'const if T>Tpmp'/) !lipscomb - evolution mod !! character(len=*), dimension(0:2), parameter :: evolution = (/ & character(len=*), dimension(-1:2), parameter :: evolution = (/ & 'no evolution ', & !lipscomb - end evolution mod 'pseudo-diffusion', & 'ADI scheme ', & 'diffusion ' /) character(len=*), dimension(0:1), parameter :: vertical_integration = (/ & 'standard ', & 'obey upper BC' /) character(len=*), dimension(0:1), parameter :: b_mbal = (/ & 'not in continutity eqn', & 'in continutity eqn ' /) call write_log('GLIDE options') call write_log('-------------') write(message,*) 'I/O parameter file : ',trim(model%funits%ncfile) call write_log(message) if (model%options%whichtemp.lt.0 .or. model%options%whichtemp.ge.size(temperature)) then call write_log('Error, temperature out of range',GM_FATAL) end if write(message,*) 'temperature calculation : ',model%options%whichtemp,temperature(model%options%whichtemp) call write_log(message) if (model%options%whichflwa.lt.0 .or. model%options%whichflwa.ge.size(flow_law)) then call write_log('Error, flow_law out of range',GM_FATAL) end if write(message,*) 'flow law : ',model%options%whichflwa,flow_law(model%options%whichflwa) call write_log(message) if (model%options%whichbwat.lt.0 .or. model%options%whichbwat.ge.size(basal_water)) then call write_log('Error, basal_water out of range',GM_FATAL) end if write(message,*) 'basal_water : ',model%options%whichbwat,basal_water(model%options%whichbwat) call write_log(message) if (model%options%whichmarn.lt.0 .or. model%options%whichmarn.ge.size(marine_margin)) then call write_log('Error, marine_margin out of range',GM_FATAL) end if write(message,*) 'marine_margin : ', model%options%whichmarn, marine_margin(model%options%whichmarn) call write_log(message) if (model%options%whichbtrc.lt.0 .or. model%options%whichbtrc.ge.size(slip_coeff)) then call write_log('Error, slip_coeff out of range',GM_FATAL) end if write(message,*) 'slip_coeff : ', model%options%whichbtrc, slip_coeff(model%options%whichbtrc) call write_log(message) !lipscomb - evolution mod !! if (model%options%whichevol.lt.0 .or. model%options%whichevol.ge.size(evolution)) then if (model%options%whichevol.lt.0) model%options%whichevol = -1 ! no thickness evolution if (model%options%whichevol.ge.size(evolution)-1 ) then !lipscomb - end evolution mod call write_log('Error, evolution out of range',GM_FATAL) end if write(message,*) 'evolution : ', model%options%whichevol, evolution(model%options%whichevol) call write_log(message) if (model%options%whichwvel.lt.0 .or. model%options%whichwvel.ge.size(vertical_integration)) then call write_log('Error, vertical_integration out of range',GM_FATAL) end if write(message,*) 'vertical_integration : ',model%options%whichwvel,vertical_integration(model%options%whichwvel) call write_log(message) if (model%options%basal_mbal.lt.0 .or. model%options%basal_mbal.ge.size(b_mbal)) then call write_log('Error, basal_mass_balance out of range',GM_FATAL) end if write(message,*) 'basal_mass_balance : ',model%options%basal_mbal,b_mbal(model%options%basal_mbal) call write_log(message) if (model%options%whichrelaxed.eq.1) then call write_log('First topo time slice is relaxed') end if if (model%options%periodic_ew.eq.1) then if (model%options%whichevol.eq.1) then call write_log('Periodic boundary conditions not implemented in ADI scheme',GM_FATAL) end if call write_log('Periodic EW lateral boundary condition') call write_log(' Slightly cheated with how temperature is implemented.',GM_WARNING) end if if (model%options%hotstart.eq.1) then call write_log('Hotstarting model') end if call write_log('') end subroutine print_options ! parameters subroutine handle_parameters(section, model) use glimmer_config use glide_types use glimmer_log implicit none type(ConfigSection), pointer :: section type(glide_global_type) :: model real, pointer, dimension(:) :: temp => NULL() integer :: loglevel loglevel = GM_levels-GM_ERROR call GetValue(section,'log_level',loglevel) call glimmer_set_msg_level(loglevel) call GetValue(section,'ice_limit',model%numerics%thklim) call GetValue(section,'marine_limit',model%numerics%mlimit) call GetValue(section,'calving_fraction',model%numerics%calving_fraction) call GetValue(section,'geothermal',model%paramets%geot) call GetValue(section,'flow_factor',model%paramets%fiddle) call GetValue(section,'hydro_time',model%paramets%hydtim) call GetValue(section,'basal_tract',temp,5) if (associated(temp)) then model%paramets%btrac_const=temp(1) deallocate(temp) end if call GetValue(section,'basal_tract_const',model%paramets%btrac_const) call GetValue(section,'basal_tract_max',model%paramets%btrac_max) call GetValue(section,'basal_tract_slope',model%paramets%btrac_slope) call GetValue(section,'basal_water_smoothing',model%paramets%bwat_smooth) end subroutine handle_parameters subroutine print_parameters(model) use glide_types use glimmer_log implicit none type(glide_global_type) :: model character(len=100) :: message call write_log('Parameters') call write_log('----------') write(message,*) 'ice limit : ',model%numerics%thklim call write_log(message) write(message,*) 'marine depth limit : ',model%numerics%mlimit call write_log(message) if (model%options%whichmarn.eq.3) then write(message,*) 'ice fraction lost due to calving :', model%numerics%calving_fraction call write_log(message) end if write(message,*) 'geothermal heat flux : ',model%paramets%geot call write_log(message) write(message,*) 'flow enhancement : ',model%paramets%fiddle call write_log(message) write(message,*) 'basal hydro time const: ',model%paramets%hydtim call write_log(message) if (model%options%whichbtrc.eq.1 .or. model%options%whichbtrc.eq.2 .or. model%options%whichbtrc.eq.4) then write(message,*) 'basal traction param : ',model%paramets%btrac_const call write_log(message) end if if (model%options%whichbtrc.eq.4) then write(message,*) 'basal traction max : ',model%paramets%btrac_max call write_log(message) write(message,*) 'basal traction slope : ',model%paramets%btrac_slope call write_log(message) end if if (model%options%whichbtrc.eq.3) then write(message,*) 'basal traction factors: ',model%paramets%bpar(1) call write_log(message) write(message,*) ' ',model%paramets%bpar(2) call write_log(message) write(message,*) ' ',model%paramets%bpar(3) call write_log(message) write(message,*) ' ',model%paramets%bpar(4) call write_log(message) write(message,*) ' ',model%paramets%bpar(5) call write_log(message) end if write(message,*) 'basal water field smoothing strength: ',model%paramets%bwat_smooth call write_log(message) call write_log('') end subroutine print_parameters ! Sigma levels subroutine handle_sigma(section, model) use glimmer_config use glide_types use glimmer_log implicit none type(ConfigSection), pointer :: section type(glide_global_type) :: model if (model%options%which_sigma==1) then call write_log('Sigma levels specified twice - use only'// & ' config file or separate file, not both',GM_FATAL) else model%options%which_sigma = 2 call GetValue(section,'sigma_levels',model%numerics%sigma,model%general%upn) end if end subroutine handle_sigma subroutine print_sigma(model) use glide_types use glimmer_log implicit none type(glide_global_type) :: model character(len=100) :: message,temp integer :: i call write_log('Sigma levels:') call write_log('------------------') message='' do i=1,model%general%upn write(temp,'(F5.2)') model%numerics%sigma(i) message=trim(message)//trim(temp) enddo call write_log(trim(message)) call write_log('') end subroutine print_sigma ! geothermal heat flux calculations subroutine handle_gthf(section, model) use glimmer_config use glide_types implicit none type(ConfigSection), pointer :: section type(glide_global_type) :: model call GetValue(section,'num_dim',model%lithot%num_dim) call GetValue(section,'nlayer',model%lithot%nlayer) call GetValue(section,'surft',model%lithot%surft) call GetValue(section,'rock_base',model%lithot%rock_base) call GetValue(section,'numt',model%lithot%numt) call GetValue(section,'rho',model%lithot%rho_r) call GetValue(section,'shc',model%lithot%shc_r) call GetValue(section,'con',model%lithot%con_r) end subroutine handle_gthf subroutine print_gthf(model) use glide_types use glimmer_log implicit none type(glide_global_type) :: model character(len=100) :: message if (model%options%gthf.gt.0) then call write_log('GTHF configuration') call write_log('------------------') if (model%lithot%num_dim.eq.1) then call write_log('solve 1D diffusion equation') else if (model%lithot%num_dim.eq.3) then call write_log('solve 3D diffusion equation') else call write_log('Wrong number of dimensions.',GM_FATAL,__FILE__,__LINE__) end if write(message,*) 'number of layers : ',model%lithot%nlayer call write_log(message) write(message,*) 'initial surface temperature : ',model%lithot%surft call write_log(message) write(message,*) 'rock base : ',model%lithot%rock_base call write_log(message) write(message,*) 'density of rock layer : ',model%lithot%rho_r call write_log(message) write(message,*) 'specific heat capacity of rock layer : ',model%lithot%shc_r call write_log(message) write(message,*) 'thermal conductivity of rock layer : ',model%lithot%con_r call write_log(message) write(message,*) 'number of time steps for spin-up : ',model%lithot%numt call write_log(message) call write_log('') end if end subroutine print_gthf end module glide_setup