Componentize Fortran model

From CSDMS
Revision as of 12:27, 11 August 2011 by Kallumad (talk | contribs)

Component Wrapping

Fortran

Fortran is one of the oldest programming languages devised, but it is also still one of the most popular, especially among engineers and applied scientists. It was developed in the 1950's at IBM. Part of the reason for Fortran's durability is that it is particularly well-suited for mathematical programming; moreover, there are millions of useful programs written in Fortran, created at considerable time and expense, and understandably people are reluctant to trash these old programs and switch to a new programming language. The name Fortran originally referred to "Formula Translation", but it has long since taken on its own meaning. There are several versions of Fortran around, among them Fortran 77, Fortran 90, and Fortran 95.

PS: Example used to describe the wrapping process is MARSSIM model from CSDMS repository.

IRF your code

Get the source code:

Fetch the source:

 > wget http://csdms.colorado.edu/pub/models/marssim/marssim-3.0.0.tar.gz

Unpack the source:

 > cp marssim-3.0.0.tar.gz /data/progs/marssim/src
 > tar xvfz marssim-3.0.0.tar.gz

To wrap your code to a CCA component it has to be CCA compliant, IRF'd!. This means that the main program should have an "I"nitialize, "R"un and "F"inalize.

From my understanding,

   "I"nitialize, as the name says should initializes all the required variables and does all the Read.
   "R"un, should be the code which is the core of your program. This is where all the calculations are done. In case of Fortran this will be mostly a loop starting (L200: DO  .... ENDDO L200) like this.
   "F"inalize, is the final steps of your code where all writing (outputs) and end wrapping will be done

My notes:

   Create a module say "irf"
   Declare the variables shared between IRF
   Create 3 subroutines Initialize, Run and Finalize
   Create main.f90. If this works then your code is IRF'd!

PROGRAM MARSSIM

   USE MARSSIM_IRF
   IMPLICIT NONE
   !Call IRF subroutines
   CALL INITIALIZE
   CALL RUN
   CALL FINALIZE

END PROGRAM MARSSIM

XML for CMT tab dialogs (Config)

Every model has an input file which will be read by the model to do the calculation. In CCA world, this will the config port on each component which contains the input data for the component. This is where the user can change the input according to his needs.

How the input data file will be shown on the tab dialogs(config port): An XML file will be created from the input file which will be parsed to be displayed on the dialogs as Label, Range, Value etc. The format is as follows

  <dialog>
   <tab name="Project">
       <entry name="/MARSSIM/Input/Var/ISEED">
           <label>Random seed:</label>
           <help_brief>A integer random seed</help_brief>
           <default>4632819</default>
           <type>Int</type>
           <range>
               <min>?</min>
               <max>?</max>
           </range>
       </entry>
       ...
   </tab>
   ...
 </dialog>

Location will be "/data/progs/components/<project-name>/projects"

Create Input Template

This will be a copy of the input file of the project with 2 changes to the files: The name of the file should be ending with "*.in" where "*" is the full name of your input file. Example: Input file "marssim.prm" should be renamed to "marssim.prm.in" Each input data in the file should be renamed with their specific variable name. As an example the following line of the input file should be replaced as follows:

   > 4632819        - ISEED                                                   -->           ${ISEED}        - ISEED

Location will be "/data/progs/components/<project-name>/share/templates"

Create Shared library

As a newcomer to C and Fortran the best thing I learned was about cmake (Refer: http://www.cmake.org/). Creation of make files sounded kind of complicated to me and I must say I haven't digged much into it. Cmake does the job of creating make files for your project and the syntax for creating CmakeLists.txt was relatively simple especially if you get an example file to start with. Steps are as follows: Create a "CmakeLists.txt" in your main project folder. This should contain a path to your project source files.

Location: /data/progs/marssim/

 >cmake_minimum_required(VERSION 2.6)
 >project (marssim)
 >add_subdirectory (src)

The project subfolder should contain a detailed CMakeLists.xml as follows

Location: /data/progs/marssim/src

   cmake_minimum_required (VERSION 2.6)
   enable_language (Fortran)
   set (MODEL marssim)
   set (BUILD_SHARED_LIBS ON)
   set (CMAKE_Fortran_FLAGS -ffree-line-length-none)
   set (marssim_srcs
    program_global_variables.f90
    <list all *.f90 files here>
    main.f90)
   add_library (${MODEL} ${marssim_srcs})
   add_executable (run_${MODEL} ${marssim_srcs})
   target_link_libraries (marssim m)
   install (TARGETS run_${MODEL} RUNTIME DESTINATION bin)
   install (TARGETS ${MODEL} DESTINATION lib)
   install (FILES
       ${PROJECT_BINARY_DIR}/src/accretion_globals.mod
      <list all *.mod file here.>
       DESTINATION include)

Now follow these steps to create the make file

Load modules:

 > module load gcc/4.3
 > module load cmake

Configure and make:

 > cd /data/progs/marssim/
 > mkdir _build && cd _build
 > cmake .. -DCMAKE_INSTALL_PREFIX=/data/progs/marssim/3.0.0
 > make -j8 && make install

To use:

 > module load marssim
 > which run_marssim
 /data/progs/marssim/3.0.0/bin/run_marssim
 > export LD_LIBRARY_PATH=/data/progs/marssim/3.0.0/lib:$LD_LIBRARY_PATH
Test it before wraping

Run the executable

   > 3.0.0/bin/run_marssim

Wrap the component

1. Checkout the latest version of the CMT components. I haven't done this here but you may want to create a branch for your edits and merge them into the trunk when you are done.

   > module load subversion
   > svn co https://csdms.colorado.edu/svn/components/trunk my_components

2. Create an XML description of your new component. These are kept in the projects directory.

   > cd my_components/projects
   > cp ROMS.xml marssim.xml
   ... Edit marssim.xml ...

3. Add a marssim target to CMakeLists.txt so that you can build it.

   > cd my_components
   ... Edit CMakeLists.txt

4. Build the bocca project

   > module load cmake
   > module load cca
   > module load csdms
   > cd my_components
   > mkdir _build && cd _build
   > cmake .. -DMODULE_NAME=marsim
   > make marssim

5. Create your component.

   > cd csdms
   > bocca create component edu.csdms.models.Marssim (not necessary)

6. Add the implementation. For this step it will probably be useful to have a look at the implementation for the ROMS component. You'll need to add implementation for setServices, go, initialize, run, and finalize.

7. Create an XML description of your configure dialog.

   > vi share/config/marssim.xml
   ... Edit marssim.xml ...

8. Create a template input file.

   > vi share/templates/MARSSIM.PRM
   ... Edit MARSSIM.PRM.in ...

9. Build the project and check that everything instantiates correctly.

   > cd my_components/_build/csdms
   > ./configure
   > make
   > module load ../marssim
   > export LD_LIBRARY_PATH=/data/progs/marssim/3.0.0/lib:$LD_LIBRARY_PATH
   > make check

10. To use the model in CMT, you'll have to edit bocca-gui-backend.sh in your bocca project. When you ran cmake, a new one should have been created for you in your build directory.

   > cd my_components/_build
   > cp bocca-gui-backend.sh csdms/utils

SVN

Commit

svn commit -m "<message text>"

ex: svn commit -m "Saving marssim changes"