FMS  2024.03
Flexible Modeling System
netcdf_add_restart_variable.inc
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 !> @file
20 !> @brief Routines to add restart variables to a netcdf file with different dimension sizes
21 !! for the @ref netcdf_add_restart_variable interface
22 
23 !> @addtogroup netcdf_io_mod
24 !> @{
25 
26 !> @brief Add a restart variable to a netcdf file.
27 subroutine netcdf_add_restart_variable_0d(fileobj, variable_name, vdata, dimensions, &
28  is_optional, chunksizes)
29 
30  class(fmsnetcdffile_t), intent(inout) :: fileobj !< File object.
31  character(len=*), intent(in) :: variable_name !< Variable name.
32  class(*), intent(in), target :: vdata !< Pointer to
33  !! variable data.
34  character(len=*), dimension(1), intent(in), optional :: dimensions !< Dimension names.
35  logical, intent(in), optional :: is_optional !< Prevent errors in read-only files
36  !! if a variable does not exist.
37  integer, intent(in), optional :: chunksizes(:) !< netcdf chunksize to use for this variable
38  !! This feature is only
39  !! available for netcdf4 files
40  character(len=8) :: buf
41 
42  if (fileobj%is_readonly .and. present(is_optional)) then
43  if (is_optional .and. .not. variable_exists(fileobj, variable_name)) then
44  return
45  endif
46  endif
47  call add_restart_var_to_array(fileobj, variable_name)
48  fileobj%restart_vars(fileobj%num_restart_vars)%data0d => vdata
49  if (.not. fileobj%is_readonly) then
50  call get_data_type_string(vdata, buf)
51  if (present(dimensions)) then
52  if (.not. is_dimension_unlimited(fileobj, dimensions(1), .true.)) then
53  call error("a scalar input variable can only have an unlimited dimension.")
54  endif
55  endif
56  call netcdf_add_variable(fileobj, variable_name, buf, dimensions, &
57  chunksizes=chunksizes)
58  endif
59 end subroutine netcdf_add_restart_variable_0d
60 
61 
62 !> @brief Wrapper to distinguish interfaces.
63 subroutine netcdf_add_restart_variable_0d_wrap(fileobj, variable_name, vdata, &
64  dimensions, is_optional, &
65  chunksizes)
66  type(fmsnetcdffile_t), intent(inout) :: fileobj !< File object.
67  character(len=*), intent(in) :: variable_name !< Variable name.
68  class(*), intent(in), target :: vdata !< Pointer to
69  !! variable data.
70  character(len=*), dimension(1), intent(in), optional :: dimensions !< Dimension names.
71  logical, intent(in), optional :: is_optional !< Prevent errors in read-only files
72  !! if a variable does not exist.
73  integer, intent(in), optional :: chunksizes(:) !< netcdf chunksize to use for this variable
74  !! This feature is only
75  !! available for netcdf4 files
76 
77  call netcdf_add_restart_variable(fileobj, variable_name, vdata, dimensions, is_optional, &
78  chunksizes=chunksizes)
80 
81 
82 !> @brief Add a restart variable to a netcdf file.
83 subroutine netcdf_add_restart_variable_1d(fileobj, variable_name, vdata, &
84  dimensions, is_optional, &
85  chunksizes)
86  class(fmsnetcdffile_t), intent(inout) :: fileobj !< File object.
87  character(len=*), intent(in) :: variable_name !< Variable name.
88  class(*), dimension(:), intent(in), target :: vdata !< Pointer to
89  !! variable data.
90  character(len=*), dimension(:), intent(in), optional :: dimensions !< Dimension names.
91  logical, intent(in), optional :: is_optional !< Prevent errors in read-only files
92  !! if a variable does not exist.
93  integer, intent(in), optional :: chunksizes(:) !< netcdf chunksize to use for this variable
94  !! This feature is only
95  !! available for netcdf4 files
96  character(len=8) :: buf
97  integer :: ndims
98  integer :: vdata_rank
99 
100  if (fileobj%is_readonly .and. present(is_optional)) then
101  if (is_optional .and. .not. variable_exists(fileobj, variable_name)) then
102  return
103  endif
104  endif
105  call add_restart_var_to_array(fileobj, variable_name)
106  fileobj%restart_vars(fileobj%num_restart_vars)%data1d => vdata
107  if (.not. fileobj%is_readonly) then
108  call get_data_type_string(vdata, buf)
109  if (.not. present(dimensions)) then
110  call error("dimension names required if the file is not read-only.")
111  endif
112  ndims = size(dimensions)
113  vdata_rank = size(shape(vdata))
114  if (ndims .eq. vdata_rank+1) then
115  if (.not. is_dimension_unlimited(fileobj, dimensions(ndims), .true.)) then
116  call error("the slowest dimension must be unlimited.")
117  endif
118  elseif (ndims .ne. vdata_rank) then
119  call error("rank mismatch between vdata and dimensions arrays.")
120  endif
121  call netcdf_add_variable(fileobj, variable_name, buf, dimensions, &
122  chunksizes=chunksizes)
123  endif
124 end subroutine netcdf_add_restart_variable_1d
125 
126 
127 !> @brief Wrapper to distinguish interfaces.
128 subroutine netcdf_add_restart_variable_1d_wrap(fileobj, variable_name, vdata, &
129  dimensions, is_optional, &
130  chunksizes)
131  type(fmsnetcdffile_t), intent(inout) :: fileobj !< File object.
132  character(len=*), intent(in) :: variable_name !< Variable name.
133  class(*), dimension(:), intent(in), target :: vdata !< Pointer to
134  !! variable data.
135  character(len=*), dimension(:), intent(in), optional :: dimensions !< Dimension names.
136  logical, intent(in), optional :: is_optional !< Prevent errors in read-only files
137  !! if a variable does not exist.
138  integer, intent(in), optional :: chunksizes(:) !< netcdf chunksize to use for this variable
139  !! This feature is only
140  !! available for netcdf4 files
141 
142  call netcdf_add_restart_variable(fileobj, variable_name, vdata, dimensions, is_optional, &
143  chunksizes=chunksizes)
145 
146 
147 !> @brief Add a restart variable to a netcdf file.
148 subroutine netcdf_add_restart_variable_2d(fileobj, variable_name, vdata, &
149  dimensions, is_optional, &
150  chunksizes)
151  class(fmsnetcdffile_t), intent(inout) :: fileobj !< File object.
152  character(len=*), intent(in) :: variable_name !< Variable name.
153  class(*), dimension(:,:), intent(in), target :: vdata !< Pointer to
154  !! variable data.
155  character(len=*), dimension(:), intent(in), optional :: dimensions !< Dimension names.
156  logical, intent(in), optional :: is_optional !< Prevent errors in read-only files
157  !! if a variable does not exist.
158  integer, intent(in), optional :: chunksizes(:) !< netcdf chunksize to use for this variable
159  !! This feature is only
160  !! available for netcdf4 files
161  character(len=8) :: buf
162  integer :: ndims
163  integer :: vdata_rank
164 
165  if (fileobj%is_readonly .and. present(is_optional)) then
166  if (is_optional .and. .not. variable_exists(fileobj, variable_name)) then
167  return
168  endif
169  endif
170  call add_restart_var_to_array(fileobj, variable_name)
171  fileobj%restart_vars(fileobj%num_restart_vars)%data2d => vdata
172  if (.not. fileobj%is_readonly) then
173  call get_data_type_string(vdata, buf)
174  if (.not. present(dimensions)) then
175  call error("dimension names required if the file is not read-only.")
176  endif
177  ndims = size(dimensions)
178  vdata_rank = size(shape(vdata))
179  if (ndims .eq. vdata_rank+1) then
180  if (.not. is_dimension_unlimited(fileobj, dimensions(ndims), .true.)) then
181  call error("the slowest dimension must be unlimited.")
182  endif
183  elseif (ndims .ne. vdata_rank) then
184  call error("rank mismatch between vdata and dimensions arrays.")
185  endif
186  call netcdf_add_variable(fileobj, variable_name, buf, dimensions, &
187  chunksizes=chunksizes)
188  endif
189 end subroutine netcdf_add_restart_variable_2d
190 
191 
192 !> @brief Wrapper to distinguish interfaces.
193 subroutine netcdf_add_restart_variable_2d_wrap(fileobj, variable_name, vdata, &
194  dimensions, is_optional, &
195  chunksizes)
196  type(fmsnetcdffile_t), intent(inout) :: fileobj !< File object.
197  character(len=*), intent(in) :: variable_name !< Variable name.
198  class(*), dimension(:,:), intent(in), target :: vdata !< Pointer to
199  !! variable data.
200  character(len=*), dimension(:), intent(in), optional :: dimensions !< Dimension names.
201  logical, intent(in), optional :: is_optional !< Prevent errors in read-only files
202  !! if a variable does not exist.
203  integer, intent(in), optional :: chunksizes(:) !< netcdf chunksize to use for this variable
204  !! This feature is only
205  !! available for netcdf4 files
206 
207  call netcdf_add_restart_variable(fileobj, variable_name, vdata, dimensions, is_optional, &
208  chunksizes=chunksizes)
210 
211 
212 !> @brief Add a restart variable to a netcdf file.
213 subroutine netcdf_add_restart_variable_3d(fileobj, variable_name, vdata, &
214  dimensions, is_optional, &
215  chunksizes)
216  class(fmsnetcdffile_t), intent(inout) :: fileobj !< File object.
217  character(len=*), intent(in) :: variable_name !< Variable name.
218  class(*), dimension(:,:,:), intent(in), target :: vdata !< Pointer to
219  !! variable data.
220  character(len=*), dimension(:), intent(in), optional :: dimensions !< Dimension names.
221  logical, intent(in), optional :: is_optional !< Prevent errors in read-only files
222  !! if a variable does not exist.
223  integer, intent(in), optional :: chunksizes(:) !< netcdf chunksize to use for this variable
224  !! This feature is only
225  !! available for netcdf4 files
226  character(len=8) :: buf
227  integer :: ndims
228  integer :: vdata_rank
229 
230  if (fileobj%is_readonly .and. present(is_optional)) then
231  if (is_optional .and. .not. variable_exists(fileobj, variable_name)) then
232  return
233  endif
234  endif
235  call add_restart_var_to_array(fileobj, variable_name)
236  fileobj%restart_vars(fileobj%num_restart_vars)%data3d => vdata
237  if (.not. fileobj%is_readonly) then
238  call get_data_type_string(vdata, buf)
239  if (.not. present(dimensions)) then
240  call error("dimension names required if the file is not read-only.")
241  endif
242  ndims = size(dimensions)
243  vdata_rank = size(shape(vdata))
244  if (ndims .eq. vdata_rank+1) then
245  if (.not. is_dimension_unlimited(fileobj, dimensions(ndims), .true.)) then
246  call error("the slowest dimension must be unlimited.")
247  endif
248  elseif (ndims .ne. vdata_rank) then
249  call error("rank mismatch between vdata and dimensions arrays.")
250  endif
251  call netcdf_add_variable(fileobj, variable_name, buf, dimensions, &
252  chunksizes=chunksizes)
253  endif
254 end subroutine netcdf_add_restart_variable_3d
255 
256 
257 !> @brief Wrapper to distinguish interfaces.
258 subroutine netcdf_add_restart_variable_3d_wrap(fileobj, variable_name, vdata, &
259  dimensions, is_optional, &
260  chunksizes)
261  type(fmsnetcdffile_t), intent(inout) :: fileobj !< File object.
262  character(len=*), intent(in) :: variable_name !< Variable name.
263  class(*), dimension(:,:,:), intent(in), target :: vdata !< Pointer to
264  !! variable data.
265  character(len=*), dimension(:), intent(in), optional :: dimensions !< Dimension names.
266  logical, intent(in), optional :: is_optional !< Prevent errors in read-only files
267  !! if a variable does not exist.
268  integer, intent(in), optional :: chunksizes(:) !< netcdf chunksize to use for this variable
269  !! This feature is only
270  !! available for netcdf4 files
271 
272  call netcdf_add_restart_variable(fileobj, variable_name, vdata, dimensions, is_optional, &
273  chunksizes=chunksizes)
275 
276 
277 !> @brief Add a restart variable to a netcdf file.
278 subroutine netcdf_add_restart_variable_4d(fileobj, variable_name, vdata, &
279  dimensions, is_optional, &
280  chunksizes)
281  class(fmsnetcdffile_t), intent(inout) :: fileobj !< File object.
282  character(len=*), intent(in) :: variable_name !< Variable name.
283  class(*), dimension(:,:,:,:), intent(in), target :: vdata !< Pointer to
284  !! variable data.
285  character(len=*), dimension(:), intent(in), optional :: dimensions !< Dimension names.
286  logical, intent(in), optional :: is_optional !< Prevent errors in read-only files
287  !! if a variable does not exist.
288  integer, intent(in), optional :: chunksizes(:) !< netcdf chunksize to use for this variable
289  !! This feature is only
290  !! available for netcdf4 files
291  character(len=8) :: buf
292  integer :: ndims
293  integer :: vdata_rank
294 
295  if (fileobj%is_readonly .and. present(is_optional)) then
296  if (is_optional .and. .not. variable_exists(fileobj, variable_name)) then
297  return
298  endif
299  endif
300  call add_restart_var_to_array(fileobj, variable_name)
301  fileobj%restart_vars(fileobj%num_restart_vars)%data4d => vdata
302  if (.not. fileobj%is_readonly) then
303  call get_data_type_string(vdata, buf)
304  if (.not. present(dimensions)) then
305  call error("dimension names required if the file is not read-only.")
306  endif
307  ndims = size(dimensions)
308  vdata_rank = size(shape(vdata))
309  if (ndims .eq. vdata_rank+1) then
310  if (.not. is_dimension_unlimited(fileobj, dimensions(ndims), .true.)) then
311  call error("the slowest dimension must be unlimited.")
312  endif
313  elseif (ndims .ne. vdata_rank) then
314  call error("rank mismatch between vdata and dimensions arrays.")
315  endif
316  call netcdf_add_variable(fileobj, variable_name, buf, dimensions, &
317  chunksizes=chunksizes)
318  endif
319 end subroutine netcdf_add_restart_variable_4d
320 
321 
322 !> @brief Wrapper to distinguish interfaces.
323 subroutine netcdf_add_restart_variable_4d_wrap(fileobj, variable_name, vdata, &
324  dimensions, is_optional, &
325  chunksizes)
326  type(fmsnetcdffile_t), intent(inout) :: fileobj !< File object.
327  character(len=*), intent(in) :: variable_name !< Variable name.
328  class(*), dimension(:,:,:,:), intent(in), target :: vdata !< Pointer to
329  !! variable data.
330  character(len=*), dimension(:), intent(in), optional :: dimensions !< Dimension names.
331  logical, intent(in), optional :: is_optional !< Prevent errors in read-only files
332  !! if a variable does not exist.
333  integer, intent(in), optional :: chunksizes(:) !< netcdf chunksize to use for this variable
334  !! This feature is only
335  !! available for netcdf4 files
336 
337  call netcdf_add_restart_variable(fileobj, variable_name, vdata, dimensions, is_optional, &
338  chunksizes=chunksizes)
340 
341 
342 !> @brief Add a restart variable to a netcdf file.
343 subroutine netcdf_add_restart_variable_5d(fileobj, variable_name, vdata, &
344  dimensions, is_optional, &
345  chunksizes)
346  class(fmsnetcdffile_t), intent(inout) :: fileobj !< File object.
347  character(len=*), intent(in) :: variable_name !< Variable name.
348  class(*), dimension(:,:,:,:,:), intent(in), target :: vdata !< Pointer to
349  !! variable data.
350  character(len=*), dimension(:), intent(in), optional :: dimensions !< Dimension names.
351  logical, intent(in), optional :: is_optional !< Prevent errors in read-only files
352  !! if a variable does not exist.
353  integer, intent(in), optional :: chunksizes(:) !< netcdf chunksize to use for this variable
354  !! This feature is only
355  !! available for netcdf4 files
356  character(len=8) :: buf
357  integer :: ndims
358  integer :: vdata_rank
359 
360  if (fileobj%is_readonly .and. present(is_optional)) then
361  if (is_optional .and. .not. variable_exists(fileobj, variable_name)) then
362  return
363  endif
364  endif
365  call add_restart_var_to_array(fileobj, variable_name)
366  fileobj%restart_vars(fileobj%num_restart_vars)%data5d => vdata
367  if (.not. fileobj%is_readonly) then
368  call get_data_type_string(vdata, buf)
369  if (.not. present(dimensions)) then
370  call error("dimension names required if the file is not read-only.")
371  endif
372  ndims = size(dimensions)
373  vdata_rank = size(shape(vdata))
374  if (ndims .eq. vdata_rank+1) then
375  if (.not. is_dimension_unlimited(fileobj, dimensions(ndims), .true.)) then
376  call error("the slowest dimension must be unlimited.")
377  endif
378  elseif (ndims .ne. vdata_rank) then
379  call error("rank mismatch between vdata and dimensions arrays.")
380  endif
381  call netcdf_add_variable(fileobj, variable_name, buf, dimensions, &
382  chunksizes=chunksizes)
383  endif
384 end subroutine netcdf_add_restart_variable_5d
385 
386 
387 !> @brief Wrapper to distinguish interfaces.
388 subroutine netcdf_add_restart_variable_5d_wrap(fileobj, variable_name, vdata, &
389  dimensions, is_optional, &
390  chunksizes)
391  type(fmsnetcdffile_t), intent(inout) :: fileobj !< File object.
392  character(len=*), intent(in) :: variable_name !< Variable name.
393  class(*), dimension(:,:,:,:,:), intent(in), target :: vdata !< Pointer to
394  !! variable data.
395  character(len=*), dimension(:), intent(in), optional :: dimensions !< Dimension names.
396  logical, intent(in), optional :: is_optional !< Prevent errors in read-only files
397  !! if a variable does not exist.
398  integer, intent(in), optional :: chunksizes(:) !< netcdf chunksize to use for this variable
399  !! This feature is only
400  !! available for netcdf4 files
401 
402  call netcdf_add_restart_variable(fileobj, variable_name, vdata, dimensions, is_optional, &
403  chunksizes=chunksizes)
405 
406 !> @brief Registers a regional 2D variable and stores the information needed
407 subroutine register_restart_region_2d(fileobj, variable_name, vdata, indices, global_size, pelist, is_root_pe, &
408  x_halo, y_halo, jshift, ishift, is_optional)
409  type(fmsnetcdffile_t), intent(inout) :: fileobj !< File object.
410  character(len=*), intent(in) :: variable_name !< Variable name.
411  class(*), dimension(:,:), intent(in), target :: vdata !< Pointer to variable data
412  integer, dimension(4), intent(in) :: indices!< Indices for the halo region for the variable
413  !! (starting x, ending x, starting y, ending y)
414  integer, dimension(:), intent(in) :: global_size !> Global_size(1:2) == size of the variable in (x,y)
415  integer, dimension(:), intent(in) :: pelist !> List of pelist that have the data for
416  !! the variable
417  logical, intent(in) :: is_root_pe !> Flag indicating if this is the root_pe
418  !! from the pelist
419  integer, intent(in), optional :: x_halo !< Number of halos in x
420  integer, intent(in), optional :: y_halo !< Number of halos in y
421  integer, intent(in), optional :: jshift !< Shift in the x axis (from center)
422  integer, intent(in), optional :: ishift !< Shift in the y axis (from center)
423  logical, intent(in), optional :: is_optional !< Prevent errors in read-only files
424  !! if a variable does not exist.
425 
426  integer :: current_var !> Current number of registered variables
427  character(len=7) :: dimnames(4) !> Names of the dimensions for the variable_name
428 
429  !> If you reading the file and the variable is optional and not in the file, leave
430  if (fileobj%is_readonly .and. present(is_optional)) then
431  if (is_optional .and. .not. variable_exists(fileobj, variable_name)) then
432  return
433  endif
434  endif
435 
436  !> Register the axis for the variable dimension and get the names of the dimensions
437  call set_dimensions(fileobj, fileobj%bc_dimensions, dimnames, global_size)
438  call netcdf_add_restart_variable_2d(fileobj, variable_name, vdata, dimnames(1:3), is_optional)
439 
440  !> Save the boundary conditions information to the bc_info type for the given variable
441  current_var = fileobj%num_restart_vars
442  fileobj%restart_vars(current_var)%is_bc_variable = .true.
443  fileobj%restart_vars(current_var)%bc_info%is_root_pe = is_root_pe
444 
445  allocate(fileobj%restart_vars(current_var)%bc_info%indices(4))
446  fileobj%restart_vars(current_var)%bc_info%indices = indices
447 
448  allocate(fileobj%restart_vars(current_var)%bc_info%global_size(2))
449  fileobj%restart_vars(current_var)%bc_info%global_size = global_size
450 
451  if (any(fileobj%io_root .eq. pelist(:))) then
452  allocate(fileobj%restart_vars(current_var)%bc_info%pelist(size(pelist)))
453  fileobj%restart_vars(current_var)%bc_info%pelist = pelist
454  fileobj%restart_vars(current_var)%bc_info%data_on_file_root = .true.
455  else
456  allocate(fileobj%restart_vars(current_var)%bc_info%pelist(size(pelist)+1))
457  fileobj%restart_vars(current_var)%bc_info%pelist = (/ fileobj%io_root, pelist(:) /)
458  fileobj%restart_vars(current_var)%bc_info%data_on_file_root = .false.
459  endif
460 
461  fileobj%restart_vars(current_var)%bc_info%x_halo = 0
462  fileobj%restart_vars(current_var)%bc_info%y_halo = 0
463  fileobj%restart_vars(current_var)%bc_info%ishift = 0
464  fileobj%restart_vars(current_var)%bc_info%jshift = 0
465 
466  if (present(x_halo)) fileobj%restart_vars(current_var)%bc_info%x_halo = x_halo
467  if (present(y_halo)) fileobj%restart_vars(current_var)%bc_info%y_halo = y_halo
468  if (present(ishift)) fileobj%restart_vars(current_var)%bc_info%ishift = ishift
469  if (present(jshift)) fileobj%restart_vars(current_var)%bc_info%jshift = jshift
470 
471 end subroutine register_restart_region_2d
472 
473 !> @brief Registers a regional 3D variable and stores the information needed
474 subroutine register_restart_region_3d(fileobj, variable_name, vdata, indices, global_size, pelist, is_root_pe, &
475  x_halo, y_halo, jshift, ishift, is_optional)
476  type(fmsnetcdffile_t), intent(inout) :: fileobj !< File object.
477  character(len=*), intent(in) :: variable_name !< Variable name.
478  class(*), dimension(:,:,:), intent(in), target :: vdata !< Pointer to variable data
479  integer, dimension(4), intent(in) :: indices !< Indices for the halo region for the variable
480  !! (starting x, ending x, starting y, ending y)
481  integer, dimension(:), intent(in) :: global_size !> Global_size(1:3) == size of the
482  !! variable in (x,y,z)
483  integer, dimension(:), intent(in) :: pelist !> List of pelist that have the data for
484  !! the variable
485  logical, intent(in) :: is_root_pe !> Flag indicating if this is the root_pe
486  !! from the pelist
487  integer, intent(in), optional :: x_halo !< Number of halos in x
488  integer, intent(in), optional :: y_halo !< Number of halos in y
489  integer, intent(in), optional :: jshift !< Shift in the y axis (from center)
490  integer, intent(in), optional :: ishift !< Shift in the x axis (from center)
491  logical, intent(in), optional :: is_optional !< Prevent errors in read-only files
492  !! if a variable does not exist.
493 
494  integer :: current_var !> Current number of registered variables
495  character(len=7) :: dimnames(4) !> Names of the dimensions for the variable_name
496 
497  !> If you reading the file and the variable is optional and not in the file, leave
498  if (fileobj%is_readonly .and. present(is_optional)) then
499  if (is_optional .and. .not. variable_exists(fileobj, variable_name)) then
500  return
501  endif
502  endif
503 
504  !> Register the axis for the variable dimension and get the names of the dimensions
505  call set_dimensions(fileobj, fileobj%bc_dimensions, dimnames, global_size)
506  call netcdf_add_restart_variable_3d(fileobj, variable_name, vdata, dimnames(1:4), is_optional)
507 
508  !> Save the boundary conditions information to the bc_info type for the given variable
509  current_var = fileobj%num_restart_vars
510  fileobj%restart_vars(current_var)%is_bc_variable = .true.
511  fileobj%restart_vars(current_var)%bc_info%is_root_pe = is_root_pe
512 
513  allocate(fileobj%restart_vars(current_var)%bc_info%indices(4))
514  fileobj%restart_vars(current_var)%bc_info%indices = indices
515 
516  allocate(fileobj%restart_vars(current_var)%bc_info%global_size(3))
517  fileobj%restart_vars(current_var)%bc_info%global_size = global_size
518 
519  if (any(fileobj%io_root .eq. pelist(:))) then
520  allocate(fileobj%restart_vars(current_var)%bc_info%pelist(size(pelist)))
521  fileobj%restart_vars(current_var)%bc_info%pelist = pelist
522  fileobj%restart_vars(current_var)%bc_info%data_on_file_root = .true.
523  else
524  allocate(fileobj%restart_vars(current_var)%bc_info%pelist(size(pelist)+1))
525  fileobj%restart_vars(current_var)%bc_info%pelist = (/ fileobj%io_root, pelist(:) /)
526  fileobj%restart_vars(current_var)%bc_info%data_on_file_root = .false.
527  endif
528 
529  fileobj%restart_vars(current_var)%bc_info%x_halo = 0
530  fileobj%restart_vars(current_var)%bc_info%y_halo = 0
531  fileobj%restart_vars(current_var)%bc_info%ishift = 0
532  fileobj%restart_vars(current_var)%bc_info%jshift = 0
533 
534  if (present(x_halo)) fileobj%restart_vars(current_var)%bc_info%x_halo = x_halo
535  if (present(y_halo)) fileobj%restart_vars(current_var)%bc_info%y_halo = y_halo
536  if (present(ishift)) fileobj%restart_vars(current_var)%bc_info%ishift = ishift
537  if (present(jshift)) fileobj%restart_vars(current_var)%bc_info%jshift = jshift
538 
539 end subroutine register_restart_region_3d
540 
541 !> @brief Updates the dimension information (bc_dimensions) for the give fileobj and outputs the
542 !! dimensions name of the variable
543 subroutine set_dimensions(fileobj, bc_dimensions, dimnames, global_size)
544  type(fmsnetcdffile_t), intent(inout) :: fileobj !> File object.
545  type(dimension_information), intent(inout) :: bc_dimensions !> Dimension information for the file
546  character(len=7), intent(inout) :: dimnames(4) !> List of the dimension names for the variable
547  !! dimnames(1): Name of the x dimension
548  !! dimnames(2): Name of the y dimension
549  !! dimnames(3): Name of the z dimension (or time if 2d)
550  !! dimnames(4): Name of the Time dimension (if 3d variable)
551  integer, dimension(:), intent(in) :: global_size !> Size of the variable for each dimension
552  !! global_size(1): Size of the x dimension
553  !! global_size(2): Size of the y dimension
554  !! global_size(3): Size of the z dimension (if it exists)
555  character(len=1) :: suffix !> Axis number converted to a string
556  character(len=7) :: axisname !> Name of the axis
557  integer :: i, found_index !> no description
558 
559  if (.not. dimension_exists(fileobj, "Time")) call netcdf_add_dimension(fileobj, "Time", unlimited)
560  dimnames(size(global_size)+1) = "Time"
561 
562  !> Check to see if a x dimension with the correct size is already registered
563  found_index = 0
564  do i = 1, bc_dimensions%cur_dim_len(1)
565  if (bc_dimensions%xlen(i) .eq. global_size(1)) then
566  found_index= i
567  write(suffix,'(I1)') i
568  axisname = 'xaxis_'//suffix
569  dimnames(1) = axisname
570  exit
571  endif
572  enddo
573 
574  !> If the x dimension doesn't already exist, register it
575  if (found_index .eq. 0) then
576  bc_dimensions%cur_dim_len(1) = bc_dimensions%cur_dim_len(1) + 1
577  bc_dimensions%xlen(bc_dimensions%cur_dim_len(1)) = global_size(1)
578  write(suffix,'(I1)') bc_dimensions%cur_dim_len(1)
579  axisname = 'xaxis_'//suffix
580  call netcdf_add_dimension(fileobj, axisname, global_size(1))
581  dimnames(1) = axisname
582  endif
583 
584  !> Check to see if a y dimension with the correct size is already registered
585  found_index = 0
586  do i = 1, bc_dimensions%cur_dim_len(2)
587  if (bc_dimensions%ylen(i) .eq. global_size(2)) then
588  found_index= i
589  write(suffix,'(I1)') i
590  axisname = 'yaxis_'//suffix
591  dimnames(2) = axisname
592  exit
593  endif
594  enddo
595 
596  !> If the y dimension doesn't already exist, register it
597  if (found_index .eq. 0) then
598  bc_dimensions%cur_dim_len(2) = bc_dimensions%cur_dim_len(2) + 1
599  bc_dimensions%ylen(bc_dimensions%cur_dim_len(2)) = global_size(2)
600  write(suffix,'(I1)') bc_dimensions%cur_dim_len(2)
601  axisname = 'yaxis_'//suffix
602  call netcdf_add_dimension(fileobj, axisname, global_size(2))
603  dimnames(2) = axisname
604  endif
605 
606  !> If the variable is 3d:
607  if (size(global_size) .eq. 3) then
608  !> Check to see if a z dimension with the correct size is already registered
609  found_index = 0
610  do i = 1, bc_dimensions%cur_dim_len(3)
611  if (bc_dimensions%zlen(i) .eq. global_size(3)) then
612  found_index= i
613  write(suffix,'(I1)') i
614  axisname = 'zaxis_'//suffix
615  dimnames(3) = axisname
616  exit
617  endif
618  enddo
619 
620  !> If the z dimension doesn't already exist, register it
621  if (found_index .eq. 0) then
622  bc_dimensions%cur_dim_len(3) = bc_dimensions%cur_dim_len(3) + 1
623  bc_dimensions%zlen(bc_dimensions%cur_dim_len(3)) = global_size(3)
624  write(suffix,'(I1)') bc_dimensions%cur_dim_len(3)
625  axisname = 'zaxis_'//suffix
626  call netcdf_add_dimension(fileobj, axisname, global_size(3))
627  dimnames(3) = axisname
628  endif
629  endif
630 end subroutine set_dimensions
631 !> @}
subroutine netcdf_add_restart_variable_4d(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Add a restart variable to a netcdf file.
subroutine netcdf_add_restart_variable_0d(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Add a restart variable to a netcdf file.
subroutine set_dimensions(fileobj, bc_dimensions, dimnames, global_size)
Updates the dimension information (bc_dimensions) for the give fileobj and outputs the dimensions nam...
subroutine netcdf_add_restart_variable_3d(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Add a restart variable to a netcdf file.
subroutine netcdf_add_restart_variable_5d_wrap(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Wrapper to distinguish interfaces.
subroutine netcdf_add_restart_variable_1d_wrap(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Wrapper to distinguish interfaces.
subroutine netcdf_add_restart_variable_0d_wrap(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Wrapper to distinguish interfaces.
subroutine netcdf_add_restart_variable_3d_wrap(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Wrapper to distinguish interfaces.
subroutine netcdf_add_restart_variable_1d(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Add a restart variable to a netcdf file.
subroutine register_restart_region_3d(fileobj, variable_name, vdata, indices, global_size, pelist, is_root_pe, x_halo, y_halo, jshift, ishift, is_optional)
Registers a regional 3D variable and stores the information needed.
subroutine netcdf_add_restart_variable_2d(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Add a restart variable to a netcdf file.
subroutine netcdf_add_restart_variable_4d_wrap(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Wrapper to distinguish interfaces.
subroutine netcdf_add_restart_variable_5d(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Add a restart variable to a netcdf file.
subroutine netcdf_add_restart_variable_2d_wrap(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Wrapper to distinguish interfaces.
subroutine register_restart_region_2d(fileobj, variable_name, vdata, indices, global_size, pelist, is_root_pe, x_halo, y_halo, jshift, ishift, is_optional)
Registers a regional 2D variable and stores the information needed.