70 constexpr static unsigned Dim = Field::dim;
71 using mesh_type =
typename Field::Mesh_t;
77 inverse_diagonal_m = std::move(inverse_diagonal);
80 void operator()(
Field& u,
Field& result)
override {
90 if constexpr (std::is_same_v<InvDiagF, std::function<double(
Field&)>>) {
91 const double scale = w_m * inverse_diagonal_m(u);
94 result = inverse_diagonal_m(u);
95 result = w_m * result;
100 InvDiagF inverse_diagonal_m;
110 constexpr static unsigned Dim = Field::dim;
111 using mesh_type =
typename Field::Mesh_t;
115 unsigned int max_level = 6,
double zeta = 1e-3,
116 double* eta =
nullptr)
123 op_m = std::move(op);
128 if (eta_m !=
nullptr) {
136 , level_m(other.level_m)
137 , alpha_m(other.alpha_m)
138 , beta_m(other.beta_m)
139 , zeta_m(other.zeta_m)
140 , eta_m(other.eta_m) {
141 op_m = std::move(other.op_m);
157 void recursive_preconditioner(
Field& u,
unsigned int level,
Field& out) {
167 Field& Pr = Pr_scratch_m[level];
168 Field& PA = PA_scratch_m[level];
169 Field& PAPr = PAPr_scratch_m[level];
173 recursive_preconditioner(u, level - 1, Pr);
175 recursive_preconditioner(PA, level - 1, PAPr);
176 out = eta_m[level] * (2.0 * Pr - PAPr);
179 void operator()(
Field& u,
Field& result)
override {
183 recursive_preconditioner(u, level_m, result);
186 void init_fields(
Field& b)
override {
188 if (eta_m ==
nullptr) {
189 eta_m =
new double[level_m + 1];
190 eta_m[0] = 2.0 / ((alpha_m + beta_m) * (1.0 + zeta_m));
194 / (1.0 + 2 * alpha_m * eta_m[0] - alpha_m * eta_m[0] * alpha_m * eta_m[0]);
196 for (
unsigned int i = 2; i < level_m + 1; ++i) {
197 eta_m[i] = 2.0 / (1.0 + 2 * eta_m[i - 1] - eta_m[i - 1] * eta_m[i - 1]);
205 mesh_type& mesh = b.get_mesh();
206 layout_type& layout = b.getLayout();
207 if (!fields_initialized_m) {
208 Pr_scratch_m.resize(level_m + 1);
209 PA_scratch_m.resize(level_m + 1);
210 PAPr_scratch_m.resize(level_m + 1);
211 for (
unsigned int i = 1; i <= level_m; ++i) {
212 Pr_scratch_m[i] =
Field(mesh, layout);
213 PA_scratch_m[i] =
Field(mesh, layout);
214 PAPr_scratch_m[i] =
Field(mesh, layout);
216 fields_initialized_m =
true;
218 for (
unsigned int i = 1; i <= level_m; ++i) {
219 Pr_scratch_m[i].updateLayout(layout);
220 PA_scratch_m[i].updateLayout(layout);
221 PAPr_scratch_m[i].updateLayout(layout);
230 unsigned int level_m;
233 double* eta_m =
nullptr;
234 std::vector<Field> Pr_scratch_m;
235 std::vector<Field> PA_scratch_m;
236 std::vector<Field> PAPr_scratch_m;
237 bool fields_initialized_m =
false;
246 constexpr static unsigned Dim = Field::dim;
247 using mesh_type =
typename Field::Mesh_t;
251 unsigned int degree = 63,
double zeta = 1e-3)
258 op_m = std::move(op);
263 if (rho_m !=
nullptr) {
271 , degree_m(other.degree_m)
272 , theta_m(other.theta_m)
273 , sigma_m(other.sigma_m)
274 , delta_m(other.delta_m)
275 , alpha_m(other.delta_m)
276 , beta_m(other.delta_m)
277 , zeta_m(other.zeta_m)
278 , rho_m(other.rho_m) {
279 op_m = std::move(other.op_m);
287 void operator()(
Field& r,
Field& result)
override {
290 x_old_m = r / theta_m;
292 x_m = 2.0 * rho_m[1] / delta_m * (2.0 * r - A_m / theta_m);
295 Kokkos::deep_copy(result.getView(), x_old_m.getView());
301 Kokkos::deep_copy(result.getView(), x_m.getView());
304 for (
unsigned int i = 2; i < degree_m + 1; ++i) {
306 z_m = 2.0 / delta_m * (r - A_m);
309 result = rho_m[i] * (2 * sigma_m * x_m - rho_m[i - 1] * x_old_m + z_m);
310 Kokkos::deep_copy(x_old_m.getView(), x_m.getView());
311 Kokkos::deep_copy(x_m.getView(), result.getView());
315 void init_fields(
Field& b)
override {
317 if (rho_m ==
nullptr) {
318 theta_m = (beta_m + alpha_m) / 2.0 * (1.0 + zeta_m);
319 delta_m = (beta_m - alpha_m) / 2.0;
320 sigma_m = theta_m / delta_m;
322 rho_m =
new double[degree_m + 1];
323 rho_m[0] = 1.0 / sigma_m;
324 for (
unsigned int i = 1; i < degree_m + 1; ++i) {
325 rho_m[i] = 1.0 / (2.0 * sigma_m - rho_m[i - 1]);
328 mesh_type& mesh = b.get_mesh();
329 layout_type& layout = b.getLayout();
332 if (!fields_initialized_m) {
333 x_m =
Field(mesh, layout);
334 x_old_m =
Field(mesh, layout);
335 A_m =
Field(mesh, layout);
336 z_m =
Field(mesh, layout);
337 fields_initialized_m =
true;
339 x_m.updateLayout(layout);
340 x_old_m.updateLayout(layout);
341 A_m.updateLayout(layout);
342 z_m.updateLayout(layout);
355 double* rho_m =
nullptr;
360 bool fields_initialized_m =
false;
368 constexpr static unsigned Dim = Field::dim;
369 using mesh_type =
typename Field::Mesh_t;
373 unsigned innerloops = 5)
375 , innerloops_m(innerloops) {
376 upper_and_lower_m = std::move(upper_and_lower);
377 inverse_diagonal_m = std::move(inverse_diagonal);
380 void operator()(
Field& r,
Field& result)
override {
387 for (
unsigned int j = 0; j < innerloops_m; ++j) {
388 ULg_m = upper_and_lower_m(result);
399 if constexpr (std::is_same_v<InvDiagF, std::function<double(
Field&)>>) {
400 result = inverse_diagonal_m(result) * result;
402 result = inverse_diagonal_m(result).deepCopy();
407 void init_fields(
Field& b)
override {
408 layout_type& layout = b.getLayout();
409 mesh_type& mesh = b.get_mesh();
410 if (!fields_initialized_m) {
411 ULg_m =
Field(mesh, layout);
412 fields_initialized_m =
true;
414 ULg_m.updateLayout(layout);
419 UpperAndLowerF upper_and_lower_m;
420 InvDiagF inverse_diagonal_m;
421 unsigned innerloops_m;
423 bool fields_initialized_m =
false;
435 constexpr static unsigned Dim = Field::dim;
436 using mesh_type =
typename Field::Mesh_t;
440 unsigned innerloops = 5)
442 , innerloops_m(innerloops) {
443 op_m = std::move(op);
444 inverse_diagonal_m = std::move(inverse_diagonal);
447 void operator()(
Field& r,
Field& result)
override {
456 for (
unsigned int j = 0; j < innerloops_m; ++j) {
468 if constexpr (std::is_same_v<InvDiagF, std::function<double(
Field&)>>) {
469 result = g_old_m + inverse_diagonal_m(result) * result;
471 result = g_old_m + inverse_diagonal_m(result);
473 Kokkos::deep_copy(g_old_m.getView(), result.getView());
477 void init_fields(
Field& b)
override {
478 layout_type& layout = b.getLayout();
479 mesh_type& mesh = b.get_mesh();
480 if (!fields_initialized_m) {
481 Ag_m =
Field(mesh, layout);
482 g_old_m =
Field(mesh, layout);
483 fields_initialized_m =
true;
485 Ag_m.updateLayout(layout);
486 g_old_m.updateLayout(layout);
492 InvDiagF inverse_diagonal_m;
493 unsigned innerloops_m;
496 bool fields_initialized_m =
false;
504 constexpr static unsigned Dim = Field::dim;
505 using mesh_type =
typename Field::Mesh_t;
509 unsigned innerloops,
unsigned outerloops)
511 , innerloops_m(innerloops)
512 , outerloops_m(outerloops) {
513 lower_m = std::move(lower);
514 upper_m = std::move(upper);
515 inverse_diagonal_m = std::move(inverse_diagonal);
518 void operator()(
Field& b,
Field& result)
override {
526 for (
unsigned int k = 0; k < outerloops_m; ++k) {
527 UL_m = upper_m(result);
530 for (
unsigned int j = 0; j < innerloops_m; ++j) {
531 UL_m = lower_m(result);
532 UL_m = UL_m.deepCopy();
534 if constexpr (std::is_same_v<InvDiagF, std::function<double(
Field&)>>) {
535 result = inverse_diagonal_m(result) * result;
537 result = inverse_diagonal_m(result).deepCopy();
547 UL_m = lower_m(result);
548 UL_m = UL_m.deepCopy();
550 for (
unsigned int j = 0; j < innerloops_m; ++j) {
551 UL_m = upper_m(result);
552 UL_m = UL_m.deepCopy();
554 if constexpr (std::is_same_v<InvDiagF, std::function<double(
Field&)>>) {
555 result = inverse_diagonal_m(result) * result;
557 result = inverse_diagonal_m(result).deepCopy();
570 void init_fields(
Field& b)
override {
571 layout_type& layout = b.getLayout();
572 mesh_type& mesh = b.get_mesh();
573 if (!fields_initialized_m) {
574 UL_m =
Field(mesh, layout);
575 r_m =
Field(mesh, layout);
576 fields_initialized_m =
true;
578 UL_m.updateLayout(layout);
579 r_m.updateLayout(layout);
586 InvDiagF inverse_diagonal_m;
587 unsigned innerloops_m;
588 unsigned outerloops_m;
591 bool fields_initialized_m =
false;
599 constexpr static unsigned Dim = Field::dim;
600 using mesh_type =
typename Field::Mesh_t;
604 DiagF&& diagonal,
unsigned innerloops,
unsigned outerloops,
607 , innerloops_m(innerloops)
608 , outerloops_m(outerloops)
610 lower_m = std::move(lower);
611 upper_m = std::move(upper);
612 inverse_diagonal_m = std::move(inverse_diagonal);
613 diagonal_m = std::move(diagonal);
616 void operator()(
Field& b,
Field& result)
override {
641 for (
unsigned int k = 0; k < outerloops_m; ++k) {
642 if constexpr (std::is_same_v<InvDiagF, std::function<double(
Field&)>>) {
643 UL_m = upper_m(result);
644 D = diagonal_m(result);
645 r_m = omega_m * (b - UL_m) + (1.0 - omega_m) * D * result;
647 for (
unsigned int j = 0; j < innerloops_m; ++j) {
648 UL_m = lower_m(result);
649 result = r_m - omega_m * UL_m;
650 result = inverse_diagonal_m(result) * result;
652 UL_m = lower_m(result);
653 D = diagonal_m(result);
654 r_m = omega_m * (b - UL_m) + (1.0 - omega_m) * D * result;
655 for (
unsigned int j = 0; j < innerloops_m; ++j) {
656 UL_m = upper_m(result);
657 result = r_m - omega_m * UL_m;
658 result = inverse_diagonal_m(result) * result;
661 UL_m = upper_m(result).deepCopy();
662 r_m = omega_m * (b - UL_m) + (1.0 - omega_m) * diagonal_m(result);
664 for (
unsigned int j = 0; j < innerloops_m; ++j) {
665 UL_m = lower_m(result).deepCopy();
666 result = r_m - omega_m * UL_m;
667 result = inverse_diagonal_m(result).deepCopy();
669 UL_m = lower_m(result).deepCopy();
670 r_m = omega_m * (b - UL_m) + (1.0 - omega_m) * diagonal_m(result);
671 for (
unsigned int j = 0; j < innerloops_m; ++j) {
672 UL_m = upper_m(result).deepCopy();
673 result = r_m - omega_m * UL_m;
674 result = inverse_diagonal_m(result).deepCopy();
680 void init_fields(
Field& b)
override {
681 layout_type& layout = b.getLayout();
682 mesh_type& mesh = b.get_mesh();
683 if (!fields_initialized_m) {
684 UL_m =
Field(mesh, layout);
685 r_m =
Field(mesh, layout);
686 fields_initialized_m =
true;
688 UL_m.updateLayout(layout);
689 r_m.updateLayout(layout);
696 InvDiagF inverse_diagonal_m;
698 unsigned innerloops_m;
699 unsigned outerloops_m;
703 bool fields_initialized_m =
false;
750 unsigned int max_iter = 5000,
double tol = 1e-3) {
752 using mesh_type =
typename Field::Mesh_t;
754 mesh_type& mesh = x_0.get_mesh();
755 layout_type& layout = x_0.getLayout();
756 Field x_new(mesh, layout);
757 Field x_diff(mesh, layout);
760 while (error > tol && i < max_iter) {
762 x_new = x_new - lambda_max * x_0;
763 lambda = -norm(x_new);
764 x_diff = x_new - lambda * x_0;
765 error = norm(x_diff);
766 x_new = x_new / -lambda;
770 lambda = lambda + lambda_max;
772 std::cerr <<
"Powermethod did not converge, lambda_min : " << lambda
773 <<
", error : " << error << std::endl;
double powermethod(Functor &&f, Field &x_0, unsigned int max_iter=5000, double tol=1e-3)
Definition Preconditioner.h:714
double adapted_powermethod(Functor &&f, Field &x_0, double lambda_max, unsigned int max_iter=5000, double tol=1e-3)
Definition Preconditioner.h:749