Skip to content

Upgrade FMS IO to FMS2 IO#1239

Closed
DavidNew-NOAA wants to merge 9 commits intodevelopfrom
feature/fms-to-fms2
Closed

Upgrade FMS IO to FMS2 IO#1239
DavidNew-NOAA wants to merge 9 commits intodevelopfrom
feature/fms-to-fms2

Conversation

@DavidNew-NOAA
Copy link
Copy Markdown
Contributor

Description

Update FMS IO to FMS2 IO

Issue(s) addressed

Resolves #1225

Dependencies

N/A

Impact

Expected impact on downstream repositories:

N/A

Manual Testing Instructions (optional)

If you would like your reviewers to manually build and test the change, please include
instructions on how the change should be built and tested. Also include a short
justification on why manual testing is necessary for this change.

Checklist

  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation
  • I have run the unit tests before creating the PR

Copilot AI and others added 8 commits March 23, 2026 17:12
Replace fms_io_mod with fms2_io_mod across all Fortran source files:

- soca_balance_mod.F90: Replace read_data from fms_mod with
  open_file/read_data/close_file from fms2_io_mod
- soca_geom_mod.F90: Replace restart_file_type with FmsNetcdfDomainFile_t,
  register_restart_field/restore_state/save_restart with
  open_file/register_restart_field/read_restart/write_restart/close_file,
  remove fms_io_init/fms_io_exit and associated counter
- soca_fields_mod.F90: Same pattern replacements plus replace
  file_exist/field_exist with open_file/variable_exists

Co-authored-by: DavidNew-NOAA <134300700+DavidNew-NOAA@users.noreply.github.com>
Agent-Logs-Url: https://github.com/DavidNew-NOAA/soca/sessions/79ffa8fd-153d-4e6d-a50b-0f9b31130309
Co-authored-by: DavidNew-NOAA <134300700+DavidNew-NOAA@users.noreply.github.com>
Agent-Logs-Url: https://github.com/DavidNew-NOAA/soca/sessions/79ffa8fd-153d-4e6d-a50b-0f9b31130309
…art for writes

Use read_data() for all file reads instead of register_restart_field + read_restart,
since input files (gridspec, ocean data, ice data) may not have restart metadata.
Add is_restart=.true. to open_file for write operations so register_restart_field
+ write_restart works correctly when creating new files.

Agent-Logs-Url: https://github.com/DavidNew-NOAA/soca/sessions/40ac97e7-ffa8-4a2f-bc1b-e089f96badc9

Co-authored-by: DavidNew-NOAA <134300700+DavidNew-NOAA@users.noreply.github.com>
FMS2's register_restart_field requires explicit dimension names when
writing (non-read-only). Added:
- ["xaxis_1"] for 1D x-axis variables (lonh, lonq)
- ["yaxis_1"] for 1D y-axis variables (lath, latq)
- ["xaxis_1", "yaxis_1"] for 2D domain-decomposed variables
- ["xaxis_1", "yaxis_1", "zaxis_1"] for 3D domain-decomposed variables

Agent-Logs-Url: https://github.com/DavidNew-NOAA/soca/sessions/4a7f62e8-b633-428b-acfa-7788b715560a

Co-authored-by: DavidNew-NOAA <134300700+DavidNew-NOAA@users.noreply.github.com>
@DavidNew-NOAA DavidNew-NOAA requested a review from Copilot April 28, 2026 19:53
@DavidNew-NOAA DavidNew-NOAA changed the title Feature/fms to fms2 Upgrade FMS IO to FMS2 IO Apr 28, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates SOCA’s Fortran I/O integration to use fms2_io_mod (FMS I/O v2) APIs, addressing build failures when fms_io_mod is unavailable/incompatible (Issue #1225).

Changes:

  • Replace legacy fms_io_mod / fms_mod: read_data usage with fms2_io_mod (open_file, read_data, close_file).
  • Rework geometry gridspec read/write paths to use FMS2 NetCDF domain file objects and restart-writing APIs.
  • Update field reading/writing and variable existence checks to use FMS2 (variable_exists) and file-object-based access.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

File Description
src/soca/LinearVariableChange/Balance/soca_balance_mod.F90 Switches dc/dT Jacobian input read to FMS2 file-object I/O.
src/soca/Geometry/soca_geom_mod.F90 Migrates gridspec read/write from legacy restart API to FMS2 open/read/close and restart writing with axis/field registration.
src/soca/Fields/soca_fields_mod.F90 Migrates restart/state I/O and existence checks to FMS2, including overwrite/write-restart workflow.
Comments suppressed due to low confidence (1)

src/soca/Fields/soca_fields_mod.F90:580

  • This if (variable_exists(...)) then block has an empty THEN branch, which makes the intent unclear and is easy to misread. Consider inverting the condition (e.g., if (.not. variable_exists(...)) then ...) so the non-default path is explicit.
              if(variable_exists(restart, self%fields(f)%metadata%io_name)) then
              else
                call seaice_categories_vars%push_back(self%fields(f)%name)
                cycle
              end if

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

do v = 1, size(atlasVars)
call read_data(geom_restart, atlasVars(v), fieldDataVars(:,:,v))
end do
call close_file(geom_restart)
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If open_file(geom_restart, ...) fails here, fieldDataVars stays at its default values and the code proceeds to populate atlas fields, which can silently corrupt the geometry-derived fields. Consider failing fast (or at least logging) when the gridspec cannot be opened/read.

Suggested change
call close_file(geom_restart)
call close_file(geom_restart)
else
write(*,*) "ERROR: failed to open geom_grid_file: ", trim(str)
error stop "Unable to read geometry gridspec file"

Copilot uses AI. Check for mistakes.
end do

call write_restart(geom_restart)
call close_file(geom_restart)
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If open_file(geom_restart, ...) fails, this routine silently produces no output file. Given this is a write path, consider handling the failure explicitly (abort or log an error including the target path) so failures aren't missed in batch workflows.

Suggested change
call close_file(geom_restart)
call close_file(geom_restart)
else
write(*, '(A)') 'ERROR: soca_geom_write failed to open geometry restart file for writing: ' // trim(str)
error stop

Copilot uses AI. Check for mistakes.
call free_restart_type(restart)
if (open_file(restart, str, "read", self%geom%Domain%mpp_domain)) then
call read_data(restart, 'h', h_common)
call close_file(restart)
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When remap_filename is provided, failing to open_file leaves h_common as all zeros and the code continues, which will produce incorrect vertical remapping results. Consider treating an open_file failure here as fatal (or at least emitting a clear error) since h_common is required for the remap path.

Suggested change
call close_file(restart)
call close_file(restart)
else
error stop "soca_fields_mod: failed to open remap_filename; common vertical coordinate 'h' is required for remapping"

Copilot uses AI. Check for mistakes.
Comment on lines 563 to +567
allocate(vars(n))

! for each variable, setup to read
! open the file for reading
if (.not. open_file(restart, filename, "read", self%geom%Domain%mpp_domain)) cycle

Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If open_file(restart, ...) fails, the code cycles after allocate(vars(n)) without deallocating vars, leaking memory and leaving partially-initialized state for the next loop iterations. Deallocate vars (and any nested allocations if added later) before cycle, or move the allocation to after a successful open_file call.

Copilot uses AI. Check for mistakes.
Comment on lines +990 to +1002
! open file, register fields, write, and close
if (open_file(restart, domain_filename, "overwrite", self%geom%Domain%mpp_domain, is_restart=.true.)) then
n=0
do f=1,size(self%fields)
if (self%fields(f)%metadata%io_file /= domains(d)) cycle
n = n + 1
if (vars(n)%afield%shape(1) == 1) then
call register_restart_field(restart, self%fields(f)%metadata%io_name, &
vars(n)%data(:,:,1), ["xaxis_1", "yaxis_1"])
else
call register_restart_field(restart, self%fields(f)%metadata%io_name, &
vars(n)%data(:,:,:), ["xaxis_1", "yaxis_1", "zaxis_1"])
end if
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

register_restart_field is called with axis names (xaxis_1, yaxis_1, zaxis_1) but this routine never registers those axes on the file object (unlike soca_geom_write, which calls register_axis). If fms2_io_mod does not auto-create these axes, this will fail at runtime or create malformed files. Register the required axes (including zaxis_1 when needed) before registering fields, and ensure the axis definitions (sizes/metadata) are consistent with the arrays being written.

Copilot uses AI. Check for mistakes.
call read_data(geom_restart, "mask2d", self%mask2d)
call read_data(geom_restart, "mask2du", self%mask2du)
call read_data(geom_restart, "mask2dv", self%mask2dv)
call close_file(geom_restart)
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If open_file(geom_restart, ...) fails, geometry arrays remain at their default/placeholder values and initialization continues, which can lead to hard-to-diagnose downstream errors. Consider handling the failure explicitly (e.g., abort with a clear message including the filename) rather than silently skipping the reads.

Suggested change
call close_file(geom_restart)
call close_file(geom_restart)
else
error stop "Failed to open geometry restart file for reading: " // trim(str)

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Update soca to fms_io v2

3 participants