diff --git a/specific/configuration/flexible_acquisition.cpp b/specific/configuration/flexible_acquisition.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b16a83972e6a2c533218213d7ec8364a06748a8b --- /dev/null +++ b/specific/configuration/flexible_acquisition.cpp @@ -0,0 +1,546 @@ +//Standard Library +#include <numeric> +#include <array> + +//GmshFEM Library +#include "GmshFem.h" +#include "Exception.h" +#include "Message.h" +#include "Domain.h" +#include "Function.h" +#include "CSVio.h" + +//Gmsh Library +#include "gmsh.h" + +//GmshFWI Library +#include "../../common/model/macro.h" +#include "../../common/data/element.h" +#include "../wave/correlation.h" +#include "flexible_acquisition.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 flexible_acquisition +{ + + /* + * class Configuration + */ + Configuration::Configuration(std::string name, const ParametrizationInterface* const parametrization, const GmshFem& gmshFem) : ConfigurationInterface(name, parametrization, gmshFem) + { + msg::print << "Initialize flexible configuration" << msg::endl; + + /* + * MESH + */ + if( + !( + gmshFem.userDefinedParameter(_H, "H") && + gmshFem.userDefinedParameter(_L, "L") && + gmshFem.userDefinedParameter(_Hsub, "Hsub") && + gmshFem.userDefinedParameter(_h, "h") + ) + ) + { + throw common::Exception("A geometric parameter could not be found."); + } + + // Setup E/R + _er_positions.emplace_back(0.4, -0.5); + _er_positions.emplace_back(0.5, -0.5); + _er_positions.emplace_back(0.6, -0.5); + + mesh(); + + /* + * DOMAIN + */ + // TODO: actual data mesh! + _data_omega = Domain("supersurface") | Domain("subsurface"); + + + std::string unknownRegion = "subsurface"; + gmshFem.userDefinedParameter(unknownRegion, "unknown"); + if (unknownRegion == "subsurface") + { + _model_known[Support::BLK] = Domain("supersurface"); + _model_known[Support::BND] = Domain("supersurface_bnd"); + + _model_unknown[Support::BLK] = Domain("subsurface"); + _model_unknown[Support::BND] = Domain("subsurface_bnd"); + } + else if (unknownRegion == "none") + { + _model_known[Support::BLK] = Domain("supersurface") | Domain("subsurface"); + _model_known[Support::BND] = Domain("supersurface_bnd") | Domain("subsurface_bnd"); + } + else { + throw Exception("Invalid unknown region type: " + unknownRegion); + } + + _wave_omega[Support::BLK] = _model_known[Support::BLK] | _model_unknown[Support::BLK]; + _wave_omega[Support::BND] = _model_known[Support::BND] | _model_unknown[Support::BND]; + + // Once Dirichlet BCs are added + //_named_domains() ... + + /* + * Reference model function + */ + + /* + _m_super.resize(model_size()); + _m_sub.resize(model_size()); + for (unsigned int c = 0; c < model_size(); c++) + { + ScalarPiecewiseFunction<std::complex<double>> m0; + std::string suffix = "c" + std::to_string(c); + double Rem_super, Imm_super, Rem_sub, Imm_sub; + if (!( + gmshFem.userDefinedParameter(Rem_super, "Re(m_super" + suffix + ")") && gmshFem.userDefinedParameter(Imm_super, "Im(m_super" + suffix + ")") && + gmshFem.userDefinedParameter(Rem_sub, "Re(m_sub" + suffix + ")") && gmshFem.userDefinedParameter(Imm_sub, "Im(m_sub" + suffix + ")"))) + { + throw common::Exception("A model component " + suffix + " could not be found."); + } + _m_super[c] = Rem_super + im * Imm_super; + _m_sub[c] = Rem_sub + im * Imm_sub; + _mc[c] = _m_sub[c]; + + m0.addFunction(_m_super[c], _supersurface[Support::BLK] | _supersurface[Support::BND] | _points); + + std::string m0_type; + if (!gmshFem.userDefinedParameter(m0_type, "m0_type" + suffix)) + { + throw Exception("Reference model type could not be found."); + } + + if (m0_type == "file") + { + std::string path = ""; + if (!gmshFem.userDefinedParameter(path, "m0_path" + suffix)) + { + throw common::Exception("Path to subsurface data could not be found."); + } + m0.addFunction(bilinearInterpolation(path), _subsurface[Support::BLK] | _subsurface[Support::BND]); + } + else if (m0_type == "file.pos") + { + std::string path = ""; + if (!gmshFem.userDefinedParameter(path, "m0_path" + suffix)) + { + throw common::Exception("Path to subsurface data could not be found."); + } + + gmsh::merge(path + suffix + ".pos"); + ScalarFunction<std::complex<double>> mpos = probeScalarView<std::complex<double>>(c); + + m0.addFunction(mpos, _subsurface[Support::BLK] | _subsurface[Support::BND]); + } + else if (m0_type == "inverse_linear_squared") + { + double Rea_0, Ima_0; + if (!( + gmshFem.userDefinedParameter(Rea_0, "Re(a0" + suffix + ")") && gmshFem.userDefinedParameter(Ima_0, "Im(a0" + suffix + ")"))) + { + throw common::Exception("Initial model parameter (a0) could not be found."); + } + + double Rea_H, Ima_H; + if (!( + gmshFem.userDefinedParameter(Rea_H, "Re(aH" + suffix + ")") && gmshFem.userDefinedParameter(Ima_H, "Im(aH" + suffix + ")"))) + { + throw common::Exception("Initial model parameter (aH) could not be found."); + } + + ScalarFunction<std::complex<double>> num = (Rea_0 + im * Ima_0) - ((Rea_H + im * Ima_H) - (Rea_0 + im * Ima_0)) / H() * y<std::complex<double>>(); + m0.addFunction(1. / pow(num, 2), _subsurface[Support::BLK] | _subsurface[Support::BND]); + } + else if (m0_type == "linear") + { + double Rea_0, Ima_0; + if (!( + gmshFem.userDefinedParameter(Rea_0, "Re(a0" + suffix + ")") && gmshFem.userDefinedParameter(Ima_0, "Im(a0" + suffix + ")"))) + { + throw common::Exception("Initial model parameter (a0) could not be found."); + } + + double Rea_H, Ima_H; + if (!( + gmshFem.userDefinedParameter(Rea_H, "Re(aH" + suffix + ")") && gmshFem.userDefinedParameter(Ima_H, "Im(aH" + suffix + ")"))) + { + throw common::Exception("Initial model parameter (aH) could not be found."); + } + + ScalarFunction<std::complex<double>> lin = (Rea_0 + im * Ima_0) - ((Rea_H + im * Ima_H) - (Rea_0 + im * Ima_0)) / H() * (y<std::complex<double>>() + _ymin); + m0.addFunction(lin, _subsurface[Support::BLK] | _subsurface[Support::BND]); + } + else if (m0_type == "constant") + { + m0.addFunction(_m_sub[c], _subsurface[Support::BLK] | _subsurface[Support::BND]); + } + else + { + throw common::Exception("Initial model type (" + suffix + ") " + m0_type + " is unknown."); + } + _m0.push_back(m0); + } + */ + // MODEL ON SUBSURFACE, SURFACE + + /* + _mb.resize(model_size()); + _mi.resize(model_size()); + for (unsigned int c = 0; c < model_size(); c++) + { + std::string suffix = "c"+std::to_string(c); + double Remb, Immb; + if + (! + ( + gmshFem.userDefinedParameter(Remb, "Re(mb"+suffix+")") && + gmshFem.userDefinedParameter(Immb, "Im(mb"+suffix+")") + ) + ) + { + throw common::Exception("Background (reference) model parameter (component "+suffix+" ) could not be found."); + } + else + { + _mb[c] = Remb + im * Immb; + _mc[c] = _mb[c]; + } + ScalarPiecewiseFunction< std::complex< double > > m0; + std::string m0_type = "constant"; + if(!gmshFem.userDefinedParameter(m0_type, "m0_type"+suffix)) + { + msg::warning << "Reference model type could not be found. Constant background is used (default)." << msg::endl; + } + if(m0_type=="file") + { + std::string path = ""; + if(!gmshFem.userDefinedParameter(path, "m0_path"+suffix)) + { + throw common::Exception("Path to circular data could not be found."); + } + m0.addFunction(bilinearInterpolation(path),_background[Support::BLK] | _background[Support::BND] ); + } + else if(m0_type=="file.pos") + { + std::string path = ""; + if(!gmshFem.userDefinedParameter(path, "m0_path"+suffix)) + { + throw common::Exception("Path to model file could not be found."); + } + + gmsh::merge(path+suffix+".pos"); + ScalarFunction<std::complex<double>> mpos = probeScalarView<std::complex<double>>(c); + + m0.addFunction(mpos,_background[Support::BLK] | _background[Support::BND]); + } + else if(m0_type=="constant") + { + m0.addFunction(_mb[c],_background[Support::BLK] | _background[Support::BND]); + } + else + { + throw common::Exception("Initial model type ("+ suffix + ") " + m0_type +" is unknown."); + } + + _mi[c].resize(_ni); + for (unsigned int i = 0; i < _ni; i++) + { + double Remi=0., Immi=0.; + if + ( + !(gmshFem.userDefinedParameter(Remi, "Re(mi"+std::to_string(i)+suffix+")") && + gmshFem.userDefinedParameter(Immi, "Im(mi"+std::to_string(i)+suffix+")")) + ) + { + throw Exception("Inclusion model parameter could not be found."); + } + _mi[c][i] = Remi + im * Immi; + m0.addFunction(_mi[c][i],_inclusion[i][Support::BLK] | _inclusion[i][Support::BND]); + } + _m0.push_back(m0); + }*/ + } + + + void Configuration::wave_mesh() const + { + int p0 = factory::addPoint(0., -_H, 0., _h); + int p1 = factory::addPoint(_L, -_H, 0., _h); + int p2 = factory::addPoint(_L, -_Hsub, 0., _h); + int p3 = factory::addPoint(0., -_Hsub, 0., _h); + int p4 = factory::addPoint(_L, 0., 0., _h); + int p5 = factory::addPoint(0., 0., 0., _h); + + // All horizontal lines defined left to right, vertical bottom to top + int lineBottom = factory::addLine(p0, p1); + int lineSub = factory::addLine(p3, p2); + int lineTop = factory::addLine(p5, p4); + int lineLeftSub = factory::addLine(p0, p3); + int lineLeftSuper = factory::addLine(p3, p5); + int lineRightSub = factory::addLine(p1, p2); + int lineRightSuper = factory::addLine(p2, p4); + + int clSub = factory::addCurveLoop({lineBottom, lineRightSub, -lineSub, -lineLeftSub}); + int clSuper = factory::addCurveLoop({lineSub, lineRightSuper, -lineTop, -lineLeftSuper}); + + int sSub = factory::addPlaneSurface({clSub}); + int sSuper = factory::addPlaneSurface({clSuper}); + + std::vector<int> p_er; + // Emitters and receivers + for (auto pos: _er_positions) { + p_er.push_back(factory::addPoint(pos.first, pos.second, 0.0, _h)); + } + + factory::synchronize(); + + // Embed the e/r. Check if they're in the subsurface or supersurface + for (unsigned i = 0; i < p_er.size(); ++i) { + bool isSub = _er_positions[i].second < (-_Hsub); + gmodel::mesh::embed(0, {p_er[i]}, 2, isSub ? sSub : sSuper); + + } + + //gmodel::addPhysicalGroup(2, {}, 1000+p); + //gmodel::setPhysicalName(0, 1000+p, "emitter_receiver_"+std::to_string(p)); + + gmodel::addPhysicalGroup(2, {sSub}, 21); + gmodel::setPhysicalName(2, 21, "subsurface"); + gmodel::addPhysicalGroup(2, {sSuper}, 22); + gmodel::setPhysicalName(2, 22, "supersurface"); + + gmodel::addPhysicalGroup(1, {lineLeftSub, lineBottom, lineRightSub}, 11); + gmodel::setPhysicalName(1, 11, "subsurface_bnd"); + gmodel::addPhysicalGroup(1, {lineLeftSuper, lineTop, lineRightSuper}, 12); + gmodel::setPhysicalName(1, 12, "supersurface_bnd"); + + for (unsigned p = 0; p < p_er.size(); ++p) { + gmodel::addPhysicalGroup(0, {p_er[p]}, 1000+p); + gmodel::setPhysicalName(0, 1000+p, "emitter_receiver_"+std::to_string(p)); + } +/* + + //Vertical emitters + std::vector<int> pnt(_np); + double DAngle = 2. * M_PI /((double) _np); + for (unsigned int p = 0; p < _np; p++) + { + double angle = ((double)p) * DAngle; + pnt[p] = factory::addPoint(_rer*std::cos(angle), _rer*std::sin(angle), 0., _h); + } + + int sb; + std::vector<int> si; + std::vector<std::vector<int>> li(_ni); + std::vector<int> li_tot; + if(_ni!=0) + { + std::vector<int> cli(_ni,0); + if(_areFilled){si.resize(_ni);} + for (unsigned int i = 0; i < _ni; i++) + { + li[i] = _inclusion_geo[i]->addInclusion(); + li_tot.insert(li_tot.end(), li[i].begin(), li[i].end()); + cli[i] = factory::addCurveLoop(li[i]); + if(_areFilled) + { + si[i] = factory::addPlaneSurface({cli[i]}); + } + } + std::vector<int> clbcli = cli; + clbcli.insert(clbcli.begin(), clb); + sb = factory::addPlaneSurface(clbcli); + } + else + { + sb = factory::addPlaneSurface({clb}); + } + + + factory::synchronize(); + gmodel::mesh::embed(0, pnt, 2, sb); + + for (unsigned int p = 0; p <_np; p++) + { + gmodel::addPhysicalGroup(0, {pnt[p]}, 1000+p); + gmodel::setPhysicalName(0, 1000+p, "emitter_receiver_"+std::to_string(p)); + } + + gmodel::addPhysicalGroup(1, {lb1,lb2,lb3,lb4}, 12); + gmodel::setPhysicalName(1, 12, "background_bnd"); + gmodel::addPhysicalGroup(2, {sb}, 21); + gmodel::setPhysicalName(2, 21, "background_vol"); + for (unsigned int i = 0; i < _ni; i++) + { + if(_areFilled) + { + gmodel::addPhysicalGroup(2, {si[i]}, 1000+i); + gmodel::setPhysicalName(2, 1000+i, "inclusion_vol"+std::to_string(i)); + } + else + { + gmodel::addPhysicalGroup(1, li[i], 2000+i); + gmodel::setPhysicalName(1, 2000+i, "inclusion_bnd"+std::to_string(i)); + } + }*/ + } + void Configuration::data_mesh() const + { + // TODO + /* + double DAngle = 2. * M_PI /((double) _np); + double Ds_e = DAngle * _emitter_skip * _rer; + double Ds_r = DAngle * _receiver_skip * _rer; + double Le0 = DAngle * _emitter_offset * _rer; + double Lr0 = DAngle * _receiver_offset * _rer; + double Le = (_ne-1) * Ds_e; + double Lr = (_nr-1) * Ds_r; + + int p0 = factory::addPoint(Le0, Lr0, 1.); + int p1 = factory::addPoint(Le0+Le, Lr0, 1.); + int p2 = factory::addPoint(Le0+Le, Lr0+Lr, 1.); + int p3 = factory::addPoint(Le0, Lr0+Lr, 1.); + + int l0 = factory::addLine(p0, p1); + int l1 = factory::addLine(p1, p2); + int l2 = factory::addLine(p2, p3); + int l3 = factory::addLine(p3, p0); + + int cl = factory::addCurveLoop({l0,l1,l2,l3}); + int s1 = factory::addPlaneSurface({cl}); + + factory::mesh::setTransfiniteCurve(l0,_ne); + factory::mesh::setTransfiniteCurve(l1,_nr); + factory::mesh::setTransfiniteCurve(l2,_ne); + factory::mesh::setTransfiniteCurve(l3,_nr); + factory::mesh::setTransfiniteSurface(s1,"Left",{p0,p1,p2,p3}); + + factory::mesh::setRecombine(2,s1); + + gmodel::addPhysicalGroup(2, {s1}, 1); + gmodel::setPhysicalName(2, 1, "data_omega"); + + */ + } + + std::array<unsigned int,2> Configuration::data_coordinate_to_index(double xs, double xr) const + { + throw Exception("Unimplemented Configuration::data_coordinate_to_index"); + /* + if( (!_receiver_on_emitter) ) + { + throw Exception("Data space when an emitter is not also a receiver is not implemented yet"); + } + std::array<unsigned int,2> index; + + double DAngle = 2. * M_PI /((double) _np); + double Ds_e = DAngle * _emitter_skip * _rer; + double Ds_r = DAngle * _receiver_skip * _rer; + double Le0 = DAngle * _emitter_offset * _rer; + double Lr0 = DAngle * _receiver_offset * _rer; + index[0] = std::round( (xs-Le0) / Ds_e ); + index[1] = std::round( (xr-Lr0) / Ds_r ); + + return index; + */ + } + + std::array<double,2> Configuration::index_to_data_coordinate(unsigned int s, unsigned int r) const + { + throw Exception("Unimplemented Configuration::index_to_data_coordinate"); + + /* + if( (!_receiver_on_emitter) ) + { + throw Exception("Data space when an emitter is not also a receiver is not implemented yet"); + } + + std::array<double,2> index; + + double DAngle = 2. * M_PI /((double) _np); + double Ds_e = DAngle * _emitter_skip * _rer; + double Ds_r = DAngle * _receiver_skip * _rer; + double Le0 = DAngle * _emitter_offset * _rer; + double Lr0 = DAngle * _receiver_offset * _rer; + index[0] = Le0 + ((double)s) * Ds_e; + index[1] = Lr0 + ((double)r) * Ds_r; + + return index;*/ + } + + double Configuration::data_area() const + { + throw Exception("Unimplemented Configuration::data_area"); + /* + double DAngle = 2. * M_PI /((double) _np); + double Ds_e = DAngle * _emitter_skip * _rer; + double Ds_r = DAngle * _receiver_skip * _rer; + double Le = (_ne-1) * Ds_e; + double Lr = (_nr-1) * Ds_r; + + return Le * Lr; + */ + }; + + double Configuration::datapoint_area() const + { + throw Exception("Unimplemented Configuration::datapoint_area"); + /* + double DAngle = 2. * M_PI /((double) _np); + double Ds_e = DAngle * _emitter_skip * _rer; + double Ds_r = DAngle * _receiver_skip * _rer; + + return Ds_e * Ds_r;*/ + }; + + bool Configuration::data_coordinate_isValid(double xs,double xr) const + { + throw Exception("Unimplemented Configuration::data_coordinate_isValid"); + + /* + double DAngle = 2. * M_PI /((double) _np); + double Ds_e = DAngle * _emitter_skip * _rer; + double Ds_r = DAngle * _receiver_skip * _rer; + double Le0 = DAngle * _emitter_offset * _rer; + double Lr0 = DAngle * _receiver_offset * _rer; + double Le = (_ne-1) * Ds_e; + double Lr = (_nr-1) * Ds_r; + + double eps = 1e-8; + gmsh::option::getNumber("Geometry.MatchMeshTolerance",eps); + if( (Le0-eps <= xs) && (xs <= Le0+Le+eps) && (Lr0-eps <= xr) && (xr <= Lr0+Lr+eps) ) + { + return true; + } + else + { + return false; + } + + */ + } + + template<Physic T_Physic> + ModelMonoFunction green0_preconditioner(const Data<T_Physic>& dd, const WaveMultiField<T_Physic>& g, const Configuration* const config) + { + return autocorrelate<T_Physic>(g,config->emitter_idx())*autocorrelate<T_Physic>(g,config->receiver_idx()); + } + + template ModelMonoFunction green0_preconditioner<Physic::acoustic>(const Data<Physic::acoustic>&, const WaveMultiField<Physic::acoustic>&, const Configuration* const); + template ModelMonoFunction green0_preconditioner<Physic::electromagnetic>(const Data<Physic::electromagnetic>&, const WaveMultiField<Physic::electromagnetic>&, const Configuration* const); + template ModelMonoFunction green0_preconditioner<Physic::elastodynamic>(const Data<Physic::elastodynamic>&, const WaveMultiField<Physic::elastodynamic>&, const Configuration* const); + +} // namespace circular_acquisition diff --git a/specific/configuration/flexible_acquisition.h b/specific/configuration/flexible_acquisition.h new file mode 100644 index 0000000000000000000000000000000000000000..b8c40af0747f84092c65397cda5bc16ebea0a8cb --- /dev/null +++ b/specific/configuration/flexible_acquisition.h @@ -0,0 +1,114 @@ +#ifndef H_CONFIGURATION_FLEXIBLE_ACQUISITION +#define H_CONFIGURATION_FLEXIBLE_ACQUISITION + +//GmshFEM Library +#include "GmshFem.h" +//#include "Function.h" + +//GmshFWI Library +#include "../../common/configuration.h" +#include "../../common/wave/element.h" +#include "inclusion/inclusion.h" + +//Forward declaration +template<Physic T_Physic> +class Data; + +namespace flexible_acquisition +{ + + class Configuration final : public ConfigurationInterface + { + private: + + /** + * Emetters and receivers are stored together, and for each shot, one point is set as emitter, + * and some others (potentially including the emitter) are enabled as receivers + */ + std::vector<std::pair<double, double>> _er_positions; + + struct ShotConfig { + unsigned int emetterIdx; + std::vector<unsigned int> enabledReceivers; + }; + + std::vector<ShotConfig> _shotsConfigs; + + /* Domain is a rectangle. "x" goes from 0 to L and "y" from -H to 0. Known part is y between 0 and -Hsub*/ + double _H; + double _L; + double _Hsub; + + // Mesh resolution + double _h; + + // TODO + std::vector<unsigned int> _emitter_idx; + std::vector<unsigned int> _receiver_idx; + + bool _areFilled; + + // Subdomains: all in the parent class + /* + double _rer; + double _rext; + + unsigned int _ne; + unsigned int _nr; + unsigned int _emitter_offset; + unsigned int _receiver_offset; + unsigned int _emitter_skip; + unsigned int _receiver_skip; + bool _receiver_on_emitter; + + unsigned int _ni; + + std::vector<const InclusionInterface*> _inclusion_geo; + + + UnknownRegion _unknown_region; + std::array<gmshfem::domain::Domain,2> _background; + std::array<gmshfem::domain::Domain,2> _inclusions; + std::vector<std::array<gmshfem::domain::Domain,2>> _inclusion; + + + + std::vector<std::complex<double>> _mb; + std::vector<std::vector<std::complex<double>>> _mi; +*/ + + + + virtual void wave_mesh() const; + virtual void data_mesh() const; + public: + Configuration(std::string name, const ParametrizationInterface* const parametrization, const gmshfem::common::GmshFem& gmshFem); + + const std::vector<unsigned int>& emitter_idx() const {return _emitter_idx;}; + const std::vector<unsigned int>& receiver_idx() const {return _receiver_idx;}; + + bool areFilled() const {return _areFilled;}; + unsigned int ner() const {return _np;}; + +// virtual void mesh() const; + + virtual std::array<unsigned int,2> data_coordinate_to_index(double xs, double xr) const; + virtual std::array<double,2> index_to_data_coordinate(unsigned int s, unsigned int r) const; + virtual bool data_coordinate_isValid(double xs,double xr) const; + + virtual double area() const {return _H * _L;}; + virtual double data_area() const override; + virtual double datapoint_area() const; + virtual double array() const {return 2. * (_L + _H);}; + virtual double depth() const {return _H;}; + + virtual std::string wave_gmodel() const {return _name;}; + virtual std::string model_gmodel() const {return _name;}; + virtual std::string data_gmodel() const {return _name;}; + }; + + template<Physic T_Physic> + ModelMonoFunction green0_preconditioner(const Data<T_Physic>& dd, const WaveMultiField<T_Physic>& g, const Configuration* const config); +} // namespace soil + +#endif // H_CONFIGURATION_FLEXIBLE_ACQUISITION diff --git a/specific/configuration/newConfiguration.h b/specific/configuration/newConfiguration.h index 992f4e7e1d06e2a89df034c3b87d87ad12673806..2aae0751e872cb8a256b6aed355394a3f5383856 100644 --- a/specific/configuration/newConfiguration.h +++ b/specific/configuration/newConfiguration.h @@ -15,6 +15,7 @@ #include "circular_acquisition.h" #include "line_acquisition.h" #include "rectangular_acquisition.h" +#include "flexible_acquisition.h" ConfigurationInterface* newConfiguration(std::string name, const ParametrizationInterface* const parametrization, const gmshfem::common::GmshFem& gmshFem) { @@ -29,6 +30,7 @@ ConfigurationInterface* newConfiguration(std::string name, const Parametrization else if(configuration=="circular_acquisition"){return new circular_acquisition::Configuration(name, parametrization, gmshFem);} else if(configuration=="line_acquisition"){return new line_acquisition::Configuration(name, parametrization, gmshFem);} else if(configuration=="rectangular_acquisition"){return new rectangular_acquisition::Configuration(name, parametrization, gmshFem);} + else if(configuration=="flexible_acquisition"){return new flexible_acquisition::Configuration(name, parametrization, gmshFem);} else { throw gmshfem::common::Exception("Configuration" + configuration + " is not valid.");