Difference between revisions of "Flexible precision in GEOS-Chem"
(→) |
(→) |
||
Line 1: | Line 1: | ||
== Overview == | == Overview == | ||
− | === === | + | === Flexible precision was introduced in Fortran 90=== |
− | + | In most existing Fortran codes (including GEOS-Chem) you will see declarations such as: | |
! Integers | ! Integers | ||
Line 15: | Line 15: | ||
REAL*8 :: E, F ! 8-byte floating point | REAL*8 :: E, F ! 8-byte floating point | ||
− | etc. | + | etc. Note that |
− | + | ||
− | Note that | + | |
#On most compilers, <tt>INTEGER</tt> refers to a 4-byte integer. You can make this default to an 8-byte integer by compiling with <tt>-i8</tt>. In most circumstances it is OK to use 4-byte integers, unless you need to point to a memory location or are reading an 8-byte integer from a netCDF file. | #On most compilers, <tt>INTEGER</tt> refers to a 4-byte integer. You can make this default to an 8-byte integer by compiling with <tt>-i8</tt>. In most circumstances it is OK to use 4-byte integers, unless you need to point to a memory location or are reading an 8-byte integer from a netCDF file. | ||
Line 23: | Line 21: | ||
#In some older Fortran codes, you will see the term <tt>DOUBLE PRECISION</tt>. This is the same as <tt>REAL*8</tt> -- it is an 8-byte floating point. | #In some older Fortran codes, you will see the term <tt>DOUBLE PRECISION</tt>. This is the same as <tt>REAL*8</tt> -- it is an 8-byte floating point. | ||
− | You can replace these with [https://www.nsc.liu.se/~boein/f77to90/c13.html declarations of arbitrary precision]. This is done with the <tt>SELECTED_REAL_KIND</tt> and <tt>SELECTED_INT_KIND</tt> functions, [https://www.nsc.liu.se/~boein/f77to90/a5.html#section6 which are described in more detail here]. | + | Fortran 90 introduced a new precision concept. You can replace these fixed data type with [https://www.nsc.liu.se/~boein/f77to90/c13.html declarations of arbitrary precision]. This is done with the <tt>SELECTED_REAL_KIND</tt> and <tt>SELECTED_INT_KIND</tt> functions, [https://www.nsc.liu.se/~boein/f77to90/a5.html#section6 which are described in more detail here]. |
+ | |||
+ | --[[User:Bmy|Bob Y.]] 15:01, 7 November 2014 (EST) | ||
=== Why are we implementing flexible precision in GEOS-Chem === | === Why are we implementing flexible precision in GEOS-Chem === |
Revision as of 20:01, 7 November 2014
Contents
Overview
Flexible precision was introduced in Fortran 90
In most existing Fortran codes (including GEOS-Chem) you will see declarations such as:
! Integers INTEGER :: I, J ! 4-byte integer INTEGER*4 :: K, L ! 4-byte integer INTEGER*8 :: M, N ! 8-byte integer ! Floating point REAL :: A, B ! 4-byte floating point REAL*4 :: C, D ! 4-byte floating point REAL*8 :: E, F ! 8-byte floating point
etc. Note that
- On most compilers, INTEGER refers to a 4-byte integer. You can make this default to an 8-byte integer by compiling with -i8. In most circumstances it is OK to use 4-byte integers, unless you need to point to a memory location or are reading an 8-byte integer from a netCDF file.
- On most compilers, REAL refers to a 4-byte floating-point. You can make this default to an 8-byte floating point by compiling with -r8.
- In some older Fortran codes, you will see the term DOUBLE PRECISION. This is the same as REAL*8 -- it is an 8-byte floating point.
Fortran 90 introduced a new precision concept. You can replace these fixed data type with declarations of arbitrary precision. This is done with the SELECTED_REAL_KIND and SELECTED_INT_KIND functions, which are described in more detail here.
--Bob Y. 15:01, 7 November 2014 (EST)
Why are we implementing flexible precision in GEOS-Chem
This will
What is often more useful is not to define an arbitrary precision, but to have the ability to declare the same variable with 4-byte precision under some circumstances and 8-byte precision under other circumstances. An example of this is that the traditional "serial" GEOS-Chem has always used 8-byte floating point variables, but we would need to make these 4-byte floating points when running GEOS-Chem within the GEOS-5 GCM.
Methodologoy
Here is an example of how you can do this:
1. Define a module named precision_mod.F. You can place this in the Headers directory. This will define a parameter that will be used to specify the precision of variables in other parts of the code.
MODULE PRECISION_MOD IMPLICIT NONE PRIVATE #if defined( USE_REAL8 ) ! Use 8-byte floating point precision when asked for it INTEGER, PARAMETER, PUBLIC :: fp = KIND( 0.d0 ) #else ! Use 4-byte floating point precision by default INTEGER, PARAMETER, PUBLIC :: fp = KIND( 0.0 ) #endif END MODULE PRECISION_MOD
Instead of having to figure out the proper settings with SELECTED_REAL_KIND, we can just use the KIND command to return that for us. KIND( 0.d0 ) returns the proper "kind" value to define an 8-byte floating point, and KIND( 0.0 ) returns the proper "kind" value for us to define a 4-byte floating point. This value is saved in the constant named fp.
Also note that we have used an #if defined block to define the value of FP. If we compile with -DUSE_REAL8, then the fp can be used to declare 8-byte floating-point variables. Otherwise, fp can be used to declare 4-byte variables by default.
2. In the Makefille_header.mk, we need to add the -DUSE_REAL8 flag to the FFLAGS variable. FFLAGS contains the set of compiler switches and preprocessor statements used to compile GEOS-Chem. This can be done by looking for the following ifeq statement. Add the following lines in RED. This has to be done in both the IFORT section and in the PGI section of Makefile_header.mk
- Add include options for ESMF & MAPL
ifeq ($(HPC),yes) INCLUDE += $(MAPL_INC) $(ESMF_MOD) $(ESMF_INC) else FFLAGS += -DUSE_REAL8 endif
3. Add precision_mod.F to the dependencies listing in the Headers/Makefile. Add this line:
precision_mod.o: precision_mod.F90
4. At the top of each GEOS-Chem module or routine (typically in the !USES: comment section), you can place a reference to precision_mod.F. For example, at the top of GeosCore/carbon_mod.F, you would add the line in RED:
!------------------------------------------------------------------------------ ! GEOS-Chem Global Chemical Transport Model ! !------------------------------------------------------------------------------ !BOP ! ! !MODULE: carbon_mod ! ! !DESCRIPTION: Module CARBON\_MOD contains arrays and routines for performing ! a carbonaceous aerosol simulation. Original code taken from Mian Chin's ! GOCART model and modified accordingly. (rjp, bmy, 4/2/04, 6/30/10) !\\ !\\ ! !INTERFACE: !
MODULE CARBON_MOD
! ! !USES: ! !
USE HCO_ERROR_MOD ! For real precisions (hp) USE PRECISION_MOD ! For GEOS-Chem precision (fp)
IMPLICIT NONE PRIVATE
Note that HEMCO has its own precision parameters. We'll leave those alone, because HEMCO ships as a separate package as well.
5. Look for all variables in the module that are declared as REAL*8. Replace the REAL*8 text with REAL(fp) instead. So these lines:
REAL*8, ALLOCATABLE :: ANTH_BLKC(:,:,:) REAL*8, ALLOCATABLE :: ANTH_ORGC(:,:,:) REAL*8, ALLOCATABLE :: BIOB_BLKC(:,:,:)
would become
REAL(fp), ALLOCATABLE :: ANTH_BLKC(:,:,:) REAL(fp), ALLOCATABLE :: ANTH_ORGC(:,:,:) REAL(fp), ALLOCATABLE :: BIOB_BLKC(:,:,:)
6. IMPORTANT NOTE! Any literal constants in scientific notation made with the Fortran "d" exponents have to be changed to "e". Also, the text _fp has to be appended to the exponent. This tells Fortran that we are using a customized precision definition. For example, the code:
! Molecules OH per kg OH [molec/kg] REAL*8, PARAMETER :: XNUMOL_OH = 6.022d23 / 17d-3 REAL*8, PARAMETER :: CM3PERM3 = 1.d6
would become instead:
! Molecules OH per kg OH [molec/kg] REAL(fp), PARAMETER :: XNUMOL_OH = 6.022e+23_fp / 17e-3_fp REAL(fp), PARAMETER :: CM3PERM3 = 1.e+6_fp
Also, probably for good style, we should use a + sign to denote a positive exponent. The + sign is optional for positive numbers, but it is good style to add it.
7. Repeat the process in steps 4-6 for each GEOS-Chem source code file. It is good practice to modify one module or file at a time, and the run a GEOS-Chem difference test. Then continue.