Skip to content
Snippets Groups Projects
Commit 438be1ad authored by Xavier Adriaens's avatar Xavier Adriaens
Browse files

Initial commit (reproducing result of paper 1)

parents
No related branches found
No related tags found
No related merge requests found
Showing
with 652 additions and 0 deletions
#ifndef H_CONFIGURATION_INCLUSION
#define H_CONFIGURATION_INCLUSION
//GmshFEM Library
#include "GmshFem.h"
//#include "Function.h"
//GmshFWI Library
#include "../../common/configuration.h"
#include "../../common/wave/element.h"
namespace inclusion
{
enum class Inclusion
{
None,
Cylinder
};
Inclusion to_inclusion(std::string inclusion);
enum class UnknownRegion
{
None,
Inclusion,
Background,
All
};
UnknownRegion to_unknownregion(const gmshfem::common::GmshFem& gmshFem);
class Configuration final : public ConfigurationInterface
{
private:
double _xe;
double _xr;
double _ye;
double _yr;
double _He;
double _Hr;
double _Le;
double _Lr;
unsigned int _nxe;
unsigned int _nxr;
unsigned int _nye;
unsigned int _nyr;
double _L;
double _H;
Inclusion _inclusion_type;
bool _isFilled;
double _r;
double _h;
UnknownRegion _unknown_region;
std::array<gmshfem::domain::Domain,2> _background;
std::array<gmshfem::domain::Domain,2> _inclusion;
std::vector<unsigned int> _emitter_idx_X;
std::vector<unsigned int> _emitter_idx_Y;
std::vector<unsigned int> _receiver_idx_X;
std::vector<unsigned int> _receiver_idx_Y;
std::complex<double> _mb;
std::complex<double> _mc;
virtual void wave_mesh() const;
virtual void data_mesh() const;
public:
Configuration(const gmshfem::common::GmshFem& gmshFem);
bool receiversAreEmittersX () const {return (std::abs(_xe-_xr)<1e-14) && (std::abs(_He-_Hr)<1e-14) && (_nxe==_nxr);};
bool receiversAreEmittersY () const {return (std::abs(_ye-_yr)<1e-14) && (std::abs(_Le-_Lr)<1e-14) && (_nye==_nyr);};
bool isFilled() const {return _isFilled;};
Inclusion inclusion() const {return _inclusion_type;};
unsigned int nxe() const {return _nxe;};
unsigned int nxr() const {return _nxr;};
unsigned int nye() const {return _nye;};
unsigned int nyr() const {return _nyr;};
virtual void mesh() const;
virtual double array() const {return std::max(_He,_Le);};
virtual double depth() const {return std::max(_H,_L)/2.;};
virtual double m_reference() const {return std::real(_mb);};
virtual std::string wave_gmodel() const {return "inclusion";};
virtual std::string model_gmodel() const {return "inclusion";};
virtual std::string data_gmodel() const {return "inclusion";};
};
template<Physic T_Physic>
ModelFunction green0_preconditioner(const WaveMultiField<T_Physic>& g, const Configuration* const config);
} // namespace soil
#endif // H_CONFIGURATION_SOIL
#ifndef H_NEW_CONFIGURATION
#define H_NEW_CONFIGURATION
//Standard Library
#include <string>
//GmshFem Library
#include "GmshFem.h"
#include "Exception.h"
//FWI Library
#include "soil.h"
#include "inclusion.h"
ConfigurationInterface* newConfiguration(const gmshfem::common::GmshFem& gmshFem)
{
std::string configuration;
if(!gmshFem.userDefinedParameter(configuration, "configuration"))
{
throw gmshfem::common::Exception("Configuration type could not be found.");
}
if(configuration=="soil"){return new soil::Configuration(gmshFem);}
else if(configuration=="inclusion"){return new inclusion::Configuration(gmshFem);}
else
{
throw gmshfem::common::Exception("Configuration " + configuration + " is not valid.");
return NULL;
}
}
#endif // H__NEW_CONFIGURATION
//Standard Library
#include <numeric>
//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 "soil.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;
/*
using namespace gmshfem::field;
using namespace gmshfem::problem;
using namespace gmshfem::equation;
*/
static const std::complex< double > im = std::complex< double >(0., 1.);
namespace soil
{
ModelFunction bilinearInterpolation(std::string filename)
{
/*
The 2D table has the following elements (nx = number of x values; ny = number of y values)
nx ny
x(1) x(2) x(3) ... x(nx)
y(1) y(2) y(3) ... y(ny)
g(x(1),y(1)) g(x(2),y(1)) g(x(3),y(1)) ... g(x(nx),y(1))
g(x(1),y(2)) g(x(2),y(2)) g(x(3),y(2)) ... g(x(nx),y(2))
g(x(1),y(3)) g(x(2),y(3)) g(x(3),y(3)) ... g(x(nx),y(3))
...
g(x(1),y(ny)) g(x(2),y(ny)) g(x(3),y(ny)) ... g(x(nx),y(ny))
*/
unsigned int nx;
unsigned int ny;
CSVio file(filename,' ',OpeningMode::Reading);
file >> nx;
file >> ny;
if( !file.isEOL() )
{
throw Exception(filename+" does not have the appropriate format: first line has more than two values.");
}
std::vector<double> x(nx,0.);
for (unsigned int j = 0; j < nx; j++)
{
file >> x[j];
x[j] /= 1000.;//length units are km!
if( file.isEOL() ){break;}
}
std::vector<double> y(ny,0.);
for (unsigned int i = 0; i < ny; i++)
{
file >> y[i];
y[i] /= 1000.;//length units are km!
if( file.isEOL() ){break;}
}
if( (!std::is_sorted(x.begin(),x.end())) || (!std::is_sorted(y.begin(),y.end())) )
{
throw Exception(filename+" does not have the appropriate format: second and third line must be sorted");
}
if( (x.size() != nx) || (y.size() != ny) )
{
throw Exception(filename+" does not have the appropriate format: second and third line must have "+std::to_string(nx)+" and "+std::to_string(ny)+" values.");
}
std::vector< std::vector< std::complex<double> > > data(nx,std::vector< std::complex<double> >(ny,0.));
for (unsigned int j = 0; j < ny; j++)
{
for (unsigned int i = 0; i < nx; i++)
{
double tmp;
file >> tmp;
data[i][j] = std::complex<double>(tmp/1000.,0.); //lengths units are km!
}
}
file.close();
return gmshfem::function::bilinearInterpolation<std::complex<double>>(x,y,data);
}
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=="soil") {return UnknownRegion::Soil;}
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(const GmshFem& gmshFem) : ConfigurationInterface(gmshFem)
{
msg::print << "Initialize soil configuration." << msg::endl;
/*
* MESH
*/
if(
!(
gmshFem.userDefinedParameter(_xoffset, "xoffset") &&
gmshFem.userDefinedParameter(_ymax, "ymax") &&
gmshFem.userDefinedParameter(_Ler, "Ler") &&
gmshFem.userDefinedParameter(_ner, "ner") &&
gmshFem.userDefinedParameter(_L, "L") &&
gmshFem.userDefinedParameter(_H, "H") &&
gmshFem.userDefinedParameter(_h, "h")
)
)
{
throw common::Exception("A geometric parameter could not be found.");
}
mesh();
/*
* DOMAIN
*/
_data_omega = Domain(2,1);
_soil[Support::BLK] = Domain(2, 21);
_soil[Support::BND] = Domain(1, 11);
_air[Support::BLK] = Domain(2, 22);
_air[Support::BND] = Domain(1, 12);
_wave_omega[Support::BLK] = _soil[Support::BLK] | _air[Support::BLK];
_wave_omega[Support::BND] = _soil[Support::BND] | _air[Support::BND];
_unknown_region = to_unknownregion(gmshFem);
switch (_unknown_region)
{
case UnknownRegion::None:
_model_known[Support::BLK] = _soil[Support::BLK]|_air[Support::BLK];
_model_known[Support::BND] = _soil[Support::BND] | _air[Support::BND];
break;
case UnknownRegion::Soil:
_model_known[Support::BLK] = _air[Support::BLK];
_model_known[Support::BND] = _air[Support::BND];
_model_unknown[Support::BLK] = _soil[Support::BLK];
_model_unknown[Support::BND] = _soil[Support::BND];
break;
}
_ns = _ner;
_np = _ner;
for (unsigned int p = 0; p < _np; p++)
{
_point.push_back(Domain(0,100+p));
_points |= _point[p];
_emitter.push_back({p});
unsigned int ReceiverOnEmitter = 0;
gmshFem.userDefinedParameter(ReceiverOnEmitter, "ReceiverOnEmitter");
std::vector<unsigned int> rec(_np,0);
std::iota(rec.begin(),rec.end(),0);
if(!ReceiverOnEmitter){rec.erase(rec.begin()+p);}
_receiver.push_back(rec);
}
unsigned int SingleEmitter;
if(gmshFem.userDefinedParameter(SingleEmitter, "SingleEmitter"))
{
_ns=1;
_emitter.resize(0);
_emitter.push_back({SingleEmitter});
}
/*
* Reference model function
*/
double Rev_air,Imv_air;
if(!(
gmshFem.userDefinedParameter(Rev_air, "Re(v_air)") && gmshFem.userDefinedParameter(Imv_air, "Im(v_air)")
))
{
throw common::Exception("Air model parameter could not be found.");
}
_m_air = 1. / (Rev_air + im*Imv_air) / (Rev_air + im*Imv_air);
double Rev_soil,Imv_soil;
if(!(
gmshFem.userDefinedParameter(Rev_soil, "Re(v_soil)") && gmshFem.userDefinedParameter(Imv_soil, "Im(v_soil)")
))
{
throw common::Exception("Air model parameter could not be found.");
}
_m_soil = 1. / (Rev_soil + im*Imv_soil) / (Rev_soil + im*Imv_soil);
ScalarPiecewiseFunction< std::complex< double > > m0;
std::string m0_type;
if(!gmshFem.userDefinedParameter(m0_type, "m0_type"))
{
throw Exception("Reference model type could not be found.");
}
if(m0_type=="file")
{
std::string path = "";
if(!gmshFem.userDefinedParameter(path, "path"))
{
throw common::Exception("Path to soil data could not be found.");
}
m0.addFunction(1. / pow(bilinearInterpolation(path),2) / m_reference() ,_soil[Support::BLK] | _soil[Support::BND] | _points );
m0.addFunction(_m_air / m_reference(),_air[Support::BLK] | _air[Support::BND] );
}
else if(m0_type == "depth")
{
double Rem_0,Imm_0;
if(!(
gmshFem.userDefinedParameter(Rem_0, "Re(v_0)") && gmshFem.userDefinedParameter(Imm_0, "Im(v_0)")
))
{
throw common::Exception("Starting velocity for initial model parameter could not be found.");
}
double Rem_H,Imm_H;
if(!(
gmshFem.userDefinedParameter(Rem_H, "Re(v_H)") && gmshFem.userDefinedParameter(Imm_H, "Im(v_H)")
))
{
throw common::Exception("Final velocity for initial model parameter could not be found.");
}
ScalarFunction< std::complex<double> > vy = (Rem_0+im*Imm_0) - ( (Rem_H+im*Imm_H) - (Rem_0+im*Imm_0) ) / H() * y< std::complex<double> >();
m0.addFunction(1. / pow(vy,2) / m_reference(),_soil[Support::BLK] | _soil[Support::BND]);
m0.addFunction(_m_air / m_reference(),_air[Support::BLK] | _air[Support::BND]);
}
_m0 = m0.copy();
}
void Configuration::mesh() const
{
msg::print << "Generate meshes" << msg::endl;
gmsh::option::setNumber("General.Terminal", 1);
std::string name = "soil";
gmodel::add("soil");
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
{
double Le0 = (_L - _Ler)/2.;
double deltaLer = _Ler/(((double) _ner)-1.);
int pyl = factory::addPoint(_xoffset, _ymax, 0., _h);
int p0l = factory::addPoint(_xoffset, 0., 0., _h);
int pHl = factory::addPoint(_xoffset, -_H, 0., _h);
//Emitters/receivers at y
std::vector<int> py(_ner);
std::vector<int> p0(_ner);
std::vector<int> pH(_ner);
for (unsigned int n = 0; n < _ner; n++)
{
double Ln = Le0 + ((double)n)*deltaLer;
py[n] = factory::addPoint(_xoffset+Ln, _ymax, 0., _h);
p0[n] = factory::addPoint(_xoffset+Ln, 0., 0., _h);
pH[n] = factory::addPoint(_xoffset+Ln, -_H, 0., _h);
}
int pyr = factory::addPoint(_xoffset+_L, _ymax, 0., _h);
int p0r = factory::addPoint(_xoffset+_L, 0., 0., _h);
int pHr = factory::addPoint(_xoffset+_L, -_H, 0., _h);
std::vector<int> ly(_ner+1);
std::vector<int> l0(_ner+1);
std::vector<int> lH(_ner+1);
ly[0] = factory::addLine(pyl, py[0]);
l0[0] = factory::addLine(p0l, p0[0]);
lH[0] = factory::addLine(pHl, pH[0]);
for (unsigned int n = 1; n < _ner; n++)
{
ly[n] = factory::addLine(py[n-1], py[n]);
l0[n] = factory::addLine(p0[n-1], p0[n]);
lH[n] = factory::addLine(pH[n-1], pH[n]);
}
ly[_ner] = factory::addLine(py[_ner-1], pyr);
l0[_ner] = factory::addLine(p0[_ner-1], p0r);
lH[_ner] = factory::addLine(pH[_ner-1], pHr);
std::vector<int> l0_reverse(_ner+1);
std::vector<int> lH_reverse(_ner+1);
for (unsigned int n = 0; n < _ner+1; n++)
{
l0_reverse[n] = -l0[n];
lH_reverse[n] = -lH[n];
}
int l0yl = factory::addLine(p0l,pyl);
int lH0l = factory::addLine(pHl,p0l);
int l0yr = factory::addLine(p0r,pyr);
int lH0r = factory::addLine(pHr,p0r);
std::vector<int> clbv1 = {l0yl};
clbv1.insert(std::end(clbv1), std::begin(ly), std::end(ly));
clbv1.push_back({-l0yr});
clbv1.insert(std::end(clbv1), std::begin(l0_reverse), std::end(l0_reverse));
int clb1 = factory::addCurveLoop({clbv1});
std::vector<int> clbv2 = {lH0l};
clbv2.insert(std::end(clbv2), std::begin(l0), std::end(l0));
clbv2.push_back({-lH0r});
clbv2.insert(std::end(clbv2), std::begin(lH_reverse), std::end(lH_reverse));
int clb2 = factory::addCurveLoop({clbv2});
int s_air = factory::addPlaneSurface({clb1});
int s_soil = factory::addPlaneSurface({clb2});
unsigned int n_ymax = ((unsigned int)std::ceil(_ymax / _h));
unsigned int n_H = ((unsigned int)std::floor(_H / _h));
unsigned int n_r = ((unsigned int)std::ceil(_Ler / _h / (_ner-1)));
unsigned int n_bord = ((unsigned int)std::floor((_L-_Ler) / 2. / _h));
factory::mesh::setTransfiniteCurve(lH0l,n_H);
factory::mesh::setTransfiniteCurve(lH0r,n_H);
factory::mesh::setTransfiniteCurve(l0yl,n_ymax);
factory::mesh::setTransfiniteCurve(l0yr,n_ymax);
factory::mesh::setTransfiniteCurve(ly[0],n_bord);
factory::mesh::setTransfiniteCurve(l0[0],n_bord);
factory::mesh::setTransfiniteCurve(lH[0],n_bord);
factory::mesh::setTransfiniteCurve(ly[_ner],n_bord);
factory::mesh::setTransfiniteCurve(l0[_ner],n_bord);
factory::mesh::setTransfiniteCurve(lH[_ner],n_bord);
for (unsigned int n = 1; n < _ner; n++)
{
factory::mesh::setTransfiniteCurve(ly[n],n_r);
factory::mesh::setTransfiniteCurve(l0[n],n_r);
factory::mesh::setTransfiniteCurve(lH[n],n_r);
}
factory::mesh::setTransfiniteSurface(s_air,"Left",{p0l,pyl,pyr,p0r});
factory::mesh::setTransfiniteSurface(s_soil,"Left",{p0l,p0r,pHr,pHl});
factory::mesh::setRecombine(2,s_air);
factory::mesh::setRecombine(2,s_soil);
for (unsigned int n = 0; n <_ner; n++)
{
gmodel::addPhysicalGroup(0, {p0[n]}, 100+n);
gmodel::setPhysicalName(0, 100+n, "emitter_receiver_"+std::to_string(n));
}
std::vector<int> lsoil = {-lH0r};
lsoil.insert(std::end(lsoil), std::begin(lH_reverse), std::end(lH_reverse));
lsoil.push_back({lH0l});
gmodel::addPhysicalGroup(1, lsoil, 11);
gmodel::setPhysicalName(1, 11, "soil_bnd");
std::vector<int> lair = {l0yl};
lair.insert(std::end(lair), std::begin(ly), std::end(ly));
lair.push_back({-l0yr});
gmodel::addPhysicalGroup(1, lair, 12);
gmodel::setPhysicalName(1, 12, "air_bnd");
gmodel::addPhysicalGroup(2, {s_soil}, 21);
gmodel::setPhysicalName(2, 21, "soil_vol");
gmodel::addPhysicalGroup(2, {s_air}, 22);
gmodel::setPhysicalName(2, 22, "air_vol");
}
void Configuration::data_mesh() const
{
double Le0 = (_L - _Ler)/2.;
double deltaLer = _Ler/(((double) _ner)-1.);
int p00 = factory::addPoint(Le0, Le0,0.,deltaLer);
int pL0 = factory::addPoint(Le0+_Ler, Le0,0.,deltaLer);
int pLL = factory::addPoint(Le0+_Ler, Le0+_Ler,0.,deltaLer);
int p0L = factory::addPoint(Le0, Le0+_Ler,0.,deltaLer);
int ly0 = factory::addLine(p00, pL0);
int lxL = factory::addLine(pL0, pLL);
int lyL = factory::addLine(pLL, p0L);
int lx0 = factory::addLine(p0L, p00);
int cl = factory::addCurveLoop({ly0,lxL,lyL,lx0});
int s1 = factory::addPlaneSurface({cl});
factory::mesh::setTransfiniteCurve(ly0,_ner);
factory::mesh::setTransfiniteCurve(lxL,_ner);
factory::mesh::setTransfiniteCurve(lyL,_ner);
factory::mesh::setTransfiniteCurve(lx0,_ner);
factory::mesh::setTransfiniteSurface(s1,"Left",{p00,pL0,pLL,p0L});
factory::mesh::setRecombine(2,s1);
gmodel::addPhysicalGroup(2, {s1}, 1);
gmodel::setPhysicalName(2, 1, "data_omega");
}
template<Physic T_Physic>
ModelFunction green0_preconditioner(const WaveMultiField<T_Physic>& g, const Configuration* const config)
{
return pow(autocorrelate<T_Physic>(g,config->emitter_idx(true)),2);
}
template ModelFunction green0_preconditioner<Physic::acoustic>(const WaveMultiField<Physic::acoustic>&, const Configuration* const);
} // namespace soil
#ifndef H_CONFIGURATION_SOIL
#define H_CONFIGURATION_SOIL
//GmshFEM Library
#include "GmshFem.h"
//#include "Function.h"
//GmshFWI Library
#include "../../common/configuration.h"
#include "../../common/wave/element.h"
namespace soil
{
ModelFunction bilinearInterpolation(std::string filename);
enum class UnknownRegion
{
None,
Soil
};
UnknownRegion to_unknownregion(const gmshfem::common::GmshFem& gmshFem);
class Configuration final : public ConfigurationInterface
{
private:
double _Ler;
unsigned int _ner;
double _xoffset;
double _ymax;
double _L;
double _H;
double _h;
std::array<gmshfem::domain::Domain,2> _soil; std::array<gmshfem::domain::Domain,2> _air;
std::complex<double> _m_air;
std::complex<double> _m_soil;
UnknownRegion _unknown_region;
virtual void wave_mesh() const;
virtual void data_mesh() const;
public:
Configuration(const gmshfem::common::GmshFem& gmshFem);
virtual void mesh() const;
unsigned int ner() const {return _ner;};
double H() const {return _H;};
virtual double array() const {return _Ler;};
virtual double depth() const {return _H;};
virtual double m_reference() const {return std::real(_m_soil);};
virtual std::string wave_gmodel() const {return "soil";};
virtual std::string model_gmodel() const {return "soil";};
virtual std::string data_gmodel() const {return "soil";};
};
template<Physic T_Physic>
ModelFunction green0_preconditioner(const WaveMultiField<T_Physic>& g, const Configuration* const config);
} // namespace soil
#endif // H_CONFIGURATION_SOIL
#ifndef H_DATA_DISCRETIZATION
#define H_DATA_DISCRETIZATION
//Standard library
#include <string>
//GmshFem library
#include "GmshFem.h"
#include "FunctionSpaceForm0.h"
#include "Message.h"
//FWI
#include "../physic.h"
namespace data
{
template<Physic T_physic>
class Discretization {};
/* acoustic */
template<>
class Discretization<Physic::acoustic>
{
private:
gmshfem::field::FunctionSpaceTypeForm0 _functionSpaceType;
unsigned int _functionSpaceDegree;
std::string _integrationType;
public:
Discretization(const gmshfem::common::GmshFem& gmshFem);
gmshfem::field::FunctionSpaceTypeForm0 functionSpaceType() const {return _functionSpaceType;};
std::string integrationType(unsigned int integrandFieldNumber) const
{
return _integrationType + std::to_string(integrandFieldNumber*_functionSpaceDegree);
};
std::string integrationType() const {return _integrationType;};
unsigned int functionSpaceDegree() const {return _functionSpaceDegree;};
void functionSpaceDegree(unsigned int order) {_functionSpaceDegree=order;};
};
}; // namespace data
#endif // H_DATA_DISCRETIZATION
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment