-
Notifications
You must be signed in to change notification settings - Fork 6
Software Development Practices
CICE Consortium Member representatives and community developers should strive to incorporate these practices throughout the development process, to the extent possible:
- Define tasks of team members ahead of time, including coordination roles
- Utilize a common communication space for chats and discussions
- Work in shared repositories
- Adhere to the documentation strategy
- Provide concise comments throughout the code
- Write readable guides for build/run and a scientific overview
- Deposit namelist settings, confidence scores and other documentation for tested and validated configurations in the repository
- Document and track requirements and issues
- Describe code changes and their effects on performance and physical result
- Document “lessons learned” e.g. configuration errors, compiler errors, software versions and dependencies, FAQ, etc
- Manage code dependencies
- Practice Test-Driven Development
- Develop tests first and upgrade them as the software development evolves
- Automate as much as possible
- Run standard testing suite regularly
- Practice version control on shared branches
- Check in only working code (i.e. does not crash or give unexplainable results)
- Check in only necessary code changes in minimal chunks (one “fix” at a time)
- Maintain unedited, reproducible tagged and released versions
- Practice continuous integration
- Frequent check-ins to the common repository
- Frequent updates of private development branches from public branches
- Automated testing
- Provide frequent technical and scientific reviews of
- Automated test suite
- Source code
- Documentation
- New features implemented with namelist (off by default)
- Bit-for-bit expectations
- Test summary
- Changes needed in test coverage
- Tag and release code frequently
- Choose a simple design
- Adhere to the current coding and naming conventions
- See the CICE module ice_state.F90 for category conventions
- See table below for file naming conventions
- Write readable code
- Use meaningful variable names
- Indent 2 or 3 spaces for loops, conditionals, etc
- Vertically align similar elements where it makes sense
- Provide concise comments throughout the code
- Write efficient code
- Use intrinsic functions or mathematical constructs instead of conditional statements, where possible
- Monitor performance changes throughout development
- Make interfaces modular
- Pass most variables and constants through subroutine arguments instead of use statements
- Declare most constants in shared modules, do not hard-wire constants
- Adhere to the icepack interface standards including no use statements of icepack columnphysics data outside icepack columnphysics, all icepack columnphysics public data and interfaces are defined in icepack_intfc.F90, and icepack interfaces should be backwards compatible as much as possible.
- Maintain bit-for-bit output from the default configuration (to the extent possible) via namelist flags
- Maintain global conservation of heat, water, salt
- C preprocessor (CPP) directives should be used primarily for build dependent modifications such as use of netcdf (or other "optional" libraries) or for various Fortran features that may not be supported by some compilers. Use namelist to support run-time code options. CPPs should be all caps.
CICE and Icepack file naming convention | |
---|---|
CICEcore modules | ice_*.F90 |
CICEcore namelist | ice_in |
Icepack driver modules | icepack_drv*.F90 |
Icepack namelist | icepack_in |
Icepack public interface module | icepack_intfc*.F90 |
Icepack modules | icepack_*.F90 |
The following code acceptance testing criteria must be completed for consideration of a pull request to the Consortium repositories:
-
Icepack-only contribution:
- Code contributor must run the Icepack base_suite with at least 1 compiler; all tests must PASS.
- If all tests PASS, then run the CICE quick_suite with at least one compiler; all tests must PASS.
-
CICE contributions:
- If there are changes in Icepack, perform step 'i' above.
- Run the CICE base_suite with at least 1 compiler; all tests must PASS.
- If all tests do not pass, then perform QC testing to classify the changes
In some instances, a new physics parameterization etc. may require a more thorough investigation of the model output to determine if the model is performing appropriately.
Icepack and CICE are currently based on the Fortran 95 coding standard. Use of newer Fortran features needs to be balanced with the desire to compile on as many systems and compilers as possible. Lags exist because as new standards are introduced, compilers are slowly updated and become robust over time and then systems install new compilers on varied schedules. In some sense, for portability, the models need to be coded to the lowest robust compiler implementation standard expected to be installed on all systems. New Fortran features can be used in Icepack and CICE if they demonstrate a benefit in performance or coding, and they are highly likely to be robustly implemented in all compilers in a typical system installation. Developers are encouraged to contact the Consortium as early as possible to discuss inclusion of new Fortran coding features if there are questions. The models are regularly tested on multiple systems with multiple compilers to ensure the portability standard is maintained.
In the same way, new features in external software packages such as NetCDF, MPI, or OpenMP should be avoided until the features can be expected to be robustly available on all systems. Again, if there are any questions, developers are encouraged to contact the Consortium as early as possible to discuss.
External libraries such as NetCDF, MPI, BLAS, PIO, Trilinos or LAPACK will be supported in Icepack and CICE when appropriate. Developers are encouraged to contact the Consortium as early as possible to discuss requirements and implementation. As much as possible, external libraries should be limited to particular kernels or algorithms within the model and should be optional. The code can be protected with preprocessor macros, and alternative implementations or aborts should be included when the external library is not available. The goal is to allow the CICE and Icepack models to compile and run without the external library, even if a subset of algorithms cannot. In general, external libraries should be installed separately from Icepack and CICE. Implementation details related to the build such as preprocessor directives and library linking may need to be addressed on a machine by machine basis thru the env and Macros files.
16 January 2017: Initial draft
1 July 2017: Dated for public posting
28 August 2018: Updates for testing practices
03 June 2020: Add Section on external libraries and new compiler features