diff --git a/CMakeLists.txt b/CMakeLists.txt index 8aa39abbedd6b7a15357b61d7b0dc586a4d56e0e..7bc72217e2143b8cf5e795459c3cd5b2b30657b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -185,6 +185,15 @@ endif(NOT GMSH_INC) list(APPEND EXTRA_INCS ${GMSH_INC}) list(APPEND EXTRA_LIBS ${GMSH_LIB}) +# Yaml-cpp +option(ENABLE_YAML_CPP "Enable YAML-CPP library" ON) + +if(ENABLE_YAML_CPP) + find_package(yaml-cpp REQUIRED) + add_definitions(-DENABLE_YAML_CPP) +endif() + + # GmshFem find_library(GMSHFEM_LIB gmshfem) @@ -211,10 +220,15 @@ find_package(OpenMP) if(OPENMP_FOUND) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") endif(OPENMP_FOUND) - if(APPLE AND EXISTS "/usr/local/opt/libomp") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Xpreprocessor -fopenmp -I/usr/local/opt/libomp/include") list(APPEND EXTRA_LIBS "-L/usr/local/opt/libomp/lib -lomp") +elseif(APPLE AND EXISTS "/opt/local/lib/libomp") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Xpreprocessor -fopenmp -I/opt/local/include/libomp") + list(APPEND EXTRA_LIBS "-L/opt/local/lib/libomp -lomp") +elseif(APPLE AND EXISTS "/opt/homebrew/opt/libomp") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Xpreprocessor -fopenmp -I/opt/homebrew/opt/libomp/include") + list(APPEND EXTRA_LIBS "-L/opt/homebrew/opt/libomp/lib -lomp") endif() include_directories(${EXTRA_INCS}) @@ -222,28 +236,38 @@ include_directories(${EXTRA_INCS}) file( GLOB LIB_SOURCES contrib/blossom5v2.05/*.cpp contrib/blossom5v2.05/*/*.cpp common/*/*/*.cpp common/*/*.cpp common/*.cpp specific/*/*/*.cpp specific/*/*.cpp specific/*.cpp) file( GLOB LIB_HEADERS contrib/blossom5v2.05/*.h contrib/blossom5v2.05/*/*.h common/*/*/*.h common/*/*.h common/*.h specific/*/*/*.h specific/*/*.h specific/*.h) add_library( fwi ${LIB_SOURCES} ${LIB_HEADERS}) +target_link_libraries(fwi yaml-cpp) -add_executable( synthetics synthetics.cpp ${EXTRA_INCS}) +add_executable( synthetics synthetics.cpp ) target_link_libraries( synthetics fwi ${EXTRA_LIBS}) -add_executable( time_synthetics_wave time_synthetics_wave.cpp ${EXTRA_INCS}) -target_link_libraries( time_synthetics_wave fwi ${EXTRA_LIBS}) -add_executable( directional directional.cpp ${EXTRA_INCS}) +#add_executable( time_synthetics_wave time_synthetics_wave.cpp ${EXTRA_INCS}) +#target_link_libraries( time_synthetics_wave fwi ${EXTRA_LIBS}) +add_executable( directional directional.cpp ) target_link_libraries( directional fwi ${EXTRA_LIBS}) -add_executable( directional_field directional_field.cpp ${EXTRA_INCS}) +add_executable( directional_field directional_field.cpp ) target_link_libraries( directional_field fwi ${EXTRA_LIBS}) -add_executable( gradient gradient.cpp ${EXTRA_INCS}) +add_executable( gradient gradient.cpp ) target_link_libraries( gradient fwi ${EXTRA_LIBS}) #add_executable( convergence convergence.cpp ${EXTRA_INCS}) #target_link_libraries( convergence fwi ${EXTRA_LIBS}) #add_executable( preconditioner preconditioner.cpp ${EXTRA_INCS}) #target_link_libraries( preconditioner fwi ${EXTRA_LIBS}) -add_executable( ip_comparison ip_comparison.cpp ${EXTRA_INCS}) +add_executable( ip_comparison ip_comparison.cpp ) target_link_libraries( ip_comparison fwi ${EXTRA_LIBS}) #add_executable( ob_comparison ob_comparison.cpp ${EXTRA_INCS}) #target_link_libraries( ob_comparison fwi ${EXTRA_LIBS}) -add_executable( multiscale multiscale.cpp ${EXTRA_INCS}) +add_executable( multiscale multiscale.cpp ) target_link_libraries( multiscale fwi ${EXTRA_LIBS}) -add_executable( inversion inversion.cpp ${EXTRA_INCS}) +add_executable( inversion inversion.cpp ) target_link_libraries( inversion fwi ${EXTRA_LIBS}) -add_executable( error error.cpp ${EXTRA_INCS}) +add_executable( error error.cpp) target_link_libraries( error fwi ${EXTRA_LIBS}) + + +# Unit tests + +find_package(Boost 1.67.0 COMPONENTS unit_test_framework REQUIRED) +include_directories(${Boost_INCLUDE_DIRS}) + +add_executable(tests tests/test.cpp ${EXTRA_INCS}) +target_link_libraries(tests ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ${EXTRA_LIBS} fwi) diff --git a/common/configuration.cpp b/common/configuration.cpp index 949e9dc77de9542177b68d4e2271aa212091b7c0..c8b5ba2b06679ba15849e1ad36f8cda0618b8478 100644 --- a/common/configuration.cpp +++ b/common/configuration.cpp @@ -6,11 +6,36 @@ //GmshFWI Library #include "configuration.h" +#include <gmsh.h> + +namespace gmodel = gmsh::model; +namespace factory = gmsh::model::geo; using namespace gmshfem; using namespace gmshfem::common; using namespace gmshfem::domain; +void ConfigurationInterface::mesh() const +{ + msg::print << "Generate meshes" << msg::endl; + gmsh::option::setNumber("General.Terminal", 1); + + gmodel::add(_name); + if (!_remesh) + { + gmsh::open(_name + ".msh"); + return; + } + + wave_mesh(); + data_mesh(); + + factory::synchronize(); + gmodel::mesh::generate(); + + gmsh::write(_name + ".msh"); +} + bool ConfigurationInterface::recIsValid(unsigned int shot,unsigned int rec) const { if( !(shot<_ns) && !(rec<nr(shot)) ) @@ -31,7 +56,7 @@ bool ConfigurationInterface::pntIsValid(unsigned int e_r) const { if( !(e_r<_np) ) { - throw Exception("Emitter-receiver "+std::to_string(e_r)+" is out of scope."); + throw Exception("Emitter-receiver "+std::to_string(e_r)+" is out of scope. There are only "+std::to_string(_np)+" points."); } return true; } diff --git a/common/configuration.h b/common/configuration.h index 1c883eef0ca90f7d5cf5da2ae346a7042758d1cd..0bc01eb06fbb3513a2fe08b1098a184eb4ebb6b3 100644 --- a/common/configuration.h +++ b/common/configuration.h @@ -9,6 +9,7 @@ #include "Domain.h" //Standard Library #include <array> +#include <map> //GmshFWI Library #include "model/element.h" #include "model/parametrization.h" @@ -24,6 +25,7 @@ protected: std::array<gmshfem::domain::Domain,2> _wave_omega; std::array<gmshfem::domain::Domain,2> _model_known; std::array<gmshfem::domain::Domain,2> _model_unknown; + std::map<std::string, gmshfem::domain::Domain> _named_domains; gmshfem::domain::Domain _data_omega; unsigned int _np; @@ -52,9 +54,15 @@ public: gmshFem.userDefinedParameter(remesh, "remesh"); _remesh = ((bool) remesh); }; + + ConfigurationInterface() : _name("dummy"), _parametrization(nullptr), _mc(1,0.) + { + _remesh = true; + }; + virtual ~ConfigurationInterface() {delete _parametrization;}; - virtual void mesh() const = 0; + virtual void mesh() const; virtual double area() const = 0; virtual double data_area() const {return gmshfem::post::integrate(1._d_sf,_data_omega,"Gauss0");}; virtual double datapoint_area() const = 0; @@ -77,6 +85,7 @@ public: gmshfem::domain::Domain model_evaldomain() const {return _model_unknown[Support::BLK] | _model_unknown[Support::BND];}; gmshfem::domain::Domain wave_evaldomain() const {return _wave_omega[Support::BLK] | _wave_omega[Support::BND] | _points;}; gmshfem::domain::Domain data_evaldomain() const {return _data_omega;}; + const std::map<std::string, gmshfem::domain::Domain>& named_domains() const {return _named_domains;} gmshfem::domain::Domain emitter(unsigned int shot, unsigned int em) const; gmshfem::domain::Domain receiver(unsigned int shot, unsigned int rec) const; diff --git a/common/data/element.h b/common/data/element.h index 68be381fe302d8e67c5b6e50cd500622d6ca7071..d17c7c3ad16809526f44c63048a7abcda8073bfa 100644 --- a/common/data/element.h +++ b/common/data/element.h @@ -118,6 +118,45 @@ std::complex<double> l2scalp(const Data<T_Physic>& d1,const Data<T_Physic>& d2) } return scalp; } +template<Physic T_Physic> +std::complex<double> l2scalpNoConj(const Data<T_Physic>& d1,const Data<T_Physic>& d2) +{ + areCompatible(d1,d2); + std::complex<double> scalp = 0.; + for (unsigned int f = 0; f < d1.nf(); f++) + { + for (unsigned int s = 0; s < d1.ns(); s++) + { + for (unsigned int r = 0; r < d1.nr(s); r++) + { + scalp += d1.value(f,s,r) * d2.value(f,s,r); + } + } + } + return scalp; +} +// Inner product are not feasible for that physic +template<> +inline std::complex<double> l2scalp<Physic::electromagnetic>(const Data<Physic::electromagnetic>& d1,const Data<Physic::electromagnetic>& d2) +{ + throw gmshfem::common::Exception("Electromagnetism isn't supported here"); +} +template<> +inline std::complex<double> l2scalp<Physic::elastodynamic>(const Data<Physic::elastodynamic>& d1, const Data<Physic::elastodynamic>& d2) +{ + throw gmshfem::common::Exception("Elastodynamics isn't supported here"); +} +template<> +inline std::complex<double> l2scalpNoConj<Physic::electromagnetic>(const Data<Physic::electromagnetic>& d1,const Data<Physic::electromagnetic>& d2) +{ + throw gmshfem::common::Exception("Electromagnetism isn't supported here"); +} +template<> +inline std::complex<double> l2scalpNoConj<Physic::elastodynamic>(const Data<Physic::elastodynamic>& d1, const Data<Physic::elastodynamic>& d2) +{ + throw gmshfem::common::Exception("Elastodynamics isn't supported here"); +} + template<Physic T_Physic> Data<T_Physic> conj(const Data<T_Physic>& d) { diff --git a/common/model/parametrization.h b/common/model/parametrization.h index 6813da8fb9d521b1aa5339b9c10fd3d7b15dbffd..ed84ae68d93af22fe3970aafaa051f0bd1a1423b 100644 --- a/common/model/parametrization.h +++ b/common/model/parametrization.h @@ -52,14 +52,14 @@ public: return out; }; - /* operator() (Only perturbed forward): from external to internal, ms in external parametrization */ + /* operator() (Only perturbed forward): from external to internal, ms in external parametrization. fct is the perturbation */ virtual ModelFunction operator()(const ModelFunction& fct, const ModelFunction& m) const = 0; ModelFunction operator()(const ModelField& field, const ModelFunction& m) const { return operator()(ModelFunction(field),m); }; - /* operator() (Only adjoint and perturbed adjoint): from internal to external, ms is internal parametrization */ + /* operator() (Only adjoint and perturbed adjoint): from internal to external, ms is internal parametrization. Fct contains derivatives in internal. */ virtual Sensitivity operator()(const SensitivityStateEvaluator& fct, Order order, Support support, const ModelStateEvaluator& ms) const = 0; /* size */ diff --git a/common/model/updater.cpp b/common/model/updater.cpp index eaff8e63acde1cea9c0b984e5af2e44d496fb072..3c904bb70b743f29da5068be93c020a9ab607535 100644 --- a/common/model/updater.cpp +++ b/common/model/updater.cpp @@ -70,6 +70,8 @@ void ModelUpdater::update(Type type, const ModelFunction* const m, const ModelFu void ModelUpdater::update(Type type, const ModelField* const m , const ModelField* const dm ) { if(_ms._isUpToDate[type]){return;} + assert(_innerproduct); + assert(_su); switch (type) { @@ -84,11 +86,13 @@ void ModelUpdater::update(Type type, const ModelField* const m , const ModelFiel } break; case Type::AS: - update(Type::FS,m,dm); - _ms._field[type] = _innerproduct->update( - _su->get(to_order(type),Support::BLK,_ms), - _su->get(to_order(type),Support::BND,_ms) - ); + { + update(Type::FS, m, dm); + auto &bulkSensitivity = _su->get(to_order(type), Support::BLK, _ms); + auto &boundarySensitivity = _su->get(to_order(type), Support::BND, _ms); + + _ms._field[type] = _innerproduct->update(bulkSensitivity, boundarySensitivity); + } break; case Type::PFS: if(dm==nullptr) diff --git a/common/statefunctional.cpp b/common/statefunctional.cpp index 5ce04598d83f8cdc3a68607ac0ae09ec72797307..b519bfa6640a12dd6a3da48b1ead6d6be4061d72 100644 --- a/common/statefunctional.cpp +++ b/common/statefunctional.cpp @@ -227,6 +227,7 @@ template<Physic T_Physic> void StateFunctional<T_Physic>::setModelPerturbation(const ModelField& dm) { modelPerturbationIsObsolete(); + // Update model PFS, e.g. copy the field to the model perturbation object std::array<bool,4> ToBeUpdated = {false,true,false,false}; _mu.get(ToBeUpdated,nullptr,&dm); } @@ -304,6 +305,8 @@ double StateFunctional<T_Physic>::performance_regularization() template<Physic T_Physic> const ModelField& StateFunctional<T_Physic>::gradient() { + // Update the model adjoint state and return it. + // TODO: no model sent but FS is updated -> Is it always up to date ? std::array<bool,4> ToBeUpdated = {false,false,true,false}; return _mu.get(ToBeUpdated).field(Type::AS); } @@ -378,6 +381,21 @@ double StateFunctional<T_Physic>::directional1(const ModelField &dm2) return std::real( _innerproduct->product(gradient(),dm2) ); } +template <Physic T_Physic> +double StateFunctional<T_Physic>::directional1direct(const ModelField &dm) +{ + setModelPerturbation(dm); + // Needs data AS (gradient kernel of the objective) and data PFS (perturbation on the receivers) + std::array<bool, 5> DataToBeUpdated = {false, true, true, false, false}; + std::array<bool, 4> ModelToBeUpdated = {false, false, false, false}; + + auto &du = _du.get(DataToBeUpdated, _mu.get(ModelToBeUpdated)); + auto &dataAS = du.state(Type::AS); + auto &dataPFS = du.state(Type::PFS); + + return real(l2scalpNoConj(dataAS, dataPFS)); +} + /* * Second order */ diff --git a/common/statefunctional.h b/common/statefunctional.h index 267cfdd858333727b22d30537147595489ae3bea..bc3aea3169afbdffabe67ef7848c5bf721d5bfbb 100644 --- a/common/statefunctional.h +++ b/common/statefunctional.h @@ -79,6 +79,8 @@ public: /* directional1 */ virtual double directional1(const ModelFunction &dm); virtual double directional1(const ModelField &dm); + // Solve the PFS for a direction and compute the variation of cost. + virtual double directional1direct(const ModelField &dm); /* * Second order diff --git a/common/wave/element.cpp b/common/wave/element.cpp index 15a818561b51d37f2f5a62a2709bd5d968a021a1..d074e2c14bcdfedb990376662171b5661c8d9e3b 100644 --- a/common/wave/element.cpp +++ b/common/wave/element.cpp @@ -11,9 +11,9 @@ template<Physic T_Physic> void WaveMultiField<T_Physic>::initializeField(const WaveField<T_Physic>& field) { _field = field; - for (auto it = _dofValues.begin(); it != _dofValues.end(); it++) + for (unsigned i = 0; i < _dofValues.size(); ++i) { - it->resize(_field.numberOfDofs()); + _dofValues[i].resize(_field.numberOfDofs()); } _isInitialized = true; } @@ -52,19 +52,29 @@ template<Physic T_Physic> void WaveAuxilaryField<T_Physic>::assignValues(const std::vector< std::complex<double> > &values) { if(_systemValuesToDofValues.size() == 0) { - _systemValuesToDofValues.reserve(values.size()); + _systemValuesToDofValues.reserve(_wmf->_field.numberOfDofs()); + _unknownIndices.reserve(values.size()); + unsigned counter = 0; for(auto it = _wmf->_field.begin(); it != _wmf->_field.end(); it++) { - if(it->first->type() == gmshfem::dofs::Type::Unknown) - { - _systemValuesToDofValues.push_back(it->first->numDof() - 1); - } + // Save all DOFs, including the fixed ones, but remember to only update the unknown ones + _systemValuesToDofValues.push_back(it->first->numDof() - 1); + if (it->first->type() == gmshfem::dofs::Type::Unknown) { + _unknownIndices.push_back(counter); + } + ++counter; + } } - for(unsigned int i = 0; i < values.size(); ++i) { + + for (unsigned int i : _unknownIndices) + { _wmf->_dofValues[_index][i] = values[_systemValuesToDofValues[i]]; } - if(_index == _wmf->_index){_wmf->_isUpToDate=false;} + if (_index == _wmf->_index) + { + _wmf->_isUpToDate = false; + } } template class WaveMultiField<Physic::acoustic>; diff --git a/common/wave/element.h b/common/wave/element.h index 26731b9191f34058061789c66dc12ea9b13d1862..23b38cec2b805847be35981099dfd1a34621ab10 100644 --- a/common/wave/element.h +++ b/common/wave/element.h @@ -52,6 +52,7 @@ private: WaveMultiField<T_Physic>* _wmf; unsigned int _index; std::vector< unsigned int > _systemValuesToDofValues; + std::vector< unsigned int > _unknownIndices; public: WaveAuxilaryField(std::string name, gmshfem::domain::Domain domain, std::string gmodel, const wave::Discretization<T_Physic>& w_discret): WaveField<T_Physic>(name,domain,gmodel,w_discret), _wmf(nullptr), _index(0), _systemValuesToDofValues() {}; void setField(WaveMultiField<T_Physic>* wmf){_wmf=wmf;_systemValuesToDofValues.clear();}; diff --git a/common/wave/equation/equation.cpp b/common/wave/equation/equation.cpp index 780b1a30b33d0770cfb9530db82d0b1efe3abbed..6f1934a60af0015f35a5d4f0acdacd79e27f5edf 100644 --- a/common/wave/equation/equation.cpp +++ b/common/wave/equation/equation.cpp @@ -40,13 +40,13 @@ EquationInterface<T_Physic>::EquationInterface(const ConfigurationInterface* con { throw Exception("Equation integration degree (boundary) could not be found."); } - double buffer=0.; + int buffer=0; if(!gmshFem.userDefinedParameter(buffer, "equation_boundary")) { msg::warning << "Boundary are not considered in equations (default behaviour)." << msg::endl; } - if(buffer==0.){_boundary=false;} - else{_boundary=true;} + if(buffer==0){_boundary=false; msg::warning << "Boundary are not enabled in equations." << msg::endl;} + else{_boundary=true; msg::warning << "Boundary are enabled in equations." << msg::endl;} }; template<Physic T_Physic> diff --git a/convergence.cpp b/convergence.cpp index 7b08d37a9584797a1a544e49302a7519db15d3d2..7b68f25843dca8f471785aae0493fd3ce1741482 100644 --- a/convergence.cpp +++ b/convergence.cpp @@ -41,7 +41,7 @@ int convergence(const GmshFem& gmshFem) ParametrizationInterface* const parametrization = newParametrization<T_Physic>(gmshFem); - ConfigurationInterface* configuration = newConfiguration(name, parametrization, gmshFem); + auto configuration = newConfiguration(name, parametrization, gmshFem); std::vector<double> frequency(1,0.); if(!gmshFem.userDefinedParameter(frequency[0], "frequency0")) @@ -50,15 +50,15 @@ int convergence(const GmshFem& gmshFem) } std::vector<std::string> filename (1,"noname"); gmshFem.userDefinedParameter(filename[0], "data0"); - const Data<T_Physic> d0(filename,frequency,configuration); + const Data<T_Physic> d0(filename,frequency,configuration.get()); - ObjectiveInterface<T_Physic>* const objective = newObjective<T_Physic>(d0,configuration,gmshFem); + ObjectiveInterface<T_Physic>* const objective = newObjective<T_Physic>(d0,configuration.get(),gmshFem); wave::Discretization<T_Physic> w_discret(gmshFem); - std::vector<EquationInterface<T_Physic>*> pequation(1,new ParametrizedEquation<T_Physic>(parametrization,0,2.*M_PI*frequency[0],configuration,w_discret,gmshFem)); + std::vector<EquationInterface<T_Physic>*> pequation(1,new ParametrizedEquation<T_Physic>(parametrization,0,2.*M_PI*frequency[0],configuration.get(),w_discret,gmshFem)); - StateFunctional<T_Physic>* const statefunctional = new StateFunctional<T_Physic>(configuration,nullptr,frequency,pequation,objective); + StateFunctional<T_Physic>* const statefunctional = new StateFunctional<T_Physic>(configuration.get(),nullptr,frequency,pequation,objective); FunctionalInterface* const functional = statefunctional; double eps0,epsN; @@ -156,7 +156,6 @@ int convergence(const GmshFem& gmshFem) delete statefunctional; delete objective; delete pequation[0]; - delete configuration; delete parametrization; return 0; diff --git a/directional.cpp b/directional.cpp index a8a6cd26bc35605d8e4e9ec8e1273ae48848b3e7..53e3771ec05dcb5f94a13e77fb36a803ff1e94a6 100644 --- a/directional.cpp +++ b/directional.cpp @@ -58,7 +58,7 @@ int directional(const GmshFem& gmshFem) ParametrizationInterface* const parametrization = newParametrization<T_Physic>(gmshFem); - ConfigurationInterface* configuration = newConfiguration(name, parametrization, gmshFem); + auto configuration = newConfiguration(name, parametrization, gmshFem); unsigned int n_freq_tot = 0; if(!gmshFem.userDefinedParameter(n_freq_tot, "n_freq")) @@ -85,7 +85,7 @@ int directional(const GmshFem& gmshFem) msg::warning << "filename #"+suffix+" = "<< filename[f] << msg::endl; } } - const Data<T_Physic> d0(filename,frequency,configuration); + const Data<T_Physic> d0(filename,frequency,configuration.get()); unsigned int n_group = 0; if(!gmshFem.userDefinedParameter(n_group, "n_group")) @@ -139,7 +139,7 @@ int directional(const GmshFem& gmshFem) } const Data<T_Physic> d0g(freq_idx,d0); - ObjectiveInterface<T_Physic>* const objective = newObjective<T_Physic>(d0g,configuration,gmshFem); + auto objective = newObjective<T_Physic>(d0g,configuration.get(),gmshFem); std::vector<EquationInterface<T_Physic>*> pequation(n_freq); std::vector<double> subfrequency(n_freq); @@ -149,10 +149,10 @@ int directional(const GmshFem& gmshFem) subfrequency[f] = frequency[freq_idx[f]]; wave::Discretization<T_Physic> w_discret(gmshFem,suffix_f); - pequation[f] = new ParametrizedEquation<T_Physic>(parametrization,f,2.*M_PI*subfrequency[f],configuration,w_discret,gmshFem,suffix_f); + pequation[f] = new ParametrizedEquation<T_Physic>(parametrization,f,2.*M_PI*subfrequency[f],configuration.get(),w_discret,gmshFem,suffix_f); } - StateFunctional<T_Physic>* const statefunctional = new StateFunctional<T_Physic>(configuration,nullptr,nullptr,subfrequency,pequation,objective); + StateFunctional<T_Physic>* const statefunctional = new StateFunctional<T_Physic>(configuration.get(),nullptr,nullptr,subfrequency,pequation,objective.get()); FunctionalInterface* const functional = statefunctional; double eps; @@ -193,7 +193,7 @@ int directional(const GmshFem& gmshFem) } ScalarPiecewiseFunction< std::complex< double > > spf_dm; - spf_dm.addFunction(Redm+im*Imdm,configuration->model_unknown(Support::BLK) | configuration->model_unknown(Support::BND)); + spf_dm.addFunction(Redm+im*Imdm,configuration.get()->model_unknown(Support::BLK) | configuration->model_unknown(Support::BND)); dm[c] = spf_dm; @@ -344,11 +344,9 @@ int directional(const GmshFem& gmshFem) { delete pequation[f]; } - delete objective; msg::unindent(); } - delete configuration; delete parametrization; return 0; diff --git a/directional_field.cpp b/directional_field.cpp index 20d08f5dc78d2b58a61a000cfe34102550ae5ea4..b52403046f978fa7277e84796ade8947e4c7f622 100644 --- a/directional_field.cpp +++ b/directional_field.cpp @@ -32,7 +32,7 @@ int directional(const GmshFem& gmshFem) ParametrizationInterface* const parametrization = newParametrization<T_Physic>(gmshFem); - ConfigurationInterface* configuration = newConfiguration(name, parametrization, gmshFem); + auto configuration = newConfiguration(name, parametrization, gmshFem); unsigned int n_freq_tot = 0; if(!gmshFem.userDefinedParameter(n_freq_tot, "n_freq")) @@ -59,7 +59,7 @@ int directional(const GmshFem& gmshFem) msg::warning << "filename #"+suffix+" = "<< filename[f] << msg::endl; } } - const Data<T_Physic> d0(filename,frequency,configuration); + const Data<T_Physic> d0(filename,frequency,configuration.get()); unsigned int n_group = 0; if(!gmshFem.userDefinedParameter(n_group, "n_group")) @@ -113,7 +113,7 @@ int directional(const GmshFem& gmshFem) } const Data<T_Physic> d0g(freq_idx,d0); - ObjectiveInterface<T_Physic>* const objective = (d0g.nf()!=0 ? newObjective<T_Physic>(d0g,configuration,gmshFem) : nullptr); + std::unique_ptr<ObjectiveInterface<T_Physic>> objective = (d0g.nf()!=0 ? newObjective<T_Physic>(d0g,configuration.get(),gmshFem) : nullptr); std::vector<EquationInterface<T_Physic>*> pequation(n_freq); std::vector<double> subfrequency(n_freq); @@ -123,16 +123,16 @@ int directional(const GmshFem& gmshFem) subfrequency[f] = frequency[freq_idx[f]]; wave::Discretization<T_Physic> w_discret(gmshFem,suffix_f); - pequation[f] = new ParametrizedEquation<T_Physic>(parametrization,f,2.*M_PI*subfrequency[f],configuration,w_discret,gmshFem,suffix_f); + pequation[f] = new ParametrizedEquation<T_Physic>(parametrization,f,2.*M_PI*subfrequency[f],configuration.get(),w_discret,gmshFem,suffix_f); } model::Discretization m_discret(gmshFem,suffix_g); - ModelFieldSweeperInterface* sweeper_m = newModelFieldSweeper("m",configuration,m_discret,gmshFem); - ModelFieldSweeperInterface* sweeper_dm = newModelFieldSweeper("dm",configuration,m_discret,gmshFem); + ModelFieldSweeperInterface* sweeper_m = newModelFieldSweeper("m",configuration.get(),m_discret,gmshFem); + ModelFieldSweeperInterface* sweeper_dm = newModelFieldSweeper("dm",configuration.get(),m_discret,gmshFem); - RegularizationInterface* const regularization = newRegularization(configuration,(*sweeper_m)(0,0), gmshFem); + RegularizationInterface* const regularization = newRegularization(configuration.get(),(*sweeper_m)(0,0), gmshFem); - StateFunctional<T_Physic>* const statefunctional = new StateFunctional<T_Physic>(configuration,nullptr,regularization,subfrequency,pequation,objective); + StateFunctional<T_Physic>* const statefunctional = new StateFunctional<T_Physic>(configuration.get(),nullptr,regularization,subfrequency,pequation,objective.get()); FunctionalInterface* const functional = statefunctional; @@ -214,12 +214,10 @@ int directional(const GmshFem& gmshFem) { delete pequation[f]; } - delete objective; delete regularization; msg::unindent(); } - delete configuration; delete parametrization; return 0; diff --git a/error.cpp b/error.cpp index c4896285ffbb29f60eebcf8478413957d63c1534..d37cfb736143656580fa2405eb79dabbe43e43de 100644 --- a/error.cpp +++ b/error.cpp @@ -42,7 +42,7 @@ int error(const GmshFem& gmshFem) const ParametrizationInterface* const parametrization = newParametrization<T_Physic>(gmshFem); - ConfigurationInterface* configuration = newConfiguration(name, parametrization, gmshFem); + auto configuration = newConfiguration(name, parametrization, gmshFem); unsigned int write_error_field = 0; gmshFem.userDefinedParameter(write_error_field, "write_error_field"); diff --git a/gradient.cpp b/gradient.cpp index bb6bb2b33dcc895070360d3e4cb0fdbdf4792bc2..b71b1819ed4165b8e1ec57b6a8b4ecb20b91ebb3 100644 --- a/gradient.cpp +++ b/gradient.cpp @@ -45,7 +45,7 @@ int gradient(const GmshFem& gmshFem) const ParametrizationInterface* const parametrization = newParametrization<T_Physic>(gmshFem); - const ConfigurationInterface* const configuration = newConfiguration(name, parametrization, gmshFem); + auto configuration = newConfiguration(name, parametrization, gmshFem); unsigned int n_freq_tot = 0; @@ -73,7 +73,7 @@ int gradient(const GmshFem& gmshFem) msg::warning << "filename #"+suffix+" = "<< filename[f] << msg::endl; } } - const Data<T_Physic> d0(filename,frequency,configuration); + const Data<T_Physic> d0(filename,frequency,configuration.get()); for (unsigned int c = 0; c < parametrization->size(); c++) { @@ -81,7 +81,7 @@ int gradient(const GmshFem& gmshFem) gmshfem::post::save(configuration->m0()[c], configuration->model_unknown(Support::BND), name+"_m_bndc"+std::to_string(c)+"f0", "pos", ""); } model::Discretization m_discret(gmshFem); - sobolev_l2::InnerProduct innerproduct(configuration,m_discret,gmshFem); + sobolev_l2::InnerProduct innerproduct(configuration.get(),m_discret,gmshFem); unsigned int n_group = 0; if(!gmshFem.userDefinedParameter(n_group, "n_group")) @@ -134,7 +134,7 @@ int gradient(const GmshFem& gmshFem) } const Data<T_Physic> d0g(freq_idx,d0); - ObjectiveInterface<T_Physic>* const objective = newObjective<T_Physic>(d0g,configuration,gmshFem); + auto objective = newObjective<T_Physic>(d0g,configuration.get(),gmshFem); std::vector<EquationInterface<T_Physic>*> pequation(n_freq); std::vector<double> subfrequency(n_freq); @@ -144,10 +144,10 @@ int gradient(const GmshFem& gmshFem) subfrequency[f] = frequency[freq_idx[f]]; wave::Discretization<T_Physic> w_discret(gmshFem,suffix_f); - pequation[f] = new ParametrizedEquation<T_Physic>(parametrization,f,2.*M_PI*subfrequency[f],configuration,w_discret,gmshFem,suffix_f); + pequation[f] = new ParametrizedEquation<T_Physic>(parametrization,f,2.*M_PI*subfrequency[f],configuration.get(),w_discret,gmshFem,suffix_f); } - StateFunctional<T_Physic>* const statefunctional = new StateFunctional<T_Physic>(configuration,&innerproduct,nullptr,subfrequency,pequation,objective); + StateFunctional<T_Physic>* const statefunctional = new StateFunctional<T_Physic>(configuration.get(),&innerproduct,nullptr,subfrequency,pequation,objective.get()); FunctionalInterface* const functional = statefunctional; functional->setModel(configuration->m0()); @@ -203,14 +203,12 @@ int gradient(const GmshFem& gmshFem) msg::unindent(); delete statefunctional; - delete objective; for (unsigned int f = 0; f < n_freq; f++) { delete pequation[f]; } msg::unindent(); } - delete configuration; delete parametrization; return 0; diff --git a/inversion.cpp b/inversion.cpp index 761006612c8a4ad56520d6755db82d3b730a09f5..af1cfab517475e16c3a2945bcf918bb1ba5ad8fd 100644 --- a/inversion.cpp +++ b/inversion.cpp @@ -28,7 +28,7 @@ int inversion(const GmshFem& gmshFem) const ParametrizationInterface* const parametrization = newParametrization<T_Physic>(gmshFem); - const ConfigurationInterface* const configuration = newConfiguration(name, parametrization, gmshFem); + auto configuration = newConfiguration(name, parametrization, gmshFem); for (unsigned int c = 0; c < parametrization->size(); c++) { @@ -61,7 +61,7 @@ int inversion(const GmshFem& gmshFem) msg::warning << "filename #"+suffix+" = "<< filename[f] << msg::endl; } } - const Data<T_Physic> d0(filename,frequency,configuration); + const Data<T_Physic> d0(filename,frequency,configuration.get()); unsigned int n_group = 0; if(!gmshFem.userDefinedParameter(n_group, "n_group")) @@ -132,17 +132,17 @@ int inversion(const GmshFem& gmshFem) double m0_scale=0.; if(gmshFem.userDefinedParameter(m0_scale, "m0_scale")) { - m = laplace_filter(configuration->m0(),m0_scale,configuration, m_discret, integrationType); + m = laplace_filter(configuration->m0(),m0_scale,configuration.get(), m_discret, integrationType); } else { - m = rediscretize(configuration->m0(), configuration, m_discret, integrationType); + m = rediscretize(configuration->m0(), configuration.get(), m_discret, integrationType); } m.write(name+"_m_initial", "pos", ""); } else { - m = rediscretize(m,configuration, m_discret, integrationType); + m = rediscretize(m,configuration.get(), m_discret, integrationType); } const Data<T_Physic> d0g(freq_idx,d0); @@ -152,10 +152,10 @@ int inversion(const GmshFem& gmshFem) std::string suffix_f = std::to_string(freq_idx[f]); wave::Discretization<T_Physic> w_discret(gmshFem,suffix_f); - pequation[f] = new ParametrizedEquation<T_Physic>(parametrization,f,2.*M_PI*frequency[freq_idx[f]],configuration,w_discret,gmshFem,suffix_f); + pequation[f] = new ParametrizedEquation<T_Physic>(parametrization,f,2.*M_PI*frequency[freq_idx[f]],configuration.get(),w_discret,gmshFem,suffix_f); } - GlobalMinimumSearchInterface<T_Physic>* const globalminimumsearch = newGlobalMinimumSearch<T_Physic>(name,configuration, gmshFem, suffix_g); + GlobalMinimumSearchInterface<T_Physic>* const globalminimumsearch = newGlobalMinimumSearch<T_Physic>(name,configuration.get(), gmshFem, suffix_g); (*globalminimumsearch)(&m,d0g,pequation); m.write(name+"_mg"+suffix_g, "pos", ""); @@ -170,7 +170,6 @@ int inversion(const GmshFem& gmshFem) msg::unindent(); } - delete configuration; delete parametrization; return 0; } diff --git a/ip_comparison.cpp b/ip_comparison.cpp index 969785a6b7cf649b1ec37b5ace3f3e880d673c24..b717c27b44c9a9cf76356a1b7e03408be2aec981 100644 --- a/ip_comparison.cpp +++ b/ip_comparison.cpp @@ -32,7 +32,7 @@ int ip_comparison(const GmshFem& gmshFem) const ParametrizationInterface* const parametrization = newParametrization<T_Physic>(gmshFem); - const ConfigurationInterface* const configuration = newConfiguration(name, parametrization, gmshFem); + auto configuration = newConfiguration(name, parametrization, gmshFem); std::string integrationType; gmshFem.userDefinedParameter(integrationType, "integration_type"); @@ -67,7 +67,7 @@ int ip_comparison(const GmshFem& gmshFem) msg::warning << "filename #"+suffix+" = "<< filename[f] << msg::endl; } } - const Data<T_Physic> d0(filename,frequency,configuration); + const Data<T_Physic> d0(filename,frequency,configuration.get()); unsigned int n_group = 0; if(!gmshFem.userDefinedParameter(n_group, "n_group")) @@ -123,10 +123,10 @@ int ip_comparison(const GmshFem& gmshFem) msg::print << "Perform comparison" << msg::endl; msg::indent(); - ModelField m = laplace_filter(configuration->m0(),filter_scale,configuration,m_discret,integrationType); + ModelField m = laplace_filter(configuration.get()->m0(),filter_scale,configuration.get(),m_discret,integrationType); m.write(name+"_m_smooth"+suffix_g); - ObjectiveInterface<T_Physic>* const objective = newObjective<T_Physic>(d0g,configuration,gmshFem); + auto objective = newObjective<T_Physic>(d0g,configuration.get(),gmshFem); std::vector<EquationInterface<T_Physic>*> pequation(n_freq); std::vector<double> subfrequency(n_freq); @@ -136,12 +136,12 @@ int ip_comparison(const GmshFem& gmshFem) subfrequency[f] = frequency[freq_idx[f]]; wave::Discretization<T_Physic> w_discret(gmshFem,suffix_f); - pequation[f] = new ParametrizedEquation<T_Physic>(parametrization,f,2.*M_PI*subfrequency[f],configuration,w_discret,gmshFem,suffix_f); + pequation[f] = new ParametrizedEquation<T_Physic>(parametrization,f,2.*M_PI*subfrequency[f],configuration.get(),w_discret,gmshFem,suffix_f); } - InnerProductInterface* const innerproduct = newInnerProduct(configuration,m_discret,gmshFem,suffix_g); - RegularizationInterface* const regularization = newRegularization(configuration,m,gmshFem,suffix_g); - StateFunctional<T_Physic>* const statefunctional = new StateFunctional<T_Physic>(configuration,innerproduct,regularization,subfrequency,pequation,objective); + auto innerproduct = newInnerProduct(configuration.get(),m_discret,gmshFem,suffix_g); + RegularizationInterface* const regularization = newRegularization(configuration.get(),m,gmshFem,suffix_g); + StateFunctional<T_Physic>* const statefunctional = new StateFunctional<T_Physic>(configuration.get(),innerproduct.get(),regularization,subfrequency,pequation,objective.get()); statefunctional->setModel(m); double j = statefunctional->performance(); msg::print << "performance = " << j << msg::endl; @@ -206,17 +206,14 @@ int ip_comparison(const GmshFem& gmshFem) msg::unindent(); delete statefunctional; - delete objective; for (unsigned int f = 0; f < n_freq; f++) { delete pequation[f]; } - delete innerproduct; delete regularization; msg::unindent(); } msg::unindent(); - delete configuration; delete parametrization; return 0; diff --git a/multiscale.cpp b/multiscale.cpp index 8982bac61a5c3acc734c05ca92067514e1d27a37..a8b335e0ff048a94ab1feb5f506bb18ab77f795d 100644 --- a/multiscale.cpp +++ b/multiscale.cpp @@ -33,7 +33,7 @@ int multiscale(const GmshFem& gmshFem) name += suffix; ParametrizationInterface* const parametrization = newParametrization<Physic::acoustic>(gmshFem); - const ConfigurationInterface* const configuration = newConfiguration(name, parametrization, gmshFem); + auto configuration = newConfiguration(name, parametrization, gmshFem); std::string integrationType; gmshFem.userDefinedParameter(integrationType, "model_IntegrationType"); @@ -68,9 +68,9 @@ int multiscale(const GmshFem& gmshFem) msg::warning << "filename #"+suffix+" = "<< filename[f] << msg::endl; } } - const Data<T_Physic> d0(filename,frequency,configuration); + const Data<T_Physic> d0(filename,frequency,configuration.get()); - ObjectiveInterface<T_Physic>* const objective = newObjective<T_Physic>(d0,configuration,gmshFem); + auto objective = newObjective<T_Physic>(d0,configuration.get(),gmshFem); std::vector<EquationInterface<T_Physic>*> pequation(n_freq); for (unsigned int f = 0; f < n_freq; f++) @@ -78,9 +78,9 @@ int multiscale(const GmshFem& gmshFem) std::string suffix_f = std::to_string(f); wave::Discretization<T_Physic> w_discret(gmshFem,suffix_f); - pequation[f] = new ParametrizedEquation<T_Physic>(parametrization,f,2.*M_PI*frequency[f],configuration,w_discret,gmshFem,suffix_f); + pequation[f] = new ParametrizedEquation<T_Physic>(parametrization,f,2.*M_PI*frequency[f],configuration.get(),w_discret,gmshFem,suffix_f); } - StateFunctional<T_Physic>* const statefunctional = new StateFunctional<T_Physic>(configuration,nullptr,nullptr,frequency,pequation,objective); + StateFunctional<T_Physic>* const statefunctional = new StateFunctional<T_Physic>(configuration.get(),nullptr,nullptr,frequency,pequation,objective.get()); FunctionalInterface* const functional = statefunctional; msg::print << "Perform multiscale analysis" << msg::endl; @@ -124,13 +124,11 @@ int multiscale(const GmshFem& gmshFem) delete statefunctional; - delete objective; for (unsigned int f = 0; f < n_freq; f++) { delete pequation[f]; } delete sweeper; - delete configuration; delete parametrization; return 0; diff --git a/ob_comparison.cpp b/ob_comparison.cpp index daa8439cdd60d415702e64eedc0f5e3318feb1a2..841fa2b401716071e179674e1cb9efe676a0de7d 100644 --- a/ob_comparison.cpp +++ b/ob_comparison.cpp @@ -41,7 +41,7 @@ int ob_comparison(const GmshFem& gmshFem) ParametrizationInterface* const parametrization = newParametrization<T_Physic>(gmshFem); - ConfigurationInterface* configuration = newConfiguration(name, parametrization, gmshFem); + auto configuration = newConfiguration(name, parametrization, gmshFem); std::string integrationType; gmshFem.userDefinedParameter(integrationType, "model_IntegrationType"); @@ -51,7 +51,7 @@ int ob_comparison(const GmshFem& gmshFem) double filter_scale = 0.; gmshFem.userDefinedParameter(filter_scale, "filter_scale"); - ModelUpdater mu(configuration,nullptr,nullptr); + ModelUpdater mu(configuration.get(),nullptr,nullptr); unsigned int n_freq = 1; gmshFem.userDefinedParameter(n_freq, "n_freq"); @@ -69,22 +69,22 @@ int ob_comparison(const GmshFem& gmshFem) msg::print << "--- Frequency #"+suffix+" = " << frequency << " --- " << msg::endl; msg::indent(); - ModelField m = laplace_filter(configuration->m0(),filter_scale,configuration,m_discret,integrationType); + ModelField m = laplace_filter(configuration->m0(),filter_scale,configuration.get(),m_discret,integrationType); m.write(name+"_m_smooth"+suffix); wave::Discretization<T_Physic> w_discret(gmshFem,suffix); parametrization->pulsation(2.*M_PI*frequency); - EquationInterface<T_Physic>* const equation = newEquation(2.*M_PI*frequency,configuration,w_discret,gmshFem); - EquationInterface<T_Physic>* const pequation = new ParametrizedEquation<T_Physic>(configuration,equation,parametrization,gmshFem); + EquationInterface<T_Physic>* const equation = newEquation(2.*M_PI*frequency,configuration.get(),w_discret,gmshFem); + EquationInterface<T_Physic>* const pequation = new ParametrizedEquation<T_Physic>(configuration.get(),equation,parametrization,gmshFem); std::string filename = "noname"; gmshFem.userDefinedParameter(filename, "data"+suffix); - Data<T_Physic> d0(filename,configuration); + Data<T_Physic> d0(filename,configuration.get()); - continuousl2distance::Objective<T_Physic>* const objective = new continuousl2distance::Objective<T_Physic>(&d0,configuration,gmshFem,suffix); + continuousl2distance::Objective<T_Physic>* const objective = new continuousl2distance::Objective<T_Physic>(&d0,configuration.get(),gmshFem,suffix); - WaveUpdater<T_Physic> wu(configuration,nullptr,pequation); - DataUpdater<T_Physic> du(configuration,&wu,objective); + WaveUpdater<T_Physic> wu(configuration.get(),nullptr,pequation); + DataUpdater<T_Physic> du(configuration.get(),&wu,objective); std::array<bool,5> dataNeedUpToDate = {true,false,false,false,false}; std::array<bool,4> modelNeedUpToDate = {true,false,false,false}; Data<T_Physic> d = (du.get(dataNeedUpToDate,mu.get(modelNeedUpToDate,&m))).state(Type::FS); @@ -150,7 +150,6 @@ int ob_comparison(const GmshFem& gmshFem) msg::unindent(); } msg::unindent(); - delete configuration; delete parametrization; return 0; diff --git a/preconditioner.cpp b/preconditioner.cpp index 04dd0623cc14ff935d64e921290a6f4c41ff6997..83e88cc0189c7a5e574e15c23f29889cc0ade888 100644 --- a/preconditioner.cpp +++ b/preconditioner.cpp @@ -27,7 +27,7 @@ int preconditioner(const GmshFem& gmshFem) const ParametrizationInterface* const parametrization = newParametrization<T_Physic>(gmshFem); - const ConfigurationInterface* const configuration = newConfiguration(name, parametrization, gmshFem); + auto configuration = newConfiguration(name, parametrization, gmshFem); unsigned int n_freq_tot = 0; if(!gmshFem.userDefinedParameter(n_freq_tot, "n_freq")) @@ -35,7 +35,7 @@ int preconditioner(const GmshFem& gmshFem) throw Exception("Total frequency number could not be found."); } std::vector<double> frequency(n_freq_tot); - const Data<T_Physic>* const d0 = new Data<T_Physic>(configuration); + const Data<T_Physic>* const d0 = new Data<T_Physic>(configuration.get()); for (unsigned int f = 0; f < n_freq_tot; f++) { std::string suffix = std::to_string(f); @@ -83,7 +83,7 @@ int preconditioner(const GmshFem& gmshFem) msg::print << "Compute preconditioner" << msg::endl; - ModelUpdater mu(configuration,nullptr,nullptr); + ModelUpdater mu(configuration.get(),nullptr,nullptr); ModelFunction m0 = configuration->m0(); std::array<bool,4> needUpToDate = {true,false,false,false}; mu.get(needUpToDate,&m0).write(Type::FS,name+"_m"+suffix_g); @@ -100,14 +100,14 @@ int preconditioner(const GmshFem& gmshFem) std::string suffix_f = std::to_string(freq_idx[f]); wave::Discretization<T_Physic> w_discret(gmshFem,suffix_f); - equation[f] = newEquation(2.*M_PI*frequency[freq_idx[f]],configuration,w_discret,gmshFem,suffix_f); - pequation[f] = new ParametrizedEquation<T_Physic>(configuration,equation[f],parametrization,gmshFem,suffix_f); + equation[f] = newEquation(2.*M_PI*frequency[freq_idx[f]],configuration.get(),w_discret,gmshFem,suffix_f); + pequation[f] = new ParametrizedEquation<T_Physic>(configuration.get(),equation[f],parametrization,gmshFem,suffix_f); - objective[f] = newObjective<T_Physic>(d0,configuration,gmshFem,suffix_f); + objective[f] = newObjective<T_Physic>(d0,configuration.get(),gmshFem,suffix_f); objective[f]->link(&mu,&du[f]); - new(&wu[f]) WaveUpdater<T_Physic>(configuration,nullptr,pequation[f]); - new(&du[f]) DataUpdater<T_Physic>(configuration,&wu[f],objective[f]); + new(&wu[f]) WaveUpdater<T_Physic>(configuration.get(),nullptr,pequation[f]); + new(&du[f]) DataUpdater<T_Physic>(configuration.get(),&wu[f],objective[f]); sue[f] = new SensitivityUpdaterFromEquation<T_Physic>(&wu[f],&du[f],pequation[f]); } SensitivityUpdaterFromVector su(n_freq,sue); @@ -130,7 +130,6 @@ int preconditioner(const GmshFem& gmshFem) msg::unindent(); } msg::unindent(); - delete configuration; delete parametrization; return 0; diff --git a/specific/configuration/circular_acquisition.cpp b/specific/configuration/circular_acquisition.cpp index 756729138122bc85c489d051310c7d8bf09ab061..59002d6e213c44bef28166f4a77f4197bf99881b 100644 --- a/specific/configuration/circular_acquisition.cpp +++ b/specific/configuration/circular_acquisition.cpp @@ -267,26 +267,7 @@ namespace circular_acquisition } } - void Configuration::mesh() const - { - msg::print << "Generate meshes" << msg::endl; - gmsh::option::setNumber("General.Terminal", 1); - - gmodel::add(_name); - 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 p0 = factory::addPoint(0., 0., 0., _h); diff --git a/specific/configuration/circular_acquisition.h b/specific/configuration/circular_acquisition.h index 40842cf1cd5da07e07c49c5feffc0f914b74bbfb..75e4f3de4eead27fbaa761a62a12fa4c5616c495 100644 --- a/specific/configuration/circular_acquisition.h +++ b/specific/configuration/circular_acquisition.h @@ -70,7 +70,6 @@ namespace circular_acquisition 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; diff --git a/specific/configuration/flexible_acquisition.cpp b/specific/configuration/flexible_acquisition.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3850bb1d1eb83971fbfcc1febee4c7c5faeb2722 --- /dev/null +++ b/specific/configuration/flexible_acquisition.cpp @@ -0,0 +1,457 @@ +//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" +#include "yaml_interface.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 FROM YAML + std::string shotsPath; + if (!gmshFem.userDefinedParameter(shotsPath, "shots_config")) + { + throw common::Exception("Path to a shots_config is needed in flexible_acquisition."); + } + ShotsConfigurationYAML shotsConfig(shotsPath); + _ns = shotsConfig.numShots(); + + // Configure points + for (const auto &coords : shotsConfig.points()) + { + _er_positions.push_back(coords); + } + + _np = _er_positions.size(); + + + mesh(); + + + // Configure shots + for (unsigned s = 0; s < shotsConfig.numShots(); ++s) + { + _emitter.push_back(shotsConfig.emitters(s)); + _receiver.push_back(shotsConfig.receivers(s)); + } + + for (unsigned p = 0; p < _er_positions.size(); ++p) { + _point.push_back("emitter_receiver_"+std::to_string(p)); + _points |= _point[p]; + } + + + + /* + * DOMAIN + */ + // TODO: actual data mesh! + _data_omega = Domain("supersurface") | Domain("subsurface"); + + _subsurface[Support::BLK] = Domain("subsurface"); + _subsurface[Support::BND] = Domain("subsurface_bnd"); + _supersurface[Support::BLK] = Domain("supersurface"); + _supersurface[Support::BND] = Domain("supersurface_bnd"); + + std::string unknownRegion = "subsurface"; + gmshFem.userDefinedParameter(unknownRegion, "unknown"); + if (unknownRegion == "subsurface") + { + _model_known[Support::BLK] = _supersurface[Support::BLK]; + _model_known[Support::BND] = _supersurface[Support::BND]; + + _model_unknown[Support::BLK] = _subsurface[Support::BLK]; + _model_unknown[Support::BND] = _subsurface[Support::BND]; + } + else if (unknownRegion == "none") + { + _model_known[Support::BLK] = _supersurface[Support::BLK] | _subsurface[Support::BLK]; + _model_known[Support::BND] = _supersurface[Support::BND] | _subsurface[Support::BND]; + } + else if (unknownRegion == "all") + { + _model_unknown[Support::BLK] = _supersurface[Support::BLK] | _subsurface[Support::BLK]; + _model_unknown[Support::BND] = _supersurface[Support::BND] | _subsurface[Support::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() ... + _named_domains["top_bnd"] = Domain("top_bnd"); + + /* + * Reference model function + */ + // TODO: remove debugging stuff + setupInitialModel(parametrization, gmshFem); + gmshfem::post::save(_m0[0], _model_known[Support::BLK], "model_known"); + gmshfem::post::save(_m0[0], _model_unknown[Support::BLK], "model_unknown"); + + + } + + + 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, {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"); + + gmodel::addPhysicalGroup(1, {lineTop}, 13); + gmodel::setPhysicalName(1, 13, "top_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)); + } + + } + 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"); + + */ + } + + void Configuration::setupInitialModel(const ParametrizationInterface* const parametrization, const GmshFem& gmshFem) { + /* + * 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"); + // Fix for weird tags when loading .pos files. + std::vector<int> tags; + gmsh::view::getTags(tags); + auto view = tags.back(); + ScalarFunction<std::complex<double>> mpos = probeScalarView<std::complex<double>>(view); + + 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); + } + } + + 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..608b9e903ccfcd602714a9e29a12b0e78e874de7 --- /dev/null +++ b/specific/configuration/flexible_acquisition.h @@ -0,0 +1,121 @@ +#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; +*/ + + std::array<gmshfem::domain::Domain, 2> _subsurface; + std::array<gmshfem::domain::Domain, 2> _supersurface; + + std::vector<std::complex<double>> _m_super; + std::vector<std::complex<double>> _m_sub; + + virtual void wave_mesh() const; + virtual void data_mesh() const; + + + void setupInitialModel(const ParametrizationInterface* const parametrization, const gmshfem::common::GmshFem& gmshFem); + 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/layeredvolume_acquisition.cpp b/specific/configuration/layeredvolume_acquisition.cpp index a12e5a2541ac8e926c14ea25a28519d528944c29..a8399ea86b1e6050e08ee1623f49ee56fa64979d 100644 --- a/specific/configuration/layeredvolume_acquisition.cpp +++ b/specific/configuration/layeredvolume_acquisition.cpp @@ -480,26 +480,6 @@ namespace layeredvolume_acquisition } } - void Configuration::mesh() const - { - msg::print << "Generate meshes" << msg::endl; - gmsh::option::setNumber("General.Terminal", 1); - - gmodel::add(_name); - 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 { std::vector<int> pl1(_layercoord1.size()); diff --git a/specific/configuration/layeredvolume_acquisition.h b/specific/configuration/layeredvolume_acquisition.h index bb83d5d84cd3d6e585137eebe82b11686d24a47e..6618487b3f0b985f4c3579d8c9fe568e2c4b10d1 100644 --- a/specific/configuration/layeredvolume_acquisition.h +++ b/specific/configuration/layeredvolume_acquisition.h @@ -107,7 +107,6 @@ namespace layeredvolume_acquisition unsigned int nye() const {return _nye;}; unsigned int nyr() const {return _nyr;}; - 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; diff --git a/specific/configuration/newConfiguration.h b/specific/configuration/newConfiguration.h index 868b390d861218f40258c2360f816eb4fba6f420..9dd88c8292488df869a7405a5d8e987db91b1627 100644 --- a/specific/configuration/newConfiguration.h +++ b/specific/configuration/newConfiguration.h @@ -6,6 +6,7 @@ //Standard Library #include <string> +#include <memory> //GmshFem Library #include "GmshFem.h" @@ -18,20 +19,22 @@ #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) +std::unique_ptr<ConfigurationInterface> newConfiguration(std::string name, const ParametrizationInterface* const parametrization, 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=="surface_acquisition"){return new surface_acquisition::Configuration(name, parametrization, gmshFem);} - else if(configuration=="volume_acquisition"){return new volume_acquisition::Configuration(name, parametrization, gmshFem);} - else if(configuration=="layeredvolume_acquisition"){return new layeredvolume_acquisition::Configuration(name, parametrization, gmshFem);} - 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);} + if(configuration=="surface_acquisition"){return std::make_unique< surface_acquisition::Configuration>(name, parametrization, gmshFem);} + else if(configuration=="volume_acquisition"){return std::make_unique< volume_acquisition::Configuration>(name, parametrization, gmshFem);} + else if(configuration=="layeredvolume_acquisition"){return std::make_unique< layeredvolume_acquisition::Configuration>(name, parametrization, gmshFem);} + else if(configuration=="circular_acquisition"){return std::make_unique< circular_acquisition::Configuration>(name, parametrization, gmshFem);} + else if(configuration=="line_acquisition"){return std::make_unique< line_acquisition::Configuration>(name, parametrization, gmshFem);} + else if(configuration=="rectangular_acquisition"){return std::make_unique< rectangular_acquisition::Configuration>(name, parametrization, gmshFem);} + else if(configuration=="flexible_acquisition"){return std::make_unique< flexible_acquisition::Configuration>(name, parametrization, gmshFem);} else { throw gmshfem::common::Exception("Configuration" + configuration + " is not valid."); diff --git a/specific/configuration/surface_acquisition.cpp b/specific/configuration/surface_acquisition.cpp index 5f2a488ec3bb88a5fffd453fd370b8ba5e501f73..dac31c5fab66bf6f5e375d55a1d76ce5b8ea97d7 100644 --- a/specific/configuration/surface_acquisition.cpp +++ b/specific/configuration/surface_acquisition.cpp @@ -116,6 +116,8 @@ namespace surface_acquisition _supersurface[Support::BLK] = Domain(2, 22); _supersurface[Support::BND] = Domain(1, 12); + _named_domains["top_bnd"] = Domain("top_bnd"); + _wave_omega[Support::BLK] = _subsurface[Support::BLK] | _supersurface[Support::BLK]; _wave_omega[Support::BND] = _subsurface[Support::BND] | _supersurface[Support::BND]; @@ -268,24 +270,7 @@ namespace surface_acquisition } } - void Configuration::mesh() const - { - msg::print << "Generate meshes" << msg::endl; - gmsh::option::setNumber("General.Terminal", 1); - gmodel::add(_name); - 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.; @@ -361,6 +346,7 @@ namespace surface_acquisition lymin_reverse[n] = -lymin[n]; } + // Nomenclature: line from one y to another, left or right. All lines go up int lHyminl = factory::addLine(pHl,pyminl); int lymin0l = factory::addLine(pyminl,p0l); int l0ymaxl = factory::addLine(p0l,pymaxl); @@ -450,6 +436,10 @@ namespace surface_acquisition gmodel::addPhysicalGroup(1, lsuper, 12); gmodel::setPhysicalName(1, 12, "supersurface_bnd"); + // Add another physical groupe for the top boundary, to represent e.g. reflection at the air-water interface + gmodel::addPhysicalGroup(1, lymax, 13); + gmodel::setPhysicalName(1, 13, "top_bnd"); + gmodel::addPhysicalGroup(2, {s_sub}, 21); gmodel::setPhysicalName(2, 21, "subsurface_vol"); gmodel::addPhysicalGroup(2, {s_supermin,s_supermax}, 22); @@ -527,6 +517,10 @@ namespace surface_acquisition gmodel::addPhysicalGroup(1, lsuper, 12); gmodel::setPhysicalName(1, 12, "supersurface_bnd"); + // Add another physical groupe for the top boundary, to represent e.g. reflection at the air-water interface + gmodel::addPhysicalGroup(1, lymax, 13); + gmodel::setPhysicalName(1, 13, "top_bnd"); + gmodel::addPhysicalGroup(2, {s_sub}, 21); gmodel::setPhysicalName(2, 21, "subsurface_vol"); gmodel::addPhysicalGroup(2, {s_supermax}, 22); diff --git a/specific/configuration/surface_acquisition.h b/specific/configuration/surface_acquisition.h index b4402359ac9663fd388b20b34a54a1db3a957062..00ad7d52aeee7904f124dfedcbaafd95c5fd50d1 100644 --- a/specific/configuration/surface_acquisition.h +++ b/specific/configuration/surface_acquisition.h @@ -59,7 +59,6 @@ namespace surface_acquisition virtual void data_mesh() const; public: Configuration(std::string name, const ParametrizationInterface* const parametrization, const gmshfem::common::GmshFem& gmshFem); - virtual void mesh() const; unsigned int ne() const {return _ne;}; unsigned int nr() const {return _nr;}; diff --git a/specific/configuration/volume_acquisition.cpp b/specific/configuration/volume_acquisition.cpp index a8fe8673ab9d844c87346d7f613fc6c041b9987e..082a57ef1910b98c32c1797e79461ec8d5dbb5f3 100644 --- a/specific/configuration/volume_acquisition.cpp +++ b/specific/configuration/volume_acquisition.cpp @@ -344,26 +344,6 @@ namespace volume_acquisition } } - void Configuration::mesh() const - { - msg::print << "Generate meshes" << msg::endl; - gmsh::option::setNumber("General.Terminal", 1); - - gmodel::add(_name); - 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); diff --git a/specific/configuration/volume_acquisition.h b/specific/configuration/volume_acquisition.h index faf51aa50f6c81a2b8421e546d1827ee9a26640d..302cc85e7e33d30a53a3334e673b42726cfbb2ee 100644 --- a/specific/configuration/volume_acquisition.h +++ b/specific/configuration/volume_acquisition.h @@ -92,7 +92,6 @@ namespace volume_acquisition unsigned int nye() const {return _nye;}; unsigned int nyr() const {return _nyr;}; - 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; diff --git a/specific/configuration/yaml_interface.cpp b/specific/configuration/yaml_interface.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a7baa4dea954bb6cd5a1444367303c06cae51766 --- /dev/null +++ b/specific/configuration/yaml_interface.cpp @@ -0,0 +1,34 @@ +#include "GmshFem.h" +#include "yaml_interface.h" + +ShotsConfigurationYAML::ShotsConfigurationYAML(const std::string &path) +{ +#ifndef ENABLE_YAML_CPP + throw gmshfem::common::Exception("Cannot use Flexible Acquisition without YAML-CPP."); +#else + YAML::Node config = YAML::LoadFile(path); + + for (const auto &coord : config["coordinates"]) + { + double x = coord[0].as<double>(); + double y = coord[1].as<double>(); + _points.emplace_back(x, y); + } + + for (const auto &shot : config["shots"]) + { + std::vector<unsigned> emitters, receivers; + for (const auto &emitter : shot["emitters"]) + { + emitters.push_back(emitter.as<int>()); + } + for (const auto &receiver : shot["receivers"]) + { + receivers.push_back(receiver.as<int>()); + } + + _emitters.push_back(std::move(emitters)); + _receivers.push_back(std::move(receivers)); + } +#endif +} \ No newline at end of file diff --git a/specific/configuration/yaml_interface.h b/specific/configuration/yaml_interface.h new file mode 100644 index 0000000000000000000000000000000000000000..23afb3fcdbde94a5e01e4d678bbba79a1e72f0d8 --- /dev/null +++ b/specific/configuration/yaml_interface.h @@ -0,0 +1,77 @@ +#ifndef H_YAML_INTERFACE_SHOTS +#define H_YAML_INTERFACE_SHOTS + +#include <vector> +#include <string> +#include <utility> +#include "yaml-cpp/yaml.h" +// TODO: refactor (abstract + impl) + +class ShotsConfigurationInterface //(abstract) +{ + public: + using Coordinates = std::pair<double, double>; + + /** + * Describe the number of shots + */ + virtual unsigned numShots() const = 0; + + /** + * Describe the number of points + */ + virtual unsigned numPoints() const = 0; + + /** + * emitters(s) is the list of enabled emitters in shot "s". + * Array must be of size numShots() + */ + virtual const std::vector<unsigned> &emitters(unsigned shot) const = 0; + + /** + * receivers(s) is the list of enabled receivers in shot "s". + * Array must be of size numShots() + */ + virtual const std::vector<unsigned> &receivers(unsigned shot) const = 0; + + /** + * List of all points + * Array must be of size numPoints() + */ + virtual const std::vector<Coordinates> &points() const = 0; +}; + +class ShotsConfigurationYAML : public ShotsConfigurationInterface { + private: + std::vector<std::vector<unsigned>> _emitters, _receivers; + std::vector<ShotsConfigurationInterface::Coordinates> _points; + + public: + + ShotsConfigurationYAML(const std::string& path); + + virtual unsigned numShots() const override { + return _emitters.size(); + } + + virtual unsigned numPoints() const override { + return _points.size(); + } + + virtual const std::vector<unsigned> &emitters(unsigned shot) const override { + return _emitters.at(shot); + } + + virtual const std::vector<unsigned> &receivers(unsigned shot) const override { + return _receivers.at(shot); + } + + virtual const std::vector<Coordinates> &points() const override { + return _points; + } + + + +}; + +#endif \ No newline at end of file diff --git a/specific/data/element.cpp b/specific/data/element.cpp index 26a948ad32be0484bae5680035e66487a479bda4..6bef6003784383cd330db1fec1bd21b59c0fbedf 100644 --- a/specific/data/element.cpp +++ b/specific/data/element.cpp @@ -12,6 +12,13 @@ using namespace gmshfem; using namespace gmshfem::common; +template<> +typename gmshfem::MathObject< std::complex< double >, propertiesOf<Physic::acoustic>::degree >::Object s_ones<Physic::acoustic>(){return 1.;} +template<> +typename gmshfem::MathObject< std::complex< double >, propertiesOf<Physic::electromagnetic>::degree >::Object s_ones<Physic::electromagnetic>(){return PointData<Physic::electromagnetic>::Object(1.,1.,1.);} +template<> +typename gmshfem::MathObject< std::complex< double >, propertiesOf<Physic::elastodynamic>::degree >::Object s_ones<Physic::elastodynamic>(){return PointData<Physic::elastodynamic>::Object(1.,1.,1.);} + /* acoustic */ template<> double norm2<Physic::acoustic>(const typename PointData<Physic::acoustic>::Object& d){return std::norm(d);} @@ -27,8 +34,6 @@ template<> typename PointData<Physic::acoustic>::Object wise_divide<Physic::acoustic>(const typename PointData<Physic::acoustic>::Object& d1,const typename PointData<Physic::acoustic>::Object& d2){return d1/d2;} template<> typename PointData<Physic::acoustic>::Object wise_multiply<Physic::acoustic>(const typename PointData<Physic::acoustic>::Object& d1,const typename PointData<Physic::acoustic>::Object& d2){return d1*d2;} -template<> -typename gmshfem::MathObject< std::complex< double >, propertiesOf<Physic::acoustic>::degree >::Object s_ones<Physic::acoustic>(){return 1.;} /* electromagnetic */ template<> @@ -48,8 +53,6 @@ template<> typename PointData<Physic::electromagnetic>::Object wise_divide<Physic::electromagnetic>(const typename PointData<Physic::electromagnetic>::Object& d1,const typename PointData<Physic::electromagnetic>::Object& d2){return d1.array() / d2.array() ;} template<> typename PointData<Physic::electromagnetic>::Object wise_multiply<Physic::electromagnetic>(const typename PointData<Physic::electromagnetic>::Object& d1,const typename PointData<Physic::electromagnetic>::Object& d2){return d1.array() * d2.array() ;} -template<> -typename gmshfem::MathObject< std::complex< double >, propertiesOf<Physic::electromagnetic>::degree >::Object s_ones<Physic::electromagnetic>(){return PointData<Physic::electromagnetic>::Object(1.,1.,1.);} /* elastodynamic */ template<> @@ -69,5 +72,3 @@ template<> typename PointData<Physic::elastodynamic>::Object wise_divide<Physic::elastodynamic>(const typename PointData<Physic::elastodynamic>::Object& d1,const typename PointData<Physic::elastodynamic>::Object& d2){return d1.array() / d2.array() ;} template<> typename PointData<Physic::elastodynamic>::Object wise_multiply<Physic::elastodynamic>(const typename PointData<Physic::elastodynamic>::Object& d1,const typename PointData<Physic::elastodynamic>::Object& d2){return d1.array() * d2.array() ;} -template<> -typename gmshfem::MathObject< std::complex< double >, propertiesOf<Physic::elastodynamic>::degree >::Object s_ones<Physic::elastodynamic>(){return PointData<Physic::elastodynamic>::Object(1.,1.,1.);} diff --git a/specific/data/objective/newObjective.h b/specific/data/objective/newObjective.h index 67c43e8574ef39c53f2c51de9b7987b82c8639e9..193f9966588f32ffc454340dfcb281d9cd61d94e 100644 --- a/specific/data/objective/newObjective.h +++ b/specific/data/objective/newObjective.h @@ -6,6 +6,7 @@ //Standard Library #include <string> +#include <memory> //GmshFEM Library #include "Exception.h" @@ -15,16 +16,16 @@ #include "phase.h" template<Physic T_Physic> -ObjectiveInterface<T_Physic>* newObjective(const Data<T_Physic>& d0, const ConfigurationInterface* const config, const gmshfem::common::GmshFem& gmshFem,std::string suffix = "") +std::unique_ptr<ObjectiveInterface<T_Physic>> newObjective(const Data<T_Physic>& d0, const ConfigurationInterface* const config, const gmshfem::common::GmshFem& gmshFem,std::string suffix = "") { std::string objective; if(!gmshFem.userDefinedParameter(objective, "objective")) { throw gmshfem::common::Exception("Objective type could not be found."); } - if(objective=="l2distance"){return new l2distance::Objective<T_Physic>(d0,gmshFem);} - else if(objective=="conventional_phase"){return new conventional_phase::Objective<T_Physic>(d0,gmshFem);} - else if(objective=="logarithmic_phase"){return new logarithmic_phase::Objective<T_Physic>(d0,gmshFem);} + if(objective=="l2distance"){return std::make_unique< l2distance::Objective<T_Physic> >(d0,gmshFem);} + else if(objective=="conventional_phase"){return std::make_unique< conventional_phase::Objective<T_Physic> >(d0,gmshFem);} + else if(objective=="logarithmic_phase"){return std::make_unique< logarithmic_phase::Objective<T_Physic> >(d0,gmshFem);} else { throw gmshfem::common::Exception("Objective " + objective + " is not valid."); diff --git a/specific/model/innerproduct/newInnerProduct.cpp b/specific/model/innerproduct/newInnerProduct.cpp index b7b8f38d47039af1bf65f54d69dc99d9f1a63d7d..651af62ad665b8cadea536c17d212599507cb4ed 100644 --- a/specific/model/innerproduct/newInnerProduct.cpp +++ b/specific/model/innerproduct/newInnerProduct.cpp @@ -11,15 +11,15 @@ #include "sobolev.h" template<class M> -InnerProductInterface* newInnerProduct(const ConfigurationInterface* const config, const M& m_discret, const gmshfem::common::GmshFem& gmshFem, std::string suffix) +std::unique_ptr<InnerProductInterface> newInnerProduct(const ConfigurationInterface* const config, const M& m_discret, const gmshfem::common::GmshFem& gmshFem, std::string suffix) { std::string innerproduct; if(!gmshFem.userDefinedParameter(innerproduct, "innerproduct")) { throw gmshfem::common::Exception("Inner product type could not be found."); } - if(innerproduct=="sobolev_l2"){return new sobolev_l2::InnerProduct(config,m_discret,gmshFem, suffix);} - else if(innerproduct=="sobolev_df"){return new sobolev_df::InnerProduct(config,m_discret,gmshFem, suffix);} + if(innerproduct=="sobolev_l2"){return std::make_unique< sobolev_l2::InnerProduct>(config,m_discret,gmshFem, suffix);} + else if(innerproduct=="sobolev_df"){return std::make_unique< sobolev_df::InnerProduct>(config,m_discret,gmshFem, suffix);} else { throw gmshfem::common::Exception("Inner product " + innerproduct + " is not valid."); @@ -27,5 +27,5 @@ InnerProductInterface* newInnerProduct(const ConfigurationInterface* const confi } } -template InnerProductInterface* newInnerProduct<model::Discretization>(const ConfigurationInterface* const, const model::Discretization&, const gmshfem::common::GmshFem&, std::string); -template InnerProductInterface* newInnerProduct<ModelField>(const ConfigurationInterface* const, const ModelField&, const gmshfem::common::GmshFem&, std::string); +template std::unique_ptr<InnerProductInterface> newInnerProduct<model::Discretization>(const ConfigurationInterface* const, const model::Discretization&, const gmshfem::common::GmshFem&, std::string); +template std::unique_ptr<InnerProductInterface> newInnerProduct<ModelField>(const ConfigurationInterface* const, const ModelField&, const gmshfem::common::GmshFem&, std::string); diff --git a/specific/model/innerproduct/newInnerProduct.h b/specific/model/innerproduct/newInnerProduct.h index c968ffac047540e6b04db4d4d3f879362d43c530..dc77005f3af143108dccfa86a77cdb6523e7f066 100644 --- a/specific/model/innerproduct/newInnerProduct.h +++ b/specific/model/innerproduct/newInnerProduct.h @@ -5,12 +5,13 @@ #define H_SPECIFIC_MODEL_NEWINNERPRODUCT //Standard Library +#include <memory> //GmshFEM Library #include "GmshFem.h" //GmshFWI Library #include "../../../common/model/innerproduct/innerproduct.h" template<class M> -InnerProductInterface* newInnerProduct(const ConfigurationInterface* const config, const M& m_discret, const gmshfem::common::GmshFem& gmshFem, std::string suffix); +std::unique_ptr<InnerProductInterface> newInnerProduct(const ConfigurationInterface* const config, const M& m_discret, const gmshfem::common::GmshFem& gmshFem, std::string suffix); #endif //H_SPECIFIC_MODEL_NEWINNERPRODUCT diff --git a/specific/optimization/globalminimumsearch/sequential.cpp b/specific/optimization/globalminimumsearch/sequential.cpp index 500aa5fd5d05e878ad8847ffd408302f27c404f9..1aa559a93f94b712b680c2664fca96b6eb028cea 100644 --- a/specific/optimization/globalminimumsearch/sequential.cpp +++ b/specific/optimization/globalminimumsearch/sequential.cpp @@ -15,8 +15,13 @@ #include "../../optimization/linesearch/newLineSearch.h" #include "../../optimization/localminimumsearch/newLocalMinimumSearch.h" +// STL +#include <memory> + using namespace gmshfem; using namespace gmshfem::common; +using std::unique_ptr; +using std::make_unique; namespace sequential { @@ -143,12 +148,11 @@ namespace sequential throw Exception("Data and equations do not have the same size."); } - ObjectiveInterface<T_Physic>* const objective = newObjective<T_Physic>(d0,_config,_gmshFem,_suffix); - InnerProductInterface* const innerproduct = newInnerProduct(_config,*m,_gmshFem,_suffix); + auto objective = newObjective<T_Physic>(d0,_config,_gmshFem,_suffix); + auto const innerproduct = newInnerProduct(_config,*m,_gmshFem,_suffix); RegularizationInterface* const regularization = newRegularization(_config,*m,_gmshFem,_suffix); - StateFunctional<T_Physic>* const statefunctional = new StateFunctional<T_Physic>(_config,innerproduct,regularization,d0.frequency(),equation,objective); - FunctionalInterface* const functional = statefunctional; - functional->setModel(*m); + auto statefunctional = make_unique<StateFunctional<T_Physic>>(_config,innerproduct.get(),regularization,d0.frequency(),equation,objective.get()); + statefunctional->setModel(*m); LocalMinimumSearchInterface* const minimumsearch = newLocalMinimumSearch(_gmshFem); DescentSearchInterface* const descentsearch = newDescentSearch(_gmshFem); @@ -157,7 +161,7 @@ namespace sequential std::vector<GlobalMinimumSearchHistoryLine2> historyline; double js_1 =0.; - double js = functional->performance(); + double js = statefunctional->performance(); historyline.emplace_back(js,0.,0.,statefunctional->performance_objective(),statefunctional->performance_regularization()); double rel_djs = 0.; bool success = false; @@ -184,8 +188,8 @@ namespace sequential } minimumsearch->name(_name+"g"+_suffix+"s"+suffix1); js_1=js; - (*minimumsearch)(m, functional, descentsearch, linesearch); - js = functional->performance(); + (*minimumsearch)(m, statefunctional.get(), descentsearch, linesearch); + js = statefunctional->performance(); m->write(_name+"_mg"+_suffix+"s"+suffix1); //statefunctional->write_data(Type::FS,_name+"_dg"+_suffix+"s"+suffix1,"pos"); rel_djs = 2. * (js_1-js) / (js_1+js); @@ -207,10 +211,7 @@ namespace sequential delete descentsearch; delete linesearch; - delete functional; - delete innerproduct; delete regularization; - delete objective; msg::unindent(); } diff --git a/specific/optimization/localminimumsearch/classic.cpp b/specific/optimization/localminimumsearch/classic.cpp index b0498aa39cffde89afbb47458457a1cf4ad8ab06..47f6e4a7838d001c181cd95ca629a22c4771dff2 100644 --- a/specific/optimization/localminimumsearch/classic.cpp +++ b/specific/optimization/localminimumsearch/classic.cpp @@ -82,6 +82,13 @@ namespace classic msg::print << "Search minimum (classic)" << msg::endl; msg::indent(); + if (!linesearch) { + throw Exception("No linesearch provided."); + } + if (!descentsearch) { + throw Exception("No descentsearch provided."); + } + descentsearch->initialize(functional); std::vector<LocalMinimumSearchHistoryLine2> historyline; diff --git a/specific/wave/discretization.cpp b/specific/wave/discretization.cpp index 3282e8ce822dec5e0c5d6b446aad9641fbbdc329..f27798f786830f5e824989aecc0c9a6b25755810 100644 --- a/specific/wave/discretization.cpp +++ b/specific/wave/discretization.cpp @@ -15,37 +15,6 @@ using namespace gmshfem::field; namespace wave { - /* - * class Discretization - */ - template<Physic T_physic> - Discretization<T_physic>::Discretization(const GmshFem& gmshFem, std::string suffix) - { - msg::print << "Read wave discretization parameters" << msg::endl; - std::string str_buffer; - if(!( - ( - gmshFem.userDefinedParameter(_functionSpaceDegree, "wave_FunctionSpaceDegree") - || - gmshFem.userDefinedParameter(_functionSpaceDegree, "wave_FunctionSpaceDegree"+suffix) - ) - && - ( - gmshFem.userDefinedParameter(str_buffer, "wave_FunctionSpaceType") - || - gmshFem.userDefinedParameter(str_buffer, "wave_FunctionSpaceType"+suffix) - ) - )) - { - throw common::Exception("A discretization parameter could not be found."); - } - _functionSpaceType = to_functionSpaceType<T_physic>(str_buffer); - } - - template class Discretization<Physic::acoustic>; - template class Discretization<Physic::electromagnetic>; - template class Discretization<Physic::elastodynamic>; - /* * to_functionSpaceType */ @@ -81,4 +50,36 @@ namespace wave else { throw common::Exception("Invalid function space type for elastodynamics."); } return out; }; + + /* + * class Discretization + */ + template<Physic T_physic> + Discretization<T_physic>::Discretization(const GmshFem& gmshFem, std::string suffix) + { + msg::print << "Read wave discretization parameters" << msg::endl; + std::string str_buffer; + if(!( + ( + gmshFem.userDefinedParameter(_functionSpaceDegree, "wave_FunctionSpaceDegree") + || + gmshFem.userDefinedParameter(_functionSpaceDegree, "wave_FunctionSpaceDegree"+suffix) + ) + && + ( + gmshFem.userDefinedParameter(str_buffer, "wave_FunctionSpaceType") + || + gmshFem.userDefinedParameter(str_buffer, "wave_FunctionSpaceType"+suffix) + ) + )) + { + throw common::Exception("A discretization parameter could not be found."); + } + _functionSpaceType = to_functionSpaceType<T_physic>(str_buffer); + } + + template class Discretization<Physic::acoustic>; + template class Discretization<Physic::electromagnetic>; + template class Discretization<Physic::elastodynamic>; + } // namespace wave diff --git a/specific/wave/equation/simplewave.cpp b/specific/wave/equation/simplewave.cpp index 56eba61d476dcbbc34c41ac14c936137e2e51900..a4ad2680d22cdf3e3e2b525030bedc7aa2ae1ea2 100644 --- a/specific/wave/equation/simplewave.cpp +++ b/specific/wave/equation/simplewave.cpp @@ -75,6 +75,21 @@ namespace simplewave { 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; + } + + _useSecondOrderABC = false; + int intArg; + gmshFem.userDefinedParameter(intArg, "useSecondOrderABC"); + _useSecondOrderABC = intArg != 0; + msg::warning << "Using Second Order ABC : " << _useSecondOrderABC << msg::endl; } bool Equation::modelIsObsolete() @@ -107,16 +122,40 @@ namespace simplewave } 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), _config->model_known(Support::BND), integrationType(_integrationDegreeBnd)); //-1 from sign conventions + _formulation.integral(-1. * im * _pulsation * sqrt(real(m0)) * dof(_v), tf(_v), absorbingPartKnown, integrationType(_integrationDegreeBnd)); //-1 from sign conventions + if (_useSecondOrderABC) _formulation.integral(1. * im / (2.0 * _pulsation * sqrt(real(m0))) * grad(dof(_v)), grad(tf(_v)), absorbingPartKnown, integrationType(_integrationDegreeBnd)); //-1 from sign conventions + } else { - _formulation.integral(-1. * im * _pulsation * sqrt(m0) * dof(_v), tf(_v), _config->model_known(Support::BND), integrationType(_integrationDegreeBnd)); //-1 from sign conventions + _formulation.integral(-1. * im * _pulsation * sqrt(m0) * dof(_v), tf(_v), absorbingPartKnown, integrationType(_integrationDegreeBnd)); //-1 from sign conventions + if (_useSecondOrderABC) _formulation.integral(1. * im / (2.0 * _pulsation * sqrt(m0)) * grad(dof(_v)), grad(tf(_v)), absorbingPartKnown, integrationType(_integrationDegreeBnd)); //-1 from sign conventions } if(!_config->model_unknown(Support::BLK).isEmpty()) { @@ -126,11 +165,13 @@ namespace simplewave { if(_realImpedance) { - _formulation.integral(-1. * im * _pulsation * sqrt(real(m)) * dof(_v), tf(_v), _config->model_unknown(Support::BND), integrationType(_integrationDegreeBnd)); //-1 from sign conventions + _formulation.integral(-1. * im * _pulsation * sqrt(real(m)) * dof(_v), tf(_v), absorbingPartUnknown, integrationType(_integrationDegreeBnd)); //-1 from sign conventions + if (_useSecondOrderABC) _formulation.integral(1. * im / (2. * _pulsation * sqrt(real(m))) * grad(dof(_v)), grad(tf(_v)), absorbingPartUnknown, integrationType(_integrationDegreeBnd)); //-1 from sign conventions } else { - _formulation.integral(-1. * im * _pulsation * sqrt(m) * dof(_v), tf(_v), _config->model_unknown(Support::BND), integrationType(_integrationDegreeBnd)); //-1 from sign conventions + _formulation.integral(-1. * im * _pulsation * sqrt(m) * dof(_v), tf(_v), absorbingPartUnknown, integrationType(_integrationDegreeBnd)); //-1 from sign conventions + if (_useSecondOrderABC) _formulation.integral(1. * im / (2. * _pulsation * sqrt(m)) * grad(dof(_v)), grad(tf(_v)), absorbingPartUnknown, integrationType(_integrationDegreeBnd)); //-1 from sign conventions } } } diff --git a/specific/wave/equation/simplewave.h b/specific/wave/equation/simplewave.h index 9e34a5815a36b976b719e5d0557ad7a401109621..2122ab80ac28f86bc43ba9ad74ee09194804bf08 100644 --- a/specific/wave/equation/simplewave.h +++ b/specific/wave/equation/simplewave.h @@ -24,6 +24,8 @@ namespace simplewave bool _realImpedance; double _const_preconditioner; using EquationInterface<Physic::acoustic>::_boundary; + std::string _topBC; + bool _useSecondOrderABC; public: 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 = ""); diff --git a/synthetics.cpp b/synthetics.cpp index 29bef54ecb1fa5b1a839e60bd9d534a26aab8a24..8f1a4a422512989adf8fa556bf8da2694f83901e 100644 --- a/synthetics.cpp +++ b/synthetics.cpp @@ -24,9 +24,9 @@ int synthetics(const GmshFem& gmshFem) const ParametrizationInterface* const parametrization = newParametrization<T_Physic>(gmshFem); - ConfigurationInterface* configuration = newConfiguration(name, parametrization, gmshFem); + auto configuration = newConfiguration(name, parametrization, gmshFem); - ModelState ms(configuration); + ModelState ms(configuration.get()); unsigned int n_freq = 1; gmshFem.userDefinedParameter(n_freq, "n_freq"); @@ -57,10 +57,10 @@ int synthetics(const GmshFem& gmshFem) msg::indent(); wave::Discretization<T_Physic> w_discret(gmshFem,suffix); - EquationInterface<T_Physic>* const pequation = new ParametrizedEquation<T_Physic>(parametrization,0,2.*M_PI*frequency,configuration,w_discret,gmshFem,suffix); + EquationInterface<T_Physic>* const pequation = new ParametrizedEquation<T_Physic>(parametrization,0,2.*M_PI*frequency,configuration.get(),w_discret,gmshFem,suffix); - WaveUpdater<T_Physic> wu(configuration,nullptr,pequation); - DataUpdater<T_Physic> du(std::vector<double>(1,frequency),configuration,&wu,nullptr); + WaveUpdater<T_Physic> wu(configuration.get(),nullptr,pequation); + DataUpdater<T_Physic> du(std::vector<double>(1,frequency),configuration.get(),&wu,nullptr); std::array<bool,5> dataNeedUpToDate = {true,false,false,false,false}; du.get(dataNeedUpToDate,ms).write(Type::FS,name+"_data"+suffix); @@ -97,7 +97,6 @@ int synthetics(const GmshFem& gmshFem) msg::unindent(); } msg::unindent(); - delete configuration; delete parametrization; return 0; diff --git a/tests/test.cpp b/tests/test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3a865294a01664b6f63317241c7bbd6c11c8c7f0 --- /dev/null +++ b/tests/test.cpp @@ -0,0 +1,109 @@ +#define BOOST_TEST_MODULE fwi_tests +#include <boost/test/unit_test.hpp> + +#include <cstring> + +#include <gmsh.h> +#include <gmshfem/Formulation.h> +#include <gmshfem/GmshFem.h> +#include "../common/wave/element.h" +#include "../common/data/element.h" +#include "../specific/data/element.h" + +#include "dummyAcquisition.h" + +#define INIT_GMSHFEM() \ + namespace geo = gmsh::model::geo; \ + namespace model = gmsh::model; \ + namespace mesh = gmsh::model::mesh; \ + using namespace gmshfem; \ + using namespace gmshfem::common; \ + using namespace gmshfem::problem; \ + using namespace gmshfem::domain; \ + using namespace gmshfem::field; \ + using namespace gmshfem::function; \ + using namespace gmshfem::post; \ + using namespace gmshfem::equation; \ + gmshfem::common::GmshFem fem(0, nullptr); + +BOOST_AUTO_TEST_SUITE(WaveMultiFieldTest); + +BOOST_AUTO_TEST_CASE(TestHomoegenuousDirichletWMF) +{ + INIT_GMSHFEM(); + fem.getArgsManager()->addUserDefinedParameter("wave_FunctionSpaceDegree", "2"); + fem.getArgsManager()->addUserDefinedParameter("wave_FunctionSpaceType", "HierarchicalH1"); + + double lc = 0.1; + model::add("Poisson"); + + geo::addPoint(0.0, 0.0, 0.0, lc, 1); + geo::addPoint(1.0, 0.0, 0.0, lc, 2); + geo::addPoint(1.0, 1.0, 0.0, lc, 3); + geo::addPoint(0.0, 1.0, 0.0, lc, 4); + + geo::addLine(1, 2); + geo::addLine(2, 3); + geo::addLine(3, 4); + geo::addLine(4, 1); + + geo::addCurveLoop({1,2,3,4}); + geo::addPlaneSurface({1}); + geo::synchronize(); + mesh::generate(); + + model::addPhysicalGroup(1, {4}, 1); + model::setPhysicalName(1, 1, "gammaLeft"); + + model::addPhysicalGroup(2, {1}, 1); + model::setPhysicalName(2, 1, "omega"); + + Formulation<std::complex<double>> formulation("Poisson"); + Domain omega("omega"); + Domain gammaLeft("gammaLeft"); + + // Allocate an Auxiliary Field that will serve as proxy to write in the WMF + WaveAuxilaryField<Physic::acoustic> v("v", omega, "Poisson", wave::Discretization<Physic::acoustic>(fem)); + v.addConstraint(gammaLeft, 0.); // Apply Dirichlet *before* preprocessing, to get correct DOF dictionary + + // Assemble LHS to get the correct number of DOFs + formulation.integral(grad(dof(v)), grad(tf(v)), omega, "Gauss6"); + formulation.pre(); + + WaveMultiField<Physic::acoustic> wmf(2, "v_multi"); + wmf.initializeField(v); + v.setField(&wmf); + + // First solve + v.setIndex(0); + formulation.integral(-1., tf(v), omega, "Gauss6"); + formulation.assemble(); + formulation.solve(true); + + // Second solve + formulation.setRHSToZero(); + + v.setIndex(1); + formulation.removeTerms(); + formulation.integral(-2., tf(v), omega, "Gauss6"); + formulation.assemble(); + formulation.solve(true); + + // Check analytical solution to tolerance. + double f = 1; + auto expected = f * x<std::complex<double>>() * (1. - 0.5 * x<std::complex<double>>()); + + // Quadratic solution -> should be exact on a coarse mesh. + auto integralV = abs(integrate(v, omega, "Gauss4")); + auto integralErr1 = abs(integrate(expected - wmf[0], omega, "Gauss4")); + auto integralErr2 = abs(integrate(2. * expected - wmf[1], omega, "Gauss4")); + BOOST_TEST(integralV < 1e-8, "AuxiliaryWaveField should be empty. Integral of absolute value is " << integralV); + BOOST_TEST(integralErr1 < 1e-8, "First WMF has the wrong value. Error norm: " << integralErr1); + BOOST_TEST(integralErr2 < 1e-8, "Second WMF has the wrong value. Error norm: " << integralErr2); +} +BOOST_AUTO_TEST_CASE(dummy_test) +{ + BOOST_CHECK(1 + 1 == 2); +} + +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/time_synthetics_wave.cpp b/time_synthetics_wave.cpp index 49c571c986e34416a039c45b6fd1fb82455f2c3f..590f427308b158927701c2fcbbed6ab3a00b514a 100644 --- a/time_synthetics_wave.cpp +++ b/time_synthetics_wave.cpp @@ -94,7 +94,7 @@ int main(int argc, char **argv) const ParametrizationInterface* const parametrization = newParametrization<Physic::acoustic>(gmshFem); - ConfigurationInterface* config = newConfiguration(name, parametrization, gmshFem); + auto configuration = newConfiguration(name, parametrization, gmshFem); ModelState ms(config);