Официальный репозиторий модуля FMS на github:

https://github.com/NOAA-GFDL/FMS/blob/master/fms

Основные функции модуля FMS:

use fms_mod, only : read_data, write_data, open_namelist_file, close_file, fms_init
use fms_mod, only : file_exist
use fms_io_mod, only : restart_file_type, reg_rf => register_restart_field
use fms_io_mod, only : restore_state, save_restart, fms_io_exit

read_data считывает распределенные данные из одного связанного файла. Чтобы обеспечить безопасность и предотвратить сбои кода, чтение fortran должно предшествовать read_data. Следующие аргументы используются для определения конца файла для процедуры read_data.

ERROR MSG="unexpected EOF" STATUS="FATAL"

read_data реализован следующим образом

call read_data(filename,fieldname,data,domain,timelevel)

Здесь имя_файла — имя файла для чтения, имя_поля — имя поля/переменной в файле для чтения, данные — это выходные данные, которые являются переменной в программе, domain — это домен, для которого читается файл, а timelevel — это время в файле, который читается. Перед чтением или записью данных необходимо вызвать set_domain, который устанавливает декомпозицию домена с соответствующим типом данных domain2D.

write_data записывает данные в формате netcdf и реализуется следующим образом.

call write_data(filename, fieldname, data, domain)

Здесь имя файла — это имя файла, в который программная переменная data записывается для определенного домена в виде имени переменной имя поля в файле.

Функция open_namelist_file используется для открытия файла списка имен, указанного в аргументе, для открытия всеми PE. Он реализован как

unit = open_namelist_file()
read(unit,nml=amfi_nml)
call close_file(unit)

Файл по умолчанию, открываемый namelist, — это input.nml.

Здесь мы видим использование подпрограммы close_file, которая используется для закрытия файлов, открытых open_namelist_file, open_restart_file и open_ieee32_file, все остальные файлы должны быть закрыты подпрограммой mpp_close.

fms_io_exit — это подпрограмма, которая вызывается после того, как все переменные были записаны соответствующими PE. Он реализован как

call fms_io_exit

fms_init инициализирует модуль fms, а также модуль mpp_io (который инициализирует все моды mpp). Он вызывается автоматически, если пользователь его не вызывает. Он реализован как

call fms_init()

Функция file_exist проверяет существование определенного файла. Он возвращает true, если файл существует, и false, если его нет. Он используется как

if ( file_exist('input.nml') ) then
!   do something
end if

restart_file_type — это производный тип данных, определенный в диспетчере времени следующим образом.

type restart_file_type   
  private   
  integer :: unit = -1 ! mpp_io unit for netcdf file
  character(len=128)  :: name = '' 
  integer             :: register_id = 0 
  integer             :: nvar = 0 
  integer             :: natt = 0 
  integer             :: max_ntime = 0 
  logical             :: is_root_pe = .FALSE.  
  logical             :: is_compressed = .FALSE.  
  logical             :: unlimited_axis = .FALSE. 
  integer             :: tile_count = 1  
  type(ax_type),  allocatable   :: axes(:)  ! Currently define X,Y,Compressed, unlimited and maybe Z   
  type(meta_type),  pointer  :: first =>NULL() ! pointer to first additional global metadata element   
  type(var_type), dimension(:),   pointer  :: var  => NULL()     
  type(Ptr0Dr),   dimension(:,:), pointer  :: p0dr => NULL()
  type(Ptr1Dr),   dimension(:,:), pointer  :: p1dr => NULL()                       
  type(Ptr2Dr),   dimension(:,:), pointer  :: p2dr => NULL()
  type(Ptr3Dr),   dimension(:,:), pointer  :: p3dr => NULL()  
  type(Ptr2Dr8),  dimension(:,:), pointer  :: p2dr8 => NULL()
  type(Ptr3Dr8),  dimension(:,:), pointer  :: p3dr8 => NULL()
  type(Ptr4Dr),   dimension(:,:), pointer  :: p4dr => NULL()
  type(Ptr0Di),   dimension(:,:), pointer  :: p0di => NULL()
  type(Ptr1Di),   dimension(:,:), pointer  :: p1di => NULL()
  type(Ptr2Di),   dimension(:,:), pointer  :: p2di => NULL()
  type(Ptr3Di),   dimension(:,:), pointer  :: p3di => NULL()
end type restart_file_type
! creates 0D, 1D, 2D and 3D pointers as each element have an attribute as a pointer

Он используется следующим образом для создания таких объектов, как files_read и files_write.

type(restart_file_type), dimension(:), allocatable :: files_read  ! store files that are read through read_data
type(restart_file_type), dimension(:), allocatable, target :: files_write ! store files that are written through write_data

Производные типы данных Ptr0Dr и другие определяются следующим образом.

type Ptr0Dr   
  real, pointer :: p => NULL()
end type Ptr0Dr 
type Ptr1Dr   
  real, dimension(:), pointer :: p => NULL()
end type Ptr1Dr
type Ptr2Dr   
  real, dimension(:,:), pointer :: p => NULL()
end type Ptr2Dr
! single pointers pointing to 0D, 1D anf 2D data

Чтобы узнать больше об указателях, обратитесь к https://www.tutorialspoint.com/fortran/fortran_pointers.htm.

Проще говоря, указатель используется для хранения адреса памяти объекта. Итак, чтобы объяснить с tutorialspoint

integer, pointer :: p1 ! pointer to integer  
real, pointer, dimension (:) :: pra ! pointer to 1-dim real array  
real, pointer, dimension (:,:) :: pra2 ! pointer to 2-dim real array

index_field и index_file — это две переменные, используемые в модуле fms следующим образом:

integer      :: index_field ! position of the fieldname in the list of fields  
integer      :: index_file  ! position of the filename in the list of files_write

var_type определяется в модуле fms следующим образом

type var_type   
  private   
  character(len=128)                   :: name = '' 
  character(len=128)                   :: longname = ''    
  character(len=128)                   :: units = ''   real, 
  dimension(:,:,:,:), _ALLOCATABLE :: buffer _NULL   
  logical                          :: domain_present = .FALSE.     
  integer                          :: domain_idx = -1   
  logical                          :: is_dimvar = .FALSE.   
  logical                          :: read_only = .FALSE.   
  logical                          :: owns_data = .FALSE. 
 ! if true, restart owns the data and will deallocate them when freed   
  type(fieldtype)                  :: field   
  type(axistype)                   :: axis   
  integer                          :: position   
  integer                          :: ndim   
  integer                          :: siz(5)  
  .
  .
  .
end type var_type

Интерфейс register_restart_field используется для чтения данных из файла в производный тип данных/регистрации скалярного реального поля файла перезапуска с одним временным уровнем. Он определяется следующим образом в модуле fms

function register_restart_field_r0d(fileObj, filename, fieldname, data, domain, mandatory, &                                    no_domain, position, tile_count, data_default, &                                    longname, units, read_only, restart_owns_data)    
  type(restart_file_type),    intent(inout)      :: fileObj    
  character(len=*),           intent(in)         :: filename, 
  fieldname  real,            intent(in), target :: data  
  type(domain2d),   optional, intent(in), target :: domain  
  logical,          optional, intent(in)         :: no_domain  
  real,             optional, intent(in)         :: data_default   
  logical,          optional, intent(in)         :: mandatory  
  integer,          optional, intent(in)         :: position,
   tile_count  
  character(len=*), optional, intent(in)         :: longname, units  
  logical,          optional, intent(in)         :: read_only  
  logical,          optional, intent(in)         :: 
  restart_owns_data  
  integer                                        :: index_field   
  integer                                        ::  
  register_restart_field_r0d
  . 
  .
  .
  fileObj%p0dr(fileObj%var(index_field)%siz(4), index_field)%p => data  
  fileObj%var(index_field)%ndim = 0  register_restart_field_r0d = index_field
end function register_restart_field_r0d

Это был пример процедуры 0D, определенной в поле register_restart_field, существуют процедуры для случаев 1D, 2D, 3D и для соответствующего представления с плавающей запятой r8.

restore_state — это интерфейс с двумя процедурами restore_state_all и restore_state_one_field.

Подпрограммы определяются следующим образом

subroutine restore_state_all(fileObj, directory, nonfatal_missing_files)
subroutine restore_state_one_field(fileObj, id_field, directory, nonfatal_missing_files)

Первая подпрограмма restore_state_all считывает состояние модели из ранее сгенерированных файлов, а все переменные перезапуска считываются из первого файла во входном списке имен файлов, в котором они находятся. restart_state_one_field делает то же самое для одного поля, идентифицированного id_field и доступного через fileObj%var(id_field), здесь fileObj — это объект restart_file_type, содержащий информацию о перезапусках, каталог – это папка, в которой нужно искать файлы перезапуска, nonfatal_missing_files – логический аргумент, который, если он истинен, не может найти ожидаемый файл перезапуска, не обязательно является фатальным, а id_field  – это идентификатор поля переменной, который был возвращен предыдущим вызовом register_restart_field.

Подпрограмма save_restart сохраняет все зарегистрированные переменные для перезапуска файлов, а переменные устанавливаются через register_restart_field. Он называется, как показано ниже:

call save_restart(fileObj, time_stamp, directory, append, time_level)

где каталог — это папка, в которой сохраняется перезагрузка, а time_stamp — символьный формат времени в файле перезагрузки.