--- manual/s_phys_pkgs/text/packages.tex 2004/02/11 18:09:17 1.1 +++ manual/s_phys_pkgs/text/packages.tex 2004/10/12 18:16:03 1.4 @@ -1,7 +1,11 @@ -% $Header: /home/ubuntu/mnt/e9_copy/manual/s_phys_pkgs/text/packages.tex,v 1.1 2004/02/11 18:09:17 edhill Exp $ +% $Header: /home/ubuntu/mnt/e9_copy/manual/s_phys_pkgs/text/packages.tex,v 1.4 2004/10/12 18:16:03 edhill Exp $ % $Name: $ \section{Using MITgcm Packages} +\label{sec:pkg:using} +\begin{rawhtml} + +\end{rawhtml} The set of packages that will be used within a partiucular model can be configured using a combination of both ``compile--time'' and @@ -63,15 +67,178 @@ For run--time package control, MITgcm uses flags set through a \texttt{data.pkg} file. While some packages (\textit{eg.} -\texttt{debug}, \texttt{mnc}, \texttt{cost}) may have their own -conventions, most follow a simple flag naming convention of the -form: +\texttt{debug}, \texttt{mnc}, \texttt{exch2}) may have their own usage +conventions, most follow a simple flag naming convention of the form: \begin{verbatim} usePackageName=.TRUE. \end{verbatim} where the \texttt{usePackageName} variable can activate or disable the -package at runtime. +package at runtime. As mentioned previously, packages must be +included in order to be activated. Generally, such mistakes will be +detected and reported as errors by the code. However, users should +still be aware of the dependency. -%\subsection{Modifying or Creating Packages} +\section{Package Coding Standards} + +The following sections describe how to modify and/or create new MITgcm +packages. + +\subsection{Packages are Not Libraries} + +To a beginner, the MITgcm packages may resemble libraries as used in +myriad software projects. While future versions are likely to +implement packages as libraries (perhaps using FORTRAN90/95 syntax) +the current packages (FORTRAN77) are \textbf{not} based upon any +concept of libraries. + +\subsubsection{File Inclusion Rules} + +Instead, packages should be viewed only as directories containing +``sets of source files'' that are built using some simple mechanisms +provided by \texttt{genmake2}. Conceptually, the build process adds +files as they are found and proceeds according to the following rules: +\begin{enumerate} +\item \texttt{genmake2} locates a ``core'' or main set of source files + (the \texttt{-standarddirs} option sets these locations and the + default value contains the directories \texttt{eesupp} and + \texttt{model}). + +\item \texttt{genmake2} then finds additional source files by + inspecting the contents of each of the package directories: + \begin{enumerate} + \item As the new files are found, they are added to a list of source + files. + + \item If there is a file name ``collision'' (that is, if one of the + files in a package has the same name as one of the files + previously encountered) then the file within the newer (more + recently visited) package will superseed (or ``hide'') any + previous file(s) with the same name. + + \item Packages are visited (and thus files discovered) {\it in the + order that the packages are enabled} within \texttt{genmake2}. + Thus, the files in \texttt{PackB} may superseed the files in + \texttt{PackA} if \texttt{PackA} is enabled before \texttt{PackB}. + Thus, package ordering can be significant! For this reason, + \texttt{genmake2} honors the order in which packages are + specified. + \end{enumerate} +\end{enumerate} + +These rules were adopted since they provide a relatively simple means +for rapidly including (or ``hiding'') existing files with modified +versions. + +\subsubsection{Conditional Compilation and \texttt{PACKAGES\_CONFIG.h}} + +Given that packages are simply groups of files that may be added or +removed to form a whole, one may wonder how linking (that is, FORTRAN +symbol resolution) is handled. This is the second way that +\texttt{genmake2} supports the concept of packages. Basically, +\texttt{genmake2} creates a \texttt{Makefile} that, in turn, is able +to create a file called \texttt{PACKAGES\_CONFIG.h} that contains a set +of C pre-processor (or ``CPP'') directives such as: +\begin{verbatim} + #undef ALLOW_KPP + #undef ALLOW_LAND + ... + #define ALLOW_GENERIC_ADVDIFF + #define ALLOW_MDSIO + ... +\end{verbatim} +These CPP symbols are then used throughout the code to conditionally +isolate variable definitions, function calls, or any other code that +depends upon the presence or absence of any particular package. + +An example illustrating the use of these defines is: +\begin{verbatim} + #ifdef ALLOW_GMREDI + IF (useGMRedi) CALL GMREDI_CALC_DIFF( + I bi,bj,iMin,iMax,jMin,jMax,K, + I maskUp, + O KappaRT,KappaRS, + I myThid) + #endif +\end{verbatim} +which is included from the file +\filelink{calc\_diffusivity.F}{model-src-calc_diffusivity.F} +and shows how both the compile--time \texttt{ALLOW\_GMREDI} flag and the +run--time \texttt{useGMRedi} are nested. + +There are some benefits to using the technique described here. The +first is that code snippets or subroutines associated with packages +can be placed or called from almost anywhere else within the code. +The second benefit is related to memory footprint and performance. +Since unused code can be removed, there is no performance penalty due +to unnecessary memory allocation, unused function calls, or extra +run-time \texttt{IF (...)} conditions. The major problems with this +approach are the potentially difficult-to-read and difficult-to-debug +code caused by an overuse of CPP statements. So while it can be done, +developers should exerecise some discipline and avoid unnecesarily +``smearing'' their package implementation details across numerous +files. + + +\subsubsection{Package Startup or Boot Sequence} + +Calls to package routines within the core code timestepping loop can +vary. However, all packages should follow a required "boot" sequence +outlined here: + +{\footnotesize +\begin{verbatim} + 1. S/R PACKAGES_BOOT() + : + CALL OPEN_COPY_DATA_FILE( 'data.pkg', 'PACKAGES_BOOT', ... ) + + + 2. S/R PACKAGES_READPARMS() + : + #ifdef ALLOW_${PKG} + if ( use${Pkg} ) + & CALL ${PKG}_READPARMS( retCode ) + #endif + + 3. S/R PACKAGES_INIT_FIXED() + : + #ifdef ALLOW_${PKG} + if ( use${Pkg} ) + & CALL ${PKG}_INIT_FIXED( retCode ) + #endif + + 4. S/R PACKAGES_CHECK() + : + #ifdef ALLOW_${PKG} + if ( use${Pkg} ) + & CALL ${PKG}_CHECK( retCode ) + #else + if ( use${Pkg} ) + & CALL PACKAGES_CHECK_ERROR('${PKG}') + #endif + + 5. S/R PACKAGES_INIT_VARIABLES() + : + #ifdef ALLOW_${PKG} + if ( use${Pkg} ) + & CALL ${PKG}_INIT_VARIA( ) + #endif + + 6. S/R DO_THE_MODEL_IO + + #ifdef ALLOW_${PKG} + if ( use${Pkg} ) + & CALL ${PKG}_DIAGS( ) + #endif + + 7. S/R PACKAGES_WRITE_PICKUP() + + #ifdef ALLOW_${PKG} + if ( use${Pkg} ) + & CALL ${PKG}_WRITE_PICKUP( ) + #endif\end{verbatim} +} + + +\subsubsection{Package Startup or Boot Sequence}