Skip to content

Commit a81078b

Browse files
committed
Generalize support for downsample diagnostics
- Generalize _d2 diagnostics to arbitrary _dl - The maximum level MAX_DSAMP_LEV needs to be specified. Default is 4. - This branch is based on the SPREAHI code base hash 2d121dc
1 parent 2d121dc commit a81078b

7 files changed

Lines changed: 1500 additions & 575 deletions

File tree

config_src/infra/FMS2/MOM_diag_manager_infra.F90

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
! This file is part of MOM6, the Modular Ocean Model version 6.
2+
! See the LICENSE file for licensing information.
3+
! SPDX-License-Identifier: Apache-2.0
4+
15
!> A wrapper for the FMS diag_manager routines. This module should be the
26
!! only MOM6 module which imports the FMS shared infrastructure for
37
!! diagnostics. Pass through interfaces are being documented
@@ -6,21 +10,24 @@
610
!! those APIs would be applied here).
711
module MOM_diag_manager_infra
812

9-
! This file is part of MOM6. See LICENSE.md for the license.
13+
#define MAX_DSAMP_LEV 4
1014

15+
use, intrinsic :: iso_fortran_env, only : real64
1116
use diag_axis_mod, only : fms_axis_init=>diag_axis_init
1217
use diag_axis_mod, only : fms_get_diag_axis_name => get_diag_axis_name
1318
use diag_axis_mod, only : EAST, NORTH
1419
use diag_data_mod, only : null_axis_id
1520
use diag_manager_mod, only : fms_diag_manager_init => diag_manager_init
1621
use diag_manager_mod, only : fms_diag_manager_end => diag_manager_end
22+
use diag_manager_mod, only : diag_send_complete
23+
use diag_manager_mod, only : diag_manager_set_time_end
1724
use diag_manager_mod, only : send_data_fms => send_data
1825
use diag_manager_mod, only : fms_diag_field_add_attribute => diag_field_add_attribute
1926
use diag_manager_mod, only : DIAG_FIELD_NOT_FOUND
2027
use diag_manager_mod, only : register_diag_field_fms => register_diag_field
2128
use diag_manager_mod, only : register_static_field_fms => register_static_field
2229
use diag_manager_mod, only : get_diag_field_id_fms => get_diag_field_id
23-
use MOM_time_manager, only : time_type
30+
use MOM_time_manager, only : time_type, set_time
2431
use MOM_domain_infra, only : MOM_domain_type
2532
use MOM_error_infra, only : MOM_error => MOM_err, FATAL, WARNING
2633

@@ -57,6 +64,8 @@ module MOM_diag_manager_infra
5764
public MOM_diag_manager_init
5865
public MOM_diag_manager_end
5966
public send_data_infra
67+
public diag_send_complete_infra
68+
public diag_manager_set_time_end_infra
6069
public MOM_diag_field_add_attribute
6170
public register_diag_field_infra
6271
public register_static_field_infra
@@ -109,10 +118,10 @@ integer function MOM_diag_axis_init(name, data, units, cart_name, long_name, MOM
109118
MOM_diag_axis_init = fms_axis_init(name, data, units, cart_name, long_name=long_name, &
110119
direction=direction, set_name=set_name, edges=edges, &
111120
domain2=MOM_domain%mpp_domain, domain_position=position)
112-
elseif (coarsening == 2) then
121+
elseif (coarsening <= MAX_DSAMP_LEV) then
113122
MOM_diag_axis_init = fms_axis_init(name, data, units, cart_name, long_name=long_name, &
114123
direction=direction, set_name=set_name, edges=edges, &
115-
domain2=MOM_domain%mpp_domain_d2, domain_position=position)
124+
domain2=MOM_domain%mpp_domain_d(coarsening), domain_position=position)
116125
else
117126
call MOM_error(FATAL, "diag_axis_init called with an invalid value of coarsen.")
118127
endif
@@ -357,7 +366,7 @@ end function send_data_infra_3d
357366
logical function send_data_infra_2d_r8(diag_field_id, field, is_in, ie_in, js_in, je_in, &
358367
time, mask, rmask, weight, err_msg)
359368
integer, intent(in) :: diag_field_id !< The diagnostic manager identifier for this field
360-
real(kind=8), dimension(:,:), intent(in) :: field !< A 2-d array of values being recorded
369+
real(kind=real64), dimension(:,:), intent(in) :: field !< A 2-d array of values being recorded
361370
integer, optional, intent(in) :: is_in !< The starting i-index for the data being recorded
362371
integer, optional, intent(in) :: ie_in !< The end i-index for the data being recorded
363372
integer, optional, intent(in) :: js_in !< The starting j-index for the data being recorded
@@ -380,7 +389,7 @@ end function send_data_infra_2d_r8
380389
logical function send_data_infra_3d_r8(diag_field_id, field, is_in, ie_in, js_in, je_in, ks_in, ke_in, &
381390
time, mask, rmask, weight, err_msg)
382391
integer, intent(in) :: diag_field_id !< The diagnostic manager identifier for this field
383-
real(kind=8), dimension(:,:,:), intent(in) :: field !< A rank 1 array of floating point values being recorded
392+
real(kind=real64), dimension(:,:,:), intent(in) :: field !< A rank 1 array of floating point values being recorded
384393
integer, optional, intent(in) :: is_in !< The starting i-index for the data being recorded
385394
integer, optional, intent(in) :: ie_in !< The end i-index for the data being recorded
386395
integer, optional, intent(in) :: js_in !< The starting j-index for the data being recorded
@@ -451,4 +460,19 @@ subroutine MOM_diag_field_add_attribute_i1d(diag_field_id, att_name, att_value)
451460

452461
end subroutine MOM_diag_field_add_attribute_i1d
453462

463+
!> Finishes the diag manager reduction methods as needed for the time_step
464+
subroutine diag_send_complete_infra ()
465+
!! The time_step in the diag_send_complete call is a dummy argument, needed for backwards compatibility
466+
!! It won't be used at all when diag_manager_nml::use_modern_diag=.true.
467+
!! It won't have any impact when diag_manager_nml::use_modern_diag=.false.
468+
call diag_send_complete (set_time(0))
469+
end subroutine diag_send_complete_infra
470+
471+
!> Sets the time that the simulation ends in the diag manager
472+
subroutine diag_manager_set_time_end_infra(time)
473+
type(time_type), optional, intent(in) :: time !< The time the simulation ends
474+
475+
call diag_manager_set_time_end(time)
476+
end subroutine diag_manager_set_time_end_infra
477+
454478
end module MOM_diag_manager_infra

config_src/infra/FMS2/MOM_domain_infra.F90

Lines changed: 88 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
! This file is part of MOM6, the Modular Ocean Model version 6.
2+
! See the LICENSE file for licensing information.
3+
! SPDX-License-Identifier: Apache-2.0
4+
15
!> Describes the decomposed MOM domain and has routines for communications across PEs
26
module MOM_domain_infra
37

4-
! This file is part of MOM6. See LICENSE.md for the license.
5-
68
use MOM_coms_infra, only : PE_here, root_PE, num_PEs
79
use MOM_cpu_clock_infra, only : cpu_clock_begin, cpu_clock_end
810
use MOM_error_infra, only : MOM_error=>MOM_err, NOTE, WARNING, FATAL
@@ -32,6 +34,7 @@ module MOM_domain_infra
3234

3335
! The `group_pass_type` fields are never accessed, so we keep it as an FMS type
3436
use mpp_domains_mod, only : group_pass_type => mpp_group_update_type
37+
#define MAX_DSAMP_LEV 4
3538

3639
implicit none ; private
3740

@@ -131,7 +134,7 @@ module MOM_domain_infra
131134
character(len=64) :: name !< The name of this domain
132135
type(domain2D), pointer :: mpp_domain => NULL() !< The FMS domain with halos
133136
!! on this processor, centered at h points.
134-
type(domain2D), pointer :: mpp_domain_d2 => NULL() !< A coarse FMS domain with halos
137+
type(domain2D), pointer :: mpp_domain_d(:) => NULL() !< A coarse FMS domain with halos
135138
!! on this processor, centered at h points.
136139
integer :: niglobal !< The total horizontal i-domain size.
137140
integer :: njglobal !< The total horizontal j-domain size.
@@ -1212,7 +1215,7 @@ subroutine redistribute_array_2d(Domain1, array1, Domain2, array2, complete)
12121215
! Local variables
12131216
logical :: do_complete
12141217

1215-
do_complete=.true.;if (PRESENT(complete)) do_complete = complete
1218+
do_complete=.true. ; if (PRESENT(complete)) do_complete = complete
12161219

12171220
call mpp_redistribute(Domain1, array1, Domain2, array2, do_complete)
12181221

@@ -1231,7 +1234,7 @@ subroutine redistribute_array_3d(Domain1, array1, Domain2, array2, complete)
12311234
! Local variables
12321235
logical :: do_complete
12331236

1234-
do_complete=.true.;if (PRESENT(complete)) do_complete = complete
1237+
do_complete=.true. ; if (PRESENT(complete)) do_complete = complete
12351238

12361239
call mpp_redistribute(Domain1, array1, Domain2, array2, do_complete)
12371240

@@ -1250,61 +1253,97 @@ subroutine redistribute_array_4d(Domain1, array1, Domain2, array2, complete)
12501253
! Local variables
12511254
logical :: do_complete
12521255

1253-
do_complete=.true.;if (PRESENT(complete)) do_complete = complete
1256+
do_complete=.true. ; if (PRESENT(complete)) do_complete = complete
12541257

12551258
call mpp_redistribute(Domain1, array1, Domain2, array2, do_complete)
12561259

12571260
end subroutine redistribute_array_4d
12581261

12591262

12601263
!> Rescale the values of a 4-D array in its computational domain by a constant factor
1261-
subroutine rescale_comp_data_4d(domain, array, scale)
1264+
subroutine rescale_comp_data_4d(domain, array, scale, zero_zeros)
12621265
type(MOM_domain_type), intent(in) :: domain !< MOM domain from which to extract information
12631266
real, dimension(:,:,:,:), intent(inout) :: array !< The array which is having the data in its
12641267
!! computational domain rescaled
12651268
real, intent(in) :: scale !< A scaling factor by which to multiply the
12661269
!! values in the computational domain of array
1267-
integer :: is, ie, js, je
1270+
logical, optional, intent(in) :: zero_zeros !< If present and true, convert negative zeros
1271+
!! into ordinary signless zeros.
1272+
logical :: unsign_zeros ! If true, convert negative zeros into ordinary signless zeros.
1273+
integer :: is, ie, js, je, i, j, k, m
12681274

1269-
if (scale == 1.0) return
1275+
unsign_zeros = .false. ; if (present(zero_zeros)) unsign_zeros = zero_zeros
1276+
1277+
if ((scale == 1.0) .and. (.not.unsign_zeros)) return
12701278

12711279
call get_simple_array_i_ind(domain, size(array,1), is, ie)
12721280
call get_simple_array_j_ind(domain, size(array,2), js, je)
1273-
array(is:ie,js:je,:,:) = scale*array(is:ie,js:je,:,:)
1281+
if (scale /= 1.0) &
1282+
array(is:ie,js:je,:,:) = scale*array(is:ie,js:je,:,:)
1283+
1284+
if (unsign_zeros) then ! Convert negative zeros into zeros
1285+
do m=1,size(array,4) ; do k=1,size(array,3) ; do j=js,je ; do i=is,ie
1286+
if (array(i,j,k,m) == 0.0) array(i,j,k,m) = 0.0
1287+
enddo ; enddo ; enddo ; enddo
1288+
endif
12741289

12751290
end subroutine rescale_comp_data_4d
12761291

12771292
!> Rescale the values of a 3-D array in its computational domain by a constant factor
1278-
subroutine rescale_comp_data_3d(domain, array, scale)
1293+
subroutine rescale_comp_data_3d(domain, array, scale, zero_zeros)
12791294
type(MOM_domain_type), intent(in) :: domain !< MOM domain from which to extract information
12801295
real, dimension(:,:,:), intent(inout) :: array !< The array which is having the data in its
12811296
!! computational domain rescaled
12821297
real, intent(in) :: scale !< A scaling factor by which to multiply the
12831298
!! values in the computational domain of array
1284-
integer :: is, ie, js, je
1299+
logical, optional, intent(in) :: zero_zeros !< If present and true, convert negative zeros
1300+
!! into ordinary signless zeros.
1301+
logical :: unsign_zeros ! If true, convert negative zeros into ordinary signless zeros.
1302+
integer :: is, ie, js, je, i, j, k
1303+
1304+
unsign_zeros = .false. ; if (present(zero_zeros)) unsign_zeros = zero_zeros
12851305

1286-
if (scale == 1.0) return
1306+
if ((scale == 1.0) .and. (.not.unsign_zeros)) return
12871307

12881308
call get_simple_array_i_ind(domain, size(array,1), is, ie)
12891309
call get_simple_array_j_ind(domain, size(array,2), js, je)
1290-
array(is:ie,js:je,:) = scale*array(is:ie,js:je,:)
1310+
if (scale /= 1.0) &
1311+
array(is:ie,js:je,:) = scale*array(is:ie,js:je,:)
1312+
1313+
if (unsign_zeros) then ! Convert negative zeros into zeros
1314+
do k=1,size(array,3) ; do j=js,je ; do i=is,ie
1315+
if (array(i,j,k) == 0.0) array(i,j,k) = 0.0
1316+
enddo ; enddo ; enddo
1317+
endif
12911318

12921319
end subroutine rescale_comp_data_3d
12931320

12941321
!> Rescale the values of a 2-D array in its computational domain by a constant factor
1295-
subroutine rescale_comp_data_2d(domain, array, scale)
1322+
subroutine rescale_comp_data_2d(domain, array, scale, zero_zeros)
12961323
type(MOM_domain_type), intent(in) :: domain !< MOM domain from which to extract information
12971324
real, dimension(:,:), intent(inout) :: array !< The array which is having the data in its
12981325
!! computational domain rescaled
12991326
real, intent(in) :: scale !< A scaling factor by which to multiply the
13001327
!! values in the computational domain of array
1301-
integer :: is, ie, js, je
1328+
logical, optional, intent(in) :: zero_zeros !< If present and true, convert negative zeros
1329+
!! into ordinary signless zeros.
1330+
logical :: unsign_zeros ! If true, convert negative zeros into ordinary signless zeros.
1331+
integer :: is, ie, js, je, i, j
13021332

1303-
if (scale == 1.0) return
1333+
unsign_zeros = .false. ; if (present(zero_zeros)) unsign_zeros = zero_zeros
1334+
1335+
if ((scale == 1.0) .and. (.not.unsign_zeros)) return
13041336

13051337
call get_simple_array_i_ind(domain, size(array,1), is, ie)
13061338
call get_simple_array_j_ind(domain, size(array,2), js, je)
1307-
array(is:ie,js:je) = scale*array(is:ie,js:je)
1339+
if (scale /= 1.0) &
1340+
array(is:ie,js:je) = scale*array(is:ie,js:je)
1341+
1342+
if (unsign_zeros) then ! Convert negative zeros into zeros
1343+
do j=js,je ; do i=is,ie
1344+
if (array(i,j) == 0.0) array(i,j) = 0.0
1345+
enddo ; enddo
1346+
endif
13081347

13091348
end subroutine rescale_comp_data_2d
13101349

@@ -1333,14 +1372,14 @@ subroutine create_MOM_domain(MOM_dom, n_global, n_halo, reentrant, tripolar_N, l
13331372
integer, dimension(4) :: global_indices ! The lower and upper global i- and j-index bounds
13341373
integer :: X_FLAGS ! A combination of integers encoding the x-direction grid connectivity.
13351374
integer :: Y_FLAGS ! A combination of integers encoding the y-direction grid connectivity.
1336-
integer :: xhalo_d2, yhalo_d2
1375+
integer :: dl
13371376
character(len=200) :: mesg ! A string for use in error messages
13381377
logical :: mask_table_exists ! Mask_table is present and the file it points to exists
13391378

13401379
if (.not.associated(MOM_dom)) then
13411380
allocate(MOM_dom)
13421381
allocate(MOM_dom%mpp_domain)
1343-
allocate(MOM_dom%mpp_domain_d2)
1382+
do dl=2,MAX_DSAMP_LEV ; allocate(MOM_dom%mpp_domain_d(dl)) ; enddo
13441383
endif
13451384

13461385
MOM_dom%name = "MOM" ; if (present(domain_name)) MOM_dom%name = trim(domain_name)
@@ -1354,8 +1393,10 @@ subroutine create_MOM_domain(MOM_dom, n_global, n_halo, reentrant, tripolar_N, l
13541393
"TRIPOLAR_N and REENTRANT_Y may not be used together.")
13551394
endif
13561395

1357-
MOM_dom%nonblocking_updates = nonblocking
1358-
MOM_dom%thin_halo_updates = thin_halos
1396+
MOM_dom%nonblocking_updates = .false.
1397+
if (present(nonblocking)) MOM_dom%nonblocking_updates = nonblocking
1398+
MOM_dom%thin_halo_updates = .false.
1399+
if (present(thin_halos)) MOM_dom%thin_halo_updates = thin_halos
13591400
MOM_dom%symmetric = .true. ; if (present(symmetric)) MOM_dom%symmetric = symmetric
13601401
MOM_dom%niglobal = n_global(1) ; MOM_dom%njglobal = n_global(2)
13611402
MOM_dom%nihalo = n_halo(1) ; MOM_dom%njhalo = n_halo(2)
@@ -1406,11 +1447,12 @@ subroutine create_MOM_domain(MOM_dom, n_global, n_halo, reentrant, tripolar_N, l
14061447

14071448
call clone_MD_to_d2D(MOM_dom, MOM_dom%mpp_domain)
14081449

1409-
!For downsampled domain, recommend a halo of 1 (or 0?) since we're not doing wide-stencil computations.
1410-
!But that does not work because the downsampled field would not have the correct size to pass the checks, e.g., we get
1411-
!error: downsample_diag_indices_get: peculiar size 28 in i-direction\ndoes not match one of 24 25 26 27
1412-
! call clone_MD_to_d2D(MOM_dom, MOM_dom%mpp_domain_d2, halo_size=(MOM_dom%nihalo/2), coarsen=2)
1413-
call clone_MD_to_d2D(MOM_dom, MOM_dom%mpp_domain_d2, coarsen=2)
1450+
do dl=2,MAX_DSAMP_LEV
1451+
!Downsample diagnostics calculations do not need halos.
1452+
call clone_MD_to_d2D(MOM_dom, MOM_dom%mpp_domain_d(dl), coarsen=dl, halo_size=0, &
1453+
domain_name="MOM_domain_d" // char(48+dl))
1454+
enddo
1455+
14141456
end subroutine create_MOM_domain
14151457

14161458
!> dealloc_MOM_domain deallocates memory associated with a pointer to a MOM_domain_type
@@ -1420,6 +1462,7 @@ subroutine deallocate_MOM_domain(MOM_domain, cursory)
14201462
logical, optional, intent(in) :: cursory !< If true do not deallocate fields associated
14211463
!! with the underlying infrastructure
14221464
logical :: invasive ! If true, deallocate fields associated with the underlying infrastructure
1465+
integer :: dl
14231466

14241467
invasive = .true. ; if (present(cursory)) invasive = .not.cursory
14251468

@@ -1428,9 +1471,11 @@ subroutine deallocate_MOM_domain(MOM_domain, cursory)
14281471
if (invasive) call mpp_deallocate_domain(MOM_domain%mpp_domain)
14291472
deallocate(MOM_domain%mpp_domain)
14301473
endif
1431-
if (associated(MOM_domain%mpp_domain_d2)) then
1432-
if (invasive) call mpp_deallocate_domain(MOM_domain%mpp_domain_d2)
1433-
deallocate(MOM_domain%mpp_domain_d2)
1474+
if (associated(MOM_domain%mpp_domain_d)) then
1475+
if (invasive) then
1476+
do dl=2,MAX_DSAMP_LEV ; call mpp_deallocate_domain(MOM_domain%mpp_domain_d(dl)); enddo
1477+
endif
1478+
deallocate(MOM_domain%mpp_domain_d)
14341479
endif
14351480
if (associated(MOM_domain%maskmap)) deallocate(MOM_domain%maskmap)
14361481
deallocate(MOM_domain)
@@ -1527,7 +1572,7 @@ subroutine clone_MD_to_MD(MD_in, MOM_dom, min_halo, halo_size, symmetric, domain
15271572
integer, dimension(:), allocatable :: exnj ! The extents of the grid for each j-row of the layout.
15281573
! The sum of exni must equal MOM_dom%niglobal.
15291574
integer :: qturns ! The number of quarter turns, restricted to the range of 0 to 3.
1530-
integer :: i, j, nl1, nl2
1575+
integer :: i, j, nl1, nl2, dl
15311576
integer :: io_layout_in(2)
15321577

15331578
qturns = 0
@@ -1542,7 +1587,7 @@ subroutine clone_MD_to_MD(MD_in, MOM_dom, min_halo, halo_size, symmetric, domain
15421587
if (.not.associated(MOM_dom)) then
15431588
allocate(MOM_dom)
15441589
allocate(MOM_dom%mpp_domain)
1545-
allocate(MOM_dom%mpp_domain_d2)
1590+
do dl=2,MAX_DSAMP_LEV ; allocate(MOM_dom%mpp_domain_d(dl)) ; enddo
15461591
endif
15471592

15481593
! Save the extra data for creating other domains of different resolution that overlay this domain
@@ -1664,7 +1709,11 @@ subroutine clone_MD_to_MD(MD_in, MOM_dom, min_halo, halo_size, symmetric, domain
16641709
endif
16651710

16661711
call clone_MD_to_d2D(MOM_dom, MOM_dom%mpp_domain, xextent=exni, yextent=exnj)
1667-
call clone_MD_to_d2D(MOM_dom, MOM_dom%mpp_domain_d2, domain_name=MOM_dom%name, coarsen=2)
1712+
do dl=2,MAX_DSAMP_LEV
1713+
!Downsample diagnostics calculations do not need halos.
1714+
call clone_MD_to_d2D(MOM_dom, MOM_dom%mpp_domain_d(dl), coarsen=dl, halo_size=0, &
1715+
domain_name="MOM_domain_d" // char(48+dl))
1716+
enddo
16681717

16691718
end subroutine clone_MD_to_MD
16701719

@@ -1802,12 +1851,12 @@ subroutine get_domain_extent_MD(Domain, isc, iec, jsc, jec, isd, ied, jsd, jed,
18021851
call mpp_get_compute_domain(Domain%mpp_domain, isc, iec, jsc, jec)
18031852
call mpp_get_data_domain(Domain%mpp_domain, isd, ied, jsd, jed)
18041853
call mpp_get_global_domain(Domain%mpp_domain, isg_, ieg_, jsg_, jeg_)
1805-
elseif (coarsen_lev == 2) then
1806-
if (.not.associated(Domain%mpp_domain_d2)) call MOM_error(FATAL, &
1807-
"get_domain_extent called with coarsen=2, but Domain%mpp_domain_d2 is not associated.")
1808-
call mpp_get_compute_domain(Domain%mpp_domain_d2, isc, iec, jsc, jec)
1809-
call mpp_get_data_domain(Domain%mpp_domain_d2, isd, ied, jsd, jed)
1810-
call mpp_get_global_domain(Domain%mpp_domain_d2, isg_, ieg_, jsg_, jeg_)
1854+
elseif (coarsen_lev <= MAX_DSAMP_LEV) then
1855+
if (.not.associated(Domain%mpp_domain_d)) call MOM_error(FATAL, &
1856+
"get_domain_extent called with coarsen_lev, but Domain%mpp_domain_d(coarsen_lev) is not associated.")
1857+
call mpp_get_compute_domain(Domain%mpp_domain_d(coarsen_lev), isc, iec, jsc, jec)
1858+
call mpp_get_data_domain(Domain%mpp_domain_d(coarsen_lev), isd, ied, jsd, jed)
1859+
call mpp_get_global_domain(Domain%mpp_domain_d(coarsen_lev), isg_, ieg_, jsg_, jeg_)
18111860
else
18121861
call MOM_error(FATAL, "get_domain_extent called with an unsupported level of coarsening.")
18131862
endif

0 commit comments

Comments
 (0)