20 #include "picard_matrix_solver.h"
31 template<
typename Scalar>
37 template<
typename Scalar>
40 this->min_allowed_damping_coeff = 1E-4;
41 this->manual_damping =
false;
42 this->auto_damping_ratio = 2.0;
43 this->manual_damping_factor = 1.0;
44 this->initial_auto_damping_factor = 1.0;
45 this->sufficient_improvement_factor = 1.05;
46 this->necessary_successful_steps_to_increase = 3;
47 this->damping_factor_condition_overloaded =
true;
49 this->sufficient_improvement_factor_jacobian = 1e-1;
50 this->max_steps_with_reused_jacobian = 0;
52 this->set_tolerance(1e-3, SolutionChangeRelative);
54 this->num_last_vectors_used = 3;
55 this->anderson_beta = 1.0;
56 this->anderson_is_on =
false;
57 this->vec_in_memory = 0;
59 this->use_initial_guess_for_iterative_solvers =
true;
62 template<
typename Scalar>
65 this->damping_factor_condition_overloaded = onOff;
68 template<
typename Scalar>
71 double current_damping_factor = this->get_parameter_value(this->p_damping_factors).back();
73 double solution_change_norm = 0.;
74 for (
int i = 0; i < this->problem_size; i++)
76 solution_change_norm += std::pow(std::abs(linear_system_solution[i] - this->sln_vector[i]), 2.);
77 this->sln_vector[i] += current_damping_factor * (linear_system_solution[i] - this->sln_vector[i]);
80 return std::sqrt(solution_change_norm) * current_damping_factor;
83 template<
typename Scalar>
86 Scalar* temp = malloc_with_check<PicardMatrixSolver<Scalar>, Scalar>(this->problem_size,
this);
87 if (this->previous_jacobian)
88 this->previous_jacobian->multiply_with_vector(this->sln_vector, temp,
true);
90 this->get_jacobian()->multiply_with_vector(this->sln_vector, temp,
true);
92 for (
int i = 0; i < this->problem_size; i++)
93 temp[i] = temp[i] - residual->
get(i);
95 double residual_norm = get_l2_norm(temp, this->problem_size);
96 free_with_check(temp);
101 template<
typename Scalar>
105 this->handle_previous_vectors();
108 template<
typename Scalar>
111 if (damping_factor_condition_overloaded)
113 if (this->get_parameter_value(this->solution_change_norms()).size() == 1)
116 double sln_change_norm = *(this->get_parameter_value(this->solution_change_norms()).end() - 1);
117 double previous_sln_change_norm = *(this->get_parameter_value(this->solution_change_norms()).end() - 2);
118 return (sln_change_norm < previous_sln_change_norm * this->sufficient_improvement_factor);
124 template<
typename Scalar>
128 this->init_anderson();
131 template<
typename Scalar>
134 this->deinit_anderson();
138 template<
typename Scalar>
141 this->num_last_vectors_used = num;
144 template<
typename Scalar>
147 this->anderson_beta = beta;
150 template<
typename Scalar>
153 anderson_is_on = to_set;
156 template<
typename Scalar>
161 previous_Anderson_sln_vector = malloc_with_check<PicardMatrixSolver<Scalar>, Scalar>(this->problem_size,
this);
162 previous_vectors = malloc_with_check<PicardMatrixSolver<Scalar>, Scalar*>(num_last_vectors_used,
this);
163 for (
int i = 0; i < num_last_vectors_used; i++)
165 anderson_coeffs = malloc_with_check<PicardMatrixSolver<Scalar>, Scalar>(num_last_vectors_used - 1,
this);
166 memcpy(previous_vectors[0], this->sln_vector, this->problem_size*
sizeof(Scalar));
167 this->vec_in_memory = 1;
171 template<
typename Scalar>
176 free_with_check(previous_Anderson_sln_vector);
177 for (
int i = 0; i < num_last_vectors_used; i++)
178 free_with_check(previous_vectors[i]);
179 free_with_check(previous_vectors);
180 free_with_check(anderson_coeffs);
184 template<
typename Scalar>
191 if (this->vec_in_memory < num_last_vectors_used)
192 memcpy(previous_vectors[this->vec_in_memory++], this->sln_vector, this->problem_size *
sizeof(Scalar));
197 Scalar* oldest_vec = previous_vectors[0];
199 for (
int i = 0; i < num_last_vectors_used - 1; i++)
200 previous_vectors[i] = previous_vectors[i + 1];
202 previous_vectors[num_last_vectors_used - 1] = oldest_vec;
204 memcpy(oldest_vec, this->sln_vector, this->problem_size*
sizeof(Scalar));
207 if (this->vec_in_memory >= num_last_vectors_used)
210 this->calculate_anderson_coeffs();
213 for (
int i = 0; i < this->problem_size; i++)
215 this->previous_Anderson_sln_vector[i] = 0.;
216 for (
int j = 1; j < num_last_vectors_used; j++)
217 this->previous_Anderson_sln_vector[i] += anderson_coeffs[j - 1] * previous_vectors[j][i] - (1.0 - anderson_beta) * anderson_coeffs[j - 1] * (previous_vectors[j][i] - previous_vectors[j - 1][i]);
223 template<
typename Scalar>
227 if (num_last_vectors_used == 2)
229 anderson_coeffs[0] = 1.0;
235 int n = num_last_vectors_used - 2;
238 Scalar** mat = new_matrix<Scalar>(n, n);
239 Scalar* rhs = malloc_with_check<PicardMatrixSolver<Scalar>, Scalar>(n,
this);
241 for (
int i = 0; i < n; i++)
245 for (
int k = 0; k < this->problem_size; k++)
247 Scalar residual_n_k = previous_vectors[n + 1][k] - previous_vectors[n][k];
248 Scalar residual_i_k = previous_vectors[i + 1][k] - previous_vectors[i][k];
249 rhs[i] += residual_n_k * (residual_n_k - residual_i_k);
251 for (
int j = 0; j < n; j++)
254 for (
int k = 0; k < this->problem_size; k++)
256 Scalar residual_n_k = previous_vectors[n + 1][k] - previous_vectors[n][k];
257 Scalar residual_i_k = previous_vectors[i + 1][k] - previous_vectors[i][k];
258 Scalar residual_j_k = previous_vectors[j + 1][k] - previous_vectors[j][k];
259 val += (residual_n_k - residual_i_k) * (residual_n_k - residual_j_k);
267 int* perm = malloc_with_check<PicardMatrixSolver<Scalar>,
int>(n,
this);
269 lubksb<Scalar>(mat, n, perm, rhs);
273 for (
int i = 0; i < n; i++)
275 anderson_coeffs[i] = rhs[i];
278 anderson_coeffs[n] = 1.0 - sum;
281 free_with_check(mat);
282 free_with_check(rhs);
HERMES_API void ludcmp(T **a, Int n, Int *indx, double *d)
General namespace for the Hermes library.
General (abstract) vector representation in Hermes.
virtual Scalar get(unsigned int idx) const =0
void calculate_anderson_coeffs()
Calcualte the coefficients.
virtual void deinit_solving()
Internal.
Namespace containing classes for vector / matrix operations.
File containing common definitions, and basic global enums etc. for HermesCommon. ...
void deinit_anderson()
Deinitialization.
Base class for defining interface for nonlinear solvers.
virtual double update_solution_return_change_norm(Scalar *linear_system_solution)
void set_anderson_beta(double beta)
Contains operation on dense matrices.
virtual void init_solving(Scalar *&coeff_vec)
Initialization - called at the beginning of solving.
virtual bool damping_factor_condition()
Returns iff the damping factor condition is fulfilled.
void init_anderson()
Initialization.
virtual void init_solving(Scalar *coeff_vec)
void use_Anderson_acceleration(bool to_set)
Turn on / off the Anderson acceleration. By default it is off.
void set_num_last_vector_used(int num)
virtual bool damping_factor_condition()
Returns iff the damping factor condition is fulfilled.
virtual void deinit_solving()
Internal.
void handle_previous_vectors()
Handle the previous vectors.
Dense (small) simply stored matrix operations.
virtual double calculate_residual_norm()
Norm for convergence.
virtual void solve_linear_system()
virtual void solve_linear_system()
Solve the step's linear system.