https://github.com/feelpp/feelpp
Raw File
Tip revision: 5df7755fea43c5be538628a7f55e2e031fdec967 authored by Christophe Prud'homme on 22 November 2022, 15:27:38 UTC
Merge remote-tracking branch 'origin/develop' into 1949-greedy
Tip revision: 5df7755
test_interpolation_Nedelec.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): Christophe Prud'homme <christophe.prudhomme@feelpp.org>
Date: 2007-12-19

Copyright (C) 2007-2012 Université Joseph Fourier (Grenoble I)

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

This library 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
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/
/**
  \file test_interpolation.cpp
  \author Christophe Prud'homme <christophe.prudhomme@feelpp.org>
  \date 2007-12-19
  */
#define USE_BOOST_TEST 1

// make sure that the init_unit_test function is defined by UTF
//#define BOOST_TEST_MAIN
// give a name to the testsuite
#define BOOST_TEST_MODULE interpolation testsuite
// disable the main function creation, use our own
//#define BOOST_TEST_NO_MAIN

#include <feel/feelcore/testsuite.hpp>

#include <feel/feelcore/environment.hpp>
#include <feel/feelfilters/loadmesh.hpp>
#include <feel/feelfilters/exporter.hpp>
#include <feel/feelvf/vf.hpp>
#include <feel/feelpoly/nedelec.hpp>
#include <feel/feelvf/print.hpp>

namespace Feel
{
/**
 * This routine returns the list of options using the
 * boost::program_options library. The data returned is typically used
 * as an argument of a Feel::Application subclass.
 *
 * \return the list of options
 */
inline
po::options_description
makeOptions()
{
    po::options_description testHcurlInterpolationOptions( "test h_div options" );
    testHcurlInterpolationOptions.add_options()
        ( "meshes-2d", po::value< std::vector<std::string> >(), "vector containing mesh names" )
        ;
    return testHcurlInterpolationOptions;
}

inline
AboutData
makeAbout()
{
    AboutData about( "test_interpolation_Nedelec" ,
                     "test_interpolation_Nedelec" ,
                     "0.1",
                     "Test for interpolation with h_curl space",
                     AboutData::License_GPL,
                     "Copyright (c) 2014 Universite Joseph Fourier" );
    about.addAuthor( "Cecile Daversin", "developer", "daversin@math.unistra.fr", "" );
    about.addAuthor( "Christophe Prud'homme", "developer", "christophe.prudhomme@feelpp.org", "" );
    return about;
}

    //using namespace Feel;

class TestInterpolationHCurl
    :
public Application
{
    typedef Application super;

public :
    //! numerical type is double
    typedef double value_type;

    //! linear algebra backend factory
    typedef Backend<value_type> backend_type;
    //! linear algebra backend factory shared_ptr<> type
    typedef typename std::shared_ptr<backend_type> backend_ptrtype ;

    //! geometry entities type composing the mesh, here Simplex in Dimension Dim of Order G_order
    typedef Simplex<2,1> convex_type;
    //! mesh type
    typedef Mesh<convex_type> mesh_type;
    //! mesh shared_ptr<> type
    typedef std::shared_ptr<mesh_type> mesh_ptrtype;

    //! the basis type of our approximation space
    typedef bases< Nedelec<0,NedelecKind::NED1> > basis_type;
    //! the approximation function space type
    typedef FunctionSpace<mesh_type, basis_type> space_type;
    typedef std::shared_ptr<space_type> space_ptrtype;
    typedef typename space_type::element_type element_type;

    //! the exporter factory type
    typedef Exporter<mesh_type> export_type;
    //! the exporter factory (shared_ptr<> type)
    typedef std::shared_ptr<export_type> export_ptrtype;

    /**
     * Constructor
     */
    TestInterpolationHCurl()
        :
        super(),
        M_backend( backend_type::build( soption( _name="backend" ) ) )
    {
        this->changeRepository( boost::format( "%1%/" )
                                % this->about().appName()
                              );
    }

    void testInterpolation( std::string one_element_mesh );

private:
    //! linear algebra backend
    backend_ptrtype M_backend;

};

void
TestInterpolationHCurl::testInterpolation( std::string one_element_mesh )
{
    // expr to interpolate
    auto myexpr = unitX() + unitY(); //(1,1)

    // one element mesh
    auto mesh_name = one_element_mesh + ".msh"; //create the mesh and load it
    fs::path mesh_path( mesh_name );

    mesh_ptrtype oneelement_mesh = loadMesh( _mesh=new mesh_type,
                                             _filename=mesh_name);

    // refined mesh (export)
    auto refine_level = std::floor(1 - math::log( 0.1 )); //Deduce refine level from meshSize (option)
    mesh_ptrtype mesh = loadMesh( _mesh=new mesh_type,
                                  _filename=mesh_name,
                                  _refine=( int )refine_level);

    space_ptrtype Xh = space_type::New( oneelement_mesh );
    std::vector<std::string> faces, edges; //list of edges
    edges = {"hypo","vert","hor"};

    element_type U_h_int = Xh->element();
    element_type U_h_on = Xh->element();
    element_type U_h_on_boundary = Xh->element();

    // handly computed interpolant coeff (in hcurl basis)
    for ( int i = 0; i < Xh->nLocalDof(); ++i )
        {
            CHECK( oneelement_mesh->hasMarkers( {edges[i]} ) );
            U_h_int(i) = integrate( _range=markedfaces( oneelement_mesh, edges[i] ), _expr=trans( T() )*myexpr ).evaluate()(0,0);
        }

    // nedelec interpolant using on
    U_h_on.zero();
    U_h_on.on(_range=elements(oneelement_mesh), _expr=myexpr);
    U_h_on_boundary.on(_range=boundaryfaces(oneelement_mesh), _expr=myexpr);

    auto exporter_proj = exporter( _mesh=mesh, _name=( boost::format( "%1%" ) % this->about().appName() ).str() );
    exporter_proj->step( 0 )->add( "U_interpolation_handly_"+mesh_path.stem().string(), U_h_int );
    exporter_proj->step( 0 )->add( "U_interpolation_on_"+mesh_path.stem().string(), U_h_on );
    exporter_proj->save();

    // print coefficient only for reference element
    U_h_int.printMatlab( "U_h_int_" + mesh_path.stem().string() + ".m" );
    U_h_on.printMatlab( "U_h_on_" + mesh_path.stem().string() + ".m" );
    U_h_on_boundary.printMatlab( "U_h_on_boundary_" + mesh_path.stem().string() + ".m" );

    //L2 norm of error
    auto error = vf::project(_space=Xh, _range=elements(oneelement_mesh), _expr=idv(U_h_int) - idv(U_h_on) );
    double L2error = error.l2Norm();
    std::cout << "L2 error (elements)  = " << L2error << std::endl;

    auto error_boundary = vf::project(_space=Xh, _range=boundaryfaces(oneelement_mesh), _expr=idv(U_h_int) - idv(U_h_on_boundary) );
    double L2error_boundary = error_boundary.l2Norm();
    std::cout << "L2 error (boundary)  = " << L2error_boundary << std::endl;
    BOOST_CHECK_SMALL( L2error_boundary - L2error, 1e-13 );
}
}// namespace Feel

#if USE_BOOST_TEST

FEELPP_ENVIRONMENT_WITH_OPTIONS( Feel::makeAbout(), Feel::makeOptions() )

BOOST_AUTO_TEST_SUITE( HCURL_INTERPOLANT )

BOOST_AUTO_TEST_CASE( test_hcurl_interpolant_1 )
{
    using namespace Feel;
    TestInterpolationHCurl t2;
    std::vector<std::string> mygeoms2d = vsoption(_name="meshes-2d");//.template as< std::vector<std::string> >();
    for(std::string geo2d : mygeoms2d)
        {
            std::cout << "*** interpolant on " << geo2d << " *** \n";
            t2.testInterpolation(geo2d);
        }
}
BOOST_AUTO_TEST_SUITE_END()
#else

int
main( int argc, char* argv[] )
{
    Feel::Environment env( argc,argv,
                           makeAbout(), makeOptions() );
    Feel::TestInterpolationHCurl app_hcurl;
    std::vector<std::string> mygeoms = option(_name="meshes-2d").template as< std::vector<std::string> >();
    for(std::string geo : mygeoms)
        {
            app_hcurl.testInterpolant(geo);
        }
}

#endif
back to top