16#ifndef Multigrille_base_TPP_H
17#define Multigrille_base_TPP_H
19#include <IJK_VDF_converter.h>
20#include <Matrice_Morse_Sym.h>
21#include <IJK_Vector.h>
22#include <Interprete_bloc.h>
23#include <Perf_counters.h>
26template <
typename _TYPE_,
typename _TYPE_ARRAY_>
36template <
typename _TYPE_FUNC_,
typename _TYPE_,
typename _TYPE_ARRAY_>
43 const int imax = x.
ni();
44 const int jmax = x.
nj();
45 const int kmax = x.
nk();
46 for (k = 0; k < kmax; k++)
47 for (j = 0; j < jmax; j++)
48 for (i = 0; i < imax; i++)
50 ijk_b(i,j,k) = (_TYPE_FUNC_)rhs(i,j,k);
55 for (k = 0; k < kmax; k++)
56 for (j = 0; j < jmax; j++)
57 for (i = 0; i < imax; i++)
59 x(i,j,k) = (_TYPE_)ijk_x(i,j,k);
65template <
typename _TYPE_,
typename _TYPE_ARRAY_>
75template <
typename _TYPE_,
typename _TYPE_ARRAY_>
84template <
typename _TYPE_,
typename _TYPE_ARRAY_>
98template <
typename _TYPE_,
typename _TYPE_ARRAY_>
100 int grid_level,
int iter_number)
102 statistics().create_custom_counter(
"projection: multigrid",2,
"IJK");
103 double norme_residu_final = 0.;
105#ifdef DUMP_LATA_ALL_LEVELS
107 copy_residu_for_post.
data() = 0.;
110 copy_xini_for_post.
data() = x.
data();
112#ifdef DUMP_X_B_AND_RESIDUE_IN_FILE
113 dump_x_b_residue_in_file(x,b,residu, grid_level, global_count_dump_in_file,
Nom(
"avt pre-smooth / recursive call / coarse solver"));
120 statistics().begin_count(
"projection: multigrid",statistics().get_last_opened_counter_level()+1);
121 const int pss = (grid_level >= pre_smooth_steps_.size_array())
122 ? pre_smooth_steps_[pre_smooth_steps_.size_array()-1]
123 : pre_smooth_steps_[grid_level];
125#ifdef DUMP_X_B_AND_RESIDUE_IN_FILE
126 dump_x_b_residue_in_file(x,b,residu, grid_level, global_count_dump_in_file,
Nom(
"apres pre-smooth"));
129#ifdef DUMP_LATA_ALL_LEVELS
133 norme_residu_final = norme_ijk(residu);
136 Cout <<
"level=" << grid_level <<
" residu(pre)=" << norme_residu_final << finl;
142 const int nmax = nb_full_mg_steps_.size_array() - 1;
144 if (iter_number != 0 || grid_level <= 1)
146 if (grid_level > nmax)
147 nb_full = nb_full_mg_steps_[nmax];
149 nb_full = nb_full_mg_steps_[grid_level];
152 for (
int fmg_step = 0; fmg_step < nb_full; fmg_step++)
154#ifdef DUMP_LATA_ALL_LEVELS
155 copy_residu_for_post = residu;
158 coarse_b.
data() = 0.;
159 coarsen(residu, coarse_b, grid_level);
174 coarse_x.
data() = 0.;
176#ifdef DUMP_X_B_AND_RESIDUE_IN_FILE
180 statistics().end_count(
"projection: multigrid");
182 multigrille_(coarse_x, coarse_b, coarse_residu, grid_level+1, fmg_step);
183 statistics().begin_count(
"projection: multigrid",statistics().get_last_opened_counter_level()+1);
185#ifdef DUMP_X_B_AND_RESIDUE_IN_FILE
186 dump_x_b_residue_in_file(coarse_x,coarse_b,coarse_residu, grid_level+1, global_count_dump_in_file,
Nom(
"avt interpol / apres recursive-call/jacobi-residu/ou/coarse-solver "));
192#ifdef DUMP_X_B_AND_RESIDUE_IN_FILE
194 copy_x_to_compute_res.
data() = x.
data();
195 const int g = x.
ghost();
198 assert(imin == copy_x_to_compute_res.
linear_index(-g,-g,-g));
199 assert(imax == copy_x_to_compute_res.
linear_index(x.
ni()-1+g, x.
nj()-1+g, x.
nk()-1+g) + 1);
200 _TYPE_ *ptr = x.
data().addr();
201 const _TYPE_ *ptr2 = copy_x_to_compute_res.
data().addr();
202 for (
int i = imin; i < imax; i++)
206 dump_x_b_residue_in_file(x,b,residu, grid_level, global_count_dump_in_file,
Nom(
"apres interpol"));
210 const int postss = (grid_level >= smooth_steps_.size_array())
211 ? smooth_steps_[smooth_steps_.size_array()-1]
212 : smooth_steps_[grid_level];
215#ifdef DUMP_X_B_AND_RESIDUE_IN_FILE
216 dump_x_b_residue_in_file(x,b,residu, grid_level, global_count_dump_in_file,
Nom(
"apres post-smooth"));
218#ifdef DUMP_LATA_ALL_LEVELS
220 static ArrOfInt step;
224 const Nom lata_name =
Nom(
"Multigrid_level") +
Nom(grid_level) +
Nom(
".lata");
225 if (step[grid_level] == 0)
230 dumplata_header(lata_name, x );
232 dumplata_newtime(lata_name,step[grid_level]);
233 dumplata_scalar(lata_name,
"xini", copy_x_for_post, step[grid_level]);
234 dumplata_scalar(lata_name,
"x1", copy_x_for_post, step[grid_level]);
235 dumplata_scalar(lata_name,
"xf", x, step[grid_level]);
236 dumplata_scalar(lata_name,
"b", b, step[grid_level]);
237 dumplata_scalar(lata_name,
"residu1", copy_residu_for_post, step[grid_level]);
238 dumplata_scalar(lata_name,
"residue", residu, step[grid_level]);
243 norme_residu_final = norme_ijk(residu);
245 Cout <<
"level=" << grid_level <<
" residu=" << norme_residu_final << finl;
247 if (grid_level == 0 && norme_residu_final < seuil_ && max_iter_gcp_ == 0)
250 statistics().end_count(
"projection: multigrid");
254 statistics().begin_count(
"projection: multigrid",statistics().get_last_opened_counter_level()+1);
255#ifdef DUMP_X_B_AND_RESIDUE_IN_FILE
260#ifdef DUMP_X_B_AND_RESIDUE_IN_FILE
265#ifdef DUMP_X_B_AND_RESIDUE_IN_FILE
271 norme_residu_final = norme_ijk(residu);
274 Cout << finl <<
"level=" << grid_level <<
" residu=" << norme_residu_final
275 <<
" (coarse solver)" << finl;
276#ifdef DUMP_LATA_ALL_LEVELS
278 static ArrOfInt step;
282 const Nom lata_name =
Nom(
"Multigrid_level") +
Nom(grid_level) +
Nom(
".lata");
283 if (step[grid_level] == 0)
286 x.get_splitting_non_const().get_grid_geometry_non_const().
nommer(dom);
287 dumplata_header(lata_name, x );
289 dumplata_newtime(lata_name,step[grid_level]);
290 dumplata_scalar(lata_name,
"x", x, step[grid_level]);
291 dumplata_scalar(lata_name,
"b", b, step[grid_level]);
292 dumplata_scalar(lata_name,
"residue", residu, step[grid_level]);
296 statistics().end_count(
"projection: multigrid");
299 return norme_residu_final;
302template <
typename _TYPE_,
typename _TYPE_ARRAY_>
319 for (k = 0; k < nk; k++)
320 for (j = 0; j < nj; j++)
321 for (i = 0; i < ni; i++)
322 secmem[mat.
renum(i,j,k)] = b(i,j,k);
329 solveur_grossier_.resoudre_systeme(mat.
matrice(), secmem, inco);
331 for (k = 0; k < nk; k++)
332 for (j = 0; j < nj; j++)
333 for (i = 0; i < ni; i++)
334 x(i,j,k) = (_TYPE_)inco[mat.
renum(i,j,k)];
338template <
typename _TYPE_,
typename _TYPE_ARRAY_>
341 const int g = x.
ghost();
344 _TYPE_ *ptr = x.
data().addr();
345 for (
int i = imin; i < imax; i++)
349template <
typename _TYPE_,
typename _TYPE_ARRAY_>
352 const int g = x.
ghost();
355 _TYPE_ *ptr = x.
data().addr();
356 for (
int i = imin; i < imax; i++)
360template <
typename _TYPE_,
typename _TYPE_ARRAY_>
363 const int g = x.
ghost();
368 _TYPE_ *ptr = x.
data().addr();
369 const _TYPE_ *ptr2 = y.
data().addr();
370 for (
int i = imin; i < imax; i++)
374template <
typename _TYPE_,
typename _TYPE_ARRAY_>
377 const int g = x.
ghost();
382 _TYPE_ *ptr = x.
data().addr();
383 const _TYPE_ *ptr2 = v.
data().addr();
384 for (
int i = imin; i < imax; i++)
385 ptr[i] += alpha * ptr2[i];
389template <
typename _TYPE_,
typename _TYPE_ARRAY_>
402 _TYPE_ dold = prod_scal_ijk(R, P);
405 for (
int iter = 0; iter < max_iter_gcp_; iter++)
410 _TYPE_ alpha = dold / prod_scal_ijk(P, residu);
412 Cout <<
"alpha=" << alpha <<
" normeP=" << norme_ijk(P) <<
" dold=" << dold << finl;
414 ajoute_alpha_v(x, alpha, P);
416 ajoute_alpha_v(R, alpha, residu);
418 _TYPE_ nr = (_TYPE_)norme_ijk(R);
419 Cout <<
"GCP+MG iteration " << iter <<
" residu " << nr << finl;
423 if (iter == max_iter_gcp_)
425 Cerr <<
"Non convergence de Multigrille_poreux::resoudre_avec_gcp en " << max_iter_gcp_
426 <<
" iterations" << finl;
433 _TYPE_ prodscal_RZ = prod_scal_ijk(R, Z);
434 _TYPE_ beta = prodscal_RZ / dold;
437 op_multiply(P, beta);
442template <
typename _TYPE_,
typename _TYPE_ARRAY_>
447 Cerr <<
"Erreur ajouter_alpha_v_multiple" << finl;
450 const int ni = x.
ni();
451 const int nj = x.
nj();
452 const int nk = x.
nk();
453 _TYPE_ * x_ptr = x.
data().addr();
458 for (nn = 0; nn < n; nn++)
460 y_ptr[nn] = y[nfirst + nn].data().addr();
461 c[nn] = (_TYPE_)coeff[nfirst + nn];
463 for (
int k = 0; k < nk; k++)
465 for (
int j = 0; j < nj; j++)
468 for (
int i = 0; i < ni; i++)
470 _TYPE_ val = x_ptr[index+i];
471 for (nn = 0; nn < n; nn++)
472 val += c[nn] * y_ptr[nn][index+i];
473 x_ptr[index+i] = val;
484template <
typename _TYPE_,
typename _TYPE_ARRAY_>
495 somme += ajouter_alpha_v_multiple_(x, coeff, y, 1, i);
497 somme += ajouter_alpha_v_multiple_(x, coeff, y, 2, i);
499 somme += ajouter_alpha_v_multiple_(x, coeff, y, 3, i);
501 somme += ajouter_alpha_v_multiple_(x, coeff, y, 4, i);
508template <
typename _TYPE_,
typename _TYPE_ARRAY_>
513 Cerr <<
"Erreur " << finl;
516 const int ni = x[0].ni();
517 const int nj = x[0].nj();
518 const int nk = x[0].nk();
519 _TYPE_ * x_ptr = x[m].data().addr();
521 _TYPE_ c[4] = { 0., 0., 0., 0. };
523 for (nn = 0; nn < n; nn++)
525 y_ptr[nn] = x[nfirst + nn].data().addr();
528 for (
int k = 0; k < nk; k++)
530 for (
int j = 0; j < nj; j++)
532 int index = x[0].linear_index(0,j,k);
533 for (
int i = 0; i < ni; i++)
535 _TYPE_ val = x_ptr[index+i];
536 for (nn = 0; nn < n; nn++)
537 c[nn] += val * y_ptr[nn][index+i];
541 for (nn = 0; nn < n; nn++)
542 resu[nfirst + nn] += c[nn];
548template <
typename _TYPE_,
typename _TYPE_ARRAY_>
560 calcul_produits_scalaires_(x, 1, i, n, resu);
562 calcul_produits_scalaires_(x, 2, i, n, resu);
564 calcul_produits_scalaires_(x, 3, i, n, resu);
566 calcul_produits_scalaires_(x, 4, i, n, resu);
572static inline void triangularise(
const DoubleTab& hessenberg,
const double norme_b, DoubleTab& resu, ArrOfDouble& r)
582 for(i = 0; i < n; i++)
586 const double h_ii = hessenberg(i, i);
587 const double h_i1i = hessenberg(i + 1, i);
588 const double tmp_val = 1. / sqrt(h_ii * h_ii + h_i1i * h_i1i);
589 ccos = h_ii * tmp_val;
590 ssin = - h_i1i * tmp_val;
592 for (
int j = i; j < n; j++)
594 const double h_ij = hessenberg(i, j);
595 const double h_i1j = hessenberg(i + 1, j);
596 resu(i, j) = ccos * h_ij - ssin * h_i1j;
597 resu(i + 1, j) = ssin * h_ij + ccos * h_i1j;
599 const double ri = r[i];
601 r[i + 1] = ssin * ri;
606template <
typename _TYPE_,
typename _TYPE_ARRAY_>
609 int n_krilov = n_krilov_;
610 DoubleTab hessenberg(n_krilov + 1, n_krilov);
618 for (
int ii=0; ii < n_krilov+1; ii++)
619 krilov_space.
add(titi);
620 for (
int ii=0; ii < n_krilov; ii++)
621 m_krilov_space.
add(titi);
625 for (
int ii=0; ii < n_krilov; ii++)
633 for (
int iter = 0; ; iter++)
637 const double norme_b = norme_ijk(krilov_space[0]);
640 Cout <<
"gmres iteration " << iter <<
" norme(residu) " << norme_b << finl;
641 if (norme_b < seuil_ || norme_b == 0.)
644 Cout <<
"gmres: norme(residu) < seuil=" << seuil_ <<
" => return" << finl;
647 if (iter >= max_iter_gmres_)
649 Cerr <<
"Error in Multigrille_base::resoudre_avec_gmres: did not converge in " << max_iter_gmres_ <<
" restarts."
650 <<
"\n Residue= " << norme_b << finl;
653 krilov_space[0].data() *= (_TYPE_)(1. / norme_b);
657 for (
int i = 0; i < n_krilov; i++)
660 m_krilov_space[i].data() = 0.;
662 krilov_space[i].echange_espace_virtuel(krilov_space[i].ghost());
665 multigrille(m_krilov_space[i], krilov_space[i], krilov_space[i+1]);
676 ArrOfDouble produit_scal(i+2);
677 ArrOfDouble coeff(i+1);
678 calcul_produits_scalaires(krilov_space, produit_scal);
679 for (
int j = 0; j <= i; j++)
681 double h = produit_scal[j];
691 hessenberg(j, i) = h;
693 double norme_v0 = ajouter_alpha_v_multiple(krilov_space[i+1], coeff, krilov_space, i+1);
694 norme_v0 = sqrt(
mp_sum(norme_v0));
695 hessenberg(i + 1, i) = norme_v0;
696 krilov_space[i+1].data() *= (_TYPE_)(1. / norme_v0);
699 DoubleTab mat(n_krilov + 1, n_krilov);
700 ArrOfDouble r__(n_krilov + 1);
701 triangularise(hessenberg, norme_b, mat, r__);
704 for (
int i = n_krilov - 1; i >= 0; i--)
707 for (
int j = i-1; j >= 0; j--)
708 r__[j] -= mat(j, i) * r__[i];
710 ajouter_alpha_v_multiple(x, r__, m_krilov_space, n_krilov);
713 Cout <<
"facteurs r : ";
715 Cout << r__[i] <<
" ";
719 Cout <<
"matrice de hessenberg " << hessenberg << finl;
725 op_negate(krilov_space[0]);
730template <
typename _TYPE_,
typename _TYPE_ARRAY_>
748 DoubleVect residu(b);
755 residu[0] -= x[0] * la_matrice(0,0) * 0.5;
756 Cout <<
"Norme de Ax et residu: " << mp_norme_vect(residu);
758 Cout <<
" " << mp_norme_vect(residu) << finl;
This class encapsulates all the information related to the eulerian mesh for TrioIJK.
void nommer(const Nom &nom) override
Donne un nom a l'Objet_U Methode virtuelle a surcharger.
void nommer(const Nom &) override
Donne un nom au champ.
int linear_index(int i, int j, int k) const
void shift_k_origin(int n)
: This class is an IJK_Field_local with parallel informations.
void echange_espace_virtuel(int ghost)
Exchange data over "ghost" number of cells.
const Domaine_IJK & get_domaine() const
static const char * get_conventional_name()
const VDF_to_IJK & get_vdf_to_ijk(Domaine_IJK::Localisation) const
static Objet_U & objet_global(const Nom &nom)
cherche l'objet demande dans l'Interprete_bloc courant (Interprete_bloc::interprete_courant()) et dan...
virtual int get_nb_items_tot() const
: Cette classe est un OWN_PTR mais l'objet pointe est partage entre plusieurs
Classe Matrice_Base Classe de base de la hierarchie des matrices.
virtual DoubleVect & multvect(const DoubleVect &, DoubleVect &) const
Multiplication d'un vecteur par la matrice.
virtual const Matrice & get_bloc(int i, int j) const
const Matrice_Base & matrice() const
const MD_Vector & md_vector() const
const int & renum(int i, int j, int k) const
Classe Matrice_Morse_Sym Represente une matrice M (creuse) symetrique stockee au format Morse.
virtual int needed_kshift_for_jacobi(int level) const =0
virtual void prepare_secmem(IJK_Field_float &x) const =0
void solve_ijk_in_storage_template()
std::enable_if_t< std::is_same< _TYPE_, float >::value, IJK_Field_template< _TYPE_, TRUSTArray< _TYPE_ > > & > get_storage_template(StorageId id, int level)
virtual void interpolate_sub_shiftk(const IJK_Field_float &coarse, IJK_Field_float &fine, int fine_level) const =0
virtual int nb_grid_levels() const =0
void resoudre_systeme_IJK_template(const IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &rhs, IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &x)
void convert_to_ijk(const DoubleVect &x, IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &ijk_x)
void resoudre_avec_gmres(IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &x, IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &b, IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &residu)
virtual void coarsen(const IJK_Field_float &fine, IJK_Field_float &coarse, int fine_level) const =0
virtual void alloc_field(IJK_Field_float &x, int level, bool with_additional_k_layers=false) const =0
void resoudre_avec_gcp(IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &x, IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &b, IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &residu)
double multigrille(IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &x, const IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &b, IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &residu)
void convert_from_ijk(const IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &ijk_x, DoubleVect &x)
const int precision_float_
void resoudre_systeme_template(const Matrice_Base &a, const DoubleVect &b, DoubleVect &x)
double multigrille_(IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &x, const IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &b, IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &residu, int grid_level, int iter_number)
virtual void jacobi_residu(IJK_Field_float &x, const IJK_Field_float *secmem, const int grid_level, const int n_jacobi, IJK_Field_float *residu) const =0
void resoudre_systeme_IJK(const IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &rhs, IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &x)
void coarse_solver(IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &x, const IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &b)
class Nom Une chaine de caractere pour nommer les objets de TRUST
static void mp_sum_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
_SIZE_ size_array() const
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
_SIZE_ dimension(int d) const
virtual void set_md_vector(const MD_Vector &)
void resize(_SIZE_, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")
value_type & add()=delete
void convert_from_ijk(const IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &ijk_x, DoubleVect &x, bool add=false) const
void convert_to_ijk(const DoubleVect &x, IJK_Field_template< _TYPE_, _TYPE_ARRAY_ > &ijk_x) const