Skip to content
Snippets Groups Projects
Select Git revision
  • 233003f1973d1128d542fb1424d83c024248d38d
  • 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

inclusion.cpp

Blame
  • inclusion.cpp 19.53 KiB
    //Standard Library
    #include <numeric>
    #include <array>
    //GmshFem Library
    #include "GmshFem.h"
    #include "Exception.h"
    #include "Message.h"
    #include "Domain.h"
    #include "Function.h"
    //#include "Formulation.h"
    #include "CSVio.h"
    //Gmsh Library
    #include "gmsh.h"
    //Fwi library
    #include "../../common/wave/correlation.h"
    #include "inclusion.h"
    
    namespace gmodel = gmsh::model;
    namespace factory = gmsh::model::geo;
    
    using namespace gmshfem;
    using namespace gmshfem::common;
    using namespace gmshfem::domain;
    using namespace gmshfem::function;
    
    static const std::complex< double > im = std::complex< double >(0., 1.);
    
    namespace inclusion
    {
        Inclusion to_inclusion(std::string inclusion)
        {
            if(inclusion=="none"){return Inclusion::None;}
            else if(inclusion=="cylinder"){return Inclusion::Cylinder;}
            else
            {
                throw common::Exception("Unknown inclusion type:"+inclusion+".");
                return Inclusion::None;
            }
        }
        UnknownRegion to_unknownregion(const GmshFem& gmshFem)
        {
            std::string str;
            if(! gmshFem.userDefinedParameter(str, "unknown") )
            {
            throw common::Exception("The unknown region to consider could not be found.");
            }
            if(str=="all") {return UnknownRegion::All;}
            else if(str=="inclusion") {return UnknownRegion::Inclusion;}
            else if(str=="background") {return UnknownRegion::Background;}
            else if(str=="none") {return UnknownRegion::None;}
            else
            {
            throw common::Exception("The unknown region " + str + " is not handled.");
            }
            return UnknownRegion::None;
        }
        /*
        *  class Configuration
        */
        Configuration::Configuration(std::string name, const GmshFem& gmshFem) : ConfigurationInterface(name, gmshFem)
        {
            msg::print << "Initialize inclusion configuration" << msg::endl;
    
            /*
            * MESH
            */
            std::string inclusion;
            if(
              !(
                gmshFem.userDefinedParameter(_xe, "xe") &&
                gmshFem.userDefinedParameter(_xr, "xr") &&
                gmshFem.userDefinedParameter(_ye, "ye") &&
                gmshFem.userDefinedParameter(_yr, "yr") &&
                gmshFem.userDefinedParameter(_He, "He") &&
                gmshFem.userDefinedParameter(_Hr, "Hr") &&
                gmshFem.userDefinedParameter(_Le, "Le") &&
                gmshFem.userDefinedParameter(_Lr, "Lr") &&
                gmshFem.userDefinedParameter(_nxe, "nxe") &&
                gmshFem.userDefinedParameter(_nxr, "nxr") &&
                gmshFem.userDefinedParameter(_nye, "nye") &&
                gmshFem.userDefinedParameter(_nyr, "nyr") &&
                gmshFem.userDefinedParameter(_L, "L") &&
                gmshFem.userDefinedParameter(_H, "H") &&
                gmshFem.userDefinedParameter(inclusion, "inclusion") &&
                gmshFem.userDefinedParameter(_h, "h")
                )
            )
            {
              throw common::Exception("A geometric parameter could not be found.");
            }
            _inclusion_type = to_inclusion(inclusion);
            if(_inclusion_type != Inclusion::None)
            {
              if (!gmshFem.userDefinedParameter(_r, "r"))
              {
                throw common::Exception("Inclusion size could not be found.");
              }
            }
            unsigned int filled = 0;
            gmshFem.userDefinedParameter(filled, "filled");
            _isFilled = ((bool) filled);
    
            mesh();
    
            /*
            * DOMAIN
            */
            if(nxe() != 0){_data_omega |= Domain(2,1);}
            if(nye() != 0){_data_omega |= Domain(2,2);}
    
            _background[Support::BLK] = Domain(2,21);
            _background[Support::BND] = Domain(1,12);
    
            if(_inclusion_type != Inclusion::None)
            {
                if(_isFilled){_inclusion[Support::BLK] = Domain(2,22);}
                else{_inclusion[Support::BND] = Domain(1,13);}
            }
    
            _wave_omega[Support::BLK] = _background[Support::BLK] | _inclusion[Support::BLK];
            _wave_omega[Support::BND] = _background[Support::BND] | _inclusion[Support::BND];
            _unknown_region = to_unknownregion(gmshFem);
            switch (_unknown_region)
            {
              case UnknownRegion::Inclusion:
                _model_known = _background;
                _model_unknown = _inclusion;
                break;
              case UnknownRegion::Background:
                _model_known = _inclusion;
                _model_unknown = _background;
                break;
              case UnknownRegion::All:
                _model_unknown[Support::BLK] = _background[Support::BLK] | _inclusion[Support::BLK];
                _model_unknown[Support::BND] = _background[Support::BND] | _inclusion[Support::BND];
                break;
              case UnknownRegion::None: default:
                _model_known[Support::BLK] = _background[Support::BLK] | _inclusion[Support::BLK];
                _model_known[Support::BND] = _background[Support::BND] | _inclusion[Support::BND];
                break;
            }
    
            _ns = _nxe+_nye;
            _np = _nxe+_nye;
            //Emitters X
            for (unsigned int e = 0; e < _nxe; e++)
            {
              _point.push_back(Domain(0,100+e));
            }
            _emitter_idx_X.resize(_nxe);
            std::iota(_emitter_idx_X.begin(),_emitter_idx_X.end(),0);
    
            //Emitters Y
            for (unsigned int e = 0; e < _nye; e++)
            {
              _point.push_back(Domain(0,300+e));
            }
            _emitter_idx_Y.resize(_nye);
            std::iota(_emitter_idx_Y.begin(),_emitter_idx_Y.end(),_nxe);
    
            //Receivers X
            if(!receiversAreEmittersX())
            {
              _np+=_nxr;
              for (unsigned int r = 0; r < _nxr; r++)
              {
                _point.push_back(Domain(0,200+r));
              }
              _receiver_idx_X.resize(_nxr);
              std::iota(_receiver_idx_X.begin(),_receiver_idx_X.end(),_nxe+_nye);
            }
            else
            {
                _receiver_idx_X = _emitter_idx_X;
            }
    
            //Receivers Y
            if(!receiversAreEmittersY())
            {
              _np+=_nyr;
              for (unsigned int r = 0; r < _nyr; r++)
              {
                _point.push_back(Domain(0,400+r));
              }
              _receiver_idx_Y.resize(_nyr);
              std::iota(_receiver_idx_Y.begin(),_receiver_idx_Y.end(),_nxe+_nye+_nxr);
            }
            else
            {
                _receiver_idx_Y = _emitter_idx_Y;
            }
    
            for (unsigned int p = 0; p < _np; p++)
            {
              _points |= _point[p];
            }
    
            for (unsigned int s = 0; s < _nxe; s++)
            {
              _emitter.push_back({s});
              std::vector<unsigned int> rec(_nxr,0);
              if(receiversAreEmittersX())
              {
                std::iota(rec.begin(),rec.end(),0);
                rec.erase(rec.begin()+s);
                _receiver.push_back(rec);
              }
              else
              {
                std::iota(rec.begin(),rec.end(),_nxe+_nye);
                _receiver.push_back(rec);
              }
            }
            for (unsigned int s = _nxe; s < _nxe+_nye; s++)
            {
              _emitter.push_back({s});
              std::vector<unsigned int> rec(_nyr,0);
              if(receiversAreEmittersY())
              {
                std::iota(rec.begin(),rec.end(),_nxe);
                rec.erase(rec.begin()+s-_nxe);
                _receiver.push_back(rec);
              }
              else
              {
                std::iota(rec.begin(),rec.end(),_nxe+_nye+_nxr);
                _receiver.push_back(rec);
              }
            }
    
            /*
            * Reference model function
            */
            double Remb, Immb;
            if
            (
              !(
                gmshFem.userDefinedParameter(Remb, "Re(mb)") &&
                gmshFem.userDefinedParameter(Immb, "Im(mb)")
              )
            )
            {
              throw common::Exception("Background model parameter could not be found.");
            }
            _mb = Remb + im * Immb;
    
            double Remc=0., Immc=0.;
            if
            (
              !(gmshFem.userDefinedParameter(Remc, "Re(mc)") &&
                gmshFem.userDefinedParameter(Immc, "Im(mc)")
              )
              &&
              (_inclusion_type!=Inclusion::None)
            )
            {
              throw Exception("Inclusion model parameter could not be found.");
            }
            _mc = Remc + im * Immc;
    
            ScalarPiecewiseFunction< std::complex< double > > m0;
            m0.addFunction(_mb,_background[Support::BLK] | _background[Support::BND] | _points);
            m0.addFunction(_mc,_inclusion[Support::BLK] | _inclusion[Support::BND]);
            _m0 = m0;
        }
    
        void Configuration::mesh() const
        {
            msg::print << "Generate meshes" << msg::endl;
            gmsh::option::setNumber("General.Terminal", 1);
    
            std::string name = _name + "_inclusion";
            switch (_inclusion_type)
            {
                case Inclusion::Cylinder: name += "_cyl"; break;
                case Inclusion::None: name += "_none"; break;
                default: break;
            }
            if(_isFilled && (_inclusion_type != Inclusion::None)){name += "_filled";}
            if((!_isFilled) && (_inclusion_type != Inclusion::None)){name += "_empty";}
    
            gmodel::add("inclusion");
            if(!_remesh)
            {
              gmsh::open(name+".msh");
              return;
            }
    
            wave_mesh();
            data_mesh();
    
            factory::synchronize();
            gmodel::mesh::generate();
    
            gmsh::write(name+".msh");
        }
        void Configuration::wave_mesh() const
        {
            int pb1 = factory::addPoint(0., 0., 0., _h);
            int pb2 = factory::addPoint(_L, 0., 0., _h);
            int pb3 = factory::addPoint(_L, _H, 0., _h);
            int pb4 = factory::addPoint(0., _H, 0., _h);
    
            int lbh1 = factory::addLine(pb1, pb2);
            int lbv1 = factory::addLine(pb2, pb3);
            int lbh2 = factory::addLine(pb3, pb4);
            int lbv2 = factory::addLine(pb4, pb1);
    
            int clb = factory::addCurveLoop({lbh1,lbv1,lbh2,lbv2});
    
            //Vertical emitters
            std::vector<int> px(_nxe);
            double He0 = (_H - _He)/2.;
            double deltaHe = _He/(((double) _nxe)-1.);
            for (unsigned int e = 0; e < _nxe; e++)
            {
                double Hee = He0 + ((double)e)*deltaHe;
                px[e] = factory::addPoint(_xe, Hee, 0., _h);
            }
    
            if(!receiversAreEmittersX())
            {
            //Vertical receivers
            px.resize(_nxe+_nxr);
            double Hr0 = (_H - _Hr)/2.;
            double deltaHr = _Hr/(((double) _nxr)-1.);
            for (unsigned int r = 0; r < _nxr; r++)
            {
                double Hrr = Hr0 + ((double)r)*deltaHr;
                px[_nxe+r] = factory::addPoint(_xr, Hrr, 0., _h);
            }
            }
            //Horizontal emitters
            std::vector<int> py(_nye);
            double Le0 = (_L - _Le)/2.;
            double deltaLe = _Le/(((double) _nye)-1.);
            for (unsigned int e = 0; e < _nye; e++)
            {
                double Lee = Le0 + ((double)e)*deltaLe;
                py[e] = factory::addPoint(Lee, _ye, 0., _h);
            }
            if(!receiversAreEmittersY())
            {
            //Horizontal receivers
            py.resize(_nye+_nyr);
            double Lr0 = (_L - _Lr)/2.;
            double deltaLr = _Lr/(((double) _nyr)-1.);
            for (unsigned int r = 0; r < _nyr; r++)
            {
                double Lrr = Lr0 + ((double)r)*deltaLr;
                py[_nye+r] = factory::addPoint(Lrr,_yr, 0., _h);
            }
            }
    
            int si=0;
            int sb=0;
            std::vector<int> lci{};
            switch (_inclusion_type)
            {
                case Inclusion::Cylinder:
                {
                    int pc0 = factory::addPoint(_L/2, _H/2, 0., _h);
                    int pc1 = factory::addPoint(_L/2+_r, _H/2, 0., _h);
                    int pc2 = factory::addPoint(_L/2, _H/2+_r, 0., _h);
                    int pc3 = factory::addPoint(_L/2-_r, _H/2, 0., _h);
                    int pc4 = factory::addPoint(_L/2, _H/2-_r, 0., _h);
    
                    int lc1 = factory::addCircleArc(pc1, pc0, pc2);
                    int lc2 = factory::addCircleArc(pc2, pc0, pc3);
                    int lc3 = factory::addCircleArc(pc3, pc0, pc4);
                    int lc4 = factory::addCircleArc(pc4, pc0, pc1);
    
                    lci = {lc1,lc2,lc3,lc4};
    
                    int cli = factory::addCurveLoop(lci);
    
                    if(_isFilled){si = factory::addPlaneSurface({cli});}
                    sb = factory::addPlaneSurface({clb,cli});
                    break;
                }
                case Inclusion::None:
                {
                    sb = factory::addPlaneSurface({clb});
                    break;
                }
            }
    
            factory::synchronize();
            gmodel::mesh::embed(0, px, 2, sb);
            gmodel::mesh::embed(0, py, 2, sb);
    
            if(receiversAreEmittersX())
            {
                for (unsigned int e = 0; e <_nxe; e++)
                {
                    gmodel::addPhysicalGroup(0, {px[e]}, 100+e);
                    gmodel::setPhysicalName(0, 100+e, "emitter_receiver_x_"+std::to_string(e));
                }
            }
            else
            {
                for (unsigned int e = 0; e <_nxe; e++)
                {
                    gmodel::addPhysicalGroup(0, {px[e]}, 100+e);
                    gmodel::setPhysicalName(0, 100+e,"emitter_x_"+std::to_string(e));
                }
                for (unsigned int r = 0; r < _nxr; r++)
                {
                    gmodel::addPhysicalGroup(0, {px[_nxe+r]}, 200+r);
                    gmodel::setPhysicalName(0, 200+r, "receiver_x_"+std::to_string(r) );
                }
            }
            if(receiversAreEmittersY())
            {
                for (unsigned int e = 0; e <_nye; e++)
                {
                    gmodel::addPhysicalGroup(0, {py[e]}, 300+e);
                    gmodel::setPhysicalName(0, 300+e,"emitter_receiver_y_"+std::to_string(e));
                }
            }
            else
            {
                for (unsigned int e = 0; e <_nye; e++)
                {
                    gmodel::addPhysicalGroup(0, {py[e]}, 300+e);
                    gmodel::setPhysicalName(0, 300+e,"emitter_y_"+std::to_string(e));
                }
                for (unsigned int r = 0; r < _nyr; r++)
                {
                    gmodel::addPhysicalGroup(0, {py[_nye+r]}, 400+r);
                    gmodel::setPhysicalName(0, 400+r, "receiver_y_"+std::to_string(r) );
                }
            }
    
            gmodel::addPhysicalGroup(1, {lbh1,lbv1,lbh2,lbv2}, 12);
            gmodel::setPhysicalName(1, 12, "background_bnd");
            gmodel::addPhysicalGroup(2, {sb}, 21);
            gmodel::setPhysicalName(2, 21, "background_vol");
            if(_inclusion_type != Inclusion::None)
            {
                if(_isFilled)
                {
                    gmodel::addPhysicalGroup(2, {si}, 22);
                    gmodel::setPhysicalName(2, 22, "inclusion_vol");
                }
                else
                {
                    gmodel::addPhysicalGroup(1, lci, 13);
                    gmodel::setPhysicalName(1, 13, "inclusion_bnd");
                }
            }
            factory::removeAllDuplicates();
        }
        void Configuration::data_mesh() const
        {
            if(nxe() != 0)
            {
                double ors = (_H - _He) / 2.;
                double orr = (_H - _Hr) / 2.;
                //Vertical array
                int p00 = factory::addPoint(ors, orr, 0.);
                int pHe0 = factory::addPoint(ors+_He,orr, 0.);
                int pHeHr = factory::addPoint(ors+_He, orr+_Hr, 0.);
                int p0Hr = factory::addPoint(ors, orr+_Hr, 0.);
    
                int ly0 = factory::addLine(p00, pHe0);
                int lxHe = factory::addLine(pHe0, pHeHr);
                int lyHr = factory::addLine(pHeHr, p0Hr);
                int lx0 = factory::addLine(p0Hr, p00);
    
                int cl = factory::addCurveLoop({ly0,lxHe,lyHr,lx0});
                int s1 = factory::addPlaneSurface({cl});
    
                factory::mesh::setTransfiniteCurve(ly0,_nxe);
                factory::mesh::setTransfiniteCurve(lxHe,_nxr);
                factory::mesh::setTransfiniteCurve(lyHr,_nxe);
                factory::mesh::setTransfiniteCurve(lx0,_nxr);
    
                factory::mesh::setTransfiniteSurface(s1,"Left",{p00,pHe0,pHeHr,p0Hr});
    
                factory::mesh::setRecombine(2,s1);
                gmodel::addPhysicalGroup(2, {s1}, 1);
                gmodel::setPhysicalName(2, 1, "data_omega1");
                factory::removeAllDuplicates();
            }
    
            if(nye() != 0)
            {
                double ors = _H + (_L - _Le) / 2.;
                double orr = _H + (_L - _Lr) / 2.;
                //Horizontal array
                int pHeHr = factory::addPoint(ors, orr, 0.);
                int pLe0 = factory::addPoint(ors+_Le, orr, 0.);
                int pLeLr = factory::addPoint(ors+_Le, orr+_Lr, 0.);
                int p0Lr = factory::addPoint(ors+0., orr+_Lr, 0.);
    
                int lyHr2 = factory::addLine(pHeHr, pLe0);
                int lxLe = factory::addLine(pLe0, pLeLr);
                int lyLr = factory::addLine(pLeLr, p0Lr);
                int lxHe2 = factory::addLine(p0Lr, pHeHr);
    
                int cl2 = factory::addCurveLoop({lyHr2,lxLe,lyLr,lxHe2});
                int s2 = factory::addPlaneSurface({cl2});
    
                factory::mesh::setTransfiniteCurve(lyHr2,_nxe);
                factory::mesh::setTransfiniteCurve(lxLe,_nxr);
                factory::mesh::setTransfiniteCurve(lyLr,_nxe);
                factory::mesh::setTransfiniteCurve(lxHe2,_nxr);
    
                factory::mesh::setTransfiniteSurface(s2,"Left",{pHeHr,pLe0,pLeLr,p0Lr});
    
                factory::mesh::setRecombine(2,s2);
                gmodel::addPhysicalGroup(2, {s2}, 2);
                gmodel::setPhysicalName(2, 2, "data_omega2");
            }
        }
    
        std::array<unsigned int,2> Configuration::data_coordinate_to_index(double xs, double xr) const
        {
            std::array<unsigned int,2> index;
            if(xs<_H && xr < _H)
            {
                double xe0 = (_H-_He)/2.;
                double stepe = _He/(nxe()-1);
                double xr0 = (_H-_Hr)/2.;
                double stepr = _Hr/(nxr()-1);
                index[0] = std::round((xs-xe0)/stepe);
                index[1] = std::round((xr-xr0)/stepr);
            }
            else if(xs>=_H && xr>=_H)
            {
                double ye0 = _H + (_L-_Le)/2.;
                double stepe = _Le/(nye()-1);
                double yr0 = _H + (_L-_Lr)/2.;
                double stepr = _Lr/(nyr()-1);
                index[0] = std::round((xs-ye0)/stepe);
                index[1] = std::round((xr-yr0)/stepr);
            }
            else
            {
                throw Exception("Invalid data coordinate.");
            }
            return index;
        }
    
        std::array<double,2> Configuration::index_to_data_coordinate(unsigned int s, unsigned int r) const
        {
            std::array<double,2> index;
            if(s < nxe() && r < nxr())
            {
                double xe0 = (_H-_He)/2.;
                double stepe = _He/(nxe()-1);
                double xr0 = (_H-_Hr)/2.;
                double stepr = _Hr/(nxr()-1);
                index[0] = xe0 + s*stepe;
                index[1] = xr0 + r*stepr;
            }
            else if( s>=nxe() && r>=nxr())
            {
                double xe0 = _H + (_L-_Le)/2.;
                double stepe = _Le/(nye()-1);
                double xr0 = _H + (_L-_Lr)/2.;
                double stepr = _Lr/(nyr()-1);
                index[0] = xe0 + (s-nxe())*stepe;
                index[1] = xr0 + (r-nxr())*stepr;
            }
            else
            {
                throw Exception("Invalid index.");
            }
            return index;
        }
    
        template<Physic T_Physic>
        ModelFunction green0_preconditioner(const WaveMultiField<T_Physic>& g, const Configuration* const config)
        {
            ModelFunction termX;
            if( !config->receiversAreEmittersX() )
            {
                termX = autocorrelate<T_Physic>(g,config->emitter_idx_X())*autocorrelate<T_Physic>(g,config->receiver_idx_X());
            }
            else
            {
                termX = pow(autocorrelate<T_Physic>(g,config->emitter_idx_X()),2);
            }
    
            ModelFunction termY;
            if( !config->receiversAreEmittersY() )
            {
                termY = autocorrelate<T_Physic>(g,config->emitter_idx_Y())*autocorrelate<T_Physic>(g,config->receiver_idx_Y());
            }
            else
            {
                termY = pow(autocorrelate<T_Physic>(g,config->emitter_idx_Y()),2);
            }
            return termX + termY;
        }
    
        template ModelFunction green0_preconditioner<Physic::acoustic>(const WaveMultiField<Physic::acoustic>&, const Configuration* const);
    
    } // namespace soil