10 #if !defined(KRATOS_FEAST_EIGENSYSTEM_SOLVER_H_INCLUDED)
11 #define KRATOS_FEAST_EIGENSYSTEM_SOLVER_H_INCLUDED
24 #include <feast_sparse.h>
30 template<
typename TScalar>
33 SettingsHelper(Parameters SolverParams) : mParam(SolverParams) {};
35 Parameters GetDefaultParameters();
36 void CheckParameters();
44 Parameters SettingsHelper<double>::GetDefaultParameters()
46 return Parameters(R
"({
53 Parameters SettingsHelper<std::complex<double>>::GetDefaultParameters()
55 return Parameters(R
"({
63 void SettingsHelper<double>::CheckParameters()
65 KRATOS_ERROR_IF( mParam[
"search_lowest_eigenvalues"].GetBool() && mParam[
"search_highest_eigenvalues"].GetBool() ) <<
66 "Cannot search for highest and lowest eigenvalues at the same time" << std::endl;
68 KRATOS_ERROR_IF( mParam[
"e_max"].GetDouble() <= mParam[
"e_min"].GetDouble() ) <<
69 "Invalid eigenvalue limits provided" << std::endl;
73 void SettingsHelper<std::complex<double>>::CheckParameters()
76 "Invalid search radius provided" << std::endl;
78 KRATOS_ERROR_IF( mParam[
"search_lowest_eigenvalues"].GetBool() || mParam[
"search_highest_eigenvalues"].GetBool() ) <<
79 "Search for extremal eigenvalues is only available for real symmetric problems" << std::endl;
82 template<>
double SettingsHelper<double>::GetE1() {
return mParam[
"e_min"].
GetDouble();}
83 template<> std::complex<double> SettingsHelper<std::complex<double>>::GetE1() {
return std::complex<double>(mParam[
"e_mid_re"].GetDouble(), mParam[
"e_mid_im"].GetDouble());}
85 template<>
double SettingsHelper<double>::GetE2() {
return mParam[
"e_max"].
GetDouble();}
86 template<>
double SettingsHelper<std::complex<double>>::GetE2() {
return mParam[
"e_r"].
GetDouble();}
88 template<
typename TScalar>
91 SortingHelper(std::string Order) : mOrder(Order) {};
93 template<
typename MatrixType,
typename VectorType>
99 template<>
template<
typename MatrixType,
typename VectorType>
100 void SortingHelper<double>::SortEigenvalues(
VectorType &rEigenvalues,
MatrixType &rEigenvectors)
102 KRATOS_WARNING_IF(
"FeastEigensystemSolver", mOrder ==
"si") <<
"Attempting to sort by imaginary value. Falling back on \"sr\"" << std::endl;
103 KRATOS_WARNING_IF(
"FeastEigensystemSolver", mOrder ==
"li") <<
"Attempting to sort by imaginary value. Falling back on \"lr\"" << std::endl;
105 std::vector<std::size_t> idx(rEigenvalues.size());
106 std::iota(idx.begin(), idx.end(), 0);
108 if( mOrder ==
"sr" || mOrder ==
"si" ) {
109 std::stable_sort(idx.begin(), idx.end(),
110 [&rEigenvalues](std::size_t i1, std::size_t i2) {return rEigenvalues[i1] < rEigenvalues[i2];});
111 }
else if( mOrder ==
"sm") {
112 std::stable_sort(idx.begin(), idx.end(),
113 [&rEigenvalues](std::size_t i1, std::size_t i2) {return std::abs(rEigenvalues[i1]) < std::abs(rEigenvalues[i2]);});
114 }
else if( mOrder ==
"lr" || mOrder ==
"li" ) {
115 std::stable_sort(idx.begin(), idx.end(),
116 [&rEigenvalues](std::size_t i1, std::size_t i2) {return rEigenvalues[i1] > rEigenvalues[i2];});
117 }
else if( mOrder ==
"lm") {
118 std::stable_sort(idx.begin(), idx.end(),
119 [&rEigenvalues](std::size_t i1, std::size_t i2) {return std::abs(rEigenvalues[i1]) > std::abs(rEigenvalues[i2]);});
121 KRATOS_ERROR <<
"Invalid sort type. Allowed are sr, sm, si, lr, lm, li" << std::endl;
124 VectorType tmp_eigenvalues(rEigenvalues.size());
125 MatrixType tmp_eigenvectors(rEigenvectors.size1(), rEigenvectors.size2());
127 for( std::size_t
i=0;
i<rEigenvalues.size(); ++
i ) {
128 tmp_eigenvalues[
i] = rEigenvalues[idx[
i]];
131 rEigenvalues.swap(tmp_eigenvalues);
132 rEigenvectors.swap(tmp_eigenvectors);
135 template<>
template<
typename MatrixType,
typename VectorType>
136 void SortingHelper<std::complex<double>>::SortEigenvalues(
VectorType &rEigenvalues,
MatrixType &rEigenvectors)
138 std::vector<std::size_t> idx(rEigenvalues.size());
139 std::iota(idx.begin(), idx.end(), 0);
141 if( mOrder ==
"sr" ) {
142 std::stable_sort(idx.begin(), idx.end(),
143 [&rEigenvalues](std::size_t i1, std::size_t i2) {return std::real(rEigenvalues[i1]) < std::real(rEigenvalues[i2]);});
144 }
else if( mOrder ==
"sm") {
145 std::stable_sort(idx.begin(), idx.end(),
146 [&rEigenvalues](std::size_t i1, std::size_t i2) {return std::abs(rEigenvalues[i1]) < std::abs(rEigenvalues[i2]);});
147 }
else if( mOrder ==
"si") {
148 std::stable_sort(idx.begin(), idx.end(),
149 [&rEigenvalues](std::size_t i1, std::size_t i2) {return std::imag(rEigenvalues[i1]) < std::imag(rEigenvalues[i2]);});
150 }
else if( mOrder ==
"lr" ) {
151 std::stable_sort(idx.begin(), idx.end(),
152 [&rEigenvalues](std::size_t i1, std::size_t i2) {return std::real(rEigenvalues[i1]) > std::real(rEigenvalues[i2]);});
153 }
else if( mOrder ==
"lm") {
154 std::stable_sort(idx.begin(), idx.end(),
155 [&rEigenvalues](std::size_t i1, std::size_t i2) {return std::abs(rEigenvalues[i1]) > std::abs(rEigenvalues[i2]);});
156 }
else if( mOrder ==
"li") {
157 std::stable_sort(idx.begin(), idx.end(),
158 [&rEigenvalues](std::size_t i1, std::size_t i2) {return std::imag(rEigenvalues[i1]) > std::imag(rEigenvalues[i2]);});
160 KRATOS_ERROR <<
"Invalid sort type. Allowed are sr, sm, si, lr, lm, li" << std::endl;
163 VectorType tmp_eigenvalues(rEigenvalues.size());
164 MatrixType tmp_eigenvectors(rEigenvectors.size1(), rEigenvectors.size2());
166 for( std::size_t
i=0;
i<rEigenvalues.size(); ++
i ) {
167 tmp_eigenvalues[
i] = rEigenvalues[idx[
i]];
170 rEigenvalues.swap(tmp_eigenvalues);
171 rEigenvectors.swap(tmp_eigenvectors);
179 class TSparseSpaceTypeIn = TUblasSparseSpace<TScalarIn>,
180 class TDenseSpaceTypeIn = TUblasDenseSpace<TScalarIn>,
181 class TSparseSpaceTypeOut = TUblasSparseSpace<TScalarOut>,
182 class TDenseSpaceTypeOut = TUblasDenseSpace<TScalarOut>>
184 :
public LinearSolver<TSparseSpaceTypeIn, TDenseSpaceTypeOut>
211 "solver_type" : "feast",
213 "number_of_eigenvalues" : 0,
214 "search_lowest_eigenvalues" : false,
215 "search_highest_eigenvalues" : false,
216 "sort_eigenvalues" : false,
219 "max_iteration" : 20,
226 mParam.ValidateAndAssignDefaults(default_params);
229 "Invalid number of eigenvalues provided" << std::endl;
232 "Invalid subspace size provided" << std::endl;
235 "Invalid maximal number of iterations provided" << std::endl;
237 KRATOS_ERROR_IF( (mParam[
"search_lowest_eigenvalues"].GetBool() || mParam[
"search_highest_eigenvalues"].GetBool())
238 && mParam[
"number_of_eigenvalues"].GetInt() == 0 ) <<
"Please specify the number of eigenvalues to be found" << std::endl;
240 KRATOS_ERROR_IF( mParam[
"subspace_size"].GetInt() == 0 && mParam[
"number_of_eigenvalues"].GetInt() == 0 ) <<
241 "Please specify either \"subspace_size\" or \"number_of_eigenvalues\"" << std::endl;
244 mParam[
"number_of_eigenvalues"].GetInt() > 0 && mParam[
"subspace_size"].GetInt() > 0 ) <<
245 "Manually defined subspace size will be overwritten to match the defined number of eigenvalues" << std::endl;
247 const std::string s = mParam[
"sort_order"].GetString();
248 KRATOS_ERROR_IF( !(s==
"sr" || s==
"sm" || s==
"si" || s==
"lr" || s==
"lm" || s==
"li") ) <<
249 "Invalid sort type. Allowed are sr, sm, si, lr, lm, li" << std::endl;
251 SettingsHelper<TScalarOut>(mParam).CheckParameters();
270 const std::size_t system_size = rK.size1();
271 std::size_t subspace_size;
273 if( mParam[
"search_lowest_eigenvalues"].GetBool() || mParam[
"search_highest_eigenvalues"].GetBool() ) {
274 subspace_size = 2 *
static_cast<std::size_t
>(mParam[
"number_of_eigenvalues"].GetInt());
275 }
else if( mParam[
"subspace_size"].GetInt() == 0 ) {
276 subspace_size = 1.5 *
static_cast<std::size_t
>(mParam[
"number_of_eigenvalues"].GetInt());
278 subspace_size =
static_cast<std::size_t
>(mParam[
"subspace_size"].GetInt());
290 mParam[
"echo_level"].GetInt() > 0 ? fpm[0] = 1 : fpm[0] = 0;
292 fpm[2] = -std::log10(mParam[
"tolerance"].GetDouble());
293 fpm[3] = mParam[
"max_iteration"].GetInt();
300 if( mParam[
"search_lowest_eigenvalues"].GetBool() ) {
303 if( mParam[
"search_highest_eigenvalues"].GetBool() ) {
308 int N =
static_cast<int>(system_size);
311 double*
A =
reinterpret_cast<double*
>(rK.value_data().begin());
313 std::vector<int> IA(
N+1);
314 CreateFortranIndices(rK.index1_data(), IA);
316 std::vector<int> JA(IA[
N]-1);
317 CreateFortranIndices(rK.index2_data(), JA);
319 double*
B =
reinterpret_cast<double*
>(rM.value_data().begin());
321 std::vector<int> IB(
N+1);
322 CreateFortranIndices(rM.index1_data(), IB);
324 std::vector<int> JB(IB[
N]-1);
325 CreateFortranIndices(rM.index2_data(), JB);
329 TScalarOut E1 = SettingsHelper<TScalarOut>(mParam).GetE1();
330 double E2 = SettingsHelper<TScalarOut>(mParam).GetE2();
331 double* Emin =
reinterpret_cast<double*
>(&E1);
332 double* Emax =
reinterpret_cast<double*
>(&E2);
333 int M0 =
static_cast<int>(subspace_size);
334 double*
E =
reinterpret_cast<double*
>(tmp_eigenvalues.data().begin());
335 double*
X =
reinterpret_cast<double*
>(tmp_eigenvectors.data().begin());
337 double*
res =
reinterpret_cast<double*
>(
residual.data().begin());
341 auto feast = CreateFeast<TScalarIn>(TSymmetric);
342 feast(&UPLO, &
N,
A, IA.data(), JA.data(),
B, IB.data(), JB.data(), fpm, &epsout, &loop, Emin, Emax, &M0,
E,
X, &M,
res, &info);
344 KRATOS_ERROR_IF(info < 0 || info > 99) <<
"FEAST encounterd error " << info <<
". Please check FEAST output." << std::endl;
345 KRATOS_INFO_IF(
"FeastEigensystemSolver", info > 1 && info < 6) <<
"FEAST finished with warning " << info <<
". Please check FEAST output." << std::endl;
346 KRATOS_ERROR_IF(info == 1) <<
"FEAST finished with warning " << info <<
", no eigenvalues could be found in the given search interval." << std::endl;
347 KRATOS_ERROR_IF(info == 7) <<
"FEAST finished with warning " << info <<
", no extremal eigenvalues could be found. Please check FEAST output." << std::endl;
350 tmp_eigenvalues.resize(M,
true);
351 tmp_eigenvectors.resize(system_size, M,
true);
354 if( mParam[
"sort_eigenvalues"].GetBool() ) {
355 SortingHelper<TScalarOut>(mParam[
"sort_order"].GetString()).SortEigenvalues(tmp_eigenvalues, tmp_eigenvectors);
359 rEigenvalues.swap(tmp_eigenvalues);
362 if( rEigenvectors.size1() != tmp_eigenvectors.size1() || rEigenvectors.size2() != tmp_eigenvectors.size2() )
363 rEigenvectors.resize(tmp_eigenvectors.size1(), tmp_eigenvectors.size2(),
false);
365 noalias(rEigenvectors) = tmp_eigenvectors;
368 rEigenvectors =
trans(rEigenvectors);
375 rOStream <<
"FEASTEigensystemSolver";
387 typedef void (feast_ptr)(
char*,
int*,
double*,
int*,
int*,
double*,
int*,
int*,
int*,
double*,
int*,
double*,
double*,
int*,
double*,
double*,
int*,
double*,
int*);
402 template<typename TScalar, typename std::enable_if<std::is_same<double, TScalar>::value,
int>
::type = 0>
403 std::function<feast_ptr> CreateFeast(
bool symmetric)
405 using namespace std::placeholders;
408 return std::bind(dfeast_scsrgv, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19);
410 return std::bind(dfeast_gcsrgv, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19);
414 template<
typename TScalar,
typename std::enable_if<std::is_same<std::complex<
double>, TScalar>::value,
int>::type = 0>
415 std::function<feast_ptr> CreateFeast(
bool symmetric)
417 using namespace std::placeholders;
420 return std::bind(zfeast_scsrgv, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19);
422 return std::bind(zfeast_gcsrgv, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19);
426 template<
typename IndexDataType>
427 void CreateFortranIndices(
const IndexDataType& rIndexData, std::vector<int>& rFortranIndices)
429 #pragma omp parallel for
430 for(
int i=0; i<static_cast<int>(rFortranIndices.size()); ++
i ) {
431 rFortranIndices[
i] =
static_cast<int>(rIndexData[
i]) + 1;
441 template<
bool TSymmetric,
typename TScalarIn,
typename TScalarOut>
443 std::istream& rIStream,
452 template<
bool TSymmetric,
typename TScalarIn,
typename TScalarOut>
454 std::ostream& rOStream,
458 rOStream << std::endl;
Definition: feast_eigensystem_solver.h:185
KRATOS_CLASS_POINTER_DEFINITION(FEASTEigensystemSolver)
void PrintData(std::ostream &rOStream) const override
Definition: feast_eigensystem_solver.h:381
FEASTEigensystemSolver(Parameters param)
Definition: feast_eigensystem_solver.h:205
TScalarOut ValueTypeOut
Definition: feast_eigensystem_solver.h:203
TDenseSpaceTypeOut::MatrixType DenseMatrixType
Definition: feast_eigensystem_solver.h:197
TSparseSpaceTypeIn::MatrixType SparseMatrixType
Definition: feast_eigensystem_solver.h:193
void PrintInfo(std::ostream &rOStream) const override
Definition: feast_eigensystem_solver.h:373
TScalarIn ValueTypeIn
Definition: feast_eigensystem_solver.h:201
TDenseSpaceTypeOut::VectorType DenseVectorType
Definition: feast_eigensystem_solver.h:195
LinearSolver< TSparseSpaceTypeIn, TDenseSpaceTypeIn > BaseType
Definition: feast_eigensystem_solver.h:191
matrix< TScalarOut, column_major > FEASTMatrixType
Definition: feast_eigensystem_solver.h:199
void Solve(SparseMatrixType &rK, SparseMatrixType &rM, DenseVectorType &rEigenvalues, DenseMatrixType &rEigenvectors) override
Definition: feast_eigensystem_solver.h:263
~FEASTEigensystemSolver() override=default
Base class for all the linear solvers in Kratos.
Definition: linear_solver.h:65
This class provides to Kratos a data structure for I/O based on the standard of JSON.
Definition: kratos_parameters.h:59
double GetDouble() const
This method returns the double contained in the current Parameter.
Definition: kratos_parameters.cpp:657
void AddMissingParameters(const Parameters &rDefaultParameters)
This function is designed to verify that the parameters under testing contain at least all parameters...
Definition: kratos_parameters.cpp:1369
#define KRATOS_ERROR
Definition: exception.h:161
#define KRATOS_ERROR_IF(conditional)
Definition: exception.h:162
#define KRATOS_INFO_IF(label, conditional)
Definition: logger.h:251
#define KRATOS_WARNING_IF(label, conditional)
Definition: logger.h:266
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
array_1d< double, 3 > VectorType
Definition: solid_mechanics_application_variables.cpp:19
std::istream & operator>>(std::istream &rIStream, LinearMasterSlaveConstraint &rThis)
input stream function
T & noalias(T &TheMatrix)
Definition: amatrix_interface.h:484
AMatrix::TransposeMatrix< const T > trans(const T &TheMatrix)
Definition: amatrix_interface.h:486
AMatrix::MatrixColumn< const TExpressionType > column(AMatrix::MatrixExpression< TExpressionType, TCategory > const &TheExpression, std::size_t ColumnIndex)
Definition: amatrix_interface.h:637
std::ostream & operator<<(std::ostream &rOStream, const LinearMasterSlaveConstraint &rThis)
output stream function
Definition: linear_master_slave_constraint.h:432
res
Definition: generate_convection_diffusion_explicit_element.py:211
type
Definition: generate_gid_list_file.py:35
E
Definition: generate_hyper_elastic_simo_taylor_neo_hookean.py:26
residual
Definition: hinsberg_optimization_4.py:433
A
Definition: sensitivityMatrix.py:70
N
Definition: sensitivityMatrix.py:29
B
Definition: sensitivityMatrix.py:76
integer i
Definition: TensorModule.f:17