5.2. Icepack Column Physics¶
5.2.1. File List¶
The column physics source code contains the following files
5.2.2. Coding Standard¶
The column physics is a library that solves the sea ice column physics on a timestep by timestep and gridpoint by gridpoint basis. It consists of Fortran routines with input and output arguments. The model state is saved in the host model. There is no communication between gridcells so the underlying implementation supports no parallelization. It however can be called in parallel by a driver that is running on multiple pes with a decomposed grid.
The column physics does not have a time manager. Calendaring is expected to be dealt with by the host model. The column physics does not read any forcing data, that is passed into the column physics though interfaces. In fact, there are no direct IO capabilities in the column physics. That is to say, the column physics does not open files to read or write. The column physics is able to write data via several different routines that specifically have a fortran unit number as an input argument. In addition, there is a warning and abort package (see section Error Messages and Aborts) that provides the column package with the ability to store log output. That output can be queried by the host model or it can be written directly via a specific routine. The warning package also provides access to an abort flag that the host model can query after each call to check for successful completion of the column physics package.
All column physics public interfaces and public data are defined in the icepack_intfc.F90 file (see section Access). Internal column physics settings should all be accessible through interfaces. The internal constants, parameters, and tracer settings have init (set), query (get), and write interfaces that provides access to internal column physics settings. The host model should not have to use “use” statements to access any of the column physics data outside of what is provided through the icepack_intfc module. The public column physics interfaces use optional arguments where it makes sense and there is an ongoing effort to extend the optional arguments supported. It’s strongly recommended that calls to the icepack interfaces be done with keyword=value arguments. All icepack arguments support this method.
Overall, columnphysics changes in the Icepack model should include the following
All modules should have the following set at the top
implicit none privateAny public module interfaces or data should be explicitly specified
All subroutines and functions should define the subname character parameter statement to match the interface name like
character(len=*),parameter :: subname='(lateral_melt_bgc)'All interfaces that are public outside the Icepack columnphysics should include autodocument_start and autodocument_end comment lines with appropriate syntax and location. If any interfaces are added or updated, then the internal documentation should be updated via
./icepack.setup --docintfcSee also Public Interfaces for more information about the docintfc option.
The icepack_warnings package should be used to cache log messages and set the abort flag. To add a log message, use icepack_warnings_add like
call icepack_warnings_add(subname//' algorithm did not converge')To formally set the abort flag, use
call icepack_warnings_setabort(.true.,__FILE__,__LINE__)See also Error Messages and Aborts for more information about how the external calling program will write those message and check whether Icepack aborted.
Every interface call within the columnphysics should be followed by
if (icepack_warnings_aborted(subname)) returnto support errors backing up the call tree to the external program
Variables defined in icepack_kinds, icepack_tracers, icepack_parameters, and icepack_orbital should be accessed within Icepack by Fortran use statements. It’s also possible to access some of those variables thru methods that query for the value, but this tends to be a little more cumbersome, so Fortran use statements are recommended within columnphysics. From the icepack driver or other external programs, the columnphysics variables should ALWAYS be access thru the interface methods and icepack_intfc (see also Access).
Optional arguments are encouraged in the public Icepack interfaces but should generally be avoided in interfaces within the columnphysics. There are several reasons for taking this approach. There is a desire to support backwards compatible Icepack public interfaces as much as possible, so optional arguments will be used for some future extensions. There is also a desire to allow users to pass only the data thru the Icepack interfaces that is needed. To support optional tracers and features, optional arguments are needed. Within the internal columnphysics calling tree, optional arguments are discouraged because they tend to add complexity to deep calling trees and often lead to implementations with many calls to the same interface that only vary by which arguments are passed. In the long term, that approach is not sustainable. As a result, a scheme has been developed to support optional arguments in the public interfaces while minimizing optional arguments within the columphysics. Within the columnphysics, we suggest optional arguments available thru the public interfaces should generally be treated as follows
Check whether optional arguments are passed and create temporary data to store the values
The temporary data should be locally name l_${argument_name}
The temporary data should be allocated at runtime if it’s not a scalar based on the size of the incoming argument
The optional argument values should be copied into the temporary data
The temporary data should be passed thru other columnphysics subroutines
The temporary data should be deallocated at the end of the method if it was allocated
The temporary data should be copied back to the argument if the argument intent is out or inout
If optional arguments are not passed, temporary data should be created of size 1 with values of c0, and they should be passed thru other columnphysics subroutines
A logical can be instantiated and passed down the columnphysics interface to manage any logic related to whether valid or fake data is being passed down the calling tree. See closing_flag and iso_flag within the columnphysics as examples. There may also be externally set logicals that can be used to control how the optional features are handles. See tr_iso within the columnphysics as an example.
An example of how this might look is
subroutine icepack_example_interface(arg1, arg2, ...) real (kind=dbl_kind), intent(inout) :: arg1 real (kind=dbl_kind), optional, dimension(:), intent(inout) :: arg2 ! real (kind=dbl_kind), allocatable, dimension(:) :: l_arg2 logical :: arg2_flag character(len=*), parameter :: subname = '(icepack_example_interface)' if (present(arg2)) then arg2_flag = .true. allocate(l_arg2(size(arg2))) l_arg2 = arg2 else arg2_flag = .false. allocate(l_arg2(1)) l_arg2 = c0 endif ... call some_columnphysics_subroutine(arg1, l_arg2, arg2_flag, ...) ... if (present(arg2)) then arg2 = l_arg2 endif deallocate(l_arg2) return end subroutine