!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! !!
!! 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_domains_mod
!
! Matthew Harrison
!
!
!
! Set the ocean domain parameters.
!
!
!
! The module computes the horizontal domain parameters needed to
! run mom4 in a parallel computational environment.
!
!
!
!
!
! S.M. Griffies, M.J. Harrison, R.C. Pacanowski, and A. Rosati
! A Technical Guide to MOM4 (2003)
!
!
!
!
!
!
! For specifying the halo size by hand.
!
!
! temporary - need to call domains_init before tracer_init
! Used for computing mpp_stack_size.
!
!
! offset to be applied on x-direction boundary condition. Its value could
! be positive or negative and the default value is 0. When the y-direction
! boundary condition is folded-north(tripolar grid), x_cyclic_offset must
! be 0. For torus (cyclic in x and y-direction), at least one of
! x_cyclic_offset and y_cyclic_offset must be 0.
!
!
! offset to be applied on y-direction boundary condition. Its value could
! be positive or negative and the default value is 0. For torus (cyclic
! in x and y-direction), at least one of x_cyclic_offset and
! y_cyclic_offset must be 0.
!
!
use fms_mod, only: open_namelist_file, write_version_number, check_nml_error, close_file
use mpp_domains_mod, only: mpp_define_layout, mpp_define_domains, mpp_domains_set_stack_size
use mpp_domains_mod, only: mpp_get_compute_domain, mpp_get_data_domain, mpp_get_global_domain
use mpp_domains_mod, only: FOLD_NORTH_EDGE, CYCLIC_GLOBAL_DOMAIN, mpp_define_io_domain
use mpp_mod, only: mpp_max, mpp_min, mpp_npes, mpp_error, FATAL, stdout, stdlog
use ocean_types_mod, only: ocean_domain_type, ocean_grid_type
use ocean_types_mod, only: ocean_prog_tracer_type, ocean_velocity_type
implicit none
private
integer, dimension(2) :: domain_layout=(/1,1/)
integer, dimension(2) :: io_domain_layout=(/0,0/)
character(len=128) :: version='$Id: ocean_domains.F90,v 16.0.42.1.2.1.50.1 2009/10/10 00:41:54 nnz Exp $'
character(len=128) :: tagname='$Name: mom4p1_pubrel_dec2009_nnz $'
character(len=32) :: name_default = 'mom_domain'
public set_ocean_domain
public get_local_indices
public get_halo_sizes
public get_global_indices
public get_active_indices
public reduce_active_domain
public get_domain_offsets
integer :: halo=1 ! size (cells) of halo region
integer :: max_tracers = 10 ! temporary - need to call domains_init before tracer_init
integer :: x_cyclic_offset=0 ! offset applied to x-direction cyclic boundary condition
integer :: y_cyclic_offset=0 ! offset applied to y-direction cyclic boundary condition
namelist /ocean_domains_nml/ halo, max_tracers, x_cyclic_offset, y_cyclic_offset
contains
!#######################################################################
!
!
!
! For setting the ocean domain layout and associated parameters.
!
!
subroutine set_ocean_domain (Domain, Grid, xhalo, yhalo, name, layout, io_layout, maskmap)
type(ocean_grid_type), intent(in) :: Grid
type(ocean_domain_type), intent(inout) :: Domain
integer, intent(in), optional :: xhalo, yhalo, layout(2), io_layout(2)
logical, intent(in), optional :: maskmap(:,:)
character(len=*), intent(in), optional :: name
real :: ph, pc
integer :: n, ioun, io_status, nhp, ncp, ncp_max, ncp_min, ncpx, ncpy, lay_out(2), xsiz, ysiz
integer :: mpp_stack_size=-1 ! temporary - need to call domains_init before tracer_init
character(len=32) :: name_
character(len=4) :: char_lay1, char_lay2, char_npes, char_xsiz, char_ysiz
integer :: stdoutunit,stdlogunit
stdoutunit=stdout();stdlogunit=stdlog()
call write_version_number(version, tagname)
! provide for namelist over-ride
ioun = open_namelist_file()
read (ioun, ocean_domains_nml,iostat=io_status)
write (stdlogunit,ocean_domains_nml)
write (stdoutunit,'(/)')
write (stdoutunit,ocean_domains_nml)
call close_file(ioun)
if (PRESENT(layout)) domain_layout = layout
if (PRESENT(io_layout)) io_domain_layout = io_layout
if (domain_layout(1) == 1 .and. domain_layout(2) == 1) then
call mpp_define_layout ((/1,Grid%ni,1,Grid%nj/), mpp_npes(), lay_out)
else
lay_out = domain_layout
endif
Domain%layout = lay_out
Domain%io_layout = io_domain_layout
allocate(Domain%maskmap(lay_out(1), lay_out(2)) )
if(PRESENT(maskmap)) then
Domain%maskmap = maskmap
else
Domain%maskmap = .TRUE.
end if
if (PRESENT(name)) then
name_ = trim(name)
else
name_ = trim(name_default)
endif
if (PRESENT(xhalo)) then
Domain%xhalo=xhalo
else
Domain%xhalo=halo
endif
if (PRESENT(yhalo)) then
Domain%yhalo=yhalo
else
Domain%yhalo=halo
endif
! setup 2D domains for local x-y regions (including halos) on each processor.
if (Grid%cyclic_x) then
! spherical with tripolar Arctic
if (Grid%tripolar) then
if(x_cyclic_offset .NE. 0) call mpp_error(FATAL, &
'==>Error in ocean_domains_mod: x_cyclic_offset must be 0 for tripolar grid')
call mpp_define_domains( (/1,Grid%ni,1,Grid%nj/), lay_out, Domain%domain2d, maskmap = Domain%maskmap&
, xflags = cyclic_global_domain, yflags = FOLD_NORTH_EDGE, xhalo=Domain%xhalo, yhalo=Domain%yhalo,name=name_)
Domain%xflags = cyclic_global_domain
Domain%yflags = FOLD_NORTH_EDGE
! torus
elseif(Grid%cyclic_y) then
if(x_cyclic_offset*y_cyclic_offset .NE. 0) call mpp_error(FATAL, &
'==>Error in ocean_domains_mod: at least one of x_cyclic_offset and y_cyclic_offset must be 0 for torus')
call mpp_define_domains( (/1,Grid%ni,1,Grid%nj/), lay_out, Domain%domain2d, maskmap = Domain%maskmap&
, xflags = cyclic_global_domain, yflags = cyclic_global_domain, xhalo=Domain%xhalo, yhalo=Domain%yhalo, name=name_&
, x_cyclic_offset=x_cyclic_offset, y_cyclic_offset=y_cyclic_offset)
Domain%xflags = cyclic_global_domain
Domain%yflags = cyclic_global_domain
! cyclic in x and solid wall in y
else
call mpp_define_domains( (/1,Grid%ni,1,Grid%nj/), lay_out, Domain%domain2d, maskmap = Domain%maskmap&
, xflags = cyclic_global_domain, xhalo=Domain%xhalo, yhalo=Domain%yhalo,name=name_, x_cyclic_offset=x_cyclic_offset)
Domain%xflags = cyclic_global_domain
Domain%yflags = 0
endif
else
! cyclic in y and solid wall in x (only physically relevant on beta or f plane)
if(Grid%cyclic_y) then
call mpp_define_domains( (/1,Grid%ni,1,Grid%nj/), lay_out, Domain%domain2d, maskmap = Domain%maskmap&
, yflags = cyclic_global_domain, xhalo=Domain%xhalo, yhalo=Domain%yhalo,name=name_, y_cyclic_offset=y_cyclic_offset)
Domain%xflags = 0
Domain%yflags = cyclic_global_domain
! four solid walls
else
call mpp_define_domains( (/1,Grid%ni,1,Grid%nj/), lay_out, Domain%domain2d, maskmap = Domain%maskmap&
, xhalo=Domain%xhalo, yhalo=Domain%yhalo,name=name_)
Domain%xflags = 0
Domain%yflags = 0
endif
endif
call mpp_define_io_domain(Domain%domain2d, io_domain_layout)
Domain%x_cyclic_offset = x_cyclic_offset
Domain%y_cyclic_offset = y_cyclic_offset
! define data and compute indices for local domain on this processor
call mpp_get_compute_domain (Domain%domain2d, Domain%isc, Domain%iec, &
Domain%jsc, Domain%jec)
call mpp_get_data_domain (Domain%domain2d, Domain%isd, Domain%ied, &
Domain%jsd, Domain%jed)
call mpp_get_global_domain (Domain%domain2d, Domain%isg, Domain%ieg, &
Domain%jsg, Domain%jeg)
Domain%isa = Domain%isc
Domain%iea = Domain%iec
Domain%jsa = Domain%jsc
Domain%jea = Domain%jec
Domain%ioff = 0
Domain%joff = 0
#ifdef MOM4_STATIC_ARRAYS
if (Domain%xhalo == 1 .AND. Domain%yhalo == 1) then
xsiz = Domain%iec - Domain%isc + 1
ysiz = Domain%jec - Domain%jsc + 1
Domain%ioff = Domain%isc - 1
Domain%isc = 1
Domain%isd = 0
Domain%iec = xsiz
Domain%ied = xsiz+1
Domain%joff = Domain%jsc - 1
Domain%jsc = 1
Domain%jsd = 0
Domain%jec = ysiz
Domain%jed = ysiz+1
if (xsiz /= NI_LOCAL_ .OR. ysiz /= NJ_LOCAL_) then
write( char_xsiz,'(i4)' ) xsiz
write( char_ysiz,'(i4)' ) ysiz
call mpp_error(FATAL,'==>Error in ocean_domains_mod: domain size (xsiz,ysiz) = ('&
//trim(char_xsiz)//','//trim(char_ysiz)// ') does not match size set by preprocessor macro.&
& Disable MOM4_STATIC_ARRAYS cpp-preprocessor option to use dynamic allocation. ')
endif
endif
#endif
ncp_max = (Domain%iec-Domain%isc+1)*(Domain%jec-Domain%jsc+1)
ncp_min = ncp_max
call mpp_max(ncp_max)
call mpp_min(ncp_min)
ncp = (Domain%iec-Domain%isc+1)*(Domain%jec-Domain%jsc+1)
nhp = 4*halo**2 + 2*(Domain%iec-Domain%isc+1 + Domain%jec-Domain%jsc+1)*halo
ph = 100.0*nhp/(nhp+ncp)
pc = 100.0 - ph
! estimate stack size
if (mpp_stack_size <= 0) then
ncpx = Domain%iec-Domain%isc+1
ncpy = Domain%jec-Domain%jsc+1
call mpp_max (ncpx)
call mpp_max (ncpy)
mpp_stack_size = 2*(ncpx + 2*max(Domain%xhalo,Domain%yhalo))*&
(ncpy + 2*max(Domain%xhalo,Domain%yhalo))*Grid%nk*(max_tracers)
endif
call mpp_domains_set_stack_size(mpp_stack_size)
end subroutine set_ocean_domain
! NAME="set_ocean_domain"
!#######################################################################
!
!
!
! For getting local indices from domain derived type.
!
!
subroutine get_local_indices(Domain, isd, ied, jsd, jed, isc, iec, jsc, jec)
type(ocean_domain_type), intent(in) :: Domain
integer, intent(out) :: isd, ied, jsd, jed, isc, iec, jsc, jec
isd=Domain%isd;ied=Domain%ied;jsd=Domain%jsd;jed=Domain%jed
isc=Domain%isc;iec=Domain%iec;jsc=Domain%jsc;jec=Domain%jec
end subroutine get_local_indices
! NAME="get_local_indices"
!#######################################################################
!
!
!
! For getting domain offsets from domain derived type.
!
!
subroutine get_domain_offsets(Domain, ioff, joff)
type(ocean_domain_type), intent(in) :: Domain
integer, intent(out) :: ioff, joff
ioff = Domain%ioff
joff = Domain%joff
end subroutine get_domain_offsets
! NAME="get_domain_offsets"
!#######################################################################
!
!
!
! For getting active domain indices from domain derived type.
!
!
subroutine get_active_indices(Domain, isa, iea, jsa, jea)
type(ocean_domain_type), intent(in) :: Domain
integer, intent(out) :: isa, iea, jsa, jea
isa=Domain%isa;iea=Domain%iea;jsa=Domain%jsa;jea=Domain%jea
end subroutine get_active_indices
! NAME="get_active_indices"
!#######################################################################
!
!
!
! For getting global indices from domain derived type.
!
!
subroutine get_global_indices(Domain, isg, ieg, jsg, jeg)
type(ocean_domain_type), intent(in) :: Domain
integer, intent(out) :: isg, ieg, jsg, jeg
isg=Domain%isg;ieg=Domain%ieg;jsg=Domain%jsg;jeg=Domain%jeg
end subroutine get_global_indices
! NAME="get_global_indices"
!#######################################################################
!
!
!
! For getting reducing the active domain
!
!
subroutine reduce_active_domain(Domain,inc_x,inc_y)
type(ocean_domain_type), intent(inout) :: Domain
integer, intent(in), optional :: inc_x, inc_y
integer :: inc
if (PRESENT(inc_x)) then
if (inc_x < 1) call mpp_error(FATAL,'==>Error: active domain decrement must be positive')
inc = inc_x
else
inc = 1
endif
Domain%isa = Domain%isa + inc
Domain%iea = Domain%iea - inc
if (PRESENT(inc_y)) then
if (inc_y < 1) call mpp_error(FATAL,'==>Error: active domain decrement must be positive')
inc = inc_y
else
inc = 1
endif
Domain%jsa = Domain%jsa + inc
Domain%jea = Domain%jea - inc
end subroutine reduce_active_domain
! NAME="reduce_active_domain"
!#######################################################################
!
!
!
! For getting halo sizes from domain derived type.
!
!
subroutine get_halo_sizes(Domain, xhalo, yhalo)
type(ocean_domain_type), intent(in) :: Domain
integer, intent(out), optional :: xhalo, yhalo
if (PRESENT(xhalo)) xhalo = Domain%xhalo
if (PRESENT(yhalo)) yhalo = Domain%yhalo
end subroutine get_halo_sizes
! NAME="get_halo_sizes"
end module ocean_domains_mod