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

Initial commit (reproducing result of paper 1)

parents
No related branches found
No related tags found
No related merge requests found
Showing
with 1272 additions and 0 deletions
build/
*.msh
*.pos
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(fwi CXX)
macro(opt OPTION HELP VALUE)
option(ENABLE_${OPTION} ${HELP} ${VALUE})
set(OPT_TEXI "${OPT_TEXI}\n@item ENABLE_${OPTION}\n${HELP} (default: ${VALUE})")
endmacro()
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("-std=c++11" HAVE_CXX11)
if(HAVE_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
else()
message(ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()
check_cxx_compiler_flag("-Wall" HAVE_WALL)
if(HAVE_WALL)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
endif()
check_cxx_compiler_flag("-O3" HAVE_O3)
if(HAVE_O3)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
endif()
####
# Mandatory libs
####
macro(find_all_libraries VARNAME LISTNAME PATH SUFFIX)
set(${VARNAME})
list(LENGTH ${LISTNAME} NUM_LIST)
foreach(LIB ${${LISTNAME}})
if("${PATH}" STREQUAL "")
find_library(FOUND_LIB ${LIB} PATH_SUFFIXES ${SUFFIX})
else("${PATH}" STREQUAL "")
find_library(FOUND_LIB ${LIB} PATHS ${PATH} NO_DEFAULT_PATH)
endif("${PATH}" STREQUAL "")
if(FOUND_LIB)
list(APPEND ${VARNAME} ${FOUND_LIB})
endif(FOUND_LIB)
unset(FOUND_LIB CACHE)
endforeach(LIB)
list(LENGTH ${VARNAME} NUM_FOUND_LIBRARIES)
if(NUM_FOUND_LIBRARIES LESS NUM_LIST)
set(${VARNAME})
endif(NUM_FOUND_LIBRARIES LESS NUM_LIST)
endmacro(find_all_libraries)
# Gmsh (Mandatory)
find_library(GMSH_LIB gmsh)
if(NOT GMSH_LIB)
message(FATAL_ERROR "Could not find libgmsh")
endif(NOT GMSH_LIB)
find_path(GMSH_INC gmsh.h)
if(NOT GMSH_INC)
message(FATAL_ERROR "Could not find gmsh.h")
endif(NOT GMSH_INC)
list(APPEND EXTRA_INCS ${GMSH_INC})
list(APPEND EXTRA_LIBS ${GMSH_LIB})
# GmshFem
find_library(GMSHFEM_LIB gmshfem)
if(NOT GMSHFEM_LIB)
message(FATAL_ERROR "Could not find libgmshfem")
endif(NOT GMSHFEM_LIB)
find_path(GMSHFEM_INC gmshfem/GmshFem.h)
if(NOT GMSHFEM_INC)
message(FATAL_ERROR "Could not find 'gmshfem/GmshFem.h'")
endif(NOT GMSHFEM_INC)
list(APPEND EXTRA_LIBS ${GMSHFEM_LIB})
list(APPEND EXTRA_INCS ${GMSHFEM_INC}/gmshfem/)
# Eigen
list(APPEND EXTRA_INCS ../fem/contrib/eigen/Eigen ../fem/contrib/eigen/Eigen/src/Core/util/)
# OpenMP
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")
endif()
include_directories(${EXTRA_INCS})
file( GLOB LIB_SOURCES common/*/*/*.cpp common/*/*.cpp common/*.cpp specific/*/*/*.cpp specific/*/*.cpp specific/*.cpp)
file( GLOB LIB_HEADERS common/*/*/*.h common/*/*.h common/*.h specific/*/*/*.h specific/*/*.h specific/*.h)
add_library( fwi ${LIB_SOURCES} ${LIB_HEADERS})
add_executable( synthetics synthetics.cpp ${EXTRA_INCS})
target_link_libraries( synthetics fwi ${EXTRA_LIBS})
add_executable( directional directional.cpp ${EXTRA_INCS})
target_link_libraries( directional fwi ${EXTRA_LIBS})
add_executable( gradient gradient.cpp ${EXTRA_INCS})
target_link_libraries( gradient fwi ${EXTRA_LIBS})
add_executable( convergence convergence.cpp ${EXTRA_INCS})
target_link_libraries( convergence fwi ${EXTRA_LIBS})
//Standard library
//GmshFem library
/*
#include "Exception.h"
#include "Message.h"
#include "Formulation.h"
*/
//FWI Library
#include "configuration.h"
/*
using namespace gmshfem::field;
using namespace gmshfem::function;
using namespace gmshfem::problem;
using namespace gmshfem::equation;
*/
using namespace gmshfem;
using namespace gmshfem::common;
using namespace gmshfem::domain;
bool ConfigurationInterface::recIsValid(unsigned int shot,unsigned int rec) const
{
if( !(shot<_ns) && !(rec<nr(shot)) )
{
throw Exception("Receiver "+std::to_string(rec)+ " is out of scope for shot "+std::to_string(shot)+".");
}
return true;
}
bool ConfigurationInterface::emIsValid(unsigned int shot,unsigned int em) const
{
if( !(shot<_ns) && !(em<ne(shot)) )
{
throw Exception("Emitter "+std::to_string(em)+ " is out of scope for shot "+std::to_string(shot)+".");
}
return true;
}
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.");
}
return true;
}
bool ConfigurationInterface::shotIsValid(unsigned int shot) const
{
if( !(shot<_ns) )
{
throw Exception("Shot "+std::to_string(shot)+" is out of scope.");
}
return true;
}
const std::vector<unsigned int>& ConfigurationInterface::emitter_idx(unsigned int shot) const
{
shotIsValid(shot);
return _emitter[shot];
}
const std::vector<unsigned int>& ConfigurationInterface::receiver_idx(unsigned int shot) const
{
shotIsValid(shot);
return _receiver[shot];
}
unsigned int ConfigurationInterface::isEmitter(unsigned int point) const
{
std::vector<unsigned int> idx = emitter_idx();
return (std::find(idx.begin(), idx.end(), point) != idx.end());
}
unsigned int ConfigurationInterface::isReceiver(unsigned int point) const
{
std::vector<unsigned int> idx = receiver_idx();
return (std::find(idx.begin(), idx.end(), point) != idx.end());
}
Domain ConfigurationInterface::emitter(unsigned int shot, unsigned int em) const
{
emIsValid(shot,em);
return _point[emitter_idx(shot)[em]];
}
Domain ConfigurationInterface::receiver(unsigned int shot, unsigned int rec) const
{
recIsValid(shot,rec);
return _point[receiver_idx(shot)[rec]];
}
Domain ConfigurationInterface::point(unsigned int idx) const
{
pntIsValid(idx);
return _point[idx];
}
std::vector<unsigned int> ConfigurationInterface::emitter_idx(bool includeReceivers) const
{
std::vector<unsigned int> em_idx;
std::vector<unsigned int> rec_idx;
if(!includeReceivers){rec_idx = receiver_idx(true);}
for (unsigned int s = 0; s < ns(); s++)
{
for (unsigned int e = 0; e < ne(s); e++)
{
if
(
(std::find(em_idx.begin(), em_idx.end(), _emitter[s][e]) == em_idx.end())
&&
(std::find(rec_idx.begin(), rec_idx.end(), _emitter[s][e]) == rec_idx.end())
)
{
em_idx.push_back(_emitter[s][e]);
}
}
}
return em_idx;
}
std::vector<unsigned int> ConfigurationInterface::receiver_idx(bool includeEmitters) const
{
std::vector<unsigned int> rec_idx;
std::vector<unsigned int> em_idx;
if(!includeEmitters){em_idx = emitter_idx(true);}
for (unsigned int s = 0; s < ns(); s++)
{
for (unsigned int r = 0; r < nr(s); r++)
{
if
(
(std::find(rec_idx.begin(), rec_idx.end(), _receiver[s][r]) == rec_idx.end())
&&
(std::find(em_idx.begin(), em_idx.end(), _receiver[s][r]) == em_idx.end())
)
{
rec_idx.push_back(_receiver[s][r]);
}
}
}
return rec_idx;
}
std::vector<unsigned int> ConfigurationInterface::receiverPerShot() const
{
std::vector<unsigned int> recPerShot;
for (unsigned int s = 0; s < _ns; s++)
{
recPerShot.push_back(nr(s));
}
return recPerShot;
}
#ifndef H_CONFIGURATION_INTERFACE
#define H_CONFIGURATION_INTERFACE
//GmshFEM library
#include "GmshFem.h"
#include "Domain.h"
/*
//Standard Library
#include <string>
#include "Function.h"
#include "Exception.h"
//#include "Message.h"
#include "FieldForm0.h"
#include "discretization.h"
#include "../specific/physics.h"
*/
//GmshFWI
#include "model/element.h"
#include "support.h"
class ConfigurationInterface //(abstract)
{
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;
gmshfem::domain::Domain _data_omega;
unsigned int _np;
std::vector< gmshfem::domain::Domain > _point;
gmshfem::domain::Domain _points;
unsigned int _ns;
std::vector< std::vector<unsigned int> > _emitter;
std::vector< std::vector<unsigned int> > _receiver;
ModelFunction _m0;
bool _remesh;
virtual void wave_mesh() const = 0;
virtual void data_mesh() const = 0;
public:
ConfigurationInterface(const gmshfem::common::GmshFem& gmshFem)
{
unsigned int remesh = true;
gmshFem.userDefinedParameter(remesh, "remesh");
_remesh = ((bool) remesh);
};
virtual ~ConfigurationInterface() = default;
virtual void mesh() const = 0;
virtual double array() const {return 0.;};
virtual double depth() const {return 0.;};
virtual std::string wave_gmodel() const = 0;
virtual std::string model_gmodel() const = 0;
virtual std::string data_gmodel() const = 0;
gmshfem::domain::Domain wave_omega(Support support) const {return _wave_omega[support];};
gmshfem::domain::Domain model_unknown(Support support) const {return _model_unknown[support];};
gmshfem::domain::Domain model_known(Support support) const {return _model_known[support];};
gmshfem::domain::Domain data_omega() const {return _data_omega;};
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;};
gmshfem::domain::Domain emitter(unsigned int shot, unsigned int em) const;
gmshfem::domain::Domain receiver(unsigned int shot, unsigned int rec) const;
gmshfem::domain::Domain point(unsigned int idx) const;
const std::vector<unsigned int>& emitter_idx(unsigned int shot) const;
const std::vector<unsigned int>& receiver_idx(unsigned int shot) const;
std::vector<unsigned int> emitter_idx(bool includeReceivers = false) const;
std::vector<unsigned int> receiver_idx(bool includeEmitters = false) const;
unsigned int isEmitter(unsigned int point) const;
unsigned int isReceiver(unsigned int point) const;
unsigned int np() const {return _np;};
unsigned int ns() const {return _ns;};
unsigned int nr(unsigned int shot) const {return _receiver[shot].size();};
unsigned int ne(unsigned int shot) const {return _emitter[shot].size();};
bool recIsValid(unsigned int shot,unsigned int rec) const;
bool emIsValid(unsigned int shot,unsigned int em) const;
bool pntIsValid(unsigned int e_r) const;
bool shotIsValid(unsigned int shot) const;
std::vector<unsigned int> receiverPerShot() const;
ModelFunction m0() const
{
return _m0.copy();
};
virtual double m_reference() const = 0;
};
#endif // H_CONFIGURATION_INTERFACE
//GmshFem library
#include "Exception.h"
#include "CSVio.h"
using namespace gmshfem;
using namespace gmshfem::common;
//FWI Library
#include "element.h"
#include "../../specific/wavetodata.h"
/*
* Class Data
*/
template<Physic T_Physic>
bool Data<T_Physic>::isValid(unsigned int s,unsigned int r) const
{
if ( !(s<ns()) )
{
throw Exception("Shot "+std::to_string(s)+" is out of scope");
}
if ( !(r<nr(s)) )
{
throw Exception("Receiver "+std::to_string(r)+" is out of scope");
}
return true;
}
template<Physic T_Physic>
Data<T_Physic>::Data(const ConfigurationInterface* const config) : _config(config)
{
std::vector<unsigned int> receiverPerShot = _config->receiverPerShot();
for (unsigned int s = 0; s < receiverPerShot.size(); s++)
{
_value.emplace_back(std::vector<PointData<T_Physic>>(receiverPerShot[s],PointData<T_Physic>()));
}
}
template<Physic T_Physic>
Data<T_Physic>::Data(std::string filename, const ConfigurationInterface* const config) : _config(config)
{
read(filename);
}
template<Physic T_Physic>
Data<T_Physic>::Data(const Data<T_Physic>& other) : Data(other._config) {*this = other;}
template<Physic T_Physic> void Data<T_Physic>::read(std::string filename)
{
/* msg::print << "Read " + filename << msg::endl; */
CSVio file(filename,';',OpeningMode::Reading);
_value.clear();
PointData<T_Physic> val;
file >> val;
while ( !file.isEOF() )
{
std::vector<PointData<T_Physic>> rec_value{};
while ( !file.isEOL() )
{
rec_value.push_back(val);
file >> val;
}
rec_value.push_back(val);
_value.push_back(rec_value);
file >> val;
}
file.close();
}
template<Physic T_Physic> void Data<T_Physic>::write(std::string filename,std::string type) const
{
/* msg::print << "Write " + filename << msg::endl; */
CSVio file(filename,';',OpeningMode::NewFile);
for (auto s = _value.begin(); s != _value.end(); s++)
{
for (auto r = s->begin(); r != s->end(); r++)
{
file << (*r);
}
file << csv::endl;
}
file.close();
}
template<Physic T_Physic>
PointData<T_Physic> Data<T_Physic>::value(unsigned int s,unsigned int r) const
{
isValid(s,r);
return _value[s][r];
}
template<Physic T_Physic>
void Data<T_Physic>::value(unsigned int s,unsigned int r,const PointData<T_Physic>& value)
{
isValid(s,r);
_value[s][r] = value;
}
template<Physic T_Physic>
void Data<T_Physic>::value(const WaveMultiField<T_Physic>& w)
{
*this = wave_to_data(_config,w);
}
template<Physic T_Physic>
std::vector<unsigned int> Data<T_Physic>::receiverPerShot() const
{
std::vector<unsigned int> recPerShot(ns(),0);
for (unsigned int s = 0; s < ns(); s++)
{
recPerShot[s] = nr(s);
}
return recPerShot;
}
template<Physic T_Physic>
void Data<T_Physic>::operator=(const Data<T_Physic>& other)
{
areCompatible(*this,other);
for (unsigned int s = 0; s < ns(); s++)
{
for (unsigned int r = 0; r < nr(s); r++)
{
value(s,r,other.value(s,r));
}
}
}
template<Physic T_Physic>
Data<T_Physic> Data<T_Physic>::operator+(const Data<T_Physic>& other) const
{
areCompatible(*this,other);
Data<T_Physic> sum(*this);
for (unsigned int s = 0; s < ns(); s++)
{
for (unsigned int r = 0; r < nr(s); r++)
{
sum.value(s,r, this->value(s,r)+other.value(s,r) );
}
}
return sum;
}
template<Physic T_Physic>
Data<T_Physic> Data<T_Physic>::operator-(const Data<T_Physic>& other) const
{
areCompatible(*this,other);
Data<T_Physic> sub(*this);
for (unsigned int s = 0; s < ns(); s++)
{
for (unsigned int r = 0; r < nr(s); r++)
{
sub.value(s,r, this->value(s,r)-other.value(s,r) );
}
}
return sub;
}
template<Physic T_Physic>
Data<T_Physic> Data<T_Physic>::operator/(const Data<T_Physic>& other) const
{
areCompatible(*this,other);
Data<T_Physic> div(*this);
for (unsigned int s = 0; s < ns(); s++)
{
for (unsigned int r = 0; r < nr(s); r++)
{
div.value(s,r, this->value(s,r)/other.value(s,r) );
}
}
return div;
}
template<Physic T_Physic>
Data<T_Physic> Data<T_Physic>::operator/(double a) const
{
Data<T_Physic> div(*this);
for (unsigned int s = 0; s < ns(); s++)
{
for (unsigned int r = 0; r < nr(s); r++)
{
div.value(s,r, this->value(s,r)/a );
}
}
return div;
}
template class Data<Physic::acoustic>;
#ifndef H_COMMON_DATA_ELEMENT
#define H_COMMON_DATA_ELEMENT
//FWI Library
#include "../../specific/physic.h"
#include "../../specific/data/element.h"
#include "../configuration.h"
#include "../wave/element.h"
/*
* Data
*/
template<Physic T_Physic>
class Data final
{
private:
std::vector< std::vector<PointData<T_Physic>> > _value;
const ConfigurationInterface* const _config;
public:
Data(const ConfigurationInterface* const config);
Data(std::string filename, const ConfigurationInterface* const config);
Data(const Data<T_Physic>& other);
void write(std::string filename,std::string type = "csv") const;
void read(std::string filename);
PointData<T_Physic> value(unsigned int s,unsigned int r) const;
void value(unsigned int s,unsigned int r,const PointData<T_Physic>& value);
void value(const WaveMultiField<T_Physic>& w);
unsigned int ns() const {return _value.size();};
unsigned int nr(unsigned int shot) const {return _value[shot].size();};
std::vector<unsigned int> receiverPerShot() const;
void operator=(const Data<T_Physic>& other);
Data<T_Physic> operator+(const Data<T_Physic>& other)const;
Data<T_Physic> operator-(const Data<T_Physic>& other)const;
Data<T_Physic> operator/(const Data<T_Physic>& other)const;
Data<T_Physic> operator/(double a)const;
private:
bool isValid(unsigned int s,unsigned r) const;
};
template<Physic T_Physic>
bool areCompatible(const Data<T_Physic>& d1,const Data<T_Physic>& d2)
{
bool areCompatible = (d1.ns()==d2.ns());
if(!areCompatible)
{
throw gmshfem::common::Exception("Data1 and Data2 are imcompatible (number of shots).");
}
for (unsigned int s = 0; s < d1.ns(); s++)
{
areCompatible = (d1.nr(s)==d2.nr(s));
if(!areCompatible)
{
throw gmshfem::common::Exception("Data1 and Data2 are imcompatible (number of receivers, shot "+std::to_string(s)+").");
}
}
return areCompatible;
};
template<Physic T_Physic>
double l2norm(const Data<T_Physic>& d)
{
double nrm = 0.;
for (unsigned int s = 0; s < d.ns(); s++)
{
for (unsigned int r = 0; r < d.nr(s); r++)
{
nrm += norm(d.value(s,r));
}
}
return nrm;
}
template<Physic T_Physic>
Data<T_Physic> conj(const Data<T_Physic>& d)
{
Data<T_Physic> cnj(d);
for (unsigned int s = 0; s < d.ns(); s++)
{
for (unsigned int r = 0; r < d.nr(s); r++)
{
cnj.value(s,r, std::conj(d.value(s,r)) );
}
}
return cnj;
};
#endif // H_COMMON_DATA_ELEMENT
#ifndef H_COMMON_DATA_OBJECTIVE
#define H_COMMON_DATA_OBJECTIVE
//GmshFem Library
#include "Formulation.h"
//FWI Library
#include "../state.h"
#include "../../wave/element.h"
#include "../../configuration.h"
//Forward declaration
class ModelUpdater;
template<Physic T_Physic>
class DataUpdater;
/*
* ObjectiveInterface
*/
template<Physic T_Physic>
class ObjectiveInterface
{
protected:
const Data<T_Physic>* const _d0;
public:
ObjectiveInterface(const Data<T_Physic>* const d0): _d0(d0) {};
virtual ~ObjectiveInterface() = default;
virtual double performance(const Data<T_Physic>& d) = 0;
virtual const Data<T_Physic>& update(Type type, const DataStateEvaluator<T_Physic>& ds) = 0;
virtual void link(ModelUpdater* const mu, DataUpdater<T_Physic>* const du) {};
virtual void unlink() {};
virtual void modelIsObsolete() {};
};
/*
* DifferentialObjectiveInterface
*/
template <Physic T_Physic>
class DifferentialObjectiveInterface: public ObjectiveInterface<T_Physic>
{
public:
virtual WaveField<T_Physic> update(Type type, const DataStateEvaluator<T_Physic>& d);
protected:
const ConfigurationInterface* const _config;
const data::Discretization<T_Physic> _d_param;
DataField<T_Physic> _v;
gmshfem::problem::Formulation< std::complex< double > > _formulation;
bool _systemIsUpToDate;
bool _systemIsFactorized;
protected:
void update();
virtual void setLHS() = 0;
virtual void setRHS() = 0;
};
#endif //H_COMMON_DATA_OBJECTIVE
//GmeshFem Library
#include "Exception.h"
//FWI Library
#include "state.h"
using namespace gmshfem::common;
/*
* Class DataState
*/
template<Physic T_Physic>
const Data<T_Physic>& DataState<T_Physic>::state(Type type) const
{
if(_isUpToDate[type]){return _state[type];}
else
{
throw Exception(type_to_string(type) + " data is not up to date while required.");
}
}
template class DataState<Physic::acoustic>;
#ifndef H_COMMON_DATA_STATE
#define H_COMMON_DATA_STATE
//FWI Library
#include "../type.h"
#include "element.h"
#include "../configuration.h"
//Forward declaration
template<Physic T_Physic>
class DataUpdater;
/*
* DataStateEvaluator
*/
template<Physic T_Physic>
class DataStateEvaluator
{
public:
virtual const Data<T_Physic>& state(Type type) const = 0;
void write(Type type, std::string name) const {state(type).write(name);};
};
/*
* DataState
*/
template<Physic T_Physic>
class DataState final : public DataStateEvaluator<T_Physic>
{
private:
std::array<Data<T_Physic>,4> _state;
std::array<bool,4> _isUpToDate;
public:
DataState(const ConfigurationInterface* const config):
_state{
Data<T_Physic>(config),
Data<T_Physic>(config),
Data<T_Physic>(config),
Data<T_Physic>(config)
}, _isUpToDate{false,false,false,false} {};
virtual const Data<T_Physic>& state(Type type) const;
friend class DataUpdater<T_Physic>;
};
#endif // H_COMMON_DATA_STATE
#include "updater.h"
#include "../wave/updater.h"
template<Physic T_Physic>
void DataUpdater<T_Physic>::update(Type type, const ModelStateEvaluator& m)
{
if(_ds._isUpToDate[type]){return;}
std::array<bool,4> waveNeedToBeUpToDate = {false,false,false,false};
switch (type)
{
case Type::F:
waveNeedToBeUpToDate[Type::F] = true;
_ds._state[type].value( (_wu->get(waveNeedToBeUpToDate,m)).state(type) );
break;
case Type::A:
update(Type::F,m);
_ds._state[type] = _objective->update(type,_ds);
break;
case Type::PF:
waveNeedToBeUpToDate[Type::PF] = true;
_ds._state[type].value( (_wu->get(waveNeedToBeUpToDate,m)).state(type) );
break;
case Type::PA:
update(Type::F,m);
update(Type::PF,m);
_ds._state[type] = _objective->update(type,_ds);
break;
}
_ds._isUpToDate[type] = true;
}
template<Physic T_Physic>
const DataStateEvaluator<T_Physic>& DataUpdater<T_Physic>::get(std::array<bool,4> needToBeUpToDate, const ModelStateEvaluator& m)
{
for (unsigned int t = 0; t < 4; t++)
{
Type type = ((Type) t);
if(needToBeUpToDate[type]){update(type,m);}
}
return _ds;
}
template<Physic T_Physic>
void DataUpdater<T_Physic>::isObsolete(std::array<bool,4> NoMoreUpToDate)
{
for (unsigned int t = 0; t < 4; t++)
{
if(NoMoreUpToDate[t]){_ds._isUpToDate[t] = false;}
}
}
template class DataUpdater<Physic::acoustic>;
#ifndef H_COMMON_DATA_UPDATER
#define H_COMMON_DATA_UPDATER
//FWI Library
//#include "../../specific/physic.h"
#include "state.h"
#include "objective/objective.h"
#include "../model/state.h"
//#include "../configuration.h"
//Forward declaration
template<Physic T_Physic>
class WaveUpdater;
/*
* DataUpdater
*/
template<Physic T_Physic>
class DataUpdater final
{
private:
DataState<T_Physic> _ds;
WaveUpdater<T_Physic>* const _wu;
ObjectiveInterface<T_Physic>* const _objective;
void update(Type type, const ModelStateEvaluator& m);
public:
DataUpdater(const ConfigurationInterface* const config, WaveUpdater<T_Physic>* wu, ObjectiveInterface<T_Physic>* objective): _ds(config), _wu(wu), _objective(objective) {};
const DataStateEvaluator<T_Physic>& get(std::array<bool,4> needToBeUpToDate, const ModelStateEvaluator& m);
void isObsolete(std::array<bool,4> NoMoreUpToDate);
};
#endif // H_COMMON_DATA_UPDATER
#ifndef H_FUNCTIONAL
#define H_FUNCTIONAL
//GmshFWI Library
#include "model/element.h"
class FunctionalInterface
{
public:
virtual ~FunctionalInterface() = default;
virtual void setModel(const ModelField& m) = 0;
virtual void setModel(const ModelFunction& m) = 0;
virtual void setModelPerturbation(const ModelField& dm) = 0;
virtual void setModelPerturbation(const ModelFunction& dm) = 0;
virtual const ModelField& m() const = 0;
virtual const ModelField& dm()const = 0;
/* performance */
virtual double performance() = 0;
template<class M> double performance(const M &m)
{
setModel(m);
return performance();
};
/*
* First order
*/
/* gradient */
virtual const ModelField& gradient() = 0;
template<class M> const ModelField& gradient(const M &m)
{
setModel(m);
return gradient();
};
/* directional1 */
virtual double directional1(const ModelFunction &dm) = 0;
virtual double directional1(const ModelField &dm) = 0;
template<class M,class DM>
double directional1(const M &m,const DM &dm)
{
setModel(m);
return directional1(dm);
};
/*
* Second order
*/
/* hessian */
virtual const ModelField& hessian() = 0;
template<class DM>
const ModelField& hessian(const DM &dm2)
{
setModelPerturbation(dm2);
return hessian();
}
template<class M,class DM>
const ModelField& hessian(const M &m,const DM &dm2)
{
setModel(m);
return hessian(dm2);
}
/* directional2 */
virtual double directional2(const ModelFunction &dm2) = 0;
virtual double directional2(const ModelField &dm2) = 0;
template<class DM1,class DM2>
double directional2(const DM1 &dm1,const DM2 &dm2)
{
setModelPerturbation(dm2);
return directional2(dm1);
}
template<class M,class DM1,class DM2>
double directional2(const M &m,const DM1 &dm1,const DM2 &dm2)
{
setModel(m);
return directional2(dm1,dm2);
}
};
#endif // H_FUNCTIONAL
//Standard library
//GmshFem library
#include "Exception.h"
#include "Message.h"
//FWI
#include "discretization.h"
using namespace gmshfem;
using namespace gmshfem::common;
using namespace gmshfem::field;
namespace model
{
/*
* class Discretization
*/
Discretization::Discretization(const GmshFem& gmshFem)
{
msg::print << "Read model discretization parameters" << msg::endl;
std::string str_buffer;
if(
!(gmshFem.userDefinedParameter(_functionSpaceDegree, "model_FunctionSpaceDegree") &&
gmshFem.userDefinedParameter(str_buffer, "model_FunctionSpaceType"))
)
{
throw common::Exception("A model discretization parameter could not be found.");
}
else
{
if(str_buffer=="Lagrange"){_functionSpaceType = FunctionSpaceTypeForm0::Lagrange;}
else if(str_buffer=="HierarchicalH1"){_functionSpaceType = FunctionSpaceTypeForm0::HierarchicalH1;}
else { throw common::Exception("Invalid function space type."); }
}
}
} // namespace model
#ifndef H_MODEL_DISCRETIZATION
#define H_MODEL_DISCRETIZATION
//Standard library
#include <string>
//GmshFem library
#include "GmshFem.h"
#include "FunctionSpaceForm0.h"
#include "Message.h"
namespace model
{
class Discretization
{
private:
gmshfem::field::FunctionSpaceTypeForm0 _functionSpaceType;
unsigned int _functionSpaceDegree;
std::string _integrationType;
public:
Discretization(const gmshfem::common::GmshFem& gmshFem);
gmshfem::field::FunctionSpaceTypeForm0 functionSpaceType() const {return _functionSpaceType;};
std::string integrationType(unsigned int integrandFieldNumber) const
{
return _integrationType + std::to_string(integrandFieldNumber*_functionSpaceDegree);
};
std::string integrationType() const {return _integrationType;};
unsigned int functionSpaceDegree() const {return _functionSpaceDegree;};
void functionSpaceDegree(unsigned int order) {_functionSpaceDegree=order;};
};
}; // namespace model
#endif // H_MODEL_DISCRETIZATION
//Standard library
//GmshFem library
#include "Exception.h"
#include "Post.h"
//GmshFWI Library
#include "element.h"
using namespace gmshfem;
using namespace gmshfem::common;
using namespace gmshfem::post;
/*
* Model
*/
void Model::write(std::string name) const
{
if(_useField){save(_field,_field.domain(),name,"pos","");}
else{save(_function,_field.domain(),name,"pos","");}
}
void Model::field(const ModelField& field)
{
_field = field;
_function = ModelFunction(_field);
_useField = true;
}
void Model::function(const ModelFunction& function)
{
_function = function;
_useField = false;
}
const ModelField& Model::field() const
{
if(!_useField)
{
throw Exception("Model has no field defined.");
}
return _field;
};
const ModelFunction& Model::function() const
{
return _function;
};
#ifndef H_MODEL_ELEMENT
#define H_MODEL_ELEMENT
//GmshFem Library
#include "FieldInterface.h"
#include "Function.h"
#include "Post.h"
//FWI Library
#include "discretization.h"
/*
* ModelField
*/
class ModelField final : public gmshfem::field::Field< std::complex<double> , gmshfem::field::Form::Form0 >
{
public:
ModelField() : gmshfem::field::Field< std::complex<double> , gmshfem::field::Form::Form0 >() {};
ModelField(std::string name,const gmshfem::domain::Domain &domain, std::string gmodel): gmshfem::field::Field< std::complex<double> , gmshfem::field::Form::Form0 >(name, domain, gmshfem::field::FunctionSpaceTypeForm0(), 0, gmodel) {};
ModelField(std::string name,const gmshfem::domain::Domain &domain, std::string gmodel, const model::Discretization& m_discret): gmshfem::field::Field< std::complex<double> , gmshfem::field::Form::Form0 >(name, domain, m_discret.functionSpaceType(), m_discret.functionSpaceDegree(), gmodel) {};
ModelField(const gmshfem::field::Field< std::complex<double> , gmshfem::field::Form::Form0 >& other) : gmshfem::field::Field< std::complex<double> , gmshfem::field::Form::Form0 >(other) {};
void write(std::string name, std::string type="pos", std::string path="") const {gmshfem::post::save(*this,this->domain(),name,type,path);}
};
/*
* ModelFunction
*/
using ModelFunction = gmshfem::function::ScalarFunction< std::complex<double> >;
/*
* Model
*/
class Model final
{
private:
ModelField _field;
ModelFunction _function;
bool _useField;
public:
Model(gmshfem::domain::Domain domain): _field("", domain, ""), _function(0.), _useField(false) {};
void write(std::string name) const;
void field(const ModelField& field);
void function(const ModelFunction& function);
const ModelField& field() const;
const ModelFunction& function() const;
void operator=(const ModelFunction& other){function(other);};
void operator=(const ModelField& other){field(other);};
};
#endif //H_MODEL_ELEMENT
//GmshFEM Library
#include "AlgebraicFunctions.h"
//GmshFWI Library
#include "innerproduct.h"
using namespace gmshfem;
using namespace gmshfem::common;
using namespace gmshfem::field;
static const std::complex< double > im = std::complex< double >(0., 1.);
/*
* DifferentialInnerProductInterface
*/
DifferentialInnerProductInterface::DifferentialInnerProductInterface(const ConfigurationInterface* const config, const model::Discretization& m_discret, const gmshfem::common::GmshFem& gmshFem)
: InnerProductInterface(config, m_discret), _j("_j",_config->model_evaldomain(),_config->model_gmodel(),_m_discret), _formulation("model_formulation"),_systemIsUpToDate(false),_systemIsFactorized(false)
{
if(!gmshFem.userDefinedParameter(_integrationType, "model_IntegrationType"))
{
throw common::Exception("Model integration type could not be found.");
}
}
const ModelField& DifferentialInnerProductInterface::update(const ModelFunction& bulk_sensi, const ModelFunction& boundary_sensi)
{
if(!_systemIsUpToDate)
{
_formulation.removeSystem();
_formulation.initSystem();
_systemIsFactorized=false;
setLHS();
_formulation.pre();
_formulation.assemble();
_systemIsUpToDate=true;
_formulation.removeTerms();
}
setRHS(bulk_sensi,boundary_sensi);
_formulation.assemble();
_formulation.removeTerms();
_formulation.solve(_systemIsFactorized);
_systemIsFactorized=true;
_formulation.setRHSToZero();
return _j;
}
std::complex<double> DifferentialInnerProductInterface::product(const ModelField& m1, const ModelField& m2, bool conjugate = false)
{
algebra::MatrixCCS< std::complex<double> > M;
algebra::Vector< std::complex<double> > m1v, m2v;
m1.getVector(m1v);
m2.getVector(m2v);
_formulation.getLHS(M);
return bilinear(m1v, M, m2v);
}
#ifndef H_COMMON_MODEL_INNERPRODUCT
#define H_COMMON_MODEL_INNERPRODUCT
//GmshFem Library
#include "Formulation.h"
//FWI Library
#include "../state.h"
#include "../discretization.h"
#include "../../configuration.h"
#include "../../sensitivity/updater.h"
//Forward declaration
class ModelPreconditionerUpdater;
class ModelUpdater;
/*
* InnerProductInterface
*/
class InnerProductInterface
{
protected:
const ConfigurationInterface* const _config;
const model::Discretization _m_discret;
public:
InnerProductInterface(const ConfigurationInterface* const config, const model::Discretization& m_discret): _config(config), _m_discret(m_discret) {};
virtual ~InnerProductInterface() = default;
virtual void link(ModelUpdater* const mu, SensitivityUpdater* const su) {};
virtual void unlink() {};
virtual const ModelField& update(const ModelFunction& bulk_sensi, const ModelFunction& boundary_sensi) = 0;
virtual std::complex<double> product(const ModelField& m1, const ModelField& m2, bool conjugate = false) = 0;
virtual void modelIsObsolete() {};
};
/*
* DifferentialInnerProductInterface
*/
class DifferentialInnerProductInterface: public InnerProductInterface
{
protected:
ModelField _j;
gmshfem::problem::Formulation< std::complex< double > > _formulation;
std::string _integrationType;
bool _systemIsUpToDate;
bool _systemIsFactorized;
public:
DifferentialInnerProductInterface(const ConfigurationInterface* const config, const model::Discretization& m_discret, const gmshfem::common::GmshFem& gmshFem);
virtual const ModelField& update(const ModelFunction& bulk_sensi, const ModelFunction& boundary_sensi) ;
std::string integrationType(unsigned int degree) const {return _integrationType + std::to_string(degree);};
virtual std::complex<double> product(const ModelField& m1, const ModelField& m2, bool conjugate);
protected:
virtual void setLHS() = 0;
virtual void setRHS(const ModelFunction& bulk_sensi, const ModelFunction& boundary_sensi) = 0;
};
#endif //H_COMMON_MODEL_INNERPRODUCT
//GmshFem Library
#include "Exception.h"
//FWI Library
#include "state.h"
using namespace gmshfem::common;
/*
* Class ModelState
*/
const Model& ModelState::state(Type type) const
{
if(_isUpToDate[type]){return _state[type];}
else
{
throw Exception(type_to_string(type) + " model is not up to date while required.");
}
}
#ifndef H_MODEL_STATE
#define H_MODEL_STATE
//GmshFEM Library
//GmshFWI Library
#include "../configuration.h"
#include "element.h"
#include "../type.h"
/*
* ModelStateEvaluator
*/
class ModelStateEvaluator
{
public:
virtual const Model& state(Type type) const = 0;
void write(Type type, std::string name) const {state(type).write(name);};
};
/*
* ModelState
*/
class ModelState final: public ModelStateEvaluator
{
private:
std::array<Model,4> _state;
std::array<bool,4> _isUpToDate;
public:
ModelState(const ConfigurationInterface* const config):
_state{
Model(config->model_evaldomain()),
Model(config->model_evaldomain()),
Model(config->model_evaldomain()),
Model(config->model_evaldomain()),
}, _isUpToDate{ {false,false,false,false} } {};
virtual const Model& state(Type type) const;
friend class ModelUpdater;
};
#endif //H_MODEL_STATE
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment