Componentize Fortran model
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 /home/csdms/models/marssim/3.0.0/ > 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 "/home/csdms/cca/<project-name>/0.1/src/share/cmt/gui"
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 "/home/csdms/cca/<project-name>/0.1/src/share/cmt/in"
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: /home/csdms/models/marssim/3.0.0
cmake_minimum_required(VERSION 2.6) project (marssim) add_subdirectory (src)
The project subfolder should contain a detailed CMakeLists.xml as follows
Location: /home/csdms/models/marssim/3.0.0/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 /home/csdms/models/marssim/3.0.0/ > mkdir _build && cd _build > cmake .. -DCMAKE_INSTALL_PREFIX=/home/csdms/models/marssim/3.0.0/ > make -j8 && make install
To use:
> module load marssim > which run_marssim /home/csdms/models/marssim/3.0.0/bin/run_marssim > export LD_LIBRARY_PATH=/home/csdms/models/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/cmt/gui/marssim.xml ... Edit marssim.xml ...
8. Create a template input file.
> vi share/cmt/in/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=/home/csdms/models/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"