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 1437 additions and 0 deletions
#ifndef H_COMMON_MODEL_UPDATER
#define H_COMMON_MODEL_UPDATER
//GmshFEM Library
#include "Exception.h"
//GmshFWI Library
#include "state.h"
#include "innerproduct/innerproduct.h"
//#include "../equation/equation.h"
#include "../sensitivity/updater.h"
using namespace gmshfem;
using namespace gmshfem::common;
/*
* ModelUpdater
*/
class ModelUpdater final
{
private:
ModelState _ms;
SensitivityUpdater* const _su;
InnerProductInterface* const _innerproduct;
template<class ModelFieldOrFunctionM,class ModelFieldOrFunctionDM>
void update(Type type, const ModelFieldOrFunctionM* const m, const ModelFieldOrFunctionDM* const dm)
{
if(_ms._isUpToDate[type]){return;}
switch (type)
{
case Type::F:
if(m==nullptr)
{
throw Exception("Model is required while not up to date.");
}
else
{
_ms._state[type] = *m;
}
break;
case Type::A:
update(Type::F,m,dm);
_ms._state[type] = _innerproduct->update(
_su->get(to_order(type),Support::BLK,_ms),
_su->get(to_order(type),Support::BND,_ms)
);
break;
/*
*/
//_ms._state[type] = 1.;
//throw Exception("Stop in update adjoint model.");
case Type::PF:
if(dm==nullptr)
{
throw Exception("Model perturbation is required while not up to date.");
}
else
{
_ms._state[type] = *dm;
}
break;
case Type::PA:
update(Type::F,m,dm);
update(Type::PF,m,dm);
_ms._state[type] =
_innerproduct->update(
_su->get(to_order(type),Support::BLK,_ms),
_su->get(to_order(type),Support::BND,_ms)
);
break;
}
_ms._isUpToDate[type] = true;
}
template<class ModelFieldOrFunctionM>
void update(Type type, const ModelFieldOrFunctionM* const m)
{
update<ModelFieldOrFunctionM,ModelFieldOrFunctionM>(type,m,nullptr);
}
void update(Type type)
{
update<ModelField,ModelField>(type,nullptr,nullptr);
}
public:
ModelUpdater(const ConfigurationInterface* const config, SensitivityUpdater* const su, InnerProductInterface* const innerproduct) : _ms(config), _su(su), _innerproduct(innerproduct) {};
template<class ModelFieldOrFunctionM,class ModelFieldOrFunctionDM>
const ModelState& get(std::array<bool,4> needToBeUpToDate, const ModelFieldOrFunctionM* const m, const ModelFieldOrFunctionDM* const dm)
{
for (unsigned int t = 0; t < 4; t++)
{
Type type = ((Type) t);
if(needToBeUpToDate[type]){update(type,m,dm);}
}
return _ms;
};
template<class ModelFieldOrFunctionM>
const ModelState& get(std::array<bool,4> needToBeUpToDate, const ModelFieldOrFunctionM* const m)
{
return get<ModelFieldOrFunctionM,ModelFieldOrFunctionM>(needToBeUpToDate,m,nullptr);
};
const ModelState& get(std::array<bool,4> needToBeUpToDate)
{
return get<ModelField,ModelField>(needToBeUpToDate,nullptr,nullptr);
};
const Model& m() const
{
return _ms.state(Type::F);
}
const Model& dm() const
{
return _ms.state(Type::PF);
}
void isObsolete(std::array<bool,4> NoMoreUpToDate)
{
for (unsigned int t = 0; t < 4; t++)
{
if(NoMoreUpToDate[t]){_ms._isUpToDate[t] = false;}
}
}
};
#endif // H_COMMON_MODEL_UPDATER
//GmshFWI Library
#include "order.h"
Order to_order(Type type)
{
switch (type)
{
default:
case Type::F: return Order::FST;
case Type::A: return Order::FST;
case Type::PF: return Order::SCD;
case Type::PA: return Order::SCD;
}
}
std::string order_to_string(Order order)
{
switch (order)
{
default:
case Order::FST: return "first";
case Order::SCD: return "second";
case Order::DIAG: return "diagonal";
}
}
#ifndef H_ORDER
#define H_ORDER
//Standard Library
#include <string>
//GmshFWI Library
#include "type.h"
enum Order : unsigned int {FST=0, SCD=1, DIAG=2};
Order to_order(Type type);
std::string order_to_string(Order order);
#endif // H_SUPPORT
//Standard library
//GmshFem library
#include "Exception.h"
//GmshFWI Library
#include "state.h"
using namespace gmshfem;
using namespace gmshfem::common;
/*
* SensitivityState
*/
const ModelFunction& SensitivityState::state(Order order, Support support) const
{
if(!_isUpToDate[order][support])
{
throw Exception(order_to_string(order) + " sensitivity is not up to date while required.");
}
return _state[order][support];
}
#ifndef H_COMMON_SENSITIVITY_STATE
#define H_COMMON_SENSITIVITY_STATE
//GmshFWI Library
#include "../support.h"
#include "../model/state.h"
#include "../order.h"
/*
* SensitivityStateEvaluator
*/
class SensitivityStateEvaluator
{
public:
virtual const ModelFunction& state(Order order, Support support) const = 0;
};
/*
* SensitivityState
*/
class SensitivityState: public SensitivityStateEvaluator
{
private:
std::array<std::array<ModelFunction,2>,3> _state;
std::array<std::array<bool,2>,3> _isUpToDate = {{ {false,false} , {false,false}, {false,false} }};
public:
virtual const ModelFunction& state(Order order, Support support) const;
friend class SensitivityUpdater;
};
#endif // H_COMMON_SENSITIVITY_STATE
//Standard library
//GmshFem library
//GmshFWI Library
#include "updater.h"
using namespace gmshfem;
using namespace gmshfem::common;
/*
* SensitivityUpdater
*/
const ModelFunction& SensitivityUpdater::get(Order order, Support support,const ModelStateEvaluator& ms)
{
update(order,support,ms);
return _ss.state(order,support);
}
void SensitivityUpdater::update(Order order, Support support, const ModelStateEvaluator& ms)
{
if(_ss._isUpToDate[order][support]){return;}
_ss._state[order][support] = sensitivity(order, support, ms);
_ss._isUpToDate[order][support] = true;
}
void SensitivityUpdater::isObsolete(std::array<bool,3> NoMoreUpToDate)
{
for (unsigned int o = 0; o < 3; o++)
{
if(NoMoreUpToDate[o])
{
_ss._isUpToDate[o] = { {false, false} };
}
}
}
/*
* SensitivityUpdaterFromWave
*/
template<Physic T_Physic>
ModelFunction SensitivityUpdaterFromWave<T_Physic>::sensitivity(Order order, Support support, const ModelStateEvaluator& ms)
{
std::array<bool,4> waveNeedToBeUpToDate = {false,false,false,false};
switch (order)
{
case Order::SCD:
waveNeedToBeUpToDate[Type::PF] = true;
waveNeedToBeUpToDate[Type::PA] = true;
case Order::FST:
waveNeedToBeUpToDate[Type::F] = true;
waveNeedToBeUpToDate[Type::A] = true;
case Order::DIAG: default: break;
}
return _equation->update_sensitivity(order,support,ms,_wu->get(waveNeedToBeUpToDate,ms));
}
template class SensitivityUpdaterFromWave<Physic::acoustic>;
#ifndef H_COMMON_SENSITIVITY_UPDATER
#define H_COMMON_SENSITIVITY_UPDATER
//GmshFWI Library
#include "state.h"
#include "../type.h"
#include "../../specific/physic.h"
#include "../wave/equation/equation.h"
#include "../wave/updater.h"
/*
* SensitivityUpdater
*/
class SensitivityUpdater
{
private:
SensitivityState _ss;
void update(Order order, Support support, const ModelStateEvaluator& ms);
virtual ModelFunction sensitivity(Order order, Support support, const ModelStateEvaluator& ms) = 0;
public:
const ModelFunction& get(Order order, Support support,const ModelStateEvaluator& ms);
void isObsolete(std::array<bool,3> NoMoreUpToDate);
};
/*
* SensitivityUpdaterFromWave
*/
template<Physic T_Physic>
class SensitivityUpdaterFromWave : public SensitivityUpdater
{
public:
SensitivityUpdaterFromWave(WaveUpdater<T_Physic>* const wu, EquationInterface<T_Physic>* const equation) : _wu(wu), _equation(equation) {};
private:
WaveUpdater<T_Physic>* const _wu;
EquationInterface<T_Physic>* const _equation;
virtual ModelFunction sensitivity(Order order, Support support, const ModelStateEvaluator& ms);
};
#endif // H_COMMON_SENSITIVITY_UPDATER
//GmshFWI Library
#include "statefunctional.h"
template<Physic T_Physic>
StateFunctional<T_Physic>::StateFunctional(const ConfigurationInterface* const config, InnerProductInterface* const innerproduct, EquationInterface<T_Physic>* const equation, ObjectiveInterface<T_Physic>* const objective): _innerproduct(innerproduct), _equation(equation), _objective(objective), _mu(config,&_su,_innerproduct), _su(&_wu,_equation), _wu(config,&_du,_equation), _du(config,&_wu,_objective)
{
if(_innerproduct!=nullptr){_innerproduct->link(&_mu,&_su);}
if(_objective!=nullptr){_objective->link(&_mu,&_du);}
}
template<Physic T_Physic>
StateFunctional<T_Physic>::~StateFunctional()
{
if(_innerproduct!=nullptr){_innerproduct->unlink();}
if(_objective!=nullptr){_objective->unlink();}
}
template<Physic T_Physic>
void StateFunctional<T_Physic>::write_model(Type type, std::string name)
{
std::array<bool,4> NeedToBeUpToDate = {false,false,false,false};
NeedToBeUpToDate[type] = true;
_mu.get(NeedToBeUpToDate).write(type,name);
}
template<Physic T_Physic>
void StateFunctional<T_Physic>::write_data(Type type, std::string name)
{
std::array<bool,4> DataNeedToBeUpToDate = {false,false,false,false};
DataNeedToBeUpToDate[type] = true;
std::array<bool,4> ModelNeedToBeUpToDate = {false,false,false,false};
switch (type)
{
case Type::PF: case Type::PA:
ModelNeedToBeUpToDate[Type::PF] = true;
//no break;
case Type::F: case Type::A:
ModelNeedToBeUpToDate[Type::F] = true;
}
_du.get(DataNeedToBeUpToDate,_mu.get(ModelNeedToBeUpToDate)).write(type,name);
}
template<Physic T_Physic>
void StateFunctional<T_Physic>::write_wave(Type type, std::string name)
{
std::array<bool,4> WaveNeedToBeUpToDate = {false,false,false,false};
WaveNeedToBeUpToDate[type] = true;
std::array<bool,4> ModelNeedToBeUpToDate = {false,false,false,false};
switch (type)
{
case Type::PF: case Type::PA:
ModelNeedToBeUpToDate[Type::PF] = true;
//no break;
case Type::F: case Type::A:
ModelNeedToBeUpToDate[Type::F] = true;
}
_wu.get(WaveNeedToBeUpToDate,_mu.get(ModelNeedToBeUpToDate)).write(type,name);
}
template<Physic T_Physic>
void StateFunctional<T_Physic>::innerproductIsObsolete()
{
std::array<bool,4> NoMoreUpToDate = {false, false, true, true};
_mu.isObsolete(NoMoreUpToDate);
}
template<Physic T_Physic>
void StateFunctional<T_Physic>::modelIsObsolete()
{
std::array<bool,4> NoMoreUpToDate = {true, true, true, true};
_wu.isObsolete(NoMoreUpToDate);
_du.isObsolete(NoMoreUpToDate);
NoMoreUpToDate[Type::PF] = false;
_mu.isObsolete(NoMoreUpToDate);
std::array<bool,3> NoMoreUpToDateSensitivity = {true, true, true};
_su.isObsolete(NoMoreUpToDateSensitivity);
if(_innerproduct != nullptr){_innerproduct->modelIsObsolete();}
if(_equation != nullptr){_equation->modelIsObsolete();}
if(_objective != nullptr){_objective->modelIsObsolete();}
}
template<Physic T_Physic>
void StateFunctional<T_Physic>::modelPerturbationIsObsolete()
{
std::array<bool,4> NoMoreUpToDate = {false, true, false, true};
_mu.isObsolete(NoMoreUpToDate);
_wu.isObsolete(NoMoreUpToDate);
_du.isObsolete(NoMoreUpToDate);
std::array<bool,3> NoMoreUpToDateSensitivity = {false, true, false};
_su.isObsolete(NoMoreUpToDateSensitivity);
}
template<Physic T_Physic>
void StateFunctional<T_Physic>::setModel(const ModelField& m)
{
modelIsObsolete();
std::array<bool,4> ToBeUpdated = {true,false,false,false};
_mu.get(ToBeUpdated,&m);
}
template<Physic T_Physic>
void StateFunctional<T_Physic>::setModel(const ModelFunction& m)
{
modelIsObsolete();
std::array<bool,4> ToBeUpdated = {true,false,false,false};
_mu.get(ToBeUpdated,&m);
}
template<Physic T_Physic>
void StateFunctional<T_Physic>::setModelPerturbation(const ModelField& dm)
{
modelPerturbationIsObsolete();
std::array<bool,4> ToBeUpdated = {false,true,false,false};
_mu.get<ModelField,ModelField>(ToBeUpdated,nullptr,&dm);
}
template<Physic T_Physic>
void StateFunctional<T_Physic>::setModelPerturbation(const ModelFunction& dm)
{
modelPerturbationIsObsolete();
std::array<bool,4> ToBeUpdated = {false,true,false,false};
_mu.get<ModelFunction,ModelFunction>(ToBeUpdated,nullptr,&dm);
}
template<Physic T_Physic>
const ModelField& StateFunctional<T_Physic>::m() const
{
return _mu.m().field();
}
template<Physic T_Physic>
const ModelField& StateFunctional<T_Physic>::dm() const
{
return _mu.dm().field();
}
/* performance */
template<Physic T_Physic>
double StateFunctional<T_Physic>::performance()
{
std::array<bool,4> DataToBeUpdated = {true,false,false,false};
std::array<bool,4> ModelToBeUpdated = {true,false,false,false};
return _objective->performance(
_du.get(DataToBeUpdated,_mu.get(ModelToBeUpdated)).state(Type::F)
);
}
/*
* First order
*/
/* gradient */
template<Physic T_Physic>
const ModelField& StateFunctional<T_Physic>::gradient()
{
std::array<bool,4> ToBeUpdated = {false,false,true,false};
return _mu.get(ToBeUpdated).state(Type::A).field();
}
/* directional */
template<Physic T_Physic>
double StateFunctional<T_Physic>::directional(Order order, Support support, const ModelFunction &dm2)
{
std::array<bool,4> ModelToBeUpToDate = {false,false,false,false};
switch (order)
{
case Order::SCD:
ModelToBeUpToDate[Type::PF] = true;
case Order::FST: case Order::DIAG:
ModelToBeUpToDate[Type::F] = true;
}
return std::real(
_equation->directional(
support,
_su.get(order,support,_mu.get(ModelToBeUpToDate)),
dm2
)
);
}
/* directional1 */
template<Physic T_Physic>
double StateFunctional<T_Physic>::directional1(const ModelFunction &dm2)
{
return directional(Order::FST, Support::BLK, dm2) + directional(Order::FST, Support::BND, dm2);
}
template<Physic T_Physic>
double StateFunctional<T_Physic>::directional1(const ModelField &dm2)
{
return std::real( _innerproduct->product(gradient(),dm2) );
}
/*
* Second order
*/
/* hessian */
template<Physic T_Physic>
const ModelField& StateFunctional<T_Physic>::hessian()
{
std::array<bool,4> ToBeUpdated = {false,false,false,true};
return _mu.get(ToBeUpdated).state(Type::PA).field();
}
/* directional2 */
template<Physic T_Physic>
double StateFunctional<T_Physic>::directional2(const ModelFunction &dm2)
{
return directional(Order::SCD, Support::BLK, dm2) + directional(Order::SCD, Support::BND, dm2);
}
template<Physic T_Physic>
double StateFunctional<T_Physic>::directional2(const ModelField &dm2)
{
return std::real( _innerproduct->product(hessian(),dm2) );
}
template class StateFunctional<Physic::acoustic>;
#ifndef H_STATEFUNCTIONAL
#define H_STATEFUNCTIONAL
//GmshFWI Library
#include "functional.h"
#include "model/updater.h"
#include "model/innerproduct/innerproduct.h"
#include "wave/updater.h"
#include "wave/equation/equation.h"
#include "data/updater.h"
#include "data/objective/objective.h"
template<Physic T_Physic>
class StateFunctional: public FunctionalInterface
{
private:
InnerProductInterface* const _innerproduct;
EquationInterface<T_Physic>* const _equation;
ObjectiveInterface<T_Physic>* const _objective;
ModelUpdater _mu;
SensitivityUpdaterFromWave<T_Physic> _su;
WaveUpdater<T_Physic> _wu;
DataUpdater<T_Physic> _du;
void modelIsObsolete();
void modelPerturbationIsObsolete();
public:
StateFunctional(const ConfigurationInterface* const config, InnerProductInterface* const innerproduct, EquationInterface<T_Physic>* const equation, ObjectiveInterface<T_Physic>* const _objective);
~StateFunctional();
void innerproductIsObsolete();
void write_model(Type type, std::string name);
void write_data(Type type, std::string name);
void write_wave(Type type, std::string name);
virtual void setModel(const ModelField& m);
virtual void setModel(const ModelFunction& m);
virtual void setModelPerturbation(const ModelField& dm);
virtual void setModelPerturbation(const ModelFunction& dm);
virtual const ModelField& m() const;
virtual const ModelField& dm() const;
/* performance */
virtual double performance();
/*
* First order
*/
/* gradient */
virtual const ModelField& gradient();
/* directional */
double directional(Order order , Support support, const ModelFunction &dm);
/* directional1 */
virtual double directional1(const ModelFunction &dm);
virtual double directional1(const ModelField &dm);
/*
* Second order
*/
/* hessian */
virtual const ModelField& hessian();
/* directional2 */
virtual double directional2(const ModelFunction &dm2);
virtual double directional2(const ModelField &dm2);
};
#endif // H_STATEFUNCTIONAL
//GmshFWI Library
#include "support.h"
std::string support_to_string(Support support)
{
switch (support)
{
case Support::BLK: return "bulk";
case Support::BND: return "boundary";
default: return "";
}
}
#ifndef H_SUPPORT
#define H_SUPPORT
//Standard Library
#include <string>
enum Support : unsigned int {BLK=0, BND=1};
std::string support_to_string(Support support);
#endif // H_SUPPORT
//FWI Library
#include "type.h"
std::string type_to_string(Type type)
{
switch (type)
{
case Type::F: return "forward";
case Type::A: return "adjoint";
case Type::PF: return "perturbed forward";
case Type::PA: return "perturbed adjoint";
default: return "";
}
}
#ifndef H_TYPE
#define H_TYPE
//Standard Library
#include <string>
/* Forward, Perturbed Forward, Adjoint, Perturbed Adjoint */
enum Type : unsigned int {F=0, PF=1, A=2, PA=3};
std::string type_to_string(Type type);
#endif // H_TYPE
#ifndef H_COMMON_WAVE_CORRELATION
#define H_COMMON_WAVE_CORRELATION
//Standard Library
#include <numeric>
//Gmsh Library
#include "gmsh.h"
//GmshFEM Library
#include "GmshFem.h"
#include "ExecutionTree.h"
#include "FieldInterface.h"
#include "FieldEvaluator.h"
#include "FieldNode.h"
#include "IndiceBucket.h"
#include "MathObject.h"
#include "OmpInterface.h"
#include "ScalarFunction.h"
#include "OperationsInterface.h"
#include "FieldForm0.h"
#include "Function.h"
#include "Domain.h"
#include "CSVio.h"
#include "MathObject.h"
//GmshFWI Library
#include "element.h"
/*
* (Optimized) Correlation function
*/
namespace gmshfem
{
namespace function
{
template<Physic T_Physic>
class BiWaveMultiFieldOperation : public OperationsInterface< std::complex<double>, Degree::Degree0 >
{
public:
typedef std::complex<double> D_Scalar;
constexpr static Degree D_Degree = Degree::Degree0;
BiWaveMultiFieldOperation() :
OperationsInterface< std::complex<double>, Degree::Degree0 >()
{
}
BiWaveMultiFieldOperation(const BiWaveMultiFieldOperation &other) :
OperationsInterface< std::complex<double>, Degree::Degree0 >(other)
{
}
virtual void operator()(const WaveMultiField<T_Physic> *fieldA, const WaveMultiField<T_Physic> *fieldB, std::vector< typename MathObject< std::complex<double>, Degree::Degree0 >::Object > &values, const std::vector< scalar::Precision< std::complex<double> > > &points, const std::vector< scalar::Precision< std::complex<double> > > &gaussPoints, const int elementType, const std::pair< int, int > &entity) const = 0;
};
template< class T_Op, Physic T_Physic >
class BiWaveMultiFieldNode final : public ExecutionTreeWithDegreeAndLeaves< typename T_Op::D_Scalar, T_Op::D_Degree >
{
protected:
T_Op _op;
const WaveMultiField<T_Physic> *_fieldA;
const WaveMultiField<T_Physic> *_fieldB;
public:
BiWaveMultiFieldNode(const WaveMultiField<T_Physic> *fieldA, const WaveMultiField<T_Physic> *fieldB) :
_op(), _fieldA(fieldA), _fieldB(fieldB)
{
}
BiWaveMultiFieldNode(const T_Op &other, const WaveMultiField<T_Physic> *fieldA, const WaveMultiField<T_Physic> *fieldB) :
_op(other), _fieldA(fieldA), _fieldB(fieldB)
{
}
virtual ~BiWaveMultiFieldNode() {}
virtual bool isConstant(const std::pair< int, int > &entity) const override
{
return false;
}
virtual void evaluate(std::vector< typename MathObject< typename T_Op::D_Scalar, T_Op::D_Degree >::Object > &values, const std::vector< scalar::Precision< typename T_Op::D_Scalar > > &points, const std::vector< scalar::Precision< typename T_Op::D_Scalar > > &gaussPoints, const int elementType, const std::pair< int, int > &entity) const override
{
#pragma omp single
{
if(this->_memorize) {
this->_isInMemory = _op.getFromMemory(values, gaussPoints, elementType, entity);
}
}
if(!this->_isInMemory) {
#pragma omp single
values.resize(points.size() / 3);
_op(_fieldA, _fieldB, values, points, gaussPoints, elementType, entity);
#pragma omp barrier
if(this->_memorize) {
#pragma omp single
_op.setInMemory(values, gaussPoints, elementType, entity);
}
}
}
virtual BiWaveMultiFieldNode< T_Op,T_Physic > *copy() const override
{
BiWaveMultiFieldNode< T_Op,T_Physic > *cp = new BiWaveMultiFieldNode< T_Op,T_Physic >(_op, _fieldA, _fieldB);
if(this->_memorize) cp->activateMemorization();
return cp;
}
};
/* Template specialization should not appear here .., à voir avec Antho pour la généralisation ... */
template< Physic T_Physic >
class Correlate final : public BiWaveMultiFieldOperation< T_Physic >
{};
/* acoustic */
template<>
class Correlate<Physic::acoustic> final : public BiWaveMultiFieldOperation<Physic::acoustic>
{
private:
std::vector<unsigned int> _idx;
mutable std::vector< std::pair< int, int > > _keys;
mutable std::vector< std::complex<double> > _dofsValuesA;
mutable std::vector< std::complex<double> > _dofsValuesB;
mutable std::vector< scalar::Precision< std::complex<double> > > _functions;
mutable std::vector< int > _fsIndex;
mutable unsigned int _nbrDofsByElements;
mutable std::vector< double > _gmshJacobians, _gmshDeterminants, _gmshPoints, _gmshGaussPoints;
mutable std::vector< scalar::Precision< std::complex<double> > > _jacobians, _determinants;
mutable term::evaluator::FieldEvaluator< std::complex<double>, field::Form::Form0 > _fieldEvaluator;
public:
Correlate<Physic::acoustic>(const std::vector<unsigned int>& idx): _idx(idx) {}
Correlate<Physic::acoustic>(const Correlate &other) :
BiWaveMultiFieldOperation< Physic::acoustic >(other), _idx(other._idx)
{
}
void operator()(const WaveMultiField<Physic::acoustic> *fieldA, const WaveMultiField<Physic::acoustic> *fieldB, std::vector< typename MathObject< std::complex<double>, Degree::Degree0 >::Object > &values, const std::vector< scalar::Precision< std::complex<double> > > &points, const std::vector< scalar::Precision< std::complex<double> > > &gaussPoints, const int elementType, const std::pair< int, int > &entity) const override
{
{
const unsigned int nbrOfElements = points.size() / gaussPoints.size();
const unsigned int nbrThreads = omp::nbrThreads();
const unsigned int myThreadID = omp::threadID();
#pragma omp single
_nbrDofsByElements = (*fieldA)[0].getFunctionSpace()->getBasisFunctions(false, _functions, _fsIndex, gaussPoints, elementType, entity);
std::vector< scalar::Precision< std::complex<double> > > coordinates;
//omp::setNested(true);
#pragma omp single
((*fieldA)[0].getFunctionSpace())->getKeys(false, _keys, coordinates, elementType, entity);
//omp::setNested(false);
const unsigned int begin = (myThreadID * _keys.size()) / nbrThreads;
const unsigned int end = ((myThreadID + 1) * _keys.size()) / nbrThreads;
const bool needOffset = !(*fieldA)[0].getFunctionSpace()->isConstantByElements();
#pragma omp single
_dofsValuesA.resize(_keys.size());
#pragma omp single
_dofsValuesB.resize(_keys.size());
const unsigned int nbrGaussPoints = gaussPoints.size() / 3;
#pragma omp single
scalar::copy(_gmshGaussPoints, gaussPoints);
if(_fieldEvaluator.needJacobians())
{
#pragma omp single
gmsh::model::mesh::preallocateJacobians(elementType, nbrGaussPoints, true, true, false, _gmshJacobians, _gmshDeterminants, _gmshPoints, entity.second);
gmsh::model::mesh::getJacobians(elementType, _gmshGaussPoints, _gmshJacobians, _gmshDeterminants, _gmshPoints, entity.second, myThreadID, nbrThreads);
#pragma omp barrier
#pragma omp single
scalar::move(_jacobians, _gmshJacobians);
#pragma omp single
scalar::move(_determinants, _gmshDeterminants);
}
for(auto it = _idx.begin(); it != _idx.end(); it++)
{
(*fieldA)[*it].getValues(_keys, _dofsValuesA, begin, end);
(*fieldB)[*it].getValues(_keys, _dofsValuesB, begin, end);
#pragma omp barrier
#pragma omp for
for(unsigned int i = 0; i < nbrOfElements; ++i)
{
Eigen::VectorX< std::complex<double> > vecDofA = Eigen::Map< const Eigen::VectorX< std::complex<double> > >(&(_dofsValuesA[i * _nbrDofsByElements]), _nbrDofsByElements);
Eigen::VectorX< std::complex<double> > vecDofB = Eigen::Map< const Eigen::VectorX< std::complex<double> > >(&(_dofsValuesB[i * _nbrDofsByElements]), _nbrDofsByElements);
for(unsigned int j = 0; j < nbrGaussPoints; ++j)
{
Eigen::MatrixX< scalar::Precision< std::complex<double>>> valueBasis = _fieldEvaluator(&_functions[((needOffset ? _fsIndex[i] * nbrGaussPoints : 0) + j) * field::NumberOfComponentsOfForm< field::Form::Form0 >::value * _nbrDofsByElements], &_jacobians[i * 9 * nbrGaussPoints + j * 9], &_determinants[i * nbrGaussPoints + j], _nbrDofsByElements);
values[i * nbrGaussPoints + j] += (valueBasis * vecDofA)(0) * (valueBasis * vecDofB)(0);
}
}
}
}
}
};
} // namespace function
} // namespace gmshfem
template<Physic T_Physic>
ModelFunction correlate(const WaveMultiField<T_Physic>& u, const WaveMultiField<T_Physic>& v, const std::vector<unsigned int>& index)
{
return gmshfem::function::Function< std::complex<double>, gmshfem::Degree::Degree0 >( new gmshfem::function::BiWaveMultiFieldNode< gmshfem::function::Correlate< T_Physic >,T_Physic >( gmshfem::function::Correlate< T_Physic >(index), &u, &v) );
};
template<Physic T_Physic>
ModelFunction correlate(const WaveMultiField<T_Physic>& u, const WaveMultiField<T_Physic>& v)
{
std::vector<unsigned int> idx(u.size());
std::iota(idx.begin(), idx.end(), 0);
return correlate(u,v,idx);
};
/*
* (Optimized) Autocorrelate function
*/
namespace gmshfem
{
namespace function
{
template<Physic T_Physic>
class WaveMultiFieldOperation : public OperationsInterface< std::complex<double>, Degree::Degree0 >
{
public:
typedef std::complex<double> D_Scalar;
constexpr static Degree D_Degree = Degree::Degree0;
WaveMultiFieldOperation() :
OperationsInterface< std::complex<double>, Degree::Degree0 >()
{
}
WaveMultiFieldOperation(const WaveMultiFieldOperation &other) :
OperationsInterface< std::complex<double>, Degree::Degree0 >(other)
{
}
virtual void operator()(const WaveMultiField<T_Physic>* field, std::vector< typename MathObject< std::complex<double>, Degree::Degree0 >::Object > &values, const std::vector< scalar::Precision< std::complex<double> > > &points, const std::vector< scalar::Precision< std::complex<double> > > &gaussPoints, const int elementType, const std::pair< int, int > &entity) const = 0;
};
template< class T_Op, Physic T_Physic >
class WaveMultiFieldNode final : public ExecutionTreeWithDegreeAndLeaves< typename T_Op::D_Scalar, T_Op::D_Degree >
{
protected:
T_Op _op;
const WaveMultiField<T_Physic> *_field;
public:
WaveMultiFieldNode(const WaveMultiField<T_Physic>* field) :
_op(), _field(field)
{
}
WaveMultiFieldNode(const T_Op &other, const WaveMultiField<T_Physic>* field) :
_op(other), _field(field)
{
}
virtual ~WaveMultiFieldNode() {}
virtual bool isConstant(const std::pair< int, int > &entity) const override
{
return false;
}
virtual void evaluate(std::vector< typename MathObject< typename T_Op::D_Scalar, T_Op::D_Degree >::Object > &values, const std::vector< scalar::Precision< typename T_Op::D_Scalar > > &points, const std::vector< scalar::Precision< typename T_Op::D_Scalar > > &gaussPoints, const int elementType, const std::pair< int, int > &entity) const override
{
#pragma omp single
{
if(this->_memorize) {
this->_isInMemory = _op.getFromMemory(values, gaussPoints, elementType, entity);
}
}
if(!this->_isInMemory) {
#pragma omp single
values.resize(points.size() / 3);
_op(_field, values, points, gaussPoints, elementType, entity);
#pragma omp barrier
if(this->_memorize) {
#pragma omp single
_op.setInMemory(values, gaussPoints, elementType, entity);
}
}
}
virtual WaveMultiFieldNode< T_Op,T_Physic > *copy() const override
{
WaveMultiFieldNode< T_Op,T_Physic > *cp = new WaveMultiFieldNode< T_Op,T_Physic >(_op, _field);
if(this->_memorize) cp->activateMemorization();
return cp;
}
};
/* Template specialization should not appear here .., à voir avec Antho pour la généralisation ... */
template< Physic T_Physic >
class Autocorrelate final : public WaveMultiFieldOperation< T_Physic >
{};
/* acoustic */
template<>
class Autocorrelate<Physic::acoustic> final : public WaveMultiFieldOperation<Physic::acoustic>
{
private:
std::vector<unsigned int> _idx;
mutable std::vector< std::pair< int, int > > _keys;
mutable std::vector< std::complex<double> > _dofsValues;
mutable std::vector< scalar::Precision< std::complex<double> > > _functions;
mutable std::vector< int > _fsIndex;
mutable unsigned int _nbrDofsByElements;
mutable std::vector< double > _gmshJacobians, _gmshDeterminants, _gmshPoints, _gmshGaussPoints;
mutable std::vector< scalar::Precision< std::complex<double> > > _jacobians, _determinants;
mutable term::evaluator::FieldEvaluator< std::complex<double>, field::Form::Form0 > _fieldEvaluator;
public:
Autocorrelate<Physic::acoustic>(const std::vector<unsigned int>& idx): _idx(idx)
{
}
Autocorrelate<Physic::acoustic>(const Autocorrelate &other) :
WaveMultiFieldOperation< Physic::acoustic >(other), _idx(other._idx)
{
}
void operator()(const WaveMultiField<Physic::acoustic>* field, std::vector< typename MathObject< std::complex<double>, Degree::Degree0 >::Object > &values, const std::vector< scalar::Precision< std::complex<double> > > &points, const std::vector< scalar::Precision< std::complex<double> > > &gaussPoints, const int elementType, const std::pair< int, int > &entity) const override
{
{
const unsigned int nbrOfElements = points.size() / gaussPoints.size();
const unsigned int nbrThreads = omp::nbrThreads();
const unsigned int myThreadID = omp::threadID();
#pragma omp single
_nbrDofsByElements = (*field)[0].getFunctionSpace()->getBasisFunctions(false, _functions, _fsIndex, gaussPoints, elementType, entity);
std::vector< scalar::Precision< std::complex<double> > > coordinates;
//omp::setNested(true);
#pragma omp single
(*field)[0].getFunctionSpace()->getKeys(false, _keys, coordinates, elementType, entity);
//omp::setNested(false);
const unsigned int begin = (myThreadID * _keys.size()) / nbrThreads;
const unsigned int end = ((myThreadID + 1) * _keys.size()) / nbrThreads;
const bool needOffset = !(*field)[0].getFunctionSpace()->isConstantByElements();
#pragma omp single
_dofsValues.resize(_keys.size());
const unsigned int nbrGaussPoints = gaussPoints.size() / 3;
#pragma omp single
scalar::copy(_gmshGaussPoints, gaussPoints);
if(_fieldEvaluator.needJacobians())
{
#pragma omp single
gmsh::model::mesh::preallocateJacobians(elementType, nbrGaussPoints, true, true, false, _gmshJacobians, _gmshDeterminants, _gmshPoints, entity.second);
gmsh::model::mesh::getJacobians(elementType, _gmshGaussPoints, _gmshJacobians, _gmshDeterminants, _gmshPoints, entity.second, myThreadID, nbrThreads);
#pragma omp barrier
#pragma omp single
scalar::move(_jacobians, _gmshJacobians);
#pragma omp single
scalar::move(_determinants, _gmshDeterminants);
}
for(auto it = _idx.begin(); it != _idx.end(); it++)
{
(*field)[*it].getValues(_keys, _dofsValues, begin, end);
#pragma omp barrier
#pragma omp for
for(unsigned int i = 0; i < nbrOfElements; ++i)
{
Eigen::VectorX< std::complex<double> > vecDof = Eigen::Map< const Eigen::VectorX< std::complex<double> > >(&(_dofsValues[i * _nbrDofsByElements]), _nbrDofsByElements);
for(unsigned int j = 0; j < nbrGaussPoints; ++j)
{
Eigen::MatrixX< scalar::Precision< std::complex<double> > > valueBasis = _fieldEvaluator(&_functions[((needOffset ? _fsIndex[i] * nbrGaussPoints : 0) + j) * field::NumberOfComponentsOfForm< field::Form::Form0 >::value * _nbrDofsByElements], &_jacobians[i * 9 * nbrGaussPoints + j * 9], &_determinants[i * nbrGaussPoints + j], _nbrDofsByElements);
values[i * nbrGaussPoints + j] += (valueBasis * vecDof)(0) * std::conj((valueBasis * vecDof)(0));
}
}
}
}
}
};
} // namespace function
} // namespace gmshfem
template<Physic T_Physic>
ModelFunction autocorrelate(const WaveMultiField<T_Physic>& u, const std::vector<unsigned int>& index)
{
return gmshfem::function::Function< std::complex<double>, gmshfem::Degree::Degree0 >( new gmshfem::function::WaveMultiFieldNode< gmshfem::function::Autocorrelate< T_Physic >,T_Physic >( gmshfem::function::Autocorrelate< T_Physic >(index), &u) );
};
template<Physic T_Physic>
ModelFunction autocorrelate(const WaveMultiField<T_Physic>& u)
{
std::vector<unsigned int> idx(u.size());
std::iota(idx.begin(), idx.end(), 0);
return autocorrelate(u,idx);
};
#endif // H_COMMON_WAVE_CORRELATION
#ifndef H_COMMON_WAVE_ELEMENT
#define H_COMMON_WAVE_ELEMENT
//GmshFWI Library
#include "../../specific/physic.h"
#include "../../specific/wave/element.h"
#include "../configuration.h"
/*
* WaveMultiField
*/
template<Physic T_Physic>
class WaveMultiField final : public std::vector<WaveField<T_Physic>>
{
public:
WaveMultiField(unsigned int n,const WaveField<T_Physic>& other) : std::vector<WaveField<T_Physic>>(n,other) {};
void write(std::string name) const
{
unsigned int s = 0;
for (auto it = this->begin(); it != this->end(); it++)
{
it->write(name+"s"+std::to_string(s++));
}
};
};
#endif // H_COMMON_WAVE_ELEMENT
//GmshFem Library
#include "FieldRoutines.h"
//FWI Library
#include "equation.h"
using namespace gmshfem;
using namespace gmshfem::common;
using namespace gmshfem::post;
static const std::complex< double > im = std::complex< double >(0., 1.);
/*
* DifferentialEquationInterface
*/
template<Physic T_Physic>
DifferentialEquationInterface<T_Physic>::DifferentialEquationInterface(const ConfigurationInterface* const config, const wave::Discretization<T_Physic>& w_discret,const GmshFem& gmshFem)
: EquationInterface<T_Physic>(config, w_discret), _v("_v",_config->wave_evaldomain(),_config->wave_gmodel(),_w_discret),_g(_config->np(),_v),_geAreUpToDate(false),_grAreUpToDate(false), _formulation("wave_formulation"),_systemIsUpToDate(false),_systemIsFactorized(false)
{
if(!gmshFem.userDefinedParameter(_integrationType, "wave_IntegrationType"))
{
throw common::Exception("Wave integration type could not be found.");
}
unsigned int useGreen_buffer = 1;
gmshFem.userDefinedParameter(useGreen_buffer,"useGreen");
_useGreen = ((bool) useGreen_buffer);
}
template<Physic T_Physic>
std::complex<double> DifferentialEquationInterface<T_Physic>::directional(Support support, const ModelFunction& sensitivity, const ModelFunction& dm2)
{
return integrate( sensitivity * dm2, _config->model_unknown(support), integrationType(3*_w_discret.functionSpaceDegree()) );
}
template<Physic T_Physic>
const WaveField<T_Physic>& DifferentialEquationInterface<T_Physic>::update_wave(Type type, unsigned int s, const DataStateEvaluator<T_Physic>& d, const ModelStateEvaluator& m, const WaveStateEvaluator<T_Physic>& w)
{
if(_useGreen){return updateWithGreen(type,s,d,m,w);}
else {return updateWithSystem(type,s,d,m,w);}
}
template<Physic T_Physic>
const WaveField<T_Physic>& DifferentialEquationInterface<T_Physic>::updateWithSystem(Type type, unsigned int s, const DataStateEvaluator<T_Physic>& d, const ModelStateEvaluator& m, const WaveStateEvaluator<T_Physic>& w)
{
if(!_systemIsUpToDate)
{
_formulation.removeSystem();
_formulation.initSystem();
_systemIsFactorized=false;
setLHS(m);
_formulation.pre();
_formulation.assemble();
_systemIsUpToDate=true;
_formulation.removeTerms();
}
setRHS(type,s,d,m,w);
_formulation.assemble();
_formulation.removeTerms();
_formulation.solve(_systemIsFactorized);
_systemIsFactorized=true;
_formulation.setRHSToZero();
return _v;
}
template<Physic T_Physic>
const WaveField<T_Physic>& DifferentialEquationInterface<T_Physic>::updateWithGreen(Type type, unsigned int s, const DataStateEvaluator<T_Physic>& d, const ModelStateEvaluator& m, const WaveStateEvaluator<T_Physic>& w)
{
switch (type)
{
case Type::F:
if(!_geAreUpToDate){updateGreenEmitter(m);}
_v.setValuesToZero();
for (unsigned int e = 0; e < _config->ne(s); e++)
{
multiplyAddAssignement(1.+0.*im,_v,1.+0.*im,_g[_config->emitter_idx(s)[e]]);
}
return _v;
case Type::A:
if(!_grAreUpToDate){updateGreenReceiver(m);}
_v.setValuesToZero();
for (unsigned int r = 0; r < _config->nr(s); r++)
{
multiplyAddAssignement(1.+0.*im,_v,std::complex<double>(d.state(Type::A).value(s,r)),_g[_config->receiver_idx(s)[r]]);
}
return _v;
case Type::PF: case Type::PA: default:
return updateWithSystem(type,s,d,m,w);
}
}
template<Physic T_Physic>
void DifferentialEquationInterface<T_Physic>::updateGreen(const ModelStateEvaluator& m, const std::vector<unsigned int>& p_idx)
{
if(!_systemIsUpToDate)
{
_formulation.removeSystem();
_formulation.initSystem();
_systemIsFactorized=false;
setLHS(m);
_formulation.pre();
_formulation.assemble();
_systemIsUpToDate=true;
_formulation.removeTerms();
}
for (auto it = p_idx.begin(); it != p_idx.end(); it++)
{
setGreenRHS(*it);
_formulation.assemble();
_formulation.removeTerms();
_formulation.solve(_systemIsFactorized);
_systemIsFactorized=true;
_formulation.setRHSToZero();
_g[*it] = _v;
}
}
template<Physic T_Physic>
void DifferentialEquationInterface<T_Physic>::updateGreenEmitter(const ModelStateEvaluator& m)
{
updateGreen(m,_config->emitter_idx(!_grAreUpToDate));
_geAreUpToDate=true;
}
template<Physic T_Physic>
void DifferentialEquationInterface<T_Physic>::updateGreenReceiver(const ModelStateEvaluator& m)
{
updateGreen(m,_config->receiver_idx(!_geAreUpToDate));
_grAreUpToDate=true;
}
template class DifferentialEquationInterface<Physic::acoustic>;
#ifndef H_COMMON_EQUATION
#define H_COMMON_EQUATION
//GmshFem Library
#include "Formulation.h"
//FWI Library
#include "../state.h"
#include "../../sensitivity/state.h"
#include "../../data/state.h"
#include "../../model/state.h"
#include "../../configuration.h"
#include "../../../specific/wave/discretization.h"
/*
* EquationInterface
*/
template<Physic T_Physic>
class EquationInterface
{
protected:
const ConfigurationInterface* const _config;
const wave::Discretization<T_Physic> _w_discret;
public:
EquationInterface(const ConfigurationInterface* const config, const wave::Discretization<T_Physic>& w_discret): _config(config), _w_discret(w_discret) {};
virtual ~EquationInterface() = default;
//Wave related
virtual const WaveField<T_Physic>& update_wave(Type type, unsigned int s, const DataStateEvaluator<T_Physic>& ds, const ModelStateEvaluator& ms, const WaveStateEvaluator<T_Physic>& ws) = 0;
//Model related
virtual ModelFunction update_sensitivity(Order order, Support support, const ModelStateEvaluator& ms, const WaveStateEvaluator<T_Physic>& ws) = 0;
virtual std::complex<double> directional(Support support, const ModelFunction& sensitivity, const ModelFunction& dm2) = 0;
//directional could be computed from WaveUpdater instead, sensitivity is not really needed!
virtual void modelIsObsolete() = 0;
};
/*
* DifferentialEquationInterface
*/
template <Physic T_Physic>
class DifferentialEquationInterface: public EquationInterface<T_Physic>
{
protected:
using EquationInterface<T_Physic>::_config;
using EquationInterface<T_Physic>::_w_discret;
WaveField<T_Physic> _v;
bool _useGreen;
WaveMultiField<T_Physic> _g;
bool _geAreUpToDate;
bool _grAreUpToDate;
gmshfem::problem::Formulation< std::complex< double > > _formulation;
std::string _integrationType;
bool _systemIsUpToDate;
bool _systemIsFactorized;
public:
DifferentialEquationInterface(const ConfigurationInterface* const config, const wave::Discretization<T_Physic>& w_discret,const gmshfem::common::GmshFem& gmshFem);
//Wave related
virtual const WaveField<T_Physic>& update_wave(Type type, unsigned int s, const DataStateEvaluator<T_Physic>& d, const ModelStateEvaluator& m, const WaveStateEvaluator<T_Physic>& w);
std::string integrationType(unsigned int degree) const {return _integrationType + std::to_string(degree);};
virtual std::complex<double> directional(Support support, const ModelFunction& sensitivity, const ModelFunction& dm2);
protected:
const WaveField<T_Physic>& updateWithSystem(Type type, unsigned int s, const DataStateEvaluator<T_Physic>& ds, const ModelStateEvaluator& ms, const WaveStateEvaluator<T_Physic>& ws);
const WaveField<T_Physic>& updateWithGreen(Type type, unsigned int s, const DataStateEvaluator<T_Physic>& ds, const ModelStateEvaluator& ms, const WaveStateEvaluator<T_Physic>& ws);
virtual void setLHS(const ModelStateEvaluator& m) = 0;
virtual void setRHS(Type type,unsigned int s, const DataStateEvaluator<T_Physic>& ds, const ModelStateEvaluator& ms, const WaveStateEvaluator<T_Physic>& ws) = 0;
void updateGreen(const ModelStateEvaluator& ms,const std::vector<unsigned int>& p_idx);
void updateGreenEmitter(const ModelStateEvaluator& ms);
void updateGreenReceiver(const ModelStateEvaluator& ms);
virtual void setGreenRHS(unsigned int p) = 0;
};
/*
* green_preconditioner
*/
template<Physic T_Physic>
ModelFunction green_preconditioner(const WaveMultiField<T_Physic>& g, const ConfigurationInterface* const _config);
#endif //H_COMMON_EQUATION
//Standard library
//GmshFem library
#include "Exception.h"
//GmshFWI Library
#include "preconditioner.h"
using namespace gmshfem;
using namespace gmshfem::common;
/*
* PreconditionerState
*/
const ModelFunction& ModelPreconditionerState::state() const
{
if(!_isUpToDate)
{
throw Exception("Model preconditioner is not up to date while required.");
}
return _state;
}
/*
* ModelPreconditionerUpdater
*/
void ModelPreconditionerUpdater::update(const ModelStateEvaluator& ms)
{
if(_ps._isUpToDate){return;}
_ps._state = update_preconditioner(ms);
_ps._isUpToDate = true;
}
const ModelFunction& ModelPreconditionerUpdater::get_preconditioner(const ModelStateEvaluator& ms)
{
update(ms);
return _ps.state();
}
void ModelPreconditionerUpdater::isObsolete(bool NoMoreUpToDate)
{
_ps._isUpToDate = !NoMoreUpToDate;
}
#ifndef H_COMMON_WAVE_PRECONDITIONER
#define H_COMMON_WAVE_PRECONDITIONER
//FWI Library
#include "../model/state.h"
/*
* ModelPreconditionerState
*/
class ModelPreconditionerState
{
private:
ModelFunction _state;
bool _isUpToDate;
public:
const ModelFunction& state() const;
friend class ModelPreconditionerUpdater;
};
/*
* ModelPreconditionerUpdater
*/
class ModelPreconditionerUpdater
{
private:
ModelPreconditionerState _ps;
void update(const ModelStateEvaluator& ms);
virtual ModelFunction update_preconditioner(const ModelStateEvaluator& ms) = 0;
public:
const ModelFunction& get_preconditioner(const ModelStateEvaluator& ms);
void isObsolete(bool NoMoreUpToDate);
virtual bool isModelDependent() {return true;};
};
#endif // H_COMMON_WAVE_PRECONDITIONER
//GmeshFem Library
#include "Exception.h"
//FWI Library
#include "state.h"
using namespace gmshfem::common;
/*
* Class WaveState
*/
template<Physic T_Physic>
const WaveMultiField<T_Physic>& WaveState<T_Physic>::state(Type type) const
{
if(_isUpToDate[((unsigned int) type)]){return _state[((unsigned int) type)];}
else
{
throw Exception(type_to_string(type) + " wave is not up to date while required.");
}
}
template class WaveState<Physic::acoustic>;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment