https://github.com/feelpp/feelpp
Raw File
Tip revision: fab9457f5df733f809b27a28186ca3c21754412e authored by Christophe Prud'homme on 26 April 2019, 07:40:37 UTC
Fixes #1320
Tip revision: fab9457
test_element_serialize.cpp
/* -*- 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=cpp:et:sw=4:ts=4:sts=4

  This file is part of the Feel library

  Author(s): Stephane Veys <stephane.veys@imag.fr>
       Date: 2012-06-30

  Copyright (C) 2008-2010 Universite 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/>.
*/
/**
   \file test_element_serialize.cpp
   \author Stephane Veys <stephane.veys@imag.fr>
   \date 2012-06-30
*/

#define BOOST_TEST_MODULE test_element_serialize
#include <feel/feelcore/testsuite.hpp>

#include <fstream>

#include <boost/tuple/tuple.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/list.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/version.hpp>
#include <boost/serialization/split_member.hpp>

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

#include <feel/feelcore/serialization.hpp>
#include <feel/feeldiscr/region.hpp>
#include <feel/feelfilters/creategmshmesh.hpp>
#include <feel/feelfilters/domain.hpp>
#include <feel/options.hpp>
#include <feel/feeltiming/tic.hpp>
#include <feel/feeldiscr/functionspace.hpp>
#include <feel/feelpoly/polynomialset.hpp>
#include <feel/feelvf/vf.hpp>

/** use Feel namespace */
using namespace Feel;
using namespace Feel::vf;


inline
po::options_description
makeOptions()
{
    po::options_description testelementserializeoptions( "TestElementSerialize options" );
    testelementserializeoptions.add_options()
        ( "hsize", po::value<double>()->default_value( 0.2 ), "mesh size" )
        ( "shape", Feel::po::value<std::string>()->default_value( "simplex" ), "shape of the domain (either simplex or hypercube)" )
        ( "nb_element", po::value<int>()->default_value( 2 ), "number of elements of the vector" )
        ;
    return testelementserializeoptions.add( Feel::feel_options() );
}


inline
AboutData
makeAbout()
{
    AboutData about( "test_element_serialize" ,
                     "test_element_serialize" ,
                     "0.2",
                     "nD(n=1,2,3) test serialization of element_type ( single and vector )",
                     Feel::AboutData::License_GPL,
                     "Copyright (c) 2008-2009 Universite Joseph Fourier" );

    about.addAuthor( "Stephane Veys", "developer", "stephane.veys@imag.fr", "" );
    return about;

}


template<int Dim>
class TestElementSerialize
    :
public Simget
{
    typedef Simget super;
public:

    static const uint16_type Order = 1;

    typedef double value_type;
    typedef Simplex<Dim> convex_type;
    typedef Mesh<convex_type> mesh_type;
    typedef std::shared_ptr<mesh_type> mesh_ptrtype;
    typedef bases<Lagrange<Order,Scalar> > basis_type;
    typedef FunctionSpace<mesh_type, basis_type> space_type;
    typedef typename space_type::element_type element_type;
    /**
     * Constructor
     */
    TestElementSerialize( bool rebuild_database )
        :
        super(),
        M_meshSize( this->vm()["hsize"].template as<double>() ),
        M_shape( this->vm()["shape"].template as<std::string>() ),
        M_nb_element( this->vm()["nb_element"].template as<int>() ),
        M_rebuild_database( rebuild_database )
    {
    }

    void run();
    void run( const double* X, unsigned long P, double* Y, unsigned long N );

    void saveDB();
    void loadDB();
    fs::path dbPath();

    friend class boost::serialization::access;

    BOOST_SERIALIZATION_SPLIT_MEMBER()

    template<class Archive>
    void save( Archive & ar, const unsigned int version ) const;
    template<class Archive>
    void load( Archive & ar, const unsigned int version ) ;
    bool existDB();
    void setRebuildDatabase( bool b);

private:

    double M_meshSize;
    std::string M_shape;
    element_type M_element;
    element_type M_element_temp;
    int M_nb_element;
    bool M_rebuild_database;
    std::vector< element_type > M_vector_element;
    std::vector< element_type > M_rebuilt_vector_element;
}; // TestElementSerialize


template<int Dim>
void
TestElementSerialize<Dim>::run()
{
    std::cout << "------------------------------------------------------------\n";
    std::cout << "Execute TestElementSerialize<" << Dim << ">\n";
    std::vector<double> X( 2 );
    X[0] = M_meshSize;

    if ( M_shape == "hypercube" )
        X[1] = 1;

    else // default is simplex
        X[1] = 0;

    std::vector<double> Y( 3 );
    run( X.data(), X.size(), Y.data(), Y.size() );
}

template<int Dim>
void
TestElementSerialize<Dim>::run( const double* X, unsigned long P, double* Y, unsigned long N )
{
    if ( X[1] == 0 ) M_shape = "simplex";

    if ( X[1] == 1 ) M_shape = "hypercube";

#if 1
    if ( !this->vm().count( "nochdir" ) )

        Environment::changeRepository( boost::format( "testsuite/feeldiscr/%1%/%2%-%3%/h_%4%/" )
                                       % this->about().appName()
                                       % M_shape
                                       % Dim
                                       % M_meshSize );
#endif


    auto mesh = mesh_type::New();

    auto is_mesh_loaded = mesh->load( _name="mymesh",_path=".",_type="text" );

    if ( ! is_mesh_loaded )
    {
        mesh = createGMSHMesh( _mesh=new mesh_type,
                               _update=MESH_CHECK|MESH_UPDATE_FACES|MESH_UPDATE_EDGES|MESH_RENUMBER,
                               _desc=domain( _name=( boost::format( "%1%-%2%-%3%" ) % M_shape % Dim % 1 ).str() ,
                                             _usenames=true,
                                             _shape=M_shape,
                                             _dim=Dim,
                                             _h=X[0],
                                             _xmin=0.,
                                             _xmax=1.,
                                             _ymin=0.,
                                             _ymax=1.,
                                             _zmin=0.,
                                             _zmax=1. ) );
        mesh->save( _name="mymesh",_path=".",_type="text" );
    }


    if( ! existDB() || M_rebuild_database )
    {
        auto Xh = space_type::New( mesh );
        M_element = Xh->element();
        M_vector_element.resize( M_nb_element );
        std::cout<<"DB will be created "<<std::endl;
        M_element = vf::project( Xh , elements(mesh), cst( 1 ) );
        M_element.setName("element");
        for( int i = 0 ; i < M_nb_element ; i++ )
        {
            M_vector_element[i] = Xh->element();
            M_vector_element[i] = M_element ;
            M_vector_element[i].setName("element_"+(boost::format("%1%") %i ).str());
           std::cout<<"save element "<<M_vector_element[i].name()<<std::endl;
        }
        M_element_temp = Xh->element();
        this->saveDB();
        std::cout<<"DB successfully created "<<std::endl;
    }
    else
    {
        std::cout<<"DB will be loaded"<<std::endl;
        this->loadDB();
        std::cout<<"DB successfully loaded"<<std::endl;


        double max = M_element.max();
        double min = M_element.min();
        BOOST_CHECK_CLOSE( max, 1.0, 2e-1 );
        BOOST_CHECK_CLOSE( min, 1.0, 2e-1 );

        for( int e = 0 ; e < M_nb_element; e++ )
        {
            max = M_rebuilt_vector_element[e].max();
            min = M_rebuilt_vector_element[e].min();
            BOOST_CHECK_CLOSE( max, 1.0, 2e-1 );
            BOOST_CHECK_CLOSE( min, 1.0, 2e-1 );
        }

    }




} // TestElementSerialize::run

template< int Dim>
bool
TestElementSerialize<Dim>::existDB()
{
    return fs::exists( this->dbPath() / "database" );
}

template< int Dim>
template<class Archive>
void
TestElementSerialize<Dim>::save( Archive & ar, const unsigned int version ) const
{
    ar & BOOST_SERIALIZATION_NVP( M_nb_element );
    ar & BOOST_SERIALIZATION_NVP( M_element );

    for( int e=0; e<M_nb_element; e++ )
        ar & BOOST_SERIALIZATION_NVP( M_vector_element[e] );

    //ar & BOOST_SERIALIZATION_NVP( M_vector_element );
}

template< int Dim>
template<class Archive>
void
TestElementSerialize<Dim>::load( Archive & ar, const unsigned int version )
{

    auto mesh = mesh_type::New();
    auto is_mesh_loaded = mesh->load( _name="mymesh",_path=".",_type="text" );

    auto Xh = space_type::New( mesh );
    M_element = Xh->element();

    ar & BOOST_SERIALIZATION_NVP( M_nb_element );

    ar & BOOST_SERIALIZATION_NVP( M_element );

    M_rebuilt_vector_element.resize( M_nb_element );
    M_vector_element.resize( M_nb_element );

#if 1
    for(int e=0; e<M_nb_element; e++)
    {
        M_element_temp = Xh->element();
        M_element_temp.setName("element_"+(boost::format("%1%") %e ).str() );
        ar & BOOST_SERIALIZATION_NVP( M_element_temp );
        M_rebuilt_vector_element[e] = M_element_temp;

        M_vector_element[e] = Xh->element();
    }
#else
    //problem when loading M_vector_element
    ar & BOOST_SERIALIZATION_NVP( M_vector_element );
#endif
}


template< int Dim>
fs::path
TestElementSerialize<Dim>::dbPath()
{
    std::string localpath = ( boost::format( "%1%/testsuite/feeldiscr/%2%/%3%-%4%/h_%5%/db/" )
                              % Feel::Environment::rootRepository()
                              % this->about().appName()
                              % M_shape
                              % Dim
                              % M_meshSize).str();

    fs::path rep_path = localpath;

    return rep_path ;
}


template< int Dim >
void
TestElementSerialize<Dim>::saveDB()
{

    fs::path path = this->dbPath();
    fs::create_directories( path );

    fs::ofstream ofs ( this->dbPath() / "database" );

    if ( ofs )
    {
        boost::archive::text_oarchive oa( ofs );
        oa << *this;
    }
    else
        throw std::logic_error(" can't use ofs in saveDB() " );
}

template< int Dim >
void
TestElementSerialize<Dim>::loadDB()
{

    fs::path db = this->dbPath();

    fs::ifstream ifs( db / "database" );

    if ( ifs )
    {
        boost::archive::text_iarchive ia( ifs );
        ia >> *this;
    }
}


template < int Dim >
void
TestElementSerialize<Dim>::setRebuildDatabase( bool b )
{
    M_rebuild_database = b;
}

/**
 * main code
 */

FEELPP_ENVIRONMENT_WITH_OPTIONS( makeAbout(), makeOptions() )

BOOST_AUTO_TEST_SUITE( element_serialize )

BOOST_AUTO_TEST_CASE( MyElementSerializeCase )
{
    Application app;

    //the first one :  create database ( if doesn't exist )
    app.add( new TestElementSerialize<1>( true ) );
    //the second one : load database
    app.add( new TestElementSerialize<1>(false ) );

    app.add( new TestElementSerialize<2>(true ) );
    app.add( new TestElementSerialize<2>(false ) );

    app.add( new TestElementSerialize<3>(true ) );
    app.add( new TestElementSerialize<3>(false ) );

    app.run();

}
BOOST_AUTO_TEST_SUITE_END()


back to top