Feel++ 0.91.0

Creating applications

Application and Options

As a Feel user, the first step in order to use Feel is to create an application. First we include the Application header file, feel/feelcore/application.hpp and the header which the internal Feel options. Feel uses the boost::program_options ( see Boost Program Options ) library from Boost to handle its command line options

//# marker1 #
#include <feel/options.hpp>
#include <feel/feelcore/feel.hpp>
#include <feel/feelcore/application.hpp>
//# endmarker1 #

Next to ease the programming and reading, we use the using C++ directive to bring the namespace Feel to the current namespace

  using namespace Feel;

Then we define the command line options that the applications will provide. Note that on the return line, we incorporate the options defined internally in Feel.

//# marker2 #
inline
po::options_description
makeOptions()
{
    po::options_description myappoptions("MyApp options");
    myappoptions.add_options()
        ("dt", po::value<double>()->default_value( 1 ), "time step value")
        ;

    // return the options myappoptions and the feel_options defined
    // internally by Feel
    return myappoptions.add( feel_options() );
}
//# endmarker2 #

In the example, we provide the options dt which takes an argument, a double and its default value is 1 if the options is not set by the command line.

Then we describe the application by defining a class AboutData which will be typically used by the help command line options to describe the application

//# marker3 #
inline
AboutData
makeAbout()
{
    AboutData about( "myapp" ,
                     "myapp" ,
                     "0.1",
                     "my first Feel application",
                     AboutData::License_GPL,
                     "Copyright (c) 2008 Universite Joseph Fourier");

    about.addAuthor("Christophe Prud'homme",
                    "developer",
                    "christophe.prudhomme@ujf-grenoble.fr", "");
    return about;
}
//# endmarker3 #

Now we turn to the class MyApp itself: it derives from Feel::Application. Two constructors take argc, argv and the AboutData as well as possibly the description of the command line options Feel::po::option_description.

The class MyApp must redefine the run() member function. It is defined as a pure virtual function in Application.

//# marker4 #
class MyApp: public Application
{
public:

    MyApp( int argc, char** argv, AboutData const& );

    MyApp( int argc, char** argv,
           AboutData const&,
           po::options_description const&  );

    void run();
};
//# endmarker4 #

The implementation of the constructors is usually simple, we pass the arguments to the super class Application that will analyze them and subsequently provide them with a Feel::po::variable_map data structure which operates like a map. Have a look at the document boost::program_options for further details.

//# marker5 #
MyApp::MyApp(int argc, char** argv,
             AboutData const& ad )
    :
    Application( argc, argv, ad )
{}
MyApp::MyApp(int argc, char** argv,
             AboutData const& ad,
             po::options_description const& od )
    :
    Application( argc, argv, ad, od )
{}
//# endmarker5 #

The MyApp::run() member function holds the application commands/statements. Here we provide the smallest code unit: we print the description of the application if the --help command line options is set.

//# marker6 #
void MyApp::run()
{
    if ( this->vm().count( "help" ) )
        {
            std::cout << this->optionsDescription() << "\n";
            return;
        }
    //# marker8 #
    this->changeRepository( boost::format( "doc/tutorial/%1%/" )
                            % this->about().appName() );
    //# endmarker8 #
    Log() << "the value of dt is " << this->vm()["dt"].as<double>() << "\n";
}
//# endmarker6 #

Finally the main() function can be implemented. We pass the results of the makeAbout() and makeOptions() to the constructor of MyApp as well as argc and argv. Then we call the MyApp::run() member function to execute the application.

//# marker7 #
int main( int argc, char** argv )
{
    Feel::Environment env( argc, argv );

    MyApp app( argc, argv, makeAbout(), makeOptions() );
    app.run();
}
//# endmarker7 #

Here is the full code

/* -*- mode: c++; coding: utf-8; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; show-trailing-whitespace: t -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4

  This file is part of the Feel library

  Author(s): Christophe Prud'homme <christophe.prudhomme@ujf-grenoble.fr>
       Date: 2008-02-04

  Copyright (C) 2008 Université Joseph Fourier (Grenoble I)

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
//# marker1 #
#include <feel/options.hpp>
#include <feel/feelcore/feel.hpp>
#include <feel/feelcore/application.hpp>
//# endmarker1 #

using namespace Feel;

//# marker2 #
inline
po::options_description
makeOptions()
{
    po::options_description myappoptions("MyApp options");
    myappoptions.add_options()
        ("dt", po::value<double>()->default_value( 1 ), "time step value")
        ;

    // return the options myappoptions and the feel_options defined
    // internally by Feel
    return myappoptions.add( feel_options() );
}
//# endmarker2 #


//# marker3 #
inline
AboutData
makeAbout()
{
    AboutData about( "myapp" ,
                     "myapp" ,
                     "0.1",
                     "my first Feel application",
                     AboutData::License_GPL,
                     "Copyright (c) 2008 Universite Joseph Fourier");

    about.addAuthor("Christophe Prud'homme",
                    "developer",
                    "christophe.prudhomme@ujf-grenoble.fr", "");
    return about;
}
//# endmarker3 #

//# marker4 #
class MyApp: public Application
{
public:

    MyApp( int argc, char** argv, AboutData const& );

    MyApp( int argc, char** argv,
           AboutData const&,
           po::options_description const&  );

    void run();
};
//# endmarker4 #

//# marker5 #
MyApp::MyApp(int argc, char** argv,
             AboutData const& ad )
    :
    Application( argc, argv, ad )
{}
MyApp::MyApp(int argc, char** argv,
             AboutData const& ad,
             po::options_description const& od )
    :
    Application( argc, argv, ad, od )
{}
//# endmarker5 #

//# marker6 #
void MyApp::run()
{
    if ( this->vm().count( "help" ) )
        {
            std::cout << this->optionsDescription() << "\n";
            return;
        }
    //# marker8 #
    this->changeRepository( boost::format( "doc/tutorial/%1%/" )
                            % this->about().appName() );
    //# endmarker8 #
    Log() << "the value of dt is " << this->vm()["dt"].as<double>() << "\n";
}
//# endmarker6 #

//# marker7 #
int main( int argc, char** argv )
{
    Feel::Environment env( argc, argv );

    MyApp app( argc, argv, makeAbout(), makeOptions() );
    app.run();
}
//# endmarker7 #

The next step is to compile it and execute it

make feel_doc_myapp
./feel_doc_myapp

The output should be

Application, Logging and Archiving

Feel provides some basic logging and archiving support: using the Application::changeRepository member functions of the class Application, the logfile and results of the application will be stored in a subdirectory of ~/feel. For example the following code

will create the directory ~/feel/myapp and will store the logfile and any files created after calling changeRepository. Refer to the documentation of Boost::format of further details about the arguments to be passed to Application::changeRepository. The logfile is named ~/feel/myapp/myapp-1.0. The name of the logfile is built using the application name, here myapp, the number of processes, here 1 and the id of the current process, here 0.

Parallel Application

Feel relies on MPI for parallel computations and the class Application initialises the MPI environment.

Initializing PETSc and Trilinos

Feel supports also the PETSc and Trilinos framework, the class takes care of initialize the associated environments.