19 #include "picard_solver.h"
20 #include "projections/ogprojection.h"
21 #include "exact_solution.h"
27 template<
typename Scalar>
28 PicardSolver<Scalar>::PicardSolver()
29 : NonlinearSolver<Scalar>(new DiscreteProblem<Scalar>()), verbose_output_linear_solver(false), own_dp(true)
34 template<
typename Scalar>
35 PicardSolver<Scalar>::PicardSolver(DiscreteProblem<Scalar>* dp)
36 : NonlinearSolver<Scalar>(dp), verbose_output_linear_solver(false), own_dp(false)
41 template<
typename Scalar>
42 PicardSolver<Scalar>::PicardSolver(
const WeakForm<Scalar>* wf,
const Space<Scalar>* space)
43 : NonlinearSolver<Scalar>(new DiscreteProblem<Scalar>(wf, space)), verbose_output_linear_solver(false), own_dp(true)
48 template<
typename Scalar>
49 PicardSolver<Scalar>::PicardSolver(
const WeakForm<Scalar>* wf, Hermes::vector<
const Space<Scalar>*> spaces)
50 : NonlinearSolver<Scalar>(new DiscreteProblem<Scalar>(wf, spaces)), verbose_output_linear_solver(false), own_dp(true)
55 template<
typename Scalar>
61 template<
typename Scalar>
66 num_last_vectors_used = 3;
68 anderson_is_on =
false;
70 matrix = create_matrix<Scalar>();
71 rhs = create_vector<Scalar>();
72 linear_solver = create_linear_solver<Scalar>(matrix, rhs);
75 template<
typename Scalar>
85 template<
typename Scalar>
88 Hermes::vector<Space<Scalar>*> spaces;
89 for(
unsigned int i = 0; i < static_cast<DiscreteProblem<Scalar>*>(this->dp)->get_spaces().size(); i++)
96 template<
typename Scalar>
102 template<
typename Scalar>
103 PicardSolver<Scalar>::~PicardSolver()
107 delete linear_solver;
111 static_cast<DiscreteProblem<Scalar>*
>(this->dp)->have_matrix =
false;
114 template<
typename Scalar>
120 template<
typename Scalar>
126 template<
typename Scalar>
132 template<
typename Scalar>
135 this->verbose_output_linear_solver = to_set;
138 template<
typename Scalar>
139 void calculate_anderson_coeffs(Scalar** previous_vectors, Scalar* anderson_coeffs,
int num_last_vectors_used,
int ndof)
141 if(num_last_vectors_used <= 1)
throw Hermes::Exceptions::Exception(
"Picard: Anderson acceleration makes sense only if at least two last iterations are used.");
144 if(num_last_vectors_used == 2)
146 anderson_coeffs[0] = 1.0;
152 int n = num_last_vectors_used - 2;
155 double** mat = new_matrix<double>(n, n);
156 Scalar* rhs =
new Scalar[n];
159 for (
int i = 0; i < n; i++)
163 for (
int k = 0; k < ndof; k++)
165 Scalar residual_n_k = previous_vectors[n + 1][k] - previous_vectors[n][k];
166 Scalar residual_i_k = previous_vectors[i + 1][k] - previous_vectors[i][k];
167 rhs[i] += residual_n_k * (residual_n_k - residual_i_k);
169 for (
int j = 0; j < n; j++)
172 for (
int k = 0; k < ndof; k++)
174 Scalar residual_n_k = previous_vectors[n + 1][k] - previous_vectors[n][k];
175 Scalar residual_i_k = previous_vectors[i + 1][k] - previous_vectors[i][k];
176 Scalar residual_j_k = previous_vectors[j + 1][k] - previous_vectors[j][k];
177 val += (residual_n_k - residual_i_k) * (residual_n_k - residual_j_k);
182 double* ptr = (
double*)(&val);
189 int* perm =
new int[n];
190 ludcmp(mat, n, perm, &d);
191 lubksb<Scalar>(mat, n, perm, rhs);
196 for (
int i = 0; i < n; i++)
198 anderson_coeffs[i] = rhs[i];
201 anderson_coeffs[n] = 1.0 - sum;
210 template<
typename Scalar>
216 template<
typename Scalar>
219 this->max_iter = max_iter;
222 template<
typename Scalar>
225 this->num_last_vectors_used = num;
228 template<
typename Scalar>
231 this->anderson_beta = beta;
234 template<
typename Scalar>
237 anderson_is_on = to_set;
240 template<
typename Scalar>
243 Hermes::vector<Solution<Scalar>*> vectorToPass;
244 vectorToPass.push_back(initial_guess);
245 this->solve(vectorToPass);
248 template<
typename Scalar>
251 int ndof = this->dp->get_num_dofs();
252 Scalar* coeff_vec =
new Scalar[ndof];
255 this->solve(coeff_vec);
258 template<
typename Scalar>
265 if(num_last_vectors_used < 1)
266 throw Hermes::Exceptions::Exception(
"Picard: Bad number of last iterations to be used (must be at least one).");
272 Hermes::vector<bool> add_dir_lift;
273 for(
unsigned int i = 0; i < spaces.size(); i++)
274 add_dir_lift.push_back(
false);
277 if(this->sln_vector != NULL)
279 delete [] this->sln_vector;
280 this->sln_vector = NULL;
283 this->sln_vector =
new Scalar[ndof];
285 bool delete_coeff_vec =
false;
286 if(coeff_vec == NULL)
288 coeff_vec =
new Scalar[ndof];
289 memset(coeff_vec, 0, ndof*
sizeof(Scalar));
290 delete_coeff_vec =
true;
293 memcpy(this->sln_vector, coeff_vec, ndof*
sizeof(Scalar));
297 Scalar* last_iter_vector =
new Scalar[ndof];
298 for (
int i = 0; i < ndof; i++)
299 last_iter_vector[i] = this->sln_vector[i];
302 Scalar** previous_vectors = NULL;
303 Scalar* anderson_coeffs = NULL;
306 previous_vectors =
new Scalar*[num_last_vectors_used];
307 for (
int i = 0; i < num_last_vectors_used; i++) previous_vectors[i] =
new Scalar[ndof];
308 anderson_coeffs =
new Scalar[num_last_vectors_used-1];
313 for (
int i = 0; i < ndof; i++) previous_vectors[0][i] = this->sln_vector[i];
316 int vec_in_memory = 1;
318 this->on_initialization();
322 this->on_step_begin();
325 this->dp->assemble(last_iter_vector, matrix, rhs);
326 if(this->output_matrixOn && (this->output_matrixIterations == -1 || this->output_matrixIterations >= it))
328 char* fileName =
new char[this->matrixFilename.length() + 5];
329 if(this->matrixFormat == Hermes::Algebra::DF_MATLAB_SPARSE)
330 sprintf(fileName,
"%s%i.m", this->matrixFilename.c_str(), it);
332 sprintf(fileName,
"%s%i", this->matrixFilename.c_str(), it);
333 FILE* matrix_file = fopen(fileName,
"w+");
335 matrix->dump(matrix_file, this->matrixVarname.c_str(), this->matrixFormat, this->matrix_number_format);
339 if(this->output_rhsOn && (this->output_rhsIterations == -1 || this->output_rhsIterations >= it))
341 char* fileName =
new char[this->RhsFilename.length() + 5];
342 if(this->RhsFormat == Hermes::Algebra::DF_MATLAB_SPARSE)
343 sprintf(fileName,
"%s%i.m", this->RhsFilename.c_str(), it);
345 sprintf(fileName,
"%s%i", this->RhsFilename.c_str(), it);
346 FILE* rhs_file = fopen(fileName,
"w+");
347 rhs->dump(rhs_file, this->RhsVarname.c_str(), this->RhsFormat, this->rhs_number_format);
357 if(!linear_solver->solve())
358 throw Exceptions::LinearMatrixSolverException();
360 memcpy(this->sln_vector, linear_solver->get_sln_vector(),
sizeof(Scalar)*ndof);
366 if (vec_in_memory < num_last_vectors_used)
368 for (
int i = 0; i < ndof; i++) previous_vectors[vec_in_memory][i] = this->sln_vector[i];
375 Scalar* oldest_vec = previous_vectors[0];
376 for (
int i = 0; i < num_last_vectors_used-1; i++) previous_vectors[i] = previous_vectors[i + 1];
377 previous_vectors[num_last_vectors_used-1] = oldest_vec;
378 for (
int j = 0; j < ndof; j++) previous_vectors[num_last_vectors_used-1][j] = this->sln_vector[j];
383 if (anderson_is_on && vec_in_memory >= num_last_vectors_used)
386 calculate_anderson_coeffs(previous_vectors, anderson_coeffs, num_last_vectors_used, ndof);
389 for (
int i = 0; i < ndof; i++)
391 this->sln_vector[i] = 0;
392 for (
int j = 1; j < num_last_vectors_used; j++)
394 this->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]);
402 double last_iter_vec_norm = 0;
403 for (
int i = 0; i < ndof; i++)
404 last_iter_vec_norm += std::abs(last_iter_vector[i] * last_iter_vector[i]);
406 last_iter_vec_norm = sqrt(last_iter_vec_norm);
408 double abs_error = 0;
409 for (
int i = 0; i < ndof; i++) abs_error += std::abs((this->sln_vector[i] - last_iter_vector[i]) * (this->sln_vector[i] - last_iter_vector[i]));
410 abs_error = sqrt(abs_error);
412 double rel_error = abs_error / last_iter_vec_norm;
415 if(std::abs(last_iter_vec_norm) < 1e-12)
416 this->info(
"\tPicard: iteration %d, nDOFs %d, starting from zero vector.", it, ndof);
418 this->info(
"\tPicard: iteration %d, nDOFs %d, relative error %g%%", it, ndof, rel_error);
423 delete [] last_iter_vector;
427 for (
int i = 0; i < num_last_vectors_used; i++)
delete [] previous_vectors[i];
428 delete [] previous_vectors;
429 delete [] anderson_coeffs;
435 this->info(
"\tPicard: solution duration: %f s.\n", this->last());
443 delete [] last_iter_vector;
447 for (
int i = 0; i < num_last_vectors_used; i++)
delete [] previous_vectors[i];
448 delete [] previous_vectors;
449 delete [] anderson_coeffs;
454 this->info(
"\tPicard: solution duration: %f s.\n", this->last());
457 throw Hermes::Exceptions::Exception(
"\tPicard: maximum allowed number of Picard iterations exceeded.");
466 for (
int i = 0; i < ndof; i++)
467 last_iter_vector[i] = this->sln_vector[i];