FV3 Bundle
coupler_types.F90
Go to the documentation of this file.
1 !***********************************************************************
2 !* GNU Lesser General Public License
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* FMS is free software: you can redistribute it and/or modify it under
7 !* the terms of the GNU Lesser General Public License as published by
8 !* the Free Software Foundation, either version 3 of the License, or (at
9 !* your option) any later version.
10 !*
11 !* FMS is distributed in the hope that it will be useful, but WITHOUT
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 !* for more details.
15 !*
16 !* You should have received a copy of the GNU Lesser General Public
17 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 !***********************************************************************
19 
20 !> \brief This module contains type declarations for the coupler.
21 !!
22 !! \author Richard Slater <Richard.Slater@noaa.gov>
23 !! \author John Dunne <John.Dunne@noaa.gov>
25 
26  use fms_mod, only: write_version_number
29  use time_manager_mod, only: time_type
33  use mpp_mod, only: mpp_error, fatal, mpp_chksum
34 
35 
36  implicit none
37  private
38 
39 
40  ! Include variable "version" to be written to log file.
41 #include<file_version.h>
42 
43  public coupler_types_init
51 
54 
55  character(len=*), parameter :: mod_name = 'coupler_types_mod'
56 
57  ! 3-d fields
58  type, public :: coupler_3d_values_type
59  character(len=48) :: name = ' ' !< The diagnostic name for this array
60  real, pointer, contiguous, dimension(:,:,:) :: values => null() !< The pointer to the
61  !! array of values for this field; this
62  !! should be changed to allocatable
63  logical :: mean = .true. !< mean
64  logical :: override = .false. !< override
65  integer :: id_diag = 0 !< The diagnostic id for this array
66  character(len=128) :: long_name = ' ' !< The diagnostic long_name for this array
67  character(len=128) :: units = ' ' !< The units for this array
68  integer :: id_rest = 0 !< The id of this array in the restart field
69  logical :: may_init = .true. !< If true, there is an internal method
70  !! that can be used to initialize this field
71  !! if it can not be read from a restart file
72  end type coupler_3d_values_type
73 
74  type, public :: coupler_3d_field_type
75  character(len=48) :: name = ' ' !< name
76  integer :: num_fields = 0 !< num_fields
77  type(coupler_3d_values_type), pointer, dimension(:) :: field => null() !< field
78  character(len=128) :: flux_type = ' ' !< flux_type
79  character(len=128) :: implementation = ' ' !< implementation
80  real, pointer, dimension(:) :: param => null() !< param
81  logical, pointer, dimension(:) :: flag => null() !< flag
82  integer :: atm_tr_index = 0 !< atm_tr_index
83  character(len=128) :: ice_restart_file = ' ' !< ice_restart_file
84  character(len=128) :: ocean_restart_file = ' ' !< ocean_restart_file
85  type(restart_file_type), pointer :: rest_type => null() !< A pointer to the restart_file_type
86  !! that is used for this field.
87  logical :: use_atm_pressure !< use_atm_pressure
88  logical :: use_10m_wind_speed !< use_10m_wind_speed
89  logical :: pass_through_ice !< pass_through_ice
90  real :: mol_wt = 0.0 !< mol_wt
91  end type coupler_3d_field_type
92 
93  type, public :: coupler_3d_bc_type
94  integer :: num_bcs = 0 !< The number of boundary condition fields
95  type(coupler_3d_field_type), dimension(:), pointer :: bc => null() !< A pointer to the array of boundary condition fields
96  logical :: set = .false. !< If true, this type has been initialized
97  integer :: isd, isc, iec, ied !< The i-direction data and computational domain index ranges for this type
98  integer :: jsd, jsc, jec, jed !< The j-direction data and computational domain index ranges for this type
99  integer :: ks, ke !< The k-direction index ranges for this type
100  end type coupler_3d_bc_type
101 
102 
103  ! 2-d fields
104  type, public :: coupler_2d_values_type
105  character(len=48) :: name = ' ' !< The diagnostic name for this array
106  real, pointer, contiguous, dimension(:,:) :: values => null() !< The pointer to the
107  !! array of values for this field; this
108  !! should be changed to allocatable
109  logical :: mean = .true. !< mean
110  logical :: override = .false. !< override
111  integer :: id_diag = 0 !< The diagnostic id for this array
112  character(len=128) :: long_name = ' ' !< The diagnostic long_name for this array
113  character(len=128) :: units = ' ' !< The units for this array
114  integer :: id_rest = 0 !< The id of this array in the restart field
115  logical :: may_init = .true. !< If true, there is an internal method
116  !! that can be used to initialize this field
117  !! if it can not be read from a restart file
118  end type coupler_2d_values_type
119 
120  type, public :: coupler_2d_field_type
121  character(len=48) :: name = ' ' !< name
122  integer :: num_fields = 0 !< num_fields
123  type(coupler_2d_values_type), pointer, dimension(:) :: field => null() !< field
124  character(len=128) :: flux_type = ' ' !< flux_type
125  character(len=128) :: implementation = ' ' !< implementation
126  real, pointer, dimension(:) :: param => null() !< param
127  logical, pointer, dimension(:) :: flag => null() !< flag
128  integer :: atm_tr_index = 0 !< atm_tr_index
129  character(len=128) :: ice_restart_file = ' ' !< ice_restart_file
130  character(len=128) :: ocean_restart_file = ' ' !< ocean_restart_file
131  type(restart_file_type), pointer :: rest_type => null() !< A pointer to the restart_file_type
132  !! that is used for this field.
133  logical :: use_atm_pressure !< use_atm_pressure
134  logical :: use_10m_wind_speed !< use_10m_wind_speed
135  logical :: pass_through_ice !< pass_through_ice
136  real :: mol_wt = 0.0 !< mol_wt
137  end type coupler_2d_field_type
138 
139  type, public :: coupler_2d_bc_type
140  integer :: num_bcs = 0 !< The number of boundary condition fields
141  type(coupler_2d_field_type), dimension(:), pointer :: bc => null() !< A pointer to the array of boundary condition fields
142  logical :: set = .false. !< If true, this type has been initialized
143  integer :: isd, isc, iec, ied !< The i-direction data and computational domain index ranges for this type
144  integer :: jsd, jsc, jec, jed !< The j-direction data and computational domain index ranges for this type
145  end type coupler_2d_bc_type
146 
147  ! 1-d fields
148  type, public :: coupler_1d_values_type
149  character(len=48) :: name = ' ' !< The diagnostic name for this array
150  real, pointer, dimension(:) :: values => null() !< The pointer to the array of values
151  logical :: mean = .true. !< mean
152  logical :: override = .false. !< override
153  integer :: id_diag = 0 !< The diagnostic id for this array
154  character(len=128) :: long_name = ' ' !< The diagnostic long_name for this array
155  character(len=128) :: units = ' ' !< The units for this array
156  logical :: may_init = .true. !< If true, there is an internal method
157  !! that can be used to initialize this field
158  !! if it can not be read from a restart file
159  end type coupler_1d_values_type
160 
161  type, public :: coupler_1d_field_type
162  character(len=48) :: name = ' ' !< name
163  integer :: num_fields = 0 !< num_fields
164  type(coupler_1d_values_type), pointer, dimension(:) :: field => null() !< field
165  character(len=128) :: flux_type = ' ' !< flux_type
166  character(len=128) :: implementation = ' ' !< implementation
167  real, pointer, dimension(:) :: param => null() !< param
168  logical, pointer, dimension(:) :: flag => null() !< flag
169  integer :: atm_tr_index = 0 !< atm_tr_index
170  character(len=128) :: ice_restart_file = ' ' !< ice_restart_file
171  character(len=128) :: ocean_restart_file = ' ' !< ocean_restart_file
172  logical :: use_atm_pressure !< use_atm_pressure
173  logical :: use_10m_wind_speed !< use_10m_wind_speed
174  logical :: pass_through_ice !< pass_through_ice
175  real :: mol_wt = 0.0 !< mol_wt
176  end type coupler_1d_field_type
177 
178  type, public :: coupler_1d_bc_type
179  integer :: num_bcs = 0 !< The number of boundary condition fields
180  type(coupler_1d_field_type), dimension(:), pointer :: bc => null() !< A pointer to the array of boundary condition fields
181  logical :: set = .false. !< If true, this type has been initialized
182  end type coupler_1d_bc_type
183 
184 
185  ! The following public parameters can help in selecting the sub-elements of a
186  ! coupler type. There are duplicate values because different boundary
187  ! conditions have different sub-elements.
188  ! Note: These should be parameters, but doing so would break openMP directives.
189  integer, public :: ind_pcair = 1 !< The index of the atmospheric concentration
190  integer, public :: ind_u10 = 2 !< The index of the 10 m wind speed
191  integer, public :: ind_psurf = 3 !< The index of the surface atmospheric pressure
192  integer, public :: ind_alpha = 1 !< The index of the solubility array for a tracer
193  integer, public :: ind_csurf = 2 !< The index of the ocean surface concentration
194  integer, public :: ind_sc_no = 3 !< The index for the Schmidt number for a tracer flux
195  integer, public :: ind_flux = 1 !< The index for the tracer flux
196  integer, public :: ind_deltap= 2 !< The index for ocean-air gas partial pressure change
197  integer, public :: ind_kw = 3 !< The index for the piston velocity
198  integer, public :: ind_flux0 = 4 !< The index for the piston velocity
199  integer, public :: ind_deposition = 1 !< The index for the atmospheric deposition flux
200  integer, public :: ind_runoff = 1 !< The index for a runoff flux
201 
202  ! Interface definitions for overloaded routines
203 
204  !> This is the interface to spawn one coupler_bc_type into another and then
205  !! register diagnostics associated with the new type.
210  end interface coupler_type_copy
211 
212  !> This is the interface to spawn one coupler_bc_type into another.
214  module procedure ct_spawn_1d_2d, ct_spawn_2d_2d, ct_spawn_3d_2d
215  module procedure ct_spawn_1d_3d, ct_spawn_2d_3d, ct_spawn_3d_3d
216  end interface coupler_type_spawn
217 
218  !> This is the interface to copy the field data from one coupler_bc_type
219  !! to another of the same rank, size and decomposition.
222  end interface coupler_type_copy_data
223 
224  !> This is the interface to redistribute the field data from one coupler_bc_type
225  !! to another of the same rank and global size, but a different decomposition.
228  end interface coupler_type_redistribute_data
229 
230  !> This is the interface to rescale the field data in a coupler_bc_type.
232  module procedure ct_rescale_data_2d, ct_rescale_data_3d
233  end interface coupler_type_rescale_data
234 
235  !> This is the interface to increment the field data from one coupler_bc_type
236  !! with the data from another. Both must have the same horizontal size and
237  !! decomposition, but a 2d type may be incremented by a 2d or 3d type
240  end interface coupler_type_increment_data
241 
242  !> This is the interface to extract a field in a coupler_bc_type into an array.
245  end interface coupler_type_extract_data
246 
247  !> This is the interface to set a field in a coupler_bc_type from an array.
250  end interface coupler_type_set_data
251 
252  !> This is the interface to set diagnostics for the arrays in a coupler_bc_type.
254  module procedure ct_set_diags_2d, ct_set_diags_3d
255  end interface coupler_type_set_diags
256 
257  !> This is the interface to write out checksums for the elements of a coupler_bc_type.
259  module procedure ct_write_chksums_2d, ct_write_chksums_3d
260  end interface coupler_type_write_chksums
261 
262  !> This is the interface to write out diagnostics of the arrays in a coupler_bc_type.
264  module procedure ct_send_data_2d, ct_send_data_3d
265  end interface coupler_type_send_data
266 
267  !> This is the interface to override the values of the arrays in a coupler_bc_type.
269  module procedure ct_data_override_2d, ct_data_override_3d
270  end interface coupler_type_data_override
271 
272  !> This is the interface to register the fields in a coupler_bc_type to be saved
273  !! in restart files.
277  end interface coupler_type_register_restarts
278 
279  !> This is the interface to read in the fields in a coupler_bc_type that have
280  !! been saved in restart files.
282  module procedure ct_restore_state_2d, ct_restore_state_3d
283  end interface coupler_type_restore_state
284 
285  !> This function interface indicates whether a coupler_bc_type has been initialized.
288  end interface coupler_type_initialized
289 
290  !> This is the interface to deallocate any data associated with a coupler_bc_type.
293  end interface coupler_type_destructor
294 
295 contains
296 
297  !> \brief Initialize the coupler types
298  subroutine coupler_types_init
300  logical, save :: module_is_initialized = .false.
301 
302  ! Return if already intialized
303  if (module_is_initialized) then
304  return
305  endif
306 
307  ! Write out the version of the file to the log file.
308  call write_version_number(trim(mod_name), version)
309 
310  module_is_initialized = .true.
311 
312  return
313  end subroutine coupler_types_init !}
314 
315 
316  !> \brief Copy fields from one coupler type to another. 1-D to 2-D version for generic coupler_type_copy.
317  !!
318  !! \throw FATAL, "Number of output fields exceeds zero"
319  subroutine coupler_type_copy_1d_2d(var_in, var_out, is, ie, js, je,&
320  & diag_name, axes, time, suffix)
321  type(coupler_1d_bc_type), intent(in) :: var_in !< variable to copy information from
322  type(coupler_2d_bc_type), intent(inout) :: var_out !< variable to copy information to
323  integer, intent(in) :: is !< lower bound of first dimension
324  integer, intent(in) :: ie !< upper bound of first dimension
325  integer, intent(in) :: js !< lower bound of second dimension
326  integer, intent(in) :: je !< upper bound of second dimension
327  character(len=*), intent(in) :: diag_name !< name for diagnostic file--if blank, then don't register the fields
328  integer, dimension(:), intent(in) :: axes !< array of axes identifiers for diagnostic variable registration
329  type(time_type), intent(in) :: time !< model time variable for registering diagnostic field
330  character(len=*), intent(in), optional :: suffix !< optional suffix to make the name identifier unique
331 
332  character(len=*), parameter :: error_header =&
333  & '==>Error from coupler_types_mod (coupler_type_copy_1d_2d):'
334  character(len=400) :: error_msg
335  integer :: m, n
336 
337  if (var_out%num_bcs > 0) then
338  ! It is an error if the number of output fields exceeds zero, because it means this
339  ! type has already been populated.
340  call mpp_error(fatal, trim(error_header) // ' Number of output fields exceeds zero')
341  endif
342 
343  if (var_in%num_bcs >= 0)&
344  & call ct_spawn_1d_2d(var_in, var_out, (/ is, is, ie, ie /), (/ js, js, je, je /), suffix)
345 
346  if ((var_out%num_bcs > 0) .and. (diag_name .ne. ' '))&
347  & call ct_set_diags_2d(var_out, diag_name, axes, time)
348  end subroutine coupler_type_copy_1d_2d
349 
350  !> \brief Copy fields from one coupler type to another. 1-D to 3-D version for generic coupler_type_copy.
351  !!
352  !!
353  !! \throw FATAL, "Number of output fields is exceeds zero"
354  subroutine coupler_type_copy_1d_3d(var_in, var_out, is, ie, js, je, kd,&
355  & diag_name, axes, time, suffix)
356  type(coupler_1d_bc_type), intent(in) :: var_in !< variable to copy information from
357  type(coupler_3d_bc_type), intent(inout) :: var_out !< variable to copy information to
358  integer, intent(in) :: is !< lower bound of first dimension
359  integer, intent(in) :: ie !< upper bound of first dimension
360  integer, intent(in) :: js !< lower bound of second dimension
361  integer, intent(in) :: je !< upper bound of second dimension
362  integer, intent(in) :: kd !< third dimension
363  character(len=*), intent(in) :: diag_name !< name for diagnostic file--if blank, then don't register the fields
364  integer, dimension(:), intent(in) :: axes !< array of axes identifiers for diagnostic variable registration
365  type(time_type), intent(in) :: time !< model time variable for registering diagnostic field
366  character(len=*), intent(in), optional :: suffix !< optional suffix to make the name identifier unique
367 
368  character(len=*), parameter :: error_header =&
369  & '==>Error from coupler_types_mod (coupler_type_copy_1d_3d):'
370  character(len=400) :: error_msg
371  integer :: m, n
372 
373  if (var_out%num_bcs > 0) then
374  ! It is an error if the number of output fields exceeds zero, because it means this
375  ! type has already been populated.
376  call mpp_error(fatal, trim(error_header) // ' Number of output fields exceeds zero')
377  endif
378 
379  if (var_in%num_bcs >= 0)&
380  & call ct_spawn_1d_3d(var_in, var_out, (/ is, is, ie, ie /), (/ js, js, je, je /), (/1, kd/), suffix)
381 
382  if ((var_out%num_bcs > 0) .and. (diag_name .ne. ' '))&
383  & call ct_set_diags_3d(var_out, diag_name, axes, time)
384  end subroutine coupler_type_copy_1d_3d
385 
386  !> \brief Copy fields from one coupler type to another. 2-D to 2-D version for generic coupler_type_copy.
387  !!
388  !! \throw FATAL, "Number of output fields is exceeds zero"
389  subroutine coupler_type_copy_2d_2d(var_in, var_out, is, ie, js, je,&
390  & diag_name, axes, time, suffix)
391  type(coupler_2d_bc_type), intent(in) :: var_in !< variable to copy information from
392  type(coupler_2d_bc_type), intent(inout) :: var_out !< variable to copy information to
393  integer, intent(in) :: is !< lower bound of first dimension
394  integer, intent(in) :: ie !< upper bound of first dimension
395  integer, intent(in) :: js !< lower bound of second dimension
396  integer, intent(in) :: je !< upper bound of second dimension
397  character(len=*), intent(in) :: diag_name !< name for diagnostic file--if blank, then don't register the fields
398  integer, dimension(:), intent(in) :: axes !< array of axes identifiers for diagnostic variable registration
399  type(time_type), intent(in) :: time !< model time variable for registering diagnostic field
400  character(len=*), intent(in), optional :: suffix !< optional suffix to make the name identifier unique
401 
402  character(len=*), parameter :: error_header =&
403  & '==>Error from coupler_types_mod (coupler_type_copy_2d_2d):'
404  character(len=400) :: error_msg
405  integer :: m, n
406 
407  if (var_out%num_bcs > 0) then
408  ! It is an error if the number of output fields exceeds zero, because it means this
409  ! type has already been populated.
410  call mpp_error(fatal, trim(error_header) // ' Number of output fields exceeds zero')
411  endif
412 
413  if (var_in%num_bcs >= 0)&
414  & call ct_spawn_2d_2d(var_in, var_out, (/ is, is, ie, ie /), (/ js, js, je, je /), suffix)
415 
416  if ((var_out%num_bcs > 0) .and. (diag_name .ne. ' '))&
417  & call ct_set_diags_2d(var_out, diag_name, axes, time)
418  end subroutine coupler_type_copy_2d_2d
419 
420  !> \brief Copy fields from one coupler type to another. 2-D to 3-D version for generic coupler_type_copy.
421  !!
422  !! \throw FATAL, "Number of output fields is exceeds zero"
423  subroutine coupler_type_copy_2d_3d(var_in, var_out, is, ie, js, je, kd,&
424  & diag_name, axes, time, suffix)
425  type(coupler_2d_bc_type), intent(in) :: var_in !< variable to copy information from
426  type(coupler_3d_bc_type), intent(inout) :: var_out !< variable to copy information to
427  integer, intent(in) :: is !< lower bound of first dimension
428  integer, intent(in) :: ie !< upper bound of first dimension
429  integer, intent(in) :: js !< lower bound of second dimension
430  integer, intent(in) :: je !< upper bound of second dimension
431  integer, intent(in) :: kd !< third dimension
432  character(len=*), intent(in) :: diag_name !< name for diagnostic file--if blank, then don't register the fields
433  integer, dimension(:), intent(in) :: axes !< array of axes identifiers for diagnostic variable registration
434  type(time_type), intent(in) :: time !< model time variable for registering diagnostic field
435  character(len=*), intent(in), optional :: suffix !< optional suffix to make the name identifier unique
436 
437  character(len=*), parameter :: error_header =&
438  & '==>Error from coupler_types_mod (coupler_type_copy_2d_3d):'
439  character(len=400) :: error_msg
440  integer :: m, n
441 
442  if (var_out%num_bcs > 0) then
443  ! It is an error if the number of output fields exceeds zero, because it means this
444  ! type has already been populated.
445  call mpp_error(fatal, trim(error_header) // ' Number of output fields exceeds zero')
446  endif
447 
448  if (var_in%num_bcs >= 0)&
449  & call ct_spawn_2d_3d(var_in, var_out, (/ is, is, ie, ie /), (/ js, js, je, je /), (/1, kd/), suffix)
450 
451  if ((var_out%num_bcs > 0) .and. (diag_name .ne. ' '))&
452  & call ct_set_diags_3d(var_out, diag_name, axes, time)
453  end subroutine coupler_type_copy_2d_3d
454 
455  !> \brief Copy fields from one coupler type to another. 3-D to 2-D version for generic coupler_type_copy.
456  !!
457  !! \throw FATAL, "Number of output fields is exceeds zero"
458  subroutine coupler_type_copy_3d_2d(var_in, var_out, is, ie, js, je,&
459  & diag_name, axes, time, suffix)
460  type(coupler_3d_bc_type), intent(in) :: var_in !< variable to copy information from
461  type(coupler_2d_bc_type), intent(inout) :: var_out !< variable to copy information to
462  integer, intent(in) :: is !< lower bound of first dimension
463  integer, intent(in) :: ie !< upper bound of first dimension
464  integer, intent(in) :: js !< lower bound of second dimension
465  integer, intent(in) :: je !< upper bound of second dimension
466  character(len=*), intent(in) :: diag_name !< name for diagnostic file--if blank, then don't register the fields
467  integer, dimension(:), intent(in) :: axes !< array of axes identifiers for diagnostic variable registration
468  type(time_type), intent(in) :: time !< model time variable for registering diagnostic field
469  character(len=*), intent(in), optional :: suffix !< optional suffix to make the name identifier unique
470 
471  character(len=*), parameter :: error_header =&
472  & '==>Error from coupler_types_mod (coupler_type_copy_3d_2d):'
473  character(len=400) :: error_msg
474  integer :: m, n
475 
476  if (var_out%num_bcs > 0) then
477  ! It is an error if the number of output fields exceeds zero, because it means this
478  ! type has already been populated.
479  call mpp_error(fatal, trim(error_header) // ' Number of output fields exceeds zero')
480  endif
481 
482  if (var_in%num_bcs >= 0)&
483  & call ct_spawn_3d_2d(var_in, var_out, (/ is, is, ie, ie /), (/ js, js, je, je /), suffix)
484 
485  if ((var_out%num_bcs > 0) .and. (diag_name .ne. ' '))&
486  & call ct_set_diags_2d(var_out, diag_name, axes, time)
487  end subroutine coupler_type_copy_3d_2d
488 
489  !> \brief Copy fields from one coupler type to another. 3-D to 3-D version for generic coupler_type_copy.
490  !!
491  !! \throw FATAL, "Number of output fields exceeds zero"
492  subroutine coupler_type_copy_3d_3d(var_in, var_out, is, ie, js, je, kd,&
493  & diag_name, axes, time, suffix)
494  type(coupler_3d_bc_type), intent(in) :: var_in !< variable to copy information from
495  type(coupler_3d_bc_type), intent(inout) :: var_out !< variable to copy information to
496  integer, intent(in) :: is !< lower bound of first dimension
497  integer, intent(in) :: ie !< upper bound of first dimension
498  integer, intent(in) :: js !< lower bound of second dimension
499  integer, intent(in) :: je !< upper bound of second dimension
500  integer, intent(in) :: kd !< third dimension
501  character(len=*), intent(in) :: diag_name !< name for diagnostic file--if blank, then don't register the fields
502  integer, dimension(:), intent(in) :: axes !< array of axes identifiers for diagnostic variable registration
503  type(time_type), intent(in) :: time !< model time variable for registering diagnostic field
504  character(len=*), intent(in), optional :: suffix !< optional suffix to make the name identifier unique
505 
506  character(len=*), parameter :: error_header =&
507  & '==>Error from coupler_types_mod (coupler_type_copy_3d_3d):'
508  character(len=400) :: error_msg
509  integer :: m, n
510 
511  if (var_out%num_bcs > 0) then
512  ! It is an error if the number of output fields exceeds zero, because it means this
513  ! type has already been populated.
514  call mpp_error(fatal, trim(error_header) // ' Number of output fields exceeds zero')
515  endif
516 
517  if (var_in%num_bcs >= 0)&
518  & call ct_spawn_3d_3d(var_in, var_out, (/ is, is, ie, ie /), (/ js, js, je, je /), (/1, kd/), suffix)
519 
520  if ((var_out%num_bcs > 0) .and. (diag_name .ne. ' '))&
521  & call ct_set_diags_3d(var_out, diag_name, axes, time)
522  end subroutine coupler_type_copy_3d_3d
523 
524 
525  !> \brief Generate one coupler type using another as a template. 1-D to 2-D version for generic coupler_type_spawn.
526  !!
527  !! \throw FATAL, "The output type has already been initialized"
528  !! \throw FATAL, "The parent type has not been initialized"
529  !! \throw FATAL, "Disordered i-dimension index bound list"
530  !! \throw FATAL, "Disordered j-dimension index bound list"
531  !! \throw FATAL, "var%bc already assocated"
532  !! \throw FATAL, "var%bc('n')%field already associated"
533  !! \throw FATAL, "var%bc('n')%field('m')%values already associated"
534  subroutine ct_spawn_1d_2d(var_in, var, idim, jdim, suffix, as_needed)
535  type(coupler_1d_bc_type), intent(in) :: var_in !< structure from which to copy information
536  type(coupler_2d_bc_type), intent(inout) :: var !< structure into which to copy information
537  integer, dimension(4), intent(in) :: idim !< The data and computational domain extents of
538  !! the first dimension in a non-decreasing list
539  integer, dimension(4), intent(in) :: jdim !< The data and computational domain extents of
540  !! the second dimension in a non-decreasing list
541  character(len=*), optional, intent(in) :: suffix !< optional suffix to make the name identifier unique
542  logical, optional, intent(in) :: as_needed !< Only do the spawn if the target type (var)
543  !! is not set and the parent type (var_in) is set.
544 
545  character(len=*), parameter :: error_header =&
546  & '==>Error from coupler_types_mod (CT_spawn_1d_2d):'
547  character(len=400) :: error_msg
548  integer :: m, n
549 
550  if (present(as_needed)) then
551  if (as_needed) then
552  if ((var%set) .or. (.not.var_in%set)) return
553  endif
554  endif
555 
556  if (var%set)&
557  & call mpp_error(fatal, trim(error_header) // ' The output type has already been initialized.')
558  if (.not.var_in%set)&
559  & call mpp_error(fatal, trim(error_header) // ' The parent type has not been initialized.')
560 
561  var%num_bcs = var_in%num_bcs
562  var%set = .true.
563 
564  if ((idim(1) > idim(2)) .or. (idim(3) > idim(4))) then
565  write (error_msg, *) trim(error_header), ' Disordered i-dimension index bound list ', idim
566  call mpp_error(fatal, trim(error_msg))
567  endif
568  if ((jdim(1) > jdim(2)) .or. (jdim(3) > jdim(4))) then
569  write (error_msg, *) trim(error_header), ' Disordered j-dimension index bound list ', jdim
570  call mpp_error(fatal, trim(error_msg))
571  endif
572  var%isd = idim(1) ; var%isc = idim(2) ; var%iec = idim(3) ; var%ied = idim(4)
573  var%jsd = jdim(1) ; var%jsc = jdim(2) ; var%jec = jdim(3) ; var%jed = jdim(4)
574 
575  if (var%num_bcs > 0) then
576  if (associated(var%bc)) then
577  call mpp_error(fatal, trim(error_header) // ' var%bc already associated')
578  endif
579  allocate ( var%bc(var%num_bcs) )
580  do n = 1, var%num_bcs
581  var%bc(n)%name = var_in%bc(n)%name
582  var%bc(n)%atm_tr_index = var_in%bc(n)%atm_tr_index
583  var%bc(n)%flux_type = var_in%bc(n)%flux_type
584  var%bc(n)%implementation = var_in%bc(n)%implementation
585  var%bc(n)%ice_restart_file = var_in%bc(n)%ice_restart_file
586  var%bc(n)%ocean_restart_file = var_in%bc(n)%ocean_restart_file
587  var%bc(n)%use_atm_pressure = var_in%bc(n)%use_atm_pressure
588  var%bc(n)%use_10m_wind_speed = var_in%bc(n)%use_10m_wind_speed
589  var%bc(n)%pass_through_ice = var_in%bc(n)%pass_through_ice
590  var%bc(n)%mol_wt = var_in%bc(n)%mol_wt
591  var%bc(n)%num_fields = var_in%bc(n)%num_fields
592  if (associated(var%bc(n)%field)) then
593  write (error_msg, *) trim(error_header), ' var%bc(', n, ')%field already associated'
594  call mpp_error(fatal, trim(error_msg))
595  endif
596  allocate ( var%bc(n)%field(var%bc(n)%num_fields) )
597  do m = 1, var%bc(n)%num_fields
598  if (present(suffix)) then
599  var%bc(n)%field(m)%name = trim(var_in%bc(n)%field(m)%name) // trim(suffix)
600  else
601  var%bc(n)%field(m)%name = var_in%bc(n)%field(m)%name
602  endif
603  var%bc(n)%field(m)%long_name = var_in%bc(n)%field(m)%long_name
604  var%bc(n)%field(m)%units = var_in%bc(n)%field(m)%units
605  var%bc(n)%field(m)%may_init = var_in%bc(n)%field(m)%may_init
606  var%bc(n)%field(m)%mean = var_in%bc(n)%field(m)%mean
607  if (associated(var%bc(n)%field(m)%values)) then
608  write (error_msg, *) trim(error_header),&
609  & ' var%bc(', n, ')%field(', m, ')%values already associated'
610  call mpp_error(fatal, trim(error_msg))
611  endif
612  ! Note that this may be allocating a zero-sized array, which is legal in Fortran.
613  allocate ( var%bc(n)%field(m)%values(var%isd:var%ied,var%jsd:var%jed) )
614  var%bc(n)%field(m)%values(:,:) = 0.0
615  enddo
616  enddo
617  endif
618  end subroutine ct_spawn_1d_2d
619 
620  !> \brief Generate one coupler type using another as a template. 1-D to 3-D version for generic CT_spawn.
621  !!
622  !! \throw FATAL, "The output type has already been initialized"
623  !! \throw FATAL, "The parent type has not been initialized"
624  !! \throw FATAL, "Disordered i-dimension index bound list"
625  !! \throw FATAL, "Disordered j-dimension index bound list"
626  !! \throw FATAL, "var%bc already assocated"
627  !! \throw FATAL, "var%bc('n')%field already associated"
628  !! \throw FATAL, "var%bc('n')%field('m')%values already associated"
629  subroutine ct_spawn_1d_3d(var_in, var, idim, jdim, kdim, suffix, as_needed)
630  type(coupler_1d_bc_type), intent(in) :: var_in !< structure from which to copy information
631  type(coupler_3d_bc_type), intent(inout) :: var !< structure into which to copy information
632  integer, dimension(4), intent(in) :: idim !< The data and computational domain extents of
633  !! the first dimension in a non-decreasing list
634  integer, dimension(4), intent(in) :: jdim !< The data and computational domain extents of
635  !! the second dimension in a non-decreasing list
636  integer, dimension(2), intent(in) :: kdim !< The array extents of the third dimension in
637  !! a non-decreasing list
638  character(len=*), optional, intent(in) :: suffix !< optional suffix to make the name identifier unique
639  logical, optional, intent(in) :: as_needed !< Only do the spawn if the target type (var)
640  !! is not set and the parent type (var_in) is set.
641 
642  character(len=*), parameter :: error_header =&
643  & '==>Error from coupler_types_mod (CT_spawn_1d_3d):'
644  character(len=400) :: error_msg
645  integer :: m, n
646 
647  if (present(as_needed)) then
648  if (as_needed) then
649  if ((var%set) .or. (.not.var_in%set)) return
650  endif
651  endif
652 
653  if (var%set)&
654  & call mpp_error(fatal, trim(error_header) // ' The output type has already been initialized.')
655  if (.not.var_in%set)&
656  & call mpp_error(fatal, trim(error_header) // ' The parent type has not been initialized.')
657 
658  var%num_bcs = var_in%num_bcs
659  var%set = .true.
660 
661  ! Store the array extents that are to be used with this bc_type.
662  if ((idim(1) > idim(2)) .or. (idim(3) > idim(4))) then
663  write (error_msg, *) trim(error_header), ' Disordered i-dimension index bound list ', idim
664  call mpp_error(fatal, trim(error_msg))
665  endif
666  if ((jdim(1) > jdim(2)) .or. (jdim(3) > jdim(4))) then
667  write (error_msg, *) trim(error_header), ' Disordered j-dimension index bound list ', jdim
668  call mpp_error(fatal, trim(error_msg))
669  endif
670  var%isd = idim(1) ; var%isc = idim(2) ; var%iec = idim(3) ; var%ied = idim(4)
671  var%jsd = jdim(1) ; var%jsc = jdim(2) ; var%jec = jdim(3) ; var%jed = jdim(4)
672  var%ks = kdim(1) ; var%ke = kdim(2)
673 
674  if (var%num_bcs > 0) then
675  if (kdim(1) > kdim(2)) then
676  write (error_msg, *) trim(error_header), ' Disordered k-dimension index bound list ', kdim
677  call mpp_error(fatal, trim(error_msg))
678  endif
679 
680  if (associated(var%bc)) then
681  call mpp_error(fatal, trim(error_header) // ' var%bc already associated')
682  endif
683  allocate ( var%bc(var%num_bcs) )
684  do n = 1, var%num_bcs
685  var%bc(n)%name = var_in%bc(n)%name
686  var%bc(n)%atm_tr_index = var_in%bc(n)%atm_tr_index
687  var%bc(n)%flux_type = var_in%bc(n)%flux_type
688  var%bc(n)%implementation = var_in%bc(n)%implementation
689  var%bc(n)%ice_restart_file = var_in%bc(n)%ice_restart_file
690  var%bc(n)%ocean_restart_file = var_in%bc(n)%ocean_restart_file
691  var%bc(n)%use_atm_pressure = var_in%bc(n)%use_atm_pressure
692  var%bc(n)%use_10m_wind_speed = var_in%bc(n)%use_10m_wind_speed
693  var%bc(n)%pass_through_ice = var_in%bc(n)%pass_through_ice
694  var%bc(n)%mol_wt = var_in%bc(n)%mol_wt
695  var%bc(n)%num_fields = var_in%bc(n)%num_fields
696  if (associated(var%bc(n)%field)) then
697  write (error_msg, *) trim(error_header), ' var%bc(', n, ')%field already associated'
698  call mpp_error(fatal, trim(error_msg))
699  endif
700  allocate ( var%bc(n)%field(var%bc(n)%num_fields) )
701  do m = 1, var%bc(n)%num_fields
702  if (present(suffix)) then
703  var%bc(n)%field(m)%name = trim(var_in%bc(n)%field(m)%name) // trim(suffix)
704  else
705  var%bc(n)%field(m)%name = var_in%bc(n)%field(m)%name
706  endif
707  var%bc(n)%field(m)%long_name = var_in%bc(n)%field(m)%long_name
708  var%bc(n)%field(m)%units = var_in%bc(n)%field(m)%units
709  var%bc(n)%field(m)%may_init = var_in%bc(n)%field(m)%may_init
710  var%bc(n)%field(m)%mean = var_in%bc(n)%field(m)%mean
711  if (associated(var%bc(n)%field(m)%values)) then
712  write (error_msg, *) trim(error_header), ' var%bc(', n, ')%field(', m, ')%values already associated'
713  call mpp_error(fatal, trim(error_msg))
714  endif
715  ! Note that this may be allocating a zero-sized array, which is legal in Fortran.
716  allocate ( var%bc(n)%field(m)%values(var%isd:var%ied,var%jsd:var%jed,var%ks:var%ke) )
717  var%bc(n)%field(m)%values(:,:,:) = 0.0
718  enddo
719  enddo
720  endif
721  end subroutine ct_spawn_1d_3d
722 
723 
724  !> \brief Generate one coupler type using another as a template. 2-D to 2-D version for generic CT_spawn.
725  !!
726  !! \throw FATAL, "The output type has already been initialized"
727  !! \throw FATAL, "The parent type has not been initialized"
728  !! \throw FATAL, "Disordered i-dimension index bound list"
729  !! \throw FATAL, "Disordered j-dimension index bound list"
730  !! \throw FATAL, "var%bc already assocated"
731  !! \throw FATAL, "var%bc('n')%field already associated"
732  !! \throw FATAL, "var%bc('n')%field('m')%values already associated"
733  subroutine ct_spawn_2d_2d(var_in, var, idim, jdim, suffix, as_needed)
734  type(coupler_2d_bc_type), intent(in) :: var_in !< structure from which to copy information
735  type(coupler_2d_bc_type), intent(inout) :: var !< structure into which to copy information
736  integer, dimension(4), intent(in) :: idim !< The data and computational domain extents of
737  !! the first dimension in a non-decreasing list
738  integer, dimension(4), intent(in) :: jdim !< The data and computational domain extents of
739  !! the second dimension in a non-decreasing list
740  character(len=*), optional, intent(in) :: suffix !< optional suffix to make the name identifier unique
741  logical, optional, intent(in) :: as_needed !< Only do the spawn if the target type (var)
742  !! is not set and the parent type (var_in) is set.
743 
744  character(len=*), parameter :: error_header =&
745  & '==>Error from coupler_types_mod (CT_spawn_2d_2d):'
746  character(len=400) :: error_msg
747  integer :: m, n
748 
749  if (present(as_needed)) then
750  if (as_needed) then
751  if ((var%set) .or. (.not.var_in%set)) return
752  endif
753  endif
754 
755  if (var%set)&
756  & call mpp_error(fatal, trim(error_header) // ' The output type has already been initialized.')
757  if (.not.var_in%set)&
758  & call mpp_error(fatal, trim(error_header) // ' The parent type has not been initialized.')
759 
760  var%num_bcs = var_in%num_bcs
761  var%set = .true.
762 
763  if ((idim(1) > idim(2)) .or. (idim(3) > idim(4))) then
764  write (error_msg, *) trim(error_header), ' Disordered i-dimension index bound list ', idim
765  call mpp_error(fatal, trim(error_msg))
766  endif
767  if ((jdim(1) > jdim(2)) .or. (jdim(3) > jdim(4))) then
768  write (error_msg, *) trim(error_header), ' Disordered j-dimension index bound list ', jdim
769  call mpp_error(fatal, trim(error_msg))
770  endif
771  var%isd = idim(1) ; var%isc = idim(2) ; var%iec = idim(3) ; var%ied = idim(4)
772  var%jsd = jdim(1) ; var%jsc = jdim(2) ; var%jec = jdim(3) ; var%jed = jdim(4)
773 
774  if (var%num_bcs > 0) then
775  if (associated(var%bc)) then
776  call mpp_error(fatal, trim(error_header) // ' var%bc already associated')
777  endif
778  allocate ( var%bc(var%num_bcs) )
779  do n = 1, var%num_bcs
780  var%bc(n)%name = var_in%bc(n)%name
781  var%bc(n)%atm_tr_index = var_in%bc(n)%atm_tr_index
782  var%bc(n)%flux_type = var_in%bc(n)%flux_type
783  var%bc(n)%implementation = var_in%bc(n)%implementation
784  var%bc(n)%ice_restart_file = var_in%bc(n)%ice_restart_file
785  var%bc(n)%ocean_restart_file = var_in%bc(n)%ocean_restart_file
786  var%bc(n)%use_atm_pressure = var_in%bc(n)%use_atm_pressure
787  var%bc(n)%use_10m_wind_speed = var_in%bc(n)%use_10m_wind_speed
788  var%bc(n)%pass_through_ice = var_in%bc(n)%pass_through_ice
789  var%bc(n)%mol_wt = var_in%bc(n)%mol_wt
790  var%bc(n)%num_fields = var_in%bc(n)%num_fields
791  if (associated(var%bc(n)%field)) then
792  write (error_msg, *) trim(error_header), ' var%bc(', n, ')%field already associated'
793  call mpp_error(fatal, trim(error_msg))
794  endif
795  allocate ( var%bc(n)%field(var%bc(n)%num_fields) )
796  do m = 1, var%bc(n)%num_fields
797  if (present(suffix)) then
798  var%bc(n)%field(m)%name = trim(var_in%bc(n)%field(m)%name) // trim(suffix)
799  else
800  var%bc(n)%field(m)%name = var_in%bc(n)%field(m)%name
801  endif
802  var%bc(n)%field(m)%long_name = var_in%bc(n)%field(m)%long_name
803  var%bc(n)%field(m)%units = var_in%bc(n)%field(m)%units
804  var%bc(n)%field(m)%may_init = var_in%bc(n)%field(m)%may_init
805  var%bc(n)%field(m)%mean = var_in%bc(n)%field(m)%mean
806  if (associated(var%bc(n)%field(m)%values)) then
807  write (error_msg, *) trim(error_header), ' var%bc(', n, ')%field(', m, ')%values already associated'
808  call mpp_error(fatal, trim(error_msg))
809  endif
810  ! Note that this may be allocating a zero-sized array, which is legal in Fortran.
811  allocate ( var%bc(n)%field(m)%values(var%isd:var%ied,var%jsd:var%jed) )
812  var%bc(n)%field(m)%values(:,:) = 0.0
813  enddo
814  enddo
815  endif
816  end subroutine ct_spawn_2d_2d
817 
818  !> \brief Generate one coupler type using another as a template. 2-D to 3-D version for generic CT_spawn.
819  !!
820  !! \throw FATAL, "The output type has already been initialized"
821  !! \throw FATAL, "The parent type has not been initialized"
822  !! \throw FATAL, "Disordered i-dimension index bound list"
823  !! \throw FATAL, "Disordered j-dimension index bound list"
824  !! \throw FATAL, "Disordered k-dimension index bound list"
825  !! \throw FATAL, "var%bc already assocated"
826  !! \throw FATAL, "var%bc('n')%field already associated"
827  !! \throw FATAL, "var%bc('n')%field('m')%values already associated"
828  subroutine ct_spawn_2d_3d(var_in, var, idim, jdim, kdim, suffix, as_needed)
829  type(coupler_2d_bc_type), intent(in) :: var_in !< structure from which to copy information
830  type(coupler_3d_bc_type), intent(inout) :: var !< structure into which to copy information
831  integer, dimension(4), intent(in) :: idim !< The data and computational domain extents of
832  !! the first dimension in a non-decreasing list
833  integer, dimension(4), intent(in) :: jdim !< The data and computational domain extents of
834  !! the second dimension in a non-decreasing list
835  integer, dimension(2), intent(in) :: kdim !< The array extents of the third dimension in
836  !! a non-decreasing list
837  character(len=*), optional, intent(in) :: suffix !< optional suffix to make the name identifier unique
838  logical, optional, intent(in) :: as_needed !< Only do the spawn if the target type (var)
839  !! is not set and the parent type (var_in) is set.
840 
841  character(len=*), parameter :: error_header =&
842  & '==>Error from coupler_types_mod (CT_spawn_2d_3d):'
843  character(len=400) :: error_msg
844  integer :: m, n
845 
846  if (present(as_needed)) then
847  if (as_needed) then
848  if ((var%set) .or. (.not.var_in%set)) return
849  endif
850  endif
851 
852  if (var%set)&
853  & call mpp_error(fatal, trim(error_header) // ' The output type has already been initialized.')
854  if (.not.var_in%set)&
855  & call mpp_error(fatal, trim(error_header) // ' The parent type has not been initialized.')
856 
857  var%num_bcs = var_in%num_bcs
858  var%set = .true.
859 
860  ! Store the array extents that are to be used with this bc_type.
861  if ((idim(1) > idim(2)) .or. (idim(3) > idim(4))) then
862  write (error_msg, *) trim(error_header), ' Disordered i-dimension index bound list ', idim
863  call mpp_error(fatal, trim(error_msg))
864  endif
865  if ((jdim(1) > jdim(2)) .or. (jdim(3) > jdim(4))) then
866  write (error_msg, *) trim(error_header), ' Disordered j-dimension index bound list ', jdim
867  call mpp_error(fatal, trim(error_msg))
868  endif
869  if (kdim(1) > kdim(2)) then
870  write (error_msg, *) trim(error_header), ' Disordered k-dimension index bound list ', kdim
871  call mpp_error(fatal, trim(error_msg))
872  endif
873  var%isd = idim(1) ; var%isc = idim(2) ; var%iec = idim(3) ; var%ied = idim(4)
874  var%jsd = jdim(1) ; var%jsc = jdim(2) ; var%jec = jdim(3) ; var%jed = jdim(4)
875  var%ks = kdim(1) ; var%ke = kdim(2)
876 
877  if (var%num_bcs > 0) then
878  if (associated(var%bc)) then
879  call mpp_error(fatal, trim(error_header) // ' var%bc already associated')
880  endif
881  allocate ( var%bc(var%num_bcs) )
882  do n = 1, var%num_bcs
883  var%bc(n)%name = var_in%bc(n)%name
884  var%bc(n)%atm_tr_index = var_in%bc(n)%atm_tr_index
885  var%bc(n)%flux_type = var_in%bc(n)%flux_type
886  var%bc(n)%implementation = var_in%bc(n)%implementation
887  var%bc(n)%ice_restart_file = var_in%bc(n)%ice_restart_file
888  var%bc(n)%ocean_restart_file = var_in%bc(n)%ocean_restart_file
889  var%bc(n)%use_atm_pressure = var_in%bc(n)%use_atm_pressure
890  var%bc(n)%use_10m_wind_speed = var_in%bc(n)%use_10m_wind_speed
891  var%bc(n)%pass_through_ice = var_in%bc(n)%pass_through_ice
892  var%bc(n)%mol_wt = var_in%bc(n)%mol_wt
893  var%bc(n)%num_fields = var_in%bc(n)%num_fields
894  if (associated(var%bc(n)%field)) then
895  write (error_msg, *) trim(error_header), ' var%bc(', n, ')%field already associated'
896  call mpp_error(fatal, trim(error_msg))
897  endif
898  allocate ( var%bc(n)%field(var%bc(n)%num_fields) )
899  do m = 1, var%bc(n)%num_fields
900  if (present(suffix)) then
901  var%bc(n)%field(m)%name = trim(var_in%bc(n)%field(m)%name) // trim(suffix)
902  else
903  var%bc(n)%field(m)%name = var_in%bc(n)%field(m)%name
904  endif
905  var%bc(n)%field(m)%long_name = var_in%bc(n)%field(m)%long_name
906  var%bc(n)%field(m)%units = var_in%bc(n)%field(m)%units
907  var%bc(n)%field(m)%may_init = var_in%bc(n)%field(m)%may_init
908  var%bc(n)%field(m)%mean = var_in%bc(n)%field(m)%mean
909  if (associated(var%bc(n)%field(m)%values)) then
910  write (error_msg, *) trim(error_header), ' var%bc(', n, ')%field(', m, ')%values already associated'
911  call mpp_error(fatal, trim(error_msg))
912  endif
913  ! Note that this may be allocating a zero-sized array, which is legal in Fortran.
914  allocate ( var%bc(n)%field(m)%values(var%isd:var%ied,var%jsd:var%jed,var%ks:var%ke) )
915  var%bc(n)%field(m)%values(:,:,:) = 0.0
916  enddo
917  enddo
918  endif
919  end subroutine ct_spawn_2d_3d
920 
921  !> \brief Generate one coupler type using another as a template. 3-D to 2-D version for generic CT_spawn.
922  !!
923  !! \throw FATAL, "The output type has already been initialized"
924  !! \throw FATAL, "The parent type has not been initialized"
925  !! \throw FATAL, "Disordered i-dimension index bound list"
926  !! \throw FATAL, "Disordered j-dimension index bound list"
927  !! \throw FATAL, "var%bc already assocated"
928  !! \throw FATAL, "var%bc('n')%field already associated"
929  !! \throw FATAL, "var%bc('n')%field('m')%values already associated"
930  subroutine ct_spawn_3d_2d(var_in, var, idim, jdim, suffix, as_needed)
931  type(coupler_3d_bc_type), intent(in) :: var_in !< structure from which to copy information
932  type(coupler_2d_bc_type), intent(inout) :: var !< structure into which to copy information
933  integer, dimension(4), intent(in) :: idim !< The data and computational domain extents of
934  !! the first dimension in a non-decreasing list
935  integer, dimension(4), intent(in) :: jdim !< The data and computational domain extents of
936  !! the second dimension in a non-decreasing list
937  character(len=*), optional, intent(in) :: suffix !< optional suffix to make the name identifier unique
938  logical, optional, intent(in) :: as_needed !< Only do the spawn if the target type (var)
939  !! is not set and the parent type (var_in) is set.
940 
941  character(len=*), parameter :: error_header =&
942  & '==>Error from coupler_types_mod (CT_spawn_3d_2d):'
943  character(len=400) :: error_msg
944  integer :: m, n
945 
946  if (present(as_needed)) then
947  if (as_needed) then
948  if ((var%set) .or. (.not.var_in%set)) return
949  endif
950  endif
951 
952  if (var%set)&
953  & call mpp_error(fatal, trim(error_header) // ' The output type has already been initialized.')
954  if (.not.var_in%set)&
955  & call mpp_error(fatal, trim(error_header) // ' The parent type has not been initialized.')
956 
957  var%num_bcs = var_in%num_bcs
958  var%set = .true.
959 
960  if ((idim(1) > idim(2)) .or. (idim(3) > idim(4))) then
961  write (error_msg, *) trim(error_header), ' Disordered i-dimension index bound list ', idim
962  call mpp_error(fatal, trim(error_msg))
963  endif
964  if ((jdim(1) > jdim(2)) .or. (jdim(3) > jdim(4))) then
965  write (error_msg, *) trim(error_header), ' Disordered j-dimension index bound list ', jdim
966  call mpp_error(fatal, trim(error_msg))
967  endif
968  var%isd = idim(1) ; var%isc = idim(2) ; var%iec = idim(3) ; var%ied = idim(4)
969  var%jsd = jdim(1) ; var%jsc = jdim(2) ; var%jec = jdim(3) ; var%jed = jdim(4)
970 
971  if (var%num_bcs > 0) then
972  if (associated(var%bc)) then
973  call mpp_error(fatal, trim(error_header) // ' var%bc already associated')
974  endif
975  allocate ( var%bc(var%num_bcs) )
976  do n = 1, var%num_bcs
977  var%bc(n)%name = var_in%bc(n)%name
978  var%bc(n)%atm_tr_index = var_in%bc(n)%atm_tr_index
979  var%bc(n)%flux_type = var_in%bc(n)%flux_type
980  var%bc(n)%implementation = var_in%bc(n)%implementation
981  var%bc(n)%ice_restart_file = var_in%bc(n)%ice_restart_file
982  var%bc(n)%ocean_restart_file = var_in%bc(n)%ocean_restart_file
983  var%bc(n)%use_atm_pressure = var_in%bc(n)%use_atm_pressure
984  var%bc(n)%use_10m_wind_speed = var_in%bc(n)%use_10m_wind_speed
985  var%bc(n)%pass_through_ice = var_in%bc(n)%pass_through_ice
986  var%bc(n)%mol_wt = var_in%bc(n)%mol_wt
987  var%bc(n)%num_fields = var_in%bc(n)%num_fields
988  if (associated(var%bc(n)%field)) then
989  write (error_msg, *) trim(error_header), ' var%bc(', n, ')%field already associated'
990  call mpp_error(fatal, trim(error_msg))
991  endif
992  allocate ( var%bc(n)%field(var%bc(n)%num_fields) )
993  do m = 1, var%bc(n)%num_fields
994  if (present(suffix)) then
995  var%bc(n)%field(m)%name = trim(var_in%bc(n)%field(m)%name) // trim(suffix)
996  else
997  var%bc(n)%field(m)%name = var_in%bc(n)%field(m)%name
998  endif
999  var%bc(n)%field(m)%long_name = var_in%bc(n)%field(m)%long_name
1000  var%bc(n)%field(m)%units = var_in%bc(n)%field(m)%units
1001  var%bc(n)%field(m)%may_init = var_in%bc(n)%field(m)%may_init
1002  var%bc(n)%field(m)%mean = var_in%bc(n)%field(m)%mean
1003  if (associated(var%bc(n)%field(m)%values)) then
1004  write (error_msg, *) trim(error_header), ' var%bc(', n, ')%field(', m, ')%values already associated'
1005  call mpp_error(fatal, trim(error_msg))
1006  endif
1007  ! Note that this may be allocating a zero-sized array, which is legal in Fortran.
1008  allocate ( var%bc(n)%field(m)%values(var%isd:var%ied,var%jsd:var%jed) )
1009  var%bc(n)%field(m)%values(:,:) = 0.0
1010  enddo
1011  enddo
1012  endif
1013  end subroutine ct_spawn_3d_2d
1014 
1015 !> \brief Generate one coupler type using another as a template. 3-D to 3-D version for generic CT_spawn.
1016 !!
1017  !! \throw FATAL, "The output type has already been initialized"
1018  !! \throw FATAL, "The parent type has not been initialized"
1019  !! \throw FATAL, "Disordered i-dimension index bound list"
1020  !! \throw FATAL, "Disordered j-dimension index bound list"
1021  !! \throw FATAL, "Disordered k-dimension index bound list"
1022  !! \throw FATAL, "var%bc already assocated"
1023  !! \throw FATAL, "var%bc('n')%field already associated"
1024  !! \throw FATAL, "var%bc('n')%field('m')%values already associated"
1025  subroutine ct_spawn_3d_3d(var_in, var, idim, jdim, kdim, suffix, as_needed)
1026  type(coupler_3d_bc_type), intent(in) :: var_in !< structure from which to copy information
1027  type(coupler_3d_bc_type), intent(inout) :: var !< structure into which to copy information
1028  integer, dimension(4), intent(in) :: idim !< The data and computational domain extents of
1029  !! the first dimension in a non-decreasing list
1030  integer, dimension(4), intent(in) :: jdim !< The data and computational domain extents of
1031  !! the second dimension in a non-decreasing list
1032  integer, dimension(2), intent(in) :: kdim !< The array extents of the third dimension in
1033  !! a non-decreasing list
1034  character(len=*), optional, intent(in) :: suffix !< optional suffix to make the name identifier unique
1035  logical, optional, intent(in) :: as_needed !< Only do the spawn if the target type (var)
1036  !! is not set and the parent type (var_in) is set.
1037 
1038  character(len=*), parameter :: error_header =&
1039  & '==>Error from coupler_types_mod (CT_spawn_3d_3d):'
1040  character(len=400) :: error_msg
1041  integer :: m, n
1042 
1043  if (present(as_needed)) then
1044  if (as_needed) then
1045  if ((var%set) .or. (.not.var_in%set)) return
1046  endif
1047  endif
1048 
1049  if (var%set)&
1050  & call mpp_error(fatal, trim(error_header) // ' The output type has already been initialized.')
1051  if (.not.var_in%set)&
1052  & call mpp_error(fatal, trim(error_header) // ' The parent type has not been initialized.')
1053 
1054  var%num_bcs = var_in%num_bcs
1055  var%set = .true.
1056 
1057  if ((idim(1) > idim(2)) .or. (idim(3) > idim(4))) then
1058  write (error_msg, *) trim(error_header), ' Disordered i-dimension index bound list ', idim
1059  call mpp_error(fatal, trim(error_msg))
1060  endif
1061  if ((jdim(1) > jdim(2)) .or. (jdim(3) > jdim(4))) then
1062  write (error_msg, *) trim(error_header), ' Disordered j-dimension index bound list ', jdim
1063  call mpp_error(fatal, trim(error_msg))
1064  endif
1065  if (kdim(1) > kdim(2)) then
1066  write (error_msg, *) trim(error_header), ' Disordered k-dimension index bound list ', kdim
1067  call mpp_error(fatal, trim(error_msg))
1068  endif
1069  var%isd = idim(1) ; var%isc = idim(2) ; var%iec = idim(3) ; var%ied = idim(4)
1070  var%jsd = jdim(1) ; var%jsc = jdim(2) ; var%jec = jdim(3) ; var%jed = jdim(4)
1071  var%ks = kdim(1) ; var%ke = kdim(2)
1072 
1073  if (var%num_bcs > 0) then
1074  if (associated(var%bc)) then
1075  call mpp_error(fatal, trim(error_header) // ' var%bc already associated')
1076  endif
1077  allocate ( var%bc(var%num_bcs) )
1078  do n = 1, var%num_bcs
1079  var%bc(n)%name = var_in%bc(n)%name
1080  var%bc(n)%atm_tr_index = var_in%bc(n)%atm_tr_index
1081  var%bc(n)%flux_type = var_in%bc(n)%flux_type
1082  var%bc(n)%implementation = var_in%bc(n)%implementation
1083  var%bc(n)%ice_restart_file = var_in%bc(n)%ice_restart_file
1084  var%bc(n)%ocean_restart_file = var_in%bc(n)%ocean_restart_file
1085  var%bc(n)%use_atm_pressure = var_in%bc(n)%use_atm_pressure
1086  var%bc(n)%use_10m_wind_speed = var_in%bc(n)%use_10m_wind_speed
1087  var%bc(n)%pass_through_ice = var_in%bc(n)%pass_through_ice
1088  var%bc(n)%mol_wt = var_in%bc(n)%mol_wt
1089  var%bc(n)%num_fields = var_in%bc(n)%num_fields
1090  if (associated(var%bc(n)%field)) then
1091  write (error_msg, *) trim(error_header), ' var%bc(', n, ')%field already associated'
1092  call mpp_error(fatal, trim(error_msg))
1093  endif
1094  allocate ( var%bc(n)%field(var%bc(n)%num_fields) )
1095  do m = 1, var%bc(n)%num_fields
1096  if (present(suffix)) then
1097  var%bc(n)%field(m)%name = trim(var_in%bc(n)%field(m)%name) // trim(suffix)
1098  else
1099  var%bc(n)%field(m)%name = var_in%bc(n)%field(m)%name
1100  endif
1101  var%bc(n)%field(m)%long_name = var_in%bc(n)%field(m)%long_name
1102  var%bc(n)%field(m)%units = var_in%bc(n)%field(m)%units
1103  var%bc(n)%field(m)%may_init = var_in%bc(n)%field(m)%may_init
1104  var%bc(n)%field(m)%mean = var_in%bc(n)%field(m)%mean
1105  if (associated(var%bc(n)%field(m)%values)) then
1106  write (error_msg, *) trim(error_header), ' var%bc(', n, ')%field(', m, ')%values already associated'
1107  call mpp_error(fatal, trim(error_msg))
1108  endif
1109 
1110  ! Note that this may be allocating a zero-sized array, which is legal in Fortran.
1111  allocate ( var%bc(n)%field(m)%values(var%isd:var%ied,var%jsd:var%jed,var%ks:var%ke) )
1112  var%bc(n)%field(m)%values(:,:,:) = 0.0
1113  enddo
1114  enddo
1115  endif
1116  end subroutine ct_spawn_3d_3d
1117 
1118 
1119  !> Copy all elements of coupler_2d_bc_type
1120  !!
1121  !! Do a direct copy of the data in all elements of one
1122  !! coupler_2d_bc_type into another. Both must have the same array sizes.
1123  !!
1124  !! \throw FATAL, "bc_index is present and exceeds var_in%num_bcs."
1125  !! \throw FATAL, "field_index is present and exceeds num_fields for var_in%bc(bc_incdx)%name"
1126  !! \throw FATAL, "bc_index must be present if field_index is present."
1127  !! \throw FATAL, "There is an i-direction computational domain size mismatch."
1128  !! \throw FATAL, "There is an j-direction computational domain size mismatch."
1129  !! \throw FATAL, "Excessive i-direction halo size for the input structure."
1130  !! \throw FATAL, "Excessive i-direction halo size for the input structure."
1131  subroutine ct_copy_data_2d(var_in, var, halo_size, bc_index, field_index,&
1132  & exclude_flux_type, only_flux_type, pass_through_ice)
1133  type(coupler_2d_bc_type), intent(in) :: var_in !< BC_type structure with the data to copy
1134  type(coupler_2d_bc_type), intent(inout) :: var !< The recipient BC_type structure
1135  integer, optional, intent(in) :: halo_size !< The extent of the halo to copy; 0 by default
1136  integer, optional, intent(in) :: bc_index !< The index of the boundary condition
1137  !! that is being copied
1138  integer, optional, intent(in) :: field_index !< The index of the field in the
1139  !! boundary condition that is being copied
1140  character(len=*), optional, intent(in) :: exclude_flux_type !< A string describing which types of fluxes to exclude from this copy.
1141  character(len=*), optional, intent(in) :: only_flux_type !< A string describing which types of fluxes to include from this copy.
1142  logical, optional, intent(in) :: pass_through_ice !< If true, only copy BCs whose
1143  !! value of pass_through ice matches this
1144  logical :: copy_bc
1145  integer :: i, j, m, n, n1, n2, halo, i_off, j_off
1146 
1147  if (present(bc_index)) then
1148  if (bc_index > var_in%num_bcs)&
1149  & call mpp_error(fatal, "CT_copy_data_2d: bc_index is present and exceeds var_in%num_bcs.")
1150  if (present(field_index)) then ; if (field_index > var_in%bc(bc_index)%num_fields)&
1151  & call mpp_error(fatal, "CT_copy_data_2d: field_index is present and exceeds num_fields for" //&
1152  & trim(var_in%bc(bc_index)%name) )
1153  endif
1154  elseif (present(field_index)) then
1155  call mpp_error(fatal, "CT_copy_data_2d: bc_index must be present if field_index is present.")
1156  endif
1157 
1158  halo = 0
1159  if (present(halo_size)) halo = halo_size
1160 
1161  n1 = 1
1162  n2 = var_in%num_bcs
1163  if (present(bc_index)) then
1164  n1 = bc_index
1165  n2 = bc_index
1166  endif
1167 
1168  if (n2 >= n1) then
1169  ! A more consciencious implementation would include a more descriptive error messages.
1170  if ((var_in%iec-var_in%isc) /= (var%iec-var%isc))&
1171  & call mpp_error(fatal, "CT_copy_data_2d: There is an i-direction computational domain size mismatch.")
1172  if ((var_in%jec-var_in%jsc) /= (var%jec-var%jsc))&
1173  & call mpp_error(fatal, "CT_copy_data_2d: There is a j-direction computational domain size mismatch.")
1174  if ((var_in%isc-var_in%isd < halo) .or. (var_in%ied-var_in%iec < halo))&
1175  & call mpp_error(fatal, "CT_copy_data_2d: Excessive i-direction halo size for the input structure.")
1176  if ((var_in%jsc-var_in%jsd < halo) .or. (var_in%jed-var_in%jec < halo))&
1177  & call mpp_error(fatal, "CT_copy_data_2d: Excessive j-direction halo size for the input structure.")
1178  if ((var%isc-var%isd < halo) .or. (var%ied-var%iec < halo))&
1179  & call mpp_error(fatal, "CT_copy_data_2d: Excessive i-direction halo size for the output structure.")
1180  if ((var%jsc-var%jsd < halo) .or. (var%jed-var%jec < halo))&
1181  & call mpp_error(fatal, "CT_copy_data_2d: Excessive j-direction halo size for the output structure.")
1182 
1183  i_off = var_in%isc - var%isc
1184  j_off = var_in%jsc - var%jsc
1185  endif
1186 
1187  do n = n1, n2
1188  copy_bc = .true.
1189  if (copy_bc .and. present(exclude_flux_type))&
1190  & copy_bc = .not.(trim(var%bc(n)%flux_type) == trim(exclude_flux_type))
1191  if (copy_bc .and. present(only_flux_type))&
1192  & copy_bc = (trim(var%bc(n)%flux_type) == trim(only_flux_type))
1193  if (copy_bc .and. present(pass_through_ice))&
1194  & copy_bc = (pass_through_ice .eqv. var%bc(n)%pass_through_ice)
1195  if (.not.copy_bc) cycle
1196 
1197  do m = 1, var%bc(n)%num_fields
1198  if (present(field_index)) then
1199  if (m /= field_index) cycle
1200  endif
1201  if ( associated(var%bc(n)%field(m)%values) ) then
1202  do j=var%jsc-halo,var%jec+halo
1203  do i=var%isc-halo,var%iec+halo
1204  var%bc(n)%field(m)%values(i,j) = var_in%bc(n)%field(m)%values(i+i_off,j+j_off)
1205  enddo
1206  enddo
1207  endif
1208  enddo
1209  enddo
1210  end subroutine ct_copy_data_2d
1211 
1212  !> Copy all elements of coupler_3d_bc_type
1213  !!
1214  !! Do a direct copy of the data in all elements of one
1215  !! coupler_3d_bc_type into another. Both must have the same array sizes.
1216  !!
1217  !! \throw FATAL, "bc_index is present and exceeds var_in%num_bcs."
1218  !! \throw FATAL, "field_index is present and exceeds num_fields for var_in%bc(bc_incdx)%name"
1219  !! \throw FATAL, "bc_index must be present if field_index is present."
1220  !! \throw FATAL, "There is an i-direction computational domain size mismatch."
1221  !! \throw FATAL, "There is an j-direction computational domain size mismatch."
1222  !! \throw FATAL, "There is an k-direction computational domain size mismatch."
1223  !! \throw FATAL, "Excessive i-direction halo size for the input structure."
1224  !! \throw FATAL, "Excessive i-direction halo size for the input structure."
1225  !! \throw FATAL, "Excessive k-direction halo size for the input structure."
1226  subroutine ct_copy_data_3d(var_in, var, halo_size, bc_index, field_index,&
1227  & exclude_flux_type, only_flux_type, pass_through_ice)
1228  type(coupler_3d_bc_type), intent(in) :: var_in !< BC_type structure with the data to copy
1229  type(coupler_3d_bc_type), intent(inout) :: var !< The recipient BC_type structure
1230  integer, optional, intent(in) :: halo_size !< The extent of the halo to copy; 0 by default
1231  integer, optional, intent(in) :: bc_index !< The index of the boundary condition
1232  !! that is being copied
1233  integer, optional, intent(in) :: field_index !< The index of the field in the
1234  !! boundary condition that is being copied
1235  character(len=*), optional, intent(in) :: exclude_flux_type !< A string describing which types
1236  !! of fluxes to exclude from this copy.
1237  character(len=*), optional, intent(in) :: only_flux_type !< A string describing which types
1238  !! of fluxes to include from this copy.
1239  logical, optional, intent(in) :: pass_through_ice !< If true, only copy BCs whose
1240  !! value of pass_through ice matches this
1241  logical :: copy_bc
1242  integer :: i, j, k, m, n, n1, n2, halo, i_off, j_off, k_off
1243 
1244  if (present(bc_index)) then
1245  if (bc_index > var_in%num_bcs) &
1246  call mpp_error(fatal, "CT_copy_data_3d: bc_index is present and exceeds var_in%num_bcs.")
1247  if (present(field_index)) then ; if (field_index > var_in%bc(bc_index)%num_fields)&
1248  & call mpp_error(fatal, "CT_copy_data_3d: field_index is present and exceeds num_fields for" //&
1249  & trim(var_in%bc(bc_index)%name) )
1250  endif
1251  elseif (present(field_index)) then
1252  call mpp_error(fatal, "CT_copy_data_3d: bc_index must be present if field_index is present.")
1253  endif
1254 
1255  halo = 0
1256  if (present(halo_size)) halo = halo_size
1257 
1258  n1 = 1
1259  n2 = var_in%num_bcs
1260  if (present(bc_index)) then
1261  n1 = bc_index
1262  n2 = bc_index
1263  endif
1264 
1265  if (n2 >= n1) then
1266  ! A more consciencious implementation would include a more descriptive error messages.
1267  if ((var_in%iec-var_in%isc) /= (var%iec-var%isc))&
1268  & call mpp_error(fatal, "CT_copy_data_3d: There is an i-direction computational domain size mismatch.")
1269  if ((var_in%jec-var_in%jsc) /= (var%jec-var%jsc))&
1270  & call mpp_error(fatal, "CT_copy_data_3d: There is a j-direction computational domain size mismatch.")
1271  if ((var_in%ke-var_in%ks) /= (var%ke-var%ks))&
1272  & call mpp_error(fatal, "CT_copy_data_3d: There is a k-direction computational domain size mismatch.")
1273  if ((var_in%isc-var_in%isd < halo) .or. (var_in%ied-var_in%iec < halo))&
1274  & call mpp_error(fatal, "CT_copy_data_3d: Excessive i-direction halo size for the input structure.")
1275  if ((var_in%jsc-var_in%jsd < halo) .or. (var_in%jed-var_in%jec < halo))&
1276  & call mpp_error(fatal, "CT_copy_data_3d: Excessive j-direction halo size for the input structure.")
1277  if ((var%isc-var%isd < halo) .or. (var%ied-var%iec < halo))&
1278  & call mpp_error(fatal, "CT_copy_data_3d: Excessive i-direction halo size for the output structure.")
1279  if ((var%jsc-var%jsd < halo) .or. (var%jed-var%jec < halo))&
1280  & call mpp_error(fatal, "CT_copy_data_3d: Excessive j-direction halo size for the output structure.")
1281 
1282  i_off = var_in%isc - var%isc
1283  j_off = var_in%jsc - var%jsc
1284  k_off = var_in%ks - var%ks
1285  endif
1286 
1287  do n = n1, n2
1288  copy_bc = .true.
1289  if (copy_bc .and. present(exclude_flux_type))&
1290  & copy_bc = .not.(trim(var%bc(n)%flux_type) == trim(exclude_flux_type))
1291  if (copy_bc .and. present(only_flux_type))&
1292  & copy_bc = (trim(var%bc(n)%flux_type) == trim(only_flux_type))
1293  if (copy_bc .and. present(pass_through_ice))&
1294  & copy_bc = (pass_through_ice .eqv. var%bc(n)%pass_through_ice)
1295  if (.not.copy_bc) cycle
1296 
1297  do m = 1, var_in%bc(n)%num_fields
1298  if (present(field_index)) then
1299  if (m /= field_index) cycle
1300  endif
1301  if ( associated(var%bc(n)%field(m)%values) ) then
1302  do k=var%ks,var%ke
1303  do j=var%jsc-halo,var%jec+halo
1304  do i=var%isc-halo,var%iec+halo
1305  var%bc(n)%field(m)%values(i,j,k) = var_in%bc(n)%field(m)%values(i+i_off,j+j_off,k+k_off)
1306  enddo
1307  enddo
1308  enddo
1309  endif
1310  enddo
1311  enddo
1312  end subroutine ct_copy_data_3d
1313 
1314  !> Copy all elements of coupler_2d_bc_type to coupler_3d_bc_type
1315  !!
1316  !! Do a direct copy of the data in all elements of one coupler_2d_bc_type into a
1317  !! coupler_3d_bc_type. Both must have the same array sizes for the first two dimensions, while
1318  !! the extend of the 3rd dimension that is being filled may be specified via optional arguments..
1319  !!
1320  !! \throw FATAL, "bc_index is present and exceeds var_in%num_bcs."
1321  !! \throw FATAL, "field_index is present and exceeds num_fields for var_in%bc(bc_incdx)%name"
1322  !! \throw FATAL, "bc_index must be present if field_index is present."
1323  !! \throw FATAL, "There is an i-direction computational domain size mismatch."
1324  !! \throw FATAL, "There is an j-direction computational domain size mismatch."
1325  !! \throw FATAL, "Excessive i-direction halo size for the input structure."
1326  !! \throw FATAL, "Excessive i-direction halo size for the input structure."
1327  subroutine ct_copy_data_2d_3d(var_in, var, halo_size, bc_index, field_index,&
1328  & exclude_flux_type, only_flux_type, pass_through_ice,&
1329  & ind3_start, ind3_end)
1330  type(coupler_2d_bc_type), intent(in) :: var_in !< BC_type structure with the data to copy
1331  type(coupler_3d_bc_type), intent(inout) :: var !< The recipient BC_type structure
1332  integer, optional, intent(in) :: halo_size !< The extent of the halo to copy; 0 by default
1333  integer, optional, intent(in) :: bc_index !< The index of the boundary condition
1334  !! that is being copied
1335  integer, optional, intent(in) :: field_index !< The index of the field in the
1336  !! boundary condition that is being copied
1337  character(len=*), optional, intent(in) :: exclude_flux_type !< A string describing which types of fluxes to exclude from this copy.
1338  character(len=*), optional, intent(in) :: only_flux_type !< A string describing which types of fluxes to include from this copy.
1339  logical, optional, intent(in) :: pass_through_ice !< If true, only copy BCs whose
1340  !! value of pass_through ice matches this
1341  integer, optional, intent(in) :: ind3_start !< The starting value of the 3rd
1342  !! index of the 3d type to fill in.
1343  integer, optional, intent(in) :: ind3_end !< The ending value of the 3rd
1344  !! index of the 3d type to fill in.
1345 
1346  logical :: copy_bc
1347  integer :: i, j, k, m, n, n1, n2, halo, i_off, j_off, ks, ke
1348 
1349  if (present(bc_index)) then
1350  if (bc_index > var_in%num_bcs)&
1351  & call mpp_error(fatal, "CT_copy_data_2d_3d: bc_index is present and exceeds var_in%num_bcs.")
1352  if (present(field_index)) then ; if (field_index > var_in%bc(bc_index)%num_fields)&
1353  & call mpp_error(fatal, "CT_copy_data_2d_3d: field_index is present and exceeds num_fields for" //&
1354  & trim(var_in%bc(bc_index)%name) )
1355  endif
1356  elseif (present(field_index)) then
1357  call mpp_error(fatal, "CT_copy_data_2d_3d: bc_index must be present if field_index is present.")
1358  endif
1359 
1360  halo = 0
1361  if (present(halo_size)) halo = halo_size
1362 
1363  n1 = 1
1364  n2 = var_in%num_bcs
1365  if (present(bc_index)) then
1366  n1 = bc_index
1367  n2 = bc_index
1368  endif
1369 
1370  if (n2 >= n1) then
1371  ! A more consciencious implementation would include a more descriptive error messages.
1372  if ((var_in%iec-var_in%isc) /= (var%iec-var%isc))&
1373  & call mpp_error(fatal, "CT_copy_data_2d_3d: There is an i-direction computational domain size mismatch.")
1374  if ((var_in%jec-var_in%jsc) /= (var%jec-var%jsc))&
1375  & call mpp_error(fatal, "CT_copy_data_2d_3d: There is a j-direction computational domain size mismatch.")
1376  if ((var_in%isc-var_in%isd < halo) .or. (var_in%ied-var_in%iec < halo))&
1377  & call mpp_error(fatal, "CT_copy_data_2d_3d: Excessive i-direction halo size for the input structure.")
1378  if ((var_in%jsc-var_in%jsd < halo) .or. (var_in%jed-var_in%jec < halo))&
1379  & call mpp_error(fatal, "CT_copy_data_2d_3d: Excessive j-direction halo size for the input structure.")
1380  if ((var%isc-var%isd < halo) .or. (var%ied-var%iec < halo))&
1381  & call mpp_error(fatal, "CT_copy_data_2d_3d: Excessive i-direction halo size for the output structure.")
1382  if ((var%jsc-var%jsd < halo) .or. (var%jed-var%jec < halo))&
1383  & call mpp_error(fatal, "CT_copy_data_2d_3d: Excessive j-direction halo size for the output structure.")
1384  endif
1385 
1386  i_off = var_in%isc - var%isc
1387  j_off = var_in%jsc - var%jsc
1388  do n = n1, n2
1389  copy_bc = .true.
1390  if (copy_bc .and. present(exclude_flux_type))&
1391  & copy_bc = .not.(trim(var_in%bc(n)%flux_type) == trim(exclude_flux_type))
1392  if (copy_bc .and. present(only_flux_type))&
1393  & copy_bc = (trim(var_in%bc(n)%flux_type) == trim(only_flux_type))
1394  if (copy_bc .and. present(pass_through_ice))&
1395  & copy_bc = (pass_through_ice .eqv. var_in%bc(n)%pass_through_ice)
1396  if (.not.copy_bc) cycle
1397 
1398  do m = 1, var_in%bc(n)%num_fields
1399  if (present(field_index)) then
1400  if (m /= field_index) cycle
1401  endif
1402  if ( associated(var%bc(n)%field(m)%values) ) then
1403  ks = var%ks
1404  if (present(ind3_start)) ks = max(ks, ind3_start)
1405  ke = var%ke
1406  if (present(ind3_end)) ke = max(ke, ind3_end)
1407  do k=ks,ke
1408  do j=var%jsc-halo,var%jec+halo
1409  do i=var%isc-halo,var%iec+halo
1410  var%bc(n)%field(m)%values(i,j,k) = var_in%bc(n)%field(m)%values(i+i_off,j+j_off)
1411  enddo
1412  enddo
1413  enddo
1414  endif
1415  enddo
1416  enddo
1417  end subroutine ct_copy_data_2d_3d
1418 
1419 
1420  !> Redistribute the data in all elements of a coupler_2d_bc_type
1421  !!
1422  !! Redistributes the data in all elements of one coupler_2d_bc_type
1423  !! into another, which may be on different processors with a different decomposition.
1424  !!
1425  !! \throw FATAL, "Mismatch in num_bcs in CT_copy_data_2d."
1426  !! \throw FATAL, "Mismatch in the total number of fields in CT_redistribute_data_2d."
1427  subroutine ct_redistribute_data_2d(var_in, domain_in, var_out, domain_out, complete)
1428  type(coupler_2d_bc_type), intent(in) :: var_in !< BC_type structure with the data to copy (intent in)
1429  type(domain2D), intent(in) :: domain_in !< The FMS domain for the input structure
1430  type(coupler_2d_bc_type), intent(inout) :: var_out !< The recipient BC_type structure (data intent out)
1431  type(domain2D), intent(in) :: domain_out !< The FMS domain for the output structure
1432  logical, optional, intent(in) :: complete !< If true, complete the updates
1433 
1434  real, pointer, dimension(:,:) :: null_ptr2D => null()
1435  logical :: do_in, do_out, do_complete
1436  integer :: m, n, fc, fc_in, fc_out
1437 
1438  do_complete = .true.
1439  if (present(complete)) do_complete = complete
1440 
1441  ! Figure out whether this PE has valid input or output fields or both.
1442  do_in = var_in%set
1443  do_out = var_out%set
1444 
1445  fc_in = 0 ; fc_out = 0
1446  if (do_in) then
1447  do n = 1, var_in%num_bcs
1448  do m = 1, var_in%bc(n)%num_fields
1449  if (associated(var_in%bc(n)%field(m)%values)) fc_in = fc_in + 1
1450  enddo
1451  enddo
1452  endif
1453  if (fc_in == 0) do_in = .false.
1454  if (do_out) then
1455  do n = 1, var_out%num_bcs
1456  do m = 1, var_out%bc(n)%num_fields
1457  if (associated(var_out%bc(n)%field(m)%values)) fc_out = fc_out + 1
1458  enddo
1459  enddo
1460  endif
1461  if (fc_out == 0) do_out = .false.
1462 
1463  if (do_in .and. do_out) then
1464  if (var_in%num_bcs /= var_out%num_bcs) call mpp_error(fatal,&
1465  & "Mismatch in num_bcs in CT_copy_data_2d.")
1466  if (fc_in /= fc_out) call mpp_error(fatal,&
1467  & "Mismatch in the total number of fields in CT_redistribute_data_2d.")
1468  endif
1469 
1470  if (.not.(do_in .or. do_out)) return
1471 
1472  fc = 0
1473  if (do_in .and. do_out) then
1474  do n = 1, var_in%num_bcs
1475  do m = 1, var_in%bc(n)%num_fields
1476  if ( associated(var_in%bc(n)%field(m)%values) .neqv.&
1477  & associated(var_out%bc(n)%field(m)%values) ) &
1478  call mpp_error(fatal,&
1479  & "Mismatch in which fields are associated in CT_redistribute_data_2d.")
1480  if ( associated(var_in%bc(n)%field(m)%values) ) then
1481  fc = fc + 1
1482  call mpp_redistribute(domain_in, var_in%bc(n)%field(m)%values,&
1483  & domain_out, var_out%bc(n)%field(m)%values,&
1484  & complete=(do_complete.and.(fc==fc_in)) )
1485  endif
1486  enddo
1487  enddo
1488  elseif (do_in) then
1489  do n = 1, var_in%num_bcs
1490  do m = 1, var_in%bc(n)%num_fields
1491  if ( associated(var_in%bc(n)%field(m)%values) ) then
1492  fc = fc + 1
1493  call mpp_redistribute(domain_in, var_in%bc(n)%field(m)%values,&
1494  & domain_out, null_ptr2d,&
1495  & complete=(do_complete.and.(fc==fc_in)) )
1496  endif
1497  enddo
1498  enddo
1499  elseif (do_out) then
1500  do n = 1, var_out%num_bcs
1501  do m = 1, var_out%bc(n)%num_fields
1502  if ( associated(var_out%bc(n)%field(m)%values) ) then
1503  fc = fc + 1
1504  call mpp_redistribute(domain_in, null_ptr2d,&
1505  & domain_out, var_out%bc(n)%field(m)%values,&
1506  & complete=(do_complete.and.(fc==fc_out)) )
1507  endif
1508  enddo
1509  enddo
1510  endif
1511  end subroutine ct_redistribute_data_2d
1512 
1513  !> Redistributes the data in all elements of one coupler_2d_bc_type
1514  !!
1515  !! Redistributes the data in all elements of one coupler_2d_bc_type into another, which may be on
1516  !! different processors with a different decomposition.
1517  subroutine ct_redistribute_data_3d(var_in, domain_in, var_out, domain_out, complete)
1518  type(coupler_3d_bc_type), intent(in) :: var_in !< BC_type structure with the data to copy (intent in)
1519  type(domain2D), intent(in) :: domain_in !< The FMS domain for the input structure
1520  type(coupler_3d_bc_type), intent(inout) :: var_out !< The recipient BC_type structure (data intent out)
1521  type(domain2D), intent(in) :: domain_out !< The FMS domain for the output structure
1522  logical, optional, intent(in) :: complete !< If true, complete the updates
1523 
1524  real, pointer, dimension(:,:,:) :: null_ptr3D => null()
1525  logical :: do_in, do_out, do_complete
1526  integer :: m, n, fc, fc_in, fc_out
1527 
1528  do_complete = .true.
1529  if (present(complete)) do_complete = complete
1530 
1531  ! Figure out whether this PE has valid input or output fields or both.
1532  do_in = var_in%set
1533  do_out = var_out%set
1534 
1535  fc_in = 0
1536  fc_out = 0
1537  if (do_in) then
1538  do n = 1, var_in%num_bcs
1539  do m = 1, var_in%bc(n)%num_fields
1540  if (associated(var_in%bc(n)%field(m)%values)) fc_in = fc_in + 1
1541  enddo
1542  enddo
1543  endif
1544  if (fc_in == 0) do_in = .false.
1545  if (do_out) then
1546  do n = 1, var_out%num_bcs
1547  do m = 1, var_out%bc(n)%num_fields
1548  if (associated(var_out%bc(n)%field(m)%values)) fc_out = fc_out + 1
1549  enddo
1550  enddo
1551  endif
1552  if (fc_out == 0) do_out = .false.
1553 
1554  if (do_in .and. do_out) then
1555  if (var_in%num_bcs /= var_out%num_bcs) call mpp_error(fatal,&
1556  & "Mismatch in num_bcs in CT_copy_data_3d.")
1557  if (fc_in /= fc_out) call mpp_error(fatal,&
1558  & "Mismatch in the total number of fields in CT_redistribute_data_3d.")
1559  endif
1560 
1561  if (.not.(do_in .or. do_out)) return
1562 
1563  fc = 0
1564  if (do_in .and. do_out) then
1565  do n = 1, var_in%num_bcs
1566  do m = 1, var_in%bc(n)%num_fields
1567  if ( associated(var_in%bc(n)%field(m)%values) .neqv.&
1568  & associated(var_out%bc(n)%field(m)%values) )&
1569  & call mpp_error(fatal,&
1570  & "Mismatch in which fields are associated in CT_redistribute_data_3d.")
1571  if ( associated(var_in%bc(n)%field(m)%values) ) then
1572  fc = fc + 1
1573  call mpp_redistribute(domain_in, var_in%bc(n)%field(m)%values,&
1574  & domain_out, var_out%bc(n)%field(m)%values,&
1575  & complete=(do_complete.and.(fc==fc_in)) )
1576  endif
1577  enddo
1578  enddo
1579  elseif (do_in) then
1580  do n = 1, var_in%num_bcs
1581  do m = 1, var_in%bc(n)%num_fields
1582  if ( associated(var_in%bc(n)%field(m)%values) ) then
1583  fc = fc + 1
1584  call mpp_redistribute(domain_in, var_in%bc(n)%field(m)%values,&
1585  & domain_out, null_ptr3d,&
1586  & complete=(do_complete.and.(fc==fc_in)) )
1587  endif
1588  enddo
1589  enddo
1590  elseif (do_out) then
1591  do n = 1, var_out%num_bcs
1592  do m = 1, var_out%bc(n)%num_fields
1593  if ( associated(var_out%bc(n)%field(m)%values) ) then
1594  fc = fc + 1
1595  call mpp_redistribute(domain_in, null_ptr3d,&
1596  & domain_out, var_out%bc(n)%field(m)%values,&
1597  & complete=(do_complete.and.(fc==fc_out)) )
1598  endif
1599  enddo
1600  enddo
1601  endif
1602  end subroutine ct_redistribute_data_3d
1603 
1604 
1605  !> Rescales the fields in the fields in the elements of a coupler_2d_bc_type
1606  !!
1607  !! Rescales the fields in the elements of a coupler_2d_bc_type by multiplying by a factor scale.
1608  !! If scale is 0, this is a direct assignment to 0, so that NaNs will not persist.
1609  subroutine ct_rescale_data_2d(var, scale, halo_size, bc_index, field_index,&
1610  & exclude_flux_type, only_flux_type, pass_through_ice)
1611  type(coupler_2d_bc_type), intent(inout) :: var !< The BC_type structure whose fields are being rescaled
1612  real, intent(in) :: scale !< A scaling factor to multiply fields by
1613  integer, optional, intent(in) :: halo_size !< The extent of the halo to copy; 0 by default or
1614  !! the full arrays if scale is 0.
1615  integer, optional, intent(in) :: bc_index !< The index of the boundary condition
1616  !! that is being copied
1617  integer, optional, intent(in) :: field_index !< The index of the field in the
1618  !! boundary condition that is being copied
1619  character(len=*), optional, intent(in) :: exclude_flux_type !< A string describing which types
1620  !! of fluxes to exclude from this copy.
1621  character(len=*), optional, intent(in) :: only_flux_type !< A string describing which types
1622  !! of fluxes to include from this copy.
1623  logical, optional, intent(in) :: pass_through_ice !< If true, only copy BCs whose
1624  !! value of pass_through ice matches this
1625 
1626  logical :: do_bc
1627  integer :: i, j, m, n, n1, n2, halo
1628 
1629  if (present(bc_index)) then
1630  if (bc_index > var%num_bcs)&
1631  & call mpp_error(fatal, "CT_rescale_data_2d: bc_index is present and exceeds var%num_bcs.")
1632  if (present(field_index)) then ; if (field_index > var%bc(bc_index)%num_fields)&
1633  & call mpp_error(fatal, "CT_rescale_data_2d: field_index is present and exceeds num_fields for" //&
1634  & trim(var%bc(bc_index)%name) )
1635  endif
1636  elseif (present(field_index)) then
1637  call mpp_error(fatal, "CT_rescale_data_2d: bc_index must be present if field_index is present.")
1638  endif
1639 
1640  halo = 0
1641  if (present(halo_size)) halo = halo_size
1642 
1643  n1 = 1
1644  n2 = var%num_bcs
1645  if (present(bc_index)) then
1646  n1 = bc_index
1647  n2 = bc_index
1648  endif
1649 
1650  if (n2 >= n1) then
1651  ! A more consciencious implementation would include a more descriptive error messages.
1652  if ((var%isc-var%isd < halo) .or. (var%ied-var%iec < halo))&
1653  & call mpp_error(fatal, "CT_rescale_data_2d: Excessive i-direction halo size.")
1654  if ((var%jsc-var%jsd < halo) .or. (var%jed-var%jec < halo))&
1655  & call mpp_error(fatal, "CT_rescale_data_2d: Excessive j-direction halo size.")
1656  endif
1657 
1658  do n = n1, n2
1659  do_bc = .true.
1660  if (do_bc .and. present(exclude_flux_type))&
1661  & do_bc = .not.(trim(var%bc(n)%flux_type) == trim(exclude_flux_type))
1662  if (do_bc .and. present(only_flux_type))&
1663  & do_bc = (trim(var%bc(n)%flux_type) == trim(only_flux_type))
1664  if (do_bc .and. present(pass_through_ice))&
1665  & do_bc = (pass_through_ice .eqv. var%bc(n)%pass_through_ice)
1666  if (.not.do_bc) cycle
1667 
1668  do m = 1, var%bc(n)%num_fields
1669  if (present(field_index)) then
1670  if (m /= field_index) cycle
1671  endif
1672  if ( associated(var%bc(n)%field(m)%values) ) then
1673  if (scale == 0.0) then
1674  if (present(halo_size)) then
1675  do j=var%jsc-halo,var%jec+halo
1676  do i=var%isc-halo,var%iec+halo
1677  var%bc(n)%field(m)%values(i,j) = 0.0
1678  enddo
1679  enddo
1680  else
1681  var%bc(n)%field(m)%values(:,:) = 0.0
1682  endif
1683  else
1684  do j=var%jsc-halo,var%jec+halo
1685  do i=var%isc-halo,var%iec+halo
1686  var%bc(n)%field(m)%values(i,j) = scale * var%bc(n)%field(m)%values(i,j)
1687  enddo
1688  enddo
1689  endif
1690  endif
1691  enddo
1692  enddo
1693  end subroutine ct_rescale_data_2d
1694 
1695  !! Rescales the fields in the elements of a coupler_3d_bc_type
1696  !!
1697  !! This subroutine rescales the fields in the elements of a coupler_3d_bc_type by multiplying by a
1698  !! factor scale. If scale is 0, this is a direct assignment to 0, so that NaNs will not persist.
1699  subroutine ct_rescale_data_3d(var, scale, halo_size, bc_index, field_index,&
1700  & exclude_flux_type, only_flux_type, pass_through_ice)
1701  type(coupler_3d_bc_type), intent(inout) :: var !< The BC_type structure whose fields are being rescaled
1702  real, intent(in) :: scale !< A scaling factor to multiply fields by
1703  integer, optional, intent(in) :: halo_size !< The extent of the halo to copy; 0 by default or
1704  !! the full arrays if scale is 0.
1705  integer, optional, intent(in) :: bc_index !< The index of the boundary condition
1706  !! that is being copied
1707  integer, optional, intent(in) :: field_index !< The index of the field in the
1708  !! boundary condition that is being copied
1709  character(len=*), optional, intent(in) :: exclude_flux_type !< A string describing which types
1710  !! of fluxes to exclude from this copy.
1711  character(len=*), optional, intent(in) :: only_flux_type !< A string describing which types of
1712  !! fluxes to include from this copy.
1713  logical, optional, intent(in) :: pass_through_ice !< If true, only copy BCs whose
1714  !! value of pass_through ice matches this
1715 
1716  logical :: do_bc
1717  integer :: i, j, k, m, n, n1, n2, halo
1718 
1719  if (present(bc_index)) then
1720  if (bc_index > var%num_bcs)&
1721  & call mpp_error(fatal, "CT_rescale_data_2d: bc_index is present and exceeds var%num_bcs.")
1722  if (present(field_index)) then ; if (field_index > var%bc(bc_index)%num_fields)&
1723  & call mpp_error(fatal, "CT_rescale_data_2d: field_index is present and exceeds num_fields for" //&
1724  & trim(var%bc(bc_index)%name) )
1725  endif
1726  elseif (present(field_index)) then
1727  call mpp_error(fatal, "CT_rescale_data_2d: bc_index must be present if field_index is present.")
1728  endif
1729 
1730  halo = 0
1731  if (present(halo_size)) halo = halo_size
1732 
1733  n1 = 1
1734  n2 = var%num_bcs
1735  if (present(bc_index)) then
1736  n1 = bc_index
1737  n2 = bc_index
1738  endif
1739 
1740  if (n2 >= n1) then
1741  ! A more consciencious implementation would include a more descriptive error messages.
1742  if ((var%isc-var%isd < halo) .or. (var%ied-var%iec < halo))&
1743  & call mpp_error(fatal, "CT_rescale_data_3d: Excessive i-direction halo size.")
1744  if ((var%jsc-var%jsd < halo) .or. (var%jed-var%jec < halo))&
1745  & call mpp_error(fatal, "CT_rescale_data_3d: Excessive j-direction halo size.")
1746  endif
1747 
1748  do n = n1, n2
1749  do_bc = .true.
1750  if (do_bc .and. present(exclude_flux_type))&
1751  & do_bc = .not.(trim(var%bc(n)%flux_type) == trim(exclude_flux_type))
1752  if (do_bc .and. present(only_flux_type))&
1753  & do_bc = (trim(var%bc(n)%flux_type) == trim(only_flux_type))
1754  if (do_bc .and. present(pass_through_ice))&
1755  & do_bc = (pass_through_ice .eqv. var%bc(n)%pass_through_ice)
1756  if (.not.do_bc) cycle
1757 
1758  do m = 1, var%bc(n)%num_fields
1759  if (present(field_index)) then
1760  if (m /= field_index) cycle
1761  endif
1762  if ( associated(var%bc(n)%field(m)%values) ) then
1763  if (scale == 0.0) then
1764  if (present(halo_size)) then
1765  do k=var%ks,var%ke
1766  do j=var%jsc-halo,var%jec+halo
1767  do i=var%isc-halo,var%iec+halo
1768  var%bc(n)%field(m)%values(i,j,k) = 0.0
1769  enddo
1770  enddo
1771  enddo
1772  else
1773  var%bc(n)%field(m)%values(:,:,:) = 0.0
1774  endif
1775  else
1776  do k=var%ks,var%ke
1777  do j=var%jsc-halo,var%jec+halo
1778  do i=var%isc-halo,var%iec+halo
1779  var%bc(n)%field(m)%values(i,j,k) = scale * var%bc(n)%field(m)%values(i,j,k)
1780  enddo
1781  enddo
1782  enddo
1783  endif
1784  endif
1785  enddo
1786  enddo
1787  end subroutine ct_rescale_data_3d
1788 
1789 
1790  !! Increment data in all elements of one coupler_2d_bc_type
1791  !!
1792  !! Do a direct increment of the data in all elements of one coupler_2d_bc_type into another. Both
1793  !! must have the same array sizes.
1794  !!
1795  !! \throw FATAL, "bc_index is present and exceeds var_in%num_bcs."
1796  !! \throw FATAL, "field_index is present and exceeds num_fields for var_in%bc(bc_incdx)%name"
1797  !! \throw FATAL, "bc_index must be present if field_index is present."
1798  !! \throw FATAL, "There is an i-direction computational domain size mismatch."
1799  !! \throw FATAL, "There is an j-direction computational domain size mismatch."
1800  !! \throw FATAL, "Excessive i-direction halo size for the input structure."
1801  !! \throw FATAL, "Excessive i-direction halo size for the input structure."
1802  subroutine ct_increment_data_2d_2d(var_in, var, halo_size, bc_index, field_index,&
1803  & scale_factor, scale_prev, exclude_flux_type, only_flux_type, pass_through_ice)
1804  type(coupler_2d_bc_type), intent(in) :: var_in !< BC_type structure with the data to add to the other type
1805  type(coupler_2d_bc_type), intent(inout) :: var !< The BC_type structure whose fields are being incremented
1806  integer, optional, intent(in) :: halo_size !< The extent of the halo to increment; 0 by default
1807  integer, optional, intent(in) :: bc_index !< The index of the boundary condition
1808  !! that is being copied
1809  integer, optional, intent(in) :: field_index !< The index of the field in the
1810  !! boundary condition that is being copied
1811  real, optional, intent(in) :: scale_factor !< A scaling factor for the data that is being added
1812  real, optional, intent(in) :: scale_prev !< A scaling factor for the data that is already here
1813  character(len=*), optional, intent(in) :: exclude_flux_type !< A string describing which types
1814  !! of fluxes to exclude from this increment.
1815  character(len=*), optional, intent(in) :: only_flux_type !< A string describing which types
1816  !! of fluxes to include from this increment.
1817  logical, optional, intent(in) :: pass_through_ice !< If true, only increment BCs whose
1818  !! value of pass_through ice matches this
1819 
1820  real :: scale, sc_prev
1821  logical :: increment_bc
1822  integer :: i, j, m, n, n1, n2, halo, i_off, j_off
1823 
1824  scale = 1.0
1825  if (present(scale_factor)) scale = scale_factor
1826  sc_prev = 1.0
1827  if (present(scale_prev)) sc_prev = scale_prev
1828 
1829  if (present(bc_index)) then
1830  if (bc_index > var_in%num_bcs)&
1831  & call mpp_error(fatal, "CT_increment_data_2d_2d: bc_index is present and exceeds var_in%num_bcs.")
1832  if (present(field_index)) then
1833  if (field_index > var_in%bc(bc_index)%num_fields)&
1834  & call mpp_error(fatal, "CT_increment_data_2d_2d: field_index is present and exceeds num_fields for" //&
1835  & trim(var_in%bc(bc_index)%name) )
1836  endif
1837  elseif (present(field_index)) then
1838  call mpp_error(fatal, "CT_increment_data_2d_2d: bc_index must be present if field_index is present.")
1839  endif
1840 
1841  halo = 0
1842  if (present(halo_size)) halo = halo_size
1843 
1844  n1 = 1
1845  n2 = var_in%num_bcs
1846  if (present(bc_index)) then
1847  n1 = bc_index
1848  n2 = bc_index
1849  endif
1850 
1851  if (n2 >= n1) then
1852  ! A more consciencious implementation would include a more descriptive error messages.
1853  if ((var_in%iec-var_in%isc) /= (var%iec-var%isc))&
1854  & call mpp_error(fatal, "CT_increment_data_2d: There is an i-direction computational domain size mismatch.")
1855  if ((var_in%jec-var_in%jsc) /= (var%jec-var%jsc))&
1856  & call mpp_error(fatal, "CT_increment_data_2d: There is a j-direction computational domain size mismatch.")
1857  if ((var_in%isc-var_in%isd < halo) .or. (var_in%ied-var_in%iec < halo))&
1858  & call mpp_error(fatal, "CT_increment_data_2d: Excessive i-direction halo size for the input structure.")
1859  if ((var_in%jsc-var_in%jsd < halo) .or. (var_in%jed-var_in%jec < halo))&
1860  & call mpp_error(fatal, "CT_increment_data_2d: Excessive j-direction halo size for the input structure.")
1861  if ((var%isc-var%isd < halo) .or. (var%ied-var%iec < halo))&
1862  & call mpp_error(fatal, "CT_increment_data_2d: Excessive i-direction halo size for the output structure.")
1863  if ((var%jsc-var%jsd < halo) .or. (var%jed-var%jec < halo))&
1864  & call mpp_error(fatal, "CT_increment_data_2d: Excessive j-direction halo size for the output structure.")
1865 
1866  i_off = var_in%isc - var%isc
1867  j_off = var_in%jsc - var%jsc
1868  endif
1869 
1870  do n = n1, n2
1871  increment_bc = .true.
1872  if (increment_bc .and. present(exclude_flux_type))&
1873  & increment_bc = .not.(trim(var%bc(n)%flux_type) == trim(exclude_flux_type))
1874  if (increment_bc .and. present(only_flux_type))&
1875  & increment_bc = (trim(var%bc(n)%flux_type) == trim(only_flux_type))
1876  if (increment_bc .and. present(pass_through_ice))&
1877  & increment_bc = (pass_through_ice .eqv. var%bc(n)%pass_through_ice)
1878  if (.not.increment_bc) cycle
1879 
1880  do m = 1, var_in%bc(n)%num_fields
1881  if (present(field_index)) then
1882  if (m /= field_index) cycle
1883  endif
1884  if ( associated(var%bc(n)%field(m)%values) ) then
1885  do j=var%jsc-halo,var%jec+halo
1886  do i=var%isc-halo,var%iec+halo
1887  var%bc(n)%field(m)%values(i,j) = sc_prev * var%bc(n)%field(m)%values(i,j) +&
1888  & scale * var_in%bc(n)%field(m)%values(i+i_off,j+j_off)
1889  enddo
1890  enddo
1891  endif
1892  enddo
1893  enddo
1894  end subroutine ct_increment_data_2d_2d
1895 
1896 
1897  !! Increment data in all elements of one coupler_3d_bc_type
1898  !!
1899  !! Do a direct increment of the data in all elements of one coupler_3d_bc_type into another. Both
1900  !! must have the same array sizes.
1901  !!
1902  !! \throw FATAL, "bc_index is present and exceeds var_in%num_bcs."
1903  !! \throw FATAL, "field_index is present and exceeds num_fields for var_in%bc(bc_incdx)%name"
1904  !! \throw FATAL, "bc_index must be present if field_index is present."
1905  !! \throw FATAL, "There is an i-direction computational domain size mismatch."
1906  !! \throw FATAL, "There is an j-direction computational domain size mismatch."
1907  !! \throw FATAL, "There is an k-direction computational domain size mismatch."
1908  !! \throw FATAL, "Excessive i-direction halo size for the input structure."
1909  !! \throw FATAL, "Excessive i-direction halo size for the input structure."
1910  !! \throw FATAL, "Excessive k-direction halo size for the input structure."
1911  subroutine ct_increment_data_3d_3d(var_in, var, halo_size, bc_index, field_index,&
1912  & scale_factor, scale_prev, exclude_flux_type, only_flux_type, pass_through_ice)
1913  type(coupler_3d_bc_type), intent(in) :: var_in !< BC_type structure with the data to add to the other type
1914  type(coupler_3d_bc_type), intent(inout) :: var !< The BC_type structure whose fields are being incremented
1915  integer, optional, intent(in) :: halo_size !< The extent of the halo to copy; 0 by default
1916  integer, optional, intent(in) :: bc_index !< The index of the boundary condition
1917  !! that is being copied
1918  integer, optional, intent(in) :: field_index !< The index of the field in the
1919  !! boundary condition that is being copied
1920  real, optional, intent(in) :: scale_factor !< A scaling factor for the data that is being added
1921  real, optional, intent(in) :: scale_prev !< A scaling factor for the data that is already here
1922  character(len=*), optional, intent(in) :: exclude_flux_type !< A string describing which types
1923  !! of fluxes to exclude from this increment.
1924  character(len=*), optional, intent(in) :: only_flux_type !< A string describing which types of
1925  !! fluxes to include from this increment.
1926  logical, optional, intent(in) :: pass_through_ice !< If true, only increment BCs whose
1927  !! value of pass_through ice matches this
1928 
1929  real :: scale, sc_prev
1930  logical :: increment_bc
1931  integer :: i, j, k, m, n, n1, n2, halo, i_off, j_off, k_off
1932 
1933  scale = 1.0
1934  if (present(scale_factor)) scale = scale_factor
1935  sc_prev = 1.0
1936  if (present(scale_prev)) sc_prev = scale_prev
1937 
1938  if (present(bc_index)) then
1939  if (bc_index > var_in%num_bcs)&
1940  & call mpp_error(fatal, "CT_increment_data_3d_3d: bc_index is present and exceeds var_in%num_bcs.")
1941  if (present(field_index)) then ; if (field_index > var_in%bc(bc_index)%num_fields)&
1942  & call mpp_error(fatal, "CT_increment_data_3d_3d: field_index is present and exceeds num_fields for" //&
1943  & trim(var_in%bc(bc_index)%name) )
1944  endif
1945  elseif (present(field_index)) then
1946  call mpp_error(fatal, "CT_increment_data_3d_3d: bc_index must be present if field_index is present.")
1947  endif
1948 
1949  halo = 0
1950  if (present(halo_size)) halo = halo_size
1951 
1952  n1 = 1
1953  n2 = var_in%num_bcs
1954  if (present(bc_index)) then
1955  n1 = bc_index
1956  n2 = bc_index
1957  endif
1958 
1959  if (n2 >= n1) then
1960  ! A more consciencious implementation would include a more descriptive error messages.
1961  if ((var_in%iec-var_in%isc) /= (var%iec-var%isc))&
1962  & call mpp_error(fatal, "CT_increment_data_3d: There is an i-direction computational domain size mismatch.")
1963  if ((var_in%jec-var_in%jsc) /= (var%jec-var%jsc))&
1964  & call mpp_error(fatal, "CT_increment_data_3d: There is a j-direction computational domain size mismatch.")
1965  if ((var_in%ke-var_in%ks) /= (var%ke-var%ks))&
1966  & call mpp_error(fatal, "CT_increment_data_3d: There is a k-direction computational domain size mismatch.")
1967  if ((var_in%isc-var_in%isd < halo) .or. (var_in%ied-var_in%iec < halo))&
1968  & call mpp_error(fatal, "CT_increment_data_3d: Excessive i-direction halo size for the input structure.")
1969  if ((var_in%jsc-var_in%jsd < halo) .or. (var_in%jed-var_in%jec < halo))&
1970  & call mpp_error(fatal, "CT_increment_data_3d: Excessive j-direction halo size for the input structure.")
1971  if ((var%isc-var%isd < halo) .or. (var%ied-var%iec < halo))&
1972  & call mpp_error(fatal, "CT_increment_data_3d: Excessive i-direction halo size for the output structure.")
1973  if ((var%jsc-var%jsd < halo) .or. (var%jed-var%jec < halo))&
1974  & call mpp_error(fatal, "CT_increment_data_3d: Excessive j-direction halo size for the output structure.")
1975 
1976  i_off = var_in%isc - var%isc
1977  j_off = var_in%jsc - var%jsc
1978  k_off = var_in%ks - var%ks
1979  endif
1980 
1981  do n = n1, n2
1982  increment_bc = .true.
1983  if (increment_bc .and. present(exclude_flux_type))&
1984  & increment_bc = .not.(trim(var%bc(n)%flux_type) == trim(exclude_flux_type))
1985  if (increment_bc .and. present(only_flux_type))&
1986  & increment_bc = (trim(var%bc(n)%flux_type) == trim(only_flux_type))
1987  if (increment_bc .and. present(pass_through_ice))&
1988  & increment_bc = (pass_through_ice .eqv. var%bc(n)%pass_through_ice)
1989  if (.not.increment_bc) cycle
1990 
1991  do m = 1, var_in%bc(n)%num_fields
1992  if (present(field_index)) then
1993  if (m /= field_index) cycle
1994  endif
1995  if ( associated(var%bc(n)%field(m)%values) ) then
1996  do k=var%ks,var%ke
1997  do j=var%jsc-halo,var%jec+halo
1998  do i=var%isc-halo,var%iec+halo
1999  var%bc(n)%field(m)%values(i,j,k) = sc_prev * var%bc(n)%field(m)%values(i,j,k) +&
2000  & scale * var_in%bc(n)%field(m)%values(i+i_off,j+j_off,k+k_off)
2001  enddo
2002  enddo
2003  enddo
2004  endif
2005  enddo
2006  enddo
2007  end subroutine ct_increment_data_3d_3d
2008 
2009  !! Increment data in the elements of a coupler_2d_bc_type with weighted averages of elements of a
2010  !! coupler_3d_bc_type
2011  !!
2012  !! Increments the data in the elements of a coupler_2d_bc_type with the weighed average of the
2013  !! elements of a coupler_3d_bc_type. Both must have the same horizontal array sizes and the
2014  !! normalized weight array must match the array sizes of the coupler_3d_bc_type.
2015  !!
2016  !! \throw FATAL, "bc_index is present and exceeds var_in%num_bcs."
2017  !! \throw FATAL, "field_index is present and exceeds num_fields for var_in%bc(bc_incdx)%name"
2018  !! \throw FATAL, "bc_index must be present if field_index is present."
2019  !! \throw FATAL, "There is an i-direction computational domain size mismatch."
2020  !! \throw FATAL, "There is an j-direction computational domain size mismatch."
2021  !! \throw FATAL, "There is an k-direction computational domain size mismatch."
2022  !! \throw FATAL, "Excessive i-direction halo size for the input structure."
2023  !! \throw FATAL, "Excessive i-direction halo size for the input structure."
2024  !! \throw FATAL, "weights array must be the i-size of a computational or data domain."
2025  !! \throw FATAL, "weights array must be the j-size of a computational or data domain."
2026  subroutine ct_increment_data_2d_3d(var_in, weights, var, halo_size, bc_index, field_index,&
2027  & scale_factor, scale_prev, exclude_flux_type, only_flux_type, pass_through_ice)
2028  type(coupler_3d_bc_type), intent(in) :: var_in !< BC_type structure with the data to add to the other type
2029  real, dimension(:,:,:), intent(in) :: weights !< An array of normalized weights for the 3d-data to
2030  !! increment the 2d-data. There is no renormalization,
2031  !! so if the weights do not sum to 1 in the 3rd dimension
2032  !! there may be adverse consequences!
2033  type(coupler_2d_bc_type), intent(inout) :: var !< The BC_type structure whose fields are being incremented
2034  integer, optional, intent(in) :: halo_size !< The extent of the halo to copy; 0 by default
2035  integer, optional, intent(in) :: bc_index !< The index of the boundary condition
2036  !! that is being copied
2037  integer, optional, intent(in) :: field_index !< The index of the field in the
2038  !! boundary condition that is being copied
2039  real, optional, intent(in) :: scale_factor !< A scaling factor for the data that is being added
2040  real, optional, intent(in) :: scale_prev !< A scaling factor for the data that is already here
2041  character(len=*), optional, intent(in) :: exclude_flux_type !< A string describing which types
2042  !! of fluxes to exclude from this increment.
2043  character(len=*), optional, intent(in) :: only_flux_type !< A string describing which types
2044  !! of fluxes to include from this increment.
2045  logical, optional, intent(in) :: pass_through_ice !< If true, only increment BCs whose
2046  !! value of pass_through ice matches this
2047 
2048  real :: scale, sc_prev
2049  logical :: increment_bc
2050  integer :: i, j, k, m, n, n1, n2, halo
2051  integer :: io1, jo1, iow, jow, kow ! Offsets to account for different index conventions.
2052 
2053  scale = 1.0
2054  if (present(scale_factor)) scale = scale_factor
2055  sc_prev = 1.0
2056  if (present(scale_prev)) sc_prev = scale_prev
2057 
2058  if (present(bc_index)) then
2059  if (bc_index > var_in%num_bcs)&
2060  & call mpp_error(fatal, "CT_increment_data_2d_3d: bc_index is present and exceeds var_in%num_bcs.")
2061  if (present(field_index)) then ; if (field_index > var_in%bc(bc_index)%num_fields)&
2062  & call mpp_error(fatal, "CT_increment_data_2d_3d: field_index is present and exceeds num_fields for" //&
2063  & trim(var_in%bc(bc_index)%name) )
2064  endif
2065  elseif (present(field_index)) then
2066  call mpp_error(fatal, "CT_increment_data_2d_3d: bc_index must be present if field_index is present.")
2067  endif
2068 
2069  halo = 0
2070  if (present(halo_size)) halo = halo_size
2071 
2072  n1 = 1
2073  n2 = var_in%num_bcs
2074  if (present(bc_index)) then
2075  n1 = bc_index
2076  n2 = bc_index
2077  endif
2078 
2079  if (n2 >= n1) then
2080  ! A more consciencious implementation would include a more descriptive error messages.
2081  if ((var_in%iec-var_in%isc) /= (var%iec-var%isc))&
2082  & call mpp_error(fatal, "CT_increment_data_2d_3d: There is an i-direction computational domain size mismatch.")
2083  if ((var_in%jec-var_in%jsc) /= (var%jec-var%jsc))&
2084  & call mpp_error(fatal, "CT_increment_data_2d_3d: There is a j-direction computational domain size mismatch.")
2085  if ((1+var_in%ke-var_in%ks) /= size(weights,3))&
2086  & call mpp_error(fatal, "CT_increment_data_2d_3d: There is a k-direction size mismatch with the weights array.")
2087  if ((var_in%isc-var_in%isd < halo) .or. (var_in%ied-var_in%iec < halo))&
2088  & call mpp_error(fatal, "CT_increment_data_2d_3d: Excessive i-direction halo size for the input structure.")
2089  if ((var_in%jsc-var_in%jsd < halo) .or. (var_in%jed-var_in%jec < halo))&
2090  & call mpp_error(fatal, "CT_increment_data_2d_3d: Excessive j-direction halo size for the input structure.")
2091  if ((var%isc-var%isd < halo) .or. (var%ied-var%iec < halo))&
2092  & call mpp_error(fatal, "CT_increment_data_2d_3d: Excessive i-direction halo size for the output structure.")
2093  if ((var%jsc-var%jsd < halo) .or. (var%jed-var%jec < halo))&
2094  & call mpp_error(fatal, "CT_increment_data_2d_3d: Excessive j-direction halo size for the output structure.")
2095 
2096  if ((1+var%iec-var%isc) == size(weights,1)) then
2097  iow = 1 - var%isc
2098  elseif ((1+var%ied-var%isd) == size(weights,1)) then
2099  iow = 1 - var%isd
2100  elseif ((1+var_in%ied-var_in%isd) == size(weights,1)) then
2101  iow = 1 + (var_in%isc - var_in%isd) - var%isc
2102  else
2103  call mpp_error(fatal, "CT_increment_data_2d_3d: weights array must be the i-size of a computational or data domain.")
2104  endif
2105  if ((1+var%jec-var%jsc) == size(weights,2)) then
2106  jow = 1 - var%jsc
2107  elseif ((1+var%jed-var%jsd) == size(weights,2)) then
2108  jow = 1 - var%jsd
2109  elseif ((1+var_in%jed-var_in%jsd) == size(weights,2)) then
2110  jow = 1 + (var_in%jsc - var_in%jsd) - var%jsc
2111  else
2112  call mpp_error(fatal, "CT_increment_data_2d_3d: weights array must be the j-size of a computational or data domain.")
2113  endif
2114 
2115  io1 = var_in%isc - var%isc
2116  jo1 = var_in%jsc - var%jsc
2117  kow = 1 - var_in%ks
2118  endif
2119 
2120  do n = n1, n2
2121  increment_bc = .true.
2122  if (increment_bc .and. present(exclude_flux_type))&
2123  & increment_bc = .not.(trim(var_in%bc(n)%flux_type) == trim(exclude_flux_type))
2124  if (increment_bc .and. present(only_flux_type))&
2125  & increment_bc = (trim(var_in%bc(n)%flux_type) == trim(only_flux_type))
2126  if (increment_bc .and. present(pass_through_ice))&
2127  & increment_bc = (pass_through_ice .eqv. var_in%bc(n)%pass_through_ice)
2128  if (.not.increment_bc) cycle
2129 
2130  do m = 1, var_in%bc(n)%num_fields
2131  if (present(field_index)) then
2132  if (m /= field_index) cycle
2133  endif
2134  if ( associated(var%bc(n)%field(m)%values) ) then
2135  do k=var_in%ks,var_in%ke
2136  do j=var%jsc-halo,var%jec+halo
2137  do i=var%isc-halo,var%iec+halo
2138  var%bc(n)%field(m)%values(i,j) = sc_prev * var%bc(n)%field(m)%values(i,j) +&
2139  & (scale * weights(i+iow,j+jow,k+kow)) * var_in%bc(n)%field(m)%values(i+io1,j+io1,k)
2140  enddo
2141  enddo
2142  enddo
2143  endif
2144  enddo
2145  enddo
2146  end subroutine ct_increment_data_2d_3d
2147 
2148  !> Extract a 2d field from a coupler_2d_bc_type
2149  !!
2150  !! Extract a single 2-d field from a coupler_2d_bc_type into a two-dimensional array.
2151  !!
2152  !! \throw FATAL, "bc_index is present and exceeds var_in%num_bcs."
2153  !! \throw FATAL, "field_index exceeds num_fields for var_in%bc(bc_incdx)%name"
2154  !! \throw FATAL, "Excessive i-direction halo size for the input structure."
2155  !! \throw FATAL, "Excessive j-direction halo size for the input structure."
2156  !! \throw FATAL, "Disordered i-dimension index bound list"
2157  !! \throw FATAL, "Disordered j-dimension index bound list"
2158  !! \throw FATAL, "The declared i-dimension size of 'n' does not match the actual size of 'a'"
2159  !! \throw FATAL, "The declared j-dimension size of 'n' does not match the actual size of 'a'"
2160  !! \throw FATAL, "There is an i-direction computational domain size mismatch."
2161  !! \throw FATAL, "There is an j-direction computational domain size mismatch."
2162  !! \throw FATAL, "The target array with i-dimension size 'n' is too small to match the data of size 'd'"
2163  !! \throw FATAL, "The target array with j-dimension size 'n' is too small to match the data of size 'd'"
2164  subroutine ct_extract_data_2d(var_in, bc_index, field_index, array_out,&
2165  & scale_factor, halo_size, idim, jdim)
2166  type(coupler_2d_bc_type), intent(in) :: var_in !< BC_type structure with the data to extract
2167  integer, intent(in) :: bc_index !< The index of the boundary condition
2168  !! that is being copied
2169  integer, intent(in) :: field_index !< The index of the field in the
2170  !! boundary condition that is being copied
2171  real, dimension(1:,1:), intent(out) :: array_out !< The recipient array for the field; its size
2172  !! must match the size of the data being copied
2173  !! unless idim and jdim are supplied.
2174  real, optional, intent(in) :: scale_factor !< A scaling factor for the data that is being added
2175  integer, optional, intent(in) :: halo_size !< The extent of the halo to copy; 0 by default
2176  integer, dimension(4), optional, intent(in) :: idim !< The data and computational domain extents of
2177  !! the first dimension of the output array
2178  !! in a non-decreasing list
2179  integer, dimension(4), optional, intent(in) :: jdim !< The data and computational domain extents of
2180  !! the second dimension of the output array
2181  !! in a non-decreasing list
2182 
2183  character(len=*), parameter :: error_header =&
2184  & '==>Error from coupler_types_mod (CT_extract_data_2d):'
2185  character(len=400) :: error_msg
2186 
2187  real :: scale
2188  integer :: i, j, halo, i_off, j_off
2189 
2190  if (bc_index <= 0) then
2191  array_out(:,:) = 0.0
2192  return
2193  endif
2194 
2195  halo = 0
2196  if (present(halo_size)) halo = halo_size
2197  scale = 1.0
2198  if (present(scale_factor)) scale = scale_factor
2199 
2200  if ((var_in%isc-var_in%isd < halo) .or. (var_in%ied-var_in%iec < halo))&
2201  & call mpp_error(fatal, trim(error_header)//" Excessive i-direction halo size for the input structure.")
2202  if ((var_in%jsc-var_in%jsd < halo) .or. (var_in%jed-var_in%jec < halo))&
2203  & call mpp_error(fatal, trim(error_header)//" Excessive j-direction halo size for the input structure.")
2204 
2205  if (bc_index > var_in%num_bcs)&
2206  & call mpp_error(fatal, trim(error_header)//" bc_index exceeds var_in%num_bcs.")
2207  if (field_index > var_in%bc(bc_index)%num_fields)&
2208  & call mpp_error(fatal, trim(error_header)//" field_index exceeds num_fields for" //&
2209  & trim(var_in%bc(bc_index)%name) )
2210 
2211  ! Do error checking on the i-dimension and determine the array offsets.
2212  if (present(idim)) then
2213  if ((idim(1) > idim(2)) .or. (idim(3) > idim(4))) then
2214  write (error_msg, *) trim(error_header), ' Disordered i-dimension index bound list ', idim
2215  call mpp_error(fatal, trim(error_msg))
2216  endif
2217  if (size(array_out,1) /= (1+idim(4)-idim(1))) then
2218  write (error_msg, *) trim(error_header), ' The declared i-dimension size of ',&
2219  & (1+idim(4)-idim(1)), ' does not match the actual size of ', size(array_out,1)
2220  call mpp_error(fatal, trim(error_msg))
2221  endif
2222  if ((var_in%iec-var_in%isc) /= (idim(3)-idim(2)))&
2223  & call mpp_error(fatal, trim(error_header)//" There is an i-direction computational domain size mismatch.")
2224  if ((idim(2)-idim(1) < halo) .or. (idim(4)-idim(3) < halo))&
2225  & call mpp_error(fatal, trim(error_header)//" Excessive i-direction halo size for the output array.")
2226  if (size(array_out,1) < 2*halo + 1 + var_in%iec - var_in%isc) then
2227  write (error_msg, *) trim(error_header), ' The target array with i-dimension size ',&
2228  & (1+idim(4)-idim(1)), ' is too small to match the data of size ',&
2229  & (2*halo + 1 + var_in%iec - var_in%isc)
2230  call mpp_error(fatal, trim(error_msg))
2231  endif
2232 
2233  i_off = (1-idim(1)) + (idim(2)-var_in%isc)
2234  else
2235  if (size(array_out,1) < 2*halo + 1 + var_in%iec - var_in%isc) then
2236  write (error_msg, *) trim(error_header), ' The target array with i-dimension size ',&
2237  & size(array_out,1), ' does not match the data of size ',&
2238  & (2*halo + 1 + var_in%iec - var_in%isc)
2239  call mpp_error(fatal, trim(error_msg))
2240  endif
2241  i_off = 1 - (var_in%isc-halo)
2242  endif
2243 
2244  ! Do error checking on the j-dimension and determine the array offsets.
2245  if (present(jdim)) then
2246  if ((jdim(1) > jdim(2)) .or. (jdim(3) > jdim(4))) then
2247  write (error_msg, *) trim(error_header), ' Disordered j-dimension index bound list ', jdim
2248  call mpp_error(fatal, trim(error_msg))
2249  endif
2250  if (size(array_out,2) /= (1+jdim(4)-jdim(1))) then
2251  write (error_msg, *) trim(error_header), ' The declared j-dimension size of ',&
2252  & (1+jdim(4)-jdim(1)), ' does not match the actual size of ', size(array_out,2)
2253  call mpp_error(fatal, trim(error_msg))
2254  endif
2255  if ((var_in%jec-var_in%jsc) /= (jdim(3)-jdim(2)))&
2256  & call mpp_error(fatal, trim(error_header)//" There is an j-direction computational domain size mismatch.")
2257  if ((jdim(2)-jdim(1) < halo) .or. (jdim(4)-jdim(3) < halo))&
2258  & call mpp_error(fatal, trim(error_header)//" Excessive j-direction halo size for the output array.")
2259  if (size(array_out,2) < 2*halo + 1 + var_in%jec - var_in%jsc) then
2260  write (error_msg, *) trim(error_header), ' The target array with j-dimension size ',&
2261  & (1+jdim(4)-jdim(1)), ' is too small to match the data of size ',&
2262  & (2*halo + 1 + var_in%jec - var_in%jsc)
2263  call mpp_error(fatal, trim(error_msg))
2264  endif
2265 
2266  j_off = (1-jdim(1)) + (jdim(2)-var_in%jsc)
2267  else
2268  if (size(array_out,2) < 2*halo + 1 + var_in%jec - var_in%jsc) then
2269  write (error_msg, *) trim(error_header), ' The target array with j-dimension size ',&
2270  & size(array_out,2), ' does not match the data of size ',&
2271  & (2*halo + 1 + var_in%jec - var_in%jsc)
2272  call mpp_error(fatal, trim(error_msg))
2273  endif
2274  j_off = 1 - (var_in%jsc-halo)
2275  endif
2276 
2277  do j=var_in%jsc-halo,var_in%jec+halo
2278  do i=var_in%isc-halo,var_in%iec+halo
2279  array_out(i+i_off,j+j_off) = scale * var_in%bc(bc_index)%field(field_index)%values(i,j)
2280  enddo
2281  enddo
2282  end subroutine ct_extract_data_2d
2283 
2284  !! Extract a single k-level of a 3d field from a coupler_3d_bc_type
2285  !!
2286  !! Extract a single k-level of a 3-d field from a coupler_3d_bc_type into a two-dimensional array.
2287  !!
2288  !! \throw FATAL, "bc_index is present and exceeds var_in%num_bcs."
2289  !! \throw FATAL, "field_index exceeds num_fields for var_in%bc(bc_incdx)%name"
2290  !! \throw FATAL, "Excessive i-direction halo size for the input structure."
2291  !! \throw FATAL, "Excessive j-direction halo size for the input structure."
2292  !! \throw FATAL, "Disordered i-dimension index bound list"
2293  !! \throw FATAL, "Disordered j-dimension index bound list"
2294  !! \throw FATAL, "The declared i-dimension size of 'n' does not match the actual size of 'a'"
2295  !! \throw FATAL, "The declared j-dimension size of 'n' does not match the actual size of 'a'"
2296  !! \throw FATAL, "There is an i-direction computational domain size mismatch."
2297  !! \throw FATAL, "There is an j-direction computational domain size mismatch."
2298  !! \throw FATAL, "The target array with i-dimension size 'n' is too small to match the data of size 'd'"
2299  !! \throw FATAL, "The target array with j-dimension size 'n' is too small to match the data of size 'd'"
2300  !! \throw FATAL, "The extracted k-index of 'k' is outside of the valid range of 'ks' to 'ke'"
2301  subroutine ct_extract_data_3d_2d(var_in, bc_index, field_index, k_in, array_out,&
2302  & scale_factor, halo_size, idim, jdim)
2303  type(coupler_3d_bc_type), intent(in) :: var_in !< BC_type structure with the data to extract
2304  integer, intent(in) :: bc_index !< The index of the boundary condition
2305  !! that is being copied
2306  integer, intent(in) :: field_index !< The index of the field in the
2307  !! boundary condition that is being copied
2308  integer, intent(in) :: k_in !< The k-index to extract
2309  real, dimension(1:,1:), intent(out) :: array_out !< The recipient array for the field; its size
2310  !! must match the size of the data being copied
2311  !! unless idim and jdim are supplied.
2312  real, optional, intent(in) :: scale_factor !< A scaling factor for the data that is being added
2313  integer, optional, intent(in) :: halo_size !< The extent of the halo to copy; 0 by default
2314  integer, dimension(4), optional, intent(in) :: idim !< The data and computational domain extents of
2315  !! the first dimension of the output array
2316  !! in a non-decreasing list
2317  integer, dimension(4), optional, intent(in) :: jdim !< The data and computational domain extents of
2318  !! the second dimension of the output array
2319  !! in a non-decreasing list
2320  character(len=*), parameter :: error_header =&
2321  & '==>Error from coupler_types_mod (CT_extract_data_3d_2d):'
2322  character(len=400) :: error_msg
2323 
2324  real :: scale
2325  integer :: i, j, k, halo, i_off, j_off
2326 
2327  if (bc_index <= 0) then
2328  array_out(:,:) = 0.0
2329  return
2330  endif
2331 
2332  halo = 0
2333  if (present(halo_size)) halo = halo_size
2334  scale = 1.0
2335  if (present(scale_factor)) scale = scale_factor
2336 
2337  if ((var_in%isc-var_in%isd < halo) .or. (var_in%ied-var_in%iec < halo))&
2338  & call mpp_error(fatal, trim(error_header)//" Excessive i-direction halo size for the input structure.")
2339  if ((var_in%jsc-var_in%jsd < halo) .or. (var_in%jed-var_in%jec < halo))&
2340  & call mpp_error(fatal, trim(error_header)//" Excessive j-direction halo size for the input structure.")
2341 
2342  if (bc_index > var_in%num_bcs)&
2343  & call mpp_error(fatal, trim(error_header)//" bc_index exceeds var_in%num_bcs.")
2344  if (field_index > var_in%bc(bc_index)%num_fields)&
2345  & call mpp_error(fatal, trim(error_header)//" field_index exceeds num_fields for" //&
2346  & trim(var_in%bc(bc_index)%name) )
2347 
2348  ! Do error checking on the i-dimension and determine the array offsets.
2349  if (present(idim)) then
2350  if ((idim(1) > idim(2)) .or. (idim(3) > idim(4))) then
2351  write (error_msg, *) trim(error_header), ' Disordered i-dimension index bound list ', idim
2352  call mpp_error(fatal, trim(error_msg))
2353  endif
2354  if (size(array_out,1) /= (1+idim(4)-idim(1))) then
2355  write (error_msg, *) trim(error_header), ' The declared i-dimension size of ',&
2356  & (1+idim(4)-idim(1)), ' does not match the actual size of ', size(array_out,1)
2357  call mpp_error(fatal, trim(error_msg))
2358  endif
2359  if ((var_in%iec-var_in%isc) /= (idim(3)-idim(2)))&
2360  & call mpp_error(fatal, trim(error_header)//" There is an i-direction computational domain size mismatch.")
2361  if ((idim(2)-idim(1) < halo) .or. (idim(4)-idim(3) < halo))&
2362  & call mpp_error(fatal, trim(error_header)//" Excessive i-direction halo size for the output array.")
2363  if (size(array_out,1) < 2*halo + 1 + var_in%iec - var_in%isc) then
2364  write (error_msg, *) trim(error_header), ' The target array with i-dimension size ',&
2365  & (1+idim(4)-idim(1)), ' is too small to match the data of size ',&
2366  & (2*halo + 1 + var_in%iec - var_in%isc)
2367  call mpp_error(fatal, trim(error_msg))
2368  endif
2369 
2370  i_off = (1-idim(1)) + (idim(2)-var_in%isc)
2371  else
2372  if (size(array_out,1) < 2*halo + 1 + var_in%iec - var_in%isc) then
2373  write (error_msg, *) trim(error_header), ' The target array with i-dimension size ',&
2374  & size(array_out,1), ' does not match the data of size ',&
2375  & (2*halo + 1 + var_in%iec - var_in%isc)
2376  call mpp_error(fatal, trim(error_msg))
2377  endif
2378  i_off = 1 - (var_in%isc-halo)
2379  endif
2380 
2381  ! Do error checking on the j-dimension and determine the array offsets.
2382  if (present(jdim)) then
2383  if ((jdim(1) > jdim(2)) .or. (jdim(3) > jdim(4))) then
2384  write (error_msg, *) trim(error_header), ' Disordered j-dimension index bound list ', jdim
2385  call mpp_error(fatal, trim(error_msg))
2386  endif
2387  if (size(array_out,2) /= (1+jdim(4)-jdim(1))) then
2388  write (error_msg, *) trim(error_header), ' The declared j-dimension size of ',&
2389  & (1+jdim(4)-jdim(1)), ' does not match the actual size of ', size(array_out,2)
2390  call mpp_error(fatal, trim(error_msg))
2391  endif
2392  if ((var_in%jec-var_in%jsc) /= (jdim(3)-jdim(2)))&
2393  & call mpp_error(fatal, trim(error_header)//" There is an j-direction computational domain size mismatch.")
2394  if ((jdim(2)-jdim(1) < halo) .or. (jdim(4)-jdim(3) < halo))&
2395  & call mpp_error(fatal, trim(error_header)//" Excessive j-direction halo size for the output array.")
2396  if (size(array_out,2) < 2*halo + 1 + var_in%jec - var_in%jsc) then
2397  write (error_msg, *) trim(error_header), ' The target array with j-dimension size ',&
2398  & (1+jdim(4)-jdim(1)), ' is too small to match the data of size ',&
2399  & (2*halo + 1 + var_in%jec - var_in%jsc)
2400  call mpp_error(fatal, trim(error_msg))
2401  endif
2402 
2403  j_off = (1-jdim(1)) + (jdim(2)-var_in%jsc)
2404  else
2405  if (size(array_out,2) < 2*halo + 1 + var_in%jec - var_in%jsc) then
2406  write (error_msg, *) trim(error_header), ' The target array with j-dimension size ',&
2407  & size(array_out,2), ' does not match the data of size ',&
2408  & (2*halo + 1 + var_in%jec - var_in%jsc)
2409  call mpp_error(fatal, trim(error_msg))
2410  endif
2411  j_off = 1 - (var_in%jsc-halo)
2412  endif
2413 
2414  if ((k_in > var_in%ke) .or. (k_in < var_in%ks)) then
2415  write (error_msg, *) trim(error_header), ' The extracted k-index of ', k_in,&
2416  & ' is outside of the valid range of ', var_in%ks, ' to ', var_in%ke
2417  call mpp_error(fatal, trim(error_msg))
2418  endif
2419 
2420  do j=var_in%jsc-halo,var_in%jec+halo
2421  do i=var_in%isc-halo,var_in%iec+halo
2422  array_out(i+i_off,j+j_off) = scale * var_in%bc(bc_index)%field(field_index)%values(i,j,k_in)
2423  enddo
2424  enddo
2425  end subroutine ct_extract_data_3d_2d
2426 
2427  !> Extract single 3d field from a coupler_3d_bc_type
2428  !!
2429  !! Extract a single 3-d field from a coupler_3d_bc_type into a three-dimensional array.
2430  !!
2431  !! \throw FATAL, "bc_index is present and exceeds var_in%num_bcs."
2432  !! \throw FATAL, "field_index exceeds num_fields for var_in%bc(bc_incdx)%name"
2433  !! \throw FATAL, "Excessive i-direction halo size for the input structure."
2434  !! \throw FATAL, "Excessive j-direction halo size for the input structure."
2435  !! \throw FATAL, "Disordered i-dimension index bound list"
2436  !! \throw FATAL, "Disordered j-dimension index bound list"
2437  !! \throw FATAL, "The declared i-dimension size of 'n' does not match the actual size of 'a'"
2438  !! \throw FATAL, "The declared j-dimension size of 'n' does not match the actual size of 'a'"
2439  !! \throw FATAL, "There is an i-direction computational domain size mismatch."
2440  !! \throw FATAL, "There is an j-direction computational domain size mismatch."
2441  !! \throw FATAL, "The target array with i-dimension size 'n' is too small to match the data of size 'd'"
2442  !! \throw FATAL, "The target array with j-dimension size 'n' is too small to match the data of size 'd'"
2443  !! \throw FATAL, "The target array with k-dimension size 'n' does not match the data of size 'd'"
2444  subroutine ct_extract_data_3d(var_in, bc_index, field_index, array_out,&
2445  & scale_factor, halo_size, idim, jdim)
2446  type(coupler_3d_bc_type), intent(in) :: var_in !< BC_type structure with the data to extract
2447  integer, intent(in) :: bc_index !< The index of the boundary condition
2448  !! that is being copied
2449  integer, intent(in) :: field_index !< The index of the field in the
2450  !! boundary condition that is being copied
2451  real, dimension(1:,1:,1:), intent(out) :: array_out !< The recipient array for the field; its size
2452  !! must match the size of the data being copied
2453  !! unless idim and jdim are supplied.
2454  real, optional, intent(in) :: scale_factor !< A scaling factor for the data that is being added
2455  integer, optional, intent(in) :: halo_size !< The extent of the halo to copy; 0 by default
2456  integer, dimension(4), optional, intent(in) :: idim !< The data and computational domain extents of
2457  !! the first dimension of the output array
2458  !! in a non-decreasing list
2459  integer, dimension(4), optional, intent(in) :: jdim !< The data and computational domain extents of
2460  !! the second dimension of the output array
2461  !! in a non-decreasing list
2462 
2463  character(len=*), parameter :: error_header =&
2464  & '==>Error from coupler_types_mod (CT_extract_data_3d):'
2465  character(len=400) :: error_msg
2466 
2467  real :: scale
2468  integer :: i, j, k, halo, i_off, j_off, k_off
2469 
2470  if (bc_index <= 0) then
2471  array_out(:,:,:) = 0.0
2472  return
2473  endif
2474 
2475  halo = 0
2476  if (present(halo_size)) halo = halo_size
2477  scale = 1.0
2478  if (present(scale_factor)) scale = scale_factor
2479 
2480  if ((var_in%isc-var_in%isd < halo) .or. (var_in%ied-var_in%iec < halo))&
2481  & call mpp_error(fatal, trim(error_header)//" Excessive i-direction halo size for the input structure.")
2482  if ((var_in%jsc-var_in%jsd < halo) .or. (var_in%jed-var_in%jec < halo))&
2483  & call mpp_error(fatal, trim(error_header)//" Excessive j-direction halo size for the input structure.")
2484 
2485  if (bc_index > var_in%num_bcs)&
2486  & call mpp_error(fatal, trim(error_header)//" bc_index exceeds var_in%num_bcs.")
2487  if (field_index > var_in%bc(bc_index)%num_fields)&
2488  & call mpp_error(fatal, trim(error_header)//" field_index exceeds num_fields for" //&
2489  & trim(var_in%bc(bc_index)%name) )
2490 
2491  ! Do error checking on the i-dimension and determine the array offsets.
2492  if (present(idim)) then
2493  if ((idim(1) > idim(2)) .or. (idim(3) > idim(4))) then
2494  write (error_msg, *) trim(error_header), ' Disordered i-dimension index bound list ', idim
2495  call mpp_error(fatal, trim(error_msg))
2496  endif
2497  if (size(array_out,1) /= (1+idim(4)-idim(1))) then
2498  write (error_msg, *) trim(error_header), ' The declared i-dimension size of ',&
2499  & (1+idim(4)-idim(1)), ' does not match the actual size of ', size(array_out,1)
2500  call mpp_error(fatal, trim(error_msg))
2501  endif
2502  if ((var_in%iec-var_in%isc) /= (idim(3)-idim(2)))&
2503  & call mpp_error(fatal, trim(error_header)//" There is an i-direction computational domain size mismatch.")
2504  if ((idim(2)-idim(1) < halo) .or. (idim(4)-idim(3) < halo))&
2505  & call mpp_error(fatal, trim(error_header)//" Excessive i-direction halo size for the output array.")
2506  if (size(array_out,1) < 2*halo + 1 + var_in%iec - var_in%isc) then
2507  write (error_msg, *) trim(error_header), ' The target array with i-dimension size ',&
2508  & (1+idim(4)-idim(1)), ' is too small to match the data of size ',&
2509  & (2*halo + 1 + var_in%iec - var_in%isc)
2510  call mpp_error(fatal, trim(error_msg))
2511  endif
2512 
2513  i_off = (1-idim(1)) + (idim(2)-var_in%isc)
2514  else
2515  if (size(array_out,1) < 2*halo + 1 + var_in%iec - var_in%isc) then
2516  write (error_msg, *) trim(error_header), ' The target array with i-dimension size ',&
2517  & size(array_out,1), ' does not match the data of size ',&
2518  & (2*halo + 1 + var_in%iec - var_in%isc)
2519  call mpp_error(fatal, trim(error_msg))
2520  endif
2521  i_off = 1 - (var_in%isc-halo)
2522  endif
2523 
2524  ! Do error checking on the j-dimension and determine the array offsets.
2525  if (present(jdim)) then
2526  if ((jdim(1) > jdim(2)) .or. (jdim(3) > jdim(4))) then
2527  write (error_msg, *) trim(error_header), ' Disordered j-dimension index bound list ', jdim
2528  call mpp_error(fatal, trim(error_msg))
2529  endif
2530  if (size(array_out,2) /= (1+jdim(4)-jdim(1))) then
2531  write (error_msg, *) trim(error_header), ' The declared j-dimension size of ',&
2532  & (1+jdim(4)-jdim(1)), ' does not match the actual size of ', size(array_out,2)
2533  call mpp_error(fatal, trim(error_msg))
2534  endif
2535  if ((var_in%jec-var_in%jsc) /= (jdim(3)-jdim(2)))&
2536  & call mpp_error(fatal, trim(error_header)//" There is an j-direction computational domain size mismatch.")
2537  if ((jdim(2)-jdim(1) < halo) .or. (jdim(4)-jdim(3) < halo))&
2538  & call mpp_error(fatal, trim(error_header)//" Excessive j-direction halo size for the output array.")
2539  if (size(array_out,2) < 2*halo + 1 + var_in%jec - var_in%jsc) then
2540  write (error_msg, *) trim(error_header), ' The target array with j-dimension size ',&
2541  & (1+jdim(4)-jdim(1)), ' is too small to match the data of size ',&
2542  & (2*halo + 1 + var_in%jec - var_in%jsc)
2543  call mpp_error(fatal, trim(error_msg))
2544  endif
2545 
2546  j_off = (1-jdim(1)) + (jdim(2)-var_in%jsc)
2547  else
2548  if (size(array_out,2) < 2*halo + 1 + var_in%jec - var_in%jsc) then
2549  write (error_msg, *) trim(error_header), ' The target array with j-dimension size ',&
2550  & size(array_out,2), ' does not match the data of size ',&
2551  & (2*halo + 1 + var_in%jec - var_in%jsc)
2552  call mpp_error(fatal, trim(error_msg))
2553  endif
2554  j_off = 1 - (var_in%jsc-halo)
2555  endif
2556 
2557  if (size(array_out,3) /= 1 + var_in%ke - var_in%ks) then
2558  write (error_msg, *) trim(error_header), ' The target array with k-dimension size ',&
2559  & size(array_out,3), ' does not match the data of size ',&
2560  & (1 + var_in%ke - var_in%ks)
2561  call mpp_error(fatal, trim(error_msg))
2562  endif
2563  k_off = 1 - var_in%ks
2564 
2565  do k=var_in%ks,var_in%ke
2566  do j=var_in%jsc-halo,var_in%jec+halo
2567  do i=var_in%isc-halo,var_in%iec+halo
2568  array_out(i+i_off,j+j_off,k+k_off) = scale * var_in%bc(bc_index)%field(field_index)%values(i,j,k)
2569  enddo
2570  enddo
2571  enddo
2572  end subroutine ct_extract_data_3d
2573 
2574  !> Set single 2d field in coupler_3d_bc_type
2575  !!
2576  !! Set a single 2-d field in a coupler_3d_bc_type from a two-dimensional array.
2577  !!
2578  !! \throw FATAL, "bc_index is present and exceeds var_in%num_bcs."
2579  !! \throw FATAL, "field_index exceeds num_fields for var_in%bc(bc_incdx)%name"
2580  !! \throw FATAL, "Excessive i-direction halo size for the input structure."
2581  !! \throw FATAL, "Excessive j-direction halo size for the input structure."
2582  !! \throw FATAL, "Disordered i-dimension index bound list"
2583  !! \throw FATAL, "Disordered j-dimension index bound list"
2584  !! \throw FATAL, "The declared i-dimension size of 'n' does not match the actual size of 'a'"
2585  !! \throw FATAL, "The declared j-dimension size of 'n' does not match the actual size of 'a'"
2586  !! \throw FATAL, "There is an i-direction computational domain size mismatch."
2587  !! \throw FATAL, "There is an j-direction computational domain size mismatch."
2588  !! \throw FATAL, "The target array with i-dimension size 'n' is too small to match the data of size 'd'"
2589  !! \throw FATAL, "The target array with j-dimension size 'n' is too small to match the data of size 'd'"
2590  subroutine ct_set_data_2d(array_in, bc_index, field_index, var,&
2591  & scale_factor, halo_size, idim, jdim)
2592  real, dimension(1:,1:), intent(in) :: array_in !< The source array for the field; its size
2593  !! must match the size of the data being copied
2594  !! unless idim and jdim are supplied.
2595  integer, intent(in) :: bc_index !< The index of the boundary condition
2596  !! that is being copied
2597  integer, intent(in) :: field_index !< The index of the field in the
2598  !! boundary condition that is being copied
2599  type(coupler_2d_bc_type), intent(inout) :: var !< BC_type structure with the data to set
2600  real, optional, intent(in) :: scale_factor !< A scaling factor for the data that is being added
2601  integer, optional, intent(in) :: halo_size !< The extent of the halo to copy; 0 by default
2602  integer, dimension(4), optional, intent(in) :: idim !< The data and computational domain extents of
2603  !! the first dimension of the output array
2604  !! in a non-decreasing list
2605  integer, dimension(4), optional, intent(in) :: jdim !< The data and computational domain extents of
2606  !! the second dimension of the output array
2607  !! in a non-decreasing list
2608  character(len=*), parameter :: error_header =&
2609  & '==>Error from coupler_types_mod (CT_set_data_2d):'
2610  character(len=400) :: error_msg
2611 
2612  real :: scale
2613  integer :: i, j, halo, i_off, j_off
2614 
2615  if (bc_index <= 0) return
2616 
2617  halo = 0
2618  if (present(halo_size)) halo = halo_size
2619  scale = 1.0
2620  if (present(scale_factor)) scale = scale_factor
2621 
2622  if ((var%isc-var%isd < halo) .or. (var%ied-var%iec < halo))&
2623  & call mpp_error(fatal, trim(error_header)//" Excessive i-direction halo size for the input structure.")
2624  if ((var%jsc-var%jsd < halo) .or. (var%jed-var%jec < halo))&
2625  & call mpp_error(fatal, trim(error_header)//" Excessive j-direction halo size for the input structure.")
2626 
2627  if (bc_index > var%num_bcs) &
2628  call mpp_error(fatal, trim(error_header)//" bc_index exceeds var%num_bcs.")
2629  if (field_index > var%bc(bc_index)%num_fields)&
2630  & call mpp_error(fatal, trim(error_header)//" field_index exceeds num_fields for" //&
2631  & trim(var%bc(bc_index)%name) )
2632 
2633  ! Do error checking on the i-dimension and determine the array offsets.
2634  if (present(idim)) then
2635  if ((idim(1) > idim(2)) .or. (idim(3) > idim(4))) then
2636  write (error_msg, *) trim(error_header), ' Disordered i-dimension index bound list ', idim
2637  call mpp_error(fatal, trim(error_msg))
2638  endif
2639  if (size(array_in,1) /= (1+idim(4)-idim(1))) then
2640  write (error_msg, *) trim(error_header), ' The declared i-dimension size of ',&
2641  & (1+idim(4)-idim(1)), ' does not match the actual size of ', size(array_in,1)
2642  call mpp_error(fatal, trim(error_msg))
2643  endif
2644  if ((var%iec-var%isc) /= (idim(3)-idim(2)))&
2645  & call mpp_error(fatal, trim(error_header)//" There is an i-direction computational domain size mismatch.")
2646  if ((idim(2)-idim(1) < halo) .or. (idim(4)-idim(3) < halo))&
2647  & call mpp_error(fatal, trim(error_header)//" Excessive i-direction halo size for the output array.")
2648  if (size(array_in,1) < 2*halo + 1 + var%iec - var%isc) then
2649  write (error_msg, *) trim(error_header), ' The target array with i-dimension size ',&
2650  & (1+idim(4)-idim(1)), ' is too small to match the data of size ',&
2651  & (2*halo + 1 + var%iec - var%isc)
2652  call mpp_error(fatal, trim(error_msg))
2653  endif
2654 
2655  i_off = (1-idim(1)) + (idim(2)-var%isc)
2656  else
2657  if (size(array_in,1) < 2*halo + 1 + var%iec - var%isc) then
2658  write (error_msg, *) trim(error_header), ' The target array with i-dimension size ',&
2659  & size(array_in,1), ' does not match the data of size ',&
2660  & (2*halo + 1 + var%iec - var%isc)
2661  call mpp_error(fatal, trim(error_msg))
2662  endif
2663  i_off = 1 - (var%isc-halo)
2664  endif
2665 
2666  ! Do error checking on the j-dimension and determine the array offsets.
2667  if (present(jdim)) then
2668  if ((jdim(1) > jdim(2)) .or. (jdim(3) > jdim(4))) then
2669  write (error_msg, *) trim(error_header), ' Disordered j-dimension index bound list ', jdim
2670  call mpp_error(fatal, trim(error_msg))
2671  endif
2672  if (size(array_in,2) /= (1+jdim(4)-jdim(1))) then
2673  write (error_msg, *) trim(error_header), ' The declared j-dimension size of ',&
2674  & (1+jdim(4)-jdim(1)), ' does not match the actual size of ', size(array_in,2)
2675  call mpp_error(fatal, trim(error_msg))
2676  endif
2677  if ((var%jec-var%jsc) /= (jdim(3)-jdim(2)))&
2678  & call mpp_error(fatal, trim(error_header)//" There is an j-direction computational domain size mismatch.")
2679  if ((jdim(2)-jdim(1) < halo) .or. (jdim(4)-jdim(3) < halo))&
2680  & call mpp_error(fatal, trim(error_header)//" Excessive j-direction halo size for the output array.")
2681  if (size(array_in,2) < 2*halo + 1 + var%jec - var%jsc) then
2682  write (error_msg, *) trim(error_header), ' The target array with j-dimension size ',&
2683  & (1+jdim(4)-jdim(1)), ' is too small to match the data of size ',&
2684  & (2*halo + 1 + var%jec - var%jsc)
2685  call mpp_error(fatal, trim(error_msg))
2686  endif
2687 
2688  j_off = (1-jdim(1)) + (jdim(2)-var%jsc)
2689  else
2690  if (size(array_in,2) < 2*halo + 1 + var%jec - var%jsc) then
2691  write (error_msg, *) trim(error_header), ' The target array with j-dimension size ',&
2692  & size(array_in,2), ' does not match the data of size ',&
2693  & (2*halo + 1 + var%jec - var%jsc)
2694  call mpp_error(fatal, trim(error_msg))
2695  endif
2696  j_off = 1 - (var%jsc-halo)
2697  endif
2698 
2699  do j=var%jsc-halo,var%jec+halo
2700  do i=var%isc-halo,var%iec+halo
2701  var%bc(bc_index)%field(field_index)%values(i,j) = scale * array_in(i+i_off,j+j_off)
2702  enddo
2703  enddo
2704  end subroutine ct_set_data_2d
2705 
2706  !> Set one k-level of a single 3d field in a coupler_3d_bc_type
2707  !!
2708  !! This subroutine sets a one k-level of a single 3-d field in a coupler_3d_bc_type from a
2709  !! two-dimensional array.
2710  !!
2711  !! \throw FATAL, "bc_index is present and exceeds var_in%num_bcs."
2712  !! \throw FATAL, "field_index exceeds num_fields for var_in%bc(bc_incdx)%name"
2713  !! \throw FATAL, "Excessive i-direction halo size for the input structure."
2714  !! \throw FATAL, "Excessive j-direction halo size for the input structure."
2715  !! \throw FATAL, "Disordered i-dimension index bound list"
2716  !! \throw FATAL, "Disordered j-dimension index bound list"
2717  !! \throw FATAL, "The declared i-dimension size of 'n' does not match the actual size of 'a'"
2718  !! \throw FATAL, "The declared j-dimension size of 'n' does not match the actual size of 'a'"
2719  !! \throw FATAL, "There is an i-direction computational domain size mismatch."
2720  !! \throw FATAL, "There is an j-direction computational domain size mismatch."
2721  !! \throw FATAL, "The target array with i-dimension size 'n' is too small to match the data of size 'd'"
2722  !! \throw FATAL, "The target array with j-dimension size 'n' is too small to match the data of size 'd'"
2723  !! \throw FATAL, "The k-index of 'k' is outside of the valid range of 'ks' to 'ke'"
2724  subroutine ct_set_data_2d_3d(array_in, bc_index, field_index, k_out, var,&
2725  & scale_factor, halo_size, idim, jdim)
2726  real, dimension(1:,1:), intent(in) :: array_in !< The source array for the field; its size
2727  !! must match the size of the data being copied
2728  !! unless idim and jdim are supplied.
2729  integer, intent(in) :: bc_index !< The index of the boundary condition
2730  !! that is being copied
2731  integer, intent(in) :: field_index !< The index of the field in the
2732  !! boundary condition that is being copied
2733  integer, intent(in) :: k_out !< The k-index to set
2734  type(coupler_3d_bc_type), intent(inout) :: var !< BC_type structure with the data to be set
2735  real, optional, intent(in) :: scale_factor !< A scaling factor for the data that is being added
2736  integer, optional, intent(in) :: halo_size !< The extent of the halo to copy; 0 by default
2737  integer, dimension(4), optional, intent(in) :: idim !< The data and computational domain extents of
2738  !! the first dimension of the output array
2739  !! in a non-decreasing list
2740  integer, dimension(4), optional, intent(in) :: jdim !< The data and computational domain extents of
2741  !! the second dimension of the output array
2742  !! in a non-decreasing list
2743 
2744  character(len=*), parameter :: error_header =&
2745  & '==>Error from coupler_types_mod (CT_set_data_3d_2d):'
2746  character(len=400) :: error_msg
2747 
2748  real :: scale
2749  integer :: i, j, halo, i_off, j_off
2750 
2751  if (bc_index <= 0) return
2752 
2753  halo = 0
2754  if (present(halo_size)) halo = halo_size
2755  scale = 1.0
2756  if (present(scale_factor)) scale = scale_factor
2757 
2758  if ((var%isc-var%isd < halo) .or. (var%ied-var%iec < halo))&
2759  & call mpp_error(fatal, trim(error_header)//" Excessive i-direction halo size for the input structure.")
2760  if ((var%jsc-var%jsd < halo) .or. (var%jed-var%jec < halo))&
2761  & call mpp_error(fatal, trim(error_header)//" Excessive j-direction halo size for the input structure.")
2762 
2763  if (bc_index > var%num_bcs)&
2764  & call mpp_error(fatal, trim(error_header)//" bc_index exceeds var%num_bcs.")
2765  if (field_index > var%bc(bc_index)%num_fields)&
2766  & call mpp_error(fatal, trim(error_header)//" field_index exceeds num_fields for" //&
2767  & trim(var%bc(bc_index)%name) )
2768 
2769  ! Do error checking on the i-dimension and determine the array offsets.
2770  if (present(idim)) then
2771  if ((idim(1) > idim(2)) .or. (idim(3) > idim(4))) then
2772  write (error_msg, *) trim(error_header), ' Disordered i-dimension index bound list ', idim
2773  call mpp_error(fatal, trim(error_msg))
2774  endif
2775  if (size(array_in,1) /= (1+idim(4)-idim(1))) then
2776  write (error_msg, *) trim(error_header), ' The declared i-dimension size of ',&
2777  & (1+idim(4)-idim(1)), ' does not match the actual size of ', size(array_in,1)
2778  call mpp_error(fatal, trim(error_msg))
2779  endif
2780  if ((var%iec-var%isc) /= (idim(3)-idim(2)))&
2781  & call mpp_error(fatal, trim(error_header)//" There is an i-direction computational domain size mismatch.")
2782  if ((idim(2)-idim(1) < halo) .or. (idim(4)-idim(3) < halo))&
2783  & call mpp_error(fatal, trim(error_header)//" Excessive i-direction halo size for the output array.")
2784  if (size(array_in,1) < 2*halo + 1 + var%iec - var%isc) then
2785  write (error_msg, *) trim(error_header), ' The target array with i-dimension size ',&
2786  & (1+idim(4)-idim(1)), ' is too small to match the data of size ',&
2787  & (2*halo + 1 + var%iec - var%isc)
2788  call mpp_error(fatal, trim(error_msg))
2789  endif
2790 
2791  i_off = (1-idim(1)) + (idim(2)-var%isc)
2792  else
2793  if (size(array_in,1) < 2*halo + 1 + var%iec - var%isc) then
2794  write (error_msg, *) trim(error_header), ' The target array with i-dimension size ',&
2795  & size(array_in,1), ' does not match the data of size ',&
2796  & (2*halo + 1 + var%iec - var%isc)
2797  call mpp_error(fatal, trim(error_msg))
2798  endif
2799  i_off = 1 - (var%isc-halo)
2800  endif
2801 
2802  ! Do error checking on the j-dimension and determine the array offsets.
2803  if (present(jdim)) then
2804  if ((jdim(1) > jdim(2)) .or. (jdim(3) > jdim(4))) then
2805  write (error_msg, *) trim(error_header), ' Disordered j-dimension index bound list ', jdim
2806  call mpp_error(fatal, trim(error_msg))
2807  endif
2808  if (size(array_in,2) /= (1+jdim(4)-jdim(1))) then
2809  write (error_msg, *) trim(error_header), ' The declared j-dimension size of ',&
2810  & (1+jdim(4)-jdim(1)), ' does not match the actual size of ', size(array_in,2)
2811  call mpp_error(fatal, trim(error_msg))
2812  endif
2813  if ((var%jec-var%jsc) /= (jdim(3)-jdim(2)))&
2814  & call mpp_error(fatal, trim(error_header)//" There is an j-direction computational domain size mismatch.")
2815  if ((jdim(2)-jdim(1) < halo) .or. (jdim(4)-jdim(3) < halo))&
2816  & call mpp_error(fatal, trim(error_header)//" Excessive j-direction halo size for the output array.")
2817  if (size(array_in,2) < 2*halo + 1 + var%jec - var%jsc) then
2818  write (error_msg, *) trim(error_header), ' The target array with j-dimension size ',&
2819  & (1+jdim(4)-jdim(1)), ' is too small to match the data of size ',&
2820  & (2*halo + 1 + var%jec - var%jsc)
2821  call mpp_error(fatal, trim(error_msg))
2822  endif
2823 
2824  j_off = (1-jdim(1)) + (jdim(2)-var%jsc)
2825  else
2826  if (size(array_in,2) < 2*halo + 1 + var%jec - var%jsc) then
2827  write (error_msg, *) trim(error_header), ' The target array with j-dimension size ',&
2828  & size(array_in,2), ' does not match the data of size ',&
2829  & (2*halo + 1 + var%jec - var%jsc)
2830  call mpp_error(fatal, trim(error_msg))
2831  endif
2832  j_off = 1 - (var%jsc-halo)
2833  endif
2834 
2835  if ((k_out > var%ke) .or. (k_out < var%ks)) then
2836  write (error_msg, *) trim(error_header), ' The k-index of ', k_out,&
2837  & ' is outside of the valid range of ', var%ks, ' to ', var%ke
2838  call mpp_error(fatal, trim(error_msg))
2839  endif
2840 
2841  do j=var%jsc-halo,var%jec+halo
2842  do i=var%isc-halo,var%iec+halo
2843  var%bc(bc_index)%field(field_index)%values(i,j,k_out) = scale * array_in(i+i_off,j+j_off)
2844  enddo
2845  enddo
2846  end subroutine ct_set_data_2d_3d
2847 
2848  !> Set a single 3d field in a coupler_3d_bc_type
2849  !!
2850  !! This subroutine sets a single 3-d field in a coupler_3d_bc_type from a three-dimensional array.
2851  !!
2852  !! \throw FATAL, "bc_index is present and exceeds var_in%num_bcs."
2853  !! \throw FATAL, "field_index exceeds num_fields for var_in%bc(bc_incdx)%name"
2854  !! \throw FATAL, "Excessive i-direction halo size for the input structure."
2855  !! \throw FATAL, "Excessive j-direction halo size for the input structure."
2856  !! \throw FATAL, "Disordered i-dimension index bound list"
2857  !! \throw FATAL, "Disordered j-dimension index bound list"
2858  !! \throw FATAL, "The declared i-dimension size of 'n' does not match the actual size of 'a'"
2859  !! \throw FATAL, "The declared j-dimension size of 'n' does not match the actual size of 'a'"
2860  !! \throw FATAL, "There is an i-direction computational domain size mismatch."
2861  !! \throw FATAL, "There is an j-direction computational domain size mismatch."
2862  !! \throw FATAL, "The target array with i-dimension size 'n' is too small to match the data of size 'd'"
2863  !! \throw FATAL, "The target array with j-dimension size 'n' is too small to match the data of size 'd'"
2864  !! \throw FATAL, "The target array with K-dimension size 'n' is too small to match the data of size 'd'"
2865  subroutine ct_set_data_3d(array_in, bc_index, field_index, var,&
2866  & scale_factor, halo_size, idim, jdim)
2867  real, dimension(1:,1:,1:), intent(in) :: array_in !< The source array for the field; its size
2868  !! must match the size of the data being copied
2869  !! unless idim and jdim are supplied.
2870  integer, intent(in) :: bc_index !< The index of the boundary condition
2871  !! that is being copied
2872  integer, intent(in) :: field_index !< The index of the field in the
2873  !! boundary condition that is being copied
2874  type(coupler_3d_bc_type), intent(inout) :: var !< BC_type structure with the data to be set
2875  real, optional, intent(in) :: scale_factor !< A scaling factor for the data that is being added
2876  integer, optional, intent(in) :: halo_size !< The extent of the halo to copy; 0 by default
2877  integer, dimension(4), optional, intent(in) :: idim !< The data and computational domain extents of
2878  !! the first dimension of the output array
2879  !! in a non-decreasing list
2880  integer, dimension(4), optional, intent(in) :: jdim !< The data and computational domain extents of
2881  !! the second dimension of the output array
2882  !! in a non-decreasing list
2883 
2884  character(len=*), parameter :: error_header =&
2885  & '==>Error from coupler_types_mod (CT_set_data_3d):'
2886  character(len=400) :: error_msg
2887 
2888  real :: scale
2889  integer :: i, j, k, halo, i_off, j_off, k_off
2890 
2891  if (bc_index <= 0) return
2892 
2893  halo = 0
2894  if (present(halo_size)) halo = halo_size
2895  scale = 1.0
2896  if (present(scale_factor)) scale = scale_factor
2897 
2898  if ((var%isc-var%isd < halo) .or. (var%ied-var%iec < halo))&
2899  & call mpp_error(fatal, trim(error_header)//" Excessive i-direction halo size for the input structure.")
2900  if ((var%jsc-var%jsd < halo) .or. (var%jed-var%jec < halo))&
2901  & call mpp_error(fatal, trim(error_header)//" Excessive j-direction halo size for the input structure.")
2902 
2903  if (bc_index > var%num_bcs)&
2904  & call mpp_error(fatal, trim(error_header)//" bc_index exceeds var%num_bcs.")
2905  if (field_index > var%bc(bc_index)%num_fields)&
2906  & call mpp_error(fatal, trim(error_header)//" field_index exceeds num_fields for" //&
2907  & trim(var%bc(bc_index)%name) )
2908 
2909  ! Do error checking on the i-dimension and determine the array offsets.
2910  if (present(idim)) then
2911  if ((idim(1) > idim(2)) .or. (idim(3) > idim(4))) then
2912  write (error_msg, *) trim(error_header), ' Disordered i-dimension index bound list ', idim
2913  call mpp_error(fatal, trim(error_msg))
2914  endif
2915  if (size(array_in,1) /= (1+idim(4)-idim(1))) then
2916  write (error_msg, *) trim(error_header), ' The declared i-dimension size of ',&
2917  & (1+idim(4)-idim(1)), ' does not match the actual size of ', size(array_in,1)
2918  call mpp_error(fatal, trim(error_msg))
2919  endif
2920  if ((var%iec-var%isc) /= (idim(3)-idim(2)))&
2921  & call mpp_error(fatal, trim(error_header)//" There is an i-direction computational domain size mismatch.")
2922  if ((idim(2)-idim(1) < halo) .or. (idim(4)-idim(3) < halo))&
2923  & call mpp_error(fatal, trim(error_header)//" Excessive i-direction halo size for the output array.")
2924  if (size(array_in,1) < 2*halo + 1 + var%iec - var%isc) then
2925  write (error_msg, *) trim(error_header), ' The target array with i-dimension size ',&
2926  & (1+idim(4)-idim(1)), ' is too small to match the data of size ',&
2927  & (2*halo + 1 + var%iec - var%isc)
2928  call mpp_error(fatal, trim(error_msg))
2929  endif
2930 
2931  i_off = (1-idim(1)) + (idim(2)-var%isc)
2932  else
2933  if (size(array_in,1) < 2*halo + 1 + var%iec - var%isc) then
2934  write (error_msg, *) trim(error_header), ' The target array with i-dimension size ',&
2935  & size(array_in,1), ' does not match the data of size ',&
2936  & (2*halo + 1 + var%iec - var%isc)
2937  call mpp_error(fatal, trim(error_msg))
2938  endif
2939  i_off = 1 - (var%isc-halo)
2940  endif
2941 
2942  ! Do error checking on the j-dimension and determine the array offsets.
2943  if (present(jdim)) then
2944  if ((jdim(1) > jdim(2)) .or. (jdim(3) > jdim(4))) then
2945  write (error_msg, *) trim(error_header), ' Disordered j-dimension index bound list ', jdim
2946  call mpp_error(fatal, trim(error_msg))
2947  endif
2948  if (size(array_in,2) /= (1+jdim(4)-jdim(1))) then
2949  write (error_msg, *) trim(error_header), ' The declared j-dimension size of ',&
2950  & (1+jdim(4)-jdim(1)), ' does not match the actual size of ', size(array_in,2)
2951  call mpp_error(fatal, trim(error_msg))
2952  endif
2953  if ((var%jec-var%jsc) /= (jdim(3)-jdim(2)))&
2954  & call mpp_error(fatal, trim(error_header)//" There is an j-direction computational domain size mismatch.")
2955  if ((jdim(2)-jdim(1) < halo) .or. (jdim(4)-jdim(3) < halo))&
2956  & call mpp_error(fatal, trim(error_header)//" Excessive j-direction halo size for the output array.")
2957  if (size(array_in,2) < 2*halo + 1 + var%jec - var%jsc) then
2958  write (error_msg, *) trim(error_header), ' The target array with j-dimension size ',&
2959  & (1+jdim(4)-jdim(1)), ' is too small to match the data of size ',&
2960  & (2*halo + 1 + var%jec - var%jsc)
2961  call mpp_error(fatal, trim(error_msg))
2962  endif
2963 
2964  j_off = (1-jdim(1)) + (jdim(2)-var%jsc)
2965  else
2966  if (size(array_in,2) < 2*halo + 1 + var%jec - var%jsc) then
2967  write (error_msg, *) trim(error_header), ' The target array with j-dimension size ',&
2968  & size(array_in,2), ' does not match the data of size ',&
2969  & (2*halo + 1 + var%jec - var%jsc)
2970  call mpp_error(fatal, trim(error_msg))
2971  endif
2972  j_off = 1 - (var%jsc-halo)
2973  endif
2974 
2975  if (size(array_in,3) /= 1 + var%ke - var%ks) then
2976  write (error_msg, *) trim(error_header), ' The target array with k-dimension size ',&
2977  & size(array_in,3), ' does not match the data of size ',&
2978  & (1 + var%ke - var%ks)
2979  call mpp_error(fatal, trim(error_msg))
2980  endif
2981  k_off = 1 - var%ks
2982 
2983  do k=var%ks,var%ke
2984  do j=var%jsc-halo,var%jec+halo
2985  do i=var%isc-halo,var%iec+halo
2986  var%bc(bc_index)%field(field_index)%values(i,j,k) = scale * array_in(i+i_off,j+j_off,k+k_off)
2987  enddo
2988  enddo
2989  enddo
2990  end subroutine ct_set_data_3d
2991 
2992 
2993  !! Register the diagnostics of a coupler_2d_bc_type
2994  !!
2995  !! \throw FATAL, "axes has less than 2 elements"
2996  subroutine ct_set_diags_2d(var, diag_name, axes, time)
2997  type(coupler_2d_bc_type), intent(inout) :: var !< BC_type structure for which to register diagnostics
2998  character(len=*), intent(in) :: diag_name !< name for diagnostic file--if blank, then don't register the fields
2999  integer, dimension(:), intent(in) :: axes !< array of axes identifiers for diagnostic variable registration
3000  type(time_type), intent(in) :: time !< model time variable for registering diagnostic field
3001 
3002  integer :: m, n
3003 
3004  if (diag_name == ' ') return
3005 
3006  if (size(axes) < 2) then
3007  call mpp_error(fatal, '==>Error from coupler_types_mod' //&
3008  & '(coupler_types_set_diags_3d): axes has less than 2 elements')
3009  endif
3010 
3011  do n = 1, var%num_bcs
3012  do m = 1, var%bc(n)%num_fields
3013  var%bc(n)%field(m)%id_diag = register_diag_field(diag_name,&
3014  & var%bc(n)%field(m)%name, axes(1:2), time,&
3015  & var%bc(n)%field(m)%long_name, var%bc(n)%field(m)%units)
3016  enddo
3017  enddo
3018  end subroutine ct_set_diags_2d
3019 
3020  !> Register the diagnostics of a coupler_3d_bc_type.
3021  !!
3022  !! \throw FATAL, "axes has less than 3 elements"
3023  subroutine ct_set_diags_3d(var, diag_name, axes, time)
3024  type(coupler_3d_bc_type), intent(inout) :: var !< BC_type structure for which to register diagnostics
3025  character(len=*), intent(in) :: diag_name !< name for diagnostic file--if blank, then don't register the fields
3026  integer, dimension(:), intent(in) :: axes !< array of axes identifiers for diagnostic variable registration
3027  type(time_type), intent(in) :: time !< model time variable for registering diagnostic field
3028 
3029  integer :: m, n
3030 
3031  if (diag_name == ' ') return
3032 
3033  if (size(axes) < 3) then
3034  call mpp_error(fatal, '==>Error from coupler_types_mod' //&
3035  & '(coupler_types_set_diags_3d): axes has less than 3 elements')
3036  endif
3037 
3038  do n = 1, var%num_bcs
3039  do m = 1, var%bc(n)%num_fields
3040  var%bc(n)%field(m)%id_diag = register_diag_field(diag_name,&
3041  & var%bc(n)%field(m)%name, axes(1:3), time,&
3042  & var%bc(n)%field(m)%long_name, var%bc(n)%field(m)%units )
3043  enddo
3044  enddo
3045  end subroutine ct_set_diags_3d
3046 
3047 
3048  !> Write out all diagnostics of elements of a coupler_2d_bc_type
3049  subroutine ct_send_data_2d(var, Time)
3050  type(coupler_2d_bc_type), intent(in) :: var !< BC_type structure with the diagnostics to write
3051  type(time_type), intent(in) :: time !< The current model time
3052 
3053  integer :: m, n
3054  logical :: used
3055 
3056  do n = 1, var%num_bcs
3057  do m = 1, var%bc(n)%num_fields
3058  if (var%bc(n)%field(m)%id_diag > 0) then
3059  used = send_data(var%bc(n)%field(m)%id_diag, var%bc(n)%field(m)%values, time)
3060  endif
3061  enddo
3062  enddo
3063  end subroutine ct_send_data_2d
3064 
3065  !> Write out all diagnostics of elements of a coupler_3d_bc_type
3066  subroutine ct_send_data_3d(var, Time)
3067  type(coupler_3d_bc_type), intent(in) :: var !< BC_type structure with the diagnostics to write
3068  type(time_type), intent(in) :: time !< The current model time
3069 
3070  integer :: m, n
3071  logical :: used
3072 
3073  do n = 1, var%num_bcs
3074  do m = 1, var%bc(n)%num_fields
3075  if (var%bc(n)%field(m)%id_diag > 0) then
3076  used = send_data(var%bc(n)%field(m)%id_diag, var%bc(n)%field(m)%values, time)
3077  endif
3078  enddo
3079  enddo
3080  end subroutine ct_send_data_3d
3081 
3082  !! Register the fields in a coupler_2d_bc_type to be saved in restart files
3083  !!
3084  !! This subroutine registers the fields in a coupler_2d_bc_type to be saved in restart files
3085  !! specified in the field table.
3086  subroutine ct_register_restarts_2d(var, bc_rest_files, num_rest_files, mpp_domain, ocean_restart)
3087  type(coupler_2d_bc_type), intent(inout) :: var !< BC_type structure to be registered for restarts
3088  type(restart_file_type), dimension(:), pointer :: bc_rest_files !< Structures describing the restart files
3089  integer, intent(out) :: num_rest_files !< The number of restart files to use
3090  type(domain2D), intent(in) :: mpp_domain !< The FMS domain to use for this registration call
3091  logical, optional, intent(in) :: ocean_restart !< If true, use the ocean restart file name.
3092 
3093  character(len=80), dimension(max(1,var%num_bcs)) :: rest_file_names
3094  character(len=80) :: file_nm
3095  logical :: ocn_rest
3096  integer :: f, n, m
3097 
3098  ocn_rest = .true.
3099  if (present(ocean_restart)) ocn_rest = ocean_restart
3100 
3101  ! Determine the number and names of the restart files
3102  num_rest_files = 0
3103  do n = 1, var%num_bcs
3104  if (var%bc(n)%num_fields <= 0) cycle
3105  file_nm = trim(var%bc(n)%ice_restart_file)
3106  if (ocn_rest) file_nm = trim(var%bc(n)%ocean_restart_file)
3107  do f = 1, num_rest_files
3108  if (trim(file_nm) == trim(rest_file_names(f))) exit
3109  enddo
3110  if (f>num_rest_files) then
3111  num_rest_files = num_rest_files + 1
3112  rest_file_names(f) = trim(file_nm)
3113  endif
3114  enddo
3115 
3116  if (num_rest_files == 0) return
3117 
3118  ! Register the fields with the restart files
3119  allocate(bc_rest_files(num_rest_files))
3120  do n = 1, var%num_bcs
3121  if (var%bc(n)%num_fields <= 0) cycle
3122 
3123  file_nm = trim(var%bc(n)%ice_restart_file)
3124  if (ocn_rest) file_nm = trim(var%bc(n)%ocean_restart_file)
3125  do f = 1, num_rest_files
3126  if (trim(file_nm) == trim(rest_file_names(f))) exit
3127  enddo
3128 
3129  var%bc(n)%rest_type => bc_rest_files(f)
3130  do m = 1, var%bc(n)%num_fields
3131  var%bc(n)%field(m)%id_rest = register_restart_field(bc_rest_files(f),&
3132  & rest_file_names(f), var%bc(n)%field(m)%name, var%bc(n)%field(m)%values,&
3133  & mpp_domain, mandatory=.not.var%bc(n)%field(m)%may_init )
3134  enddo
3135  enddo
3136  end subroutine ct_register_restarts_2d
3137 
3138  !! Register the fields in a coupler_2d_bc_type to be saved to restart files
3139  !!
3140  !! This subroutine registers the fields in a coupler_2d_bc_type to be saved in the specified
3141  !! restart file.
3142  subroutine ct_register_restarts_to_file_2d(var, file_name, rest_file, mpp_domain, varname_prefix)
3143  type(coupler_2d_bc_type), intent(inout) :: var !< BC_type structure to be registered for restarts
3144  character(len=*), intent(in) :: file_name !< The name of the restart file
3145  type(restart_file_type), pointer :: rest_file !< A (possibly associated) structure describing the restart file
3146  type(domain2D), intent(in) :: mpp_domain !< The FMS domain to use for this registration call
3147  character(len=*), optional, intent(in) :: varname_prefix !< A prefix for the variable name
3148  !! in the restart file, intended to allow
3149  !! multiple BC_type variables to use the
3150  !! same restart files.
3151 
3152  character(len=128) :: var_name
3153  integer :: n, m
3154 
3155  ! Register the fields with the restart file
3156  if (.not.associated(rest_file)) allocate(rest_file)
3157  do n = 1, var%num_bcs
3158  if (var%bc(n)%num_fields <= 0) cycle
3159 
3160  var%bc(n)%rest_type => rest_file
3161  do m = 1, var%bc(n)%num_fields
3162  var_name = trim(var%bc(n)%field(m)%name)
3163  if (present(varname_prefix)) var_name = trim(varname_prefix)//trim(var_name)
3164  var%bc(n)%field(m)%id_rest = register_restart_field(rest_file,&
3165  & file_name, var_name, var%bc(n)%field(m)%values,&
3166  & mpp_domain, mandatory=.not.var%bc(n)%field(m)%may_init )
3167  enddo
3168  enddo
3169  end subroutine ct_register_restarts_to_file_2d
3170 
3171  !! Register the fields in a coupler_3d_bc_type to be saved to restart files
3172  !!
3173  !! This subroutine registers the fields in a coupler_3d_bc_type to be saved in restart files
3174  !! specified in the field table.
3175  subroutine ct_register_restarts_3d(var, bc_rest_files, num_rest_files, mpp_domain, ocean_restart)
3176  type(coupler_3d_bc_type), intent(inout) :: var !< BC_type structure to be registered for restarts
3177  type(restart_file_type), dimension(:), pointer :: bc_rest_files !< Structures describing the restart files
3178  integer, intent(out) :: num_rest_files !< The number of restart files to use
3179  type(domain2D), intent(in) :: mpp_domain !< The FMS domain to use for this registration call
3180  logical, optional, intent(in) :: ocean_restart !< If true, use the ocean restart file name.
3181 
3182  character(len=80), dimension(max(1,var%num_bcs)) :: rest_file_names
3183  character(len=80) :: file_nm
3184  logical :: ocn_rest
3185  integer :: f, n, m, id_restart
3186 
3187  ocn_rest = .true.
3188  if (present(ocean_restart)) ocn_rest = ocean_restart
3189 
3190  ! Determine the number and names of the restart files
3191  num_rest_files = 0
3192  do n = 1, var%num_bcs
3193  if (var%bc(n)%num_fields <= 0) cycle
3194  file_nm = trim(var%bc(n)%ice_restart_file)
3195  if (ocn_rest) file_nm = trim(var%bc(n)%ocean_restart_file)
3196  do f = 1, num_rest_files
3197  if (trim(file_nm) == trim(rest_file_names(f))) exit
3198  enddo
3199  if (f>num_rest_files) then
3200  num_rest_files = num_rest_files + 1
3201  rest_file_names(f) = trim(file_nm)
3202  endif
3203  enddo
3204 
3205  if (num_rest_files == 0) return
3206 
3207  ! Register the fields with the restart files
3208  allocate(bc_rest_files(num_rest_files))
3209  do n = 1, var%num_bcs
3210  if (var%bc(n)%num_fields <= 0) cycle
3211  file_nm = trim(var%bc(n)%ice_restart_file)
3212  if (ocn_rest) file_nm = trim(var%bc(n)%ocean_restart_file)
3213  do f = 1, num_rest_files
3214  if (trim(file_nm) == trim(rest_file_names(f))) exit
3215  enddo
3216 
3217  var%bc(n)%rest_type => bc_rest_files(f)
3218  do m = 1, var%bc(n)%num_fields
3219  var%bc(n)%field(m)%id_rest = register_restart_field(bc_rest_files(f),&
3220  & rest_file_names(f), var%bc(n)%field(m)%name, var%bc(n)%field(m)%values,&
3221  & mpp_domain, mandatory=.not.var%bc(n)%field(m)%may_init )
3222  enddo
3223  enddo
3224  end subroutine ct_register_restarts_3d
3225 
3226  !> Register the fields in a coupler_3d_bc_type to be saved to restart files
3227  !!
3228  !! Registers the fields in a coupler_3d_bc_type to be saved in the specified restart file.
3229  subroutine ct_register_restarts_to_file_3d(var, file_name, rest_file, mpp_domain, varname_prefix)
3230  type(coupler_3d_bc_type), intent(inout) :: var !< BC_type structure to be registered for restarts
3231  character(len=*), intent(in) :: file_name !< The name of the restart file
3232  type(restart_file_type), pointer :: rest_file !< A (possibly associated) structure describing the restart file
3233  type(domain2D), intent(in) :: mpp_domain !< The FMS domain to use for this registration call
3234  character(len=*), optional, intent(in) :: varname_prefix !< A prefix for the variable name
3235  !! in the restart file, intended to allow
3236  !! multiple BC_type variables to use the
3237  !! same restart files.
3238 
3239  character(len=128) :: var_name
3240  integer :: n, m
3241 
3242  ! Register the fields with the restart file
3243  if (.not.associated(rest_file)) allocate(rest_file)
3244  do n = 1, var%num_bcs
3245  if (var%bc(n)%num_fields <= 0) cycle
3246 
3247  var%bc(n)%rest_type => rest_file
3248  do m = 1, var%bc(n)%num_fields
3249  var_name = trim(var%bc(n)%field(m)%name)
3250  if (present(varname_prefix)) var_name = trim(varname_prefix)//trim(var_name)
3251  var%bc(n)%field(m)%id_rest = register_restart_field(rest_file,&
3252  & file_name, var_name, var%bc(n)%field(m)%values,&
3253  & mpp_domain, mandatory=.not.var%bc(n)%field(m)%may_init )
3254  enddo
3255  enddo
3256  end subroutine ct_register_restarts_to_file_3d
3257 
3258 
3259  !> Reads in fields from restart files into a coupler_2d_bc_type
3260  !!
3261  !! This subroutine reads in the fields in a coupler_2d_bc_type that have been saved in restart
3262  !! files.
3263  subroutine ct_restore_state_2d(var, directory, all_or_nothing, all_required, test_by_field)
3264  type(coupler_2d_bc_type), intent(inout) :: var !< BC_type structure to restore from restart files
3265  character(len=*), optional, intent(in) :: directory !< A directory where the restart files should
3266  !! be found. The default for FMS is 'INPUT'.
3267  logical, optional, intent(in) :: all_or_nothing !< If true and there are non-mandatory
3268  !! restart fields, it is still an error if some
3269  !! fields are read successfully but others are not.
3270  logical, optional, intent(in) :: all_required !< If true, all fields must be successfully
3271  !! read from the restart file, even if they were
3272  !! registered as not mandatory.
3273  logical, optional, intent(in) :: test_by_field !< If true, all or none of the variables
3274  !! in a single field must be read successfully.
3275 
3276  integer :: n, m, num_fld
3277  character(len=80) :: unset_varname
3278  logical :: any_set, all_set, all_var_set, any_var_set, var_set
3279 
3280  any_set = .false.
3281  all_set = .true.
3282  num_fld = 0
3283  unset_varname = ""
3284 
3285  do n = 1, var%num_bcs
3286  any_var_set = .false.
3287  all_var_set = .true.
3288  do m = 1, var%bc(n)%num_fields
3289  var_set = .false.
3290  if (var%bc(n)%field(m)%id_rest > 0) then
3291  var_set = query_initialized(var%bc(n)%rest_type, var%bc(n)%field(m)%id_rest)
3292  if (.not.var_set) then
3293  call restore_state(var%bc(n)%rest_type, var%bc(n)%field(m)%id_rest,&
3294  & directory=directory, nonfatal_missing_files=.true.)
3295  var_set = query_initialized(var%bc(n)%rest_type, var%bc(n)%field(m)%id_rest)
3296  endif
3297  endif
3298 
3299  if (.not.var_set) unset_varname = trim(var%bc(n)%field(m)%name)
3300  if (var_set) any_set = .true.
3301  if (all_set) all_set = var_set
3302  if (var_set) any_var_set = .true.
3303  if (all_var_set) all_var_set = var_set
3304  enddo
3305 
3306  num_fld = num_fld + var%bc(n)%num_fields
3307  if ((var%bc(n)%num_fields > 0) .and. present(test_by_field)) then
3308  if (test_by_field .and. (all_var_set .neqv. any_var_set)) call mpp_error(fatal,&
3309  & "CT_restore_state_2d: test_by_field is true, and "//&
3310  & trim(unset_varname)//" was not read but some other fields in "//&
3311  & trim(trim(var%bc(n)%name))//" were.")
3312  endif
3313  enddo
3314 
3315  if ((num_fld > 0) .and. present(all_or_nothing)) then
3316  if (all_or_nothing .and. (all_set .neqv. any_set)) call mpp_error(fatal,&
3317  & "CT_restore_state_2d: all_or_nothing is true, and "//&
3318  & trim(unset_varname)//" was not read but some other fields were.")
3319  endif
3320 
3321  if (present(all_required)) then
3322  if (all_required .and. .not.all_set) then
3323  call mpp_error(fatal, "CT_restore_state_2d: all_required is true, but "//&
3324  & trim(unset_varname)//" was not read from its restart file.")
3325  endif
3326  endif
3327  end subroutine ct_restore_state_2d
3328 
3329  !> Read in fields from restart files into a coupler_3d_bc_type
3330  !!
3331  !! This subroutine reads in the fields in a coupler_3d_bc_type that have been saved in restart
3332  !! files.
3333  subroutine ct_restore_state_3d(var, directory, all_or_nothing, all_required, test_by_field)
3334  type(coupler_3d_bc_type), intent(inout) :: var !< BC_type structure to restore from restart files
3335  character(len=*), optional, intent(in) :: directory !< A directory where the restart files should
3336  !! be found. The default for FMS is 'INPUT'.
3337  logical, optional, intent(in) :: all_or_nothing !< If true and there are non-mandatory
3338  !! restart fields, it is still an error if some
3339  !! fields are read successfully but others are not.
3340  logical, optional, intent(in) :: all_required !< If true, all fields must be successfully
3341  !! read from the restart file, even if they were
3342  !! registered as not mandatory.
3343  logical, optional, intent(in) :: test_by_field !< If true, all or none of the variables
3344  !! in a single field must be read successfully.
3345 
3346  integer :: n, m, num_fld
3347  character(len=80) :: unset_varname
3348  logical :: any_set, all_set, all_var_set, any_var_set, var_set
3349 
3350  any_set = .false.
3351  all_set = .true.
3352  num_fld = 0
3353  unset_varname = ""
3354 
3355  do n = 1, var%num_bcs
3356  any_var_set = .false.
3357  all_var_set = .true.
3358  do m = 1, var%bc(n)%num_fields
3359  var_set = .false.
3360  if (var%bc(n)%field(m)%id_rest > 0) then
3361  var_set = query_initialized(var%bc(n)%rest_type, var%bc(n)%field(m)%id_rest)
3362  if (.not.var_set) then
3363  call restore_state(var%bc(n)%rest_type, var%bc(n)%field(m)%id_rest,&
3364  & directory=directory, nonfatal_missing_files=.true.)
3365  var_set = query_initialized(var%bc(n)%rest_type, var%bc(n)%field(m)%id_rest)
3366  endif
3367  endif
3368 
3369  if (.not.var_set) unset_varname = trim(var%bc(n)%field(m)%name)
3370 
3371  if (var_set) any_set = .true.
3372  if (all_set) all_set = var_set
3373  if (var_set) any_var_set = .true.
3374  if (all_var_set) all_var_set = var_set
3375  enddo
3376 
3377  num_fld = num_fld + var%bc(n)%num_fields
3378  if ((var%bc(n)%num_fields > 0) .and. present(test_by_field)) then
3379  if (test_by_field .and. (all_var_set .neqv. any_var_set)) call mpp_error(fatal,&
3380  & "CT_restore_state_3d: test_by_field is true, and "//&
3381  & trim(unset_varname)//" was not read but some other fields in "//&
3382  & trim(trim(var%bc(n)%name))//" were.")
3383  endif
3384  enddo
3385 
3386  if ((num_fld > 0) .and. present(all_or_nothing)) then
3387  if (all_or_nothing .and. (all_set .neqv. any_set)) call mpp_error(fatal,&
3388  & "CT_restore_state_3d: all_or_nothing is true, and "//&
3389  & trim(unset_varname)//" was not read but some other fields were.")
3390  endif
3391 
3392  if (present(all_required)) then
3393  if (all_required .and. .not.all_set) then
3394  call mpp_error(fatal, "CT_restore_state_3d: all_required is true, but "//&
3395  & trim(unset_varname)//" was not read from its restart file.")
3396  endif
3397  endif
3398  end subroutine ct_restore_state_3d
3399 
3400 
3401  !> Potentially override the values in a coupler_2d_bc_type
3402  subroutine ct_data_override_2d(gridname, var, Time)
3403  character(len=3), intent(in) :: gridname !< 3-character long model grid ID
3404  type(coupler_2d_bc_type), intent(inout) :: var !< BC_type structure to override
3405  type(time_type), intent(in) :: time !< The current model time
3406 
3407  integer :: m, n
3408 
3409  do n = 1, var%num_bcs
3410  do m = 1, var%bc(n)%num_fields
3411  call data_override(gridname, var%bc(n)%field(m)%name, var%bc(n)%field(m)%values, time)
3412  enddo
3413  enddo
3414  end subroutine ct_data_override_2d
3415 
3416  !> Potentially override the values in a coupler_3d_bc_type
3417  subroutine ct_data_override_3d(gridname, var, Time)
3418  character(len=3), intent(in) :: gridname !< 3-character long model grid ID
3419  type(coupler_3d_bc_type), intent(inout) :: var !< BC_type structure to override
3420  type(time_type), intent(in) :: time !< The current model time
3421 
3422  integer :: m, n
3423 
3424  do n = 1, var%num_bcs
3425  do m = 1, var%bc(n)%num_fields
3426  call data_override(gridname, var%bc(n)%field(m)%name, var%bc(n)%field(m)%values, time)
3427  enddo
3428  enddo
3429  end subroutine ct_data_override_3d
3430 
3431 
3432  !> Write out checksums for the elements of a coupler_2d_bc_type
3433  subroutine ct_write_chksums_2d(var, outunit, name_lead)
3434  type(coupler_2d_bc_type), intent(in) :: var !< BC_type structure for which to register diagnostics
3435  integer, intent(in) :: outunit !< The index of a open output file
3436  character(len=*), optional, intent(in) :: name_lead !< An optional prefix for the variable names
3437 
3438  character(len=120) :: var_name
3439  integer :: m, n
3440 
3441  do n = 1, var%num_bcs
3442  do m = 1, var%bc(n)%num_fields
3443  if (present(name_lead)) then
3444  var_name = trim(name_lead)//trim(var%bc(n)%field(m)%name)
3445  else
3446  var_name = trim(var%bc(n)%field(m)%name)
3447  endif
3448  write(outunit, '(" CHECKSUM:: ",A40," = ",Z20)') trim(var_name),&
3449  & mpp_chksum(var%bc(n)%field(m)%values(var%isc:var%iec,var%jsc:var%jec) )
3450  enddo
3451  enddo
3452  end subroutine ct_write_chksums_2d
3453 
3454  !> Write out checksums for the elements of a coupler_3d_bc_type
3455  subroutine ct_write_chksums_3d(var, outunit, name_lead)
3456  type(coupler_3d_bc_type), intent(in) :: var !< BC_type structure for which to register diagnostics
3457  integer, intent(in) :: outunit !< The index of a open output file
3458  character(len=*), optional, intent(in) :: name_lead !< An optional prefix for the variable names
3459 
3460  character(len=120) :: var_name
3461  integer :: m, n
3462 
3463  do n = 1, var%num_bcs
3464  do m = 1, var%bc(n)%num_fields
3465  if (present(name_lead)) then
3466  var_name = trim(name_lead)//trim(var%bc(n)%field(m)%name)
3467  else
3468  var_name = trim(var%bc(n)%field(m)%name)
3469  endif
3470  write(outunit, '(" CHECKSUM:: ",A40," = ",Z20)') var_name,&
3471  & mpp_chksum(var%bc(n)%field(m)%values(var%isc:var%iec,var%jsc:var%jec,:) )
3472  enddo
3473  enddo
3474  end subroutine ct_write_chksums_3d
3475 
3476 
3477  !> Indicate whether a coupler_1d_bc_type has been initialized.
3478  logical function ct_initialized_1d(var)
3479  type(coupler_1d_bc_type), intent(in) :: var !< BC_type structure to be deconstructed
3480 
3481  ct_initialized_1d = var%set
3482  end function ct_initialized_1d
3483 
3484  !> Indicate whether a coupler_2d_bc_type has been initialized.
3485  logical function ct_initialized_2d(var)
3486  type(coupler_2d_bc_type), intent(in) :: var !< BC_type structure to be deconstructed
3487 
3488  ct_initialized_2d = var%set
3489  end function ct_initialized_2d
3490 
3491  !> Indicate whether a coupler_3d_bc_type has been initialized.
3492  logical function ct_initialized_3d(var)
3493  type(coupler_3d_bc_type), intent(in) :: var !< BC_type structure to be deconstructed
3494 
3495  ct_initialized_3d = var%set
3496  end function ct_initialized_3d
3497 
3498  !> Deallocate all data associated with a coupler_1d_bc_type
3499  subroutine ct_destructor_1d(var)
3500  type(coupler_1d_bc_type), intent(inout) :: var !< BC_type structure to be deconstructed
3501 
3502  integer :: m, n
3503 
3504  if (var%num_bcs > 0) then
3505  do n = 1, var%num_bcs
3506  do m = 1, var%bc(n)%num_fields
3507  deallocate ( var%bc(n)%field(m)%values )
3508  enddo
3509  deallocate ( var%bc(n)%field )
3510  enddo
3511  deallocate ( var%bc )
3512  endif
3513 
3514  var%num_bcs = 0
3515  var%set = .false.
3516  end subroutine ct_destructor_1d
3517 
3518  !> Deallocate all data associated with a coupler_2d_bc_type
3519  subroutine ct_destructor_2d(var)
3520  type(coupler_2d_bc_type), intent(inout) :: var !< BC_type structure to be deconstructed
3521 
3522  integer :: m, n
3523 
3524  if (var%num_bcs > 0) then
3525  do n = 1, var%num_bcs
3526  do m = 1, var%bc(n)%num_fields
3527  deallocate ( var%bc(n)%field(m)%values )
3528  enddo
3529  deallocate ( var%bc(n)%field )
3530  enddo
3531  deallocate ( var%bc )
3532  endif
3533 
3534  var%num_bcs = 0
3535  var%set = .false.
3536  end subroutine ct_destructor_2d
3537 
3538  !> Deallocate all data associated with a coupler_3d_bc_type
3539  subroutine ct_destructor_3d(var)
3540  type(coupler_3d_bc_type), intent(inout) :: var !< BC_type structure to be deconstructed
3541 
3542  integer :: m, n
3543 
3544  if (var%num_bcs > 0) then
3545  do n = 1, var%num_bcs
3546  do m = 1, var%bc(n)%num_fields
3547  deallocate ( var%bc(n)%field(m)%values )
3548  enddo
3549  deallocate ( var%bc(n)%field )
3550  enddo
3551  deallocate ( var%bc )
3552  endif
3553 
3554  var%num_bcs = 0
3555  var%set = .false.
3556  end subroutine ct_destructor_3d
3557 end module coupler_types_mod
Definition: fms.F90:20
subroutine ct_increment_data_3d_3d(var_in, var, halo_size, bc_index, field_index, scale_factor, scale_prev, exclude_flux_type, only_flux_type, pass_through_ice)
subroutine ct_redistribute_data_2d(var_in, domain_in, var_out, domain_out, complete)
Redistribute the data in all elements of a coupler_2d_bc_type.
subroutine ct_send_data_3d(var, Time)
Write out all diagnostics of elements of a coupler_3d_bc_type.
This is the interface to set diagnostics for the arrays in a coupler_bc_type.
subroutine ct_extract_data_3d_2d(var_in, bc_index, field_index, k_in, array_out, scale_factor, halo_size, idim, jdim)
subroutine ct_set_diags_3d(var, diag_name, axes, time)
Register the diagnostics of a coupler_3d_bc_type.
subroutine, public coupler_type_copy_1d_3d(var_in, var_out, is, ie, js, je, kd, diag_name, axes, time, suffix)
Copy fields from one coupler type to another. 1-D to 3-D version for generic coupler_type_copy.
subroutine ct_register_restarts_to_file_2d(var, file_name, rest_file, mpp_domain, varname_prefix)
subroutine coupler_type_copy_3d_2d(var_in, var_out, is, ie, js, je, diag_name, axes, time, suffix)
Copy fields from one coupler type to another. 3-D to 2-D version for generic coupler_type_copy.
subroutine ct_destructor_3d(var)
Deallocate all data associated with a coupler_3d_bc_type.
subroutine ct_write_chksums_3d(var, outunit, name_lead)
Write out checksums for the elements of a coupler_3d_bc_type.
This is the interface to rescale the field data in a coupler_bc_type.
integer, public ind_csurf
The index of the ocean surface concentration.
subroutine ct_data_override_3d(gridname, var, Time)
Potentially override the values in a coupler_3d_bc_type.
character(len= *), parameter mod_name
subroutine ct_restore_state_3d(var, directory, all_or_nothing, all_required, test_by_field)
Read in fields from restart files into a coupler_3d_bc_type.
subroutine ct_spawn_3d_3d(var_in, var, idim, jdim, kdim, suffix, as_needed)
Generate one coupler type using another as a template. 3-D to 3-D version for generic CT_spawn...
subroutine, public coupler_type_copy_1d_2d(var_in, var_out, is, ie, js, je, diag_name, axes, time, suffix)
Copy fields from one coupler type to another. 1-D to 2-D version for generic coupler_type_copy.
subroutine ct_extract_data_3d(var_in, bc_index, field_index, array_out, scale_factor, halo_size, idim, jdim)
Extract single 3d field from a coupler_3d_bc_type.
logical function ct_initialized_1d(var)
Indicate whether a coupler_1d_bc_type has been initialized.
integer, public ind_deposition
The index for the atmospheric deposition flux.
subroutine ct_copy_data_2d(var_in, var, halo_size, bc_index, field_index, exclude_flux_type, only_flux_type, pass_through_ice)
Copy all elements of coupler_2d_bc_type.
subroutine coupler_type_copy_3d_3d(var_in, var_out, is, ie, js, je, kd, diag_name, axes, time, suffix)
Copy fields from one coupler type to another. 3-D to 3-D version for generic coupler_type_copy.
This is the interface to read in the fields in a coupler_bc_type that have been saved in restart file...
This is the interface to copy the field data from one coupler_bc_type to another of the same rank...
integer, public ind_alpha
The index of the solubility array for a tracer.
subroutine ct_restore_state_2d(var, directory, all_or_nothing, all_required, test_by_field)
Reads in fields from restart files into a coupler_2d_bc_type.
integer, public ind_kw
The index for the piston velocity.
subroutine ct_data_override_2d(gridname, var, Time)
Potentially override the values in a coupler_2d_bc_type.
This is the interface to increment the field data from one coupler_bc_type with the data from another...
Definition: mpp.F90:39
subroutine coupler_type_copy_2d_2d(var_in, var_out, is, ie, js, je, diag_name, axes, time, suffix)
Copy fields from one coupler type to another. 2-D to 2-D version for generic coupler_type_copy.
This is the interface to write out checksums for the elements of a coupler_bc_type.
subroutine ct_spawn_1d_3d(var_in, var, idim, jdim, kdim, suffix, as_needed)
Generate one coupler type using another as a template. 1-D to 3-D version for generic CT_spawn...
subroutine, public coupler_types_init
Initialize the coupler types.
This is the interface to extract a field in a coupler_bc_type into an array.
integer, public ind_sc_no
The index for the Schmidt number for a tracer flux.
integer, public ind_deltap
The index for ocean-air gas partial pressure change.
This is the interface to deallocate any data associated with a coupler_bc_type.
subroutine ct_spawn_2d_3d(var_in, var, idim, jdim, kdim, suffix, as_needed)
Generate one coupler type using another as a template. 2-D to 3-D version for generic CT_spawn...
subroutine ct_set_diags_2d(var, diag_name, axes, time)
subroutine ct_rescale_data_2d(var, scale, halo_size, bc_index, field_index, exclude_flux_type, only_flux_type, pass_through_ice)
Rescales the fields in the fields in the elements of a coupler_2d_bc_type.
This is the interface to set a field in a coupler_bc_type from an array.
subroutine coupler_type_copy_2d_3d(var_in, var_out, is, ie, js, je, kd, diag_name, axes, time, suffix)
Copy fields from one coupler type to another. 2-D to 3-D version for generic coupler_type_copy.
integer, public ind_runoff
The index for a runoff flux.
subroutine ct_rescale_data_3d(var, scale, halo_size, bc_index, field_index, exclude_flux_type, only_flux_type, pass_through_ice)
subroutine ct_copy_data_2d_3d(var_in, var, halo_size, bc_index, field_index, exclude_flux_type, only_flux_type, pass_through_ice, ind3_start, ind3_end)
Copy all elements of coupler_2d_bc_type to coupler_3d_bc_type.
logical function ct_initialized_3d(var)
Indicate whether a coupler_3d_bc_type has been initialized.
integer, public ind_psurf
The index of the surface atmospheric pressure.
subroutine ct_copy_data_3d(var_in, var, halo_size, bc_index, field_index, exclude_flux_type, only_flux_type, pass_through_ice)
Copy all elements of coupler_3d_bc_type.
This is the interface to register the fields in a coupler_bc_type to be saved in restart files...
subroutine ct_spawn_2d_2d(var_in, var, idim, jdim, suffix, as_needed)
Generate one coupler type using another as a template. 2-D to 2-D version for generic CT_spawn...
subroutine ct_set_data_3d(array_in, bc_index, field_index, var, scale_factor, halo_size, idim, jdim)
Set a single 3d field in a coupler_3d_bc_type.
This is the interface to write out diagnostics of the arrays in a coupler_bc_type.
subroutine ct_spawn_3d_2d(var_in, var, idim, jdim, suffix, as_needed)
Generate one coupler type using another as a template. 3-D to 2-D version for generic CT_spawn...
subroutine ct_set_data_2d_3d(array_in, bc_index, field_index, k_out, var, scale_factor, halo_size, idim, jdim)
Set one k-level of a single 3d field in a coupler_3d_bc_type.
subroutine ct_register_restarts_to_file_3d(var, file_name, rest_file, mpp_domain, varname_prefix)
Register the fields in a coupler_3d_bc_type to be saved to restart files.
integer, public ind_u10
The index of the 10 m wind speed.
This module contains type declarations for the coupler.
subroutine ct_increment_data_2d_3d(var_in, weights, var, halo_size, bc_index, field_index, scale_factor, scale_prev, exclude_flux_type, only_flux_type, pass_through_ice)
subroutine ct_send_data_2d(var, Time)
Write out all diagnostics of elements of a coupler_2d_bc_type.
This is the interface to spawn one coupler_bc_type into another and then register diagnostics associa...
#define max(a, b)
Definition: mosaic_util.h:33
integer, public ind_pcair
The index of the atmospheric concentration.
subroutine ct_register_restarts_2d(var, bc_rest_files, num_rest_files, mpp_domain, ocean_restart)
subroutine ct_increment_data_2d_2d(var_in, var, halo_size, bc_index, field_index, scale_factor, scale_prev, exclude_flux_type, only_flux_type, pass_through_ice)
subroutine ct_register_restarts_3d(var, bc_rest_files, num_rest_files, mpp_domain, ocean_restart)
subroutine ct_redistribute_data_3d(var_in, domain_in, var_out, domain_out, complete)
Redistributes the data in all elements of one coupler_2d_bc_type.
subroutine ct_extract_data_2d(var_in, bc_index, field_index, array_out, scale_factor, halo_size, idim, jdim)
Extract a 2d field from a coupler_2d_bc_type.
subroutine ct_destructor_2d(var)
Deallocate all data associated with a coupler_2d_bc_type.
This is the interface to override the values of the arrays in a coupler_bc_type.
This is the interface to redistribute the field data from one coupler_bc_type to another of the same ...
This is the interface to spawn one coupler_bc_type into another.
subroutine ct_destructor_1d(var)
Deallocate all data associated with a coupler_1d_bc_type.
logical function ct_initialized_2d(var)
Indicate whether a coupler_2d_bc_type has been initialized.
integer, public ind_flux0
The index for the piston velocity.
subroutine ct_write_chksums_2d(var, outunit, name_lead)
Write out checksums for the elements of a coupler_2d_bc_type.
This function interface indicates whether a coupler_bc_type has been initialized. ...
integer, public ind_flux
The index for the tracer flux.
subroutine ct_set_data_2d(array_in, bc_index, field_index, var, scale_factor, halo_size, idim, jdim)
Set single 2d field in coupler_3d_bc_type.
subroutine ct_spawn_1d_2d(var_in, var, idim, jdim, suffix, as_needed)
Generate one coupler type using another as a template. 1-D to 2-D version for generic coupler_type_sp...