Официальный репозиторий модуля 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 — символьный формат времени в файле перезагрузки.