Feel++ 0.91.0
|
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> #include <feel/feelalg/backend.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() ).add( backend_options( "myapp" ) ); } //# 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; } //# 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> #include <feel/feelalg/backend.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() ).add( backend_options( "myapp" ) ); } //# 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; } //# endmarker6 # //# marker8 # this->changeRepository( boost::format( "doc/tutorial/%1%/" ) % this->about().appName() ); //# endmarker8 # Log() << "the value of dt is " << this->vm()["dt"].as<double>() << "\n"; Log() << "the value of myapp-solver-type is " << this->vm()["myapp-ksp-type"].as<std::string>() << "\n"; Log() << "the value of myapp-pc-type is " << this->vm()["myapp-pc-type"].as<std::string>() << "\n"; } //# 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
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.
Feel relies on MPI for parallel computations and the class Application
initialises the MPI environment.
Feel supports also the PETSc and Trilinos framework, the class takes care of initialize the associated environments.