!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! !! !! GNU General Public License !! !! !! !! This file is part of the Flexible Modeling System (FMS). !! !! !! !! FMS is free software; you can redistribute it and/or modify !! !! it and are expected to follow the terms of the GNU General Public !! !! License as published by the Free Software Foundation. !! !! !! !! FMS 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 FMS; if not, write to: !! !! Free Software Foundation, Inc. !! !! 59 Temple Place, Suite 330 !! !! Boston, MA 02111-1307 USA !! !! or see: !! !! http://www.gnu.org/licenses/gpl.txt !! !! !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! module ocean_passive_mod ! ! Stephen M. Griffies ! ! ! Alistair Adcroft ! ! ! ! Set up for idealized passive tracers. ! ! ! ! This module setups various passive tracer configurations. ! Some idealized initial conditions are provided. ! ! These tracers are used for various idealized purposes, ! such as tracing water mass transports, testing ! advection schemes, etc. ! ! These passive tracers are always initialized within ! this module with an idealized profile. ! No preprocessing step is required. To define a common initial condition ! for all passive tracers use the namelist "ocean_passive_nml" ! ! This setting can be overwritten for each tracer by the namelist feature of the tracer field_table. ! For example ! ! "namelists","ocean_mod","ocean_passive/patch" ! restore = f ! init_condition = temp_sq_init ! ! init_condition is one of :: 'level', 'wall','patch', 'patch_'klevel, with "klevel" an integer ! for the k-level that will place the patch. ! 'exponential', 'shelfbowl', 'rho_surface', 'temp_sq_init', 'salt_sq_init' ! Default is 'patch' ! ! With rho_surface' a density surface can be selected, the density value ! is defined in the field table namelist, for example ! ! init_surface = 1025 ! ! However, if an initial file exists for a passive tracer, ! then ocean_tracer_mod will overwrite the passive tracer ! with the tracer concentration in the initial file. In this ! way, we can, for example, initialize a passive tracer with ! some profile that is not readily determined via a simple ! algorithmic procedure. ! ! If restoring of a passive tracer to its initial value is enabled by ! setting in the field table ! ! restore = t ! ! the initial field is used only to find the grid cells where to restore the ! passive tracer to the initial tracer field. Restoring is done where the tracer ! concentration exceeds 0.00001. The inital value of passive tracers with restoring ! is always set to '1'. With the field_table namelist ! ! init_value = some_real ! ! this can be changed to another but also constant value. ! ! All passive tracers in this module are dimensionless and are ! treated the same internally to this module. However, they can ! generally have different initial conditions and can use ! different advection schemes. Indeed, one motivation for ! developing this module is to test advection schemes, with ! the same initial condition used for each of the tracers, ! but different advection schemes. In this way we can readily ! determine the difference between advection schemes on various ! profiles within mom4p1. ! ! Sample passive tracers are setup here. The user can modify ! code in a straightforward manner to change the number of ! passive tracers and/or the initial profiles. ! ! ! ! ! ! ! For debugging the module. ! ! ! ! Default for the tracer initial conditions. ! ! Options are the following: ! common_init_condition='level' ! common_init_condition='wall' ! common_init_condition='patch' ! common_init_condition='patch_'klevel, with "klevel" an integer ! for the k-level that will place the patch. ! common_init_condition='exponential' ! common_init_condition='shelfbowl' ! common_init_condition='rho_surface' ! common_init_condition='temp_sq_init' ! common_init_condition='salt_sq_init' ! Default=common_init_condition='patch' ! ! ! ! Value of tracer concentration within the layer. ! Default=1.0. ! ! ! Depth at the top of the tracer layer. ! ! ! Depth at the bottom of the tracer layer. ! ! ! To initialize on the klevel with a gaussian region. ! Default=patch_init_klevel_gaussian=.false. ! ! ! ! Value of tracer concentration within the wall. ! Default=1.0. ! ! ! Ratio of the full j-range, northward of which ! we place the wall. ! ! ! Ratio of the full j-range, southward of which ! we place the wall. ! ! ! ! Value of the tracer concentration within a patch. ! Default=1.0. ! ! ! Depth at the top of the tracer patch. ! ! ! Depth at the bottom of the tracer patch. ! ! ! For setting position of tracer patch. ! ! ! For setting position of tracer patch. ! ! ! ! The efolding depth used for exponential tracer profile. ! Default=1000.0. ! ! ! The tracer value at zero depth when choosing the exponential profile. ! Default=1.0. ! ! ! use constants_mod, only: pi use field_manager_mod, only: fm_string_len, fm_path_name_len, fm_field_name_len use field_manager_mod, only: fm_get_length, fm_get_value, fm_new_value use fm_util_mod, only: fm_util_start_namelist, fm_util_end_namelist use fm_util_mod, only: fm_util_set_value, fm_util_get_real, fm_util_get_logical use fm_util_mod, only: fm_util_get_string_array, fm_util_get_string use fm_util_mod, only: fm_util_check_for_bad_fields use fms_mod, only: write_version_number use fms_mod, only: open_namelist_file, check_nml_error, close_file use mpp_mod, only: mpp_min, mpp_max, mpp_error, FATAL, WARNING, NOTE, stdout, stdlog use ocean_domains_mod, only: get_local_indices use ocean_tpm_util_mod, only: otpm_set_prog_tracer, otpm_set_tracer_package, otpm_set_diag_tracer use ocean_types_mod, only: ocean_domain_type, ocean_grid_type use ocean_types_mod, only: ocean_options_type use ocean_types_mod, only: ocean_prog_tracer_type, ocean_diag_tracer_type implicit none private #include type(ocean_domain_type), pointer :: Dom =>NULL() type(ocean_grid_type), pointer :: Grd =>NULL() character(len=128) :: version=& '$Id: ocean_passive.F90,v 16.0.70.3.20.1 2009/10/10 00:43:00 nnz Exp $' character (len=128) :: tagname = & '$Name: mom4p1_pubrel_dec2009_nnz $' public ocean_passive_init public passive_tracer_init public ocean_passive_tracer_init public update_tracer_passive private layer_init private wall_init private patch_init private patch_init_klevel private exponential_init private shelfbowl_init type passive_type real, allocatable , dimension(:,:,:) :: mask character(len=fm_field_name_len) :: name character(len=30) :: init_condition integer :: index, diag_index real :: init_surface real :: init_value logical :: restore end type passive_type type(passive_type), dimension(:), allocatable, save :: passive integer :: index_temp =-1 integer :: index_salt =-1 ! defaults for the passive tracer package integer, parameter :: num_types = 1 character(len=fm_field_name_len), parameter :: package_name = 'ocean_passive' character(len=48), parameter :: mod_name = 'ocean_passive_mod' character(len=fm_string_len), parameter :: default_restart_file = 'ocean_passive.res.nc' ! logical set according to tracer table logical :: use_tracer_sq=.false. logical :: use_tracer_restore=.false. ! set min/max tracer concentration ! if solution falls outside this range, model will be ! gracefully brought down. real :: t_min=-1e6 real :: t_max= 1e6 ! min/max tracer concentration beyond which employ upwind ! advection if set limit_tracer_range_quick=.true. ! (set in ocean_tracer_advect_nml) and/or ! horizontal diffusion if limit_tracer_range_neutral=.true. ! (set in ocean_neutral_physics_nml) real :: t_min_limit=-.10 real :: t_max_limit=1.0 ! number of passive tracers integer :: instances ! for setting the passive tracer package integer :: package_index logical :: module_is_initialized=.false. logical :: use_this_module=.false. ! nml settings logical :: debug_this_module = .false. ! options are 'patch', 'patch_'klevel, 'layer', 'wall', 'exponential', and 'shelfbowl' character(len=32) :: common_init_condition='patch' real :: layer_value = 1.0 real :: layer_ztop = 100.0 ! metres real :: layer_zbot = 200.0 ! metres real :: wall_value = 1.0 real :: wall_ratio_south = 0.33333 real :: wall_ratio_north = 0.66666 real :: patch_value = 1.0 real :: patch_ztop = 0.0 ! metres real :: patch_zbot = 200.0 ! metres real :: patch_ratio1 = 0.33333 real :: patch_ratio2 = 0.66666 logical :: patch_init_klevel_gaussian=.false. real :: shelfbowl_north = 70.0 ! latitude real :: shelf_value = 1.0 real :: efold_depth = 1000.0 ! metres real :: exponential_value = 1.0 namelist /ocean_passive_nml/ debug_this_module, common_init_condition, & layer_value, layer_ztop, layer_zbot, & wall_value, wall_ratio_south, wall_ratio_north, & patch_value, patch_ztop, patch_zbot, patch_ratio1, patch_ratio2, & patch_init_klevel_gaussian, efold_depth, exponential_value, & shelfbowl_north, shelf_value contains !####################################################################### ! ! ! ! Initialize the indices for passive tracer fields. ! This routine is called by ocean_model.F90. ! ! subroutine ocean_passive_init(Domain, Grid, Ocean_options, debug) type(ocean_domain_type), intent(in), target :: Domain type(ocean_grid_type), intent(in), target :: Grid type(ocean_options_type), intent(inout) :: Ocean_options logical, intent(in), optional :: debug integer :: ioun, io_status, ierr ! ------------------------------------------------------------------------- ! start of tracer package material ! local parameters character(len=64), parameter :: sub_name = 'ocean_passive_init' character(len=256), parameter :: error_header = & '==>Error from ' // trim(mod_name) // '(' // trim(sub_name) // '):' character(len=256), parameter :: warn_header = & '==>Warning from ' // trim(mod_name) // '(' // trim(sub_name) // '):' character(len=256), parameter :: note_header = & '==>Note from ' // trim(mod_name) // '(' // trim(sub_name) // '):' ! local variables integer :: n character(len=fm_field_name_len) :: name character(len=fm_path_name_len) :: path_to_names character(len=fm_field_name_len+1) :: suffix character(len=fm_field_name_len+3) :: long_suffix character(len=256) :: caller_str character(len=fm_string_len), pointer, dimension(:) :: good_list integer :: stdoutunit,stdlogunit stdoutunit=stdout();stdlogunit=stdlog() if ( module_is_initialized ) then call mpp_error(FATAL, '==>Error in ocean_passive_mod (ocean_passive_init): module initialized.') endif module_is_initialized=.true. ! initialize the ocean passive tracer package and set some defaults. ! each of these defaults can be altered via entries to the field_table. package_index = otpm_set_tracer_package(package_name, & units = 'dimensionless', min_tracer=t_min, max_tracer=t_max, & min_tracer_limit=t_min_limit, max_tracer_limit=t_max_limit, & restart_file=default_restart_file, & caller = trim(mod_name) // '(' // trim(sub_name) // ')', & conversion=1.0, offset=0.0, min_range=-10.0, max_range=100.0, & flux_units = 'dimensionless', min_flux_range=-1.0e+16, max_flux_range=1.0e+16, & vert_adv_scheme='mdppm', horiz_adv_scheme='mdppm', psom_limit=.true.) ! check for number of entries in the field_table for passive tracers. path_to_names = '/ocean_mod/tracer_packages/' // trim(package_name) // '/names' instances = fm_get_length(path_to_names) if (instances < 0) then call mpp_error( & FATAL, trim(error_header) // ' Could not get number of passive tracer instances.') endif ! determine whether to use this module. write (stdoutunit,*) ' ' if(instances==0) then write (stdoutunit,*) trim(note_header), ' No instances of passive tracers in field_table.' use_this_module=.false. write(stdoutunit,'(a)') ' ' write(stdoutunit,'(a)') & '==>Note: NOT running with idealized passive tracers.' call mpp_error(NOTE, '==>Note: ocean_passive_mod: NOT using idealized passive tracer module.') Ocean_options%passive_tracers = 'Did NOT use the idealized passive tracer module.' return else write (stdoutunit,*) trim(note_header), ' ', instances, ' instances of passive tracers in field_table.' use_this_module=.true. Ocean_options%passive_tracers = 'Ran with idealized passive tracer module.' endif ! allocate the passive array allocate (passive(instances)) ! loop over the names of the passive tracers, saving them into the passive array do n=1,instances if (fm_get_value(path_to_names, name, index = n)) then passive(n)%name = name else write (name,*) n call mpp_error(FATAL, trim(error_header) // & ' Bad field name for index ' // trim(name)) endif enddo ! determine the tracer name for this instance, ! and set the prog tracer through otpm_set_prog_tracer do n=1,instances name = passive(n)%name if (name(1:1) .eq. '_') then suffix = ' ' long_suffix = ' ' else suffix = '_' // name long_suffix = ' (' // trim(name) // ')' endif passive(n)%index = otpm_set_prog_tracer('passive' // trim(suffix), package_name, & longname = 'passive' // trim(long_suffix), & caller = trim(mod_name)//'('//trim(sub_name)//')') enddo ! add the package name to the list of good namelists; used later for consistency check if (fm_new_value('/ocean_mod/GOOD/good_namelists', package_name, append = .true.) .le. 0) then call mpp_error(FATAL, trim(error_header) // & ' Could not add ' // trim(package_name) // ' to "good_namelists" list') endif ! set defaults for the available namelist parameters caller_str = trim(mod_name) // '(' // trim(sub_name) // ')' do n=1,instances call fm_util_start_namelist(package_name, passive(n)%name, caller=caller_str, & no_overwrite=.true., check=.true.) call fm_util_set_value('init_condition', 'patch') call fm_util_set_value('init_surface', 1030.0) call fm_util_set_value('init_value', 1.0) call fm_util_set_value('restore', .false.) call fm_util_end_namelist(package_name, passive(n)%name, check = .true., caller = caller_str) enddo ! check for errors in number of fields in the namelists for this package good_list => fm_util_get_string_array('/ocean_mod/GOOD/namelists/' // trim(package_name) // '/good_values', & caller = trim(mod_name) // '(' // trim(sub_name) // ')') if (associated(good_list)) then call fm_util_check_for_bad_fields('/ocean_mod/namelists/' // trim(package_name), good_list, & caller = trim(mod_name) // '(' // trim(sub_name) // ')') deallocate(good_list) else call mpp_error(FATAL,trim(error_header) // ' Empty "' // trim(package_name) // '" list') endif ! end of tracer package material ! ------------------------------------------------------------------------- #ifndef MOM4_STATIC_ARRAYS call get_local_indices(Domain, isd, ied, jsd, jed, isc, iec, jsc, jec) nk = Grid%nk #endif Dom => Domain Grd => Grid call write_version_number( version, tagname ) ! provide for namelist override of defaults ioun = open_namelist_file() read (ioun,ocean_passive_nml,IOSTAT=io_status) write (stdoutunit,'(/)') write (stdoutunit,ocean_passive_nml) write (stdlogunit,ocean_passive_nml) ierr = check_nml_error(io_status, 'ocean_passive_nml') call close_file(ioun) if (PRESENT(debug) .and. .not. debug_this_module) then debug_this_module = debug endif if(debug_this_module) then write(stdoutunit,'(a)') '==>Note: running ocean_passive with debug_this_module=.true.' endif ! set default initial condition according to setting in ocean_passive_nml do n=1,instances passive(n)%init_condition = trim(common_init_condition) enddo ! namelist information for each passive tracer from the field_table. ! in particular, can override the common_init_condition so that each ! tracer can, for example, have a distinct initial condition. caller_str = trim(mod_name) // '(' // trim(sub_name) // ')' do n=1,instances call fm_util_start_namelist(package_name, passive(n)%name, caller = caller_str) passive(n)%init_condition = fm_util_get_string ('init_condition', scalar = .true.) passive(n)%init_surface = fm_util_get_real('init_surface', scalar = .true.) passive(n)%init_value = fm_util_get_real('init_value', scalar = .true.) passive(n)%restore = fm_util_get_logical('restore', scalar = .true.) call fm_util_end_namelist(package_name, passive(n)%name, caller = caller_str) enddo do n=1,instances if (passive(n)%restore ) then name = passive(n)%name if (name(1:1) .eq. '_') then suffix = ' ' long_suffix = ' ' else suffix = '_' // name long_suffix = ' (' // trim(name) // ')' endif passive(n)%diag_index = otpm_set_diag_tracer('passive' // trim(suffix) // 'mask', & longname = 'passive' // trim(long_suffix), restart_file='ocean_passive_masks.res.nc', & min_range=-1.0, max_range=2.0, const_init_tracer=.true.,const_init_value=0.0, & caller = caller_str ) use_tracer_restore=.true. endif enddo end subroutine ocean_passive_init ! NAME="ocean_passive_init" !####################################################################### ! ! ! ! Initialize profiles for the passive tracers. ! This routine is called by ocean_tracer.F90. ! ! subroutine passive_tracer_init(time_init, Tracer, initialize_as_a_passive_tracer) logical, intent(in) :: time_init type(ocean_prog_tracer_type), intent(inout) :: Tracer logical, intent(inout) :: initialize_as_a_passive_tracer integer :: i,j,k,n integer :: stdoutunit stdoutunit=stdout() initialize_as_a_passive_tracer=.false. if(.not. use_this_module) return if(.not. time_init) return do n=1,instances if(trim(Tracer%name)=='passive_'//trim(passive(n)%name)) then initialize_as_a_passive_tracer=.true. if(trim(passive(n)%init_condition)=='layer') then call layer_init(Tracer%field(:,:,:,1)) write(stdoutunit,'(a)') '==>From passive_tracer_init: initialized tracer '& //trim(passive(n)%name)//' with "layer" profile.' elseif(trim(passive(n)%init_condition)=='wall') then call wall_init(Tracer%field(:,:,:,1)) write(stdoutunit,'(a)') '==>From passive_tracer_init: initialized tracer '& //trim(passive(n)%name)//' with "wall" profile.' elseif(trim(passive(n)%init_condition)=='patch') then call patch_init(Tracer%field(:,:,:,1)) write(stdoutunit,'(a)') '==>From passive_tracer_init: initialized tracer '& //trim(passive(n)%name)//' with "patch" profile.' elseif(trim(passive(n)%init_condition)=='patch_klevel') then call patch_init_klevel(Tracer%field(:,:,:,1),trim(Tracer%name)) write(stdoutunit,'(a)') '==>From passive_tracer_init: initialized tracer '& //trim(passive(n)%name)//' with "patch_klevel" profile, w/ patch on single k-level.' elseif(trim(passive(n)%init_condition)=='exponential') then call exponential_init(Tracer%field(:,:,:,1)) write(stdoutunit,'(a)') '==>From passive_tracer_init: initialized tracer '& //trim(passive(n)%name)//' with "exponential" profile.' elseif(trim(passive(n)%init_condition)=='shelfbowl') then call shelfbowl_init(Tracer%field(:,:,:,1)) write(stdoutunit,'(a)') '==>From passive_tracer_init: initialized tracer '& //trim(passive(n)%name)//' with "shelfbowl" profile.' elseif( trim(passive(n)%init_condition(1:4))=='temp') then write(stdoutunit,'(a)') & '==>From passive_tracer_init: tracer to be initialized after initialize temp.' elseif( trim(passive(n)%init_condition(1:3))=='rho') then write(stdoutunit,'(a)') & '==>From passive_tracer_init: tracer to be initialized after initialize density.' elseif( trim(passive(n)%init_condition(1:12))=='temp_sq_init') then write(stdoutunit,'(a)') & '==>From passive_tracer_init: tracer to be initialized after initialize temp.' elseif( trim(passive(n)%init_condition(1:12))=='salt_sq_init') then write(stdoutunit,'(a)') & '==>From passive_tracer_init: tracer to be initialized after initialize salinity.' else write(stdoutunit,'(a)') & '==>Error in passive_tracer_init: tracer '//trim(Tracer%name)// ' is not initialized.' call mpp_error(FATAL, & '==>Error in passive_tracer_init: passive tracer not initialized.') endif do k=1,nk do j=jsd,jed do i=isd,ied Tracer%field(i,j,k,2) = Tracer%field(i,j,k,1) Tracer%field(i,j,k,3) = Tracer%field(i,j,k,1) enddo enddo enddo endif enddo end subroutine passive_tracer_init ! NAME="passive_tracer_init" !####################################################################### ! ! ! ! Initialize restoring to initial values for the passive tracers. ! ! or ! Initialize profiles for the passive tracers which are tagged with ! specific values of the temperature field or potential density field. ! ! or ! Initialize profiles for the passive tracers which are defined ! as the temperature or salinity squared. These tracers are used ! for diagnosing the level of spurious mixing associated with ! PSOM advection. ! ! subroutine ocean_passive_tracer_init(T_prog, T_diag, rho, & time_init, tau, num_prog_tracers, i_temp, i_salt) type(ocean_prog_tracer_type), intent(inout) :: T_prog(:) type(ocean_diag_tracer_type), intent(inout) :: T_diag(:) real, dimension(isd:,jsd:,:), intent(in) :: rho logical, intent(in) :: time_init integer, intent(in) :: tau, num_prog_tracers, i_temp, i_salt integer :: i,j,k,n,nt real :: isotherm, isorho integer :: stdoutunit stdoutunit=stdout() if(.not. use_this_module) return if(.not. time_init) return index_temp = i_temp index_salt = i_salt do nt=1,num_prog_tracers do n=1,instances if(trim(T_prog(nt)%name)=='passive_'//trim(passive(n)%name)) then if( passive(n)%restore ) then T_diag(passive(n)%diag_index)%field = 0. do k=1,nk do j=jsd,jed do i=isd,ied if (T_prog(nt)%field(i,j,k,tau) > 0.00001) then ! set a mask to 1 if restoring is required T_diag(passive(n)%diag_index)%field(i,j,k) = 1. T_prog(nt)%field(i,j,k,1) = passive(n)%init_value T_prog(nt)%field(i,j,k,2) = passive(n)%init_value T_prog(nt)%field(i,j,k,3) = passive(n)%init_value endif enddo enddo enddo write(stdoutunit,'(a)') & '==>From passive_tracer_init: restore '//trim(T_prog(nt)%name)// ' to initial conditions.' else write(stdoutunit,'(a)') & '==>From passive_tracer_init: do not restore '//trim(T_prog(nt)%name)// ' to initial conditions.' endif ! Initialize profiles for the passive tracers which are tagged with ! specific values of the temperature field or potential density field. if(trim(passive(n)%init_condition)=='temp_surface') then isotherm=passive(n)%init_surface call surface_init(isotherm, 'temp', T_prog(index_temp)%field(:,:,:,tau), & T_prog(nt)%field(:,:,:,1)) write(stdoutunit,'(a,a,a,f12.3)') & '==>From passive_tracer_surface_init: passive tracer ',T_prog(nt)%name,& ' initialized to isotherm (C) = ',isotherm write(stdoutunit,'(a)') ' ' do k=1,nk do j=jsd,jed do i=isd,ied T_prog(nt)%field(i,j,k,2) = T_prog(nt)%field(i,j,k,1) T_prog(nt)%field(i,j,k,3) = T_prog(nt)%field(i,j,k,1) enddo enddo enddo endif if(trim(passive(n)%init_condition)=='rho_surface') then isorho=passive(n)%init_surface call surface_init(isorho, 'rho', rho, T_prog(nt)%field(:,:,:,1)) write(stdoutunit,'(a,a,a,f12.3)') & '==>From passive_tracer_surface_init: passive tracer ',T_prog(nt)%name,& ' initialized to neutral rho (kg/m^3) = ',isorho write(stdoutunit,'(a)') ' ' do k=1,nk do j=jsd,jed do i=isd,ied T_prog(nt)%field(i,j,k,2) = T_prog(nt)%field(i,j,k,1) T_prog(nt)%field(i,j,k,3) = T_prog(nt)%field(i,j,k,1) enddo enddo enddo endif ! Initialize profiles for the passive tracers which are defined ! as the temperature or salinity squared. These tracers are used ! for diagnosing the level of spurious mixing associated with ! PSOM advection. if(trim(passive(n)%init_condition)=='temp_sq_init') then do k=1,nk do j=jsd,jed do i=isd,ied T_prog(nt)%field(i,j,k,1) = T_prog(index_temp)%field(i,j,k,tau)**2 T_prog(nt)%field(i,j,k,2) = T_prog(nt)%field(i,j,k,1) T_prog(nt)%field(i,j,k,3) = T_prog(nt)%field(i,j,k,1) T_prog(nt)%units = '(deg C)^2' enddo enddo enddo write(stdoutunit,'(a,a,a)') & '==>From ocean_tracer_sq_init: tracer ',T_prog(nt)%name,& ' initialized to squared temp (degC^2)' write(stdoutunit,'(a)') ' ' use_tracer_sq=.true. endif if(trim(passive(n)%init_condition)=='salt_sq_init') then do k=1,nk do j=jsd,jed do i=isd,ied T_prog(nt)%field(i,j,k,1) = T_prog(index_salt)%field(i,j,k,tau)**2 T_prog(nt)%field(i,j,k,2) = T_prog(nt)%field(i,j,k,1) T_prog(nt)%field(i,j,k,3) = T_prog(nt)%field(i,j,k,1) T_prog(nt)%units = '(psu)^2' enddo enddo enddo write(stdoutunit,'(a,a,a)') & '==>From ocean_tracer_sq_init: tracer ',T_prog(nt)%name,& ' initialized to squared salinity (psu^2)' write(stdoutunit,'(a)') ' ' use_tracer_sq=.true. endif endif enddo !!n=1,instances enddo !!nt=1,num_prog_tracers end subroutine ocean_passive_tracer_init ! NAME="ocean_passive_tracer_init" !####################################################################### ! ! ! ! Initialize passive tracer according to a particular iso-surface. ! ! subroutine surface_init(isovalue, surface_name, surface_field, passive_field) real, intent(in) :: isovalue character(len=*), intent(in) :: surface_name real, intent(in) , dimension(isd:,jsd:,:) :: surface_field real, intent(inout), dimension(isd:,jsd:,:) :: passive_field integer :: i, j, k passive_field(:,:,:) = 0.0 if(trim(surface_name)=='rho') then do k=1,nk-1 do j=jsd,jed do i=isd,ied if(surface_field(i,j,k) <= isovalue .and. surface_field(i,j,k+1) > isovalue) then passive_field(i,j,k) = Grd%tmask(i,j,k+1) endif enddo enddo enddo elseif(trim(surface_name)=='temp') then do k=1,nk-1 do j=jsd,jed do i=isd,ied if(surface_field(i,j,k) >= isovalue .and. surface_field(i,j,k+1) < isovalue) then passive_field(i,j,k) = Grd%tmask(i,j,k+1) endif enddo enddo enddo endif end subroutine surface_init ! NAME="surface_init" !####################################################################### ! ! ! ! ! Initialize tracer inside a depth layer to have a value, and ! zero outside the layer. ! ! ! subroutine layer_init(field) real, intent(inout), dimension(isd:,jsd:,:) :: field integer :: i, j, k field(:,:,:) = 0.0 do k=1,nk if(Grd%zt(k) >=layer_ztop .and. Grd%zt(k) <= layer_zbot) then do j=jsd,jed do i=isd,ied field(i,j,k) = layer_value enddo enddo endif enddo end subroutine layer_init ! NAME="layer_init" !####################################################################### ! ! ! ! ! Initialize tracer inside an (i,k) wall to have a value, and ! zero outside the wall. ! ! ! subroutine wall_init(field) real, intent(inout), dimension(isd:,jsd:,:) :: field integer :: i, j, k integer :: jsouth, jnorth jsouth = int(wall_ratio_south*Grd%nj) jnorth = int(wall_ratio_north*Grd%nj) field(:,:,:) = 0.0 do j=jsd,jed if(j+Dom%joff >= jsouth .and. j+Dom%joff <= jnorth) then do k=1,nk do i=isd,ied field(i,j,k) = wall_value enddo enddo endif enddo end subroutine wall_init ! NAME="wall_init" !####################################################################### ! ! ! ! ! Initialize tracer with simple shapes based on vertical layer: ! Level k=1, square pill box ! Level k=2, circular pill box (cylinder) ! Level k=3, circular cone ! Level k=4, cosine bell ! Level k=5, Gaussian bell ! Levels k>5, square patch based on i,j coordinates (original "patch"). ! ! ! subroutine patch_init(field) real, intent(inout), dimension(isd:,jsd:,:) :: field integer :: i, j, k integer :: iwest, ieast integer :: jsouth, jnorth real :: x_min,x_max,y_min,y_max real :: x_mid,y_mid,xnd,ynd,scl,rr integer :: stdoutunit stdoutunit=stdout() x_min = minval( Grd%xu(:,:) ) call mpp_min(x_min) x_max = maxval( Grd%xu(:,:) ) call mpp_max(x_max) y_min = minval( Grd%yu(:,:) ) call mpp_min(y_min) y_max = maxval( Grd%yu(:,:) ) call mpp_max(y_max) scl = 0.5 * ( patch_ratio2 - patch_ratio1 ) x_mid = x_min + 0.5 * ( patch_ratio1 + patch_ratio2 ) * ( x_max - x_min ) y_mid = y_min + 0.5 * ( patch_ratio1 + patch_ratio2 ) * ( y_max - y_min ) field(:,:,:) = 0.0 iwest = int(patch_ratio1*Grd%ni) ieast = int(patch_ratio2*Grd%ni) jsouth = int(patch_ratio1*Grd%nj) jnorth = int(patch_ratio2*Grd%nj) ! Discontinuous square box for all k-levels (levels k=1,5 over-written below) do k=1,nk if(Grd%zt(k) >=patch_ztop .and. Grd%zt(k) <= patch_zbot) then do j=jsd,jed do i=isd,ied if(i+Dom%ioff >= iwest .and. i+Dom%ioff <= ieast .and. & j+Dom%joff >= jsouth .and. j+Dom%joff <= jnorth ) then field(i,j,k) = patch_value endif enddo enddo endif enddo write(stdoutunit,*) 'passive_init: ',iwest,ieast,jsouth,jnorth write(stdoutunit,*) 'passive_init: ',x_min,x_max write(stdoutunit,*) 'passive_init: ',y_min,y_max write(stdoutunit,*) 'passive_init: ',x_mid,y_mid write(stdoutunit,*) 'passive_init: ',scl ! k=1: Discontinuous square box k=1 if (nk.ge.k) then do j=jsd,jed do i=isd,ied xnd = 1.-abs(Grd%xt(i,j)-x_mid)/(x_max-x_min)/scl ynd = 1.-abs(Grd%yt(i,j)-y_mid)/(y_max-y_min)/scl field(i,j,k) = patch_value * max( 0., sign( 1., xnd ) ) & * max( 0., sign( 1., ynd ) ) enddo enddo endif ! k ! k=2: Discontinuous circular box (cylinder) k=2 if (nk.ge.k) then do j=jsd,jed do i=isd,ied xnd = (Grd%xt(i,j)-x_mid)/(x_max-x_min) ynd = (Grd%yt(i,j)-y_mid)/(y_max-y_min) rr = 1.-sqrt( xnd**2 + ynd**2 )/scl field(i,j,k) = patch_value * max( 0., sign( 1., rr ) ) enddo enddo endif ! k ! k=3: Circular cone k=3 if (nk.ge.k) then do j=jsd,jed do i=isd,ied xnd = (Grd%xt(i,j)-x_mid)/(x_max-x_min) ynd = (Grd%yt(i,j)-y_mid)/(y_max-y_min) rr = sqrt( xnd**2 + ynd**2 ) field(i,j,k) = patch_value * max( 0., 1.-0.5*rr/scl ) enddo enddo endif ! k ! k=4: Circular cosine bell k=4 if (nk.ge.k) then do j=jsd,jed do i=isd,ied xnd = (Grd%xt(i,j)-x_mid)/(x_max-x_min) ynd = (Grd%yt(i,j)-y_mid)/(y_max-y_min) rr = sqrt( xnd**2 + ynd**2 ) field(i,j,k) = patch_value * 0.5 * ( 1.0+cos(2.*pi*min(0.5,0.25*rr/scl)) ) enddo enddo endif ! k ! k=5: Circular Gaussian (with 2.5 sigma inside patch) k=5 if (nk.ge.k) then do j=jsd,jed do i=isd,ied xnd = (Grd%xt(i,j)-x_mid)/(x_max-x_min) ynd = (Grd%yt(i,j)-y_mid)/(y_max-y_min) rr = sqrt( xnd**2 + ynd**2 ) field(i,j,k) = patch_value * ( max(0.001, 1.001*exp(-(1.*rr/scl)**2) ) - 0.001 ) enddo enddo endif ! k end subroutine patch_init ! NAME="patch_init" !####################################################################### ! ! ! ! Initialize tracer with gaussian patch or constant on a level, ! both on a single k-level ! ! subroutine patch_init_klevel(field, name) real, dimension(isd:,jsd:,:), intent(inout) :: field character(len=*), intent(in) :: name integer :: i, j, k, n integer :: start, strlen, klevel, digit real :: x_min,x_max,y_min,y_max real :: x_mid,y_mid,xnd,ynd,scl,rr logical :: fatal_flag=.false. integer :: stdoutunit stdoutunit=stdout() x_min = minval( Grd%xu(:,:) ) call mpp_min(x_min) x_max = maxval( Grd%xu(:,:) ) call mpp_max(x_max) y_min = minval( Grd%yu(:,:) ) call mpp_min(y_min) y_max = maxval( Grd%yu(:,:) ) call mpp_max(y_max) scl = 0.5 * ( patch_ratio2 - patch_ratio1 ) x_mid = x_min + 0.5 * ( patch_ratio1 + patch_ratio2 ) * ( x_max - x_min ) y_mid = y_min + 0.5 * ( patch_ratio1 + patch_ratio2 ) * ( y_max - y_min ) ! determine the k-level that is to be initialized ! Algorithm from Zhi.Liang@noaa.gov ! start=15 is specific to "passive_patch_" having 14 characters, ! so the 15th character in the name of the tracer begins the klevel. ! Example: passive_patch_123. ! do n=15,17 ! when n=1, klevel=1 = 1 ! when n=2, klevel=1*10+2 = 12 ! when n=3, klevel=12*10+3 = 123 start = 15 strlen = len_trim(name) klevel = 0 fatal_flag=.false. write(stdoutunit,'(a)') ' Initializing passive_patch_klevel for tracer name = ',name do n=start,strlen digit = ichar(name(n:n)) - ichar("0") if(digit > 9 .or. digit < 0) then write(*,*)'Error: digit = ',digit fatal_flag=.true. endif klevel = klevel*10 + digit end do if(fatal_flag) then call mpp_error(FATAL, & '==>Error in ocean_passive_mod (patch_init_klevel): did not find a digit for klevel.') endif ! initialize the patch at k=klevel as a circular Gaussian ! (with 2.5 sigma inside patch) if(patch_init_klevel_gaussian) then field(:,:,:) = 0.0 do j=jsd,jed do i=isd,ied xnd = (Grd%xt(i,j)-x_mid)/(x_max-x_min) ynd = (Grd%yt(i,j)-y_mid)/(y_max-y_min) rr = sqrt( xnd**2 + ynd**2 ) field(i,j,klevel) = Grd%tmask(i,j,klevel) * patch_value & *( max(0.001, 1.001*exp(-(1.*rr/scl)**2) ) - 0.001 ) enddo enddo else do j=jsd,jed do i=isd,ied field(i,j,klevel) = patch_value*Grd%tmask(i,j,klevel) enddo enddo endif end subroutine patch_init_klevel ! NAME="patch_init_klevel" !####################################################################### ! ! ! ! ! Initialize tracer with a vertical exponential profile. ! ! ! subroutine exponential_init(field) real, intent(inout), dimension(isd:,jsd:,:) :: field integer :: i, j, k field(:,:,:) = 0.0 do k=1,nk do j=jsd,jed do i=isd,ied field(i,j,k) = exponential_value*exp(-Grd%zt(k)/efold_depth) enddo enddo enddo end subroutine exponential_init ! NAME="exponential_init" !####################################################################### ! ! ! ! ! Initialize tracer as in the shelfbowl topography of use for studying ! idealized overflow problems, as in Winton etal (1998). ! ! ! subroutine shelfbowl_init(field) real, intent(inout), dimension(isd:,jsd:,:) :: field integer :: i, j, k field(:,:,:) = 0.0 do k=1,nk do j=jsc,jec do i=isc,iec field(i,j,k) = 0.5*shelf_value*(1.0 + 0.5*(1.0-tanh(0.5*(Grd%yt(i,j)-shelfbowl_north))) ) enddo enddo enddo end subroutine shelfbowl_init ! NAME="shelfbowl_init" !####################################################################### ! ! ! ! Update the squared tracer. ! Restore passive tracers. ! ! subroutine update_tracer_passive(num_prog_tracers, T_prog, T_diag, taup1) integer, intent(in) :: num_prog_tracers type(ocean_prog_tracer_type), intent(inout) :: T_prog(:) type(ocean_diag_tracer_type), intent(inout) :: T_diag(:) integer , intent(in) :: taup1 integer :: i,j,k,n,nt real :: mask if(.not. use_this_module) return if(use_tracer_sq) then do nt=1,num_prog_tracers if(trim(T_prog(nt)%name)=='passive_temp_sq') then do k=1,nk do j=jsd,jed do i=isd,ied T_prog(nt)%field(i,j,k,1) = T_prog(index_temp)%field(i,j,k,1)**2 T_prog(nt)%field(i,j,k,2) = T_prog(index_temp)%field(i,j,k,2)**2 T_prog(nt)%field(i,j,k,3) = T_prog(index_temp)%field(i,j,k,3)**2 enddo enddo enddo endif if(trim(T_prog(nt)%name)=='passive_salt_sq') then do k=1,nk do j=jsd,jed do i=isd,ied T_prog(nt)%field(i,j,k,1) = T_prog(index_salt)%field(i,j,k,1)**2 T_prog(nt)%field(i,j,k,2) = T_prog(index_salt)%field(i,j,k,2)**2 T_prog(nt)%field(i,j,k,3) = T_prog(index_salt)%field(i,j,k,3)**2 enddo enddo enddo endif enddo endif if(use_tracer_restore) then do nt=1,num_prog_tracers do n=1,instances if( trim(T_prog(nt)%name)=='passive_'//trim(passive(n)%name) .and. passive(n)%restore ) then do k=1,nk do j=jsd,jed do i=isd,ied mask = T_diag(passive(n)%diag_index)%field(i,j,k) T_prog(nt)%field(i,j,k,taup1) = mask * passive(n)%init_value & + (1.- mask) * T_prog(nt)%field(i,j,k,taup1) enddo enddo enddo endif enddo ! n enddo ! nt endif end subroutine update_tracer_passive ! NAME="update_tracer_passive" end module ocean_passive_mod