Skip to content
Snippets Groups Projects
Select Git revision
  • 50c8b039adc5841d7e51e709e04cac67dd461348
  • master default protected
  • NewDistributionGmshFWI
  • parametrizationSimpleWave
  • tuto_obstacle
  • everything
  • cleanup_configuuration_mesh
  • fix
  • source_estimation
  • unique_ptr
  • SobolevDirectionalFilter
  • OT
  • newPhysics
  • SimultaneousFrequency
  • SobolevDistance
  • BonesImaging
  • MultiParameter
  • UpdateAntho
  • v2.0
  • v1.0
20 results

simplewave.cpp

Blame
  • simplewave.cpp 12.01 KiB
    //Standard library
    
    //GmshFem library
    #include "Message.h"
    #include "Exception.h"
    #include "Function.h"
    #include "Post.h"
    
    //GmshFWI Library
    #include "simplewave.h"
    #include "../../model/parametrization/simplewave.h"
    #include "../../configuration/green0_preconditioner.h"
    #include "../correlation.h"
    
    using namespace gmshfem;
    using namespace gmshfem::common;
    using namespace gmshfem::equation;
    using namespace gmshfem::function;
    using namespace gmshfem::post;
    
    
    static const std::complex< double > im = std::complex< double >(0., 1.);
    
    /*
    * Simple wave (acoustics)
    */
    #define u ws.state(Type::FS)
    #define du ws.state(Type::PFS)
    #define lambda ws.state(Type::AS)
    #define dlambda ws.state(Type::PAS)
    
    #define m0 _config->m0_natural(_pulsation)[0]
    #define m ms.state(Type::FS)[0]
    #define dm ms.state(Type::PFS)[0]
    
    #define _w_degree _v.degree()
    
    namespace simplewave
    {
        Equation::Equation(unsigned int f_idx,double pulsation,const ConfigurationInterface* const config, const wave::Discretization<Physic::acoustic>& w_discret,const gmshfem::common::GmshFem& gmshFem, std::string suffix) : DifferentialEquationInterface<Physic::acoustic>(config,w_discret,gmshFem,suffix), _f_idx(f_idx), _pulsation(pulsation)
        {
            unsigned int gn = 0;
            if(!gmshFem.userDefinedParameter(gn, "gaussNewton"))
            {
                msg::warning << "Gauss-Newton approximation (equation) flag could not be found. Approximation is not used (default)." << msg::endl;
            }
            _gaussNewton = ((bool) gn);
    
            unsigned int ri = 0;
            if(!gmshFem.userDefinedParameter(ri, "equation_boundary_realImpedance"))
            {
                msg::warning << "Real boundary impedance flag could not be found.  Complex boundary impedances are used (default)." << msg::endl;
            }
            _realImpedance = ((bool) ri);
    
            unsigned int gp = 1;
            if(!gmshFem.userDefinedParameter(gp, "equation_greenPreconditioner"))
            {
                msg::warning << "Green preconditionner (equation) flag could not be found. Green preconditioner is used (default)." << msg::endl;
            }
            _greenPreconditioner = ((bool) gp);
    
            if(!_greenPreconditioner)
            {
                if(!gmshFem.userDefinedParameter(_const_preconditioner, "equation_const_preconditioner"))
                {
                    throw Exception("Impossible to find constant preconditioner (equation)");
                }
            }
    
            if(_realImpedance && _boundary)
            {
                    throw Exception("Impossible to compute boundary terms with real impedance: sensitivities are wrong.");
            }
    
            if (gmshFem.userDefinedParameter(_topBC, "top_bc")) {
                if (_topBC != "Absorbing" && _topBC != "Dirichlet" && _topBC != "Neumann") {
                    throw Exception("Invalid value of parameter top_bc: " + _topBC);
                }
            }
            else {
                msg::warning << "SimpleWave without specified top_bc defaults to Absorbing." << msg::endl;
            }
        }
    
        bool Equation::modelIsObsolete()
        {
            _systemIsUpToDate=false;
            _systemIsFactorized=false;
            _geAreUpToDate=false;
            _grAreUpToDate=false;
            return _greenPreconditioner;
        }
    
        bool Equation::compatible(const ParametrizationInterface* const parametrization) const
        {
            return
            (
                nullptr != dynamic_cast<const natural::Parametrization* const>(parametrization)
                ||
                nullptr != dynamic_cast<const slowness2_real::Parametrization* const>(parametrization)
                ||
                nullptr != dynamic_cast<const ln_slowness2_real::Parametrization* const>(parametrization)
                ||
                nullptr != dynamic_cast<const permcond_bireal::Parametrization* const>(parametrization)
                ||
                nullptr != dynamic_cast<const ln_permcond_bireal::Parametrization* const>(parametrization)
            );
        }
        double Equation::wavelength(std::vector<std::complex<double>> mc) const
        {
            return 2. * M_PI / (_pulsation * std::real(std::sqrt(mc[0])));
        }
        void Equation::setLHS(const ModelStateEvaluator& ms)
        {
            auto top = _config->named_domains().find("top_bnd");
            if (_topBC == "Dirichlet" || _topBC == "Neumann")
            {
                if (top == _config->named_domains().end())
                    throw Exception("Asked for specific BCs on top but this entity isn't defined.");
            }
    
            if (_topBC == "Dirichlet")
            {
                _v.addConstraint(top->second, 0.0);
            }
    
            _formulation.integral(-1.*grad(dof(_v)), grad(tf(_v)), _config->wave_omega(Support::BLK),integrationType(2*_w_degree));
            _formulation.integral(_pulsation * _pulsation * m0 * dof(_v), tf(_v), _config->model_known(Support::BLK), integrationType(_integrationDegreeBlk));
            
            auto absorbingPartKnown = _config->model_known(Support::BND);
            auto absorbingPartUnknown = _config->model_unknown(Support::BND);
            if (_topBC == "Neumann") {
                absorbingPartKnown &= ~(top->second);
                absorbingPartUnknown &= ~(top->second);
            }
    
            if(_realImpedance)
            {
                _formulation.integral(-1. * im * _pulsation * sqrt(real(m0)) * dof(_v), tf(_v), absorbingPartKnown, integrationType(_integrationDegreeBnd)); //-1 from sign conventions
            }
            else
            {
                _formulation.integral(-1. * im * _pulsation * sqrt(m0) * dof(_v), tf(_v), absorbingPartKnown, integrationType(_integrationDegreeBnd)); //-1 from sign conventions
            }
            if(!_config->model_unknown(Support::BLK).isEmpty())
            {
                _formulation.integral(_pulsation * _pulsation * m * dof(_v), tf(_v), _config->model_unknown(Support::BLK), integrationType(_integrationDegreeBlk));
            }
            if(!_config->model_unknown(Support::BND).isEmpty())
            {
                if(_realImpedance)
                {
                    _formulation.integral(-1. * im * _pulsation * sqrt(real(m)) *  dof(_v), tf(_v), absorbingPartUnknown, integrationType(_integrationDegreeBnd)); //-1 from sign conventions
                }
                else
                {
                    _formulation.integral(-1. * im * _pulsation * sqrt(m) *  dof(_v), tf(_v), absorbingPartUnknown, integrationType(_integrationDegreeBnd)); //-1 from sign conventions
                }
            }
        }
        void Equation::setRHS(Type type, unsigned int s, const DataStateEvaluator<Physic::acoustic>& d, const ModelStateEvaluator& ms, const WaveStateEvaluator<Physic::acoustic>& ws)
        {
            switch (type)
            {
                case Type::FS:
                    for (unsigned int e = 0; e < _config->ne(s); e++)
                    {
                      _formulation.integral(-1.,tf(_v), _config->emitter(s,e), integrationType(0));
                    }
                    break;
                case Type::AS:
                    for (unsigned int r = 0; r < _config->nr(s); r++)
                    {
                      _formulation.integral(-d.state(Type::AS).value(_f_idx,s,r),tf(_v), _config->receiver(s,r), integrationType(0));
                    }
                    break;
                case Type::PFS:
                    _formulation.integral( u[s] * _pulsation * _pulsation * dm, tf(_v), _config->model_unknown(Support::BLK), integrationType(_integrationDegreeBlk));
                    if(_boundary)
                    {
                        _formulation.integral(-im * u[s] * _pulsation / 2. / sqrt(m)* dm, tf(_v), _config->model_unknown(Support::BND), integrationType(_integrationDegreeBnd)); //-1 from sign conventions
                    }
                    break;
                case Type::PAS:
                    for (unsigned int r = 0; r < _config->nr(s); r++)
                    {
                        _formulation.integral(-d.state(Type::PAS).value(_f_idx,s,r), tf(_v), _config->receiver(s,r), integrationType(0));
                    }
                    if(!_gaussNewton)
                    {
                        _formulation.integral( lambda[s] * _pulsation * _pulsation * dm, tf(_v), _config->model_unknown(Support::BLK), integrationType(_integrationDegreeBlk));
                        if(_boundary)
                        {
                            _formulation.integral(-im * lambda[s] * _pulsation / 2. / sqrt(m) * dm, tf(_v), _config->model_unknown(Support::BND), integrationType(_integrationDegreeBnd)); //-1 from sign conventions
                        }
                    }
                    break;
                case Type::DS: default:
                    throw Exception("Impossible to set RHS other than F,PF,A,PA");
                    break;
            }
        }
        void Equation::setGreenRHS(unsigned int p)
        {
            _formulation.integral(-1.,tf(_v), _config->point(p), integrationType(0));
        }
    
        Sensitivity Equation::update_sensitivity(Order order, Support support, const DataStateEvaluator<Physic::acoustic>& ds, const ModelStateEvaluator& ms, const WaveStateEvaluator<Physic::acoustic>& ws)
        {
            ModelMonoFunction fct;
            switch (order)
            {
                case Order::FST:
                    switch (support)
                    {
                        case Support::BLK:
                            fct =  - _pulsation * _pulsation * correlate(u,lambda);
                            break;
                        case Support::BND:
                            fct =  im * _pulsation / 2. / sqrt(m) * correlate(u,lambda);
                            break;
                    }
                    break;
                case Order::SCD:
                    switch (support)
                    {
                        case Support::BLK:
                            if(!_gaussNewton)
                            {
                                fct =  - _pulsation * _pulsation *
                                (
                                    correlate(u,dlambda)
                                    +correlate(du,lambda)
                                );
                            }
                            else
                            {
                                fct =  - _pulsation * _pulsation *
                                (
                                    correlate(u,dlambda)
                                );
                            }
                            break;
                        case Support::BND:
                            if(!_gaussNewton)
                            {
                                fct =  im * _pulsation / 2. /  sqrt(m) *
                                (
                                    correlate(u,dlambda)
                                    +correlate(du,lambda)
                                    -dm / 2. / m * correlate(u,lambda)
                                );
                            }
                            else
                            {
                                fct =  im * _pulsation / 2. /  sqrt(m) *
                                (
                                    correlate(u,dlambda)
                                );
                            }
                            break;
                    }
                    break;
                case Order::DIAG:
                    switch (support)
                    {
                        case Support::BLK:
                            return preconditioner(ds,ms);
                        case Support::BND:
                            break;
                    }
                    break;
            }
            return Sensitivity(1,ModelMonoFunction(fct));
        }
    
        Sensitivity Equation::preconditioner(const DataStateEvaluator<Physic::acoustic>& ds, const ModelStateEvaluator& ms)
        {
            if(_greenPreconditioner)
            {
                if(!_geAreUpToDate){updateGreenEmitter(ms);};
                if(!_grAreUpToDate){updateGreenReceiver(ms);};
                double pulsation4 = _pulsation * _pulsation * _pulsation * _pulsation;
                double wl = wavelength(_config->mc_natural(_pulsation));
                double integrationSupport = M_PI * (wl/2.) * (wl/2.);
                //wl/4. signifie que les interférences destructive apparaissent en xr->+infty et xr -> -infty (ou à l'opposé si les récepteur sont sur un cercle)
                //wl/2. signifie que la phase du préconditionneur fait un tour entier de xr->+infty à xr -> -infty (ou un tour si les récepteur sont sur un cercle)
                return Sensitivity(1,green0_preconditioner<Physic::acoustic>(ds.state(Type::DS),_g,_config) * pulsation4 * integrationSupport);
            }
            else
            {
                return Sensitivity(1,_const_preconditioner);
            }
        }
    };