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